~ubuntu-branches/ubuntu/trusty/gtk+2.0/trusty-updates

« back to all changes in this revision

Viewing changes to .pc/gdk-Fix-GdkWindowFilter-internal-refcounting.patch/gdk/x11/gdkevents-x11.c

  • Committer: Package Import Robot
  • Author(s): Vlad Orlov
  • Date: 2015-07-28 10:17:14 UTC
  • Revision ID: package-import@ubuntu.com-20150728101714-rd9msqcb0etcfpsr
Tags: 2.24.23-0ubuntu1.3
* fix_gdk_event_apply_filters.patch: new patch. Makes gdk_event_apply_filters
  function safe against changes in the filter list, prevents weird crashes in
  various apps. (LP: #1351890)
* gdk-Fix-GdkWindowFilter-internal-refcounting.patch,
  gdkwindow-Fix-event-unref-iteration.patch: new patches. Fix refcounting
  errors after fix_gdk_event_apply_filters.patch, prevent crashes in some
  applications like Spotify.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GDK - The GIMP Drawing Kit
 
2
 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
 
3
 * Josh MacDonald, Ryan Lortie
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
/*
 
22
 * Modified by the GTK+ Team and others 1997-2007.  See the AUTHORS
 
23
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 
24
 * files for a list of changes.  These files are distributed with
 
25
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 
26
 */
 
27
 
 
28
#include "config.h"
 
29
 
 
30
#include "gdk.h"
 
31
#include "gdkprivate-x11.h"
 
32
#include "gdkinternals.h"
 
33
#include "gdkx.h"
 
34
#include "gdkscreen-x11.h"
 
35
#include "gdkdisplay-x11.h"
 
36
#include "gdkasync.h"
 
37
 
 
38
#include "gdkkeysyms.h"
 
39
 
 
40
#include "xsettings-client.h"
 
41
 
 
42
#include <string.h>
 
43
 
 
44
#include "gdkinputprivate.h"
 
45
#include "gdksettings.c"
 
46
#include "gdkalias.h"
 
47
 
 
48
 
 
49
#ifdef HAVE_XKB
 
50
#include <X11/XKBlib.h>
 
51
#endif
 
52
 
 
53
#ifdef HAVE_XSYNC
 
54
#include <X11/extensions/sync.h>
 
55
#endif
 
56
 
 
57
#ifdef HAVE_XFIXES
 
58
#include <X11/extensions/Xfixes.h>
 
59
#endif
 
60
 
 
61
#ifdef HAVE_RANDR
 
62
#include <X11/extensions/Xrandr.h>
 
63
#endif
 
64
 
 
65
#include <X11/Xatom.h>
 
66
 
 
67
typedef struct _GdkIOClosure GdkIOClosure;
 
68
typedef struct _GdkDisplaySource GdkDisplaySource;
 
69
typedef struct _GdkEventTypeX11 GdkEventTypeX11;
 
70
 
 
71
struct _GdkIOClosure
 
72
{
 
73
  GdkInputFunction function;
 
74
  GdkInputCondition condition;
 
75
  GDestroyNotify notify;
 
76
  gpointer data;
 
77
};
 
78
 
 
79
struct _GdkDisplaySource
 
80
{
 
81
  GSource source;
 
82
  
 
83
  GdkDisplay *display;
 
84
  GPollFD event_poll_fd;
 
85
};
 
86
 
 
87
struct _GdkEventTypeX11
 
88
{
 
89
  gint base;
 
90
  gint n_events;
 
91
};
 
92
 
 
93
/* 
 
94
 * Private function declarations
 
95
 */
 
96
 
 
97
static gint      gdk_event_apply_filters (XEvent   *xevent,
 
98
                                          GdkEvent *event,
 
99
                                          GList    **filters);
 
100
static gboolean  gdk_event_translate     (GdkDisplay *display,
 
101
                                          GdkEvent   *event, 
 
102
                                          XEvent     *xevent,
 
103
                                          gboolean    return_exposes);
 
104
 
 
105
static gboolean gdk_event_prepare  (GSource     *source,
 
106
                                    gint        *timeout);
 
107
static gboolean gdk_event_check    (GSource     *source);
 
108
static gboolean gdk_event_dispatch (GSource     *source,
 
109
                                    GSourceFunc  callback,
 
110
                                    gpointer     user_data);
 
111
 
 
112
static GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
 
113
                                                GdkEvent  *event,
 
114
                                                gpointer   data);
 
115
 
 
116
static GSource *gdk_display_source_new (GdkDisplay *display);
 
117
static gboolean gdk_check_xpending     (GdkDisplay *display);
 
118
 
 
119
static Bool gdk_xsettings_watch_cb  (Window            window,
 
120
                                     Bool              is_start,
 
121
                                     long              mask,
 
122
                                     void             *cb_data);
 
123
static void gdk_xsettings_notify_cb (const char       *name,
 
124
                                     XSettingsAction   action,
 
125
                                     XSettingsSetting *setting,
 
126
                                     void             *data);
 
127
 
 
128
/* Private variable declarations
 
129
 */
 
130
 
 
131
static GList *display_sources;
 
132
 
 
133
static GSourceFuncs event_funcs = {
 
134
  gdk_event_prepare,
 
135
  gdk_event_check,
 
136
  gdk_event_dispatch,
 
137
  NULL
 
138
};
 
139
 
 
140
static GSource *
 
141
gdk_display_source_new (GdkDisplay *display)
 
142
{
 
143
  GSource *source = g_source_new (&event_funcs, sizeof (GdkDisplaySource));
 
144
  GdkDisplaySource *display_source = (GdkDisplaySource *)source;
 
145
  char *name;
 
146
  
 
147
  name = g_strdup_printf ("GDK X11 Event source (%s)",
 
148
                          gdk_display_get_name (display));
 
149
  g_source_set_name (source, name);
 
150
  g_free (name);
 
151
  display_source->display = display;
 
152
  
 
153
  return source;
 
154
}
 
155
 
 
156
static gboolean
 
157
gdk_check_xpending (GdkDisplay *display)
 
158
{
 
159
  return XPending (GDK_DISPLAY_XDISPLAY (display));
 
160
}
 
161
 
 
162
/*********************************************
 
163
 * Functions for maintaining the event queue *
 
164
 *********************************************/
 
165
 
 
166
static void
 
167
refcounted_grab_server (Display *xdisplay)
 
168
{
 
169
  GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
 
170
 
 
171
  gdk_x11_display_grab (display);
 
172
}
 
173
 
 
174
static void
 
175
refcounted_ungrab_server (Display *xdisplay)
 
176
{
 
177
  GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
 
178
  
 
179
  gdk_x11_display_ungrab (display);
 
180
}
 
181
 
 
182
void
 
183
_gdk_x11_events_init_screen (GdkScreen *screen)
 
184
{
 
185
  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
 
186
 
 
187
  /* Keep a flag to avoid extra notifies that we don't need
 
188
   */
 
189
  screen_x11->xsettings_in_init = TRUE;
 
190
  screen_x11->xsettings_client = xsettings_client_new_with_grab_funcs (screen_x11->xdisplay,
 
191
                                                                       screen_x11->screen_num,
 
192
                                                                       gdk_xsettings_notify_cb,
 
193
                                                                       gdk_xsettings_watch_cb,
 
194
                                                                       screen,
 
195
                                                                       refcounted_grab_server,
 
196
                                                                       refcounted_ungrab_server);
 
197
  screen_x11->xsettings_in_init = FALSE;
 
198
}
 
199
 
 
200
void
 
201
_gdk_x11_events_uninit_screen (GdkScreen *screen)
 
202
{
 
203
  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
 
204
 
 
205
  if (screen_x11->xsettings_client)
 
206
    {
 
207
      xsettings_client_destroy (screen_x11->xsettings_client);
 
208
      screen_x11->xsettings_client = NULL;
 
209
    }
 
210
}
 
211
 
 
212
void 
 
213
_gdk_events_init (GdkDisplay *display)
 
214
{
 
215
  GSource *source;
 
216
  GdkDisplaySource *display_source;
 
217
  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
 
218
  
 
219
  int connection_number = ConnectionNumber (display_x11->xdisplay);
 
220
  GDK_NOTE (MISC, g_message ("connection number: %d", connection_number));
 
221
 
 
222
 
 
223
  source = display_x11->event_source = gdk_display_source_new (display);
 
224
  display_source = (GdkDisplaySource*) source;
 
225
  g_source_set_priority (source, GDK_PRIORITY_EVENTS);
 
226
  
 
227
  display_source->event_poll_fd.fd = connection_number;
 
228
  display_source->event_poll_fd.events = G_IO_IN;
 
229
  
 
230
  g_source_add_poll (source, &display_source->event_poll_fd);
 
231
  g_source_set_can_recurse (source, TRUE);
 
232
  g_source_attach (source, NULL);
 
233
 
 
234
  display_sources = g_list_prepend (display_sources,display_source);
 
235
 
 
236
  gdk_display_add_client_message_filter (display,
 
237
                                         gdk_atom_intern_static_string ("WM_PROTOCOLS"), 
 
238
                                         gdk_wm_protocols_filter,   
 
239
                                         NULL);
 
240
}
 
241
 
 
242
void
 
243
_gdk_events_uninit (GdkDisplay *display)
 
244
{
 
245
  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
 
246
 
 
247
  if (display_x11->event_source)
 
248
    {
 
249
      display_sources = g_list_remove (display_sources,
 
250
                                       display_x11->event_source);
 
251
      g_source_destroy (display_x11->event_source);
 
252
      g_source_unref (display_x11->event_source);
 
253
      display_x11->event_source = NULL;
 
254
    }
 
255
}
 
256
 
 
257
/**
 
258
 * gdk_events_pending:
 
259
 * 
 
260
 * Checks if any events are ready to be processed for any display.
 
261
 * 
 
262
 * Return value:  %TRUE if any events are pending.
 
263
 **/
 
264
gboolean
 
265
gdk_events_pending (void)
 
266
{
 
267
  GList *tmp_list;
 
268
 
 
269
  for (tmp_list = display_sources; tmp_list; tmp_list = tmp_list->next)
 
270
    {
 
271
      GdkDisplaySource *tmp_source = tmp_list->data;
 
272
      GdkDisplay *display = tmp_source->display;
 
273
      
 
274
      if (_gdk_event_queue_find_first (display))
 
275
        return TRUE;
 
276
    }
 
277
 
 
278
  for (tmp_list = display_sources; tmp_list; tmp_list = tmp_list->next)
 
279
    {
 
280
      GdkDisplaySource *tmp_source = tmp_list->data;
 
281
      GdkDisplay *display = tmp_source->display;
 
282
      
 
283
      if (gdk_check_xpending (display))
 
284
        return TRUE;
 
285
    }
 
286
  
 
287
  return FALSE;
 
288
}
 
289
 
 
290
static Bool
 
291
graphics_expose_predicate (Display  *display,
 
292
                           XEvent   *xevent,
 
293
                           XPointer  arg)
 
294
{
 
295
  if (xevent->xany.window == GDK_DRAWABLE_XID ((GdkDrawable *)arg) &&
 
296
      (xevent->xany.type == GraphicsExpose ||
 
297
       xevent->xany.type == NoExpose))
 
298
    return True;
 
299
  else
 
300
    return False;
 
301
}
 
302
 
 
303
/**
 
304
 * gdk_event_get_graphics_expose:
 
305
 * @window: the #GdkWindow to wait for the events for.
 
306
 * 
 
307
 * Waits for a GraphicsExpose or NoExpose event from the X server.
 
308
 * This is used in the #GtkText and #GtkCList widgets in GTK+ to make sure any
 
309
 * GraphicsExpose events are handled before the widget is scrolled.
 
310
 *
 
311
 * Return value:  a #GdkEventExpose if a GraphicsExpose was received, or %NULL if a
 
312
 * NoExpose event was received.
 
313
 *
 
314
 * Deprecated: 2.18:
 
315
 **/
 
316
GdkEvent*
 
317
gdk_event_get_graphics_expose (GdkWindow *window)
 
318
{
 
319
  XEvent xevent;
 
320
  GdkEvent *event;
 
321
  
 
322
  g_return_val_if_fail (window != NULL, NULL);
 
323
 
 
324
  XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, 
 
325
            graphics_expose_predicate, (XPointer) window);
 
326
  
 
327
  if (xevent.xany.type == GraphicsExpose)
 
328
    {
 
329
      event = gdk_event_new (GDK_NOTHING);
 
330
      
 
331
      if (gdk_event_translate (GDK_WINDOW_DISPLAY (window), event,
 
332
                               &xevent, TRUE))
 
333
        return event;
 
334
      else
 
335
        gdk_event_free (event);
 
336
    }
 
337
  
 
338
  return NULL;  
 
339
}
 
340
 
 
341
static gint
 
342
gdk_event_apply_filters (XEvent *xevent,
 
343
                         GdkEvent *event,
 
344
                         GList **filters)
 
345
{
 
346
  GList *tmp_list;
 
347
  GdkFilterReturn result;
 
348
  
 
349
  tmp_list = *filters;
 
350
  
 
351
  while (tmp_list)
 
352
    {
 
353
      GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
 
354
      GList *node;
 
355
      
 
356
      if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0)
 
357
        {
 
358
          tmp_list = tmp_list->next;
 
359
          continue;
 
360
        }
 
361
 
 
362
      filter->ref_count++;
 
363
      result = filter->function (xevent, event, filter->data);
 
364
 
 
365
      /* get the next node after running the function since the
 
366
         function may add or remove a next node */
 
367
      node = tmp_list;
 
368
      tmp_list = tmp_list->next;
 
369
 
 
370
      filter->ref_count--;
 
371
      if (filter->ref_count == 0)
 
372
        {
 
373
          *filters = g_list_remove_link (*filters, node);
 
374
          g_list_free_1 (node);
 
375
          g_free (filter);
 
376
        }
 
377
 
 
378
      if (result != GDK_FILTER_CONTINUE)
 
379
        return result;
 
380
    }
 
381
  
 
382
  return GDK_FILTER_CONTINUE;
 
383
}
 
384
 
 
385
/**
 
386
 * gdk_display_add_client_message_filter:
 
387
 * @display: a #GdkDisplay for which this message filter applies
 
388
 * @message_type: the type of ClientMessage events to receive.
 
389
 *   This will be checked against the @message_type field 
 
390
 *   of the XClientMessage event struct.
 
391
 * @func: the function to call to process the event.
 
392
 * @data: user data to pass to @func.
 
393
 *
 
394
 * Adds a filter to be called when X ClientMessage events are received.
 
395
 * See gdk_window_add_filter() if you are interested in filtering other
 
396
 * types of events.
 
397
 *
 
398
 * Since: 2.2
 
399
 **/ 
 
400
void 
 
401
gdk_display_add_client_message_filter (GdkDisplay   *display,
 
402
                                       GdkAtom       message_type,
 
403
                                       GdkFilterFunc func,
 
404
                                       gpointer      data)
 
405
{
 
406
  GdkClientFilter *filter;
 
407
  g_return_if_fail (GDK_IS_DISPLAY (display));
 
408
  filter = g_new (GdkClientFilter, 1);
 
409
 
 
410
  filter->type = message_type;
 
411
  filter->function = func;
 
412
  filter->data = data;
 
413
  
 
414
  GDK_DISPLAY_X11(display)->client_filters = 
 
415
    g_list_append (GDK_DISPLAY_X11 (display)->client_filters,
 
416
                   filter);
 
417
}
 
