1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3
/* Mutter X display handler */
6
* Copyright (C) 2001 Havoc Pennington
7
* Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
8
* Copyright (C) 2003, 2004 Rob Adams
9
* Copyright (C) 2004-2006 Elijah Newren
11
* This program is free software; you can redistribute it and/or
12
* modify it under the terms of the GNU General Public License as
13
* published by the Free Software Foundation; either version 2 of the
14
* License, or (at your option) any later version.
16
* This program is distributed in the hope that it will be useful, but
17
* WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
* General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28
* \file display.c Handles operations on an X display.
30
* The display is represented as a MetaDisplay struct.
34
#include "display-private.h"
37
#include "screen-private.h"
38
#include "window-private.h"
39
#include "window-props.h"
40
#include "group-props.h"
41
#include "frame-private.h"
43
#include "keybindings-private.h"
45
#include "resizepopup.h"
47
#include "workspace-private.h"
49
#include "compositor.h"
50
#include <X11/Xatom.h>
51
#include <X11/cursorfont.h>
52
#ifdef HAVE_SOLARIS_XINERAMA
53
#include <X11/extensions/xinerama.h>
55
#ifdef HAVE_XFREE_XINERAMA
56
#include <X11/extensions/Xinerama.h>
59
#include <X11/extensions/Xrandr.h>
62
#include <X11/extensions/shape.h>
65
#include <X11/XKBlib.h>
68
#include <X11/Xcursor/Xcursor.h>
70
#include <X11/extensions/Xrender.h>
71
#include <X11/extensions/Xcomposite.h>
72
#include <X11/extensions/Xdamage.h>
73
#include <X11/extensions/Xfixes.h>
76
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
77
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
78
g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
79
g == META_GRAB_OP_KEYBOARD_TABBING_GROUP || \
80
g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL || \
81
g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK || \
82
g == META_GRAB_OP_KEYBOARD_ESCAPING_GROUP)
85
* \defgroup pings Pings
87
* Sometimes we want to see whether a window is responding,
88
* so we send it a "ping" message and see whether it sends us back a "pong"
89
* message within a reasonable time. Here we have a system which lets us
90
* nominate one function to be called if we get the pong in time and another
91
* function if we don't. The system is rather more complicated than it needs
92
* to be, since we only ever use it to destroy windows which are asked to
93
* close themselves and don't do so within a reasonable amount of time, and
94
* therefore we always use the same callbacks. It's possible that we might
95
* use it for other things in future, or on the other hand we might decide
96
* that we're never going to do so and simplify it a bit.
100
* Describes a ping on a window. When we send a ping to a window, we build
101
* one of these structs, and it eventually gets passed to the timeout function
102
* or to the function which handles the response from the window. If the window
103
* does or doesn't respond to the ping, we use this information to deal with
104
* these facts; we have a handler function for each.
110
MetaDisplay *display;
113
MetaWindowPingFunc ping_reply_func;
114
MetaWindowPingFunc ping_timeout_func;
116
guint ping_timeout_id;
121
MetaDisplay *display;
125
G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT);
134
static guint display_signals [LAST_SIGNAL] = { 0 };
137
* The display we're managing. This is a singleton object. (Historically,
138
* this was a list of displays, but there was never any way to add more
139
* than one element to it.) The goofy name is because we don't want it
140
* to shadow the parameter in its object methods.
142
static MetaDisplay *the_display = NULL;
144
static void meta_spew_event (MetaDisplay *display,
147
static gboolean event_callback (XEvent *event,
149
static Window event_get_modified_window (MetaDisplay *display,
151
static guint32 event_get_time (MetaDisplay *display,
153
static void process_request_frame_extents (MetaDisplay *display,
155
static void process_pong_message (MetaDisplay *display,
157
static void process_selection_request (MetaDisplay *display,
159
static void process_selection_clear (MetaDisplay *display,
162
static void update_window_grab_modifiers (MetaDisplay *display);
164
static void prefs_changed_callback (MetaPreference pref,
167
static void sanity_check_timestamps (MetaDisplay *display,
168
guint32 known_good_timestamp);
170
MetaGroup* get_focussed_group (MetaDisplay *display);
173
meta_display_class_init (MetaDisplayClass *klass)
175
display_signals[OVERLAY_KEY] =
176
g_signal_new ("overlay-key",
177
G_TYPE_FROM_CLASS (klass),
181
g_cclosure_marshal_VOID__VOID,
186
* Destructor for MetaPingData structs. Will destroy the
187
* event source for the struct as well.
192
ping_data_free (MetaPingData *ping_data)
194
/* Remove the timeout */
195
if (ping_data->ping_timeout_id != 0)
196
g_source_remove (ping_data->ping_timeout_id);
202
* Frees every pending ping structure for the given X window on the
203
* given display. This means that we also destroy the timeouts.
205
* \param display The display the window appears on
206
* \param xwindow The X ID of the window whose pings we should remove
212
remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
217
/* could obviously be more efficient, don't care */
219
/* build list to be removed */
221
for (tmp = display->pending_pings; tmp; tmp = tmp->next)
223
MetaPingData *ping_data = tmp->data;
225
if (ping_data->xwindow == xwindow)
226
dead = g_slist_prepend (dead, ping_data);
229
/* remove what we found */
230
for (tmp = dead; tmp; tmp = tmp->next)
232
MetaPingData *ping_data = tmp->data;
234
display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
235
ping_data_free (ping_data);
242
#ifdef HAVE_STARTUP_NOTIFICATION
244
sn_error_trap_push (SnDisplay *sn_display,
247
MetaDisplay *display;
248
display = meta_display_for_x_display (xdisplay);
250
meta_error_trap_push (display);
254
sn_error_trap_pop (SnDisplay *sn_display,
257
MetaDisplay *display;
258
display = meta_display_for_x_display (xdisplay);
260
meta_error_trap_pop (display, FALSE);
265
enable_compositor (MetaDisplay *display,
266
gboolean composite_windows)
270
if (!META_DISPLAY_HAS_COMPOSITE (display) ||
271
!META_DISPLAY_HAS_DAMAGE (display) ||
272
!META_DISPLAY_HAS_XFIXES (display) ||
273
!META_DISPLAY_HAS_RENDER (display))
275
meta_warning (_("Missing %s extension required for compositing"),
276
!META_DISPLAY_HAS_COMPOSITE (display) ? "composite" :
277
!META_DISPLAY_HAS_DAMAGE (display) ? "damage" :
278
!META_DISPLAY_HAS_XFIXES (display) ? "xfixes" : "render");
282
if (!display->compositor)
283
display->compositor = meta_compositor_new (display);
285
if (!display->compositor)
288
for (list = display->screens; list != NULL; list = list->next)
290
MetaScreen *screen = list->data;
292
meta_compositor_manage_screen (screen->display->compositor,
295
if (composite_windows)
296
meta_screen_composite_all_windows (screen);
301
disable_compositor (MetaDisplay *display)
305
if (!display->compositor)
308
for (list = display->screens; list != NULL; list = list->next)
310
MetaScreen *screen = list->data;
312
meta_compositor_unmanage_screen (screen->display->compositor,
316
meta_compositor_destroy (display->compositor);
317
display->compositor = NULL;
321
meta_display_init (MetaDisplay *disp)
323
/* Some stuff could go in here that's currently in _open,
324
* but it doesn't really matter. */
328
* Opens a new display, sets it up, initialises all the X extensions
329
* we will need, and adds it to the list of displays.
331
* \return True if the display was opened successfully, and False
332
* otherwise-- that is, if the display doesn't exist or it already
333
* has a window manager.
338
meta_display_open (void)
346
/* A list of all atom names, so that we can intern them in one go. */
347
char *atom_names[] = {
349
#include "atomnames.h"
352
Atom atoms[G_N_ELEMENTS(atom_names)];
354
meta_verbose ("Opening display '%s'\n", XDisplayName (NULL));
356
xdisplay = meta_ui_get_display ();
358
if (xdisplay == NULL)
360
meta_warning (_("Failed to open X Window System display '%s'\n"),
361
XDisplayName (NULL));
365
if (meta_is_syncing ())
366
XSynchronize (xdisplay, True);
368
g_assert (the_display == NULL);
369
the_display = g_object_new (META_TYPE_DISPLAY, NULL);
371
the_display->closing = 0;
373
/* here we use XDisplayName which is what the user
374
* probably put in, vs. DisplayString(display) which is
375
* canonicalized by XOpenDisplay()
377
the_display->name = g_strdup (XDisplayName (NULL));
378
the_display->xdisplay = xdisplay;
379
the_display->error_trap_synced_at_last_pop = TRUE;
380
the_display->error_traps = 0;
381
the_display->error_trap_handler = NULL;
382
the_display->server_grab_count = 0;
383
the_display->display_opening = TRUE;
385
the_display->pending_pings = NULL;
386
the_display->autoraise_timeout_id = 0;
387
the_display->autoraise_window = NULL;
388
the_display->focus_window = NULL;
389
the_display->expected_focus_window = NULL;
390
the_display->grab_old_window_stacking = NULL;
392
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
393
the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
394
terminal has the focus */
397
the_display->grab_sync_request_alarm = None;
400
/* FIXME copy the checks from GDK probably */
401
the_display->static_gravity_works = g_getenv ("MUTTER_USE_STATIC_GRAVITY") != NULL;
403
meta_bell_init (the_display);
405
meta_display_init_keys (the_display);
407
update_window_grab_modifiers (the_display);
409
meta_prefs_add_listener (prefs_changed_callback, the_display);
411
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
412
XInternAtoms (the_display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
416
#define item(x) the_display->atom_##x = atoms[i++];
417
#include "atomnames.h"
421
the_display->prop_hooks = NULL;
422
meta_display_init_window_prop_hooks (the_display);
423
the_display->group_prop_hooks = NULL;
424
meta_display_init_group_prop_hooks (the_display);
426
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
427
* created in screen_new
429
the_display->leader_window = None;
430
the_display->timestamp_pinging_window = None;
432
the_display->xinerama_cache_invalidated = TRUE;
434
the_display->groups_by_leader = NULL;
436
the_display->window_with_menu = NULL;
437
the_display->window_menu = NULL;
439
the_display->screens = NULL;
440
the_display->active_screen = NULL;
442
#ifdef HAVE_STARTUP_NOTIFICATION
443
the_display->sn_display = sn_display_new (the_display->xdisplay,
448
the_display->events = NULL;
451
meta_ui_add_event_func (the_display->xdisplay,
455
the_display->window_ids = g_hash_table_new (meta_unsigned_long_hash,
456
meta_unsigned_long_equal);
459
while (i < N_IGNORED_SERIALS)
461
the_display->ignored_serials[i] = 0;
464
the_display->ungrab_should_not_cause_focus_window = None;
466
the_display->current_time = CurrentTime;
467
the_display->sentinel_counter = 0;
469
the_display->grab_resize_timeout_id = 0;
470
the_display->grab_have_keyboard = FALSE;
473
the_display->last_bell_time = 0;
476
the_display->grab_op = META_GRAB_OP_NONE;
477
the_display->grab_window = NULL;
478
the_display->grab_screen = NULL;
479
the_display->grab_resize_popup = NULL;
481
the_display->grab_edge_resistance_data = NULL;
487
the_display->have_xsync = FALSE;
489
the_display->xsync_error_base = 0;
490
the_display->xsync_event_base = 0;
492
/* I don't think we really have to fill these in */
493
major = SYNC_MAJOR_VERSION;
494
minor = SYNC_MINOR_VERSION;
496
if (!XSyncQueryExtension (the_display->xdisplay,
497
&the_display->xsync_event_base,
498
&the_display->xsync_error_base) ||
499
!XSyncInitialize (the_display->xdisplay,
502
the_display->xsync_error_base = 0;
503
the_display->xsync_event_base = 0;
506
the_display->have_xsync = TRUE;
508
meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n",
510
the_display->xsync_error_base,
511
the_display->xsync_event_base);
513
#else /* HAVE_XSYNC */
514
meta_verbose ("Not compiled with Xsync support\n");
515
#endif /* !HAVE_XSYNC */
520
the_display->have_shape = FALSE;
522
the_display->shape_error_base = 0;
523
the_display->shape_event_base = 0;
525
if (!XShapeQueryExtension (the_display->xdisplay,
526
&the_display->shape_event_base,
527
&the_display->shape_error_base))
529
the_display->shape_error_base = 0;
530
the_display->shape_event_base = 0;
533
the_display->have_shape = TRUE;
535
meta_verbose ("Attempted to init Shape, found error base %d event base %d\n",
536
the_display->shape_error_base,
537
the_display->shape_event_base);
539
#else /* HAVE_SHAPE */
540
meta_verbose ("Not compiled with Shape support\n");
541
#endif /* !HAVE_SHAPE */
544
the_display->have_render = FALSE;
546
the_display->render_error_base = 0;
547
the_display->render_event_base = 0;
549
if (!XRenderQueryExtension (the_display->xdisplay,
550
&the_display->render_event_base,
551
&the_display->render_error_base))
553
the_display->render_error_base = 0;
554
the_display->render_event_base = 0;
557
the_display->have_render = TRUE;
559
meta_verbose ("Attempted to init Render, found error base %d event base %d\n",
560
the_display->render_error_base,
561
the_display->render_event_base);
565
the_display->have_composite = FALSE;
567
the_display->composite_error_base = 0;
568
the_display->composite_event_base = 0;
570
if (!XCompositeQueryExtension (the_display->xdisplay,
571
&the_display->composite_event_base,
572
&the_display->composite_error_base))
574
the_display->composite_error_base = 0;
575
the_display->composite_event_base = 0;
579
the_display->composite_major_version = 0;
580
the_display->composite_minor_version = 0;
581
if (XCompositeQueryVersion (the_display->xdisplay,
582
&the_display->composite_major_version,
583
&the_display->composite_minor_version))
585
the_display->have_composite = TRUE;
589
the_display->composite_major_version = 0;
590
the_display->composite_minor_version = 0;
594
meta_verbose ("Attempted to init Composite, found error base %d event base %d "
596
the_display->composite_error_base,
597
the_display->composite_event_base,
598
the_display->composite_major_version,
599
the_display->composite_minor_version);
601
the_display->have_damage = FALSE;
603
the_display->damage_error_base = 0;
604
the_display->damage_event_base = 0;
606
if (!XDamageQueryExtension (the_display->xdisplay,
607
&the_display->damage_event_base,
608
&the_display->damage_error_base))
610
the_display->damage_error_base = 0;
611
the_display->damage_event_base = 0;
614
the_display->have_damage = TRUE;
616
meta_verbose ("Attempted to init Damage, found error base %d event base %d\n",
617
the_display->damage_error_base,
618
the_display->damage_event_base);
620
the_display->have_xfixes = FALSE;
622
the_display->xfixes_error_base = 0;
623
the_display->xfixes_event_base = 0;
625
if (!XFixesQueryExtension (the_display->xdisplay,
626
&the_display->xfixes_event_base,
627
&the_display->xfixes_error_base))
629
the_display->xfixes_error_base = 0;
630
the_display->xfixes_event_base = 0;
633
the_display->have_xfixes = TRUE;
635
meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n",
636
the_display->xfixes_error_base,
637
the_display->xfixes_event_base);
642
XcursorSetTheme (the_display->xdisplay, meta_prefs_get_cursor_theme ());
643
XcursorSetDefaultSize (the_display->xdisplay, meta_prefs_get_cursor_size ());
645
#else /* HAVE_XCURSOR */
646
meta_verbose ("Not compiled with Xcursor support\n");
647
#endif /* !HAVE_XCURSOR */
649
/* Create the leader window here. Set its properties and
650
* use the timestamp from one of the PropertyNotify events
657
/* We only care about the PropertyChangeMask in the next 30 or so lines of
658
* code. Note that gdk will at some point unset the PropertyChangeMask for
659
* this window, so we can't rely on it still being set later. See bug
660
* 354213 for details.
662
the_display->leader_window =
663
meta_create_offscreen_window (the_display->xdisplay,
664
DefaultRootWindow (the_display->xdisplay),
667
meta_prop_set_utf8_string_hint (the_display,
668
the_display->leader_window,
669
the_display->atom__NET_WM_NAME,
672
meta_prop_set_utf8_string_hint (the_display,
673
the_display->leader_window,
674
the_display->atom__MUTTER_VERSION,
677
data[0] = the_display->leader_window;
678
XChangeProperty (the_display->xdisplay,
679
the_display->leader_window,
680
the_display->atom__NET_SUPPORTING_WM_CHECK,
682
32, PropModeReplace, (guchar*) data, 1);
684
XWindowEvent (the_display->xdisplay,
685
the_display->leader_window,
689
timestamp = event.xproperty.time;
691
/* Make it painfully clear that we can't rely on PropertyNotify events on
692
* this window, as per bug 354213.
694
XSelectInput(the_display->xdisplay,
695
the_display->leader_window,
699
/* Make a little window used only for pinging the server for timestamps; note
700
* that meta_create_offscreen_window already selects for PropertyChangeMask.
702
the_display->timestamp_pinging_window =
703
meta_create_offscreen_window (the_display->xdisplay,
704
DefaultRootWindow (the_display->xdisplay),
707
the_display->last_focus_time = timestamp;
708
the_display->last_user_time = timestamp;
709
the_display->compositor = NULL;
714
while (i < ScreenCount (xdisplay))
718
screen = meta_screen_new (the_display, i, timestamp);
721
screens = g_slist_prepend (screens, screen);
725
the_display->screens = screens;
729
/* This would typically happen because all the screens already
730
* have window managers.
732
meta_display_close (the_display, timestamp);
736
/* We don't composite the windows here because they will be composited
737
faster with the call to meta_screen_manage_all_windows further down
739
if (1) /* meta_prefs_get_compositing_manager ()) FIXME */
740
enable_compositor (the_display, FALSE);
742
meta_display_grab (the_display);
744
/* Now manage all existing windows */
745
tmp = the_display->screens;
748
MetaScreen *screen = tmp->data;
750
meta_screen_manage_all_windows (screen);
759
/* kinda bogus because GetInputFocus has no possible errors */
760
meta_error_trap_push (the_display);
762
/* FIXME: This is totally broken; see comment 9 of bug 88194 about this */
764
ret_to = RevertToPointerRoot;
765
XGetInputFocus (the_display->xdisplay, &focus, &ret_to);
767
/* Force a new FocusIn (does this work?) */
769
/* Use the same timestamp that was passed to meta_screen_new(),
770
* as it is the most recent timestamp.
772
if (focus == None || focus == PointerRoot)
773
/* Just focus the no_focus_window on the first screen */
774
meta_display_focus_the_no_focus_window (the_display,
775
the_display->screens->data,
780
window = meta_display_lookup_x_window (the_display, focus);
782
meta_display_set_input_focus_window (the_display, window, FALSE, timestamp);
784
/* Just focus the no_focus_window on the first screen */
785
meta_display_focus_the_no_focus_window (the_display,
786
the_display->screens->data,
790
meta_error_trap_pop (the_display, FALSE);
793
meta_display_ungrab (the_display);
795
/* Done opening new display */
796
the_display->display_opening = FALSE;
802
ptrcmp (gconstpointer a, gconstpointer b)
813
* meta_display_list_windows:
814
* @display: a #MetaDisplay
815
* @flags: options for listing
817
* Lists windows for the display, the @flags parameter for
818
* now determines whether override-redirect windows will be
821
* Return value: (transfer container): the list of windows.
824
meta_display_list_windows (MetaDisplay *display,
825
MetaListWindowsFlags flags)
835
g_hash_table_iter_init (&iter, display->window_ids);
836
while (g_hash_table_iter_next (&iter, &key, &value))
838
MetaWindow *window = value;
840
if (!window->override_redirect ||
841
(flags & META_LIST_INCLUDE_OVERRIDE_REDIRECT) != 0)
842
winlist = g_slist_prepend (winlist, window);
845
/* Uniquify the list, since both frame windows and plain
846
* windows are in the hash
848
winlist = g_slist_sort (winlist, ptrcmp);
859
next->data == tmp->data)
861
/* Delete tmp from list */
869
g_slist_free_1 (tmp);
871
/* leave prev unchanged */
885
meta_display_close (MetaDisplay *display,
890
g_assert (display != NULL);
892
if (display->closing != 0)
894
/* The display's already been closed. */
898
if (display->error_traps > 0)
899
meta_bug ("Display closed with error traps pending\n");
901
display->closing += 1;
903
meta_prefs_remove_listener (prefs_changed_callback, display);
905
meta_display_remove_autoraise_callback (display);
907
if (display->grab_old_window_stacking)
908
g_list_free (display->grab_old_window_stacking);
910
/* Stop caring about events */
911
meta_ui_remove_event_func (display->xdisplay,
915
/* Free all screens */
916
tmp = display->screens;
919
MetaScreen *screen = tmp->data;
920
meta_screen_free (screen, timestamp);
924
g_slist_free (display->screens);
925
display->screens = NULL;
927
#ifdef HAVE_STARTUP_NOTIFICATION
928
if (display->sn_display)
930
sn_display_unref (display->sn_display);
931
display->sn_display = NULL;
935
/* Must be after all calls to meta_window_unmanage() since they
938
g_hash_table_destroy (display->window_ids);
940
if (display->leader_window != None)
941
XDestroyWindow (display->xdisplay, display->leader_window);
943
XFlush (display->xdisplay);
945
meta_display_free_window_prop_hooks (display);
946
meta_display_free_group_prop_hooks (display);
948
g_free (display->name);
950
meta_display_shutdown_keys (display);
952
if (display->compositor)
953
meta_compositor_destroy (display->compositor);
955
g_object_unref (display);
957
meta_quit (META_EXIT_SUCCESS);
961
* meta_display_screen_for_root:
962
* @display: a #MetaDisplay
964
* Return the #MetaScreen corresponding to a specified X root window ID.
966
* Return Value: (transfer none): the screen for the specified root window ID, or %NULL
969
meta_display_screen_for_root (MetaDisplay *display,
974
tmp = display->screens;
977
MetaScreen *screen = tmp->data;
979
if (xroot == screen->xroot)
989
meta_display_screen_for_xwindow (MetaDisplay *display,
992
XWindowAttributes attr;
995
meta_error_trap_push (display);
997
result = XGetWindowAttributes (display->xdisplay, xwindow, &attr);
998
meta_error_trap_pop (display, TRUE);
1000
/* Note, XGetWindowAttributes is on all kinds of crack
1001
* and returns 1 on success 0 on failure, rather than Success
1004
if (result == 0 || attr.screen == NULL)
1007
return meta_display_screen_for_x_screen (display, attr.screen);
1011
meta_display_screen_for_x_screen (MetaDisplay *display,
1016
tmp = display->screens;
1019
MetaScreen *screen = tmp->data;
1021
if (xscreen == screen->xscreen)
1030
/* Grab/ungrab routines taken from fvwm */
1032
meta_display_grab (MetaDisplay *display)
1034
if (display->server_grab_count == 0)
1036
XGrabServer (display->xdisplay);
1038
display->server_grab_count += 1;
1039
meta_verbose ("Grabbing display, grab count now %d\n",
1040
display->server_grab_count);
1044
meta_display_ungrab (MetaDisplay *display)
1046
if (display->server_grab_count == 0)
1047
meta_bug ("Ungrabbed non-grabbed server\n");
1049
display->server_grab_count -= 1;
1050
if (display->server_grab_count == 0)
1052
/* FIXME we want to purge all pending "queued" stuff
1053
* at this point, such as window hide/show
1055
XUngrabServer (display->xdisplay);
1056
XFlush (display->xdisplay);
1059
meta_verbose ("Ungrabbing display, grab count now %d\n",
1060
display->server_grab_count);
1064
* Returns the singleton MetaDisplay if "xdisplay" matches the X display it's
1065
* managing; otherwise gives a warning and returns NULL. When we were claiming
1066
* to be able to manage multiple displays, this was supposed to find the
1067
* display out of the list which matched that display. Now it's merely an
1068
* extra sanity check.
1070
* \param xdisplay An X display
1071
* \return The singleton X display, or NULL if "xdisplay" isn't the one
1075
meta_display_for_x_display (Display *xdisplay)
1077
if (the_display->xdisplay == xdisplay)
1080
meta_warning ("Could not find display for X display %p, probably going to crash\n",
1087
* Accessor for the singleton MetaDisplay.
1089
* \return The only MetaDisplay there is. This can be NULL, but only
1093
meta_get_display (void)
1098
#ifdef WITH_VERBOSE_MODE
1099
static gboolean dump_events = TRUE;
1103
grab_op_is_mouse_only (MetaGrabOp op)
1107
case META_GRAB_OP_MOVING:
1108
case META_GRAB_OP_RESIZING_SE:
1109
case META_GRAB_OP_RESIZING_S:
1110
case META_GRAB_OP_RESIZING_SW:
1111
case META_GRAB_OP_RESIZING_N:
1112
case META_GRAB_OP_RESIZING_NE:
1113
case META_GRAB_OP_RESIZING_NW:
1114
case META_GRAB_OP_RESIZING_W:
1115
case META_GRAB_OP_RESIZING_E:
1124
grab_op_is_mouse (MetaGrabOp op)
1128
case META_GRAB_OP_MOVING:
1129
case META_GRAB_OP_RESIZING_SE:
1130
case META_GRAB_OP_RESIZING_S:
1131
case META_GRAB_OP_RESIZING_SW:
1132
case META_GRAB_OP_RESIZING_N:
1133
case META_GRAB_OP_RESIZING_NE:
1134
case META_GRAB_OP_RESIZING_NW:
1135
case META_GRAB_OP_RESIZING_W:
1136
case META_GRAB_OP_RESIZING_E:
1137
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
1138
case META_GRAB_OP_KEYBOARD_RESIZING_S:
1139
case META_GRAB_OP_KEYBOARD_RESIZING_N:
1140
case META_GRAB_OP_KEYBOARD_RESIZING_W:
1141
case META_GRAB_OP_KEYBOARD_RESIZING_E:
1142
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
1143
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
1144
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
1145
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
1146
case META_GRAB_OP_KEYBOARD_MOVING:
1155
grab_op_is_keyboard (MetaGrabOp op)
1159
case META_GRAB_OP_KEYBOARD_MOVING:
1160
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
1161
case META_GRAB_OP_KEYBOARD_RESIZING_S:
1162
case META_GRAB_OP_KEYBOARD_RESIZING_N:
1163
case META_GRAB_OP_KEYBOARD_RESIZING_W:
1164
case META_GRAB_OP_KEYBOARD_RESIZING_E:
1165
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
1166
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
1167
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
1168
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
1169
case META_GRAB_OP_KEYBOARD_TABBING_NORMAL:
1170
case META_GRAB_OP_KEYBOARD_TABBING_DOCK:
1171
case META_GRAB_OP_KEYBOARD_TABBING_GROUP:
1172
case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL:
1173
case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK:
1174
case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP:
1175
case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING:
1184
meta_grab_op_is_resizing (MetaGrabOp op)
1188
case META_GRAB_OP_RESIZING_SE:
1189
case META_GRAB_OP_RESIZING_S:
1190
case META_GRAB_OP_RESIZING_SW:
1191
case META_GRAB_OP_RESIZING_N:
1192
case META_GRAB_OP_RESIZING_NE:
1193
case META_GRAB_OP_RESIZING_NW:
1194
case META_GRAB_OP_RESIZING_W:
1195
case META_GRAB_OP_RESIZING_E:
1196
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
1197
case META_GRAB_OP_KEYBOARD_RESIZING_S:
1198
case META_GRAB_OP_KEYBOARD_RESIZING_N:
1199
case META_GRAB_OP_KEYBOARD_RESIZING_W:
1200
case META_GRAB_OP_KEYBOARD_RESIZING_E:
1201
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
1202
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
1203
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
1204
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
1213
meta_grab_op_is_moving (MetaGrabOp op)
1217
case META_GRAB_OP_MOVING:
1218
case META_GRAB_OP_KEYBOARD_MOVING:
1226
/* Get time of current event, or CurrentTime if none. */
1228
meta_display_get_current_time (MetaDisplay *display)
1230
return display->current_time;
1233
/* Get a timestamp, even if it means a roundtrip */
1235
meta_display_get_current_time_roundtrip (MetaDisplay *display)
1239
timestamp = meta_display_get_current_time (display);
1240
if (timestamp == CurrentTime)
1242
XEvent property_event;
1244
/* Using the property XA_PRIMARY because it's safe; nothing
1245
* would use it as a property. The type doesn't matter.
1247
XChangeProperty (display->xdisplay,
1248
display->timestamp_pinging_window,
1249
XA_PRIMARY, XA_STRING, 8,
1250
PropModeAppend, NULL, 0);
1251
XWindowEvent (display->xdisplay,
1252
display->timestamp_pinging_window,
1255
timestamp = property_event.xproperty.time;
1258
sanity_check_timestamps (display, timestamp);
1264
add_ignored_serial (MetaDisplay *display,
1265
unsigned long serial)
1269
/* don't add the same serial more than once */
1270
if (display->ignored_serials[N_IGNORED_SERIALS-1] == serial)
1273
/* shift serials to the left */
1275
while (i < (N_IGNORED_SERIALS - 1))
1277
display->ignored_serials[i] = display->ignored_serials[i+1];
1280
/* put new one on the end */
1281
display->ignored_serials[i] = serial;
1285
serial_is_ignored (MetaDisplay *display,
1286
unsigned long serial)
1291
while (i < N_IGNORED_SERIALS)
1293
if (display->ignored_serials[i] == serial)
1301
reset_ignores (MetaDisplay *display)
1306
while (i < N_IGNORED_SERIALS)
1308
display->ignored_serials[i] = 0;
1312
display->ungrab_should_not_cause_focus_window = None;
1316
window_raise_with_delay_callback (void *data)
1319
MetaAutoRaiseData *auto_raise;
1323
meta_topic (META_DEBUG_FOCUS,
1324
"In autoraise callback for window 0x%lx\n",
1325
auto_raise->xwindow);
1327
auto_raise->display->autoraise_timeout_id = 0;
1328
auto_raise->display->autoraise_window = NULL;
1330
window = meta_display_lookup_x_window (auto_raise->display,
1331
auto_raise->xwindow);
1336
/* If we aren't already on top, check whether the pointer is inside
1337
* the window and raise the window if so.
1339
if (meta_stack_get_top (window->screen->stack) != window)
1341
int x, y, root_x, root_y;
1344
gboolean same_screen;
1345
gboolean point_in_window;
1347
meta_error_trap_push (window->display);
1348
same_screen = XQueryPointer (window->display->xdisplay,
1351
&root_x, &root_y, &x, &y, &mask);
1352
meta_error_trap_pop (window->display, TRUE);
1355
(window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) ||
1356
(window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect));
1357
if (same_screen && point_in_window)
1358
meta_window_raise (window);
1360
meta_topic (META_DEBUG_FOCUS,
1361
"Pointer not inside window, not raising %s\n",
1369
meta_display_queue_autoraise_callback (MetaDisplay *display,
1372
MetaAutoRaiseData *auto_raise_data;
1374
meta_topic (META_DEBUG_FOCUS,
1375
"Queuing an autoraise timeout for %s with delay %d\n",
1377
meta_prefs_get_auto_raise_delay ());
1379
auto_raise_data = g_new (MetaAutoRaiseData, 1);
1380
auto_raise_data->display = window->display;
1381
auto_raise_data->xwindow = window->xwindow;
1383
if (display->autoraise_timeout_id != 0)
1384
g_source_remove (display->autoraise_timeout_id);
1386
display->autoraise_timeout_id =
1387
g_timeout_add_full (G_PRIORITY_DEFAULT,
1388
meta_prefs_get_auto_raise_delay (),
1389
window_raise_with_delay_callback,
1392
display->autoraise_window = window;
1397
handle_net_restack_window (MetaDisplay* display,
1402
window = meta_display_lookup_x_window (display,
1403
event->xclient.window);
1407
/* FIXME: The EWMH includes a sibling for the restack request, but we
1408
* (stupidly) don't currently support these types of raises.
1410
* Also, unconditionally following these is REALLY stupid--we should
1411
* combine this code with the stuff in
1412
* meta_window_configure_request() which is smart about whether to
1413
* follow the request or do something else (though not smart enough
1414
* and is also too stupid to handle the sibling stuff).
1416
switch (event->xclient.data.l[2])
1419
meta_window_raise (window);
1422
meta_window_lower (window);
1434
* This is the most important function in the whole program. It is the heart,
1435
* it is the nexus, it is the Grand Central Station of Mutter's world.
1436
* When we create a MetaDisplay, we ask GDK to pass *all* events for *all*
1437
* windows to this function. So every time anything happens that we might
1438
* want to know about, this function gets called. You see why it gets a bit
1439
* busy around here. Most of this function is a ginormous switch statement
1440
* dealing with all the kinds of events that might turn up.
1442
* \param event The event that just happened
1443
* \param data The MetaDisplay that events are coming from, cast to a gpointer
1444
* so that it can be sent to a callback
1449
event_callback (XEvent *event,
1453
MetaWindow *property_for_window;
1454
MetaDisplay *display;
1456
gboolean frame_was_receiver;
1457
gboolean filter_out_event;
1461
#ifdef WITH_VERBOSE_MODE
1463
meta_spew_event (display, event);
1466
#ifdef HAVE_STARTUP_NOTIFICATION
1467
sn_display_process_event (display->sn_display, event);
1470
filter_out_event = FALSE;
1471
display->current_time = event_get_time (display, event);
1472
display->xinerama_cache_invalidated = TRUE;
1474
modified = event_get_modified_window (display, event);
1476
if (event->type == UnmapNotify)
1478
if (meta_ui_window_should_not_cause_focus (display->xdisplay,
1481
add_ignored_serial (display, event->xany.serial);
1482
meta_topic (META_DEBUG_FOCUS,
1483
"Adding EnterNotify serial %lu to ignored focus serials\n",
1484
event->xany.serial);
1487
else if (event->type == LeaveNotify &&
1488
event->xcrossing.mode == NotifyUngrab &&
1489
modified == display->ungrab_should_not_cause_focus_window)
1491
add_ignored_serial (display, event->xany.serial);
1492
meta_topic (META_DEBUG_FOCUS,
1493
"Adding LeaveNotify serial %lu to ignored focus serials\n",
1494
event->xany.serial);
1497
if (modified != None)
1498
window = meta_display_lookup_x_window (display, modified);
1502
/* We only want to respond to _NET_WM_USER_TIME property notify
1503
* events on _NET_WM_USER_TIME_WINDOW windows; in particular,
1504
* responding to UnmapNotify events is kind of bad.
1506
property_for_window = NULL;
1507
if (window && modified == window->user_time_window)
1509
property_for_window = window;
1514
frame_was_receiver = FALSE;
1517
modified == window->frame->xwindow)
1519
/* Note that if the frame and the client both have an
1520
* XGrabButton (as is normal with our setup), the event
1521
* goes to the frame.
1523
frame_was_receiver = TRUE;
1524
meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n",
1529
if (META_DISPLAY_HAS_XSYNC (display) &&
1530
event->type == (display->xsync_event_base + XSyncAlarmNotify) &&
1531
((XSyncAlarmNotifyEvent*)event)->alarm == display->grab_sync_request_alarm)
1533
filter_out_event = TRUE; /* GTK doesn't want to see this really */
1535
if (display->grab_op != META_GRAB_OP_NONE &&
1536
display->grab_window != NULL &&
1537
grab_op_is_mouse (display->grab_op))
1538
meta_window_handle_mouse_grab_op_event (display->grab_window, event);
1540
#endif /* HAVE_XSYNC */
1543
if (META_DISPLAY_HAS_SHAPE (display) &&
1544
event->type == (display->shape_event_base + ShapeNotify))
1546
filter_out_event = TRUE; /* GTK doesn't want to see this really */
1548
if (window && !frame_was_receiver)
1550
XShapeEvent *sev = (XShapeEvent*) event;
1552
if (sev->kind == ShapeBounding)
1554
if (sev->shaped && !window->has_shape)
1556
window->has_shape = TRUE;
1557
meta_topic (META_DEBUG_SHAPES,
1558
"Window %s now has a shape\n",
1561
else if (!sev->shaped && window->has_shape)
1563
window->has_shape = FALSE;
1564
meta_topic (META_DEBUG_SHAPES,
1565
"Window %s no longer has a shape\n",
1570
meta_topic (META_DEBUG_SHAPES,
1571
"Window %s shape changed\n",
1577
window->frame->need_reapply_frame_shape = TRUE;
1578
meta_warning("from event callback\n");
1579
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
1585
meta_topic (META_DEBUG_SHAPES,
1586
"ShapeNotify not on a client window (window %s frame_was_receiver = %d)\n",
1587
window ? window->desc : "(none)",
1588
frame_was_receiver);
1591
#endif /* HAVE_SHAPE */
1593
if (window && ((event->type == KeyPress) || (event->type == ButtonPress)))
1595
if (CurrentTime == display->current_time)
1597
/* We can't use missing (i.e. invalid) timestamps to set user time,
1598
* nor do we want to use them to sanity check other timestamps.
1599
* See bug 313490 for more details.
1601
meta_warning ("Event has no timestamp! You may be using a broken "
1602
"program such as xse. Please ask the authors of that "
1603
"program to fix it.\n");
1607
meta_window_set_user_time (window, display->current_time);
1608
sanity_check_timestamps (display, display->current_time);
1612
switch (event->type)
1616
meta_display_process_key_event (display, window, event);
1619
if (event->xbutton.button == 4 || event->xbutton.button == 5)
1621
if (display->compositor && window)
1623
return meta_compositor_process_event (display->compositor,
1631
grab_op_is_mouse (display->grab_op) &&
1632
display->grab_button != (int) event->xbutton.button &&
1633
display->grab_window == window) ||
1634
grab_op_is_keyboard (display->grab_op))
1636
meta_topic (META_DEBUG_WINDOW_OPS,
1637
"Ending grab op %u on window %s due to button press\n",
1639
(display->grab_window ?
1640
display->grab_window->desc :
1642
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
1645
meta_topic (META_DEBUG_WINDOW_OPS,
1646
"Syncing to old stack positions.\n");
1648
meta_display_screen_for_root (display, event->xany.window);
1651
meta_stack_set_positions (screen->stack,
1652
display->grab_old_window_stacking);
1654
meta_display_end_grab_op (display,
1655
event->xbutton.time);
1657
else if (window && display->grab_op == META_GRAB_OP_NONE)
1659
gboolean begin_move = FALSE;
1660
unsigned int grab_mask;
1661
gboolean unmodified;
1663
grab_mask = display->window_grab_modifiers;
1664
if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
1665
grab_mask |= ControlMask;
1667
/* Two possible sources of an unmodified event; one is a
1668
* client that's letting button presses pass through to the
1669
* frame, the other is our focus_window_grab on unmodified
1670
* button 1. So for all such events we focus the window.
1672
unmodified = (event->xbutton.state & grab_mask) == 0;
1675
event->xbutton.button == 1)
1677
/* don't focus if frame received, will be lowered in
1678
* frames.c or special-cased if the click was on a
1679
* minimize/close button.
1681
if (!frame_was_receiver)
1683
if (meta_prefs_get_raise_on_click ())
1684
meta_window_raise (window);
1686
meta_topic (META_DEBUG_FOCUS,
1687
"Not raising window on click due to don't-raise-on-click option\n");
1689
/* Don't focus panels--they must explicitly request focus.
1692
if (window->type != META_WINDOW_DOCK)
1694
meta_topic (META_DEBUG_FOCUS,
1695
"Focusing %s due to unmodified button %u press (display.c)\n",
1696
window->desc, event->xbutton.button);
1697
meta_window_focus (window, event->xbutton.time);
1700
/* However, do allow terminals to lose focus due to new
1701
* window mappings after the user clicks on a panel.
1703
display->allow_terminal_deactivation = TRUE;
1706
/* you can move on alt-click but not on
1707
* the click-to-focus
1712
else if (!unmodified && event->xbutton.button == meta_prefs_get_mouse_button_resize())
1714
if (window->has_resize_func)
1716
gboolean north, south;
1717
gboolean west, east;
1721
meta_window_get_position (window, &root_x, &root_y);
1723
west = event->xbutton.x_root < (root_x + 1 * window->rect.width / 3);
1724
east = event->xbutton.x_root > (root_x + 2 * window->rect.width / 3);
1725
north = event->xbutton.y_root < (root_y + 1 * window->rect.height / 3);
1726
south = event->xbutton.y_root > (root_y + 2 * window->rect.height / 3);
1729
op = META_GRAB_OP_RESIZING_NW;
1730
else if (north && east)
1731
op = META_GRAB_OP_RESIZING_NE;
1732
else if (south && west)
1733
op = META_GRAB_OP_RESIZING_SW;
1734
else if (south && east)
1735
op = META_GRAB_OP_RESIZING_SE;
1737
op = META_GRAB_OP_RESIZING_N;
1739
op = META_GRAB_OP_RESIZING_W;
1741
op = META_GRAB_OP_RESIZING_E;
1743
op = META_GRAB_OP_RESIZING_S;
1744
else /* Middle region is no-op to avoid user triggering wrong action */
1745
op = META_GRAB_OP_NONE;
1747
if (op != META_GRAB_OP_NONE)
1748
meta_display_begin_grab_op (display,
1754
event->xbutton.button,
1756
event->xbutton.time,
1757
event->xbutton.x_root,
1758
event->xbutton.y_root);
1761
else if (event->xbutton.button == meta_prefs_get_mouse_button_menu())
1763
if (meta_prefs_get_raise_on_click ())
1764
meta_window_raise (window);
1765
meta_window_show_menu (window,
1766
event->xbutton.x_root,
1767
event->xbutton.y_root,
1768
event->xbutton.button,
1769
event->xbutton.time);
1772
if (!frame_was_receiver && unmodified)
1774
/* This is from our synchronous grab since
1775
* it has no modifiers and was on the client window
1779
/* When clicking a different app in click-to-focus
1780
* in application-based mode, and the different
1781
* app is not a dock or desktop, eat the focus click.
1783
if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
1784
meta_prefs_get_application_based () &&
1785
!window->has_focus &&
1786
window->type != META_WINDOW_DOCK &&
1787
window->type != META_WINDOW_DESKTOP &&
1788
(display->focus_window == NULL ||
1789
!meta_window_same_application (window,
1790
display->focus_window)))
1791
mode = AsyncPointer; /* eat focus click */
1793
mode = ReplayPointer; /* give event back */
1795
meta_verbose ("Allowing events mode %s time %u\n",
1796
mode == AsyncPointer ? "AsyncPointer" : "ReplayPointer",
1797
(unsigned int)event->xbutton.time);
1799
XAllowEvents (display->xdisplay,
1800
mode, event->xbutton.time);
1803
if (begin_move && window->has_move_func)
1805
meta_display_begin_grab_op (display,
1808
META_GRAB_OP_MOVING,
1811
event->xbutton.button,
1813
event->xbutton.time,
1814
event->xbutton.x_root,
1815
event->xbutton.y_root);
1820
if (display->grab_window == window &&
1821
grab_op_is_mouse (display->grab_op))
1822
meta_window_handle_mouse_grab_op_event (window, event);
1825
if (display->grab_window == window &&
1826
grab_op_is_mouse (display->grab_op))
1827
meta_window_handle_mouse_grab_op_event (window, event);
1830
if (display->grab_window == window &&
1831
grab_op_is_mouse (display->grab_op))
1833
meta_window_handle_mouse_grab_op_event (window, event);
1837
/* If the mouse switches screens, active the default window on the new
1838
* screen; this will make keybindings and workspace-launched items
1839
* actually appear on the right screen.
1842
MetaScreen *new_screen =
1843
meta_display_screen_for_root (display, event->xcrossing.root);
1845
if (new_screen != NULL && display->active_screen != new_screen)
1846
meta_workspace_focus_default_window (new_screen->active_workspace,
1848
event->xcrossing.time);
1851
/* Check if we've entered a window; do this even if window->has_focus to
1854
if (window && !serial_is_ignored (display, event->xany.serial) &&
1855
event->xcrossing.mode != NotifyGrab &&
1856
event->xcrossing.mode != NotifyUngrab &&
1857
event->xcrossing.detail != NotifyInferior &&
1858
meta_display_focus_sentinel_clear (display))
1860
switch (meta_prefs_get_focus_mode ())
1862
case META_FOCUS_MODE_SLOPPY:
1863
case META_FOCUS_MODE_MOUSE:
1864
display->mouse_mode = TRUE;
1865
if (window->type != META_WINDOW_DOCK &&
1866
window->type != META_WINDOW_DESKTOP)
1868
meta_topic (META_DEBUG_FOCUS,
1869
"Focusing %s due to enter notify with serial %lu "
1870
"at time %lu, and setting display->mouse_mode to "
1874
event->xcrossing.time);
1876
meta_window_focus (window, event->xcrossing.time);
1878
/* stop ignoring stuff */
1879
reset_ignores (display);
1881
if (meta_prefs_get_auto_raise ())
1883
meta_display_queue_autoraise_callback (display, window);
1887
meta_topic (META_DEBUG_FOCUS,
1888
"Auto raise is disabled\n");
1891
/* In mouse focus mode, we defocus when the mouse *enters*
1892
* the DESKTOP window, instead of defocusing on LeaveNotify.
1893
* This is because having the mouse enter override-redirect
1894
* child windows unfortunately causes LeaveNotify events that
1895
* we can't distinguish from the mouse actually leaving the
1896
* toplevel window as we expect. But, since we filter out
1897
* EnterNotify events on override-redirect windows, this
1898
* alternative mechanism works great.
1900
if (window->type == META_WINDOW_DESKTOP &&
1901
meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE &&
1902
display->expected_focus_window != NULL)
1904
meta_topic (META_DEBUG_FOCUS,
1905
"Unsetting focus from %s due to mouse entering "
1906
"the DESKTOP window\n",
1907
display->expected_focus_window->desc);
1908
meta_display_focus_the_no_focus_window (display,
1910
event->xcrossing.time);
1913
case META_FOCUS_MODE_CLICK:
1917
if (window->type == META_WINDOW_DOCK)
1918
meta_window_raise (window);
1922
if (display->grab_window == window &&
1923
grab_op_is_mouse (display->grab_op))
1924
meta_window_handle_mouse_grab_op_event (window, event);
1925
else if (window != NULL)
1927
if (window->type == META_WINDOW_DOCK &&
1928
event->xcrossing.mode != NotifyGrab &&
1929
event->xcrossing.mode != NotifyUngrab &&
1931
meta_window_lower (window);
1938
meta_window_notify_focus (window, event);
1940
else if (meta_display_xwindow_is_a_no_focus_window (display,
1941
event->xany.window))
1943
meta_topic (META_DEBUG_FOCUS,
1944
"Focus %s event received on no_focus_window 0x%lx "
1945
"mode %s detail %s\n",
1946
event->type == FocusIn ? "in" :
1947
event->type == FocusOut ? "out" :
1950
meta_event_mode_to_string (event->xfocus.mode),
1951
meta_event_detail_to_string (event->xfocus.detail));
1955
MetaScreen *screen =
1956
meta_display_screen_for_root(display,
1957
event->xany.window);
1961
meta_topic (META_DEBUG_FOCUS,
1962
"Focus %s event received on root window 0x%lx "
1963
"mode %s detail %s\n",
1964
event->type == FocusIn ? "in" :
1965
event->type == FocusOut ? "out" :
1968
meta_event_mode_to_string (event->xfocus.mode),
1969
meta_event_detail_to_string (event->xfocus.detail));
1971
if (event->type == FocusIn &&
1972
event->xfocus.detail == NotifyDetailNone)
1974
meta_topic (META_DEBUG_FOCUS,
1975
"Focus got set to None, probably due to "
1976
"brain-damage in the X protocol (see bug "
1977
"125492). Setting the default focus window.\n");
1978
meta_workspace_focus_default_window (screen->active_workspace,
1980
meta_display_get_current_time_roundtrip (display));
1982
else if (event->type == FocusIn &&
1983
event->xfocus.mode == NotifyNormal &&
1984
event->xfocus.detail == NotifyInferior)
1986
meta_topic (META_DEBUG_FOCUS,
1987
"Focus got set to root window, probably due to "
1988
"gnome-session logout dialog usage (see bug "
1989
"153220). Setting the default focus window.\n");
1990
meta_workspace_focus_default_window (screen->active_workspace,
1992
meta_display_get_current_time_roundtrip (display));
2001
case GraphicsExpose:
2005
case VisibilityNotify:
2011
screen = meta_display_screen_for_root (display,
2012
event->xcreatewindow.parent);
2014
meta_stack_tracker_create_event (screen->stack_tracker,
2015
&event->xcreatewindow);
2023
screen = meta_display_screen_for_root (display,
2024
event->xdestroywindow.event);
2026
meta_stack_tracker_destroy_event (screen->stack_tracker,
2027
&event->xdestroywindow);
2031
/* FIXME: It sucks that DestroyNotify events don't come with
2032
* a timestamp; could we do something better here? Maybe X
2033
* will change one day?
2036
timestamp = meta_display_get_current_time_roundtrip (display);
2038
if (display->grab_op != META_GRAB_OP_NONE &&
2039
display->grab_window == window)
2040
meta_display_end_grab_op (display, timestamp);
2042
if (frame_was_receiver)
2044
meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n",
2045
window->frame->xwindow);
2046
meta_error_trap_push (display);
2047
meta_window_destroy_frame (window->frame->window);
2048
meta_error_trap_pop (display, FALSE);
2052
/* Unmanage destroyed window */
2053
meta_window_unmanage (window, timestamp);
2061
/* FIXME: It sucks that UnmapNotify events don't come with
2062
* a timestamp; could we do something better here? Maybe X
2063
* will change one day?
2066
timestamp = meta_display_get_current_time_roundtrip (display);
2068
if (display->grab_op != META_GRAB_OP_NONE &&
2069
display->grab_window == window &&
2070
((window->frame == NULL) || !window->frame->mapped))
2071
meta_display_end_grab_op (display, timestamp);
2073
if (!frame_was_receiver)
2075
if (window->unmaps_pending == 0)
2077
meta_topic (META_DEBUG_WINDOW_STATE,
2078
"Window %s withdrawn\n",
2081
/* Unmanage withdrawn window */
2082
window->withdrawn = TRUE;
2083
meta_window_unmanage (window, timestamp);
2088
window->unmaps_pending -= 1;
2089
meta_topic (META_DEBUG_WINDOW_STATE,
2090
"Received pending unmap, %d now pending\n",
2091
window->unmaps_pending);
2095
/* Unfocus on UnmapNotify, do this after the possible
2096
* window_free above so that window_free can see if window->has_focus
2097
* and move focus to another window
2100
meta_window_notify_focus (window, event);
2104
/* NB: override redirect windows wont cause a map request so we
2105
* watch out for map notifies against any root windows too if a
2106
* compositor is enabled: */
2107
if (display->compositor && window == NULL
2108
&& meta_display_screen_for_root (display, event->xmap.event))
2110
window = meta_window_new (display, event->xmap.window,
2117
window = meta_window_new (display, event->xmaprequest.window,
2120
/* if frame was receiver it's some malicious send event or something */
2121
else if (!frame_was_receiver && window)
2123
meta_verbose ("MapRequest on %s mapped = %d minimized = %d\n",
2124
window->desc, window->mapped, window->minimized);
2125
if (window->minimized)
2127
meta_window_unminimize (window);
2128
if (window->workspace != window->screen->active_workspace)
2130
meta_verbose ("Changing workspace due to MapRequest mapped = %d minimized = %d\n",
2131
window->mapped, window->minimized);
2132
meta_window_change_workspace (window,
2133
window->screen->active_workspace);
2138
case ReparentNotify:
2142
screen = meta_display_screen_for_root (display,
2143
event->xconfigure.event);
2147
meta_stack_tracker_reparent_event (screen->stack_tracker,
2152
case ConfigureNotify:
2153
if (event->xconfigure.event != event->xconfigure.window)
2157
screen = meta_display_screen_for_root (display,
2158
event->xconfigure.event);
2160
meta_stack_tracker_configure_event (screen->stack_tracker,
2161
&event->xconfigure);
2163
if (window && window->override_redirect)
2164
meta_window_configure_notify (window, &event->xconfigure);
2166
/* Handle screen resize */
2170
screen = meta_display_screen_for_root (display,
2171
event->xconfigure.window);
2176
/* do the resize the official way */
2177
XRRUpdateConfiguration (event);
2179
/* poke around in Xlib */
2180
screen->xscreen->width = event->xconfigure.width;
2181
screen->xscreen->height = event->xconfigure.height;
2184
meta_screen_resize (screen,
2185
event->xconfigure.width,
2186
event->xconfigure.height);
2190
case ConfigureRequest:
2191
/* This comment and code is found in both twm and fvwm */
2193
* According to the July 27, 1988 ICCCM draft, we should ignore size and
2194
* position fields in the WM_NORMAL_HINTS property when we map a window.
2195
* Instead, we'll read the current geometry. Therefore, we should respond
2196
* to configuration requests for windows which have never been mapped.
2203
xwcm = event->xconfigurerequest.value_mask &
2204
(CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
2206
xwc.x = event->xconfigurerequest.x;
2207
xwc.y = event->xconfigurerequest.y;
2208
xwc.width = event->xconfigurerequest.width;
2209
xwc.height = event->xconfigurerequest.height;
2210
xwc.border_width = event->xconfigurerequest.border_width;
2212
meta_verbose ("Configuring withdrawn window to %d,%d %dx%d border %d (some values may not be in mask)\n",
2213
xwc.x, xwc.y, xwc.width, xwc.height, xwc.border_width);
2214
meta_error_trap_push (display);
2215
XConfigureWindow (display->xdisplay, event->xconfigurerequest.window,
2217
meta_error_trap_pop (display, FALSE);
2221
if (!frame_was_receiver)
2222
meta_window_configure_request (window, event);
2229
case CirculateNotify:
2231
case CirculateRequest:
2233
case PropertyNotify:
2238
if (window && !frame_was_receiver)
2239
meta_window_property_notify (window, event);
2240
else if (property_for_window && !frame_was_receiver)
2241
meta_window_property_notify (property_for_window, event);
2243
group = meta_display_lookup_group (display,
2244
event->xproperty.window);
2246
meta_group_property_notify (group, event);
2249
if (window == NULL &&
2250
group == NULL) /* window/group != NULL means it wasn't a root window */
2251
screen = meta_display_screen_for_root (display,
2252
event->xproperty.window);
2256
if (event->xproperty.atom ==
2257
display->atom__NET_DESKTOP_LAYOUT)
2258
meta_screen_update_workspace_layout (screen);
2259
else if (event->xproperty.atom ==
2260
display->atom__NET_DESKTOP_NAMES)
2261
meta_screen_update_workspace_names (screen);
2263
else if (event->xproperty.atom ==
2264
display->atom__NET_RESTACK_WINDOW)
2265
handle_net_restack_window (display, event);
2268
/* we just use this property as a sentinel to avoid
2269
* certain race conditions. See the comment for the
2270
* sentinel_counter variable declaration in display.h
2272
if (event->xproperty.atom ==
2273
display->atom__MUTTER_SENTINEL)
2275
meta_display_decrement_focus_sentinel (display);
2280
case SelectionClear:
2281
/* do this here instead of at end of function
2285
/* FIXME: Clearing display->current_time here makes no sense to
2286
* me; who put this here and why?
2288
display->current_time = CurrentTime;
2290
process_selection_clear (display, event);
2291
/* Note that processing that may have resulted in
2292
* closing the display... so return right away.
2295
case SelectionRequest:
2296
process_selection_request (display, event);
2298
case SelectionNotify:
2300
case ColormapNotify:
2301
if (window && !frame_was_receiver)
2302
window->colormap = event->xcolormap.colormap;
2307
if (!frame_was_receiver)
2308
meta_window_client_message (window, event);
2314
screen = meta_display_screen_for_root (display,
2315
event->xclient.window);
2319
if (event->xclient.message_type ==
2320
display->atom__NET_CURRENT_DESKTOP)
2323
MetaWorkspace *workspace;
2326
space = event->xclient.data.l[0];
2327
time = event->xclient.data.l[1];
2329
meta_verbose ("Request to change current workspace to %d with "
2330
"specified timestamp of %u\n",
2334
meta_screen_get_workspace_by_index (screen,
2337
/* Handle clients using the older version of the spec... */
2338
if (time == 0 && workspace)
2340
meta_warning ("Received a NET_CURRENT_DESKTOP message "
2341
"from a broken (outdated) client who sent "
2343
time = meta_display_get_current_time_roundtrip (display);
2347
meta_workspace_activate (workspace, time);
2349
meta_verbose ("Don't know about workspace %d\n", space);
2351
else if (event->xclient.message_type ==
2352
display->atom__NET_NUMBER_OF_DESKTOPS)
2356
num_spaces = event->xclient.data.l[0];
2358
meta_verbose ("Request to set number of workspaces to %d\n",
2361
meta_prefs_set_num_workspaces (num_spaces);
2363
else if (event->xclient.message_type ==
2364
display->atom__NET_SHOWING_DESKTOP)
2366
gboolean showing_desktop;
2369
showing_desktop = event->xclient.data.l[0] != 0;
2370
/* FIXME: Braindead protocol doesn't have a timestamp */
2371
timestamp = meta_display_get_current_time_roundtrip (display);
2372
meta_verbose ("Request to %s desktop\n",
2373
showing_desktop ? "show" : "hide");
2375
if (showing_desktop)
2376
meta_screen_show_desktop (screen, timestamp);
2379
meta_screen_unshow_desktop (screen);
2380
meta_workspace_focus_default_window (screen->active_workspace, NULL, timestamp);
2383
else if (event->xclient.message_type ==
2384
display->atom__MUTTER_RESTART_MESSAGE)
2386
meta_verbose ("Received restart request\n");
2389
else if (event->xclient.message_type ==
2390
display->atom__MUTTER_RELOAD_THEME_MESSAGE)
2392
meta_verbose ("Received reload theme request\n");
2393
meta_ui_set_current_theme (meta_prefs_get_theme (),
2395
meta_display_retheme_all ();
2397
else if (event->xclient.message_type ==
2398
display->atom__MUTTER_SET_KEYBINDINGS_MESSAGE)
2400
meta_verbose ("Received set keybindings request = %d\n",
2401
(int) event->xclient.data.l[0]);
2402
meta_set_keybindings_disabled (!event->xclient.data.l[0]);
2404
else if (event->xclient.message_type ==
2405
display->atom__MUTTER_TOGGLE_VERBOSE)
2407
meta_verbose ("Received toggle verbose message\n");
2408
meta_set_verbose (!meta_is_verbose ());
2410
else if (event->xclient.message_type ==
2411
display->atom_WM_PROTOCOLS)
2413
meta_verbose ("Received WM_PROTOCOLS message\n");
2415
if ((Atom)event->xclient.data.l[0] == display->atom__NET_WM_PING)
2417
process_pong_message (display, event);
2419
/* We don't want ping reply events going into
2420
* the GTK+ event loop because gtk+ will treat
2421
* them as ping requests and send more replies.
2423
filter_out_event = TRUE;
2428
if (event->xclient.message_type ==
2429
display->atom__NET_REQUEST_FRAME_EXTENTS)
2431
meta_verbose ("Received _NET_REQUEST_FRAME_EXTENTS message\n");
2432
process_request_frame_extents (display, event);
2438
gboolean ignore_current;
2440
ignore_current = FALSE;
2442
/* Check whether the next event is an identical MappingNotify
2443
* event. If it is, ignore the current event, we'll update
2444
* when we get the next one.
2446
if (XPending (display->xdisplay))
2450
XPeekEvent (display->xdisplay, &next_event);
2452
if (next_event.type == MappingNotify &&
2453
next_event.xmapping.request == event->xmapping.request)
2454
ignore_current = TRUE;
2457
if (!ignore_current)
2459
/* Let XLib know that there is a new keyboard mapping.
2461
XRefreshKeyboardMapping (&event->xmapping);
2462
meta_display_process_mapping_event (display, event);
2468
if (event->type == display->xkb_base_event_type)
2470
XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
2472
switch (xkb_ev->xkb_type)
2475
if (XSERVER_TIME_IS_BEFORE(display->last_bell_time,
2476
xkb_ev->time - 1000))
2478
display->last_bell_time = xkb_ev->time;
2479
meta_bell_notify (display, xkb_ev);
2488
if (display->compositor)
2490
if (meta_compositor_process_event (display->compositor,
2493
filter_out_event = TRUE;
2496
display->current_time = CurrentTime;
2497
return filter_out_event;
2500
/* Return the window this has to do with, if any, rather
2501
* than the frame or root window that was selecting
2505
event_get_modified_window (MetaDisplay *display,
2508
switch (event->type)
2519
case GraphicsExpose:
2521
case VisibilityNotify:
2523
case PropertyNotify:
2524
case SelectionClear:
2525
case SelectionRequest:
2526
case SelectionNotify:
2527
case ColormapNotify:
2531
return event->xany.window;
2534
return event->xcreatewindow.window;
2537
return event->xdestroywindow.window;
2540
return event->xunmap.window;
2543
return event->xmap.window;
2546
return event->xmaprequest.window;
2548
case ReparentNotify:
2549
return event->xreparent.window;
2551
case ConfigureNotify:
2552
return event->xconfigure.window;
2554
case ConfigureRequest:
2555
return event->xconfigurerequest.window;
2558
return event->xgravity.window;
2560
case CirculateNotify:
2561
return event->xcirculate.window;
2563
case CirculateRequest:
2564
return event->xcirculaterequest.window;
2571
if (META_DISPLAY_HAS_SHAPE (display) &&
2572
event->type == (display->shape_event_base + ShapeNotify))
2574
XShapeEvent *sev = (XShapeEvent*) event;
2584
event_get_time (MetaDisplay *display,
2587
switch (event->type)
2591
return event->xkey.time;
2595
return event->xbutton.time;
2598
return event->xmotion.time;
2600
case PropertyNotify:
2601
return event->xproperty.time;
2603
case SelectionClear:
2604
case SelectionRequest:
2605
case SelectionNotify:
2606
return event->xselection.time;
2610
return event->xcrossing.time;
2616
case GraphicsExpose:
2620
case VisibilityNotify:
2622
case ColormapNotify:
2627
case ReparentNotify:
2628
case ConfigureNotify:
2629
case ConfigureRequest:
2631
case CirculateNotify:
2632
case CirculateRequest:
2639
#ifdef WITH_VERBOSE_MODE
2641
meta_event_detail_to_string (int d)
2643
const char *detail = "???";
2646
/* We are an ancestor in the A<->B focus change relationship */
2647
case NotifyAncestor:
2648
detail = "NotifyAncestor";
2650
case NotifyDetailNone:
2651
detail = "NotifyDetailNone";
2653
/* We are a descendant in the A<->B focus change relationship */
2654
case NotifyInferior:
2655
detail = "NotifyInferior";
2657
case NotifyNonlinear:
2658
detail = "NotifyNonlinear";
2660
case NotifyNonlinearVirtual:
2661
detail = "NotifyNonlinearVirtual";
2664
detail = "NotifyPointer";
2666
case NotifyPointerRoot:
2667
detail = "NotifyPointerRoot";
2670
detail = "NotifyVirtual";
2676
#endif /* WITH_VERBOSE_MODE */
2678
#ifdef WITH_VERBOSE_MODE
2680
meta_event_mode_to_string (int m)
2682
const char *mode = "???";
2686
mode = "NotifyNormal";
2689
mode = "NotifyGrab";
2692
mode = "NotifyUngrab";
2694
/* not sure any X implementations are missing this, but
2695
* it seems to be absent from some docs.
2697
#ifdef NotifyWhileGrabbed
2698
case NotifyWhileGrabbed:
2699
mode = "NotifyWhileGrabbed";
2706
#endif /* WITH_VERBOSE_MODE */
2708
#ifdef WITH_VERBOSE_MODE
2710
stack_mode_to_string (int mode)
2728
#endif /* WITH_VERBOSE_MODE */
2730
#ifdef WITH_VERBOSE_MODE
2732
key_event_description (Display *xdisplay,
2738
keysym = XKeycodeToKeysym (xdisplay, event->xkey.keycode, 0);
2740
str = XKeysymToString (keysym);
2742
return g_strdup_printf ("Key '%s' state 0x%x",
2743
str ? str : "none", event->xkey.state);
2745
#endif /* WITH_VERBOSE_MODE */
2748
#ifdef WITH_VERBOSE_MODE
2750
sync_value_to_64 (const XSyncValue *value)
2754
v = XSyncValueLow32 (*value);
2755
v |= (((gint64)XSyncValueHigh32 (*value)) << 32);
2759
#endif /* WITH_VERBOSE_MODE */
2761
#ifdef WITH_VERBOSE_MODE
2763
alarm_state_to_string (XSyncAlarmState state)
2767
case XSyncAlarmActive:
2769
case XSyncAlarmInactive:
2771
case XSyncAlarmDestroyed:
2777
#endif /* WITH_VERBOSE_MODE */
2779
#endif /* HAVE_XSYNC */
2781
#ifdef WITH_VERBOSE_MODE
2783
meta_spew_event (MetaDisplay *display,
2786
const char *name = NULL;
2791
if (!meta_is_verbose())
2794
/* filter overnumerous events */
2795
if (event->type == Expose || event->type == MotionNotify ||
2796
event->type == NoExpose)
2799
switch (event->type)
2803
extra = key_event_description (display->xdisplay, event);
2806
name = "KeyRelease";
2807
extra = key_event_description (display->xdisplay, event);
2810
name = "ButtonPress";
2811
extra = g_strdup_printf ("button %u state 0x%x x %d y %d root 0x%lx same_screen %d",
2812
event->xbutton.button,
2813
event->xbutton.state,
2816
event->xbutton.root,
2817
event->xbutton.same_screen);
2820
name = "ButtonRelease";
2821
extra = g_strdup_printf ("button %u state 0x%x x %d y %d root 0x%lx same_screen %d",
2822
event->xbutton.button,
2823
event->xbutton.state,
2826
event->xbutton.root,
2827
event->xbutton.same_screen);
2830
name = "MotionNotify";
2831
extra = g_strdup_printf ("win: 0x%lx x: %d y: %d",
2832
event->xmotion.window,
2837
name = "EnterNotify";
2838
extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %s detail: %s focus: %d x: %d y: %d",
2839
event->xcrossing.window,
2840
event->xcrossing.root,
2841
event->xcrossing.subwindow,
2842
meta_event_mode_to_string (event->xcrossing.mode),
2843
meta_event_detail_to_string (event->xcrossing.detail),
2844
event->xcrossing.focus,
2846
event->xcrossing.y);
2849
name = "LeaveNotify";
2850
extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %s detail: %s focus: %d x: %d y: %d",
2851
event->xcrossing.window,
2852
event->xcrossing.root,
2853
event->xcrossing.subwindow,
2854
meta_event_mode_to_string (event->xcrossing.mode),
2855
meta_event_detail_to_string (event->xcrossing.detail),
2856
event->xcrossing.focus,
2858
event->xcrossing.y);
2862
extra = g_strdup_printf ("detail: %s mode: %s\n",
2863
meta_event_detail_to_string (event->xfocus.detail),
2864
meta_event_mode_to_string (event->xfocus.mode));
2868
extra = g_strdup_printf ("detail: %s mode: %s\n",
2869
meta_event_detail_to_string (event->xfocus.detail),
2870
meta_event_mode_to_string (event->xfocus.mode));
2873
name = "KeymapNotify";
2878
case GraphicsExpose:
2879
name = "GraphicsExpose";
2884
case VisibilityNotify:
2885
name = "VisibilityNotify";
2888
name = "CreateNotify";
2889
extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx",
2890
event->xcreatewindow.parent,
2891
event->xcreatewindow.window);
2894
name = "DestroyNotify";
2895
extra = g_strdup_printf ("event: 0x%lx window: 0x%lx",
2896
event->xdestroywindow.event,
2897
event->xdestroywindow.window);
2900
name = "UnmapNotify";
2901
extra = g_strdup_printf ("event: 0x%lx window: 0x%lx from_configure: %d",
2902
event->xunmap.event,
2903
event->xunmap.window,
2904
event->xunmap.from_configure);
2908
extra = g_strdup_printf ("event: 0x%lx window: 0x%lx override_redirect: %d",
2911
event->xmap.override_redirect);
2914
name = "MapRequest";
2915
extra = g_strdup_printf ("window: 0x%lx parent: 0x%lx\n",
2916
event->xmaprequest.window,
2917
event->xmaprequest.parent);
2919
case ReparentNotify:
2920
name = "ReparentNotify";
2921
extra = g_strdup_printf ("window: 0x%lx parent: 0x%lx event: 0x%lx\n",
2922
event->xreparent.window,
2923
event->xreparent.parent,
2924
event->xreparent.event);
2926
case ConfigureNotify:
2927
name = "ConfigureNotify";
2928
extra = g_strdup_printf ("x: %d y: %d w: %d h: %d above: 0x%lx override_redirect: %d",
2929
event->xconfigure.x,
2930
event->xconfigure.y,
2931
event->xconfigure.width,
2932
event->xconfigure.height,
2933
event->xconfigure.above,
2934
event->xconfigure.override_redirect);
2936
case ConfigureRequest:
2937
name = "ConfigureRequest";
2938
extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx x: %d %sy: %d %sw: %d %sh: %d %sborder: %d %sabove: %lx %sstackmode: %s %s",
2939
event->xconfigurerequest.parent,
2940
event->xconfigurerequest.window,
2941
event->xconfigurerequest.x,
2942
event->xconfigurerequest.value_mask &
2943
CWX ? "" : "(unset) ",
2944
event->xconfigurerequest.y,
2945
event->xconfigurerequest.value_mask &
2946
CWY ? "" : "(unset) ",
2947
event->xconfigurerequest.width,
2948
event->xconfigurerequest.value_mask &
2949
CWWidth ? "" : "(unset) ",
2950
event->xconfigurerequest.height,
2951
event->xconfigurerequest.value_mask &
2952
CWHeight ? "" : "(unset) ",
2953
event->xconfigurerequest.border_width,
2954
event->xconfigurerequest.value_mask &
2955
CWBorderWidth ? "" : "(unset)",
2956
event->xconfigurerequest.above,
2957
event->xconfigurerequest.value_mask &
2958
CWSibling ? "" : "(unset)",
2959
stack_mode_to_string (event->xconfigurerequest.detail),
2960
event->xconfigurerequest.value_mask &
2961
CWStackMode ? "" : "(unset)");
2964
name = "GravityNotify";
2967
name = "ResizeRequest";
2968
extra = g_strdup_printf ("width = %d height = %d",
2969
event->xresizerequest.width,
2970
event->xresizerequest.height);
2972
case CirculateNotify:
2973
name = "CirculateNotify";
2975
case CirculateRequest:
2976
name = "CirculateRequest";
2978
case PropertyNotify:
2983
name = "PropertyNotify";
2985
meta_error_trap_push (display);
2986
str = XGetAtomName (display->xdisplay,
2987
event->xproperty.atom);
2988
meta_error_trap_pop (display, TRUE);
2990
if (event->xproperty.state == PropertyNewValue)
2991
state = "PropertyNewValue";
2992
else if (event->xproperty.state == PropertyDelete)
2993
state = "PropertyDelete";
2997
extra = g_strdup_printf ("atom: %s state: %s",
2998
str ? str : "(unknown atom)",
3003
case SelectionClear:
3004
name = "SelectionClear";
3006
case SelectionRequest:
3007
name = "SelectionRequest";
3009
case SelectionNotify:
3010
name = "SelectionNotify";
3012
case ColormapNotify:
3013
name = "ColormapNotify";
3018
name = "ClientMessage";
3019
meta_error_trap_push (display);
3020
str = XGetAtomName (display->xdisplay,
3021
event->xclient.message_type);
3022
meta_error_trap_pop (display, TRUE);
3023
extra = g_strdup_printf ("type: %s format: %d\n",
3024
str ? str : "(unknown atom)",
3025
event->xclient.format);
3030
name = "MappingNotify";
3034
if (META_DISPLAY_HAS_XSYNC (display) &&
3035
event->type == (display->xsync_event_base + XSyncAlarmNotify))
3037
XSyncAlarmNotifyEvent *aevent = (XSyncAlarmNotifyEvent*) event;
3039
name = "XSyncAlarmNotify";
3041
g_strdup_printf ("alarm: 0x%lx"
3042
" counter_value: %" G_GINT64_FORMAT
3043
" alarm_value: %" G_GINT64_FORMAT
3044
" time: %u alarm state: %s",
3046
(gint64) sync_value_to_64 (&aevent->counter_value),
3047
(gint64) sync_value_to_64 (&aevent->alarm_value),
3048
(unsigned int)aevent->time,
3049
alarm_state_to_string (aevent->state));
3052
#endif /* HAVE_XSYNC */
3054
if (META_DISPLAY_HAS_SHAPE (display) &&
3055
event->type == (display->shape_event_base + ShapeNotify))
3057
XShapeEvent *sev = (XShapeEvent*) event;
3059
name = "ShapeNotify";
3062
g_strdup_printf ("kind: %s "
3063
"x: %d y: %d w: %u h: %u "
3065
sev->kind == ShapeBounding ?
3067
(sev->kind == ShapeClip ?
3068
"ShapeClip" : "(unknown)"),
3069
sev->x, sev->y, sev->width, sev->height,
3073
#endif /* HAVE_SHAPE */
3075
name = "(Unknown event)";
3076
extra = g_strdup_printf ("type: %d", event->xany.type);
3081
screen = meta_display_screen_for_root (display, event->xany.window);
3084
winname = g_strdup_printf ("root %d", screen->number);
3086
winname = g_strdup_printf ("0x%lx", event->xany.window);
3088
meta_topic (META_DEBUG_EVENTS,
3089
"%s on %s%s %s %sserial %lu\n", name, winname,
3090
extra ? ":" : "", extra ? extra : "",
3091
event->xany.send_event ? "SEND " : "",
3092
event->xany.serial);
3099
#endif /* WITH_VERBOSE_MODE */
3102
meta_display_lookup_x_window (MetaDisplay *display,
3105
return g_hash_table_lookup (display->window_ids, &xwindow);
3109
meta_display_register_x_window (MetaDisplay *display,
3113
g_return_if_fail (g_hash_table_lookup (display->window_ids, xwindowp) == NULL);
3115
g_hash_table_insert (display->window_ids, xwindowp, window);
3119
meta_display_unregister_x_window (MetaDisplay *display,
3122
g_return_if_fail (g_hash_table_lookup (display->window_ids, &xwindow) != NULL);
3124
g_hash_table_remove (display->window_ids, &xwindow);
3126
/* Remove any pending pings */
3127
remove_pending_pings_for_window (display, xwindow);
3131
meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
3134
gboolean is_a_no_focus_window = FALSE;
3135
GSList *temp = display->screens;
3136
while (temp != NULL) {
3137
MetaScreen *screen = temp->data;
3138
if (screen->no_focus_window == xwindow) {
3139
is_a_no_focus_window = TRUE;
3145
return is_a_no_focus_window;
3149
meta_display_create_x_cursor (MetaDisplay *display,
3157
case META_CURSOR_DEFAULT:
3158
glyph = XC_left_ptr;
3160
case META_CURSOR_NORTH_RESIZE:
3161
glyph = XC_top_side;
3163
case META_CURSOR_SOUTH_RESIZE:
3164
glyph = XC_bottom_side;
3166
case META_CURSOR_WEST_RESIZE:
3167
glyph = XC_left_side;
3169
case META_CURSOR_EAST_RESIZE:
3170
glyph = XC_right_side;
3172
case META_CURSOR_SE_RESIZE:
3173
glyph = XC_bottom_right_corner;
3175
case META_CURSOR_SW_RESIZE:
3176
glyph = XC_bottom_left_corner;
3178
case META_CURSOR_NE_RESIZE:
3179
glyph = XC_top_right_corner;
3181
case META_CURSOR_NW_RESIZE:
3182
glyph = XC_top_left_corner;
3184
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
3187
case META_CURSOR_BUSY:
3192
g_assert_not_reached ();
3193
glyph = 0; /* silence compiler */
3197
xcursor = XCreateFontCursor (display->xdisplay, glyph);
3203
xcursor_for_op (MetaDisplay *display,
3206
MetaCursor cursor = META_CURSOR_DEFAULT;
3210
case META_GRAB_OP_RESIZING_SE:
3211
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
3212
cursor = META_CURSOR_SE_RESIZE;
3214
case META_GRAB_OP_RESIZING_S:
3215
case META_GRAB_OP_KEYBOARD_RESIZING_S:
3216
cursor = META_CURSOR_SOUTH_RESIZE;
3218
case META_GRAB_OP_RESIZING_SW:
3219
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
3220
cursor = META_CURSOR_SW_RESIZE;
3222
case META_GRAB_OP_RESIZING_N:
3223
case META_GRAB_OP_KEYBOARD_RESIZING_N:
3224
cursor = META_CURSOR_NORTH_RESIZE;
3226
case META_GRAB_OP_RESIZING_NE:
3227
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
3228
cursor = META_CURSOR_NE_RESIZE;
3230
case META_GRAB_OP_RESIZING_NW:
3231
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
3232
cursor = META_CURSOR_NW_RESIZE;
3234
case META_GRAB_OP_RESIZING_W:
3235
case META_GRAB_OP_KEYBOARD_RESIZING_W:
3236
cursor = META_CURSOR_WEST_RESIZE;
3238
case META_GRAB_OP_RESIZING_E:
3239
case META_GRAB_OP_KEYBOARD_RESIZING_E:
3240
cursor = META_CURSOR_EAST_RESIZE;
3242
case META_GRAB_OP_MOVING:
3243
case META_GRAB_OP_KEYBOARD_MOVING:
3244
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
3245
cursor = META_CURSOR_MOVE_OR_RESIZE_WINDOW;
3252
if (cursor == META_CURSOR_DEFAULT)
3254
return meta_display_create_x_cursor (display, cursor);
3258
meta_display_set_grab_op_cursor (MetaDisplay *display,
3261
gboolean change_pointer,
3262
Window grab_xwindow,
3267
cursor = xcursor_for_op (display, op);
3269
#define GRAB_MASK (PointerMotionMask | \
3270
ButtonPressMask | ButtonReleaseMask | \
3271
EnterWindowMask | LeaveWindowMask)
3275
meta_error_trap_push_with_return (display);
3276
XChangeActivePointerGrab (display->xdisplay,
3281
meta_topic (META_DEBUG_WINDOW_OPS,
3282
"Changed pointer with XChangeActivePointerGrab()\n");
3284
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
3286
meta_topic (META_DEBUG_WINDOW_OPS,
3287
"Error trapped from XChangeActivePointerGrab()\n");
3288
if (display->grab_have_pointer)
3289
display->grab_have_pointer = FALSE;
3294
g_assert (screen != NULL);
3296
meta_error_trap_push (display);
3297
if (XGrabPointer (display->xdisplay,
3301
GrabModeAsync, GrabModeAsync,
3304
timestamp) == GrabSuccess)
3306
display->grab_have_pointer = TRUE;
3307
meta_topic (META_DEBUG_WINDOW_OPS,
3308
"XGrabPointer() returned GrabSuccess time %u\n",
3313
meta_topic (META_DEBUG_WINDOW_OPS,
3314
"XGrabPointer() failed time %u\n",
3317
meta_error_trap_pop (display, TRUE);
3323
XFreeCursor (display->xdisplay, cursor);
3327
meta_display_begin_grab_op (MetaDisplay *display,
3331
gboolean pointer_already_grabbed,
3332
gboolean frame_action,
3339
Window grab_xwindow;
3341
meta_topic (META_DEBUG_WINDOW_OPS,
3342
"Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n",
3343
op, window ? window->desc : "none", button, pointer_already_grabbed,
3346
if (display->grab_op != META_GRAB_OP_NONE)
3349
meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect\n",
3350
op, window->desc, display->grab_op,
3351
display->grab_window ? display->grab_window->desc : "none");
3356
(meta_grab_op_is_moving (op) || meta_grab_op_is_resizing (op)))
3358
if (meta_prefs_get_raise_on_click ())
3359
meta_window_raise (window);
3362
display->grab_initial_x = root_x;
3363
display->grab_initial_y = root_y;
3364
display->grab_threshold_movement_reached = FALSE;
3369
* If we have no MetaWindow we do our best
3370
* and try to do the grab on the RootWindow.
3371
* This will fail if anyone else has any
3372
* key grab on the RootWindow.
3375
grab_xwindow = window->frame ? window->frame->xwindow : window->xwindow;
3377
grab_xwindow = screen->xroot;
3379
display->grab_have_pointer = FALSE;
3381
if (pointer_already_grabbed)
3382
display->grab_have_pointer = TRUE;
3384
meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow,
3387
if (!display->grab_have_pointer)
3389
meta_topic (META_DEBUG_WINDOW_OPS,
3390
"XGrabPointer() failed\n");
3394
/* Grab keys for keyboard ops and mouse move/resizes; see #126497 */
3395
if (grab_op_is_keyboard (op) || grab_op_is_mouse_only (op))
3398
display->grab_have_keyboard =
3399
meta_window_grab_all_keys (window, timestamp);
3402
display->grab_have_keyboard =
3403
meta_screen_grab_all_keys (screen, timestamp);
3405
if (!display->grab_have_keyboard)
3407
meta_topic (META_DEBUG_WINDOW_OPS,
3408
"grabbing all keys failed, ungrabbing pointer\n");
3409
XUngrabPointer (display->xdisplay, timestamp);
3410
display->grab_have_pointer = FALSE;
3415
display->grab_op = op;
3416
display->grab_window = window;
3417
display->grab_screen = screen;
3418
display->grab_xwindow = grab_xwindow;
3419
display->grab_button = button;
3420
display->grab_mask = modmask;
3421
display->grab_anchor_root_x = root_x;
3422
display->grab_anchor_root_y = root_y;
3423
display->grab_latest_motion_x = root_x;
3424
display->grab_latest_motion_y = root_y;
3425
display->grab_last_moveresize_time.tv_sec = 0;
3426
display->grab_last_moveresize_time.tv_usec = 0;
3427
display->grab_motion_notify_time = 0;
3428
display->grab_old_window_stacking = NULL;
3430
display->grab_sync_request_alarm = None;
3431
display->grab_last_user_action_was_snap = FALSE;
3433
display->grab_frame_action = frame_action;
3435
if (display->grab_resize_timeout_id)
3437
g_source_remove (display->grab_resize_timeout_id);
3438
display->grab_resize_timeout_id = 0;
3441
if (display->grab_window)
3443
meta_window_get_client_root_coords (display->grab_window,
3444
&display->grab_initial_window_pos);
3445
display->grab_anchor_window_pos = display->grab_initial_window_pos;
3448
if ( meta_grab_op_is_resizing (display->grab_op) &&
3449
display->grab_window->sync_request_counter != None)
3451
XSyncAlarmAttributes values;
3454
meta_error_trap_push_with_return (display);
3456
/* Set the counter to 0, so we know that the application's
3457
* responses to the client messages will always trigger
3458
* a PositiveTransition
3461
XSyncIntToValue (&init, 0);
3462
XSyncSetCounter (display->xdisplay,
3463
display->grab_window->sync_request_counter, init);
3465
display->grab_window->sync_request_serial = 0;
3466
display->grab_window->sync_request_time.tv_sec = 0;
3467
display->grab_window->sync_request_time.tv_usec = 0;
3469
values.trigger.counter = display->grab_window->sync_request_counter;
3470
values.trigger.value_type = XSyncAbsolute;
3471
values.trigger.test_type = XSyncPositiveTransition;
3472
XSyncIntToValue (&values.trigger.wait_value,
3473
display->grab_window->sync_request_serial + 1);
3475
/* After triggering, increment test_value by this.
3476
* (NOT wait_value above)
3478
XSyncIntToValue (&values.delta, 1);
3480
/* we want events (on by default anyway) */
3481
values.events = True;
3483
display->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay,
3492
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
3493
display->grab_sync_request_alarm = None;
3495
meta_topic (META_DEBUG_RESIZING,
3496
"Created update alarm 0x%lx\n",
3497
display->grab_sync_request_alarm);
3502
meta_topic (META_DEBUG_WINDOW_OPS,
3503
"Grab op %u on window %s successful\n",
3504
display->grab_op, window ? window->desc : "(null)");
3506
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
3507
g_assert (display->grab_op != META_GRAB_OP_NONE);
3509
/* If this is a move or resize, cache the window edges for
3510
* resistance/snapping
3512
if (meta_grab_op_is_resizing (display->grab_op) ||
3513
meta_grab_op_is_moving (display->grab_op))
3515
meta_topic (META_DEBUG_WINDOW_OPS,
3516
"Computing edges to resist-movement or snap-to for %s.\n",
3518
meta_display_compute_resistance_and_snapping_edges (display);
3521
/* Save the old stacking */
3522
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
3524
meta_topic (META_DEBUG_WINDOW_OPS,
3525
"Saving old stack positions; old pointer was %p.\n",
3526
display->grab_old_window_stacking);
3527
display->grab_old_window_stacking =
3528
meta_stack_get_positions (screen->stack);
3531
if (display->grab_window)
3533
meta_window_refresh_resize_popup (display->grab_window);
3540
meta_display_end_grab_op (MetaDisplay *display,
3543
meta_topic (META_DEBUG_WINDOW_OPS,
3544
"Ending grab op %u at time %u\n", display->grab_op, timestamp);
3546
if (display->grab_op == META_GRAB_OP_NONE)
3549
if (display->grab_window != NULL)
3550
display->grab_window->shaken_loose = FALSE;
3552
if (display->grab_window != NULL &&
3553
!meta_prefs_get_raise_on_click () &&
3554
(meta_grab_op_is_moving (display->grab_op) ||
3555
meta_grab_op_is_resizing (display->grab_op)))
3557
/* Only raise the window in orthogonal raise
3558
* ('do-not-raise-on-click') mode if the user didn't try to move
3559
* or resize the given window by at least a threshold amount.
3560
* For raise on click mode, the window was raised at the
3561
* beginning of the grab_op.
3563
if (!display->grab_threshold_movement_reached)
3564
meta_window_raise (display->grab_window);
3567
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) ||
3568
display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING)
3570
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
3571
meta_screen_tab_popup_destroy (display->grab_screen);
3573
meta_screen_workspace_popup_destroy (display->grab_screen);
3575
/* If the ungrab here causes an EnterNotify, ignore it for
3578
display->ungrab_should_not_cause_focus_window = display->grab_xwindow;
3581
/* If this was a move or resize clear out the edge cache */
3582
if (meta_grab_op_is_resizing (display->grab_op) ||
3583
meta_grab_op_is_moving (display->grab_op))
3585
meta_topic (META_DEBUG_WINDOW_OPS,
3586
"Clearing out the edges for resistance/snapping");
3587
meta_display_cleanup_edges (display);
3590
if (display->grab_old_window_stacking != NULL)
3592
meta_topic (META_DEBUG_WINDOW_OPS,
3593
"Clearing out the old stack position, which was %p.\n",
3594
display->grab_old_window_stacking);
3595
g_list_free (display->grab_old_window_stacking);
3596
display->grab_old_window_stacking = NULL;
3599
if (display->grab_have_pointer)
3601
meta_topic (META_DEBUG_WINDOW_OPS,
3602
"Ungrabbing pointer with timestamp %u\n", timestamp);
3603
XUngrabPointer (display->xdisplay, timestamp);
3606
if (display->grab_have_keyboard)
3608
meta_topic (META_DEBUG_WINDOW_OPS,
3609
"Ungrabbing all keys timestamp %u\n", timestamp);
3610
if (display->grab_window)
3611
meta_window_ungrab_all_keys (display->grab_window, timestamp);
3613
meta_screen_ungrab_all_keys (display->grab_screen, timestamp);
3617
if (display->grab_sync_request_alarm != None)
3619
XSyncDestroyAlarm (display->xdisplay,
3620
display->grab_sync_request_alarm);
3621
display->grab_sync_request_alarm = None;
3623
#endif /* HAVE_XSYNC */
3625
display->grab_window = NULL;
3626
display->grab_screen = NULL;
3627
display->grab_xwindow = None;
3628
display->grab_op = META_GRAB_OP_NONE;
3630
if (display->grab_resize_popup)
3632
meta_ui_resize_popup_free (display->grab_resize_popup);
3633
display->grab_resize_popup = NULL;
3636
if (display->grab_resize_timeout_id)
3638
g_source_remove (display->grab_resize_timeout_id);
3639
display->grab_resize_timeout_id = 0;
3644
meta_display_check_threshold_reached (MetaDisplay *display,
3648
/* Don't bother doing the check again if we've already reached the threshold */
3649
if (meta_prefs_get_raise_on_click () ||
3650
display->grab_threshold_movement_reached)
3653
if (ABS (display->grab_initial_x - x) >= 8 ||
3654
ABS (display->grab_initial_y - y) >= 8)
3655
display->grab_threshold_movement_reached = TRUE;
3659
meta_change_button_grab (MetaDisplay *display,
3666
unsigned int ignored_mask;
3668
meta_verbose ("%s 0x%lx sync = %d button = %d modmask 0x%x\n",
3669
grab ? "Grabbing" : "Ungrabbing",
3671
sync, button, modmask);
3673
meta_error_trap_push (display);
3676
while (ignored_mask <= display->ignored_modifier_mask)
3678
if (ignored_mask & ~(display->ignored_modifier_mask))
3680
/* Not a combination of ignored modifiers
3681
* (it contains some non-ignored modifiers)
3687
if (meta_is_debugging ())
3688
meta_error_trap_push_with_return (display);
3690
/* GrabModeSync means freeze until XAllowEvents */
3693
XGrabButton (display->xdisplay, button, modmask | ignored_mask,
3695
ButtonPressMask | ButtonReleaseMask |
3696
PointerMotionMask | PointerMotionHintMask,
3697
sync ? GrabModeSync : GrabModeAsync,
3701
XUngrabButton (display->xdisplay, button, modmask | ignored_mask,
3704
if (meta_is_debugging ())
3708
result = meta_error_trap_pop_with_return (display, FALSE);
3710
if (result != Success)
3711
meta_verbose ("Failed to %s button %d with mask 0x%x for window 0x%lx error code %d\n",
3712
grab ? "grab" : "ungrab",
3713
button, modmask | ignored_mask, xwindow, result);
3719
meta_error_trap_pop (display, FALSE);
3723
meta_display_grab_window_buttons (MetaDisplay *display,
3726
/* Grab Alt + button1 for moving window.
3727
* Grab Alt + button2 for resizing window.
3728
* Grab Alt + button3 for popping up window menu.
3729
* Grab Alt + Shift + button1 for snap-moving window.
3731
meta_verbose ("Grabbing window buttons for 0x%lx\n", xwindow);
3733
/* FIXME If we ignored errors here instead of spewing, we could
3734
* put one big error trap around the loop and avoid a bunch of
3738
if (display->window_grab_modifiers != 0)
3740
gboolean debug = g_getenv ("MUTTER_DEBUG_BUTTON_GRABS") != NULL;
3742
for (i = 1; i < 4; i++)
3744
meta_change_button_grab (display, xwindow,
3747
i, display->window_grab_modifiers);
3749
/* This is for debugging, since I end up moving the Xnest
3753
meta_change_button_grab (display, xwindow,
3759
/* In addition to grabbing Alt+Button1 for moving the window,
3760
* grab Alt+Shift+Button1 for snap-moving the window. See bug
3761
* 112478. Unfortunately, this doesn't work with
3762
* Shift+Alt+Button1 for some reason; so at least part of the
3763
* order still matters, which sucks (please FIXME).
3765
meta_change_button_grab (display, xwindow,
3768
1, display->window_grab_modifiers | ShiftMask);
3773
meta_display_ungrab_window_buttons (MetaDisplay *display,
3779
if (display->window_grab_modifiers == 0)
3782
debug = g_getenv ("MUTTER_DEBUG_BUTTON_GRABS") != NULL;
3786
meta_change_button_grab (display, xwindow,
3788
display->window_grab_modifiers);
3791
meta_change_button_grab (display, xwindow,
3792
FALSE, FALSE, i, ControlMask);
3798
/* Grab buttons we only grab while unfocused in click-to-focus mode */
3799
#define MAX_FOCUS_BUTTON 4
3801
meta_display_grab_focus_window_button (MetaDisplay *display,
3804
/* Grab button 1 for activating unfocused windows */
3805
meta_verbose ("Grabbing unfocused window buttons for %s\n", window->desc);
3809
/* Don't grab at all unless in click to focus mode. In click to
3810
* focus, we may sometimes be clever about intercepting and eating
3811
* the focus click. But in mouse focus, we never do that since the
3812
* focus window may not be raised, and who wants to think about
3813
* mouse focus anyway.
3815
if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK)
3817
meta_verbose (" (well, not grabbing since not in click to focus mode)\n");
3822
if (window->have_focus_click_grab)
3824
meta_verbose (" (well, not grabbing since we already have the grab)\n");
3828
/* FIXME If we ignored errors here instead of spewing, we could
3829
* put one big error trap around the loop and avoid a bunch of
3835
while (i < MAX_FOCUS_BUTTON)
3837
meta_change_button_grab (display,
3845
window->have_focus_click_grab = TRUE;
3850
meta_display_ungrab_focus_window_button (MetaDisplay *display,
3853
meta_verbose ("Ungrabbing unfocused window buttons for %s\n", window->desc);
3855
if (!window->have_focus_click_grab)
3860
while (i < MAX_FOCUS_BUTTON)
3862
meta_change_button_grab (display, window->xwindow,
3863
FALSE, FALSE, i, 0);
3868
window->have_focus_click_grab = FALSE;
3873
meta_display_increment_event_serial (MetaDisplay *display)
3875
/* We just make some random X request */
3876
XDeleteProperty (display->xdisplay, display->leader_window,
3877
display->atom__MOTIF_WM_HINTS);
3881
meta_display_update_active_window_hint (MetaDisplay *display)
3887
if (display->focus_window)
3888
data[0] = display->focus_window->xwindow;
3892
tmp = display->screens;
3895
MetaScreen *screen = tmp->data;
3897
meta_error_trap_push (display);
3898
XChangeProperty (display->xdisplay, screen->xroot,
3899
display->atom__NET_ACTIVE_WINDOW,
3901
32, PropModeReplace, (guchar*) data, 1);
3903
meta_error_trap_pop (display, FALSE);
3910
meta_display_queue_retheme_all_windows (MetaDisplay *display)
3915
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
3919
MetaWindow *window = tmp->data;
3921
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
3924
window->frame->need_reapply_frame_shape = TRUE;
3926
meta_frame_queue_draw (window->frame);
3932
g_slist_free (windows);
3936
meta_display_retheme_all (void)
3938
meta_display_queue_retheme_all_windows (meta_get_display ());
3942
meta_display_set_cursor_theme (const char *theme,
3948
MetaDisplay *display = meta_get_display ();
3950
XcursorSetTheme (display->xdisplay, theme);
3951
XcursorSetDefaultSize (display->xdisplay, size);
3953
tmp = display->screens;
3956
MetaScreen *screen = tmp->data;
3958
meta_screen_update_cursor (screen);
3967
* Stores whether syncing is currently enabled.
3969
static gboolean is_syncing = FALSE;
3972
* Returns whether X synchronisation is currently enabled.
3974
* \return true if we must wait for events whenever we send X requests;
3977
* \bug This is *only* called by meta_display_open, but by that time
3978
* we have already turned syncing on or off on startup, and we don't
3979
* have any way to do so while Mutter is running, so it's rather
3983
meta_is_syncing (void)
3989
* A handy way to turn on synchronisation on or off for every display.
3991
* \bug Of course there is only one display ever anyway, so this can
3992
* be rather hugely simplified.
3995
meta_set_syncing (gboolean setting)
3997
if (setting != is_syncing)
3999
is_syncing = setting;
4001
XSynchronize (meta_get_display ()->xdisplay, is_syncing);
4006
* How long, in milliseconds, we should wait after pinging a window
4007
* before deciding it's not going to get back to us.
4009
#define PING_TIMEOUT_DELAY 2250
4012
* Does whatever it is we decided to do when a window didn't respond
4013
* to a ping. We also remove the ping from the display's list of
4014
* pending pings. This function is called by the event loop when the timeout
4015
* times out which we created at the start of the ping.
4017
* \param data All the information about this ping. It is a MetaPingData
4018
* cast to a void* in order to be passable to a timeout function.
4019
* This function will also free this parameter.
4021
* \return Always returns false, because this function is called as a
4022
* timeout and we don't want to run the timer again.
4027
meta_display_ping_timeout (gpointer data)
4029
MetaPingData *ping_data;
4033
ping_data->ping_timeout_id = 0;
4035
meta_topic (META_DEBUG_PING,
4036
"Ping %u on window %lx timed out\n",
4037
ping_data->timestamp, ping_data->xwindow);
4039
(* ping_data->ping_timeout_func) (ping_data->display, ping_data->xwindow,
4040
ping_data->timestamp, ping_data->user_data);
4042
ping_data->display->pending_pings =
4043
g_slist_remove (ping_data->display->pending_pings,
4045
ping_data_free (ping_data);
4051
* Sends a ping request to a window. The window must respond to
4052
* the request within a certain amount of time. If it does, we
4053
* will call one callback; if the time passes and we haven't had
4054
* a response, we call a different callback. The window must have
4055
* the hint showing that it can respond to a ping; if it doesn't,
4056
* we call the "got a response" callback immediately and return.
4057
* This function returns straight away after setting things up;
4058
* the callbacks will be called from the event loop.
4060
* \param display The MetaDisplay that the window is on
4061
* \param window The MetaWindow to send the ping to
4062
* \param timestamp The timestamp of the ping. Used for uniqueness.
4063
* Cannot be CurrentTime; use a real timestamp!
4064
* \param ping_reply_func The callback to call if we get a response.
4065
* \param ping_timeout_func The callback to call if we don't get a response.
4066
* \param user_data Arbitrary data that will be passed to the callback
4067
* function. (In practice it's often a pointer to
4070
* \bug This should probably be a method on windows, rather than displays
4071
* for one of their windows.
4076
meta_display_ping_window (MetaDisplay *display,
4079
MetaWindowPingFunc ping_reply_func,
4080
MetaWindowPingFunc ping_timeout_func,
4083
MetaPingData *ping_data;
4085
if (timestamp == CurrentTime)
4087
meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n");
4091
if (!window->net_wm_ping)
4093
if (ping_reply_func)
4094
(* ping_reply_func) (display, window->xwindow, timestamp, user_data);
4099
ping_data = g_new (MetaPingData, 1);
4100
ping_data->display = display;
4101
ping_data->xwindow = window->xwindow;
4102
ping_data->timestamp = timestamp;
4103
ping_data->ping_reply_func = ping_reply_func;
4104
ping_data->ping_timeout_func = ping_timeout_func;
4105
ping_data->user_data = user_data;
4106
ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY,
4107
meta_display_ping_timeout,
4110
display->pending_pings = g_slist_prepend (display->pending_pings, ping_data);
4112
meta_topic (META_DEBUG_PING,
4113
"Sending ping with timestamp %u to window %s\n",
4114
timestamp, window->desc);
4115
meta_window_send_icccm_message (window,
4116
display->atom__NET_WM_PING,
4121
process_request_frame_extents (MetaDisplay *display,
4124
/* The X window whose frame extents will be set. */
4125
Window xwindow = event->xclient.window;
4126
unsigned long data[4] = { 0, 0, 0, 0 };
4128
MotifWmHints *hints = NULL;
4129
gboolean hints_set = FALSE;
4131
meta_verbose ("Setting frame extents for 0x%lx\n", xwindow);
4133
/* See if the window is decorated. */
4134
hints_set = meta_prop_get_motif_hints (display,
4136
display->atom__MOTIF_WM_HINTS,
4138
if ((hints_set && hints->decorations) || !hints_set)
4147
screen = meta_display_screen_for_xwindow (display,
4148
event->xclient.window);
4151
meta_warning ("Received request to set _NET_FRAME_EXTENTS "
4152
"on 0x%lx which is on a screen we are not managing\n",
4153
event->xclient.window);
4158
/* Return estimated frame extents for a normal window. */
4159
meta_ui_theme_get_frame_borders (screen->ui,
4160
META_FRAME_TYPE_NORMAL,
4173
meta_topic (META_DEBUG_GEOMETRY,
4174
"Setting _NET_FRAME_EXTENTS on unmanaged window 0x%lx "
4175
"to top = %lu, left = %lu, bottom = %lu, right = %lu\n",
4176
xwindow, data[0], data[1], data[2], data[3]);
4178
meta_error_trap_push (display);
4179
XChangeProperty (display->xdisplay, xwindow,
4180
display->atom__NET_FRAME_EXTENTS,
4182
32, PropModeReplace, (guchar*) data, 4);
4183
meta_error_trap_pop (display, FALSE);
4189
* Process the pong (the response message) from the ping we sent
4190
* to the window. This involves removing the timeout, calling the
4191
* reply handler function, and freeing memory.
4193
* \param display the display we got the pong from
4194
* \param event the XEvent which is a pong; we can tell which
4195
* ping it corresponds to because it bears the
4201
process_pong_message (MetaDisplay *display,
4205
guint32 timestamp = event->xclient.data.l[1];
4207
meta_topic (META_DEBUG_PING, "Received a pong with timestamp %u\n",
4210
for (tmp = display->pending_pings; tmp; tmp = tmp->next)
4212
MetaPingData *ping_data = tmp->data;
4214
if (timestamp == ping_data->timestamp)
4216
meta_topic (META_DEBUG_PING,
4217
"Matching ping found for pong %u\n",
4218
ping_data->timestamp);
4220
/* Remove the ping data from the list */
4221
display->pending_pings = g_slist_remove (display->pending_pings,
4224
/* Remove the timeout */
4225
if (ping_data->ping_timeout_id != 0)
4227
g_source_remove (ping_data->ping_timeout_id);
4228
ping_data->ping_timeout_id = 0;
4232
(* ping_data->ping_reply_func) (display,
4234
ping_data->timestamp,
4235
ping_data->user_data);
4237
ping_data_free (ping_data);
4245
* Finds whether a window has any pings waiting on it.
4247
* \param display The MetaDisplay of the window.
4248
* \param window The MetaWindow whose pings we want to know about.
4250
* \return True if there is at least one ping which has been sent
4251
* to the window without getting a response; false otherwise.
4253
* \bug This should probably be a method on windows, rather than displays
4254
* for one of their windows.
4259
meta_display_window_has_pending_pings (MetaDisplay *display,
4264
for (tmp = display->pending_pings; tmp; tmp = tmp->next)
4266
MetaPingData *ping_data = tmp->data;
4268
if (ping_data->xwindow == window->xwindow)
4276
get_focussed_group (MetaDisplay *display)
4278
if (display->focus_window)
4279
return display->focus_window->group;
4284
#define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \
4285
|| ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \
4286
|| ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focussed_group(w->display))))
4289
find_tab_forward (MetaDisplay *display,
4292
MetaWorkspace *workspace,
4294
gboolean skip_first)
4298
g_return_val_if_fail (start != NULL, NULL);
4299
g_return_val_if_fail (workspace != NULL, NULL);
4307
MetaWindow *window = tmp->data;
4309
if (window->screen == screen &&
4310
IN_TAB_CHAIN (window, type))
4316
tmp = workspace->mru_list;
4317
while (tmp != start)
4319
MetaWindow *window = tmp->data;
4321
if (IN_TAB_CHAIN (window, type))
4331
find_tab_backward (MetaDisplay *display,
4334
MetaWorkspace *workspace,
4340
g_return_val_if_fail (start != NULL, NULL);
4341
g_return_val_if_fail (workspace != NULL, NULL);
4348
MetaWindow *window = tmp->data;
4350
if (window->screen == screen &&
4351
IN_TAB_CHAIN (window, type))
4357
tmp = g_list_last (workspace->mru_list);
4358
while (tmp != start)
4360
MetaWindow *window = tmp->data;
4362
if (IN_TAB_CHAIN (window, type))
4372
meta_display_get_tab_list (MetaDisplay *display,
4375
MetaWorkspace *workspace)
4379
g_return_val_if_fail (workspace != NULL, NULL);
4381
/* Windows sellout mode - MRU order. Collect unminimized windows
4382
* then minimized so minimized windows aren't in the way so much.
4388
tmp = workspace->mru_list;
4391
MetaWindow *window = tmp->data;
4393
if (!window->minimized &&
4394
window->screen == screen &&
4395
IN_TAB_CHAIN (window, type))
4396
tab_list = g_list_prepend (tab_list, window);
4405
tmp = workspace->mru_list;
4408
MetaWindow *window = tmp->data;
4410
if (window->minimized &&
4411
window->screen == screen &&
4412
IN_TAB_CHAIN (window, type))
4413
tab_list = g_list_prepend (tab_list, window);
4419
tab_list = g_list_reverse (tab_list);
4423
MetaWindow *l_window;
4425
tmp = meta_display_list_windows (display, META_LIST_DEFAULT);
4427
/* Go through all windows */
4432
/* Check to see if it demands attention */
4433
if (l_window->wm_state_demands_attention &&
4434
l_window->workspace!=workspace)
4436
/* if it does, add it to the popup */
4437
tab_list = g_list_prepend (tab_list, l_window);
4441
} /* End while tmp!=NULL */
4448
meta_display_get_tab_next (MetaDisplay *display,
4451
MetaWorkspace *workspace,
4458
tab_list = meta_display_get_tab_list(display,
4463
if (tab_list == NULL)
4468
g_assert (window->display == display);
4471
ret = find_tab_backward (display, type, screen, workspace,
4472
g_list_find (tab_list,
4476
ret = find_tab_forward (display, type, screen, workspace,
4477
g_list_find (tab_list,
4483
skip = display->focus_window != NULL &&
4484
IN_TAB_CHAIN (display->focus_window, type);
4486
ret = find_tab_backward (display, type, screen, workspace,
4489
ret = find_tab_forward (display, type, screen, workspace,
4493
g_list_free (tab_list);
4498
meta_display_get_tab_current (MetaDisplay *display,
4501
MetaWorkspace *workspace)
4505
window = display->focus_window;
4507
if (window != NULL &&
4508
window->screen == screen &&
4509
IN_TAB_CHAIN (window, type) &&
4510
(workspace == NULL ||
4511
meta_window_located_on_workspace (window, workspace)))
4518
meta_resize_gravity_from_grab_op (MetaGrabOp op)
4525
case META_GRAB_OP_RESIZING_SE:
4526
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
4527
gravity = NorthWestGravity;
4529
case META_GRAB_OP_KEYBOARD_RESIZING_S:
4530
case META_GRAB_OP_RESIZING_S:
4531
gravity = NorthGravity;
4533
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
4534
case META_GRAB_OP_RESIZING_SW:
4535
gravity = NorthEastGravity;
4537
case META_GRAB_OP_KEYBOARD_RESIZING_N:
4538
case META_GRAB_OP_RESIZING_N:
4539
gravity = SouthGravity;
4541
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
4542
case META_GRAB_OP_RESIZING_NE:
4543
gravity = SouthWestGravity;
4545
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
4546
case META_GRAB_OP_RESIZING_NW:
4547
gravity = SouthEastGravity;
4549
case META_GRAB_OP_KEYBOARD_RESIZING_E:
4550
case META_GRAB_OP_RESIZING_E:
4551
gravity = WestGravity;
4553
case META_GRAB_OP_KEYBOARD_RESIZING_W:
4554
case META_GRAB_OP_RESIZING_W:
4555
gravity = EastGravity;
4557
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
4558
gravity = CenterGravity;
4568
find_screen_for_selection (MetaDisplay *display,
4574
tmp = display->screens;
4577
MetaScreen *screen = tmp->data;
4579
if (screen->wm_sn_selection_window == owner &&
4580
screen->wm_sn_atom == selection)
4589
/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
4591
convert_property (MetaDisplay *display,
4598
Atom conversion_targets[N_TARGETS];
4599
long icccm_version[] = { 2, 0 };
4601
conversion_targets[0] = display->atom_TARGETS;
4602
conversion_targets[1] = display->atom_MULTIPLE;
4603
conversion_targets[2] = display->atom_TIMESTAMP;
4604
conversion_targets[3] = display->atom_VERSION;
4606
meta_error_trap_push_with_return (display);
4607
if (target == display->atom_TARGETS)
4608
XChangeProperty (display->xdisplay, w, property,
4609
XA_ATOM, 32, PropModeReplace,
4610
(unsigned char *)conversion_targets, N_TARGETS);
4611
else if (target == display->atom_TIMESTAMP)
4612
XChangeProperty (display->xdisplay, w, property,
4613
XA_INTEGER, 32, PropModeReplace,
4614
(unsigned char *)&screen->wm_sn_timestamp, 1);
4615
else if (target == display->atom_VERSION)
4616
XChangeProperty (display->xdisplay, w, property,
4617
XA_INTEGER, 32, PropModeReplace,
4618
(unsigned char *)icccm_version, 2);
4621
meta_error_trap_pop_with_return (display, FALSE);
4625
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
4628
/* Be sure the PropertyNotify has arrived so we
4629
* can send SelectionNotify
4631
/* FIXME the error trap pop synced anyway, right? */
4632
meta_topic (META_DEBUG_SYNC, "Syncing on %s\n", G_STRFUNC);
4633
XSync (display->xdisplay, False);
4638
/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
4640
process_selection_request (MetaDisplay *display,
4643
XSelectionEvent reply;
4646
screen = find_screen_for_selection (display,
4647
event->xselectionrequest.owner,
4648
event->xselectionrequest.selection);
4654
meta_error_trap_push (display);
4655
str = XGetAtomName (display->xdisplay,
4656
event->xselectionrequest.selection);
4657
meta_error_trap_pop (display, TRUE);
4659
meta_verbose ("Selection request with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
4660
str ? str : "(bad atom)", event->xselectionrequest.owner);
4667
reply.type = SelectionNotify;
4668
reply.display = display->xdisplay;
4669
reply.requestor = event->xselectionrequest.requestor;
4670
reply.selection = event->xselectionrequest.selection;
4671
reply.target = event->xselectionrequest.target;
4672
reply.property = None;
4673
reply.time = event->xselectionrequest.time;
4675
if (event->xselectionrequest.target == display->atom_MULTIPLE)
4677
if (event->xselectionrequest.property != None)
4681
unsigned long num, rest;
4682
unsigned char *data;
4684
meta_error_trap_push_with_return (display);
4685
if (XGetWindowProperty (display->xdisplay,
4686
event->xselectionrequest.requestor,
4687
event->xselectionrequest.property, 0, 256, False,
4688
display->atom_ATOM_PAIR,
4689
&type, &format, &num, &rest, &data) != Success)
4691
meta_error_trap_pop_with_return (display, TRUE);
4695
if (meta_error_trap_pop_with_return (display, TRUE) == Success)
4697
/* FIXME: to be 100% correct, should deal with rest > 0,
4698
* but since we have 4 possible targets, we will hardly ever
4699
* meet multiple requests with a length > 8
4701
adata = (Atom*)data;
4703
while (i < (int) num)
4705
if (!convert_property (display, screen,
4706
event->xselectionrequest.requestor,
4707
adata[i], adata[i+1]))
4712
meta_error_trap_push (display);
4713
XChangeProperty (display->xdisplay,
4714
event->xselectionrequest.requestor,
4715
event->xselectionrequest.property,
4716
display->atom_ATOM_PAIR,
4717
32, PropModeReplace, data, num);
4718
meta_error_trap_pop (display, FALSE);
4725
if (event->xselectionrequest.property == None)
4726
event->xselectionrequest.property = event->xselectionrequest.target;
4728
if (convert_property (display, screen,
4729
event->xselectionrequest.requestor,
4730
event->xselectionrequest.target,
4731
event->xselectionrequest.property))
4732
reply.property = event->xselectionrequest.property;
4735
XSendEvent (display->xdisplay,
4736
event->xselectionrequest.requestor,
4737
False, 0L, (XEvent*)&reply);
4739
meta_verbose ("Handled selection request\n");
4743
process_selection_clear (MetaDisplay *display,
4746
/* We need to unmanage the screen on which we lost the selection */
4749
screen = find_screen_for_selection (display,
4750
event->xselectionclear.window,
4751
event->xselectionclear.selection);
4756
meta_verbose ("Got selection clear for screen %d on display %s\n",
4757
screen->number, display->name);
4759
meta_display_unmanage_screen (display,
4761
event->xselectionclear.time);
4763
/* display and screen may both be invalid memory... */
4771
meta_error_trap_push (display);
4772
str = XGetAtomName (display->xdisplay,
4773
event->xselectionclear.selection);
4774
meta_error_trap_pop (display, TRUE);
4776
meta_verbose ("Selection clear with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
4777
str ? str : "(bad atom)", event->xselectionclear.window);
4784
meta_display_unmanage_screen (MetaDisplay *display,
4788
meta_verbose ("Unmanaging screen %d on display %s\n",
4789
screen->number, display->name);
4791
g_return_if_fail (g_slist_find (display->screens, screen) != NULL);
4793
meta_screen_free (screen, timestamp);
4794
display->screens = g_slist_remove (display->screens, screen);
4796
if (display->screens == NULL)
4797
meta_display_close (display, timestamp);
4801
meta_display_unmanage_windows_for_screen (MetaDisplay *display,
4808
winlist = meta_display_list_windows (display,
4809
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
4810
winlist = g_slist_sort (winlist, meta_display_stack_cmp);
4812
/* Unmanage all windows */
4816
meta_window_unmanage (tmp->data, timestamp);
4820
g_slist_free (winlist);
4824
meta_display_stack_cmp (const void *a,
4827
MetaWindow *aw = (void*) a;
4828
MetaWindow *bw = (void*) b;
4830
if (aw->screen == bw->screen)
4831
return meta_stack_windows_cmp (aw->screen->stack, aw, bw);
4832
/* Then assume screens are stacked by number */
4833
else if (aw->screen->number < bw->screen->number)
4835
else if (aw->screen->number > bw->screen->number)
4838
return 0; /* not reached in theory, if windows on same display */
4842
meta_display_devirtualize_modifiers (MetaDisplay *display,
4843
MetaVirtualModifier modifiers,
4848
if (modifiers & META_VIRTUAL_SHIFT_MASK)
4850
if (modifiers & META_VIRTUAL_CONTROL_MASK)
4851
*mask |= ControlMask;
4852
if (modifiers & META_VIRTUAL_ALT_MASK)
4854
if (modifiers & META_VIRTUAL_META_MASK)
4855
*mask |= display->meta_mask;
4856
if (modifiers & META_VIRTUAL_HYPER_MASK)
4857
*mask |= display->hyper_mask;
4858
if (modifiers & META_VIRTUAL_SUPER_MASK)
4859
*mask |= display->super_mask;
4860
if (modifiers & META_VIRTUAL_MOD2_MASK)
4862
if (modifiers & META_VIRTUAL_MOD3_MASK)
4864
if (modifiers & META_VIRTUAL_MOD4_MASK)
4866
if (modifiers & META_VIRTUAL_MOD5_MASK)
4871
update_window_grab_modifiers (MetaDisplay *display)
4874
MetaVirtualModifier virtual_mods;
4877
virtual_mods = meta_prefs_get_mouse_button_mods ();
4878
meta_display_devirtualize_modifiers (display, virtual_mods,
4881
display->window_grab_modifiers = mods;
4885
prefs_changed_callback (MetaPreference pref,
4888
MetaDisplay *display = data;
4890
/* It may not be obvious why we regrab on focus mode
4891
* change; it's because we handle focus clicks a
4892
* bit differently for the different focus modes.
4894
if (pref == META_PREF_MOUSE_BUTTON_MODS ||
4895
pref == META_PREF_FOCUS_MODE)
4897
MetaDisplay *display = data;
4901
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
4907
MetaWindow *w = tmp->data;
4908
meta_display_ungrab_window_buttons (display, w->xwindow);
4909
meta_display_ungrab_focus_window_button (display, w);
4913
/* change our modifier */
4914
if (pref == META_PREF_MOUSE_BUTTON_MODS)
4915
update_window_grab_modifiers (display);
4921
MetaWindow *w = tmp->data;
4922
if (w->type != META_WINDOW_DOCK)
4924
meta_display_grab_focus_window_button (display, w);
4925
meta_display_grab_window_buttons (display, w->xwindow);
4930
g_slist_free (windows);
4932
else if (pref == META_PREF_AUDIBLE_BELL)
4934
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
4936
else if (pref == META_PREF_COMPOSITING_MANAGER)
4938
gboolean cm = meta_prefs_get_compositing_manager ();
4941
enable_compositor (display, TRUE);
4943
disable_compositor (display);
4948
meta_display_increment_focus_sentinel (MetaDisplay *display)
4950
unsigned long data[1];
4952
data[0] = meta_display_get_current_time (display);
4954
XChangeProperty (display->xdisplay,
4955
((MetaScreen*) display->screens->data)->xroot,
4956
display->atom__MUTTER_SENTINEL,
4958
32, PropModeReplace, (guchar*) data, 1);
4960
display->sentinel_counter += 1;
4964
meta_display_decrement_focus_sentinel (MetaDisplay *display)
4966
display->sentinel_counter -= 1;
4968
if (display->sentinel_counter < 0)
4969
display->sentinel_counter = 0;
4973
meta_display_focus_sentinel_clear (MetaDisplay *display)
4975
return (display->sentinel_counter == 0);
4979
sanity_check_timestamps (MetaDisplay *display,
4982
if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time))
4984
meta_warning ("last_focus_time (%u) is greater than comparison "
4985
"timestamp (%u). This most likely represents a buggy "
4986
"client sending inaccurate timestamps in messages such as "
4987
"_NET_ACTIVE_WINDOW. Trying to work around...\n",
4988
display->last_focus_time, timestamp);
4989
display->last_focus_time = timestamp;
4991
if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time))
4996
meta_warning ("last_user_time (%u) is greater than comparison "
4997
"timestamp (%u). This most likely represents a buggy "
4998
"client sending inaccurate timestamps in messages such as "
4999
"_NET_ACTIVE_WINDOW. Trying to work around...\n",
5000
display->last_user_time, timestamp);
5001
display->last_user_time = timestamp;
5003
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
5007
MetaWindow *window = tmp->data;
5009
if (XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time))
5011
meta_warning ("%s appears to be one of the offending windows "
5012
"with a timestamp of %u. Working around...\n",
5013
window->desc, window->net_wm_user_time);
5014
window->net_wm_user_time = timestamp;
5020
g_slist_free (windows);
5025
timestamp_too_old (MetaDisplay *display,
5029
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
5030
* us to sanity check the timestamp here and ensure it doesn't correspond to
5031
* a future time (though we would want to rename to
5032
* timestamp_too_old_or_in_future).
5035
if (*timestamp == CurrentTime)
5037
meta_warning ("Got a request to focus %s with a timestamp of 0. This "
5038
"shouldn't happen!\n",
5039
window ? window->desc : "the no_focus_window");
5040
meta_print_backtrace ();
5041
*timestamp = meta_display_get_current_time_roundtrip (display);
5044
else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
5046
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
5048
meta_topic (META_DEBUG_FOCUS,
5049
"Ignoring focus request for %s since %u "
5050
"is less than %u and %u.\n",
5051
window ? window->desc : "the no_focus_window",
5053
display->last_user_time,
5054
display->last_focus_time);
5059
meta_topic (META_DEBUG_FOCUS,
5060
"Received focus request for %s which is newer than most "
5061
"recent user_time, but less recent than "
5062
"last_focus_time (%u < %u < %u); adjusting "
5063
"accordingly. (See bug 167358)\n",
5064
window ? window->desc : "the no_focus_window",
5065
display->last_user_time,
5067
display->last_focus_time);
5068
*timestamp = display->last_focus_time;
5077
meta_display_set_input_focus_window (MetaDisplay *display,
5079
gboolean focus_frame,
5082
if (timestamp_too_old (display, window, ×tamp))
5085
meta_error_trap_push (display);
5086
XSetInputFocus (display->xdisplay,
5087
focus_frame ? window->frame->xwindow : window->xwindow,
5088
RevertToPointerRoot,
5090
meta_error_trap_pop (display, FALSE);
5092
display->expected_focus_window = window;
5093
display->last_focus_time = timestamp;
5094
display->active_screen = window->screen;
5096
if (window != display->autoraise_window)
5097
meta_display_remove_autoraise_callback (window->display);
5101
meta_display_focus_the_no_focus_window (MetaDisplay *display,
5105
if (timestamp_too_old (display, NULL, ×tamp))
5108
XSetInputFocus (display->xdisplay,
5109
screen->no_focus_window,
5110
RevertToPointerRoot,
5112
display->expected_focus_window = NULL;
5113
display->last_focus_time = timestamp;
5114
display->active_screen = screen;
5116
meta_display_remove_autoraise_callback (display);
5120
meta_display_remove_autoraise_callback (MetaDisplay *display)
5122
if (display->autoraise_timeout_id != 0)
5124
g_source_remove (display->autoraise_timeout_id);
5125
display->autoraise_timeout_id = 0;
5126
display->autoraise_window = NULL;
5131
meta_display_overlay_key_activate (MetaDisplay *display)
5133
g_signal_emit (display, display_signals[OVERLAY_KEY], 0);
5137
meta_display_get_compositor_version (MetaDisplay *display,
5141
*major = display->composite_major_version;
5142
*minor = display->composite_minor_version;
5146
meta_display_get_xdisplay (MetaDisplay *display)
5148
return display->xdisplay;
5152
meta_display_get_compositor (MetaDisplay *display)
5154
return display->compositor;
5158
meta_display_get_screens (MetaDisplay *display)
5160
return display->screens;
5164
meta_display_has_shape (MetaDisplay *display)
5166
return META_DISPLAY_HAS_SHAPE (display);
5170
* meta_display_get_focus_window:
5171
* @display: a #MetaDisplay
5173
* Get the window that, according to events received from X server,
5174
* currently has the input focus. We may have already sent a request
5175
* to the X server to move the focus window elsewhere. (The
5176
* expected_focus_window records where we've last set the input
5179
* Return Value: (transfer none): The current focus window
5182
meta_display_get_focus_window (MetaDisplay *display)
5184
return display->focus_window;
5188
meta_display_get_damage_event_base (MetaDisplay *display)
5190
return display->damage_event_base;
5195
meta_display_get_shape_event_base (MetaDisplay *display)
5197
return display->shape_event_base;
5201
Atom meta_display_get_atom (MetaDisplay *display, MetaAtom meta_atom)
5203
Atom *atoms = & display->atom_WM_PROTOCOLS;
5205
return atoms[meta_atom - 1];