418
 
 
419
/**
 
420
 * gdk_add_client_message_filter:
 
421
 * @message_type: the type of ClientMessage events to receive. This will be
 
422
 *     checked against the <structfield>message_type</structfield> field of the
 
423
 *     XClientMessage event struct.
 
424
 * @func: the function to call to process the event.
 
425
 * @data: user data to pass to @func. 
 
426
 * 
 
427
 * Adds a filter to the default display to be called when X ClientMessage events
 
428
 * are received. See gdk_display_add_client_message_filter().
 
429
 **/
 
430
void 
 
431
gdk_add_client_message_filter (GdkAtom       message_type,
 
432
                               GdkFilterFunc func,
 
433
                               gpointer      data)
 
434
{
 
435
  gdk_display_add_client_message_filter (gdk_display_get_default (),
 
436
                                         message_type, func, data);
 
437
}
 
438
 
 
439
static void
 
440
do_net_wm_state_changes (GdkWindow *window)
 
441
{
 
442
  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
 
443
  GdkWindowState old_state;
 
444
  
 
445
  if (GDK_WINDOW_DESTROYED (window) ||
 
446
      gdk_window_get_window_type (window) != GDK_WINDOW_TOPLEVEL)
 
447
    return;
 
448
  
 
449
  old_state = gdk_window_get_state (window);
 
450
 
 
451
  /* For found_sticky to remain TRUE, we have to also be on desktop
 
452
   * 0xFFFFFFFF
 
453
   */
 
454
  if (old_state & GDK_WINDOW_STATE_STICKY)
 
455
    {
 
456
      if (!(toplevel->have_sticky && toplevel->on_all_desktops))
 
457
        gdk_synthesize_window_state (window,
 
458
                                     GDK_WINDOW_STATE_STICKY,
 
459
                                     0);
 
460
    }
 
461
  else
 
462
    {
 
463
      if (toplevel->have_sticky || toplevel->on_all_desktops)
 
464
        gdk_synthesize_window_state (window,
 
465
                                     0,
 
466
                                     GDK_WINDOW_STATE_STICKY);
 
467
    }
 
468
 
 
469
  if (old_state & GDK_WINDOW_STATE_FULLSCREEN)
 
470
    {
 
471
      if (!toplevel->have_fullscreen)
 
472
        gdk_synthesize_window_state (window,
 
473
                                     GDK_WINDOW_STATE_FULLSCREEN,
 
474
                                     0);
 
475
    }
 
476
  else
 
477
    {
 
478
      if (toplevel->have_fullscreen)
 
479
        gdk_synthesize_window_state (window,
 
480
                                     0,
 
481
                                     GDK_WINDOW_STATE_FULLSCREEN);
 
482
    }
 
483
  
 
484
  /* Our "maximized" means both vertical and horizontal; if only one,
 
485
   * we don't expose that via GDK
 
486
   */
 
487
  if (old_state & GDK_WINDOW_STATE_MAXIMIZED)
 
488
    {
 
489
      if (!(toplevel->have_maxvert && toplevel->have_maxhorz))
 
490
        gdk_synthesize_window_state (window,
 
491
                                     GDK_WINDOW_STATE_MAXIMIZED,
 
492
                                     0);
 
493
    }
 
494
  else
 
495
    {
 
496
      if (toplevel->have_maxvert && toplevel->have_maxhorz)
 
497
        gdk_synthesize_window_state (window,
 
498
                                     0,
 
499
                                     GDK_WINDOW_STATE_MAXIMIZED);
 
500
    }
 
501
 
 
502
  if (old_state & GDK_WINDOW_STATE_ICONIFIED)
 
503
    {
 
504
      if (!toplevel->have_hidden)
 
505
        gdk_synthesize_window_state (window,
 
506
                                     GDK_WINDOW_STATE_ICONIFIED,
 
507
                                     0);
 
508
    }
 
509
  else
 
510
    {
 
511
      if (toplevel->have_hidden)
 
512
        gdk_synthesize_window_state (window,
 
513
                                     0,
 
514
                                     GDK_WINDOW_STATE_ICONIFIED);
 
515
    }
 
516
}
 
517
 
 
518
static void
 
519
gdk_check_wm_desktop_changed (GdkWindow *window)
 
520
{
 
521
  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
 
522
  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
523
 
 
524
  Atom type;
 
525
  gint format;
 
526
  gulong nitems;
 
527
  gulong bytes_after;
 
528
  guchar *data;
 
529
  gulong *desktop;
 
530
 
 
531
  type = None;
 
532
  gdk_error_trap_push ();
 
533
  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
 
534
                      GDK_WINDOW_XID (window),
 
535
                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
 
536
                      0, G_MAXLONG, False, XA_CARDINAL, &type, 
 
537
                      &format, &nitems,
 
538
                      &bytes_after, &data);
 
539
  gdk_error_trap_pop ();
 
540
 
 
541
  if (type != None)
 
542
    {
 
543
      desktop = (gulong *)data;
 
544
      toplevel->on_all_desktops = (*desktop == 0xFFFFFFFF);
 
545
      XFree (desktop);
 
546
    }
 
547
  else
 
548
    toplevel->on_all_desktops = FALSE;
 
549
      
 
550
  do_net_wm_state_changes (window);
 
551
}
 
552
 
 
553
static void
 
554
gdk_check_wm_state_changed (GdkWindow *window)
 
555
{
 
556
  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
 
557
  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
558
  
 
559
  Atom type;
 
560
  gint format;
 
561
  gulong nitems;
 
562
  gulong bytes_after;
 
563
  guchar *data;
 
564
  Atom *atoms = NULL;
 
565
  gulong i;
 
566
 
 
567
  gboolean had_sticky = toplevel->have_sticky;
 
568
 
 
569
  toplevel->have_sticky = FALSE;
 
570
  toplevel->have_maxvert = FALSE;
 
571
  toplevel->have_maxhorz = FALSE;
 
572
  toplevel->have_fullscreen = FALSE;
 
573
  toplevel->have_hidden = FALSE;
 
574
 
 
575
  type = None;
 
576
  gdk_error_trap_push ();
 
577
  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
 
578
                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
 
579
                      0, G_MAXLONG, False, XA_ATOM, &type, &format, &nitems,
 
580
                      &bytes_after, &data);
 
581
  gdk_error_trap_pop ();
 
582
 
 
583
  if (type != None)
 
584
    {
 
585
      Atom sticky_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_STICKY");
 
586
      Atom maxvert_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
 
587
      Atom maxhorz_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
 
588
      Atom fullscreen_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN");
 
589
      Atom hidden_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_HIDDEN");
 
590
 
 
591
      atoms = (Atom *)data;
 
592
 
 
593
      i = 0;
 
594
      while (i < nitems)
 
595
        {
 
596
          if (atoms[i] == sticky_atom)
 
597
            toplevel->have_sticky = TRUE;
 
598
          else if (atoms[i] == maxvert_atom)
 
599
            toplevel->have_maxvert = TRUE;
 
600
          else if (atoms[i] == maxhorz_atom)
 
601
            toplevel->have_maxhorz = TRUE;
 
602
          else if (atoms[i] == fullscreen_atom)
 
603
            toplevel->have_fullscreen = TRUE;
 
604
          else if (atoms[i] == hidden_atom)
 
605
            toplevel->have_hidden = TRUE;
 
606
          
 
607
          ++i;
 
608
        }
 
609
 
 
610
      XFree (atoms);
 
611
    }
 
612
 
 
613
  /* When have_sticky is turned on, we have to check the DESKTOP property
 
614
   * as well.
 
615
   */
 
616
  if (toplevel->have_sticky && !had_sticky)
 
617
    gdk_check_wm_desktop_changed (window);
 
618
  else
 
619
    do_net_wm_state_changes (window);
 
620
}
 
621
 
 
622
#define HAS_FOCUS(toplevel)                           \
 
623
  ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
 
624
 
 
625
static void
 
626
generate_focus_event (GdkWindow *window,
 
627
                      gboolean   in)
 
628
{
 
629
  GdkEvent event;
 
630
  
 
631
  event.type = GDK_FOCUS_CHANGE;
 
632
  event.focus_change.window = window;
 
633
  event.focus_change.send_event = FALSE;
 
634
  event.focus_change.in = in;
 
635
  
 
636
  gdk_event_put (&event);
 
637
}
 
638
 
 
639
static gboolean
 
640
set_screen_from_root (GdkDisplay *display,
 
641
                      GdkEvent   *event,
 
642
                      Window      xrootwin)
 
643
{
 
644
  GdkScreen *screen;
 
645
 
 
646
  screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
 
647
 
 
648
  if (screen)
 
649
    {
 
650
      gdk_event_set_screen (event, screen);
 
651
 
 
652
      return TRUE;
 
653
    }
 
654
  
 
655
  return FALSE;
 
656
}
 
657
 
 
658
static void
 
659
translate_key_event (GdkDisplay *display,
 
660
                     GdkEvent   *event,
 
661
                     XEvent     *xevent)
 
662
{
 
663
  GdkKeymap *keymap = gdk_keymap_get_for_display (display);
 
664
  gunichar c = 0;
 
665
  gchar buf[7];
 
666
  GdkModifierType consumed, state;
 
667
 
 
668
  event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
 
669
  event->key.time = xevent->xkey.time;
 
670
 
 
671
  event->key.state = (GdkModifierType) xevent->xkey.state;
 
672
  event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
 
673
  event->key.hardware_keycode = xevent->xkey.keycode;
 
674
 
 
675
  event->key.keyval = GDK_VoidSymbol;
 
676
 
 
677
  gdk_keymap_translate_keyboard_state (keymap,
 
678
                                       event->key.hardware_keycode,
 
679
                                       event->key.state,
 
680
                                       event->key.group,
 
681
                                       &event->key.keyval,
 
682
                                       NULL, NULL, &consumed);
 
683
   state = event->key.state & ~consumed;
 
684
   _gdk_keymap_add_virtual_modifiers_compat (keymap, &state);
 
685
   event->key.state |= state;
 
686
 
 
687
  event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
 
688
 
 
689
  /* Fill in event->string crudely, since various programs
 
690
   * depend on it.
 
691
   */
 
692
  event->key.string = NULL;
 
693
  
 
694
  if (event->key.keyval != GDK_VoidSymbol)
 
695
    c = gdk_keyval_to_unicode (event->key.keyval);
 
696
 
 
697
  if (c)
 
698
    {
 
699
      gsize bytes_written;
 
700
      gint len;
 
701
 
 
702
      /* Apply the control key - Taken from Xlib
 
703
       */
 
704
      if (event->key.state & GDK_CONTROL_MASK)
 
705
        {
 
706
          if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
 
707
          else if (c == '2')
 
708
            {
 
709
              event->key.string = g_memdup ("\0\0", 2);
 
710
              event->key.length = 1;
 
711
              buf[0] = '\0';
 
712
              goto out;
 
713
            }
 
714
          else if (c >= '3' && c <= '7') c -= ('3' - '\033');
 
715
          else if (c == '8') c = '\177';
 
716
          else if (c == '/') c = '_' & 0x1F;
 
717
        }
 
718
      
 
719
      len = g_unichar_to_utf8 (c, buf);
 
720
      buf[len] = '\0';
 
721
      
 
722
      event->key.string = g_locale_from_utf8 (buf, len,
 
723
                                              NULL, &bytes_written,
 
724
                                              NULL);
 
725
      if (event->key.string)
 
726
        event->key.length = bytes_written;
 
727
    }
 
728
  else if (event->key.keyval == GDK_Escape)
 
729
    {
 
730
      event->key.length = 1;
 
731
      event->key.string = g_strdup ("\033");
 
732
    }
 
733
  else if (event->key.keyval == GDK_Return ||
 
734
          event->key.keyval == GDK_KP_Enter)
 
735
    {
 
736
      event->key.length = 1;
 
737
      event->key.string = g_strdup ("\r");
 
738
    }
 
739
 
 
740
  if (!event->key.string)
 
741
    {
 
742
      event->key.length = 0;
 
743
      event->key.string = g_strdup ("");
 
744
    }
 
745
  
 
746
 out:
 
747
#ifdef G_ENABLE_DEBUG
 
748
  if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
 
749
    {
 
750
      g_message ("%s:\t\twindow: %ld     key: %12s  %d",
 
751
                 event->type == GDK_KEY_PRESS ? "key press  " : "key release",
 
752
                 xevent->xkey.window,
 
753
                 event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
 
754
                 event->key.keyval);
 
755
  
 
756
      if (event->key.length > 0)
 
757
        g_message ("\t\tlength: %4d string: \"%s\"",
 
758
                   event->key.length, buf);
 
759
    }
 
760
#endif /* G_ENABLE_DEBUG */  
 
761
  return;
 
762
}
 
763
 
 
764
/**
 
765
 * gdk_x11_register_standard_event_type:
 
766
 * @display: a #GdkDisplay
 
767
 * @event_base: first event type code to register
 
768
 * @n_events: number of event type codes to register
 
769
 * 
 
770
 * Registers interest in receiving extension events with type codes
 
771
 * between @event_base and <literal>event_base + n_events - 1</literal>.
 
772
 * The registered events must have the window field in the same place
 
773
 * as core X events (this is not the case for e.g. XKB extension events).
 
774
 *
 
775
 * If an event type is registered, events of this type will go through
 
776
 * global and window-specific filters (see gdk_window_add_filter()). 
 
777
 * Unregistered events will only go through global filters.
 
778
 * GDK may register the events of some X extensions on its own.
 
779
 * 
 
780
 * This function should only be needed in unusual circumstances, e.g.
 
781
 * when filtering XInput extension events on the root window.
 
782
 *
 
783
 * Since: 2.4
 
784
 **/
 
785
void
 
786
gdk_x11_register_standard_event_type (GdkDisplay          *display,
 
787
                                      gint                 event_base,
 
788
                                      gint                 n_events)
 
789
{
 
790
  GdkEventTypeX11 *event_type;
 
791
  GdkDisplayX11 *display_x11;
 
792
 
 
793
  display_x11 = GDK_DISPLAY_X11 (display);
 
794
  event_type = g_new (GdkEventTypeX11, 1);
 
795
 
 
796
  event_type->base = event_base;
 
797
  event_type->n_events = n_events;
 
798
 
 
799
  display_x11->event_types = g_slist_prepend (display_x11->event_types, event_type);
 
800
}
 
801
 
 
802
/* Return the window this has to do with, if any, rather
 
803
 * than the frame or root window that was selecting
 
804
 * for substructure
 
805
 */
 
806
static void
 
807
get_real_window (GdkDisplay *display,
 
808
                 XEvent     *event,
 
809
                 Window     *event_window,
 
810
                 Window     *filter_window)
 
811
{
 
812
  /* Core events all have an event->xany.window field, but that's
 
813
   * not true for extension events
 
814
   */
 
815
  if (event->type >= KeyPress &&
 
816
      event->type <= MappingNotify)
 
817
    {
 
818
      *filter_window = event->xany.window;
 
819
      switch (event->type)
 
820
        {      
 
821
        case CreateNotify:
 
822
          *event_window = event->xcreatewindow.window;
 
823
          break;
 
824
        case DestroyNotify:
 
825
          *event_window = event->xdestroywindow.window;
 
826
          break;
 
827
        case UnmapNotify:
 
828
          *event_window = event->xunmap.window;
 
829
          break;
 
830
        case MapNotify:
 
831
          *event_window = event->xmap.window;
 
832
          break;
 
833
        case MapRequest:
 
834
          *event_window = event->xmaprequest.window;
 
835
          break;
 
836
        case ReparentNotify:
 
837
          *event_window = event->xreparent.window;
 
838
          break;
 
839
        case ConfigureNotify:
 
840
          *event_window = event->xconfigure.window;
 
841
          break;
 
842
        case ConfigureRequest:
 
843
          *event_window = event->xconfigurerequest.window;
 
844
          break;
 
845
        case GravityNotify:
 
846
          *event_window = event->xgravity.window;
 
847
          break;
 
848
        case CirculateNotify:
 
849
          *event_window = event->xcirculate.window;
 
850
          break;
 
851
        case CirculateRequest:
 
852
          *event_window = event->xcirculaterequest.window;
 
853
          break;
 
854
        default:
 
855
          *event_window = event->xany.window;
 
856
        }
 
857
    }
 
858
  else
 
859
    {
 
860
      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
 
861
      GSList *tmp_list;
 
862
 
 
863
      for (tmp_list = display_x11->event_types;
 
864
           tmp_list;
 
865
           tmp_list = tmp_list->next)
 
866
        {
 
867
          GdkEventTypeX11 *event_type = tmp_list->data;
 
868
 
 
869
          if (event->type >= event_type->base &&
 
870
              event->type < event_type->base + event_type->n_events)
 
871
            {
 
872
              *event_window = event->xany.window;
 
873
              *filter_window = event->xany.window;
 
874
              return;
 
875
            }
 
876
        }
 
877
           
 
878
      *event_window = None;
 
879
      *filter_window = None;
 
880
    }
 
881
}
 
882
 
 
883
#ifdef G_ENABLE_DEBUG
 
884
static const char notify_modes[][19] = {
 
885
  "NotifyNormal",
 
886
  "NotifyGrab",
 
887
  "NotifyUngrab",
 
888
  "NotifyWhileGrabbed"
 
889
};
 
890
 
 
891
static const char notify_details[][23] = {
 
892
  "NotifyAncestor",
 
893
  "NotifyVirtual",
 
894
  "NotifyInferior",
 
895
  "NotifyNonlinear",
 
896
  "NotifyNonlinearVirtual",
 
897
  "NotifyPointer",
 
898
  "NotifyPointerRoot",
 
899
  "NotifyDetailNone"
 
900
};
 
901
#endif
 
902
 
 
903
static void
 
904
set_user_time (GdkWindow *window,
 
905
               GdkEvent  *event)
 
906
{
 
907
  g_return_if_fail (event != NULL);
 
908
 
 
909
  window = gdk_window_get_toplevel (event->client.window);
 
910
  g_return_if_fail (GDK_IS_WINDOW (window));
 
911
 
 
912
  /* If an event doesn't have a valid timestamp, we shouldn't use it
 
913
   * to update the latest user interaction time.
 
914
   */
 
915
  if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
 
916
    gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
 
917
                                  gdk_event_get_time (event));
 
918
}
 
919
 
 
920
static gboolean
 
921
is_parent_of (GdkWindow *parent,
 
922
              GdkWindow *child)
 
923
{
 
924
  GdkWindow *w;
 
925
 
 
926
  w = child;
 
927
  while (w != NULL)
 
928
    {
 
929
      if (w == parent)
 
930
        return TRUE;
 
931
 
 
932
      w = gdk_window_get_parent (w);
 
933
    }
 
934
 
 
935
  return FALSE;
 
936
}
 
937
 
 
938
static gboolean
 
939
gdk_event_translate (GdkDisplay *display,
 
940
                     GdkEvent   *event,
 
941
                     XEvent     *xevent,
 
942
                     gboolean    return_exposes)
 
943
{
 
944
  
 
945
  GdkWindow *window;
 
946
  GdkWindowObject *window_private;
 
947
  GdkWindow *filter_window;
 
948
  GdkWindowImplX11 *window_impl = NULL;
 
949
  gboolean return_val;
 
950
  GdkScreen *screen = NULL;
 
951
  GdkScreenX11 *screen_x11 = NULL;
 
952
  GdkToplevelX11 *toplevel = NULL;
 
953
  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
 
954
  Window xwindow, filter_xwindow;
 
955
  
 
956
  return_val = FALSE;
 
957
 
 
958
  /* init these, since the done: block uses them */
 
959
  window = NULL;
 
960
  window_private = NULL;
 
961
  event->any.window = NULL;
 
962
 
 
963
  if (_gdk_default_filters)
 
964
    {
 
965
      /* Apply global filters */
 
966
      GdkFilterReturn result;
 
967
      result = gdk_event_apply_filters (xevent, event,
 
968
                                        &_gdk_default_filters);
 
969
      
 
970
      if (result != GDK_FILTER_CONTINUE)
 
971
        {
 
972
          return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
 
973
          goto done;
 
974
        }
 
975
    }  
 
976
 
 
977
  /* Find the GdkWindow that this event relates to.
 
978
   * Basically this means substructure events
 
979
   * are reported same as structure events
 
980
   */
 
981
  get_real_window (display, xevent, &xwindow, &filter_xwindow);
 
982
  
 
983
  window = gdk_window_lookup_for_display (display, xwindow);
 
984
  /* We may receive events such as NoExpose/GraphicsExpose
 
985
   * and ShmCompletion for pixmaps
 
986
   */
 
987
  if (window && !GDK_IS_WINDOW (window))
 
988
    window = NULL;
 
989
  window_private = (GdkWindowObject *) window;
 
990
 
 
991
  /* We always run the filters for the window where the event
 
992
   * is delivered, not the window that it relates to
 
993
   */
 
994
  if (filter_xwindow == xwindow)
 
995
    filter_window = window;
 
996
  else
 
997
    {
 
998
      filter_window = gdk_window_lookup_for_display (display, filter_xwindow);
 
999
      if (filter_window && !GDK_IS_WINDOW (filter_window))
 
1000
        filter_window = NULL;
 
1001
    }
 
1002
 
 
1003
  if (window)
 
1004
    {
 
1005
      screen = GDK_WINDOW_SCREEN (window);
 
1006
      screen_x11 = GDK_SCREEN_X11 (screen);
 
1007
      toplevel = _gdk_x11_window_get_toplevel (window);
 
1008
    }
 
1009
    
 
1010
  if (window != NULL)
 
1011
    {
 
1012
      /* Apply keyboard grabs to non-native windows */
 
1013
      if (/* Is key event */
 
1014
          (xevent->type == KeyPress || xevent->type == KeyRelease) &&
 
1015
          /* And we have a grab */
 
1016
          display->keyboard_grab.window != NULL &&
 
1017
          (
 
1018
           /* The window is not a descendant of the grabbed window */
 
1019
           !is_parent_of ((GdkWindow *)display->keyboard_grab.window, window) ||
 
1020
           /* Or owner event is false */
 
1021
           !display->keyboard_grab.owner_events
 
1022
           )
 
1023
          )
 
1024
        {
 
1025
          /* Report key event against grab window */
 
1026
          window = display->keyboard_grab.window;;
 
1027
          window_private = (GdkWindowObject *) window;
 
1028
        }
 
1029
 
 
1030
      window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
 
1031
      
 
1032
      /* Move key events on focus window to the real toplevel, and
 
1033
       * filter out all other events on focus window
 
1034
       */          
 
1035
      if (toplevel && xwindow == toplevel->focus_window)
 
1036
        {
 
1037
          switch (xevent->type)
 
1038
            {
 
1039
            case KeyPress:
 
1040
            case KeyRelease:
 
1041
              xwindow = GDK_WINDOW_XID (window);
 
1042
              xevent->xany.window = xwindow;
 
1043
              break;
 
1044
            default:
 
1045
              return FALSE;
 
1046
            }
 
1047
        }
 
1048
 
 
1049
      g_object_ref (window);
 
1050
    }
 
1051
 
 
1052
  event->any.window = window;
 
1053
  event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
 
1054
  
 
1055
  if (window_private && GDK_WINDOW_DESTROYED (window))
 
1056
    {
 
1057
      if (xevent->type != DestroyNotify)
 
1058
        {
 
1059
          return_val = FALSE;
 
1060
          goto done;
 
1061
        }
 
1062
    }
 
1063
  else if (filter_window)
 
1064
    {
 
1065
      /* Apply per-window filters */
 
1066
      GdkWindowObject *filter_private = (GdkWindowObject *) filter_window;
 
1067
      GdkFilterReturn result;
 
1068
 
 
1069
      if (filter_private->filters)
 
1070
        {
 
1071
          g_object_ref (filter_window);
 
1072
          
 
1073
          result = gdk_event_apply_filters (xevent, event,
 
1074
                                            &filter_private->filters);
 
1075
          
 
1076
          g_object_unref (filter_window);
 
1077
      
 
1078
          if (result != GDK_FILTER_CONTINUE)
 
1079
            {
 
1080
              return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
 
1081
              goto done;
 
1082
            }
 
1083
        }
 
1084
    }
 
1085
 
 
1086
  if (xevent->type == DestroyNotify)
 
1087
    {
 
1088
      int i, n;
 
1089
 
 
1090
      n = gdk_display_get_n_screens (display);
 
1091
      for (i = 0; i < n; i++)
 
1092
        {
 
1093
          screen = gdk_display_get_screen (display, i);
 
1094
          screen_x11 = GDK_SCREEN_X11 (screen);
 
1095
 
 
1096
          if (screen_x11->wmspec_check_window == xwindow)
 
1097
            {
 
1098
              screen_x11->wmspec_check_window = None;
 
1099
              screen_x11->last_wmspec_check_time = 0;
 
1100
              g_free (screen_x11->window_manager_name);
 
1101
              screen_x11->window_manager_name = g_strdup ("unknown");
 
1102
 
 
1103
              /* careful, reentrancy */
 
1104
              _gdk_x11_screen_window_manager_changed (screen);
 
1105
 
 
1106
              return_val = FALSE;
 
1107
              goto done;
 
1108
            }
 
1109
        }
 
1110
    }
 
1111
 
 
1112
  if (window &&
 
1113
      (xevent->xany.type == MotionNotify ||
 
1114
       xevent->xany.type == ButtonRelease))
 
1115
    {
 
1116
      if (_gdk_moveresize_handle_event (xevent))
 
1117
        {
 
1118
          return_val = FALSE;
 
1119
          goto done;
 
1120
        }
 
1121
    }
 
1122
  
 
1123
  /* We do a "manual" conversion of the XEvent to a
 
1124
   *  GdkEvent. The structures are mostly the same so
 
1125
   *  the conversion is fairly straightforward. We also
 
1126
   *  optionally print debugging info regarding events
 
1127
   *  received.
 
1128
   */
 
1129
 
 
1130
  return_val = TRUE;
 
1131
 
 
1132
  switch (xevent->type)
 
1133
    {
 
1134
    case KeyPress:
 
1135
      if (window_private == NULL)
 
1136
        {
 
1137
          return_val = FALSE;
 
1138
          break;
 
1139
        }
 
1140
      translate_key_event (display, event, xevent);
 
1141
      set_user_time (window, event);
 
1142
      break;
 
1143
 
 
1144
    case KeyRelease:
 
1145
      if (window_private == NULL)
 
1146
        {
 
1147
          return_val = FALSE;
 
1148
          break;
 
1149
        }
 
1150
      
 
1151
      /* Emulate detectable auto-repeat by checking to see
 
1152
       * if the next event is a key press with the same
 
1153
       * keycode and timestamp, and if so, ignoring the event.
 
1154
       */
 
1155
 
 
1156
      if (!display_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
 
1157
        {
 
1158
          XEvent next_event;
 
1159
 
 
1160
          XPeekEvent (xevent->xkey.display, &next_event);
 
1161
 
 
1162
          if (next_event.type == KeyPress &&
 
1163
              next_event.xkey.keycode == xevent->xkey.keycode &&
 
1164
              next_event.xkey.time == xevent->xkey.time)
 
1165
            {
 
1166
              return_val = FALSE;
 
1167
              break;
 
1168
            }
 
1169
        }
 
1170
 
 
1171
      translate_key_event (display, event, xevent);
 
1172
      break;
 
1173
      
 
1174
    case ButtonPress:
 
1175
      GDK_NOTE (EVENTS, 
 
1176
                g_message ("button press:\t\twindow: %ld  x,y: %d %d  button: %d",
 
1177
                           xevent->xbutton.window,
 
1178
                           xevent->xbutton.x, xevent->xbutton.y,
 
1179
                           xevent->xbutton.button));
 
1180
      
 
1181
      if (window_private == NULL)
 
1182
        {
 
1183
          return_val = FALSE;
 
1184
          break;
 
1185
        }
 
1186
      
 
1187
      /* If we get a ButtonPress event where the button is 4 or 5,
 
1188
         it's a Scroll event */
 
1189
      switch (xevent->xbutton.button)
 
1190
        {
 
1191
        case 4: /* up */
 
1192
        case 5: /* down */
 
1193
        case 6: /* left */
 
1194
        case 7: /* right */
 
1195
          event->scroll.type = GDK_SCROLL;
 
1196
 
 
1197
          if (xevent->xbutton.button == 4)
 
1198
            event->scroll.direction = GDK_SCROLL_UP;
 
1199
          else if (xevent->xbutton.button == 5)
 
1200
            event->scroll.direction = GDK_SCROLL_DOWN;
 
1201
          else if (xevent->xbutton.button == 6)
 
1202
            event->scroll.direction = GDK_SCROLL_LEFT;
 
1203
          else
 
1204
            event->scroll.direction = GDK_SCROLL_RIGHT;
 
1205
 
 
1206
          event->scroll.window = window;
 
1207
          event->scroll.time = xevent->xbutton.time;
 
1208
          event->scroll.x = xevent->xbutton.x;
 
1209
          event->scroll.y = xevent->xbutton.y;
 
1210
          event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
 
1211
          event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
 
1212
          event->scroll.state = (GdkModifierType) xevent->xbutton.state;
 
1213
          event->scroll.device = display->core_pointer;
 
1214
          
 
1215
          if (!set_screen_from_root (display, event, xevent->xbutton.root))
 
1216
            {
 
1217
              return_val = FALSE;
 
1218
              break;
 
1219
            }
 
1220
          
 
1221
          break;
 
1222
          
 
1223
        default:
 
1224
          event->button.type = GDK_BUTTON_PRESS;
 
1225
          event->button.window = window;
 
1226
          event->button.time = xevent->xbutton.time;
 
1227
          event->button.x = xevent->xbutton.x;
 
1228
          event->button.y = xevent->xbutton.y;
 
1229
          event->button.x_root = (gfloat)xevent->xbutton.x_root;
 
1230
          event->button.y_root = (gfloat)xevent->xbutton.y_root;
 
1231
          event->button.axes = NULL;
 
1232
          event->button.state = (GdkModifierType) xevent->xbutton.state;
 
1233
          event->button.button = xevent->xbutton.button;
 
1234
          event->button.device = display->core_pointer;
 
1235
          
 
1236
          if (!set_screen_from_root (display, event, xevent->xbutton.root))
 
1237
            {
 
1238
              return_val = FALSE;
 
1239
              break;
 
1240
            }
 
1241
          break;
 
1242
        }
 
1243
 
 
1244
      set_user_time (window, event);
 
1245
 
 
1246
      break;
 
1247
      
 
1248
    case ButtonRelease:
 
1249
      GDK_NOTE (EVENTS, 
 
1250
                g_message ("button release:\twindow: %ld  x,y: %d %d  button: %d",
 
1251
                           xevent->xbutton.window,
 
1252
                           xevent->xbutton.x, xevent->xbutton.y,
 
1253
                           xevent->xbutton.button));
 
1254
      
 
1255
      if (window_private == NULL)
 
1256
        {
 
1257
          return_val = FALSE;
 
1258
          break;
 
1259
        }
 
1260
      
 
1261
      /* We treat button presses as scroll wheel events, so ignore the release */
 
1262
      if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
 
1263
          xevent->xbutton.button == 6 || xevent->xbutton.button ==7)
 
1264
        {
 
1265
          return_val = FALSE;
 
1266
          break;
 
1267
        }
 
1268
 
 
1269
      event->button.type = GDK_BUTTON_RELEASE;
 
1270
      event->button.window = window;
 
1271
      event->button.time = xevent->xbutton.time;
 
1272
      event->button.x = xevent->xbutton.x;
 
1273
      event->button.y = xevent->xbutton.y;
 
1274
      event->button.x_root = (gfloat)xevent->xbutton.x_root;
 
1275
      event->button.y_root = (gfloat)xevent->xbutton.y_root;
 
1276
      event->button.axes = NULL;
 
1277
      event->button.state = (GdkModifierType) xevent->xbutton.state;
 
1278
      event->button.button = xevent->xbutton.button;
 
1279
      event->button.device = display->core_pointer;
 
1280
 
 
1281
      if (!set_screen_from_root (display, event, xevent->xbutton.root))
 
1282
        return_val = FALSE;
 
1283
      
 
1284
      break;
 
1285
      
 
1286
    case MotionNotify:
 
1287
      GDK_NOTE (EVENTS,
 
1288
                g_message ("motion notify:\t\twindow: %ld  x,y: %d %d  hint: %s", 
 
1289
                           xevent->xmotion.window,
 
1290
                           xevent->xmotion.x, xevent->xmotion.y,
 
1291
                           (xevent->xmotion.is_hint) ? "true" : "false"));
 
1292
      
 
1293
      if (window_private == NULL)
 
1294
        {
 
1295
          return_val = FALSE;
 
1296
          break;
 
1297
        }
 
1298
 
 
1299
      event->motion.type = GDK_MOTION_NOTIFY;
 
1300
      event->motion.window = window;
 
1301
      event->motion.time = xevent->xmotion.time;
 
1302
      event->motion.x = xevent->xmotion.x;
 
1303
      event->motion.y = xevent->xmotion.y;
 
1304
      event->motion.x_root = (gfloat)xevent->xmotion.x_root;
 
1305
      event->motion.y_root = (gfloat)xevent->xmotion.y_root;
 
1306
      event->motion.axes = NULL;
 
1307
      event->motion.state = (GdkModifierType) xevent->xmotion.state;
 
1308
      event->motion.is_hint = xevent->xmotion.is_hint;
 
1309
      event->motion.device = display->core_pointer;
 
1310
      
 
1311
      if (!set_screen_from_root (display, event, xevent->xbutton.root))
 
1312
        {
 
1313
          return_val = FALSE;
 
1314
          break;
 
1315
        }
 
1316
            
 
1317
      break;
 
1318
      
 
1319
    case EnterNotify:
 
1320
      GDK_NOTE (EVENTS,
 
1321
                g_message ("enter notify:\t\twindow: %ld  detail: %d subwin: %ld mode: %d",
 
1322
                           xevent->xcrossing.window,
 
1323
                           xevent->xcrossing.detail,
 
1324
                           xevent->xcrossing.subwindow,
 
1325
                           xevent->xcrossing.mode));
 
1326
 
 
1327
      if (window_private == NULL)
 
1328
        {
 
1329
          return_val = FALSE;
 
1330
          break;
 
1331
        }
 
1332
      
 
1333
      if (!set_screen_from_root (display, event, xevent->xbutton.root))
 
1334
        {
 
1335
          return_val = FALSE;
 
1336
          break;
 
1337
        }
 
1338
      
 
1339
      /* Handle focusing (in the case where no window manager is running */
 
1340
      if (toplevel && xevent->xcrossing.detail != NotifyInferior)
 
1341
        {
 
1342
          toplevel->has_pointer = TRUE;
 
1343
 
 
1344
          if (xevent->xcrossing.focus && !toplevel->has_focus_window)
 
1345
            {
 
1346
              gboolean had_focus = HAS_FOCUS (toplevel);
 
1347
              
 
1348
              toplevel->has_pointer_focus = TRUE;
 
1349
              
 
1350
              if (HAS_FOCUS (toplevel) != had_focus)
 
1351
                generate_focus_event (window, TRUE);
 
1352
            }
 
1353
        }
 
1354
 
 
1355
      event->crossing.type = GDK_ENTER_NOTIFY;
 
1356
      event->crossing.window = window;
 
1357
      
 
1358
      /* If the subwindow field of the XEvent is non-NULL, then
 
1359
       *  lookup the corresponding GdkWindow.
 
1360
       */
 
1361
      if (xevent->xcrossing.subwindow != None)
 
1362
        event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
 
1363
      else
 
1364
        event->crossing.subwindow = NULL;
 
1365
      
 
1366
      event->crossing.time = xevent->xcrossing.time;
 
1367
      event->crossing.x = xevent->xcrossing.x;
 
1368
      event->crossing.y = xevent->xcrossing.y;
 
1369
      event->crossing.x_root = xevent->xcrossing.x_root;
 
1370
      event->crossing.y_root = xevent->xcrossing.y_root;
 
1371
      
 
1372
      /* Translate the crossing mode into Gdk terms.
 
1373
       */
 
1374
      switch (xevent->xcrossing.mode)
 
1375
        {
 
1376
        case NotifyNormal:
 
1377
          event->crossing.mode = GDK_CROSSING_NORMAL;
 
1378
          break;
 
1379
        case NotifyGrab:
 
1380
          event->crossing.mode = GDK_CROSSING_GRAB;
 
1381
          break;
 
1382
        case NotifyUngrab:
 
1383
          event->crossing.mode = GDK_CROSSING_UNGRAB;
 
1384
          break;
 
1385
        };
 
1386
      
 
1387
      /* Translate the crossing detail into Gdk terms.
 
1388
       */
 
1389
      switch (xevent->xcrossing.detail)
 
1390
        {
 
1391
        case NotifyInferior:
 
1392
          event->crossing.detail = GDK_NOTIFY_INFERIOR;
 
1393
          break;
 
1394
        case NotifyAncestor:
 
1395
          event->crossing.detail = GDK_NOTIFY_ANCESTOR;
 
1396
          break;
 
1397
        case NotifyVirtual:
 
1398
          event->crossing.detail = GDK_NOTIFY_VIRTUAL;
 
1399
          break;
 
1400
        case NotifyNonlinear:
 
1401
          event->crossing.detail = GDK_NOTIFY_NONLINEAR;
 
1402
          break;
 
1403
        case NotifyNonlinearVirtual:
 
1404
          event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
 
1405
          break;
 
1406
        default:
 
1407
          event->crossing.detail = GDK_NOTIFY_UNKNOWN;
 
1408
          break;
 
1409
        }
 
1410
      
 
1411
      event->crossing.focus = xevent->xcrossing.focus;
 
1412
      event->crossing.state = xevent->xcrossing.state;
 
1413
  
 
1414
      break;
 
1415
      
 
1416
    case LeaveNotify:
 
1417
      GDK_NOTE (EVENTS, 
 
1418
                g_message ("leave notify:\t\twindow: %ld  detail: %d subwin: %ld mode: %d",
 
1419
                           xevent->xcrossing.window,
 
1420
                           xevent->xcrossing.detail,
 
1421
                           xevent->xcrossing.subwindow,
 
1422
                           xevent->xcrossing.mode));
 
1423
 
 
1424
      if (window_private == NULL)
 
1425
        {
 
1426
          return_val = FALSE;
 
1427
          break;
 
1428
        }
 
1429
 
 
1430
      if (!set_screen_from_root (display, event, xevent->xbutton.root))
 
1431
        {
 
1432
          return_val = FALSE;
 
1433
          break;
 
1434
        }
 
1435
                  
 
1436
      /* Handle focusing (in the case where no window manager is running */
 
1437
      if (toplevel && xevent->xcrossing.detail != NotifyInferior)
 
1438
        {
 
1439
          toplevel->has_pointer = FALSE;
 
1440
 
 
1441
          if (xevent->xcrossing.focus && !toplevel->has_focus_window)
 
1442
            {
 
1443
              gboolean had_focus = HAS_FOCUS (toplevel);
 
1444
              
 
1445
              toplevel->has_pointer_focus = FALSE;
 
1446
              
 
1447
              if (HAS_FOCUS (toplevel) != had_focus)
 
1448
                generate_focus_event (window, FALSE);
 
1449
            }
 
1450
        }
 
1451
 
 
1452
      event->crossing.type = GDK_LEAVE_NOTIFY;
 
1453
      event->crossing.window = window;
 
1454
      
 
1455
      /* If the subwindow field of the XEvent is non-NULL, then
 
1456
       *  lookup the corresponding GdkWindow.
 
1457
       */
 
1458
      if (xevent->xcrossing.subwindow != None)
 
1459
        event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
 
1460
      else
 
1461
        event->crossing.subwindow = NULL;
 
1462
      
 
1463
      event->crossing.time = xevent->xcrossing.time;
 
1464
      event->crossing.x = xevent->xcrossing.x;
 
1465
      event->crossing.y = xevent->xcrossing.y;
 
1466
      event->crossing.x_root = xevent->xcrossing.x_root;
 
1467
      event->crossing.y_root = xevent->xcrossing.y_root;
 
1468
      
 
1469
      /* Translate the crossing mode into Gdk terms.
 
1470
       */
 
1471
      switch (xevent->xcrossing.mode)
 
1472
        {
 
1473
        case NotifyNormal:
 
1474
          event->crossing.mode = GDK_CROSSING_NORMAL;
 
1475
          break;
 
1476
        case NotifyGrab:
 
1477
          event->crossing.mode = GDK_CROSSING_GRAB;
 
1478
          break;
 
1479
        case NotifyUngrab:
 
1480
          event->crossing.mode = GDK_CROSSING_UNGRAB;
 
1481
          break;
 
1482
        };
 
1483
      
 
1484
      /* Translate the crossing detail into Gdk terms.
 
1485
       */
 
1486
      switch (xevent->xcrossing.detail)
 
1487
        {
 
1488
        case NotifyInferior:
 
1489
          event->crossing.detail = GDK_NOTIFY_INFERIOR;
 
1490
          break;
 
1491
        case NotifyAncestor:
 
1492
          event->crossing.detail = GDK_NOTIFY_ANCESTOR;
 
1493
          break;
 
1494
        case NotifyVirtual:
 
1495
          event->crossing.detail = GDK_NOTIFY_VIRTUAL;
 
1496
          break;
 
1497
        case NotifyNonlinear:
 
1498
          event->crossing.detail = GDK_NOTIFY_NONLINEAR;
 
1499
          break;
 
1500
        case NotifyNonlinearVirtual:
 
1501
          event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
 
1502
          break;
 
1503
        default:
 
1504
          event->crossing.detail = GDK_NOTIFY_UNKNOWN;
 
1505
          break;
 
1506
        }
 
1507
      
 
1508
      event->crossing.focus = xevent->xcrossing.focus;
 
1509
      event->crossing.state = xevent->xcrossing.state;
 
1510
      
 
1511
      break;
 
1512
      
 
1513
      /* We only care about focus events that indicate that _this_
 
1514
       * window (not a ancestor or child) got or lost the focus
 
1515
       */
 
1516
    case FocusIn:
 
1517
      GDK_NOTE (EVENTS,
 
1518
                g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
 
1519
                           xevent->xfocus.window,
 
1520
                           notify_details[xevent->xfocus.detail],
 
1521
                           notify_modes[xevent->xfocus.mode]));
 
1522
      
 
1523
      if (toplevel)
 
1524
        {
 
1525
          gboolean had_focus = HAS_FOCUS (toplevel);
 
1526
          
 
1527
          switch (xevent->xfocus.detail)
 
1528
            {
 
1529
            case NotifyAncestor:
 
1530
            case NotifyVirtual:
 
1531
              /* When the focus moves from an ancestor of the window to
 
1532
               * the window or a descendent of the window, *and* the
 
1533
               * pointer is inside the window, then we were previously
 
1534
               * receiving keystroke events in the has_pointer_focus
 
1535
               * case and are now receiving them in the
 
1536
               * has_focus_window case.
 
1537
               */
 
1538
              if (toplevel->has_pointer &&
 
1539
                  xevent->xfocus.mode != NotifyGrab &&
 
1540
                  xevent->xfocus.mode != NotifyUngrab)
 
1541
                toplevel->has_pointer_focus = FALSE;
 
1542
              
 
1543
              /* fall through */
 
1544
            case NotifyNonlinear:
 
1545
            case NotifyNonlinearVirtual:
 
1546
              if (xevent->xfocus.mode != NotifyGrab &&
 
1547
                  xevent->xfocus.mode != NotifyUngrab)
 
1548
                toplevel->has_focus_window = TRUE;
 
1549
              /* We pretend that the focus moves to the grab
 
1550
               * window, so we pay attention to NotifyGrab
 
1551
               * NotifyUngrab, and ignore NotifyWhileGrabbed
 
1552
               */
 
1553
              if (xevent->xfocus.mode != NotifyWhileGrabbed)
 
1554
                toplevel->has_focus = TRUE;
 
1555
              break;
 
1556
            case NotifyPointer:
 
1557
              /* The X server sends NotifyPointer/NotifyGrab,
 
1558
               * but the pointer focus is ignored while a
 
1559
               * grab is in effect
 
1560
               */
 
1561
              if (xevent->xfocus.mode != NotifyGrab &&
 
1562
                  xevent->xfocus.mode != NotifyUngrab)
 
1563
                toplevel->has_pointer_focus = TRUE;
 
1564
              break;
 
1565
            case NotifyInferior:
 
1566
            case NotifyPointerRoot:
 
1567
            case NotifyDetailNone:
 
1568
              break;
 
1569
            }
 
1570
 
 
1571
          if (HAS_FOCUS (toplevel) != had_focus)
 
1572
            generate_focus_event (window, TRUE);
 
1573
        }
 
1574
      break;
 
1575
    case FocusOut:
 
1576
      GDK_NOTE (EVENTS,
 
1577
                g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
 
1578
                           xevent->xfocus.window,
 
1579
                           notify_details[xevent->xfocus.detail],
 
1580
                           notify_modes[xevent->xfocus.mode]));
 
1581
      
 
1582
      if (toplevel)
 
1583
        {
 
1584
          gboolean had_focus = HAS_FOCUS (toplevel);
 
1585
            
 
1586
          switch (xevent->xfocus.detail)
 
1587
            {
 
1588
            case NotifyAncestor:
 
1589
            case NotifyVirtual:
 
1590
              /* When the focus moves from the window or a descendent
 
1591
               * of the window to an ancestor of the window, *and* the
 
1592
               * pointer is inside the window, then we were previously
 
1593
               * receiving keystroke events in the has_focus_window
 
1594
               * case and are now receiving them in the
 
1595
               * has_pointer_focus case.
 
1596
               */
 
1597
              if (toplevel->has_pointer &&
 
1598
                  xevent->xfocus.mode != NotifyGrab &&
 
1599
                  xevent->xfocus.mode != NotifyUngrab)
 
1600
                toplevel->has_pointer_focus = TRUE;
 
1601
 
 
1602
              /* fall through */
 
1603
            case NotifyNonlinear:
 
1604
            case NotifyNonlinearVirtual:
 
1605
              if (xevent->xfocus.mode != NotifyGrab &&
 
1606
                  xevent->xfocus.mode != NotifyUngrab)
 
1607
                toplevel->has_focus_window = FALSE;
 
1608
              if (xevent->xfocus.mode != NotifyWhileGrabbed)
 
1609
                toplevel->has_focus = FALSE;
 
1610
              break;
 
1611
            case NotifyPointer:
 
1612
              if (xevent->xfocus.mode != NotifyGrab &&
 
1613
                  xevent->xfocus.mode != NotifyUngrab)
 
1614
                toplevel->has_pointer_focus = FALSE;
 
1615
            break;
 
1616
            case NotifyInferior:
 
1617
            case NotifyPointerRoot:
 
1618
            case NotifyDetailNone:
 
1619
              break;
 
1620
            }
 
1621
 
 
1622
          if (HAS_FOCUS (toplevel) != had_focus)
 
1623
            generate_focus_event (window, FALSE);
 
1624
        }
 
1625
      break;
 
1626
 
 
1627
#if 0      
 
1628
          /* gdk_keyboard_grab() causes following events. These events confuse
 
1629
           * the XIM focus, so ignore them.
 
1630
           */
 
1631
          if (xevent->xfocus.mode == NotifyGrab ||
 
1632
              xevent->xfocus.mode == NotifyUngrab)
 
1633
            break;
 
1634
#endif
 
1635
 
 
1636
    case KeymapNotify:
 
1637
      GDK_NOTE (EVENTS,
 
1638
                g_message ("keymap notify"));
 
1639
 
 
1640
      /* Not currently handled */
 
1641
      return_val = FALSE;
 
1642
      break;
 
1643
      
 
1644
    case Expose:
 
1645
      GDK_NOTE (EVENTS,
 
1646
                g_message ("expose:\t\twindow: %ld  %d  x,y: %d %d  w,h: %d %d%s",
 
1647
                           xevent->xexpose.window, xevent->xexpose.count,
 
1648
                           xevent->xexpose.x, xevent->xexpose.y,
 
1649
                           xevent->xexpose.width, xevent->xexpose.height,
 
1650
                           event->any.send_event ? " (send)" : ""));
 
1651
     
 
1652
      if (window_private == NULL)
 
1653
        {
 
1654
          return_val = FALSE;
 
1655
          break;
 
1656
        }
 
1657
 
 
1658
      {
 
1659
        GdkRectangle expose_rect;
 
1660
 
 
1661
        expose_rect.x = xevent->xexpose.x;
 
1662
        expose_rect.y = xevent->xexpose.y;
 
1663
        expose_rect.width = xevent->xexpose.width;
 
1664
        expose_rect.height = xevent->xexpose.height;
 
1665
 
 
1666
        _gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
 
1667
         return_val = FALSE;
 
1668
      }
 
1669
 
 
1670
      break;
 
1671
      
 
1672
    case GraphicsExpose:
 
1673
      {
 
1674
        GdkRectangle expose_rect;
 
1675
 
 
1676
        GDK_NOTE (EVENTS,
 
1677
                  g_message ("graphics expose:\tdrawable: %ld",
 
1678
                             xevent->xgraphicsexpose.drawable));
 
1679
 
 
1680
        if (window_private == NULL)
 
1681
          {
 
1682
            return_val = FALSE;
 
1683
            break;
 
1684
          }
 
1685
        
 
1686
        expose_rect.x = xevent->xgraphicsexpose.x;
 
1687
        expose_rect.y = xevent->xgraphicsexpose.y;
 
1688
        expose_rect.width = xevent->xgraphicsexpose.width;
 
1689
        expose_rect.height = xevent->xgraphicsexpose.height;
 
1690
            
 
1691
        if (return_exposes)
 
1692
          {
 
1693
            event->expose.type = GDK_EXPOSE;
 
1694
            event->expose.area = expose_rect;
 
1695
            event->expose.region = gdk_region_rectangle (&expose_rect);
 
1696
            event->expose.window = window;
 
1697
            event->expose.count = xevent->xgraphicsexpose.count;
 
1698
 
 
1699
            return_val = TRUE;
 
1700
          }
 
1701
        else
 
1702
          {
 
1703
            _gdk_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
 
1704
            
 
1705
            return_val = FALSE;
 
1706
          }
 
1707
        
 
1708
      }
 
1709
      break;
 
1710
      
 
1711
    case NoExpose:
 
1712
      GDK_NOTE (EVENTS,
 
1713
                g_message ("no expose:\t\tdrawable: %ld",
 
1714
                           xevent->xnoexpose.drawable));
 
1715
      
 
1716
      event->no_expose.type = GDK_NO_EXPOSE;
 
1717
      event->no_expose.window = window;
 
1718
      
 
1719
      break;
 
1720
      
 
1721
    case VisibilityNotify:
 
1722
#ifdef G_ENABLE_DEBUG
 
1723
      if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
 
1724
        switch (xevent->xvisibility.state)
 
1725
          {
 
1726
          case VisibilityFullyObscured:
 
1727
            g_message ("visibility notify:\twindow: %ld  none",
 
1728
                       xevent->xvisibility.window);
 
1729
            break;
 
1730
          case VisibilityPartiallyObscured:
 
1731
            g_message ("visibility notify:\twindow: %ld  partial",
 
1732
                       xevent->xvisibility.window);
 
1733
            break;
 
1734
          case VisibilityUnobscured:
 
1735
            g_message ("visibility notify:\twindow: %ld  full",
 
1736
                       xevent->xvisibility.window);
 
1737
            break;
 
1738
          }
 
1739
#endif /* G_ENABLE_DEBUG */
 
1740
      
 
1741
      if (window_private == NULL)
 
1742
        {
 
1743
          return_val = FALSE;
 
1744
          break;
 
1745
        }
 
1746
      
 
1747
      event->visibility.type = GDK_VISIBILITY_NOTIFY;
 
1748
      event->visibility.window = window;
 
1749
      
 
1750
      switch (xevent->xvisibility.state)
 
1751
        {
 
1752
        case VisibilityFullyObscured:
 
1753
          event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
 
1754
          break;
 
1755
          
 
1756
        case VisibilityPartiallyObscured:
 
1757
          event->visibility.state = GDK_VISIBILITY_PARTIAL;
 
1758
          break;
 
1759
          
 
1760
        case VisibilityUnobscured:
 
1761
          event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
 
1762
          break;
 
1763
        }
 
1764
      
 
1765
      break;
 
1766
      
 
1767
    case CreateNotify:
 
1768
      GDK_NOTE (EVENTS,
 
1769
                g_message ("create notify:\twindow: %ld  x,y: %d %d     w,h: %d %d  b-w: %d  parent: %ld         ovr: %d",
 
1770
                           xevent->xcreatewindow.window,
 
1771
                           xevent->xcreatewindow.x,
 
1772
                           xevent->xcreatewindow.y,
 
1773
                           xevent->xcreatewindow.width,
 
1774
                           xevent->xcreatewindow.height,
 
1775
                           xevent->xcreatewindow.border_width,
 
1776
                           xevent->xcreatewindow.parent,
 
1777
                           xevent->xcreatewindow.override_redirect));
 
1778
      /* not really handled */
 
1779
      break;
 
1780
      
 
1781
    case DestroyNotify:
 
1782
      GDK_NOTE (EVENTS,
 
1783
                g_message ("destroy notify:\twindow: %ld",
 
1784
                           xevent->xdestroywindow.window));
 
1785
 
 
1786
      /* Ignore DestroyNotify from SubstructureNotifyMask */
 
1787
      if (xevent->xdestroywindow.window == xevent->xdestroywindow.event)
 
1788
        {
 
1789
          event->any.type = GDK_DESTROY;
 
1790
          event->any.window = window;
 
1791
          
 
1792
          return_val = window_private && !GDK_WINDOW_DESTROYED (window);
 
1793
          
 
1794
          if (window && GDK_WINDOW_XID (window) != screen_x11->xroot_window)
 
1795
            gdk_window_destroy_notify (window);
 
1796
        }
 
1797
      else
 
1798
        return_val = FALSE;
 
1799
      
 
1800
      break;
 
1801
      
 
1802
    case UnmapNotify:
 
1803
      GDK_NOTE (EVENTS,
 
1804
                g_message ("unmap notify:\t\twindow: %ld",
 
1805
                           xevent->xmap.window));
 
1806
      
 
1807
      event->any.type = GDK_UNMAP;
 
1808
      event->any.window = window;      
 
1809
 
 
1810
      /* If the WM supports the _NET_WM_STATE_HIDDEN hint, we do not want to
 
1811
       * interpret UnmapNotify events as implying iconic state.
 
1812
       * http://bugzilla.gnome.org/show_bug.cgi?id=590726.
 
1813
       */
 
1814
      if (screen &&
 
1815
          !gdk_x11_screen_supports_net_wm_hint (screen,
 
1816
                                                gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN")))
 
1817
        {
 
1818
          /* If we are shown (not withdrawn) and get an unmap, it means we were
 
1819
           * iconified in the X sense. If we are withdrawn, and get an unmap, it
 
1820
           * means we hid the window ourselves, so we will have already flipped
 
1821
           * the iconified bit off.
 
1822
           */
 
1823
          if (window && GDK_WINDOW_IS_MAPPED (window))
 
1824
            gdk_synthesize_window_state (window,
 
1825
                                         0,
 
1826
                                         GDK_WINDOW_STATE_ICONIFIED);
 
1827
        }
 
1828
 
 
1829
      if (window)
 
1830
        _gdk_xgrab_check_unmap (window, xevent->xany.serial);
 
1831
 
 
1832
      break;
 
1833
      
 
1834
    case MapNotify:
 
1835
      GDK_NOTE (EVENTS,
 
1836
                g_message ("map notify:\t\twindow: %ld",
 
1837
                           xevent->xmap.window));
 
1838
      
 
1839
      event->any.type = GDK_MAP;
 
1840
      event->any.window = window;
 
1841
 
 
1842
      /* Unset iconified if it was set */
 
1843
      if (window && (((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_ICONIFIED))
 
1844
        gdk_synthesize_window_state (window,
 
1845
                                     GDK_WINDOW_STATE_ICONIFIED,
 
1846
                                     0);
 
1847
      
 
1848
      break;
 
1849
      
 
1850
    case ReparentNotify:
 
1851
      GDK_NOTE (EVENTS,
 
1852
                g_message ("reparent notify:\twindow: %ld  x,y: %d %d  parent: %ld      ovr: %d",
 
1853
                           xevent->xreparent.window,
 
1854
                           xevent->xreparent.x,
 
1855
                           xevent->xreparent.y,
 
1856
                           xevent->xreparent.parent,
 
1857
                           xevent->xreparent.override_redirect));
 
1858
 
 
1859
      /* Not currently handled */
 
1860
      return_val = FALSE;
 
1861
      break;
 
1862
      
 
1863
    case ConfigureNotify:
 
1864
      GDK_NOTE (EVENTS,
 
1865
                g_message ("configure notify:\twindow: %ld  x,y: %d %d  w,h: %d %d  b-w: %d  above: %ld  ovr: %d%s",
 
1866
                           xevent->xconfigure.window,
 
1867
                           xevent->xconfigure.x,
 
1868
                           xevent->xconfigure.y,
 
1869
                           xevent->xconfigure.width,
 
1870
                           xevent->xconfigure.height,
 
1871
                           xevent->xconfigure.border_width,
 
1872
                           xevent->xconfigure.above,
 
1873
                           xevent->xconfigure.override_redirect,
 
1874
                           !window
 
1875
                           ? " (discarding)"
 
1876
                           : GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD
 
1877
                           ? " (discarding child)"
 
1878
                           : xevent->xconfigure.event != xevent->xconfigure.window
 
1879
                           ? " (discarding substructure)"
 
1880
                           : ""));
 
1881
      if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
 
1882
        { 
 
1883
          window_private->width = xevent->xconfigure.width;
 
1884
          window_private->height = xevent->xconfigure.height;
 
1885
 
 
1886
          _gdk_window_update_size (window);
 
1887
          _gdk_x11_drawable_update_size (window_private->impl);
 
1888
          _gdk_x11_screen_size_changed (screen, xevent);
 
1889
        }
 
1890
 
 
1891
      if (window &&
 
1892
          xevent->xconfigure.event == xevent->xconfigure.window &&
 
1893
          !GDK_WINDOW_DESTROYED (window) &&
 
1894
          window_private->input_window != NULL)
 
1895
        _gdk_input_configure_event (&xevent->xconfigure, window);
 
1896
      
 
1897
#ifdef HAVE_XSYNC
 
1898
      if (toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value))
 
1899
        {
 
1900
          toplevel->current_counter_value = toplevel->pending_counter_value;
 
1901
          XSyncIntToValue (&toplevel->pending_counter_value, 0);
 
1902
        }
 
1903
#endif
 
1904
 
 
1905
      if (!window ||
 
1906
          xevent->xconfigure.event != xevent->xconfigure.window ||
 
1907
          GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
 
1908
          GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
 
1909
        return_val = FALSE;
 
1910
      else
 
1911
        {
 
1912
          event->configure.type = GDK_CONFIGURE;
 
1913
          event->configure.window = window;
 
1914
          event->configure.width = xevent->xconfigure.width;
 
1915
          event->configure.height = xevent->xconfigure.height;
 
1916
          
 
1917
          if (!xevent->xconfigure.send_event &&
 
1918
              !xevent->xconfigure.override_redirect &&
 
1919
              !GDK_WINDOW_DESTROYED (window))
 
1920
            {
 
1921
              gint tx = 0;
 
1922
              gint ty = 0;
 
1923
              Window child_window = 0;
 
1924
 
 
1925
              gdk_error_trap_push ();
 
1926
              if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window),
 
1927
                                         GDK_DRAWABLE_XID (window),
 
1928
                                         screen_x11->xroot_window,
 
1929
                                         0, 0,
 
1930
                                         &tx, &ty,
 
1931
                                         &child_window))
 
1932
                {
 
1933
                  event->configure.x = tx;
 
1934
                  event->configure.y = ty;
 
1935
                }
 
1936
              gdk_error_trap_pop ();
 
1937
            }
 
1938
          else
 
1939
            {
 
1940
              event->configure.x = xevent->xconfigure.x;
 
1941
              event->configure.y = xevent->xconfigure.y;
 
1942
            }
 
1943
          window_private->x = event->configure.x;
 
1944
          window_private->y = event->configure.y;
 
1945
          window_private->width = xevent->xconfigure.width;
 
1946
          window_private->height = xevent->xconfigure.height;
 
1947
          
 
1948
          _gdk_window_update_size (window);
 
1949
          _gdk_x11_drawable_update_size (window_private->impl);
 
1950
          
 
1951
          if (window_private->resize_count >= 1)
 
1952
            {
 
1953
              window_private->resize_count -= 1;
 
1954
 
 
1955
              if (window_private->resize_count == 0)
 
1956
                _gdk_moveresize_configure_done (display, window);
 
1957
            }
 
1958
        }
 
1959
      break;
 
1960
      
 
1961
    case PropertyNotify:
 
1962
      GDK_NOTE (EVENTS,
 
1963
                g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
 
1964
                           xevent->xproperty.window,
 
1965
                           xevent->xproperty.atom,
 
1966
                           "\"",
 
1967
                           gdk_x11_get_xatom_name_for_display (display, xevent->xproperty.atom),
 
1968
                           "\""));
 
1969
 
 
1970
      if (window_private == NULL)
 
1971
        {
 
1972
          return_val = FALSE;
 
1973
          break;
 
1974
        }
 
1975
 
 
1976
      /* We compare with the serial of the last time we mapped the
 
1977
       * window to avoid refetching properties that we set ourselves
 
1978
       */
 
1979
      if (toplevel &&
 
1980
          xevent->xproperty.serial >= toplevel->map_serial)
 
1981
        {
 
1982
          if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"))
 
1983
            gdk_check_wm_state_changed (window);
 
1984
          
 
1985
          if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"))
 
1986
            gdk_check_wm_desktop_changed (window);
 
1987
        }
 
1988
      
 
1989
      if (window_private->event_mask & GDK_PROPERTY_CHANGE_MASK) 
 
1990
        {
 
1991
          event->property.type = GDK_PROPERTY_NOTIFY;
 
1992
          event->property.window = window;
 
1993
          event->property.atom = gdk_x11_xatom_to_atom_for_display (display, xevent->xproperty.atom);
 
1994
          event->property.time = xevent->xproperty.time;
 
1995
          event->property.state = xevent->xproperty.state;
 
1996
        }
 
1997
      else
 
1998
        return_val = FALSE;
 
1999
 
 
2000
      break;
 
2001
      
 
2002
    case SelectionClear:
 
2003
      GDK_NOTE (EVENTS,
 
2004
                g_message ("selection clear:\twindow: %ld",
 
2005
                           xevent->xproperty.window));
 
2006
 
 
2007
      if (_gdk_selection_filter_clear_event (&xevent->xselectionclear))
 
2008
        {
 
2009
          event->selection.type = GDK_SELECTION_CLEAR;
 
2010
          event->selection.window = window;
 
2011
          event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionclear.selection);
 
2012
          event->selection.time = xevent->xselectionclear.time;
 
2013
        }
 
2014
      else
 
2015
        return_val = FALSE;
 
2016
          
 
2017
      break;
 
2018
      
 
2019
    case SelectionRequest:
 
2020
      GDK_NOTE (EVENTS,
 
2021
                g_message ("selection request:\twindow: %ld",
 
2022
                           xevent->xproperty.window));
 
2023
      
 
2024
      event->selection.type = GDK_SELECTION_REQUEST;
 
2025
      event->selection.window = window;
 
2026
      event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.selection);
 
2027
      event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.target);
 
2028
      event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.property);
 
2029
      event->selection.requestor = xevent->xselectionrequest.requestor;
 
2030
      event->selection.time = xevent->xselectionrequest.time;
 
2031
      
 
2032
      break;
 
2033
      
 
2034
    case SelectionNotify:
 
2035
      GDK_NOTE (EVENTS,
 
2036
                g_message ("selection notify:\twindow: %ld",
 
2037
                           xevent->xproperty.window));
 
2038
      
 
2039
      
 
2040
      event->selection.type = GDK_SELECTION_NOTIFY;
 
2041
      event->selection.window = window;
 
2042
      event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.selection);
 
2043
      event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.target);
 
2044
      if (xevent->xselection.property == None)
 
2045
        event->selection.property = GDK_NONE;
 
2046
      else
 
2047
        event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.property);
 
2048
      event->selection.time = xevent->xselection.time;
 
2049
      
 
2050
      break;
 
2051
      
 
2052
    case ColormapNotify:
 
2053
      GDK_NOTE (EVENTS,
 
2054
                g_message ("colormap notify:\twindow: %ld",
 
2055
                           xevent->xcolormap.window));
 
2056
      
 
2057
      /* Not currently handled */
 
2058
      return_val = FALSE;
 
2059
      break;
 
2060
      
 
2061
    case ClientMessage:
 
2062
      {
 
2063
        GList *tmp_list;
 
2064
        GdkFilterReturn result = GDK_FILTER_CONTINUE;
 
2065
        GdkAtom message_type = gdk_x11_xatom_to_atom_for_display (display, xevent->xclient.message_type);
 
2066
 
 
2067
        GDK_NOTE (EVENTS,
 
2068
                  g_message ("client message:\twindow: %ld",
 
2069
                             xevent->xclient.window));
 
2070
        
 
2071
        tmp_list = display_x11->client_filters;
 
2072
        while (tmp_list)
 
2073
          {
 
2074
            GdkClientFilter *filter = tmp_list->data;
 
2075
            tmp_list = tmp_list->next;
 
2076
            
 
2077
            if (filter->type == message_type)
 
2078
              {
 
2079
                result = (*filter->function) (xevent, event, filter->data);
 
2080
                if (result != GDK_FILTER_CONTINUE)
 
2081
                  break;
 
2082
              }
 
2083
          }
 
2084
 
 
2085
        switch (result)
 
2086
          {
 
2087
          case GDK_FILTER_REMOVE:
 
2088
            return_val = FALSE;
 
2089
            break;
 
2090
          case GDK_FILTER_TRANSLATE:
 
2091
            return_val = TRUE;
 
2092
            break;
 
2093
          case GDK_FILTER_CONTINUE:
 
2094
            /* Send unknown ClientMessage's on to Gtk for it to use */
 
2095
            if (window_private == NULL)
 
2096
              {
 
2097
                return_val = FALSE;
 
2098
              }
 
2099
            else
 
2100
              {
 
2101
                event->client.type = GDK_CLIENT_EVENT;
 
2102
                event->client.window = window;
 
2103
                event->client.message_type = message_type;
 
2104
                event->client.data_format = xevent->xclient.format;
 
2105
                memcpy(&event->client.data, &xevent->xclient.data,
 
2106
                       sizeof(event->client.data));
 
2107
              }
 
2108
            break;
 
2109
          }
 
2110
      }
 
2111
      
 
2112
      break;
 
2113
      
 
2114
    case MappingNotify:
 
2115
      GDK_NOTE (EVENTS,
 
2116
                g_message ("mapping notify"));
 
2117
      
 
2118
      /* Let XLib know that there is a new keyboard mapping.
 
2119
       */
 
2120
      XRefreshKeyboardMapping (&xevent->xmapping);
 
2121
      _gdk_keymap_keys_changed (display);
 
2122
      return_val = FALSE;
 
2123
      break;
 
2124
 
 
2125
    default:
 
2126
#ifdef HAVE_XKB
 
2127
      if (xevent->type == display_x11->xkb_event_type)
 
2128
        {
 
2129
          XkbEvent *xkb_event = (XkbEvent *)xevent;
 
2130
 
 
2131
          switch (xkb_event->any.xkb_type)
 
2132
            {
 
2133
            case XkbNewKeyboardNotify:
 
2134
            case XkbMapNotify:
 
2135
              _gdk_keymap_keys_changed (display);
 
2136
 
 
2137
              return_val = FALSE;
 
2138
              break;
 
2139
              
 
2140
            case XkbStateNotify:
 
2141
              _gdk_keymap_state_changed (display, xevent);
 
2142
              break;
 
2143
            }
 
2144
        }
 
2145
      else
 
2146
#endif
 
2147
#ifdef HAVE_XFIXES
 
2148
      if (xevent->type - display_x11->xfixes_event_base == XFixesSelectionNotify)
 
2149
        {
 
2150
          XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)xevent;
 
2151
 
 
2152
          _gdk_x11_screen_process_owner_change (screen, xevent);
 
2153
          
 
2154
          event->owner_change.type = GDK_OWNER_CHANGE;
 
2155
          event->owner_change.window = window;
 
2156
          event->owner_change.owner = selection_notify->owner;
 
2157
          event->owner_change.reason = selection_notify->subtype;
 
2158
          event->owner_change.selection = 
 
2159
            gdk_x11_xatom_to_atom_for_display (display, 
 
2160
                                               selection_notify->selection);
 
2161
          event->owner_change.time = selection_notify->timestamp;
 
2162
          event->owner_change.selection_time = selection_notify->selection_timestamp;
 
2163
          
 
2164
          return_val = TRUE;
 
2165
        }
 
2166
      else
 
2167
#endif
 
2168
#ifdef HAVE_RANDR
 
2169
      if (xevent->type - display_x11->xrandr_event_base == RRScreenChangeNotify ||
 
2170
          xevent->type - display_x11->xrandr_event_base == RRNotify)
 
2171
        {
 
2172
          if (screen)
 
2173
            _gdk_x11_screen_size_changed (screen, xevent);
 
2174
        }
 
2175
      else
 
2176
#endif
 
2177
#if defined(HAVE_XCOMPOSITE) && defined (HAVE_XDAMAGE) && defined (HAVE_XFIXES)
 
2178
      if (display_x11->have_xdamage && window_private && window_private->composited &&
 
2179
          xevent->type == display_x11->xdamage_event_base + XDamageNotify &&
 
2180
          ((XDamageNotifyEvent *) xevent)->damage == window_impl->damage)
 
2181
        {
 
2182
          XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) xevent;
 
2183
          XserverRegion repair;
 
2184
          GdkRectangle rect;
 
2185
 
 
2186
          rect.x = window_private->x + damage_event->area.x;
 
2187
          rect.y = window_private->y + damage_event->area.y;
 
2188
          rect.width = damage_event->area.width;
 
2189
          rect.height = damage_event->area.height;
 
2190
 
 
2191
          repair = XFixesCreateRegion (display_x11->xdisplay,
 
2192
                                       &damage_event->area, 1);
 
2193
          XDamageSubtract (display_x11->xdisplay,
 
2194
                           window_impl->damage,
 
2195
                           repair, None);
 
2196
          XFixesDestroyRegion (display_x11->xdisplay, repair);
 
2197
 
 
2198
          if (window_private->parent != NULL)
 
2199
            _gdk_window_process_expose (GDK_WINDOW (window_private->parent),
 
2200
                                        damage_event->serial, &rect);
 
2201
 
 
2202
          return_val = TRUE;
 
2203
        }
 
2204
      else
 
2205
#endif
 
2206
        {
 
2207
          /* something else - (e.g., a Xinput event) */
 
2208
          
 
2209
          if (window_private &&
 
2210
              !GDK_WINDOW_DESTROYED (window_private) &&
 
2211
              window_private->input_window)
 
2212
            return_val = _gdk_input_other_event (event, xevent, window);
 
2213
          else
 
2214
            return_val = FALSE;
 
2215
          
 
2216
          break;
 
2217
        }
 
2218
    }
 
2219
 
 
2220
 done:
 
2221
  if (return_val)
 
2222
    {
 
2223
      if (event->any.window)
 
2224
        g_object_ref (event->any.window);
 
2225
      if (((event->any.type == GDK_ENTER_NOTIFY) ||
 
2226
           (event->any.type == GDK_LEAVE_NOTIFY)) &&
 
2227
          (event->crossing.subwindow != NULL))
 
2228
        g_object_ref (event->crossing.subwindow);
 
2229
    }
 
2230
  else
 
2231
    {
 
2232
      /* Mark this event as having no resources to be freed */
 
2233
      event->any.window = NULL;
 
2234
      event->any.type = GDK_NOTHING;
 
2235
    }
 
2236
  
 
2237
  if (window)
 
2238
    g_object_unref (window);
 
2239
 
 
2240
  return return_val;
 
2241
}
 
2242
 
 
2243
static GdkFilterReturn
 
2244
gdk_wm_protocols_filter (GdkXEvent *xev,
 
2245
                         GdkEvent  *event,
 
2246
                         gpointer data)
 
2247
{
 
2248
  XEvent *xevent = (XEvent *)xev;
 
2249
  GdkWindow *win = event->any.window;
 
2250
  GdkDisplay *display;
 
2251
  Atom atom;
 
2252
 
 
2253
  if (!win)
 
2254
      return GDK_FILTER_REMOVE;    
 
2255
 
 
2256
  display = GDK_WINDOW_DISPLAY (win);
 
2257
  atom = (Atom)xevent->xclient.data.l[0];
 
2258
 
 
2259
  if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
 
2260
    {
 
2261
  /* The delete window request specifies a window
 
2262
   *  to delete. We don't actually destroy the
 
2263
   *  window because "it is only a request". (The
 
2264
   *  window might contain vital data that the
 
2265
   *  program does not want destroyed). Instead
 
2266
   *  the event is passed along to the program,
 
2267
   *  which should then destroy the window.
 
2268
   */
 
2269
      GDK_NOTE (EVENTS,
 
2270
                g_message ("delete window:\t\twindow: %ld",
 
2271
                           xevent->xclient.window));
 
2272
      
 
2273
      event->any.type = GDK_DELETE;
 
2274
 
 
2275
      gdk_x11_window_set_user_time (win, xevent->xclient.data.l[1]);
 
2276
 
 
2277
      return GDK_FILTER_TRANSLATE;
 
2278
    }
 
2279
  else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
 
2280
    {
 
2281
      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
 
2282
      GdkWindowObject *private = (GdkWindowObject *)win;
 
2283
 
 
2284
      /* There is no way of knowing reliably whether we are viewable;
 
2285
       * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
 
2286
       */
 
2287
      if (toplevel && private->accept_focus)
 
2288
        _gdk_x11_set_input_focus_safe (display, toplevel->focus_window,
 
2289
                                       RevertToParent,
 
2290
                                       xevent->xclient.data.l[1]);
 
2291
 
 
2292
      return GDK_FILTER_REMOVE;
 
2293
    }
 
2294
  else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") &&
 
2295
           !_gdk_x11_display_is_root_window (display,
 
2296
                                             xevent->xclient.window))
 
2297
    {
 
2298
      XClientMessageEvent xclient = xevent->xclient;
 
2299
      
 
2300
      xclient.window = GDK_WINDOW_XROOTWIN (win);
 
2301
      XSendEvent (GDK_WINDOW_XDISPLAY (win), 
 
2302
                  xclient.window,
 
2303
                  False, 
 
2304
                  SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xclient);
 
2305
 
 
2306
      return GDK_FILTER_REMOVE;
 
2307
    }
 
2308
  else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST") &&
 
2309
           GDK_DISPLAY_X11 (display)->use_sync)
 
2310
    {
 
2311
      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
 
2312
      if (toplevel)
 
2313
        {
 
2314
#ifdef HAVE_XSYNC
 
2315
          XSyncIntsToValue (&toplevel->pending_counter_value, 
 
2316
                            xevent->xclient.data.l[2], 
 
2317
                            xevent->xclient.data.l[3]);
 
2318
#endif
 
2319
        }
 
2320
      return GDK_FILTER_REMOVE;
 
2321
    }
 
2322
  
 
2323
  return GDK_FILTER_CONTINUE;
 
2324
}
 
2325
 
 
2326
void
 
2327
_gdk_events_queue (GdkDisplay *display)
 
2328
{
 
2329
  GList *node;
 
2330
  GdkEvent *event;
 
2331
  XEvent xevent;
 
2332
  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
 
2333
 
 
2334
  while (!_gdk_event_queue_find_first(display) && XPending (xdisplay))
 
2335
    {
 
2336
      XNextEvent (xdisplay, &xevent);
 
2337
 
 
2338
      switch (xevent.type)
 
2339
        {
 
2340
        case KeyPress:
 
2341
        case KeyRelease:
 
2342
          break;
 
2343
        default:
 
2344
          if (XFilterEvent (&xevent, None))
 
2345
            continue;
 
2346
        }
 
2347
      
 
2348
      event = gdk_event_new (GDK_NOTHING);
 
2349
      
 
2350
      event->any.window = NULL;
 
2351
      event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
 
2352
 
 
2353
      ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
 
2354
 
 
2355
      node = _gdk_event_queue_append (display, event);
 
2356
 
 
2357
      if (gdk_event_translate (display, event, &xevent, FALSE))
 
2358
        {
 
2359
          ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
 
2360
          _gdk_windowing_got_event (display, node, event, xevent.xany.serial);
 
2361
        }
 
2362
      else
 
2363
        {
 
2364
          _gdk_event_queue_remove_link (display, node);
 
2365
          g_list_free_1 (node);
 
2366
          gdk_event_free (event);
 
2367
        }
 
2368
    }
 
2369
}
 
2370
 
 
2371
static gboolean  
 
2372
gdk_event_prepare (GSource  *source,
 
2373
                   gint     *timeout)
 
2374
{
 
2375
  GdkDisplay *display = ((GdkDisplaySource*)source)->display;
 
2376
  gboolean retval;
 
2377
  
 
2378
  GDK_THREADS_ENTER ();
 
2379
 
 
2380
  *timeout = -1;
 
2381
  retval = (_gdk_event_queue_find_first (display) != NULL || 
 
2382
            gdk_check_xpending (display));
 
2383
  
 
2384
  GDK_THREADS_LEAVE ();
 
2385
 
 
2386
  return retval;
 
2387
}
 
2388
 
 
2389
static gboolean  
 
2390
gdk_event_check (GSource *source) 
 
2391
{
 
2392
  GdkDisplaySource *display_source = (GdkDisplaySource*)source;
 
2393
  gboolean retval;
 
2394
 
 
2395
  GDK_THREADS_ENTER ();
 
2396
 
 
2397
  if (display_source->event_poll_fd.revents & G_IO_IN)
 
2398
    retval = (_gdk_event_queue_find_first (display_source->display) != NULL || 
 
2399
              gdk_check_xpending (display_source->display));
 
2400
  else
 
2401
    retval = FALSE;
 
2402
 
 
2403
  GDK_THREADS_LEAVE ();
 
2404
 
 
2405
  return retval;
 
2406
}
 
2407
 
 
2408
static gboolean  
 
2409
gdk_event_dispatch (GSource    *source,
 
2410
                    GSourceFunc callback,
 
2411
                    gpointer    user_data)
 
2412
{
 
2413
  GdkDisplay *display = ((GdkDisplaySource*)source)->display;
 
2414
  GdkEvent *event;
 
2415
 
 
2416
  GDK_THREADS_ENTER ();
 
2417
 
 
2418
  _gdk_events_queue (display);
 
2419
  event = _gdk_event_unqueue (display);
 
2420
 
 
2421
  if (event)
 
2422
    {
 
2423
      if (_gdk_event_func)
 
2424
        (*_gdk_event_func) (event, _gdk_event_data);
 
2425
      
 
2426
      gdk_event_free (event);
 
2427
    }
 
2428
  
 
2429
  GDK_THREADS_LEAVE ();
 
2430
 
 
2431
  return TRUE;
 
2432
}
 
2433
 
 
2434
/**
 
2435
 * gdk_event_send_client_message_for_display:
 
2436
 * @display: the #GdkDisplay for the window where the message is to be sent.
 
2437
 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
 
2438
 * @winid: the window to send the client message to.
 
2439
 *
 
2440
 * On X11, sends an X ClientMessage event to a given window. On
 
2441
 * Windows, sends a message registered with the name
 
2442
 * GDK_WIN32_CLIENT_MESSAGE.
 
2443
 *
 
2444
 * This could be used for communicating between different
 
2445
 * applications, though the amount of data is limited to 20 bytes on
 
2446
 * X11, and to just four bytes on Windows.
 
2447
 *
 
2448
 * Returns: non-zero on success.
 
2449
 *
 
2450
 * Since: 2.2
 
2451
 */
 
2452
gboolean
 
2453
gdk_event_send_client_message_for_display (GdkDisplay     *display,
 
2454
                                           GdkEvent       *event,
 
2455
                                           GdkNativeWindow winid)
 
2456
{
 
2457
  XEvent sev;
 
2458
  
 
2459
  g_return_val_if_fail(event != NULL, FALSE);
 
2460
 
 
2461
  /* Set up our event to send, with the exception of its target window */
 
2462
  sev.xclient.type = ClientMessage;
 
2463
  sev.xclient.display = GDK_DISPLAY_XDISPLAY (display);
 
2464
  sev.xclient.format = event->client.data_format;
 
2465
  sev.xclient.window = winid;
 
2466
  memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
 
2467
  sev.xclient.message_type = gdk_x11_atom_to_xatom_for_display (display, event->client.message_type);
 
2468
  
 
2469
  return _gdk_send_xevent (display, winid, False, NoEventMask, &sev);
 
2470
}
 
2471
 
 
2472
 
 
2473
 
 
2474
/* Sends a ClientMessage to all toplevel client windows */
 
2475
static gboolean
 
2476
gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
 
2477
                                              XEvent     *xev, 
 
2478
                                              guint32     xid,
 
2479
                                              guint       level)
 
2480
{
 
2481
  Atom type = None;
 
2482
  int format;
 
2483
  unsigned long nitems, after;
 
2484
  unsigned char *data;
 
2485
  Window *ret_children, ret_root, ret_parent;
 
2486
  unsigned int ret_nchildren;
 
2487
  gboolean send = FALSE;
 
2488
  gboolean found = FALSE;
 
2489
  gboolean result = FALSE;
 
2490
  int i;
 
2491
  
 
2492
  gdk_error_trap_push ();
 
2493
  
 
2494
  if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid, 
 
2495
                          gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
 
2496
                          0, 0, False, AnyPropertyType,
 
2497
                          &type, &format, &nitems, &after, &data) != Success)
 
2498
    goto out;
 
2499
  
 
2500
  if (type)
 
2501
    {
 
2502
      send = TRUE;
 
2503
      XFree (data);
 
2504
    }
 
2505
  else
 
2506
    {
 
2507
      /* OK, we're all set, now let's find some windows to send this to */
 
2508
      if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xid,
 
2509
                      &ret_root, &ret_parent,
 
2510
                      &ret_children, &ret_nchildren))   
 
2511
        goto out;
 
2512
 
 
2513
      for(i = 0; i < ret_nchildren; i++)
 
2514
        if (gdk_event_send_client_message_to_all_recurse (display, xev, ret_children[i], level + 1))
 
2515
          found = TRUE;
 
2516
 
 
2517
      XFree (ret_children);
 
2518
    }
 
2519
 
 
2520
  if (send || (!found && (level == 1)))
 
2521
    {
 
2522
      xev->xclient.window = xid;
 
2523
      _gdk_send_xevent (display, xid, False, NoEventMask, xev);
 
2524
    }
 
2525
 
 
2526
  result = send || found;
 
2527
 
 
2528
 out:
 
2529
  gdk_error_trap_pop ();
 
2530
 
 
2531
  return result;
 
2532
}
 
2533
 
 
2534
/**
 
2535
 * gdk_screen_broadcast_client_message:
 
2536
 * @screen: the #GdkScreen where the event will be broadcasted.
 
2537
 * @event: the #GdkEvent.
 
2538
 *
 
2539
 * On X11, sends an X ClientMessage event to all toplevel windows on
 
2540
 * @screen. 
 
2541
 *
 
2542
 * Toplevel windows are determined by checking for the WM_STATE property, 
 
2543
 * as described in the Inter-Client Communication Conventions Manual (ICCCM).
 
2544
 * If no windows are found with the WM_STATE property set, the message is 
 
2545
 * sent to all children of the root window.
 
2546
 *
 
2547
 * On Windows, broadcasts a message registered with the name
 
2548
 * GDK_WIN32_CLIENT_MESSAGE to all top-level windows. The amount of
 
2549
 * data is limited to one long, i.e. four bytes.
 
2550
 *
 
2551
 * Since: 2.2
 
2552
 */
 
2553
 
 
2554
void
 
2555
gdk_screen_broadcast_client_message (GdkScreen *screen, 
 
2556
                                     GdkEvent  *event)
 
2557
{
 
2558
  XEvent sev;
 
2559
  GdkWindow *root_window;
 
2560
 
 
2561
  g_return_if_fail (event != NULL);
 
2562
  
 
2563
  root_window = gdk_screen_get_root_window (screen);
 
2564
  
 
2565
  /* Set up our event to send, with the exception of its target window */
 
2566
  sev.xclient.type = ClientMessage;
 
2567
  sev.xclient.display = GDK_WINDOW_XDISPLAY (root_window);
 
2568
  sev.xclient.format = event->client.data_format;
 
2569
  memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
 
2570
  sev.xclient.message_type = 
 
2571
    gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (root_window),
 
2572
                                       event->client.message_type);
 
2573
 
 
2574
  gdk_event_send_client_message_to_all_recurse (gdk_screen_get_display (screen),
 
2575
                                                &sev, 
 
2576
                                                GDK_WINDOW_XID (root_window), 
 
2577
                                                0);
 
2578
}
 
2579
 
 
2580
/*
 
2581
 *--------------------------------------------------------------
 
2582
 * gdk_flush
 
2583
 *
 
2584
 *   Flushes the Xlib output buffer and then waits
 
2585
 *   until all requests have been received and processed
 
2586
 *   by the X server. The only real use for this function
 
2587
 *   is in dealing with XShm.
 
2588
 *
 
2589
 * Arguments:
 
2590
 *
 
2591
 * Results:
 
2592
 *
 
2593
 * Side effects:
 
2594
 *
 
2595
 *--------------------------------------------------------------
 
2596
 */
 
2597
 
 
2598
void
 
2599
gdk_flush (void)
 
2600
{
 
2601
  GSList *tmp_list = _gdk_displays;
 
2602
  
 
2603
  while (tmp_list)
 
2604
    {
 
2605
      XSync (GDK_DISPLAY_XDISPLAY (tmp_list->data), False);
 
2606
      tmp_list = tmp_list->next;
 
2607
    }
 
2608
}
 
2609
 
 
2610
static Bool
 
2611
timestamp_predicate (Display *display,
 
2612
                     XEvent  *xevent,
 
2613
                     XPointer arg)
 
2614
{
 
2615
  Window xwindow = GPOINTER_TO_UINT (arg);
 
2616
  GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
 
2617
 
 
2618
  if (xevent->type == PropertyNotify &&
 
2619
      xevent->xproperty.window == xwindow &&
 
2620
      xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
 
2621
                                                                       "GDK_TIMESTAMP_PROP"))
 
2622
    return True;
 
2623
 
 
2624
  return False;
 
2625
}
 
2626
 
 
2627
/**
 
2628
 * gdk_x11_get_server_time:
 
2629
 * @window: a #GdkWindow, used for communication with the server.
 
2630
 *          The window must have GDK_PROPERTY_CHANGE_MASK in its
 
2631
 *          events mask or a hang will result.
 
2632
 * 
 
2633
 * Routine to get the current X server time stamp. 
 
2634
 * 
 
2635
 * Return value: the time stamp.
 
2636
 **/
 
2637
guint32
 
2638
gdk_x11_get_server_time (GdkWindow *window)
 
2639
{
 
2640
  Display *xdisplay;
 
2641
  Window   xwindow;
 
2642
  guchar c = 'a';
 
2643
  XEvent xevent;
 
2644
  Atom timestamp_prop_atom;
 
2645
 
 
2646
  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
2647
  g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
 
2648
 
 
2649
  xdisplay = GDK_WINDOW_XDISPLAY (window);
 
2650
  xwindow = GDK_WINDOW_XWINDOW (window);
 
2651
  timestamp_prop_atom = 
 
2652
    gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
 
2653
                                           "GDK_TIMESTAMP_PROP");
 
2654
  
 
2655
  XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
 
2656
                   timestamp_prop_atom,
 
2657
                   8, PropModeReplace, &c, 1);
 
2658
 
 
2659
  XIfEvent (xdisplay, &xevent,
 
2660
            timestamp_predicate, GUINT_TO_POINTER(xwindow));
 
2661
 
 
2662
  return xevent.xproperty.time;
 
2663
}
 
2664
 
 
2665
static void
 
2666
fetch_net_wm_check_window (GdkScreen *screen)
 
2667
{
 
2668
  GdkScreenX11 *screen_x11;
 
2669
  GdkDisplay *display;
 
2670
  Atom type;
 
2671
  gint format;
 
2672
  gulong n_items;
 
2673
  gulong bytes_after;
 
2674
  guchar *data;
 
2675
  Window *xwindow;
 
2676
  GTimeVal tv;
 
2677
  gint error;
 
2678
 
 
2679
  screen_x11 = GDK_SCREEN_X11 (screen);
 
2680
  display = screen_x11->display;
 
2681
 
 
2682
  g_return_if_fail (GDK_DISPLAY_X11 (display)->trusted_client);
 
2683
  
 
2684
  g_get_current_time (&tv);
 
2685
 
 
2686
  if (ABS  (tv.tv_sec - screen_x11->last_wmspec_check_time) < 15)
 
2687
    return; /* we've checked recently */
 
2688
 
 
2689
  screen_x11->last_wmspec_check_time = tv.tv_sec;
 
2690
 
 
2691
  data = NULL;
 
2692
  XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
 
2693
                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
 
2694
                      0, G_MAXLONG, False, XA_WINDOW, &type, &format,
 
2695
                      &n_items, &bytes_after, &data);
 
2696
  
 
2697
  if (type != XA_WINDOW)
 
2698
    {
 
2699
      if (data)
 
2700
        XFree (data);
 
2701
      return;
 
2702
    }
 
2703
 
 
2704
  xwindow = (Window *)data;
 
2705
 
 
2706
  if (screen_x11->wmspec_check_window == *xwindow)
 
2707
    {
 
2708
      XFree (xwindow);
 
2709
      return;
 
2710
    }
 
2711
 
 
2712
  gdk_error_trap_push ();
 
2713
 
 
2714
  /* Find out if this WM goes away, so we can reset everything. */
 
2715
  XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
 
2716
  gdk_display_sync (display);
 
2717
 
 
2718
  error = gdk_error_trap_pop ();
 
2719
  if (!error)
 
2720
    {
 
2721
      screen_x11->wmspec_check_window = *xwindow;
 
2722
      screen_x11->need_refetch_net_supported = TRUE;
 
2723
      screen_x11->need_refetch_wm_name = TRUE;
 
2724
 
 
2725
      /* Careful, reentrancy */
 
2726
      _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
 
2727
    }
 
2728
  else if (error == BadWindow)
 
2729
    {
 
2730
      /* Leftover property, try again immediately, new wm may be starting up */
 
2731
      screen_x11->last_wmspec_check_time = 0;
 
2732
    }
 
2733
 
 
2734
  XFree (xwindow);
 
2735
}
 
2736
 
 
2737
/**
 
2738
 * gdk_x11_screen_get_window_manager_name:
 
2739
 * @screen: a #GdkScreen 
 
2740
 * 
 
2741
 * Returns the name of the window manager for @screen. 
 
2742
 * 
 
2743
 * Return value: the name of the window manager screen @screen, or 
 
2744
 * "unknown" if the window manager is unknown. The string is owned by GDK
 
2745
 * and should not be freed.
 
2746
 *
 
2747
 * Since: 2.2
 
2748
 **/
 
2749
const char*
 
2750
gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
 
2751
{
 
2752
  GdkScreenX11 *screen_x11;
 
2753
 
 
2754
  screen_x11 = GDK_SCREEN_X11 (screen);
 
2755
  
 
2756
  if (!G_LIKELY (GDK_DISPLAY_X11 (screen_x11->display)->trusted_client))
 
2757
    return screen_x11->window_manager_name;
 
2758
 
 
2759
  fetch_net_wm_check_window (screen);
 
2760
 
 
2761
  if (screen_x11->need_refetch_wm_name)
 
2762
    {
 
2763
      /* Get the name of the window manager */
 
2764
      screen_x11->need_refetch_wm_name = FALSE;
 
2765
 
 
2766
      g_free (screen_x11->window_manager_name);
 
2767
      screen_x11->window_manager_name = g_strdup ("unknown");
 
2768
      
 
2769
      if (screen_x11->wmspec_check_window != None)
 
2770
        {
 
2771
          Atom type;
 
2772
          gint format;
 
2773
          gulong n_items;
 
2774
          gulong bytes_after;
 
2775
          gchar *name;
 
2776
          
 
2777
          name = NULL;
 
2778
 
 
2779
          gdk_error_trap_push ();
 
2780
          
 
2781
          XGetWindowProperty (GDK_DISPLAY_XDISPLAY (screen_x11->display),
 
2782
                              screen_x11->wmspec_check_window,
 
2783
                              gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
 
2784
                                                                     "_NET_WM_NAME"),
 
2785
                              0, G_MAXLONG, False,
 
2786
                              gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
 
2787
                                                                     "UTF8_STRING"),
 
2788
                              &type, &format, 
 
2789
                              &n_items, &bytes_after,
 
2790
                              (guchar **)&name);
 
2791
          
 
2792
          gdk_display_sync (screen_x11->display);
 
2793
          
 
2794
          gdk_error_trap_pop ();
 
2795
          
 
2796
          if (name != NULL)
 
2797
            {
 
2798
              g_free (screen_x11->window_manager_name);
 
2799
              screen_x11->window_manager_name = g_strdup (name);
 
2800
              XFree (name);
 
2801
            }
 
2802
        }
 
2803
    }
 
2804
  
 
2805
  return GDK_SCREEN_X11 (screen)->window_manager_name;
 
2806
}
 
2807
 
 
2808
typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
 
2809
 
 
2810
struct _NetWmSupportedAtoms
 
2811
{
 
2812
  Atom *atoms;
 
2813
  gulong n_atoms;
 
2814
};
 
2815
 
 
2816
static void
 
2817
cleanup_atoms(gpointer data)
 
2818
{
 
2819
  NetWmSupportedAtoms *supported_atoms = data;
 
2820
  if (supported_atoms->atoms)
 
2821
      XFree (supported_atoms->atoms);
 
2822
  g_free (supported_atoms);
 
2823
}
 
2824
 
 
2825
/**
 
2826
 * gdk_x11_screen_supports_net_wm_hint:
 
2827
 * @screen: the relevant #GdkScreen.
 
2828
 * @property: a property atom.
 
2829
 * 
 
2830
 * This function is specific to the X11 backend of GDK, and indicates
 
2831
 * whether the window manager supports a certain hint from the
 
2832
 * Extended Window Manager Hints Specification. You can find this
 
2833
 * specification on 
 
2834
 * <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
 
2835
 *
 
2836
 * When using this function, keep in mind that the window manager
 
2837
 * can change over time; so you shouldn't use this function in
 
2838
 * a way that impacts persistent application state. A common bug
 
2839
 * is that your application can start up before the window manager
 
2840
 * does when the user logs in, and before the window manager starts
 
2841
 * gdk_x11_screen_supports_net_wm_hint() will return %FALSE for every property.
 
2842
 * You can monitor the window_manager_changed signal on #GdkScreen to detect
 
2843
 * a window manager change.
 
2844
 * 
 
2845
 * Return value: %TRUE if the window manager supports @property
 
2846
 *
 
2847
 * Since: 2.2
 
2848
 **/
 
2849
gboolean
 
2850
gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
 
2851
                                     GdkAtom    property)
 
2852
{
 
2853
  gulong i;
 
2854
  GdkScreenX11 *screen_x11;
 
2855
  NetWmSupportedAtoms *supported_atoms;
 
2856
  GdkDisplay *display;
 
2857
 
 
2858
  g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
 
2859
  
 
2860
  screen_x11 = GDK_SCREEN_X11 (screen);
 
2861
  display = screen_x11->display;
 
2862
 
 
2863
  if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
 
2864
    return FALSE;
 
2865
 
 
2866
  supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms");
 
2867
  if (!supported_atoms)
 
2868
    {
 
2869
      supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
 
2870
      g_object_set_data_full (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms, cleanup_atoms);
 
2871
    }
 
2872
 
 
2873
  fetch_net_wm_check_window (screen);
 
2874
 
 
2875
  if (screen_x11->wmspec_check_window == None)
 
2876
    return FALSE;
 
2877
  
 
2878
  if (screen_x11->need_refetch_net_supported)
 
2879
    {
 
2880
      /* WM has changed since we last got the supported list,
 
2881
       * refetch it.
 
2882
       */
 
2883
      Atom type;
 
2884
      gint format;
 
2885
      gulong bytes_after;
 
2886
 
 
2887
      screen_x11->need_refetch_net_supported = FALSE;
 
2888
      
 
2889
      if (supported_atoms->atoms)
 
2890
        XFree (supported_atoms->atoms);
 
2891
      
 
2892
      supported_atoms->atoms = NULL;
 
2893
      supported_atoms->n_atoms = 0;
 
2894
      
 
2895
      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
 
2896
                          gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"),
 
2897
                          0, G_MAXLONG, False, XA_ATOM, &type, &format, 
 
2898
                          &supported_atoms->n_atoms, &bytes_after,
 
2899
                          (guchar **)&supported_atoms->atoms);
 
2900
      
 
2901
      if (type != XA_ATOM)
 
2902
        return FALSE;
 
2903
    }
 
2904
  
 
2905
  if (supported_atoms->atoms == NULL)
 
2906
    return FALSE;
 
2907
  
 
2908
  i = 0;
 
2909
  while (i < supported_atoms->n_atoms)
 
2910
    {
 
2911
      if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
 
2912
        return TRUE;
 
2913
      
 
2914
      ++i;
 
2915
    }
 
2916
  
 
2917
  return FALSE;
 
2918
}
 
2919
 
 
2920
/**
 
2921
 * gdk_net_wm_supports:
 
2922
 * @property: a property atom.
 
2923
 * 
 
2924
 * This function is specific to the X11 backend of GDK, and indicates
 
2925
 * whether the window manager for the default screen supports a certain
 
2926
 * hint from the Extended Window Manager Hints Specification. See
 
2927
 * gdk_x11_screen_supports_net_wm_hint() for complete details.
 
2928
 * 
 
2929
 * Return value: %TRUE if the window manager supports @property
 
2930
 *
 
2931
 * Deprecated:2.24: Use gdk_x11_screen_supports_net_wm_hint() instead
 
2932
 **/
 
2933
gboolean
 
2934
gdk_net_wm_supports (GdkAtom property)
 
2935
{
 
2936
  return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
 
2937
}
 
2938
 
 
2939
 
 
2940
static void
 
2941
gdk_xsettings_notify_cb (const char       *name,
 
2942
                         XSettingsAction   action,
 
2943
                         XSettingsSetting *setting,
 
2944
                         void             *data)
 
2945
{
 
2946
  GdkEvent new_event;
 
2947
  GdkScreen *screen = data;
 
2948
  GdkScreenX11 *screen_x11 = data;
 
2949
  int i;
 
2950
 
 
2951
  if (screen_x11->xsettings_in_init)
 
2952
    return;
 
2953
  
 
2954
  new_event.type = GDK_SETTING;
 
2955
  new_event.setting.window = gdk_screen_get_root_window (screen);
 
2956
  new_event.setting.send_event = FALSE;
 
2957
  new_event.setting.name = NULL;
 
2958
 
 
2959
  for (i = 0; i < GDK_SETTINGS_N_ELEMENTS() ; i++)
 
2960
    if (strcmp (GDK_SETTINGS_X_NAME (i), name) == 0)
 
2961
      {
 
2962
        new_event.setting.name = (char*) GDK_SETTINGS_GDK_NAME (i);
 
2963
        break;
 
2964
      }
 
2965
  
 
2966
  if (!new_event.setting.name)
 
2967
    return;
 
2968
  
 
2969
  switch (action)
 
2970
    {
 
2971
    case XSETTINGS_ACTION_NEW:
 
2972
      new_event.setting.action = GDK_SETTING_ACTION_NEW;
 
2973
      break;
 
2974
    case XSETTINGS_ACTION_CHANGED:
 
2975
      new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
 
2976
      break;
 
2977
    case XSETTINGS_ACTION_DELETED:
 
2978
      new_event.setting.action = GDK_SETTING_ACTION_DELETED;
 
2979
      break;
 
2980
    }
 
2981
 
 
2982
  gdk_event_put (&new_event);
 
2983
}
 
2984
 
 
2985
static gboolean
 
2986
check_transform (const gchar *xsettings_name,
 
2987
                 GType        src_type,
 
2988
                 GType        dest_type)
 
2989
{
 
2990
  if (!g_value_type_transformable (src_type, dest_type))
 
2991
    {
 
2992
      g_warning ("Cannot transform xsetting %s of type %s to type %s\n",
 
2993
                 xsettings_name,
 
2994
                 g_type_name (src_type),
 
2995
                 g_type_name (dest_type));
 
2996
      return FALSE;
 
2997
    }
 
2998
  else
 
2999
    return TRUE;
 
3000
}
 
3001
 
 
3002
/**
 
3003
 * gdk_screen_get_setting:
 
3004
 * @screen: the #GdkScreen where the setting is located
 
3005
 * @name: the name of the setting
 
3006
 * @value: location to store the value of the setting
 
3007
 *
 
3008
 * Retrieves a desktop-wide setting such as double-click time
 
3009
 * for the #GdkScreen @screen. 
 
3010
 *
 
3011
 * FIXME needs a list of valid settings here, or a link to 
 
3012
 * more information.
 
3013
 * 
 
3014
 * Returns: %TRUE if the setting existed and a value was stored
 
3015
 *   in @value, %FALSE otherwise.
 
3016
 *
 
3017
 * Since: 2.2
 
3018
 **/
 
3019
gboolean
 
3020
gdk_screen_get_setting (GdkScreen   *screen,
 
3021
                        const gchar *name,
 
3022
                        GValue      *value)
 
3023
{
 
3024
 
 
3025
  const char *xsettings_name = NULL;
 
3026
  XSettingsResult result;
 
3027
  XSettingsSetting *setting = NULL;
 
3028
  GdkScreenX11 *screen_x11;
 
3029
  gboolean success = FALSE;
 
3030
  gint i;
 
3031
  GValue tmp_val = { 0, };
 
3032
  
 
3033
  g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
 
3034
  
 
3035
  screen_x11 = GDK_SCREEN_X11 (screen);
 
3036
 
 
3037
  for (i = 0; i < GDK_SETTINGS_N_ELEMENTS(); i++)
 
3038
    if (strcmp (GDK_SETTINGS_GDK_NAME (i), name) == 0)
 
3039
      {
 
3040
        xsettings_name = GDK_SETTINGS_X_NAME (i);
 
3041
        break;
 
3042
      }
 
3043
 
 
3044
  if (!xsettings_name)
 
3045
    goto out;
 
3046
 
 
3047
  result = xsettings_client_get_setting (screen_x11->xsettings_client, 
 
3048
                                         xsettings_name, &setting);
 
3049
  if (result != XSETTINGS_SUCCESS)
 
3050
    goto out;
 
3051
 
 
3052
  switch (setting->type)
 
3053
    {
 
3054
    case XSETTINGS_TYPE_INT:
 
3055
      if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
 
3056
        {
 
3057
          g_value_init (&tmp_val, G_TYPE_INT);
 
3058
          g_value_set_int (&tmp_val, setting->data.v_int);
 
3059
          g_value_transform (&tmp_val, value);
 
3060
 
 
3061
          success = TRUE;
 
3062
        }
 
3063
      break;
 
3064
    case XSETTINGS_TYPE_STRING:
 
3065
      if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
 
3066
        {
 
3067
          g_value_init (&tmp_val, G_TYPE_STRING);
 
3068
          g_value_set_string (&tmp_val, setting->data.v_string);
 
3069
          g_value_transform (&tmp_val, value);
 
3070
 
 
3071
          success = TRUE;
 
3072
        }
 
3073
      break;
 
3074
    case XSETTINGS_TYPE_COLOR:
 
3075
      if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
 
3076
        {
 
3077
          GdkColor color;
 
3078
          
 
3079
          g_value_init (&tmp_val, GDK_TYPE_COLOR);
 
3080
 
 
3081
          color.pixel = 0;
 
3082
          color.red = setting->data.v_color.red;
 
3083
          color.green = setting->data.v_color.green;
 
3084
          color.blue = setting->data.v_color.blue;
 
3085
          
 
3086
          g_value_set_boxed (&tmp_val, &color);
 
3087
          
 
3088
          g_value_transform (&tmp_val, value);
 
3089
          
 
3090
          success = TRUE;
 
3091
        }
 
3092
      break;
 
3093
    }
 
3094
  
 
3095
  g_value_unset (&tmp_val);
 
3096
 
 
3097
 out:
 
3098
  if (setting)
 
3099
    xsettings_setting_free (setting);
 
3100
 
 
3101
  if (success)
 
3102
    return TRUE;
 
3103
  else
 
3104
    return _gdk_x11_get_xft_setting (screen, name, value);
 
3105
}
 
3106
 
 
3107
static GdkFilterReturn 
 
3108
gdk_xsettings_client_event_filter (GdkXEvent *xevent,
 
3109
                                   GdkEvent  *event,
 
3110
                                   gpointer   data)
 
3111
{
 
3112
  GdkScreenX11 *screen = data;
 
3113
  
 
3114
  if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent))
 
3115
    return GDK_FILTER_REMOVE;
 
3116
  else
 
3117
    return GDK_FILTER_CONTINUE;
 
3118
}
 
3119
 
 
3120
static Bool
 
3121
gdk_xsettings_watch_cb (Window   window,
 
3122
                        Bool     is_start,
 
3123
                        long     mask,
 
3124
                        void    *cb_data)
 
3125
{
 
3126
  GdkWindow *gdkwin;
 
3127
  GdkScreen *screen = cb_data;
 
3128
 
 
3129
  gdkwin = gdk_window_lookup_for_display (gdk_screen_get_display (screen), window);
 
3130
 
 
3131
  if (is_start)
 
3132
    {
 
3133
      if (gdkwin)
 
3134
        g_object_ref (gdkwin);
 
3135
      else
 
3136
        {
 
3137
          gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
 
3138
          
 
3139
          /* gdk_window_foreign_new_for_display() can fail and return NULL if the
 
3140
           * window has already been destroyed.
 
3141
           */
 
3142
          if (!gdkwin)
 
3143
            return False;
 
3144
        }
 
3145
 
 
3146
      gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
 
3147
    }
 
3148
  else
 
3149
    {
 
3150
      if (!gdkwin)
 
3151
        {
 
3152
          /* gdkwin should not be NULL here, since if starting the watch succeeded
 
3153
           * we have a reference on the window. It might mean that the caller didn't
 
3154
           * remove the watch when it got a DestroyNotify event. Or maybe the
 
3155
           * caller ignored the return value when starting the watch failed.
 
3156
           */
 
3157
          g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch");
 
3158
          return False;
 
3159
        }
 
3160
      
 
3161
      gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
 
3162
      g_object_unref (gdkwin);
 
3163
    }
 
3164
 
 
3165
  return True;
 
3166
}
 
3167
 
 
3168
void
 
3169
_gdk_windowing_event_data_copy (const GdkEvent *src,
 
3170
                                GdkEvent       *dst)
 
3171
{
 
3172
}
 
3173
 
 
3174
void
 
3175
_gdk_windowing_event_data_free (GdkEvent *event)
 
3176
{
 
3177
}
 
3178
 
 
3179
#define __GDK_EVENTS_X11_C__
 
3180
#include "gdkaliasdef.c"