00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00033 #include <config.h>
00034 #include "display-private.h"
00035 #include "util.h"
00036 #include "main.h"
00037 #include "screen-private.h"
00038 #include "window-private.h"
00039 #include "window-props.h"
00040 #include "group-props.h"
00041 #include "frame-private.h"
00042 #include "errors.h"
00043 #include "keybindings.h"
00044 #include "prefs.h"
00045 #include "resizepopup.h"
00046 #include "xprops.h"
00047 #include "workspace.h"
00048 #include "bell.h"
00049 #include "effects.h"
00050 #include "compositor.h"
00051 #include <X11/Xatom.h>
00052 #include <X11/cursorfont.h>
00053 #ifdef HAVE_SOLARIS_XINERAMA
00054 #include <X11/extensions/xinerama.h>
00055 #endif
00056 #ifdef HAVE_XFREE_XINERAMA
00057 #include <X11/extensions/Xinerama.h>
00058 #endif
00059 #ifdef HAVE_RANDR
00060 #include <X11/extensions/Xrandr.h>
00061 #endif
00062 #ifdef HAVE_SHAPE
00063 #include <X11/extensions/shape.h>
00064 #endif
00065 #ifdef HAVE_RENDER
00066 #include <X11/extensions/Xrender.h>
00067 #endif
00068 #ifdef HAVE_XKB
00069 #include <X11/XKBlib.h>
00070 #endif
00071 #ifdef HAVE_XCURSOR
00072 #include <X11/Xcursor/Xcursor.h>
00073 #endif
00074 #ifdef HAVE_COMPOSITE_EXTENSIONS
00075 #include <X11/extensions/Xcomposite.h>
00076 #include <X11/extensions/Xdamage.h>
00077 #include <X11/extensions/Xfixes.h>
00078 #endif
00079 #include <string.h>
00080
00081 #define GRAB_OP_IS_WINDOW_SWITCH(g) \
00082 (g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
00083 g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
00084 g == META_GRAB_OP_KEYBOARD_TABBING_GROUP || \
00085 g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL || \
00086 g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK || \
00087 g == META_GRAB_OP_KEYBOARD_ESCAPING_GROUP)
00088
00113 typedef struct
00114 {
00115 MetaDisplay *display;
00116 Window xwindow;
00117 guint32 timestamp;
00118 MetaWindowPingFunc ping_reply_func;
00119 MetaWindowPingFunc ping_timeout_func;
00120 void *user_data;
00121 guint ping_timeout_id;
00122 } MetaPingData;
00123
00124 typedef struct
00125 {
00126 MetaDisplay *display;
00127 Window xwindow;
00128 } MetaAutoRaiseData;
00129
00136 static MetaDisplay *the_display = NULL;
00137
00138 static void meta_spew_event (MetaDisplay *display,
00139 XEvent *event);
00140
00141 static gboolean event_callback (XEvent *event,
00142 gpointer data);
00143 static Window event_get_modified_window (MetaDisplay *display,
00144 XEvent *event);
00145 static guint32 event_get_time (MetaDisplay *display,
00146 XEvent *event);
00147 static void process_request_frame_extents (MetaDisplay *display,
00148 XEvent *event);
00149 static void process_pong_message (MetaDisplay *display,
00150 XEvent *event);
00151 static void process_selection_request (MetaDisplay *display,
00152 XEvent *event);
00153 static void process_selection_clear (MetaDisplay *display,
00154 XEvent *event);
00155
00156 static void update_window_grab_modifiers (MetaDisplay *display);
00157
00158 static void prefs_changed_callback (MetaPreference pref,
00159 void *data);
00160
00161 static void sanity_check_timestamps (MetaDisplay *display,
00162 guint32 known_good_timestamp);
00163
00164 MetaGroup* get_focussed_group (MetaDisplay *display);
00165
00172 static void
00173 ping_data_free (MetaPingData *ping_data)
00174 {
00175
00176 if (ping_data->ping_timeout_id != 0)
00177 g_source_remove (ping_data->ping_timeout_id);
00178
00179 g_free (ping_data);
00180 }
00181
00192 static void
00193 remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
00194 {
00195 GSList *tmp;
00196 GSList *dead;
00197
00198
00199
00200
00201 dead = NULL;
00202 for (tmp = display->pending_pings; tmp; tmp = tmp->next)
00203 {
00204 MetaPingData *ping_data = tmp->data;
00205
00206 if (ping_data->xwindow == xwindow)
00207 dead = g_slist_prepend (dead, ping_data);
00208 }
00209
00210
00211 for (tmp = dead; tmp; tmp = tmp->next)
00212 {
00213 MetaPingData *ping_data = tmp->data;
00214
00215 display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
00216 ping_data_free (ping_data);
00217 }
00218
00219 g_slist_free (dead);
00220 }
00221
00222
00223 #ifdef HAVE_STARTUP_NOTIFICATION
00224 static void
00225 sn_error_trap_push (SnDisplay *sn_display,
00226 Display *xdisplay)
00227 {
00228 MetaDisplay *display;
00229 display = meta_display_for_x_display (xdisplay);
00230 if (display != NULL)
00231 meta_error_trap_push (display);
00232 }
00233
00234 static void
00235 sn_error_trap_pop (SnDisplay *sn_display,
00236 Display *xdisplay)
00237 {
00238 MetaDisplay *display;
00239 display = meta_display_for_x_display (xdisplay);
00240 if (display != NULL)
00241 meta_error_trap_pop (display, FALSE);
00242 }
00243 #endif
00244
00245 static void
00246 enable_compositor (MetaDisplay *display,
00247 gboolean composite_windows)
00248 {
00249 GSList *list;
00250
00251 if (!META_DISPLAY_HAS_COMPOSITE (display) ||
00252 !META_DISPLAY_HAS_DAMAGE (display) ||
00253 !META_DISPLAY_HAS_XFIXES (display) ||
00254 !META_DISPLAY_HAS_RENDER (display))
00255 {
00256 meta_warning (_("Missing %s extension required for compositing"),
00257 !META_DISPLAY_HAS_COMPOSITE (display) ? "composite" :
00258 !META_DISPLAY_HAS_DAMAGE (display) ? "damage" :
00259 !META_DISPLAY_HAS_XFIXES (display) ? "xfixes" : "render");
00260 return;
00261 }
00262
00263 if (!display->compositor)
00264 display->compositor = meta_compositor_new (display);
00265
00266 if (!display->compositor)
00267 return;
00268
00269 for (list = display->screens; list != NULL; list = list->next)
00270 {
00271 MetaScreen *screen = list->data;
00272
00273 meta_compositor_manage_screen (screen->display->compositor,
00274 screen);
00275
00276 if (composite_windows)
00277 meta_screen_composite_all_windows (screen);
00278 }
00279 }
00280
00281 static void
00282 disable_compositor (MetaDisplay *display)
00283 {
00284 GSList *list;
00285
00286 if (!display->compositor)
00287 return;
00288
00289 for (list = display->screens; list != NULL; list = list->next)
00290 {
00291 MetaScreen *screen = list->data;
00292
00293 meta_compositor_unmanage_screen (screen->display->compositor,
00294 screen);
00295 }
00296
00297 meta_compositor_destroy (display->compositor);
00298 display->compositor = NULL;
00299 }
00300
00311 gboolean
00312 meta_display_open (void)
00313 {
00314 Display *xdisplay;
00315 GSList *screens;
00316 GSList *tmp;
00317 int i;
00318 guint32 timestamp;
00319
00320
00321 char *atom_names[] = {
00322 #define item(x) #x,
00323 #include "atomnames.h"
00324 #undef item
00325 };
00326 Atom atoms[G_N_ELEMENTS(atom_names)];
00327
00328 meta_verbose ("Opening display '%s'\n", XDisplayName (NULL));
00329
00330 xdisplay = meta_ui_get_display ();
00331
00332 if (xdisplay == NULL)
00333 {
00334 meta_warning (_("Failed to open X Window System display '%s'\n"),
00335 XDisplayName (NULL));
00336 return FALSE;
00337 }
00338
00339 if (meta_is_syncing ())
00340 XSynchronize (xdisplay, True);
00341
00342 g_assert (the_display == NULL);
00343 the_display = g_new (MetaDisplay, 1);
00344
00345 the_display->closing = 0;
00346
00347
00348
00349
00350
00351 the_display->name = g_strdup (XDisplayName (NULL));
00352 the_display->xdisplay = xdisplay;
00353 the_display->error_trap_synced_at_last_pop = TRUE;
00354 the_display->error_traps = 0;
00355 the_display->error_trap_handler = NULL;
00356 the_display->server_grab_count = 0;
00357 the_display->display_opening = TRUE;
00358
00359 the_display->pending_pings = NULL;
00360 the_display->autoraise_timeout_id = 0;
00361 the_display->autoraise_window = NULL;
00362 the_display->focus_window = NULL;
00363 the_display->expected_focus_window = NULL;
00364 the_display->grab_old_window_stacking = NULL;
00365
00366 the_display->mouse_mode = TRUE;
00367 the_display->allow_terminal_deactivation = TRUE;
00368
00369
00370 #ifdef HAVE_XSYNC
00371 the_display->grab_sync_request_alarm = None;
00372 #endif
00373
00374
00375 the_display->static_gravity_works = g_getenv ("METACITY_USE_STATIC_GRAVITY") != NULL;
00376
00377 meta_bell_init (the_display);
00378
00379 meta_display_init_keys (the_display);
00380
00381 update_window_grab_modifiers (the_display);
00382
00383 meta_prefs_add_listener (prefs_changed_callback, the_display);
00384
00385 meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
00386 XInternAtoms (the_display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
00387 False, atoms);
00388 {
00389 int i = 0;
00390 #define item(x) the_display->atom_##x = atoms[i++];
00391 #include "atomnames.h"
00392 #undef item
00393 }
00394
00395 the_display->prop_hooks = NULL;
00396 meta_display_init_window_prop_hooks (the_display);
00397 the_display->group_prop_hooks = NULL;
00398 meta_display_init_group_prop_hooks (the_display);
00399
00400
00401
00402
00403 the_display->leader_window = None;
00404 the_display->timestamp_pinging_window = None;
00405
00406 the_display->xinerama_cache_invalidated = TRUE;
00407
00408 the_display->groups_by_leader = NULL;
00409
00410 the_display->window_with_menu = NULL;
00411 the_display->window_menu = NULL;
00412
00413 the_display->screens = NULL;
00414 the_display->active_screen = NULL;
00415
00416 #ifdef HAVE_STARTUP_NOTIFICATION
00417 the_display->sn_display = sn_display_new (the_display->xdisplay,
00418 sn_error_trap_push,
00419 sn_error_trap_pop);
00420 #endif
00421
00422 the_display->events = NULL;
00423
00424
00425 meta_ui_add_event_func (the_display->xdisplay,
00426 event_callback,
00427 the_display);
00428
00429 the_display->window_ids = g_hash_table_new (meta_unsigned_long_hash,
00430 meta_unsigned_long_equal);
00431
00432 i = 0;
00433 while (i < N_IGNORED_SERIALS)
00434 {
00435 the_display->ignored_serials[i] = 0;
00436 ++i;
00437 }
00438 the_display->ungrab_should_not_cause_focus_window = None;
00439
00440 the_display->current_time = CurrentTime;
00441 the_display->sentinel_counter = 0;
00442
00443 the_display->grab_resize_timeout_id = 0;
00444 the_display->grab_have_keyboard = FALSE;
00445
00446 #ifdef HAVE_XKB
00447 the_display->last_bell_time = 0;
00448 #endif
00449
00450 the_display->grab_op = META_GRAB_OP_NONE;
00451 the_display->grab_wireframe_active = FALSE;
00452 the_display->grab_window = NULL;
00453 the_display->grab_screen = NULL;
00454 the_display->grab_resize_popup = NULL;
00455
00456 the_display->grab_edge_resistance_data = NULL;
00457
00458 #ifdef HAVE_XSYNC
00459 {
00460 int major, minor;
00461
00462 the_display->have_xsync = FALSE;
00463
00464 the_display->xsync_error_base = 0;
00465 the_display->xsync_event_base = 0;
00466
00467
00468 major = SYNC_MAJOR_VERSION;
00469 minor = SYNC_MINOR_VERSION;
00470
00471 if (!XSyncQueryExtension (the_display->xdisplay,
00472 &the_display->xsync_event_base,
00473 &the_display->xsync_error_base) ||
00474 !XSyncInitialize (the_display->xdisplay,
00475 &major, &minor))
00476 {
00477 the_display->xsync_error_base = 0;
00478 the_display->xsync_event_base = 0;
00479 }
00480 else
00481 the_display->have_xsync = TRUE;
00482
00483 meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n",
00484 major, minor,
00485 the_display->xsync_error_base,
00486 the_display->xsync_event_base);
00487 }
00488 #else
00489 meta_verbose ("Not compiled with Xsync support\n");
00490 #endif
00491
00492
00493 #ifdef HAVE_SHAPE
00494 {
00495 the_display->have_shape = FALSE;
00496
00497 the_display->shape_error_base = 0;
00498 the_display->shape_event_base = 0;
00499
00500 if (!XShapeQueryExtension (the_display->xdisplay,
00501 &the_display->shape_event_base,
00502 &the_display->shape_error_base))
00503 {
00504 the_display->shape_error_base = 0;
00505 the_display->shape_event_base = 0;
00506 }
00507 else
00508 the_display->have_shape = TRUE;
00509
00510 meta_verbose ("Attempted to init Shape, found error base %d event base %d\n",
00511 the_display->shape_error_base,
00512 the_display->shape_event_base);
00513 }
00514 #else
00515 meta_verbose ("Not compiled with Shape support\n");
00516 #endif
00517
00518 #ifdef HAVE_RENDER
00519 {
00520 the_display->have_render = FALSE;
00521
00522 the_display->render_error_base = 0;
00523 the_display->render_event_base = 0;
00524
00525 if (!XRenderQueryExtension (the_display->xdisplay,
00526 &the_display->render_event_base,
00527 &the_display->render_error_base))
00528 {
00529 the_display->render_error_base = 0;
00530 the_display->render_event_base = 0;
00531 }
00532 else
00533 the_display->have_render = TRUE;
00534
00535 meta_verbose ("Attempted to init Render, found error base %d event base %d\n",
00536 the_display->render_error_base,
00537 the_display->render_event_base);
00538 }
00539 #else
00540 meta_verbose ("Not compiled with Render support\n");
00541 #endif
00542
00543 #ifdef HAVE_COMPOSITE_EXTENSIONS
00544 {
00545 the_display->have_composite = FALSE;
00546
00547 the_display->composite_error_base = 0;
00548 the_display->composite_event_base = 0;
00549
00550 if (!XCompositeQueryExtension (the_display->xdisplay,
00551 &the_display->composite_event_base,
00552 &the_display->composite_error_base))
00553 {
00554 the_display->composite_error_base = 0;
00555 the_display->composite_event_base = 0;
00556 }
00557 else
00558 {
00559 the_display->composite_major_version = 0;
00560 the_display->composite_minor_version = 0;
00561 if (XCompositeQueryVersion (the_display->xdisplay,
00562 &the_display->composite_major_version,
00563 &the_display->composite_minor_version))
00564 {
00565 the_display->have_composite = TRUE;
00566 }
00567 else
00568 {
00569 the_display->composite_major_version = 0;
00570 the_display->composite_minor_version = 0;
00571 }
00572 }
00573
00574 meta_verbose ("Attempted to init Composite, found error base %d event base %d "
00575 "extn ver %d %d\n",
00576 the_display->composite_error_base,
00577 the_display->composite_event_base,
00578 the_display->composite_major_version,
00579 the_display->composite_minor_version);
00580
00581 the_display->have_damage = FALSE;
00582
00583 the_display->damage_error_base = 0;
00584 the_display->damage_event_base = 0;
00585
00586 if (!XDamageQueryExtension (the_display->xdisplay,
00587 &the_display->damage_event_base,
00588 &the_display->damage_error_base))
00589 {
00590 the_display->damage_error_base = 0;
00591 the_display->damage_event_base = 0;
00592 }
00593 else
00594 the_display->have_damage = TRUE;
00595
00596 meta_verbose ("Attempted to init Damage, found error base %d event base %d\n",
00597 the_display->damage_error_base,
00598 the_display->damage_event_base);
00599
00600 the_display->have_xfixes = FALSE;
00601
00602 the_display->xfixes_error_base = 0;
00603 the_display->xfixes_event_base = 0;
00604
00605 if (!XFixesQueryExtension (the_display->xdisplay,
00606 &the_display->xfixes_event_base,
00607 &the_display->xfixes_error_base))
00608 {
00609 the_display->xfixes_error_base = 0;
00610 the_display->xfixes_event_base = 0;
00611 }
00612 else
00613 the_display->have_xfixes = TRUE;
00614
00615 meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n",
00616 the_display->xfixes_error_base,
00617 the_display->xfixes_event_base);
00618 }
00619 #else
00620 meta_verbose ("Not compiled with Composite support\n");
00621 #endif
00622
00623 #ifdef HAVE_XCURSOR
00624 {
00625 XcursorSetTheme (the_display->xdisplay, meta_prefs_get_cursor_theme ());
00626 XcursorSetDefaultSize (the_display->xdisplay, meta_prefs_get_cursor_size ());
00627 }
00628 #else
00629 meta_verbose ("Not compiled with Xcursor support\n");
00630 #endif
00631
00632
00633
00634
00635
00636 {
00637 gulong data[1];
00638 XEvent event;
00639
00640
00641
00642
00643
00644
00645 the_display->leader_window =
00646 meta_create_offscreen_window (the_display->xdisplay,
00647 DefaultRootWindow (the_display->xdisplay),
00648 PropertyChangeMask);
00649
00650 meta_prop_set_utf8_string_hint (the_display,
00651 the_display->leader_window,
00652 the_display->atom__NET_WM_NAME,
00653 "Metacity");
00654
00655 meta_prop_set_utf8_string_hint (the_display,
00656 the_display->leader_window,
00657 the_display->atom__METACITY_VERSION,
00658 VERSION);
00659
00660 data[0] = the_display->leader_window;
00661 XChangeProperty (the_display->xdisplay,
00662 the_display->leader_window,
00663 the_display->atom__NET_SUPPORTING_WM_CHECK,
00664 XA_WINDOW,
00665 32, PropModeReplace, (guchar*) data, 1);
00666
00667 XWindowEvent (the_display->xdisplay,
00668 the_display->leader_window,
00669 PropertyChangeMask,
00670 &event);
00671
00672 timestamp = event.xproperty.time;
00673
00674
00675
00676
00677 XSelectInput(the_display->xdisplay,
00678 the_display->leader_window,
00679 NoEventMask);
00680 }
00681
00682
00683
00684
00685 the_display->timestamp_pinging_window =
00686 meta_create_offscreen_window (the_display->xdisplay,
00687 DefaultRootWindow (the_display->xdisplay),
00688 PropertyChangeMask);
00689
00690 the_display->last_focus_time = timestamp;
00691 the_display->last_user_time = timestamp;
00692 the_display->compositor = NULL;
00693
00694 screens = NULL;
00695
00696 i = 0;
00697 while (i < ScreenCount (xdisplay))
00698 {
00699 MetaScreen *screen;
00700
00701 screen = meta_screen_new (the_display, i, timestamp);
00702
00703 if (screen)
00704 screens = g_slist_prepend (screens, screen);
00705 ++i;
00706 }
00707
00708 the_display->screens = screens;
00709
00710 if (screens == NULL)
00711 {
00712
00713
00714
00715 meta_display_close (the_display, timestamp);
00716 return FALSE;
00717 }
00718
00719
00720
00721
00722 if (meta_prefs_get_compositing_manager ())
00723 enable_compositor (the_display, FALSE);
00724
00725 meta_display_grab (the_display);
00726
00727
00728 tmp = the_display->screens;
00729 while (tmp != NULL)
00730 {
00731 MetaScreen *screen = tmp->data;
00732
00733 meta_screen_manage_all_windows (screen);
00734
00735 tmp = tmp->next;
00736 }
00737
00738 {
00739 Window focus;
00740 int ret_to;
00741
00742
00743 meta_error_trap_push (the_display);
00744
00745
00746 focus = None;
00747 ret_to = RevertToPointerRoot;
00748 XGetInputFocus (the_display->xdisplay, &focus, &ret_to);
00749
00750
00751
00752
00753
00754
00755 if (focus == None || focus == PointerRoot)
00756
00757 meta_display_focus_the_no_focus_window (the_display,
00758 the_display->screens->data,
00759 timestamp);
00760 else
00761 {
00762 MetaWindow * window;
00763 window = meta_display_lookup_x_window (the_display, focus);
00764 if (window)
00765 meta_display_set_input_focus_window (the_display, window, FALSE, timestamp);
00766 else
00767
00768 meta_display_focus_the_no_focus_window (the_display,
00769 the_display->screens->data,
00770 timestamp);
00771 }
00772
00773 meta_error_trap_pop (the_display, FALSE);
00774 }
00775
00776 meta_display_ungrab (the_display);
00777
00778
00779 the_display->display_opening = FALSE;
00780
00781 return TRUE;
00782 }
00783
00784 static void
00785 listify_func (gpointer key, gpointer value, gpointer data)
00786 {
00787 GSList **listp;
00788
00789 listp = data;
00790 *listp = g_slist_prepend (*listp, value);
00791 }
00792
00793 static gint
00794 ptrcmp (gconstpointer a, gconstpointer b)
00795 {
00796 if (a < b)
00797 return -1;
00798 else if (a > b)
00799 return 1;
00800 else
00801 return 0;
00802 }
00803
00804 GSList*
00805 meta_display_list_windows (MetaDisplay *display)
00806 {
00807 GSList *winlist;
00808 GSList *tmp;
00809 GSList *prev;
00810
00811 winlist = NULL;
00812 g_hash_table_foreach (display->window_ids,
00813 listify_func,
00814 &winlist);
00815
00816
00817
00818
00819 winlist = g_slist_sort (winlist, ptrcmp);
00820
00821 prev = NULL;
00822 tmp = winlist;
00823 while (tmp != NULL)
00824 {
00825 GSList *next;
00826
00827 next = tmp->next;
00828
00829 if (next &&
00830 next->data == tmp->data)
00831 {
00832
00833
00834 if (prev)
00835 prev->next = next;
00836
00837 if (tmp == winlist)
00838 winlist = next;
00839
00840 g_slist_free_1 (tmp);
00841
00842
00843 }
00844 else
00845 {
00846 prev = tmp;
00847 }
00848
00849 tmp = next;
00850 }
00851
00852 return winlist;
00853 }
00854
00855 void
00856 meta_display_close (MetaDisplay *display,
00857 guint32 timestamp)
00858 {
00859 GSList *tmp;
00860
00861 g_assert (display != NULL);
00862
00863 if (display->closing != 0)
00864 {
00865
00866 return;
00867 }
00868
00869 if (display->error_traps > 0)
00870 meta_bug ("Display closed with error traps pending\n");
00871
00872 display->closing += 1;
00873
00874 meta_prefs_remove_listener (prefs_changed_callback, display);
00875
00876 meta_display_remove_autoraise_callback (display);
00877
00878 if (display->grab_old_window_stacking)
00879 g_list_free (display->grab_old_window_stacking);
00880
00881
00882 meta_ui_remove_event_func (display->xdisplay,
00883 event_callback,
00884 display);
00885
00886
00887 tmp = display->screens;
00888 while (tmp != NULL)
00889 {
00890 MetaScreen *screen = tmp->data;
00891 meta_screen_free (screen, timestamp);
00892 tmp = tmp->next;
00893 }
00894
00895 g_slist_free (display->screens);
00896 display->screens = NULL;
00897
00898 #ifdef HAVE_STARTUP_NOTIFICATION
00899 if (display->sn_display)
00900 {
00901 sn_display_unref (display->sn_display);
00902 display->sn_display = NULL;
00903 }
00904 #endif
00905
00906
00907
00908
00909 g_hash_table_destroy (display->window_ids);
00910
00911 if (display->leader_window != None)
00912 XDestroyWindow (display->xdisplay, display->leader_window);
00913
00914 XFlush (display->xdisplay);
00915
00916 meta_display_free_window_prop_hooks (display);
00917 meta_display_free_group_prop_hooks (display);
00918
00919 g_free (display->name);
00920
00921 meta_display_shutdown_keys (display);
00922
00923 if (display->compositor)
00924 meta_compositor_destroy (display->compositor);
00925
00926 g_free (display);
00927 display = NULL;
00928
00929 meta_quit (META_EXIT_SUCCESS);
00930 }
00931
00932 MetaScreen*
00933 meta_display_screen_for_root (MetaDisplay *display,
00934 Window xroot)
00935 {
00936 GSList *tmp;
00937
00938 tmp = display->screens;
00939 while (tmp != NULL)
00940 {
00941 MetaScreen *screen = tmp->data;
00942
00943 if (xroot == screen->xroot)
00944 return screen;
00945
00946 tmp = tmp->next;
00947 }
00948
00949 return NULL;
00950 }
00951
00952 MetaScreen*
00953 meta_display_screen_for_xwindow (MetaDisplay *display,
00954 Window xwindow)
00955 {
00956 XWindowAttributes attr;
00957 int result;
00958
00959 meta_error_trap_push (display);
00960 attr.screen = NULL;
00961 result = XGetWindowAttributes (display->xdisplay, xwindow, &attr);
00962 meta_error_trap_pop (display, TRUE);
00963
00964
00965
00966
00967
00968 if (result == 0 || attr.screen == NULL)
00969 return NULL;
00970
00971 return meta_display_screen_for_x_screen (display, attr.screen);
00972 }
00973
00974 MetaScreen*
00975 meta_display_screen_for_x_screen (MetaDisplay *display,
00976 Screen *xscreen)
00977 {
00978 GSList *tmp;
00979
00980 tmp = display->screens;
00981 while (tmp != NULL)
00982 {
00983 MetaScreen *screen = tmp->data;
00984
00985 if (xscreen == screen->xscreen)
00986 return screen;
00987
00988 tmp = tmp->next;
00989 }
00990
00991 return NULL;
00992 }
00993
00994
00995 void
00996 meta_display_grab (MetaDisplay *display)
00997 {
00998 if (display->server_grab_count == 0)
00999 {
01000 XGrabServer (display->xdisplay);
01001 }
01002 display->server_grab_count += 1;
01003 meta_verbose ("Grabbing display, grab count now %d\n",
01004 display->server_grab_count);
01005 }
01006
01007 void
01008 meta_display_ungrab (MetaDisplay *display)
01009 {
01010 if (display->server_grab_count == 0)
01011 meta_bug ("Ungrabbed non-grabbed server\n");
01012
01013 display->server_grab_count -= 1;
01014 if (display->server_grab_count == 0)
01015 {
01016
01017
01018
01019 XUngrabServer (display->xdisplay);
01020 XFlush (display->xdisplay);
01021 }
01022
01023 meta_verbose ("Ungrabbing display, grab count now %d\n",
01024 display->server_grab_count);
01025 }
01026
01038 MetaDisplay*
01039 meta_display_for_x_display (Display *xdisplay)
01040 {
01041 if (the_display->xdisplay == xdisplay)
01042 return the_display;
01043
01044 meta_warning ("Could not find display for X display %p, probably going to crash\n",
01045 xdisplay);
01046
01047 return NULL;
01048 }
01049
01056 MetaDisplay*
01057 meta_get_display (void)
01058 {
01059 return the_display;
01060 }
01061
01062 #ifdef WITH_VERBOSE_MODE
01063 static gboolean dump_events = TRUE;
01064 #endif
01065
01066 static gboolean
01067 grab_op_is_mouse_only (MetaGrabOp op)
01068 {
01069 switch (op)
01070 {
01071 case META_GRAB_OP_MOVING:
01072 case META_GRAB_OP_RESIZING_SE:
01073 case META_GRAB_OP_RESIZING_S:
01074 case META_GRAB_OP_RESIZING_SW:
01075 case META_GRAB_OP_RESIZING_N:
01076 case META_GRAB_OP_RESIZING_NE:
01077 case META_GRAB_OP_RESIZING_NW:
01078 case META_GRAB_OP_RESIZING_W:
01079 case META_GRAB_OP_RESIZING_E:
01080 return TRUE;
01081
01082 default:
01083 return FALSE;
01084 }
01085 }
01086
01087 static gboolean
01088 grab_op_is_mouse (MetaGrabOp op)
01089 {
01090 switch (op)
01091 {
01092 case META_GRAB_OP_MOVING:
01093 case META_GRAB_OP_RESIZING_SE:
01094 case META_GRAB_OP_RESIZING_S:
01095 case META_GRAB_OP_RESIZING_SW:
01096 case META_GRAB_OP_RESIZING_N:
01097 case META_GRAB_OP_RESIZING_NE:
01098 case META_GRAB_OP_RESIZING_NW:
01099 case META_GRAB_OP_RESIZING_W:
01100 case META_GRAB_OP_RESIZING_E:
01101 case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
01102 case META_GRAB_OP_KEYBOARD_RESIZING_S:
01103 case META_GRAB_OP_KEYBOARD_RESIZING_N:
01104 case META_GRAB_OP_KEYBOARD_RESIZING_W:
01105 case META_GRAB_OP_KEYBOARD_RESIZING_E:
01106 case META_GRAB_OP_KEYBOARD_RESIZING_SE:
01107 case META_GRAB_OP_KEYBOARD_RESIZING_NE:
01108 case META_GRAB_OP_KEYBOARD_RESIZING_SW:
01109 case META_GRAB_OP_KEYBOARD_RESIZING_NW:
01110 case META_GRAB_OP_KEYBOARD_MOVING:
01111 return TRUE;
01112
01113 default:
01114 return FALSE;
01115 }
01116 }
01117
01118 static gboolean
01119 grab_op_is_keyboard (MetaGrabOp op)
01120 {
01121 switch (op)
01122 {
01123 case META_GRAB_OP_KEYBOARD_MOVING:
01124 case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
01125 case META_GRAB_OP_KEYBOARD_RESIZING_S:
01126 case META_GRAB_OP_KEYBOARD_RESIZING_N:
01127 case META_GRAB_OP_KEYBOARD_RESIZING_W:
01128 case META_GRAB_OP_KEYBOARD_RESIZING_E:
01129 case META_GRAB_OP_KEYBOARD_RESIZING_SE:
01130 case META_GRAB_OP_KEYBOARD_RESIZING_NE:
01131 case META_GRAB_OP_KEYBOARD_RESIZING_SW:
01132 case META_GRAB_OP_KEYBOARD_RESIZING_NW:
01133 case META_GRAB_OP_KEYBOARD_TABBING_NORMAL:
01134 case META_GRAB_OP_KEYBOARD_TABBING_DOCK:
01135 case META_GRAB_OP_KEYBOARD_TABBING_GROUP:
01136 case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL:
01137 case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK:
01138 case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP:
01139 case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING:
01140 return TRUE;
01141
01142 default:
01143 return FALSE;
01144 }
01145 }
01146
01147 gboolean
01148 meta_grab_op_is_resizing (MetaGrabOp op)
01149 {
01150 switch (op)
01151 {
01152 case META_GRAB_OP_RESIZING_SE:
01153 case META_GRAB_OP_RESIZING_S:
01154 case META_GRAB_OP_RESIZING_SW:
01155 case META_GRAB_OP_RESIZING_N:
01156 case META_GRAB_OP_RESIZING_NE:
01157 case META_GRAB_OP_RESIZING_NW:
01158 case META_GRAB_OP_RESIZING_W:
01159 case META_GRAB_OP_RESIZING_E:
01160 case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
01161 case META_GRAB_OP_KEYBOARD_RESIZING_S:
01162 case META_GRAB_OP_KEYBOARD_RESIZING_N:
01163 case META_GRAB_OP_KEYBOARD_RESIZING_W:
01164 case META_GRAB_OP_KEYBOARD_RESIZING_E:
01165 case META_GRAB_OP_KEYBOARD_RESIZING_SE:
01166 case META_GRAB_OP_KEYBOARD_RESIZING_NE:
01167 case META_GRAB_OP_KEYBOARD_RESIZING_SW:
01168 case META_GRAB_OP_KEYBOARD_RESIZING_NW:
01169 return TRUE;
01170
01171 default:
01172 return FALSE;
01173 }
01174 }
01175
01176 gboolean
01177 meta_grab_op_is_moving (MetaGrabOp op)
01178 {
01179 switch (op)
01180 {
01181 case META_GRAB_OP_MOVING:
01182 case META_GRAB_OP_KEYBOARD_MOVING:
01183 return TRUE;
01184
01185 default:
01186 return FALSE;
01187 }
01188 }
01189
01190
01191 guint32
01192 meta_display_get_current_time (MetaDisplay *display)
01193 {
01194 return display->current_time;
01195 }
01196
01197
01198 guint32
01199 meta_display_get_current_time_roundtrip (MetaDisplay *display)
01200 {
01201 guint32 timestamp;
01202
01203 timestamp = meta_display_get_current_time (display);
01204 if (timestamp == CurrentTime)
01205 {
01206 XEvent property_event;
01207
01208
01209
01210
01211 XChangeProperty (display->xdisplay,
01212 display->timestamp_pinging_window,
01213 XA_PRIMARY, XA_STRING, 8,
01214 PropModeAppend, NULL, 0);
01215 XWindowEvent (display->xdisplay,
01216 display->timestamp_pinging_window,
01217 PropertyChangeMask,
01218 &property_event);
01219 timestamp = property_event.xproperty.time;
01220 }
01221
01222 sanity_check_timestamps (display, timestamp);
01223
01224 return timestamp;
01225 }
01226
01227 static void
01228 add_ignored_serial (MetaDisplay *display,
01229 unsigned long serial)
01230 {
01231 int i;
01232
01233
01234 if (display->ignored_serials[N_IGNORED_SERIALS-1] == serial)
01235 return;
01236
01237
01238 i = 0;
01239 while (i < (N_IGNORED_SERIALS - 1))
01240 {
01241 display->ignored_serials[i] = display->ignored_serials[i+1];
01242 ++i;
01243 }
01244
01245 display->ignored_serials[i] = serial;
01246 }
01247
01248 static gboolean
01249 serial_is_ignored (MetaDisplay *display,
01250 unsigned long serial)
01251 {
01252 int i;
01253
01254 i = 0;
01255 while (i < N_IGNORED_SERIALS)
01256 {
01257 if (display->ignored_serials[i] == serial)
01258 return TRUE;
01259 ++i;
01260 }
01261 return FALSE;
01262 }
01263
01264 static void
01265 reset_ignores (MetaDisplay *display)
01266 {
01267 int i;
01268
01269 i = 0;
01270 while (i < N_IGNORED_SERIALS)
01271 {
01272 display->ignored_serials[i] = 0;
01273 ++i;
01274 }
01275
01276 display->ungrab_should_not_cause_focus_window = None;
01277 }
01278
01279 static gboolean
01280 window_raise_with_delay_callback (void *data)
01281 {
01282 MetaWindow *window;
01283 MetaAutoRaiseData *auto_raise;
01284
01285 auto_raise = data;
01286
01287 meta_topic (META_DEBUG_FOCUS,
01288 "In autoraise callback for window 0x%lx\n",
01289 auto_raise->xwindow);
01290
01291 auto_raise->display->autoraise_timeout_id = 0;
01292 auto_raise->display->autoraise_window = NULL;
01293
01294 window = meta_display_lookup_x_window (auto_raise->display,
01295 auto_raise->xwindow);
01296
01297 if (window == NULL)
01298 return FALSE;
01299
01300
01301
01302
01303 if (meta_stack_get_top (window->screen->stack) != window)
01304 {
01305 int x, y, root_x, root_y;
01306 Window root, child;
01307 unsigned int mask;
01308 gboolean same_screen;
01309 gboolean point_in_window;
01310
01311 meta_error_trap_push (window->display);
01312 same_screen = XQueryPointer (window->display->xdisplay,
01313 window->xwindow,
01314 &root, &child,
01315 &root_x, &root_y, &x, &y, &mask);
01316 meta_error_trap_pop (window->display, TRUE);
01317
01318 point_in_window =
01319 (window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) ||
01320 (window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect));
01321 if (same_screen && point_in_window)
01322 meta_window_raise (window);
01323 else
01324 meta_topic (META_DEBUG_FOCUS,
01325 "Pointer not inside window, not raising %s\n",
01326 window->desc);
01327 }
01328
01329 return FALSE;
01330 }
01331
01332 void
01333 meta_display_queue_autoraise_callback (MetaDisplay *display,
01334 MetaWindow *window)
01335 {
01336 MetaAutoRaiseData *auto_raise_data;
01337
01338 meta_topic (META_DEBUG_FOCUS,
01339 "Queuing an autoraise timeout for %s with delay %d\n",
01340 window->desc,
01341 meta_prefs_get_auto_raise_delay ());
01342
01343 auto_raise_data = g_new (MetaAutoRaiseData, 1);
01344 auto_raise_data->display = window->display;
01345 auto_raise_data->xwindow = window->xwindow;
01346
01347 if (display->autoraise_timeout_id != 0)
01348 g_source_remove (display->autoraise_timeout_id);
01349
01350 display->autoraise_timeout_id =
01351 g_timeout_add_full (G_PRIORITY_DEFAULT,
01352 meta_prefs_get_auto_raise_delay (),
01353 window_raise_with_delay_callback,
01354 auto_raise_data,
01355 g_free);
01356 display->autoraise_window = window;
01357 }
01358
01359 #if 0
01360 static void
01361 handle_net_restack_window (MetaDisplay* display,
01362 XEvent *event)
01363 {
01364 MetaWindow *window;
01365
01366 window = meta_display_lookup_x_window (display,
01367 event->xclient.window);
01368
01369 if (window)
01370 {
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380 switch (event->xclient.data.l[2])
01381 {
01382 case Above:
01383 meta_window_raise (window);
01384 break;
01385 case Below:
01386 meta_window_lower (window);
01387 break;
01388 case TopIf:
01389 case BottomIf:
01390 case Opposite:
01391 break;
01392 }
01393 }
01394 }
01395 #endif
01396
01412 static gboolean
01413 event_callback (XEvent *event,
01414 gpointer data)
01415 {
01416 MetaWindow *window;
01417 MetaWindow *property_for_window;
01418 MetaDisplay *display;
01419 Window modified;
01420 gboolean frame_was_receiver;
01421 gboolean filter_out_event;
01422
01423 display = data;
01424
01425 #ifdef WITH_VERBOSE_MODE
01426 if (dump_events)
01427 meta_spew_event (display, event);
01428 #endif
01429
01430 #ifdef HAVE_STARTUP_NOTIFICATION
01431 sn_display_process_event (display->sn_display, event);
01432 #endif
01433
01434 filter_out_event = FALSE;
01435 display->current_time = event_get_time (display, event);
01436 display->xinerama_cache_invalidated = TRUE;
01437
01438 modified = event_get_modified_window (display, event);
01439
01440 if (event->type == ButtonPress)
01441 {
01442
01443 if (event->xbutton.button == 4 ||
01444 event->xbutton.button == 5)
01445 return FALSE;
01446 }
01447 else if (event->type == UnmapNotify)
01448 {
01449 if (meta_ui_window_should_not_cause_focus (display->xdisplay,
01450 modified))
01451 {
01452 add_ignored_serial (display, event->xany.serial);
01453 meta_topic (META_DEBUG_FOCUS,
01454 "Adding EnterNotify serial %lu to ignored focus serials\n",
01455 event->xany.serial);
01456 }
01457 }
01458 else if (event->type == LeaveNotify &&
01459 event->xcrossing.mode == NotifyUngrab &&
01460 modified == display->ungrab_should_not_cause_focus_window)
01461 {
01462 add_ignored_serial (display, event->xany.serial);
01463 meta_topic (META_DEBUG_FOCUS,
01464 "Adding LeaveNotify serial %lu to ignored focus serials\n",
01465 event->xany.serial);
01466 }
01467
01468 if (modified != None)
01469 window = meta_display_lookup_x_window (display, modified);
01470 else
01471 window = NULL;
01472
01473
01474
01475
01476
01477 property_for_window = NULL;
01478 if (window && modified == window->user_time_window)
01479 {
01480 property_for_window = window;
01481 window = NULL;
01482 }
01483
01484
01485 frame_was_receiver = FALSE;
01486 if (window &&
01487 window->frame &&
01488 modified == window->frame->xwindow)
01489 {
01490
01491
01492
01493
01494 frame_was_receiver = TRUE;
01495 meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n",
01496 window->desc);
01497 }
01498
01499 #ifdef HAVE_XSYNC
01500 if (META_DISPLAY_HAS_XSYNC (display) &&
01501 event->type == (display->xsync_event_base + XSyncAlarmNotify) &&
01502 ((XSyncAlarmNotifyEvent*)event)->alarm == display->grab_sync_request_alarm)
01503 {
01504 filter_out_event = TRUE;
01505
01506 if (display->grab_op != META_GRAB_OP_NONE &&
01507 display->grab_window != NULL &&
01508 grab_op_is_mouse (display->grab_op))
01509 meta_window_handle_mouse_grab_op_event (display->grab_window, event);
01510 }
01511 #endif
01512
01513 #ifdef HAVE_SHAPE
01514 if (META_DISPLAY_HAS_SHAPE (display) &&
01515 event->type == (display->shape_event_base + ShapeNotify))
01516 {
01517 filter_out_event = TRUE;
01518
01519 if (window && !frame_was_receiver)
01520 {
01521 XShapeEvent *sev = (XShapeEvent*) event;
01522
01523 if (sev->kind == ShapeBounding)
01524 {
01525 if (sev->shaped && !window->has_shape)
01526 {
01527 window->has_shape = TRUE;
01528 meta_topic (META_DEBUG_SHAPES,
01529 "Window %s now has a shape\n",
01530 window->desc);
01531 }
01532 else if (!sev->shaped && window->has_shape)
01533 {
01534 window->has_shape = FALSE;
01535 meta_topic (META_DEBUG_SHAPES,
01536 "Window %s no longer has a shape\n",
01537 window->desc);
01538 }
01539 else
01540 {
01541 meta_topic (META_DEBUG_SHAPES,
01542 "Window %s shape changed\n",
01543 window->desc);
01544 }
01545
01546 if (window->frame)
01547 {
01548 window->frame->need_reapply_frame_shape = TRUE;
01549 meta_warning("from event callback\n");
01550 meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
01551 }
01552 }
01553 }
01554 else
01555 {
01556 meta_topic (META_DEBUG_SHAPES,
01557 "ShapeNotify not on a client window (window %s frame_was_receiver = %d)\n",
01558 window ? window->desc : "(none)",
01559 frame_was_receiver);
01560 }
01561 }
01562 #endif
01563
01564 if (window && ((event->type == KeyPress) || (event->type == ButtonPress)))
01565 {
01566 if (CurrentTime == display->current_time)
01567 {
01568
01569
01570
01571
01572 meta_warning ("Event has no timestamp! You may be using a broken "
01573 "program such as xse. Please ask the authors of that "
01574 "program to fix it.\n");
01575 }
01576 else
01577 {
01578 meta_window_set_user_time (window, display->current_time);
01579 sanity_check_timestamps (display, display->current_time);
01580 }
01581 }
01582
01583 switch (event->type)
01584 {
01585 case KeyPress:
01586 case KeyRelease:
01587 meta_display_process_key_event (display, window, event);
01588 break;
01589 case ButtonPress:
01590 if ((window &&
01591 grab_op_is_mouse (display->grab_op) &&
01592 display->grab_button != (int) event->xbutton.button &&
01593 display->grab_window == window) ||
01594 grab_op_is_keyboard (display->grab_op))
01595 {
01596 meta_topic (META_DEBUG_WINDOW_OPS,
01597 "Ending grab op %u on window %s due to button press\n",
01598 display->grab_op,
01599 (display->grab_window ?
01600 display->grab_window->desc :
01601 "none"));
01602 if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
01603 {
01604 MetaScreen *screen;
01605 meta_topic (META_DEBUG_WINDOW_OPS,
01606 "Syncing to old stack positions.\n");
01607 screen =
01608 meta_display_screen_for_root (display, event->xany.window);
01609
01610 if (screen!=NULL)
01611 meta_stack_set_positions (screen->stack,
01612 display->grab_old_window_stacking);
01613 }
01614 meta_display_end_grab_op (display,
01615 event->xbutton.time);
01616 }
01617 else if (window && display->grab_op == META_GRAB_OP_NONE)
01618 {
01619 gboolean begin_move = FALSE;
01620 unsigned int grab_mask;
01621 gboolean unmodified;
01622
01623 grab_mask = display->window_grab_modifiers;
01624 if (g_getenv ("METACITY_DEBUG_BUTTON_GRABS"))
01625 grab_mask |= ControlMask;
01626
01627
01628
01629
01630
01631
01632 unmodified = (event->xbutton.state & grab_mask) == 0;
01633
01634 if (unmodified ||
01635 event->xbutton.button == 1)
01636 {
01637
01638
01639
01640
01641 if (!frame_was_receiver)
01642 {
01643 if (meta_prefs_get_raise_on_click ())
01644 meta_window_raise (window);
01645 else
01646 meta_topic (META_DEBUG_FOCUS,
01647 "Not raising window on click due to don't-raise-on-click option\n");
01648
01649
01650
01651
01652 if (window->type != META_WINDOW_DOCK)
01653 {
01654 meta_topic (META_DEBUG_FOCUS,
01655 "Focusing %s due to unmodified button %u press (display.c)\n",
01656 window->desc, event->xbutton.button);
01657 meta_window_focus (window, event->xbutton.time);
01658 }
01659 else
01660
01661
01662
01663 display->allow_terminal_deactivation = TRUE;
01664 }
01665
01666
01667
01668
01669 if (!unmodified)
01670 begin_move = TRUE;
01671 }
01672 else if (!unmodified && event->xbutton.button == 2)
01673 {
01674 if (window->has_resize_func)
01675 {
01676 gboolean north, south;
01677 gboolean west, east;
01678 int root_x, root_y;
01679 MetaGrabOp op;
01680
01681 meta_window_get_position (window, &root_x, &root_y);
01682
01683 west = event->xbutton.x_root < (root_x + 1 * window->rect.width / 3);
01684 east = event->xbutton.x_root > (root_x + 2 * window->rect.width / 3);
01685 north = event->xbutton.y_root < (root_y + 1 * window->rect.height / 3);
01686 south = event->xbutton.y_root > (root_y + 2 * window->rect.height / 3);
01687
01688 if (north && west)
01689 op = META_GRAB_OP_RESIZING_NW;
01690 else if (north && east)
01691 op = META_GRAB_OP_RESIZING_NE;
01692 else if (south && west)
01693 op = META_GRAB_OP_RESIZING_SW;
01694 else if (south && east)
01695 op = META_GRAB_OP_RESIZING_SE;
01696 else if (north)
01697 op = META_GRAB_OP_RESIZING_N;
01698 else if (west)
01699 op = META_GRAB_OP_RESIZING_W;
01700 else if (east)
01701 op = META_GRAB_OP_RESIZING_E;
01702 else if (south)
01703 op = META_GRAB_OP_RESIZING_S;
01704 else
01705 op = META_GRAB_OP_NONE;
01706
01707 if (op != META_GRAB_OP_NONE)
01708 meta_display_begin_grab_op (display,
01709 window->screen,
01710 window,
01711 op,
01712 TRUE,
01713 FALSE,
01714 event->xbutton.button,
01715 0,
01716 event->xbutton.time,
01717 event->xbutton.x_root,
01718 event->xbutton.y_root);
01719 }
01720 }
01721 else if (event->xbutton.button == 3)
01722 {
01723 if (meta_prefs_get_raise_on_click ())
01724 meta_window_raise (window);
01725 meta_window_show_menu (window,
01726 event->xbutton.x_root,
01727 event->xbutton.y_root,
01728 event->xbutton.button,
01729 event->xbutton.time);
01730 }
01731
01732 if (!frame_was_receiver && unmodified)
01733 {
01734
01735
01736
01737 int mode;
01738
01739
01740
01741
01742
01743 if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
01744 meta_prefs_get_application_based () &&
01745 !window->has_focus &&
01746 window->type != META_WINDOW_DOCK &&
01747 window->type != META_WINDOW_DESKTOP &&
01748 (display->focus_window == NULL ||
01749 !meta_window_same_application (window,
01750 display->focus_window)))
01751 mode = AsyncPointer;
01752 else
01753 mode = ReplayPointer;
01754
01755 meta_verbose ("Allowing events mode %s time %u\n",
01756 mode == AsyncPointer ? "AsyncPointer" : "ReplayPointer",
01757 (unsigned int)event->xbutton.time);
01758
01759 XAllowEvents (display->xdisplay,
01760 mode, event->xbutton.time);
01761 }
01762
01763 if (begin_move && window->has_move_func)
01764 {
01765 meta_display_begin_grab_op (display,
01766 window->screen,
01767 window,
01768 META_GRAB_OP_MOVING,
01769 TRUE,
01770 FALSE,
01771 event->xbutton.button,
01772 0,
01773 event->xbutton.time,
01774 event->xbutton.x_root,
01775 event->xbutton.y_root);
01776 }
01777 }
01778 break;
01779 case ButtonRelease:
01780 if (display->grab_window == window &&
01781 grab_op_is_mouse (display->grab_op))
01782 meta_window_handle_mouse_grab_op_event (window, event);
01783 break;
01784 case MotionNotify:
01785 if (display->grab_window == window &&
01786 grab_op_is_mouse (display->grab_op))
01787 meta_window_handle_mouse_grab_op_event (window, event);
01788 break;
01789 case EnterNotify:
01790 if (display->grab_window == window &&
01791 grab_op_is_mouse (display->grab_op))
01792 {
01793 meta_window_handle_mouse_grab_op_event (window, event);
01794 break;
01795 }
01796
01797
01798
01799
01800
01801 {
01802 MetaScreen *new_screen =
01803 meta_display_screen_for_root (display, event->xcrossing.root);
01804
01805 if (new_screen != NULL && display->active_screen != new_screen)
01806 meta_workspace_focus_default_window (new_screen->active_workspace,
01807 NULL,
01808 event->xcrossing.time);
01809 }
01810
01811
01812
01813
01814 if (window && !serial_is_ignored (display, event->xany.serial) &&
01815 event->xcrossing.mode != NotifyGrab &&
01816 event->xcrossing.mode != NotifyUngrab &&
01817 event->xcrossing.detail != NotifyInferior &&
01818 meta_display_focus_sentinel_clear (display))
01819 {
01820 switch (meta_prefs_get_focus_mode ())
01821 {
01822 case META_FOCUS_MODE_SLOPPY:
01823 case META_FOCUS_MODE_MOUSE:
01824 display->mouse_mode = TRUE;
01825 if (window->type != META_WINDOW_DOCK &&
01826 window->type != META_WINDOW_DESKTOP)
01827 {
01828 meta_topic (META_DEBUG_FOCUS,
01829 "Focusing %s due to enter notify with serial %lu "
01830 "at time %lu, and setting display->mouse_mode to "
01831 "TRUE.\n",
01832 window->desc,
01833 event->xany.serial,
01834 event->xcrossing.time);
01835
01836 meta_window_focus (window, event->xcrossing.time);
01837
01838
01839 reset_ignores (display);
01840
01841 if (meta_prefs_get_auto_raise ())
01842 {
01843 meta_display_queue_autoraise_callback (display, window);
01844 }
01845 else
01846 {
01847 meta_topic (META_DEBUG_FOCUS,
01848 "Auto raise is disabled\n");
01849 }
01850 }
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860 if (window->type == META_WINDOW_DESKTOP &&
01861 meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE &&
01862 display->expected_focus_window != NULL)
01863 {
01864 meta_topic (META_DEBUG_FOCUS,
01865 "Unsetting focus from %s due to mouse entering "
01866 "the DESKTOP window\n",
01867 display->expected_focus_window->desc);
01868 meta_display_focus_the_no_focus_window (display,
01869 window->screen,
01870 event->xcrossing.time);
01871 }
01872 break;
01873 case META_FOCUS_MODE_CLICK:
01874 break;
01875 }
01876
01877 if (window->type == META_WINDOW_DOCK)
01878 meta_window_raise (window);
01879 }
01880 break;
01881 case LeaveNotify:
01882 if (display->grab_window == window &&
01883 grab_op_is_mouse (display->grab_op))
01884 meta_window_handle_mouse_grab_op_event (window, event);
01885 else if (window != NULL)
01886 {
01887 if (window->type == META_WINDOW_DOCK &&
01888 event->xcrossing.mode != NotifyGrab &&
01889 event->xcrossing.mode != NotifyUngrab &&
01890 !window->has_focus)
01891 meta_window_lower (window);
01892 }
01893 break;
01894 case FocusIn:
01895 case FocusOut:
01896 if (window)
01897 {
01898 meta_window_notify_focus (window, event);
01899 }
01900 else if (meta_display_xwindow_is_a_no_focus_window (display,
01901 event->xany.window))
01902 {
01903 meta_topic (META_DEBUG_FOCUS,
01904 "Focus %s event received on no_focus_window 0x%lx "
01905 "mode %s detail %s\n",
01906 event->type == FocusIn ? "in" :
01907 event->type == FocusOut ? "out" :
01908 "???",
01909 event->xany.window,
01910 meta_event_mode_to_string (event->xfocus.mode),
01911 meta_event_detail_to_string (event->xfocus.detail));
01912 }
01913 else
01914 {
01915 MetaScreen *screen =
01916 meta_display_screen_for_root(display,
01917 event->xany.window);
01918 if (screen == NULL)
01919 break;
01920
01921 meta_topic (META_DEBUG_FOCUS,
01922 "Focus %s event received on root window 0x%lx "
01923 "mode %s detail %s\n",
01924 event->type == FocusIn ? "in" :
01925 event->type == FocusOut ? "out" :
01926 "???",
01927 event->xany.window,
01928 meta_event_mode_to_string (event->xfocus.mode),
01929 meta_event_detail_to_string (event->xfocus.detail));
01930
01931 if (event->type == FocusIn &&
01932 event->xfocus.detail == NotifyDetailNone)
01933 {
01934 meta_topic (META_DEBUG_FOCUS,
01935 "Focus got set to None, probably due to "
01936 "brain-damage in the X protocol (see bug "
01937 "125492). Setting the default focus window.\n");
01938 meta_workspace_focus_default_window (screen->active_workspace,
01939 NULL,
01940 meta_display_get_current_time_roundtrip (display));
01941 }
01942 else if (event->type == FocusIn &&
01943 event->xfocus.mode == NotifyNormal &&
01944 event->xfocus.detail == NotifyInferior)
01945 {
01946 meta_topic (META_DEBUG_FOCUS,
01947 "Focus got set to root window, probably due to "
01948 "gnome-session logout dialog usage (see bug "
01949 "153220). Setting the default focus window.\n");
01950 meta_workspace_focus_default_window (screen->active_workspace,
01951 NULL,
01952 meta_display_get_current_time_roundtrip (display));
01953 }
01954
01955 }
01956 break;
01957 case KeymapNotify:
01958 break;
01959 case Expose:
01960 break;
01961 case GraphicsExpose:
01962 break;
01963 case NoExpose:
01964 break;
01965 case VisibilityNotify:
01966 break;
01967 case CreateNotify:
01968 break;
01969
01970 case DestroyNotify:
01971 if (window)
01972 {
01973
01974
01975
01976
01977 guint32 timestamp;
01978 timestamp = meta_display_get_current_time_roundtrip (display);
01979
01980 if (display->grab_op != META_GRAB_OP_NONE &&
01981 display->grab_window == window)
01982 meta_display_end_grab_op (display, timestamp);
01983
01984 if (frame_was_receiver)
01985 {
01986 meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n",
01987 window->frame->xwindow);
01988 meta_error_trap_push (display);
01989 meta_window_destroy_frame (window->frame->window);
01990 meta_error_trap_pop (display, FALSE);
01991 }
01992 else
01993 {
01994
01995 meta_window_free (window, timestamp);
01996 window = NULL;
01997 }
01998 }
01999 break;
02000 case UnmapNotify:
02001 if (window)
02002 {
02003
02004
02005
02006
02007 guint32 timestamp;
02008 timestamp = meta_display_get_current_time_roundtrip (display);
02009
02010 if (display->grab_op != META_GRAB_OP_NONE &&
02011 display->grab_window == window &&
02012 ((window->frame == NULL) || !window->frame->mapped))
02013 meta_display_end_grab_op (display, timestamp);
02014
02015 if (!frame_was_receiver)
02016 {
02017 if (window->unmaps_pending == 0)
02018 {
02019 meta_topic (META_DEBUG_WINDOW_STATE,
02020 "Window %s withdrawn\n",
02021 window->desc);
02022
02023 meta_effect_run_close (window, NULL, NULL);
02024
02025
02026 window->withdrawn = TRUE;
02027 meta_window_free (window, timestamp);
02028 window = NULL;
02029 }
02030 else
02031 {
02032 window->unmaps_pending -= 1;
02033 meta_topic (META_DEBUG_WINDOW_STATE,
02034 "Received pending unmap, %d now pending\n",
02035 window->unmaps_pending);
02036 }
02037 }
02038
02039
02040
02041
02042
02043 if (window)
02044 meta_window_notify_focus (window, event);
02045 }
02046 break;
02047 case MapNotify:
02048 break;
02049 case MapRequest:
02050 if (window == NULL)
02051 {
02052 window = meta_window_new (display, event->xmaprequest.window,
02053 FALSE);
02054 }
02055
02056 else if (!frame_was_receiver && window)
02057 {
02058 meta_verbose ("MapRequest on %s mapped = %d minimized = %d\n",
02059 window->desc, window->mapped, window->minimized);
02060 if (window->minimized)
02061 {
02062 meta_window_unminimize (window);
02063 if (window->workspace != window->screen->active_workspace)
02064 {
02065 meta_verbose ("Changing workspace due to MapRequest mapped = %d minimized = %d\n",
02066 window->mapped, window->minimized);
02067 meta_window_change_workspace (window,
02068 window->screen->active_workspace);
02069 }
02070 }
02071 }
02072 break;
02073 case ReparentNotify:
02074 break;
02075 case ConfigureNotify:
02076
02077 {
02078 MetaScreen *screen;
02079
02080 screen = meta_display_screen_for_root (display,
02081 event->xconfigure.window);
02082
02083 if (screen != NULL)
02084 {
02085 #ifdef HAVE_RANDR
02086
02087 XRRUpdateConfiguration (event);
02088 #else
02089
02090 screen->xscreen->width = event->xconfigure.width;
02091 screen->xscreen->height = event->xconfigure.height;
02092 #endif
02093
02094 meta_screen_resize (screen,
02095 event->xconfigure.width,
02096 event->xconfigure.height);
02097 }
02098 }
02099 break;
02100 case ConfigureRequest:
02101
02102
02103
02104
02105
02106
02107
02108 if (window == NULL)
02109 {
02110 unsigned int xwcm;
02111 XWindowChanges xwc;
02112
02113 xwcm = event->xconfigurerequest.value_mask &
02114 (CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
02115
02116 xwc.x = event->xconfigurerequest.x;
02117 xwc.y = event->xconfigurerequest.y;
02118 xwc.width = event->xconfigurerequest.width;
02119 xwc.height = event->xconfigurerequest.height;
02120 xwc.border_width = event->xconfigurerequest.border_width;
02121
02122 meta_verbose ("Configuring withdrawn window to %d,%d %dx%d border %d (some values may not be in mask)\n",
02123 xwc.x, xwc.y, xwc.width, xwc.height, xwc.border_width);
02124 meta_error_trap_push (display);
02125 XConfigureWindow (display->xdisplay, event->xconfigurerequest.window,
02126 xwcm, &xwc);
02127 meta_error_trap_pop (display, FALSE);
02128 }
02129 else
02130 {
02131 if (!frame_was_receiver)
02132 meta_window_configure_request (window, event);
02133 }
02134 break;
02135 case GravityNotify:
02136 break;
02137 case ResizeRequest:
02138 break;
02139 case CirculateNotify:
02140 break;
02141 case CirculateRequest:
02142 break;
02143 case PropertyNotify:
02144 {
02145 MetaGroup *group;
02146 MetaScreen *screen;
02147
02148 if (window && !frame_was_receiver)
02149 meta_window_property_notify (window, event);
02150 else if (property_for_window && !frame_was_receiver)
02151 meta_window_property_notify (property_for_window, event);
02152
02153 group = meta_display_lookup_group (display,
02154 event->xproperty.window);
02155 if (group != NULL)
02156 meta_group_property_notify (group, event);
02157
02158 screen = NULL;
02159 if (window == NULL &&
02160 group == NULL)
02161 screen = meta_display_screen_for_root (display,
02162 event->xproperty.window);
02163
02164 if (screen != NULL)
02165 {
02166 if (event->xproperty.atom ==
02167 display->atom__NET_DESKTOP_LAYOUT)
02168 meta_screen_update_workspace_layout (screen);
02169 else if (event->xproperty.atom ==
02170 display->atom__NET_DESKTOP_NAMES)
02171 meta_screen_update_workspace_names (screen);
02172 #if 0
02173 else if (event->xproperty.atom ==
02174 display->atom__NET_RESTACK_WINDOW)
02175 handle_net_restack_window (display, event);
02176 #endif
02177
02178
02179
02180
02181
02182 if (event->xproperty.atom ==
02183 display->atom__METACITY_SENTINEL)
02184 {
02185 meta_display_decrement_focus_sentinel (display);
02186 }
02187 }
02188 }
02189 break;
02190 case SelectionClear:
02191
02192
02193
02194
02195
02196
02197
02198 display->current_time = CurrentTime;
02199
02200 process_selection_clear (display, event);
02201
02202
02203
02204 return FALSE;
02205 case SelectionRequest:
02206 process_selection_request (display, event);
02207 break;
02208 case SelectionNotify:
02209 break;
02210 case ColormapNotify:
02211 if (window && !frame_was_receiver)
02212 window->colormap = event->xcolormap.colormap;
02213 break;
02214 case ClientMessage:
02215 if (window)
02216 {
02217 if (!frame_was_receiver)
02218 meta_window_client_message (window, event);
02219 }
02220 else
02221 {
02222 MetaScreen *screen;
02223
02224 screen = meta_display_screen_for_root (display,
02225 event->xclient.window);
02226
02227 if (screen)
02228 {
02229 if (event->xclient.message_type ==
02230 display->atom__NET_CURRENT_DESKTOP)
02231 {
02232 int space;
02233 MetaWorkspace *workspace;
02234 guint32 time;
02235
02236 space = event->xclient.data.l[0];
02237 time = event->xclient.data.l[1];
02238
02239 meta_verbose ("Request to change current workspace to %d with "
02240 "specified timestamp of %u\n",
02241 space, time);
02242
02243 workspace =
02244 meta_screen_get_workspace_by_index (screen,
02245 space);
02246
02247
02248 if (time == 0 && workspace)
02249 {
02250 meta_warning ("Received a NET_CURRENT_DESKTOP message "
02251 "from a broken (outdated) client who sent "
02252 "a 0 timestamp\n");
02253 time = meta_display_get_current_time_roundtrip (display);
02254 }
02255
02256 if (workspace)
02257 meta_workspace_activate (workspace, time);
02258 else
02259 meta_verbose ("Don't know about workspace %d\n", space);
02260 }
02261 else if (event->xclient.message_type ==
02262 display->atom__NET_NUMBER_OF_DESKTOPS)
02263 {
02264 int num_spaces;
02265
02266 num_spaces = event->xclient.data.l[0];
02267
02268 meta_verbose ("Request to set number of workspaces to %d\n",
02269 num_spaces);
02270
02271 meta_prefs_set_num_workspaces (num_spaces);
02272 }
02273 else if (event->xclient.message_type ==
02274 display->atom__NET_SHOWING_DESKTOP)
02275 {
02276 gboolean showing_desktop;
02277 guint32 timestamp;
02278
02279 showing_desktop = event->xclient.data.l[0] != 0;
02280
02281 timestamp = meta_display_get_current_time_roundtrip (display);
02282 meta_verbose ("Request to %s desktop\n",
02283 showing_desktop ? "show" : "hide");
02284
02285 if (showing_desktop)
02286 meta_screen_show_desktop (screen, timestamp);
02287 else
02288 {
02289 meta_screen_unshow_desktop (screen);
02290 meta_workspace_focus_default_window (screen->active_workspace, NULL, timestamp);
02291 }
02292 }
02293 else if (event->xclient.message_type ==
02294 display->atom__METACITY_RESTART_MESSAGE)
02295 {
02296 meta_verbose ("Received restart request\n");
02297 meta_restart ();
02298 }
02299 else if (event->xclient.message_type ==
02300 display->atom__METACITY_RELOAD_THEME_MESSAGE)
02301 {
02302 meta_verbose ("Received reload theme request\n");
02303 meta_ui_set_current_theme (meta_prefs_get_theme (),
02304 TRUE);
02305 meta_display_retheme_all ();
02306 }
02307 else if (event->xclient.message_type ==
02308 display->atom__METACITY_SET_KEYBINDINGS_MESSAGE)
02309 {
02310 meta_verbose ("Received set keybindings request = %d\n",
02311 (int) event->xclient.data.l[0]);
02312 meta_set_keybindings_disabled (!event->xclient.data.l[0]);
02313 }
02314 else if (event->xclient.message_type ==
02315 display->atom__METACITY_TOGGLE_VERBOSE)
02316 {
02317 meta_verbose ("Received toggle verbose message\n");
02318 meta_set_verbose (!meta_is_verbose ());
02319 }
02320 else if (event->xclient.message_type ==
02321 display->atom_WM_PROTOCOLS)
02322 {
02323 meta_verbose ("Received WM_PROTOCOLS message\n");
02324
02325 if ((Atom)event->xclient.data.l[0] == display->atom__NET_WM_PING)
02326 {
02327 process_pong_message (display, event);
02328
02329
02330
02331
02332
02333 filter_out_event = TRUE;
02334 }
02335 }
02336 }
02337
02338 if (event->xclient.message_type ==
02339 display->atom__NET_REQUEST_FRAME_EXTENTS)
02340 {
02341 meta_verbose ("Received _NET_REQUEST_FRAME_EXTENTS message\n");
02342 process_request_frame_extents (display, event);
02343 }
02344 }
02345 break;
02346 case MappingNotify:
02347 {
02348 gboolean ignore_current;
02349
02350 ignore_current = FALSE;
02351
02352
02353
02354
02355
02356 if (XPending (display->xdisplay))
02357 {
02358 XEvent next_event;
02359
02360 XPeekEvent (display->xdisplay, &next_event);
02361
02362 if (next_event.type == MappingNotify &&
02363 next_event.xmapping.request == event->xmapping.request)
02364 ignore_current = TRUE;
02365 }
02366
02367 if (!ignore_current)
02368 {
02369
02370
02371 XRefreshKeyboardMapping (&event->xmapping);
02372 meta_display_process_mapping_event (display, event);
02373 }
02374 }
02375 break;
02376 default:
02377 #ifdef HAVE_XKB
02378 if (event->type == display->xkb_base_event_type)
02379 {
02380 XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
02381
02382 switch (xkb_ev->xkb_type)
02383 {
02384 case XkbBellNotify:
02385 if (XSERVER_TIME_IS_BEFORE(display->last_bell_time,
02386 xkb_ev->time - 1000))
02387 {
02388 display->last_bell_time = xkb_ev->time;
02389 meta_bell_notify (display, xkb_ev);
02390 }
02391 break;
02392 }
02393 }
02394 #endif
02395 break;
02396 }
02397
02398 if (display->compositor)
02399 {
02400 meta_compositor_process_event (display->compositor,
02401 event,
02402 window);
02403 }
02404
02405 display->current_time = CurrentTime;
02406 return filter_out_event;
02407 }
02408
02409
02410
02411
02412
02413 static Window
02414 event_get_modified_window (MetaDisplay *display,
02415 XEvent *event)
02416 {
02417 switch (event->type)
02418 {
02419 case KeyPress:
02420 case KeyRelease:
02421 case ButtonPress:
02422 case ButtonRelease:
02423 case MotionNotify:
02424 case FocusIn:
02425 case FocusOut:
02426 case KeymapNotify:
02427 case Expose:
02428 case GraphicsExpose:
02429 case NoExpose:
02430 case VisibilityNotify:
02431 case ResizeRequest:
02432 case PropertyNotify:
02433 case SelectionClear:
02434 case SelectionRequest:
02435 case SelectionNotify:
02436 case ColormapNotify:
02437 case ClientMessage:
02438 case EnterNotify:
02439 case LeaveNotify:
02440 return event->xany.window;
02441
02442 case CreateNotify:
02443 return event->xcreatewindow.window;
02444
02445 case DestroyNotify:
02446 return event->xdestroywindow.window;
02447
02448 case UnmapNotify:
02449 return event->xunmap.window;
02450
02451 case MapNotify:
02452 return event->xmap.window;
02453
02454 case MapRequest:
02455 return event->xmaprequest.window;
02456
02457 case ReparentNotify:
02458 return event->xreparent.window;
02459
02460 case ConfigureNotify:
02461 return event->xconfigure.window;
02462
02463 case ConfigureRequest:
02464 return event->xconfigurerequest.window;
02465
02466 case GravityNotify:
02467 return event->xgravity.window;
02468
02469 case CirculateNotify:
02470 return event->xcirculate.window;
02471
02472 case CirculateRequest:
02473 return event->xcirculaterequest.window;
02474
02475 case MappingNotify:
02476 return None;
02477
02478 default:
02479 #ifdef HAVE_SHAPE
02480 if (META_DISPLAY_HAS_SHAPE (display) &&
02481 event->type == (display->shape_event_base + ShapeNotify))
02482 {
02483 XShapeEvent *sev = (XShapeEvent*) event;
02484 return sev->window;
02485 }
02486 #endif
02487
02488 return None;
02489 }
02490 }
02491
02492 static guint32
02493 event_get_time (MetaDisplay *display,
02494 XEvent *event)
02495 {
02496 switch (event->type)
02497 {
02498 case KeyPress:
02499 case KeyRelease:
02500 return event->xkey.time;
02501
02502 case ButtonPress:
02503 case ButtonRelease:
02504 return event->xbutton.time;
02505
02506 case MotionNotify:
02507 return event->xmotion.time;
02508
02509 case PropertyNotify:
02510 return event->xproperty.time;
02511
02512 case SelectionClear:
02513 case SelectionRequest:
02514 case SelectionNotify:
02515 return event->xselection.time;
02516
02517 case EnterNotify:
02518 case LeaveNotify:
02519 return event->xcrossing.time;
02520
02521 case FocusIn:
02522 case FocusOut:
02523 case KeymapNotify:
02524 case Expose:
02525 case GraphicsExpose:
02526 case NoExpose:
02527 case MapNotify:
02528 case UnmapNotify:
02529 case VisibilityNotify:
02530 case ResizeRequest:
02531 case ColormapNotify:
02532 case ClientMessage:
02533 case CreateNotify:
02534 case DestroyNotify:
02535 case MapRequest:
02536 case ReparentNotify:
02537 case ConfigureNotify:
02538 case ConfigureRequest:
02539 case GravityNotify:
02540 case CirculateNotify:
02541 case CirculateRequest:
02542 case MappingNotify:
02543 default:
02544 return CurrentTime;
02545 }
02546 }
02547
02548 #ifdef WITH_VERBOSE_MODE
02549 const char*
02550 meta_event_detail_to_string (int d)
02551 {
02552 const char *detail = "???";
02553 switch (d)
02554 {
02555
02556 case NotifyAncestor:
02557 detail = "NotifyAncestor";
02558 break;
02559 case NotifyDetailNone:
02560 detail = "NotifyDetailNone";
02561 break;
02562
02563 case NotifyInferior:
02564 detail = "NotifyInferior";
02565 break;
02566 case NotifyNonlinear:
02567 detail = "NotifyNonlinear";
02568 break;
02569 case NotifyNonlinearVirtual:
02570 detail = "NotifyNonlinearVirtual";
02571 break;
02572 case NotifyPointer:
02573 detail = "NotifyPointer";
02574 break;
02575 case NotifyPointerRoot:
02576 detail = "NotifyPointerRoot";
02577 break;
02578 case NotifyVirtual:
02579 detail = "NotifyVirtual";
02580 break;
02581 }
02582
02583 return detail;
02584 }
02585 #endif
02586
02587 #ifdef WITH_VERBOSE_MODE
02588 const char*
02589 meta_event_mode_to_string (int m)
02590 {
02591 const char *mode = "???";
02592 switch (m)
02593 {
02594 case NotifyNormal:
02595 mode = "NotifyNormal";
02596 break;
02597 case NotifyGrab:
02598 mode = "NotifyGrab";
02599 break;
02600 case NotifyUngrab:
02601 mode = "NotifyUngrab";
02602 break;
02603
02604
02605
02606 #ifdef NotifyWhileGrabbed
02607 case NotifyWhileGrabbed:
02608 mode = "NotifyWhileGrabbed";
02609 break;
02610 #endif
02611 }
02612
02613 return mode;
02614 }
02615 #endif
02616
02617 #ifdef WITH_VERBOSE_MODE
02618 static const char*
02619 stack_mode_to_string (int mode)
02620 {
02621 switch (mode)
02622 {
02623 case Above:
02624 return "Above";
02625 case Below:
02626 return "Below";
02627 case TopIf:
02628 return "TopIf";
02629 case BottomIf:
02630 return "BottomIf";
02631 case Opposite:
02632 return "Opposite";
02633 }
02634
02635 return "Unknown";
02636 }
02637 #endif
02638
02639 #ifdef WITH_VERBOSE_MODE
02640 static char*
02641 key_event_description (Display *xdisplay,
02642 XEvent *event)
02643 {
02644 KeySym keysym;
02645 const char *str;
02646
02647 keysym = XKeycodeToKeysym (xdisplay, event->xkey.keycode, 0);
02648
02649 str = XKeysymToString (keysym);
02650
02651 return g_strdup_printf ("Key '%s' state 0x%x",
02652 str ? str : "none", event->xkey.state);
02653 }
02654 #endif
02655
02656 #ifdef HAVE_XSYNC
02657 #ifdef WITH_VERBOSE_MODE
02658 static gint64
02659 sync_value_to_64 (const XSyncValue *value)
02660 {
02661 gint64 v;
02662
02663 v = XSyncValueLow32 (*value);
02664 v |= (((gint64)XSyncValueHigh32 (*value)) << 32);
02665
02666 return v;
02667 }
02668 #endif
02669
02670 #ifdef WITH_VERBOSE_MODE
02671 static const char*
02672 alarm_state_to_string (XSyncAlarmState state)
02673 {
02674 switch (state)
02675 {
02676 case XSyncAlarmActive:
02677 return "Active";
02678 case XSyncAlarmInactive:
02679 return "Inactive";
02680 case XSyncAlarmDestroyed:
02681 return "Destroyed";
02682 default:
02683 return "(unknown)";
02684 }
02685 }
02686 #endif
02687
02688 #endif
02689
02690 #ifdef WITH_VERBOSE_MODE
02691 static void
02692 meta_spew_event (MetaDisplay *display,
02693 XEvent *event)
02694 {
02695 const char *name = NULL;
02696 char *extra = NULL;
02697 char *winname;
02698 MetaScreen *screen;
02699
02700 if (!meta_is_verbose())
02701 return;
02702
02703
02704 if (event->type == Expose || event->type == MotionNotify ||
02705 event->type == NoExpose)
02706 return;
02707
02708 switch (event->type)
02709 {
02710 case KeyPress:
02711 name = "KeyPress";
02712 extra = key_event_description (display->xdisplay, event);
02713 break;
02714 case KeyRelease:
02715 name = "KeyRelease";
02716 extra = key_event_description (display->xdisplay, event);
02717 break;
02718 case ButtonPress:
02719 name = "ButtonPress";
02720 extra = g_strdup_printf ("button %u state 0x%x x %d y %d root 0x%lx same_screen %d",
02721 event->xbutton.button,
02722 event->xbutton.state,
02723 event->xbutton.x,
02724 event->xbutton.y,
02725 event->xbutton.root,
02726 event->xbutton.same_screen);
02727 break;
02728 case ButtonRelease:
02729 name = "ButtonRelease";
02730 extra = g_strdup_printf ("button %u state 0x%x x %d y %d root 0x%lx same_screen %d",
02731 event->xbutton.button,
02732 event->xbutton.state,
02733 event->xbutton.x,
02734 event->xbutton.y,
02735 event->xbutton.root,
02736 event->xbutton.same_screen);
02737 break;
02738 case MotionNotify:
02739 name = "MotionNotify";
02740 extra = g_strdup_printf ("win: 0x%lx x: %d y: %d",
02741 event->xmotion.window,
02742 event->xmotion.x,
02743 event->xmotion.y);
02744 break;
02745 case EnterNotify:
02746 name = "EnterNotify";
02747 extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %s detail: %s focus: %d x: %d y: %d",
02748 event->xcrossing.window,
02749 event->xcrossing.root,
02750 event->xcrossing.subwindow,
02751 meta_event_mode_to_string (event->xcrossing.mode),
02752 meta_event_detail_to_string (event->xcrossing.detail),
02753 event->xcrossing.focus,
02754 event->xcrossing.x,
02755 event->xcrossing.y);
02756 break;
02757 case LeaveNotify:
02758 name = "LeaveNotify";
02759 extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %s detail: %s focus: %d x: %d y: %d",
02760 event->xcrossing.window,
02761 event->xcrossing.root,
02762 event->xcrossing.subwindow,
02763 meta_event_mode_to_string (event->xcrossing.mode),
02764 meta_event_detail_to_string (event->xcrossing.detail),
02765 event->xcrossing.focus,
02766 event->xcrossing.x,
02767 event->xcrossing.y);
02768 break;
02769 case FocusIn:
02770 name = "FocusIn";
02771 extra = g_strdup_printf ("detail: %s mode: %s\n",
02772 meta_event_detail_to_string (event->xfocus.detail),
02773 meta_event_mode_to_string (event->xfocus.mode));
02774 break;
02775 case FocusOut:
02776 name = "FocusOut";
02777 extra = g_strdup_printf ("detail: %s mode: %s\n",
02778 meta_event_detail_to_string (event->xfocus.detail),
02779 meta_event_mode_to_string (event->xfocus.mode));
02780 break;
02781 case KeymapNotify:
02782 name = "KeymapNotify";
02783 break;
02784 case Expose:
02785 name = "Expose";
02786 break;
02787 case GraphicsExpose:
02788 name = "GraphicsExpose";
02789 break;
02790 case NoExpose:
02791 name = "NoExpose";
02792 break;
02793 case VisibilityNotify:
02794 name = "VisibilityNotify";
02795 break;
02796 case CreateNotify:
02797 name = "CreateNotify";
02798 extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx",
02799 event->xcreatewindow.parent,
02800 event->xcreatewindow.window);
02801 break;
02802 case DestroyNotify:
02803 name = "DestroyNotify";
02804 extra = g_strdup_printf ("event: 0x%lx window: 0x%lx",
02805 event->xdestroywindow.event,
02806 event->xdestroywindow.window);
02807 break;
02808 case UnmapNotify:
02809 name = "UnmapNotify";
02810 extra = g_strdup_printf ("event: 0x%lx window: 0x%lx from_configure: %d",
02811 event->xunmap.event,
02812 event->xunmap.window,
02813 event->xunmap.from_configure);
02814 break;
02815 case MapNotify:
02816 name = "MapNotify";
02817 extra = g_strdup_printf ("event: 0x%lx window: 0x%lx override_redirect: %d",
02818 event->xmap.event,
02819 event->xmap.window,
02820 event->xmap.override_redirect);
02821 break;
02822 case MapRequest:
02823 name = "MapRequest";
02824 extra = g_strdup_printf ("window: 0x%lx parent: 0x%lx\n",
02825 event->xmaprequest.window,
02826 event->xmaprequest.parent);
02827 break;
02828 case ReparentNotify:
02829 name = "ReparentNotify";
02830 extra = g_strdup_printf ("window: 0x%lx parent: 0x%lx event: 0x%lx\n",
02831 event->xreparent.window,
02832 event->xreparent.parent,
02833 event->xreparent.event);
02834 break;
02835 case ConfigureNotify:
02836 name = "ConfigureNotify";
02837 extra = g_strdup_printf ("x: %d y: %d w: %d h: %d above: 0x%lx override_redirect: %d",
02838 event->xconfigure.x,
02839 event->xconfigure.y,
02840 event->xconfigure.width,
02841 event->xconfigure.height,
02842 event->xconfigure.above,
02843 event->xconfigure.override_redirect);
02844 break;
02845 case ConfigureRequest:
02846 name = "ConfigureRequest";
02847 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",
02848 event->xconfigurerequest.parent,
02849 event->xconfigurerequest.window,
02850 event->xconfigurerequest.x,
02851 event->xconfigurerequest.value_mask &
02852 CWX ? "" : "(unset) ",
02853 event->xconfigurerequest.y,
02854 event->xconfigurerequest.value_mask &
02855 CWY ? "" : "(unset) ",
02856 event->xconfigurerequest.width,
02857 event->xconfigurerequest.value_mask &
02858 CWWidth ? "" : "(unset) ",
02859 event->xconfigurerequest.height,
02860 event->xconfigurerequest.value_mask &
02861 CWHeight ? "" : "(unset) ",
02862 event->xconfigurerequest.border_width,
02863 event->xconfigurerequest.value_mask &
02864 CWBorderWidth ? "" : "(unset)",
02865 event->xconfigurerequest.above,
02866 event->xconfigurerequest.value_mask &
02867 CWSibling ? "" : "(unset)",
02868 stack_mode_to_string (event->xconfigurerequest.detail),
02869 event->xconfigurerequest.value_mask &
02870 CWStackMode ? "" : "(unset)");
02871 break;
02872 case GravityNotify:
02873 name = "GravityNotify";
02874 break;
02875 case ResizeRequest:
02876 name = "ResizeRequest";
02877 extra = g_strdup_printf ("width = %d height = %d",
02878 event->xresizerequest.width,
02879 event->xresizerequest.height);
02880 break;
02881 case CirculateNotify:
02882 name = "CirculateNotify";
02883 break;
02884 case CirculateRequest:
02885 name = "CirculateRequest";
02886 break;
02887 case PropertyNotify:
02888 {
02889 char *str;
02890 const char *state;
02891
02892 name = "PropertyNotify";
02893
02894 meta_error_trap_push (display);
02895 str = XGetAtomName (display->xdisplay,
02896 event->xproperty.atom);
02897 meta_error_trap_pop (display, TRUE);
02898
02899 if (event->xproperty.state == PropertyNewValue)
02900 state = "PropertyNewValue";
02901 else if (event->xproperty.state == PropertyDelete)
02902 state = "PropertyDelete";
02903 else
02904 state = "???";
02905
02906 extra = g_strdup_printf ("atom: %s state: %s",
02907 str ? str : "(unknown atom)",
02908 state);
02909 meta_XFree (str);
02910 }
02911 break;
02912 case SelectionClear:
02913 name = "SelectionClear";
02914 break;
02915 case SelectionRequest:
02916 name = "SelectionRequest";
02917 break;
02918 case SelectionNotify:
02919 name = "SelectionNotify";
02920 break;
02921 case ColormapNotify:
02922 name = "ColormapNotify";
02923 break;
02924 case ClientMessage:
02925 {
02926 char *str;
02927 name = "ClientMessage";
02928 meta_error_trap_push (display);
02929 str = XGetAtomName (display->xdisplay,
02930 event->xclient.message_type);
02931 meta_error_trap_pop (display, TRUE);
02932 extra = g_strdup_printf ("type: %s format: %d\n",
02933 str ? str : "(unknown atom)",
02934 event->xclient.format);
02935 meta_XFree (str);
02936 }
02937 break;
02938 case MappingNotify:
02939 name = "MappingNotify";
02940 break;
02941 default:
02942 #ifdef HAVE_XSYNC
02943 if (META_DISPLAY_HAS_XSYNC (display) &&
02944 event->type == (display->xsync_event_base + XSyncAlarmNotify))
02945 {
02946 XSyncAlarmNotifyEvent *aevent = (XSyncAlarmNotifyEvent*) event;
02947
02948 name = "XSyncAlarmNotify";
02949 extra =
02950 g_strdup_printf ("alarm: 0x%lx"
02951 " counter_value: %" G_GINT64_FORMAT
02952 " alarm_value: %" G_GINT64_FORMAT
02953 " time: %u alarm state: %s",
02954 aevent->alarm,
02955 (gint64) sync_value_to_64 (&aevent->counter_value),
02956 (gint64) sync_value_to_64 (&aevent->alarm_value),
02957 (unsigned int)aevent->time,
02958 alarm_state_to_string (aevent->state));
02959 }
02960 else
02961 #endif
02962 #ifdef HAVE_SHAPE
02963 if (META_DISPLAY_HAS_SHAPE (display) &&
02964 event->type == (display->shape_event_base + ShapeNotify))
02965 {
02966 XShapeEvent *sev = (XShapeEvent*) event;
02967
02968 name = "ShapeNotify";
02969
02970 extra =
02971 g_strdup_printf ("kind: %s "
02972 "x: %d y: %d w: %u h: %u "
02973 "shaped: %d",
02974 sev->kind == ShapeBounding ?
02975 "ShapeBounding" :
02976 (sev->kind == ShapeClip ?
02977 "ShapeClip" : "(unknown)"),
02978 sev->x, sev->y, sev->width, sev->height,
02979 sev->shaped);
02980 }
02981 else
02982 #endif
02983 {
02984 name = "(Unknown event)";
02985 extra = g_strdup_printf ("type: %d", event->xany.type);
02986 }
02987 break;
02988 }
02989
02990 screen = meta_display_screen_for_root (display, event->xany.window);
02991
02992 if (screen)
02993 winname = g_strdup_printf ("root %d", screen->number);
02994 else
02995 winname = g_strdup_printf ("0x%lx", event->xany.window);
02996
02997 meta_topic (META_DEBUG_EVENTS,
02998 "%s on %s%s %s %sserial %lu\n", name, winname,
02999 extra ? ":" : "", extra ? extra : "",
03000 event->xany.send_event ? "SEND " : "",
03001 event->xany.serial);
03002
03003 g_free (winname);
03004
03005 if (extra)
03006 g_free (extra);
03007 }
03008 #endif
03009
03010 MetaWindow*
03011 meta_display_lookup_x_window (MetaDisplay *display,
03012 Window xwindow)
03013 {
03014 return g_hash_table_lookup (display->window_ids, &xwindow);
03015 }
03016
03017 void
03018 meta_display_register_x_window (MetaDisplay *display,
03019 Window *xwindowp,
03020 MetaWindow *window)
03021 {
03022 g_return_if_fail (g_hash_table_lookup (display->window_ids, xwindowp) == NULL);
03023
03024 g_hash_table_insert (display->window_ids, xwindowp, window);
03025 }
03026
03027 void
03028 meta_display_unregister_x_window (MetaDisplay *display,
03029 Window xwindow)
03030 {
03031 g_return_if_fail (g_hash_table_lookup (display->window_ids, &xwindow) != NULL);
03032
03033 g_hash_table_remove (display->window_ids, &xwindow);
03034
03035
03036 remove_pending_pings_for_window (display, xwindow);
03037 }
03038
03039 gboolean
03040 meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
03041 Window xwindow)
03042 {
03043 gboolean is_a_no_focus_window = FALSE;
03044 GSList *temp = display->screens;
03045 while (temp != NULL) {
03046 MetaScreen *screen = temp->data;
03047 if (screen->no_focus_window == xwindow) {
03048 is_a_no_focus_window = TRUE;
03049 break;
03050 }
03051 temp = temp->next;
03052 }
03053
03054 return is_a_no_focus_window;
03055 }
03056
03057 Cursor
03058 meta_display_create_x_cursor (MetaDisplay *display,
03059 MetaCursor cursor)
03060 {
03061 Cursor xcursor;
03062 guint glyph;
03063
03064 switch (cursor)
03065 {
03066 case META_CURSOR_DEFAULT:
03067 glyph = XC_left_ptr;
03068 break;
03069 case META_CURSOR_NORTH_RESIZE:
03070 glyph = XC_top_side;
03071 break;
03072 case META_CURSOR_SOUTH_RESIZE:
03073 glyph = XC_bottom_side;
03074 break;
03075 case META_CURSOR_WEST_RESIZE:
03076 glyph = XC_left_side;
03077 break;
03078 case META_CURSOR_EAST_RESIZE:
03079 glyph = XC_right_side;
03080 break;
03081 case META_CURSOR_SE_RESIZE:
03082 glyph = XC_bottom_right_corner;
03083 break;
03084 case META_CURSOR_SW_RESIZE:
03085 glyph = XC_bottom_left_corner;
03086 break;
03087 case META_CURSOR_NE_RESIZE:
03088 glyph = XC_top_right_corner;
03089 break;
03090 case META_CURSOR_NW_RESIZE:
03091 glyph = XC_top_left_corner;
03092 break;
03093 case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
03094 glyph = XC_fleur;
03095 break;
03096 case META_CURSOR_BUSY:
03097 glyph = XC_watch;
03098 break;
03099
03100 default:
03101 g_assert_not_reached ();
03102 glyph = 0;
03103 break;
03104 }
03105
03106 xcursor = XCreateFontCursor (display->xdisplay, glyph);
03107
03108 return xcursor;
03109 }
03110
03111 static Cursor
03112 xcursor_for_op (MetaDisplay *display,
03113 MetaGrabOp op)
03114 {
03115 MetaCursor cursor = META_CURSOR_DEFAULT;
03116
03117 switch (op)
03118 {
03119 case META_GRAB_OP_RESIZING_SE:
03120 case META_GRAB_OP_KEYBOARD_RESIZING_SE:
03121 cursor = META_CURSOR_SE_RESIZE;
03122 break;
03123 case META_GRAB_OP_RESIZING_S:
03124 case META_GRAB_OP_KEYBOARD_RESIZING_S:
03125 cursor = META_CURSOR_SOUTH_RESIZE;
03126 break;
03127 case META_GRAB_OP_RESIZING_SW:
03128 case META_GRAB_OP_KEYBOARD_RESIZING_SW:
03129 cursor = META_CURSOR_SW_RESIZE;
03130 break;
03131 case META_GRAB_OP_RESIZING_N:
03132 case META_GRAB_OP_KEYBOARD_RESIZING_N:
03133 cursor = META_CURSOR_NORTH_RESIZE;
03134 break;
03135 case META_GRAB_OP_RESIZING_NE:
03136 case META_GRAB_OP_KEYBOARD_RESIZING_NE:
03137 cursor = META_CURSOR_NE_RESIZE;
03138 break;
03139 case META_GRAB_OP_RESIZING_NW:
03140 case META_GRAB_OP_KEYBOARD_RESIZING_NW:
03141 cursor = META_CURSOR_NW_RESIZE;
03142 break;
03143 case META_GRAB_OP_RESIZING_W:
03144 case META_GRAB_OP_KEYBOARD_RESIZING_W:
03145 cursor = META_CURSOR_WEST_RESIZE;
03146 break;
03147 case META_GRAB_OP_RESIZING_E:
03148 case META_GRAB_OP_KEYBOARD_RESIZING_E:
03149 cursor = META_CURSOR_EAST_RESIZE;
03150 break;
03151 case META_GRAB_OP_MOVING:
03152 case META_GRAB_OP_KEYBOARD_MOVING:
03153 case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
03154 cursor = META_CURSOR_MOVE_OR_RESIZE_WINDOW;
03155 break;
03156
03157 default:
03158 break;
03159 }
03160
03161 if (cursor == META_CURSOR_DEFAULT)
03162 return None;
03163 return meta_display_create_x_cursor (display, cursor);
03164 }
03165
03166 void
03167 meta_display_set_grab_op_cursor (MetaDisplay *display,
03168 MetaScreen *screen,
03169 MetaGrabOp op,
03170 gboolean change_pointer,
03171 Window grab_xwindow,
03172 guint32 timestamp)
03173 {
03174 Cursor cursor;
03175
03176 cursor = xcursor_for_op (display, op);
03177
03178 #define GRAB_MASK (PointerMotionMask | \
03179 ButtonPressMask | ButtonReleaseMask | \
03180 EnterWindowMask | LeaveWindowMask)
03181
03182 if (change_pointer)
03183 {
03184 meta_error_trap_push_with_return (display);
03185 XChangeActivePointerGrab (display->xdisplay,
03186 GRAB_MASK,
03187 cursor,
03188 timestamp);
03189
03190 meta_topic (META_DEBUG_WINDOW_OPS,
03191 "Changed pointer with XChangeActivePointerGrab()\n");
03192
03193 if (meta_error_trap_pop_with_return (display, FALSE) != Success)
03194 {
03195 meta_topic (META_DEBUG_WINDOW_OPS,
03196 "Error trapped from XChangeActivePointerGrab()\n");
03197 if (display->grab_have_pointer)
03198 display->grab_have_pointer = FALSE;
03199 }
03200 }
03201 else
03202 {
03203 g_assert (screen != NULL);
03204
03205 meta_error_trap_push (display);
03206 if (XGrabPointer (display->xdisplay,
03207 grab_xwindow,
03208 False,
03209 GRAB_MASK,
03210 GrabModeAsync, GrabModeAsync,
03211 screen->xroot,
03212 cursor,
03213 timestamp) == GrabSuccess)
03214 {
03215 display->grab_have_pointer = TRUE;
03216 meta_topic (META_DEBUG_WINDOW_OPS,
03217 "XGrabPointer() returned GrabSuccess time %u\n",
03218 timestamp);
03219 }
03220 else
03221 {
03222 meta_topic (META_DEBUG_WINDOW_OPS,
03223 "XGrabPointer() failed time %u\n",
03224 timestamp);
03225 }
03226 meta_error_trap_pop (display, TRUE);
03227 }
03228
03229 #undef GRAB_MASK
03230
03231 if (cursor != None)
03232 XFreeCursor (display->xdisplay, cursor);
03233 }
03234
03235 gboolean
03236 meta_display_begin_grab_op (MetaDisplay *display,
03237 MetaScreen *screen,
03238 MetaWindow *window,
03239 MetaGrabOp op,
03240 gboolean pointer_already_grabbed,
03241 gboolean frame_action,
03242 int button,
03243 gulong modmask,
03244 guint32 timestamp,
03245 int root_x,
03246 int root_y)
03247 {
03248 Window grab_xwindow;
03249
03250 if (grab_op_is_mouse (op) && meta_grab_op_is_moving (op))
03251 {
03252 if (display->compositor)
03253 {
03254 meta_compositor_begin_move (display->compositor,
03255 window, &window->rect,
03256 root_x, root_y);
03257 }
03258 }
03259
03260 meta_topic (META_DEBUG_WINDOW_OPS,
03261 "Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n",
03262 op, window ? window->desc : "none", button, pointer_already_grabbed,
03263 root_x, root_y);
03264
03265 if (display->grab_op != META_GRAB_OP_NONE)
03266 {
03267 meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect\n",
03268 op, window ? window->desc : "none", display->grab_op,
03269 display->grab_window ? display->grab_window->desc : "none");
03270 return FALSE;
03271 }
03272
03273 if (window &&
03274 (meta_grab_op_is_moving (op) || meta_grab_op_is_resizing (op)))
03275 {
03276 if (meta_prefs_get_raise_on_click ())
03277 meta_window_raise (window);
03278 else
03279 {
03280 display->grab_initial_x = root_x;
03281 display->grab_initial_y = root_y;
03282 display->grab_threshold_movement_reached = FALSE;
03283 }
03284 }
03285
03286
03287
03288
03289
03290
03291
03292 if (window)
03293 grab_xwindow = window->frame ? window->frame->xwindow : window->xwindow;
03294 else
03295 grab_xwindow = screen->xroot;
03296
03297 display->grab_have_pointer = FALSE;
03298
03299 if (pointer_already_grabbed)
03300 display->grab_have_pointer = TRUE;
03301
03302 meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow,
03303 timestamp);
03304
03305 if (!display->grab_have_pointer)
03306 {
03307 meta_topic (META_DEBUG_WINDOW_OPS,
03308 "XGrabPointer() failed\n");
03309 return FALSE;
03310 }
03311
03312
03313 if (grab_op_is_keyboard (op) || grab_op_is_mouse_only (op))
03314 {
03315 if (window)
03316 display->grab_have_keyboard =
03317 meta_window_grab_all_keys (window, timestamp);
03318
03319 else
03320 display->grab_have_keyboard =
03321 meta_screen_grab_all_keys (screen, timestamp);
03322
03323 if (!display->grab_have_keyboard)
03324 {
03325 meta_topic (META_DEBUG_WINDOW_OPS,
03326 "grabbing all keys failed, ungrabbing pointer\n");
03327 XUngrabPointer (display->xdisplay, timestamp);
03328 display->grab_have_pointer = FALSE;
03329 return FALSE;
03330 }
03331 }
03332
03333 display->grab_op = op;
03334 display->grab_window = window;
03335 display->grab_screen = screen;
03336 display->grab_xwindow = grab_xwindow;
03337 display->grab_button = button;
03338 display->grab_mask = modmask;
03339 display->grab_anchor_root_x = root_x;
03340 display->grab_anchor_root_y = root_y;
03341 display->grab_latest_motion_x = root_x;
03342 display->grab_latest_motion_y = root_y;
03343 display->grab_last_moveresize_time.tv_sec = 0;
03344 display->grab_last_moveresize_time.tv_usec = 0;
03345 display->grab_motion_notify_time = 0;
03346 display->grab_old_window_stacking = NULL;
03347 #ifdef HAVE_XSYNC
03348 display->grab_sync_request_alarm = None;
03349 display->grab_last_user_action_was_snap = FALSE;
03350 #endif
03351 display->grab_was_cancelled = FALSE;
03352 display->grab_frame_action = frame_action;
03353
03354 if (display->grab_resize_timeout_id)
03355 {
03356 g_source_remove (display->grab_resize_timeout_id);
03357 display->grab_resize_timeout_id = 0;
03358 }
03359
03360 if (display->grab_window)
03361 {
03362 meta_window_get_client_root_coords (display->grab_window,
03363 &display->grab_initial_window_pos);
03364 display->grab_anchor_window_pos = display->grab_initial_window_pos;
03365
03366 display->grab_wireframe_active =
03367 (meta_prefs_get_reduced_resources () && !meta_prefs_get_gnome_accessibility ()) &&
03368 (meta_grab_op_is_resizing (display->grab_op) ||
03369 meta_grab_op_is_moving (display->grab_op));
03370
03371 if (display->grab_wireframe_active)
03372 {
03373 meta_window_calc_showing (display->grab_window);
03374 meta_window_begin_wireframe (window);
03375 }
03376
03377 #ifdef HAVE_XSYNC
03378 if (!display->grab_wireframe_active &&
03379 meta_grab_op_is_resizing (display->grab_op) &&
03380 display->grab_window->sync_request_counter != None)
03381 {
03382 XSyncAlarmAttributes values;
03383 XSyncValue init;
03384
03385 meta_error_trap_push_with_return (display);
03386
03387
03388
03389
03390
03391
03392 XSyncIntToValue (&init, 0);
03393 XSyncSetCounter (display->xdisplay,
03394 display->grab_window->sync_request_counter, init);
03395
03396 display->grab_window->sync_request_serial = 0;
03397 display->grab_window->sync_request_time.tv_sec = 0;
03398 display->grab_window->sync_request_time.tv_usec = 0;
03399
03400 values.trigger.counter = display->grab_window->sync_request_counter;
03401 values.trigger.value_type = XSyncAbsolute;
03402 values.trigger.test_type = XSyncPositiveTransition;
03403 XSyncIntToValue (&values.trigger.wait_value,
03404 display->grab_window->sync_request_serial + 1);
03405
03406
03407
03408
03409 XSyncIntToValue (&values.delta, 1);
03410
03411
03412 values.events = True;
03413
03414 display->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay,
03415 XSyncCACounter |
03416 XSyncCAValueType |
03417 XSyncCAValue |
03418 XSyncCATestType |
03419 XSyncCADelta |
03420 XSyncCAEvents,
03421 &values);
03422
03423 if (meta_error_trap_pop_with_return (display, FALSE) != Success)
03424 display->grab_sync_request_alarm = None;
03425
03426 meta_topic (META_DEBUG_RESIZING,
03427 "Created update alarm 0x%lx\n",
03428 display->grab_sync_request_alarm);
03429 }
03430 #endif
03431 }
03432
03433 meta_topic (META_DEBUG_WINDOW_OPS,
03434 "Grab op %u on window %s successful\n",
03435 display->grab_op, window ? window->desc : "(null)");
03436
03437 g_assert (display->grab_window != NULL || display->grab_screen != NULL);
03438 g_assert (display->grab_op != META_GRAB_OP_NONE);
03439
03440
03441
03442
03443 if (meta_grab_op_is_resizing (display->grab_op) ||
03444 meta_grab_op_is_moving (display->grab_op))
03445 {
03446 meta_topic (META_DEBUG_WINDOW_OPS,
03447 "Computing edges to resist-movement or snap-to for %s.\n",
03448 window->desc);
03449 meta_display_compute_resistance_and_snapping_edges (display);
03450 }
03451
03452
03453 if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
03454 {
03455 meta_topic (META_DEBUG_WINDOW_OPS,
03456 "Saving old stack positions; old pointer was %p.\n",
03457 display->grab_old_window_stacking);
03458 display->grab_old_window_stacking =
03459 meta_stack_get_positions (screen->stack);
03460 }
03461
03462
03463 switch (op)
03464 {
03465 case META_GRAB_OP_KEYBOARD_TABBING_NORMAL:
03466 meta_screen_ensure_tab_popup (screen,
03467 META_TAB_LIST_NORMAL,
03468 META_TAB_SHOW_ICON);
03469 break;
03470 case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL:
03471 meta_screen_ensure_tab_popup (screen,
03472 META_TAB_LIST_NORMAL,
03473 META_TAB_SHOW_INSTANTLY);
03474 break;
03475
03476 case META_GRAB_OP_KEYBOARD_TABBING_DOCK:
03477 meta_screen_ensure_tab_popup (screen,
03478 META_TAB_LIST_DOCKS,
03479 META_TAB_SHOW_ICON);
03480 break;
03481 case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK:
03482 meta_screen_ensure_tab_popup (screen,
03483 META_TAB_LIST_DOCKS,
03484 META_TAB_SHOW_INSTANTLY);
03485 break;
03486 case META_GRAB_OP_KEYBOARD_TABBING_GROUP:
03487 meta_screen_ensure_tab_popup (screen,
03488 META_TAB_LIST_GROUP,
03489 META_TAB_SHOW_ICON);
03490 break;
03491 case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP:
03492 meta_screen_ensure_tab_popup (screen,
03493 META_TAB_LIST_GROUP,
03494 META_TAB_SHOW_INSTANTLY);
03495
03496 case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING:
03497 meta_screen_ensure_workspace_popup (screen);
03498 break;
03499
03500 default:
03501 break;
03502 }
03503
03504 if (display->grab_window)
03505 {
03506 meta_window_refresh_resize_popup (display->grab_window);
03507 }
03508
03509 return TRUE;
03510 }
03511
03512 void
03513 meta_display_end_grab_op (MetaDisplay *display,
03514 guint32 timestamp)
03515 {
03516 meta_topic (META_DEBUG_WINDOW_OPS,
03517 "Ending grab op %u at time %u\n", display->grab_op, timestamp);
03518
03519 if (display->grab_op == META_GRAB_OP_NONE)
03520 return;
03521
03522 if (display->grab_window != NULL)
03523 display->grab_window->shaken_loose = FALSE;
03524
03525 if (display->grab_window != NULL &&
03526 !meta_prefs_get_raise_on_click () &&
03527 (meta_grab_op_is_moving (display->grab_op) ||
03528 meta_grab_op_is_resizing (display->grab_op)))
03529 {
03530
03531
03532
03533
03534
03535
03536 if (!display->grab_threshold_movement_reached)
03537 meta_window_raise (display->grab_window);
03538 }
03539
03540 if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) ||
03541 display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING)
03542 {
03543 meta_ui_tab_popup_free (display->grab_screen->tab_popup);
03544 display->grab_screen->tab_popup = NULL;
03545
03546
03547
03548
03549 display->ungrab_should_not_cause_focus_window = display->grab_xwindow;
03550 }
03551
03552
03553 if (meta_grab_op_is_resizing (display->grab_op) ||
03554 meta_grab_op_is_moving (display->grab_op))
03555 {
03556 meta_topic (META_DEBUG_WINDOW_OPS,
03557 "Clearing out the edges for resistance/snapping");
03558 meta_display_cleanup_edges (display);
03559 }
03560
03561 if (display->grab_old_window_stacking != NULL)
03562 {
03563 meta_topic (META_DEBUG_WINDOW_OPS,
03564 "Clearing out the old stack position, which was %p.\n",
03565 display->grab_old_window_stacking);
03566 g_list_free (display->grab_old_window_stacking);
03567 display->grab_old_window_stacking = NULL;
03568 }
03569
03570 if (display->grab_wireframe_active)
03571 {
03572 display->grab_wireframe_active = FALSE;
03573 meta_window_end_wireframe (display->grab_window);
03574
03575 if (!display->grab_was_cancelled)
03576 {
03577 if (meta_grab_op_is_moving (display->grab_op))
03578 meta_window_move (display->grab_window,
03579 TRUE,
03580 display->grab_wireframe_rect.x,
03581 display->grab_wireframe_rect.y);
03582 if (meta_grab_op_is_resizing (display->grab_op))
03583 meta_window_resize_with_gravity (display->grab_window,
03584 TRUE,
03585 display->grab_wireframe_rect.width,
03586 display->grab_wireframe_rect.height,
03587 meta_resize_gravity_from_grab_op (display->grab_op));
03588 }
03589 meta_window_calc_showing (display->grab_window);
03590 }
03591
03592 if (display->compositor &&
03593 display->grab_window &&
03594 grab_op_is_mouse (display->grab_op) &&
03595 meta_grab_op_is_moving (display->grab_op))
03596 {
03597 meta_compositor_end_move (display->compositor,
03598 display->grab_window);
03599 }
03600
03601 if (display->grab_have_pointer)
03602 {
03603 meta_topic (META_DEBUG_WINDOW_OPS,
03604 "Ungrabbing pointer with timestamp %u\n", timestamp);
03605 XUngrabPointer (display->xdisplay, timestamp);
03606 }
03607
03608 if (display->grab_have_keyboard)
03609 {
03610 meta_topic (META_DEBUG_WINDOW_OPS,
03611 "Ungrabbing all keys timestamp %u\n", timestamp);
03612 if (display->grab_window)
03613 meta_window_ungrab_all_keys (display->grab_window, timestamp);
03614 else
03615 meta_screen_ungrab_all_keys (display->grab_screen, timestamp);
03616 }
03617
03618 #ifdef HAVE_XSYNC
03619 if (display->grab_sync_request_alarm != None)
03620 {
03621 XSyncDestroyAlarm (display->xdisplay,
03622 display->grab_sync_request_alarm);
03623 display->grab_sync_request_alarm = None;
03624 }
03625 #endif
03626
03627 display->grab_window = NULL;
03628 display->grab_screen = NULL;
03629 display->grab_xwindow = None;
03630 display->grab_op = META_GRAB_OP_NONE;
03631
03632 if (display->grab_resize_popup)
03633 {
03634 meta_ui_resize_popup_free (display->grab_resize_popup);
03635 display->grab_resize_popup = NULL;
03636 }
03637
03638 if (display->grab_resize_timeout_id)
03639 {
03640 g_source_remove (display->grab_resize_timeout_id);
03641 display->grab_resize_timeout_id = 0;
03642 }
03643 }
03644
03645 void
03646 meta_display_check_threshold_reached (MetaDisplay *display,
03647 int x,
03648 int y)
03649 {
03650
03651 if (meta_prefs_get_raise_on_click () ||
03652 display->grab_threshold_movement_reached)
03653 return;
03654
03655 if (ABS (display->grab_initial_x - x) >= 8 ||
03656 ABS (display->grab_initial_y - y) >= 8)
03657 display->grab_threshold_movement_reached = TRUE;
03658 }
03659
03660 static void
03661 meta_change_button_grab (MetaDisplay *display,
03662 Window xwindow,
03663 gboolean grab,
03664 gboolean sync,
03665 int button,
03666 int modmask)
03667 {
03668 unsigned int ignored_mask;
03669
03670 meta_verbose ("%s 0x%lx sync = %d button = %d modmask 0x%x\n",
03671 grab ? "Grabbing" : "Ungrabbing",
03672 xwindow,
03673 sync, button, modmask);
03674
03675 meta_error_trap_push (display);
03676
03677 ignored_mask = 0;
03678 while (ignored_mask <= display->ignored_modifier_mask)
03679 {
03680 if (ignored_mask & ~(display->ignored_modifier_mask))
03681 {
03682
03683
03684
03685 ++ignored_mask;
03686 continue;
03687 }
03688
03689 if (meta_is_debugging ())
03690 meta_error_trap_push_with_return (display);
03691
03692
03693
03694 if (grab)
03695 XGrabButton (display->xdisplay, button, modmask | ignored_mask,
03696 xwindow, False,
03697 ButtonPressMask | ButtonReleaseMask |
03698 PointerMotionMask | PointerMotionHintMask,
03699 sync ? GrabModeSync : GrabModeAsync,
03700 GrabModeAsync,
03701 False, None);
03702 else
03703 XUngrabButton (display->xdisplay, button, modmask | ignored_mask,
03704 xwindow);
03705
03706 if (meta_is_debugging ())
03707 {
03708 int result;
03709
03710 result = meta_error_trap_pop_with_return (display, FALSE);
03711
03712 if (result != Success)
03713 meta_verbose ("Failed to %s button %d with mask 0x%x for window 0x%lx error code %d\n",
03714 grab ? "grab" : "ungrab",
03715 button, modmask | ignored_mask, xwindow, result);
03716 }
03717
03718 ++ignored_mask;
03719 }
03720
03721 meta_error_trap_pop (display, FALSE);
03722 }
03723
03724 void
03725 meta_display_grab_window_buttons (MetaDisplay *display,
03726 Window xwindow)
03727 {
03728
03729
03730
03731
03732
03733 meta_verbose ("Grabbing window buttons for 0x%lx\n", xwindow);
03734
03735
03736
03737
03738
03739
03740 if (display->window_grab_modifiers != 0)
03741 {
03742 gboolean debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL;
03743 int i;
03744 for (i = 1; i < 4; i++)
03745 {
03746 meta_change_button_grab (display, xwindow,
03747 TRUE,
03748 FALSE,
03749 i, display->window_grab_modifiers);
03750
03751
03752
03753
03754 if (debug)
03755 meta_change_button_grab (display, xwindow,
03756 TRUE,
03757 FALSE,
03758 i, ControlMask);
03759 }
03760
03761
03762
03763
03764
03765
03766
03767 meta_change_button_grab (display, xwindow,
03768 TRUE,
03769 FALSE,
03770 1, display->window_grab_modifiers | ShiftMask);
03771 }
03772 }
03773
03774 void
03775 meta_display_ungrab_window_buttons (MetaDisplay *display,
03776 Window xwindow)
03777 {
03778 gboolean debug;
03779 int i;
03780
03781 if (display->window_grab_modifiers == 0)
03782 return;
03783
03784 debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL;
03785 i = 1;
03786 while (i < 4)
03787 {
03788 meta_change_button_grab (display, xwindow,
03789 FALSE, FALSE, i,
03790 display->window_grab_modifiers);
03791
03792 if (debug)
03793 meta_change_button_grab (display, xwindow,
03794 FALSE, FALSE, i, ControlMask);
03795
03796 ++i;
03797 }
03798 }
03799
03800
03801 #define MAX_FOCUS_BUTTON 4
03802 void
03803 meta_display_grab_focus_window_button (MetaDisplay *display,
03804 MetaWindow *window)
03805 {
03806
03807 meta_verbose ("Grabbing unfocused window buttons for %s\n", window->desc);
03808
03809 #if 0
03810
03811
03812
03813
03814
03815
03816
03817 if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK)
03818 {
03819 meta_verbose (" (well, not grabbing since not in click to focus mode)\n");
03820 return;
03821 }
03822 #endif
03823
03824 if (window->have_focus_click_grab)
03825 {
03826 meta_verbose (" (well, not grabbing since we already have the grab)\n");
03827 return;
03828 }
03829
03830
03831
03832
03833
03834
03835 {
03836 int i = 1;
03837 while (i < MAX_FOCUS_BUTTON)
03838 {
03839 meta_change_button_grab (display,
03840 window->xwindow,
03841 TRUE, TRUE,
03842 i, 0);
03843
03844 ++i;
03845 }
03846
03847 window->have_focus_click_grab = TRUE;
03848 }
03849 }
03850
03851 void
03852 meta_display_ungrab_focus_window_button (MetaDisplay *display,
03853 MetaWindow *window)
03854 {
03855 meta_verbose ("Ungrabbing unfocused window buttons for %s\n", window->desc);
03856
03857 if (!window->have_focus_click_grab)
03858 return;
03859
03860 {
03861 int i = 1;
03862 while (i < MAX_FOCUS_BUTTON)
03863 {
03864 meta_change_button_grab (display, window->xwindow,
03865 FALSE, FALSE, i, 0);
03866
03867 ++i;
03868 }
03869
03870 window->have_focus_click_grab = FALSE;
03871 }
03872 }
03873
03874 void
03875 meta_display_increment_event_serial (MetaDisplay *display)
03876 {
03877
03878 XDeleteProperty (display->xdisplay, display->leader_window,
03879 display->atom__MOTIF_WM_HINTS);
03880 }
03881
03882 void
03883 meta_display_update_active_window_hint (MetaDisplay *display)
03884 {
03885 GSList *tmp;
03886
03887 gulong data[1];
03888
03889 if (display->focus_window)
03890 data[0] = display->focus_window->xwindow;
03891 else
03892 data[0] = None;
03893
03894 tmp = display->screens;
03895 while (tmp != NULL)
03896 {
03897 MetaScreen *screen = tmp->data;
03898
03899 meta_error_trap_push (display);
03900 XChangeProperty (display->xdisplay, screen->xroot,
03901 display->atom__NET_ACTIVE_WINDOW,
03902 XA_WINDOW,
03903 32, PropModeReplace, (guchar*) data, 1);
03904
03905 meta_error_trap_pop (display, FALSE);
03906
03907 tmp = tmp->next;
03908 }
03909 }
03910
03911 void
03912 meta_display_queue_retheme_all_windows (MetaDisplay *display)
03913 {
03914 GSList* windows;
03915 GSList *tmp;
03916
03917 windows = meta_display_list_windows (display);
03918 tmp = windows;
03919 while (tmp != NULL)
03920 {
03921 MetaWindow *window = tmp->data;
03922
03923 meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
03924 if (window->frame)
03925 {
03926 window->frame->need_reapply_frame_shape = TRUE;
03927
03928 meta_frame_queue_draw (window->frame);
03929 }
03930
03931 tmp = tmp->next;
03932 }
03933
03934 g_slist_free (windows);
03935 }
03936
03937 void
03938 meta_display_retheme_all (void)
03939 {
03940 meta_display_queue_retheme_all_windows (meta_get_display ());
03941 }
03942
03943 void
03944 meta_display_set_cursor_theme (const char *theme,
03945 int size)
03946 {
03947 #ifdef HAVE_XCURSOR
03948 GSList *tmp;
03949
03950 MetaDisplay *display = meta_get_display ();
03951
03952 XcursorSetTheme (display->xdisplay, theme);
03953 XcursorSetDefaultSize (display->xdisplay, size);
03954
03955 tmp = display->screens;
03956 while (tmp != NULL)
03957 {
03958 MetaScreen *screen = tmp->data;
03959
03960 meta_screen_update_cursor (screen);
03961
03962 tmp = tmp->next;
03963 }
03964
03965 #endif
03966 }
03967
03971 static gboolean is_syncing = FALSE;
03972
03984 gboolean
03985 meta_is_syncing (void)
03986 {
03987 return is_syncing;
03988 }
03989
03996 void
03997 meta_set_syncing (gboolean setting)
03998 {
03999 if (setting != is_syncing)
04000 {
04001 is_syncing = setting;
04002
04003 XSynchronize (meta_get_display ()->xdisplay, is_syncing);
04004 }
04005 }
04006
04011 #define PING_TIMEOUT_DELAY 2250
04012
04028 static gboolean
04029 meta_display_ping_timeout (gpointer data)
04030 {
04031 MetaPingData *ping_data;
04032
04033 ping_data = data;
04034
04035 ping_data->ping_timeout_id = 0;
04036
04037 meta_topic (META_DEBUG_PING,
04038 "Ping %u on window %lx timed out\n",
04039 ping_data->timestamp, ping_data->xwindow);
04040
04041 (* ping_data->ping_timeout_func) (ping_data->display, ping_data->xwindow,
04042 ping_data->timestamp, ping_data->user_data);
04043
04044 ping_data->display->pending_pings =
04045 g_slist_remove (ping_data->display->pending_pings,
04046 ping_data);
04047 ping_data_free (ping_data);
04048
04049 return FALSE;
04050 }
04051
04077 void
04078 meta_display_ping_window (MetaDisplay *display,
04079 MetaWindow *window,
04080 guint32 timestamp,
04081 MetaWindowPingFunc ping_reply_func,
04082 MetaWindowPingFunc ping_timeout_func,
04083 gpointer user_data)
04084 {
04085 MetaPingData *ping_data;
04086
04087 if (timestamp == CurrentTime)
04088 {
04089 meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n");
04090 return;
04091 }
04092
04093 if (!window->net_wm_ping)
04094 {
04095 if (ping_reply_func)
04096 (* ping_reply_func) (display, window->xwindow, timestamp, user_data);
04097
04098 return;
04099 }
04100
04101 ping_data = g_new (MetaPingData, 1);
04102 ping_data->display = display;
04103 ping_data->xwindow = window->xwindow;
04104 ping_data->timestamp = timestamp;
04105 ping_data->ping_reply_func = ping_reply_func;
04106 ping_data->ping_timeout_func = ping_timeout_func;
04107 ping_data->user_data = user_data;
04108 ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY,
04109 meta_display_ping_timeout,
04110 ping_data);
04111
04112 display->pending_pings = g_slist_prepend (display->pending_pings, ping_data);
04113
04114 meta_topic (META_DEBUG_PING,
04115 "Sending ping with timestamp %u to window %s\n",
04116 timestamp, window->desc);
04117 meta_window_send_icccm_message (window,
04118 display->atom__NET_WM_PING,
04119 timestamp);
04120 }
04121
04122 static void
04123 process_request_frame_extents (MetaDisplay *display,
04124 XEvent *event)
04125 {
04126
04127 Window xwindow = event->xclient.window;
04128 unsigned long data[4] = { 0, 0, 0, 0 };
04129
04130 MotifWmHints *hints = NULL;
04131 gboolean hints_set = FALSE;
04132
04133 meta_verbose ("Setting frame extents for 0x%lx\n", xwindow);
04134
04135
04136 hints_set = meta_prop_get_motif_hints (display,
04137 xwindow,
04138 display->atom__MOTIF_WM_HINTS,
04139 &hints);
04140 if ((hints_set && hints->decorations) || !hints_set)
04141 {
04142 int top = 0;
04143 int bottom = 0;
04144 int left = 0;
04145 int right = 0;
04146
04147 MetaScreen *screen;
04148
04149 screen = meta_display_screen_for_xwindow (display,
04150 event->xclient.window);
04151 if (screen == NULL)
04152 {
04153 meta_warning ("Received request to set _NET_FRAME_EXTENTS "
04154 "on 0x%lx which is on a screen we are not managing\n",
04155 event->xclient.window);
04156 meta_XFree (hints);
04157 return;
04158 }
04159
04160
04161 meta_ui_theme_get_frame_borders (screen->ui,
04162 META_FRAME_TYPE_NORMAL,
04163 0,
04164 &top,
04165 &bottom,
04166 &left,
04167 &right);
04168
04169 data[0] = left;
04170 data[1] = right;
04171 data[2] = top;
04172 data[3] = bottom;
04173 }
04174
04175 meta_topic (META_DEBUG_GEOMETRY,
04176 "Setting _NET_FRAME_EXTENTS on unmanaged window 0x%lx "
04177 "to top = %lu, left = %lu, bottom = %lu, right = %lu\n",
04178 xwindow, data[0], data[1], data[2], data[3]);
04179
04180 meta_error_trap_push (display);
04181 XChangeProperty (display->xdisplay, xwindow,
04182 display->atom__NET_FRAME_EXTENTS,
04183 XA_CARDINAL,
04184 32, PropModeReplace, (guchar*) data, 4);
04185 meta_error_trap_pop (display, FALSE);
04186
04187 meta_XFree (hints);
04188 }
04189
04202 static void
04203 process_pong_message (MetaDisplay *display,
04204 XEvent *event)
04205 {
04206 GSList *tmp;
04207 guint32 timestamp = event->xclient.data.l[1];
04208
04209 meta_topic (META_DEBUG_PING, "Received a pong with timestamp %u\n",
04210 timestamp);
04211
04212 for (tmp = display->pending_pings; tmp; tmp = tmp->next)
04213 {
04214 MetaPingData *ping_data = tmp->data;
04215
04216 if (timestamp == ping_data->timestamp)
04217 {
04218 meta_topic (META_DEBUG_PING,
04219 "Matching ping found for pong %u\n",
04220 ping_data->timestamp);
04221
04222
04223 display->pending_pings = g_slist_remove (display->pending_pings,
04224 ping_data);
04225
04226
04227 if (ping_data->ping_timeout_id != 0)
04228 {
04229 g_source_remove (ping_data->ping_timeout_id);
04230 ping_data->ping_timeout_id = 0;
04231 }
04232
04233
04234 (* ping_data->ping_reply_func) (display,
04235 ping_data->xwindow,
04236 ping_data->timestamp,
04237 ping_data->user_data);
04238
04239 ping_data_free (ping_data);
04240
04241 break;
04242 }
04243 }
04244 }
04245
04260 gboolean
04261 meta_display_window_has_pending_pings (MetaDisplay *display,
04262 MetaWindow *window)
04263 {
04264 GSList *tmp;
04265
04266 for (tmp = display->pending_pings; tmp; tmp = tmp->next)
04267 {
04268 MetaPingData *ping_data = tmp->data;
04269
04270 if (ping_data->xwindow == window->xwindow)
04271 return TRUE;
04272 }
04273
04274 return FALSE;
04275 }
04276
04277 MetaGroup*
04278 get_focussed_group (MetaDisplay *display)
04279 {
04280 if (display->focus_window)
04281 return display->focus_window->group;
04282 else
04283 return NULL;
04284 }
04285
04286 #define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \
04287 || ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \
04288 || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focussed_group(w->display))))
04289
04290 static MetaWindow*
04291 find_tab_forward (MetaDisplay *display,
04292 MetaTabList type,
04293 MetaScreen *screen,
04294 MetaWorkspace *workspace,
04295 GList *start,
04296 gboolean skip_first)
04297 {
04298 GList *tmp;
04299
04300 g_return_val_if_fail (start != NULL, NULL);
04301 g_return_val_if_fail (workspace != NULL, NULL);
04302
04303 tmp = start;
04304 if (skip_first)
04305 tmp = tmp->next;
04306
04307 while (tmp != NULL)
04308 {
04309 MetaWindow *window = tmp->data;
04310
04311 if (window->screen == screen &&
04312 IN_TAB_CHAIN (window, type))
04313 return window;
04314
04315 tmp = tmp->next;
04316 }
04317
04318 tmp = workspace->mru_list;
04319 while (tmp != start)
04320 {
04321 MetaWindow *window = tmp->data;
04322
04323 if (IN_TAB_CHAIN (window, type))
04324 return window;
04325
04326 tmp = tmp->next;
04327 }
04328
04329 return NULL;
04330 }
04331
04332 static MetaWindow*
04333 find_tab_backward (MetaDisplay *display,
04334 MetaTabList type,
04335 MetaScreen *screen,
04336 MetaWorkspace *workspace,
04337 GList *start,
04338 gboolean skip_last)
04339 {
04340 GList *tmp;
04341
04342 g_return_val_if_fail (start != NULL, NULL);
04343 g_return_val_if_fail (workspace != NULL, NULL);
04344
04345 tmp = start;
04346 if (skip_last)
04347 tmp = tmp->prev;
04348 while (tmp != NULL)
04349 {
04350 MetaWindow *window = tmp->data;
04351
04352 if (window->screen == screen &&
04353 IN_TAB_CHAIN (window, type))
04354 return window;
04355
04356 tmp = tmp->prev;
04357 }
04358
04359 tmp = g_list_last (workspace->mru_list);
04360 while (tmp != start)
04361 {
04362 MetaWindow *window = tmp->data;
04363
04364 if (IN_TAB_CHAIN (window, type))
04365 return window;
04366
04367 tmp = tmp->prev;
04368 }
04369
04370 return NULL;
04371 }
04372
04373 GList*
04374 meta_display_get_tab_list (MetaDisplay *display,
04375 MetaTabList type,
04376 MetaScreen *screen,
04377 MetaWorkspace *workspace)
04378 {
04379 GList *tab_list;
04380
04381 g_return_val_if_fail (workspace != NULL, NULL);
04382
04383
04384
04385
04386 {
04387 GList *tmp;
04388
04389 tab_list = NULL;
04390 tmp = workspace->mru_list;
04391 while (tmp != NULL)
04392 {
04393 MetaWindow *window = tmp->data;
04394
04395 if (!window->minimized &&
04396 window->screen == screen &&
04397 IN_TAB_CHAIN (window, type))
04398 tab_list = g_list_prepend (tab_list, window);
04399
04400 tmp = tmp->next;
04401 }
04402 }
04403
04404 {
04405 GList *tmp;
04406
04407 tmp = workspace->mru_list;
04408 while (tmp != NULL)
04409 {
04410 MetaWindow *window = tmp->data;
04411
04412 if (window->minimized &&
04413 window->screen == screen &&
04414 IN_TAB_CHAIN (window, type))
04415 tab_list = g_list_prepend (tab_list, window);
04416
04417 tmp = tmp->next;
04418 }
04419 }
04420
04421 tab_list = g_list_reverse (tab_list);
04422
04423 {
04424 GSList *tmp;
04425 MetaWindow *l_window;
04426
04427 tmp = meta_display_list_windows (display);
04428
04429
04430 while (tmp != NULL)
04431 {
04432 l_window=tmp->data;
04433
04434
04435 if (l_window->wm_state_demands_attention &&
04436 l_window->workspace!=workspace)
04437 {
04438
04439 tab_list = g_list_prepend (tab_list, l_window);
04440 }
04441
04442 tmp = tmp->next;
04443 }
04444 }
04445
04446 return tab_list;
04447 }
04448
04449 MetaWindow*
04450 meta_display_get_tab_next (MetaDisplay *display,
04451 MetaTabList type,
04452 MetaScreen *screen,
04453 MetaWorkspace *workspace,
04454 MetaWindow *window,
04455 gboolean backward)
04456 {
04457 gboolean skip;
04458 GList *tab_list;
04459 MetaWindow *ret;
04460 tab_list = meta_display_get_tab_list(display,
04461 type,
04462 screen,
04463 workspace);
04464
04465 if (tab_list == NULL)
04466 return NULL;
04467
04468 if (window != NULL)
04469 {
04470 g_assert (window->display == display);
04471
04472 if (backward)
04473 ret = find_tab_backward (display, type, screen, workspace,
04474 g_list_find (tab_list,
04475 window),
04476 TRUE);
04477 else
04478 ret = find_tab_forward (display, type, screen, workspace,
04479 g_list_find (tab_list,
04480 window),
04481 TRUE);
04482 }
04483 else
04484 {
04485 skip = display->focus_window != NULL &&
04486 IN_TAB_CHAIN (display->focus_window, type);
04487 if (backward)
04488 ret = find_tab_backward (display, type, screen, workspace,
04489 tab_list, skip);
04490 else
04491 ret = find_tab_forward (display, type, screen, workspace,
04492 tab_list, skip);
04493 }
04494
04495 g_list_free (tab_list);
04496 return ret;
04497 }
04498
04499 MetaWindow*
04500 meta_display_get_tab_current (MetaDisplay *display,
04501 MetaTabList type,
04502 MetaScreen *screen,
04503 MetaWorkspace *workspace)
04504 {
04505 MetaWindow *window;
04506
04507 window = display->focus_window;
04508
04509 if (window != NULL &&
04510 window->screen == screen &&
04511 IN_TAB_CHAIN (window, type) &&
04512 (workspace == NULL ||
04513 meta_window_located_on_workspace (window, workspace)))
04514 return window;
04515 else
04516 return NULL;
04517 }
04518
04519 int
04520 meta_resize_gravity_from_grab_op (MetaGrabOp op)
04521 {
04522 int gravity;
04523
04524 gravity = -1;
04525 switch (op)
04526 {
04527 case META_GRAB_OP_RESIZING_SE:
04528 case META_GRAB_OP_KEYBOARD_RESIZING_SE:
04529 gravity = NorthWestGravity;
04530 break;
04531 case META_GRAB_OP_KEYBOARD_RESIZING_S:
04532 case META_GRAB_OP_RESIZING_S:
04533 gravity = NorthGravity;
04534 break;
04535 case META_GRAB_OP_KEYBOARD_RESIZING_SW:
04536 case META_GRAB_OP_RESIZING_SW:
04537 gravity = NorthEastGravity;
04538 break;
04539 case META_GRAB_OP_KEYBOARD_RESIZING_N:
04540 case META_GRAB_OP_RESIZING_N:
04541 gravity = SouthGravity;
04542 break;
04543 case META_GRAB_OP_KEYBOARD_RESIZING_NE:
04544 case META_GRAB_OP_RESIZING_NE:
04545 gravity = SouthWestGravity;
04546 break;
04547 case META_GRAB_OP_KEYBOARD_RESIZING_NW:
04548 case META_GRAB_OP_RESIZING_NW:
04549 gravity = SouthEastGravity;
04550 break;
04551 case META_GRAB_OP_KEYBOARD_RESIZING_E:
04552 case META_GRAB_OP_RESIZING_E:
04553 gravity = WestGravity;
04554 break;
04555 case META_GRAB_OP_KEYBOARD_RESIZING_W:
04556 case META_GRAB_OP_RESIZING_W:
04557 gravity = EastGravity;
04558 break;
04559 case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
04560 gravity = CenterGravity;
04561 break;
04562 default:
04563 break;
04564 }
04565
04566 return gravity;
04567 }
04568
04569 static MetaScreen*
04570 find_screen_for_selection (MetaDisplay *display,
04571 Window owner,
04572 Atom selection)
04573 {
04574 GSList *tmp;
04575
04576 tmp = display->screens;
04577 while (tmp != NULL)
04578 {
04579 MetaScreen *screen = tmp->data;
04580
04581 if (screen->wm_sn_selection_window == owner &&
04582 screen->wm_sn_atom == selection)
04583 return screen;
04584
04585 tmp = tmp->next;
04586 }
04587
04588 return NULL;
04589 }
04590
04591
04592 static gboolean
04593 convert_property (MetaDisplay *display,
04594 MetaScreen *screen,
04595 Window w,
04596 Atom target,
04597 Atom property)
04598 {
04599 #define N_TARGETS 4
04600 Atom conversion_targets[N_TARGETS];
04601 long icccm_version[] = { 2, 0 };
04602
04603 conversion_targets[0] = display->atom_TARGETS;
04604 conversion_targets[1] = display->atom_MULTIPLE;
04605 conversion_targets[2] = display->atom_TIMESTAMP;
04606 conversion_targets[3] = display->atom_VERSION;
04607
04608 meta_error_trap_push_with_return (display);
04609 if (target == display->atom_TARGETS)
04610 XChangeProperty (display->xdisplay, w, property,
04611 XA_ATOM, 32, PropModeReplace,
04612 (unsigned char *)conversion_targets, N_TARGETS);
04613 else if (target == display->atom_TIMESTAMP)
04614 XChangeProperty (display->xdisplay, w, property,
04615 XA_INTEGER, 32, PropModeReplace,
04616 (unsigned char *)&screen->wm_sn_timestamp, 1);
04617 else if (target == display->atom_VERSION)
04618 XChangeProperty (display->xdisplay, w, property,
04619 XA_INTEGER, 32, PropModeReplace,
04620 (unsigned char *)icccm_version, 2);
04621 else
04622 {
04623 meta_error_trap_pop_with_return (display, FALSE);
04624 return FALSE;
04625 }
04626
04627 if (meta_error_trap_pop_with_return (display, FALSE) != Success)
04628 return FALSE;
04629
04630
04631
04632
04633
04634 meta_topic (META_DEBUG_SYNC, "Syncing on %s\n", G_STRFUNC);
04635 XSync (display->xdisplay, False);
04636
04637 return TRUE;
04638 }
04639
04640
04641 static void
04642 process_selection_request (MetaDisplay *display,
04643 XEvent *event)
04644 {
04645 XSelectionEvent reply;
04646 MetaScreen *screen;
04647
04648 screen = find_screen_for_selection (display,
04649 event->xselectionrequest.owner,
04650 event->xselectionrequest.selection);
04651
04652 if (screen == NULL)
04653 {
04654 char *str;
04655
04656 meta_error_trap_push (display);
04657 str = XGetAtomName (display->xdisplay,
04658 event->xselectionrequest.selection);
04659 meta_error_trap_pop (display, TRUE);
04660
04661 meta_verbose ("Selection request with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
04662 str ? str : "(bad atom)", event->xselectionrequest.owner);
04663
04664 meta_XFree (str);
04665
04666 return;
04667 }
04668
04669 reply.type = SelectionNotify;
04670 reply.display = display->xdisplay;
04671 reply.requestor = event->xselectionrequest.requestor;
04672 reply.selection = event->xselectionrequest.selection;
04673 reply.target = event->xselectionrequest.target;
04674 reply.property = None;
04675 reply.time = event->xselectionrequest.time;
04676
04677 if (event->xselectionrequest.target == display->atom_MULTIPLE)
04678 {
04679 if (event->xselectionrequest.property != None)
04680 {
04681 Atom type, *adata;
04682 int i, format;
04683 unsigned long num, rest;
04684 unsigned char *data;
04685
04686 meta_error_trap_push_with_return (display);
04687 if (XGetWindowProperty (display->xdisplay,
04688 event->xselectionrequest.requestor,
04689 event->xselectionrequest.property, 0, 256, False,
04690 display->atom_ATOM_PAIR,
04691 &type, &format, &num, &rest, &data) != Success)
04692 {
04693 meta_error_trap_pop_with_return (display, TRUE);
04694 return;
04695 }
04696
04697 if (meta_error_trap_pop_with_return (display, TRUE) == Success)
04698 {
04699
04700
04701
04702
04703 adata = (Atom*)data;
04704 i = 0;
04705 while (i < (int) num)
04706 {
04707 if (!convert_property (display, screen,
04708 event->xselectionrequest.requestor,
04709 adata[i], adata[i+1]))
04710 adata[i+1] = None;
04711 i += 2;
04712 }
04713
04714 meta_error_trap_push (display);
04715 XChangeProperty (display->xdisplay,
04716 event->xselectionrequest.requestor,
04717 event->xselectionrequest.property,
04718 display->atom_ATOM_PAIR,
04719 32, PropModeReplace, data, num);
04720 meta_error_trap_pop (display, FALSE);
04721 meta_XFree (data);
04722 }
04723 }
04724 }
04725 else
04726 {
04727 if (event->xselectionrequest.property == None)
04728 event->xselectionrequest.property = event->xselectionrequest.target;
04729
04730 if (convert_property (display, screen,
04731 event->xselectionrequest.requestor,
04732 event->xselectionrequest.target,
04733 event->xselectionrequest.property))
04734 reply.property = event->xselectionrequest.property;
04735 }
04736
04737 XSendEvent (display->xdisplay,
04738 event->xselectionrequest.requestor,
04739 False, 0L, (XEvent*)&reply);
04740
04741 meta_verbose ("Handled selection request\n");
04742 }
04743
04744 static void
04745 process_selection_clear (MetaDisplay *display,
04746 XEvent *event)
04747 {
04748
04749 MetaScreen *screen;
04750
04751 screen = find_screen_for_selection (display,
04752 event->xselectionclear.window,
04753 event->xselectionclear.selection);
04754
04755
04756 if (screen != NULL)
04757 {
04758 meta_verbose ("Got selection clear for screen %d on display %s\n",
04759 screen->number, display->name);
04760
04761 meta_display_unmanage_screen (display,
04762 screen,
04763 event->xselectionclear.time);
04764
04765
04766
04767 return;
04768 }
04769
04770 {
04771 char *str;
04772
04773 meta_error_trap_push (display);
04774 str = XGetAtomName (display->xdisplay,
04775 event->xselectionclear.selection);
04776 meta_error_trap_pop (display, TRUE);
04777
04778 meta_verbose ("Selection clear with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
04779 str ? str : "(bad atom)", event->xselectionclear.window);
04780
04781 meta_XFree (str);
04782 }
04783 }
04784
04785 void
04786 meta_display_unmanage_screen (MetaDisplay *display,
04787 MetaScreen *screen,
04788 guint32 timestamp)
04789 {
04790 meta_verbose ("Unmanaging screen %d on display %s\n",
04791 screen->number, display->name);
04792
04793 g_return_if_fail (g_slist_find (display->screens, screen) != NULL);
04794
04795 meta_screen_free (screen, timestamp);
04796 display->screens = g_slist_remove (display->screens, screen);
04797
04798 if (display->screens == NULL)
04799 meta_display_close (display, timestamp);
04800 }
04801
04802 void
04803 meta_display_unmanage_windows_for_screen (MetaDisplay *display,
04804 MetaScreen *screen,
04805 guint32 timestamp)
04806 {
04807 GSList *tmp;
04808 GSList *winlist;
04809
04810 winlist = meta_display_list_windows (display);
04811 winlist = g_slist_sort (winlist, meta_display_stack_cmp);
04812
04813
04814 tmp = winlist;
04815 while (tmp != NULL)
04816 {
04817 meta_window_free (tmp->data, timestamp);
04818
04819 tmp = tmp->next;
04820 }
04821 g_slist_free (winlist);
04822 }
04823
04824 int
04825 meta_display_stack_cmp (const void *a,
04826 const void *b)
04827 {
04828 MetaWindow *aw = (void*) a;
04829 MetaWindow *bw = (void*) b;
04830
04831 if (aw->screen == bw->screen)
04832 return meta_stack_windows_cmp (aw->screen->stack, aw, bw);
04833
04834 else if (aw->screen->number < bw->screen->number)
04835 return -1;
04836 else if (aw->screen->number > bw->screen->number)
04837 return 1;
04838 else
04839 return 0;
04840 }
04841
04842 void
04843 meta_display_devirtualize_modifiers (MetaDisplay *display,
04844 MetaVirtualModifier modifiers,
04845 unsigned int *mask)
04846 {
04847 *mask = 0;
04848
04849 if (modifiers & META_VIRTUAL_SHIFT_MASK)
04850 *mask |= ShiftMask;
04851 if (modifiers & META_VIRTUAL_CONTROL_MASK)
04852 *mask |= ControlMask;
04853 if (modifiers & META_VIRTUAL_ALT_MASK)
04854 *mask |= Mod1Mask;
04855 if (modifiers & META_VIRTUAL_META_MASK)
04856 *mask |= display->meta_mask;
04857 if (modifiers & META_VIRTUAL_HYPER_MASK)
04858 *mask |= display->hyper_mask;
04859 if (modifiers & META_VIRTUAL_SUPER_MASK)
04860 *mask |= display->super_mask;
04861 if (modifiers & META_VIRTUAL_MOD2_MASK)
04862 *mask |= Mod2Mask;
04863 if (modifiers & META_VIRTUAL_MOD3_MASK)
04864 *mask |= Mod3Mask;
04865 if (modifiers & META_VIRTUAL_MOD4_MASK)
04866 *mask |= Mod4Mask;
04867 if (modifiers & META_VIRTUAL_MOD5_MASK)
04868 *mask |= Mod5Mask;
04869 }
04870
04871 static void
04872 update_window_grab_modifiers (MetaDisplay *display)
04873
04874 {
04875 MetaVirtualModifier virtual_mods;
04876 unsigned int mods;
04877
04878 virtual_mods = meta_prefs_get_mouse_button_mods ();
04879 meta_display_devirtualize_modifiers (display, virtual_mods,
04880 &mods);
04881
04882 display->window_grab_modifiers = mods;
04883 }
04884
04885 static void
04886 prefs_changed_callback (MetaPreference pref,
04887 void *data)
04888 {
04889 MetaDisplay *display = data;
04890
04891
04892
04893
04894
04895 if (pref == META_PREF_MOUSE_BUTTON_MODS ||
04896 pref == META_PREF_FOCUS_MODE)
04897 {
04898 MetaDisplay *display = data;
04899 GSList *windows;
04900 GSList *tmp;
04901
04902 windows = meta_display_list_windows (display);
04903
04904
04905 tmp = windows;
04906 while (tmp != NULL)
04907 {
04908 MetaWindow *w = tmp->data;
04909 meta_display_ungrab_window_buttons (display, w->xwindow);
04910 meta_display_ungrab_focus_window_button (display, w);
04911 tmp = tmp->next;
04912 }
04913
04914
04915 if (pref == META_PREF_MOUSE_BUTTON_MODS)
04916 update_window_grab_modifiers (display);
04917
04918
04919 tmp = windows;
04920 while (tmp != NULL)
04921 {
04922 MetaWindow *w = tmp->data;
04923 meta_display_grab_focus_window_button (display, w);
04924 meta_display_grab_window_buttons (display, w->xwindow);
04925 tmp = tmp->next;
04926 }
04927
04928 g_slist_free (windows);
04929 }
04930 else if (pref == META_PREF_AUDIBLE_BELL)
04931 {
04932 meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
04933 }
04934 else if (pref == META_PREF_COMPOSITING_MANAGER)
04935 {
04936 gboolean cm = meta_prefs_get_compositing_manager ();
04937
04938 if (cm)
04939 enable_compositor (display, TRUE);
04940 else
04941 disable_compositor (display);
04942 }
04943 }
04944
04945 void
04946 meta_display_increment_focus_sentinel (MetaDisplay *display)
04947 {
04948 unsigned long data[1];
04949
04950 data[0] = meta_display_get_current_time (display);
04951
04952 XChangeProperty (display->xdisplay,
04953 ((MetaScreen*) display->screens->data)->xroot,
04954 display->atom__METACITY_SENTINEL,
04955 XA_CARDINAL,
04956 32, PropModeReplace, (guchar*) data, 1);
04957
04958 display->sentinel_counter += 1;
04959 }
04960
04961 void
04962 meta_display_decrement_focus_sentinel (MetaDisplay *display)
04963 {
04964 display->sentinel_counter -= 1;
04965
04966 if (display->sentinel_counter < 0)
04967 display->sentinel_counter = 0;
04968 }
04969
04970 gboolean
04971 meta_display_focus_sentinel_clear (MetaDisplay *display)
04972 {
04973 return (display->sentinel_counter == 0);
04974 }
04975
04976 static void
04977 sanity_check_timestamps (MetaDisplay *display,
04978 guint32 timestamp)
04979 {
04980 if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time))
04981 {
04982 meta_warning ("last_focus_time (%u) is greater than comparison "
04983 "timestamp (%u). This most likely represents a buggy "
04984 "client sending inaccurate timestamps in messages such as "
04985 "_NET_ACTIVE_WINDOW. Trying to work around...\n",
04986 display->last_focus_time, timestamp);
04987 display->last_focus_time = timestamp;
04988 }
04989 if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time))
04990 {
04991 GSList *windows;
04992 GSList *tmp;
04993
04994 meta_warning ("last_user_time (%u) is greater than comparison "
04995 "timestamp (%u). This most likely represents a buggy "
04996 "client sending inaccurate timestamps in messages such as "
04997 "_NET_ACTIVE_WINDOW. Trying to work around...\n",
04998 display->last_user_time, timestamp);
04999 display->last_user_time = timestamp;
05000
05001 windows = meta_display_list_windows (display);
05002 tmp = windows;
05003 while (tmp != NULL)
05004 {
05005 MetaWindow *window = tmp->data;
05006
05007 if (XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time))
05008 {
05009 meta_warning ("%s appears to be one of the offending windows "
05010 "with a timestamp of %u. Working around...\n",
05011 window->desc, window->net_wm_user_time);
05012 window->net_wm_user_time = timestamp;
05013 }
05014
05015 tmp = tmp->next;
05016 }
05017
05018 g_slist_free (windows);
05019 }
05020 }
05021
05022 static gboolean
05023 timestamp_too_old (MetaDisplay *display,
05024 MetaWindow *window,
05025 guint32 *timestamp)
05026 {
05027
05028
05029
05030
05031
05032
05033 if (*timestamp == CurrentTime)
05034 {
05035 meta_warning ("Got a request to focus %s with a timestamp of 0. This "
05036 "shouldn't happen!\n",
05037 window ? window->desc : "the no_focus_window");
05038 meta_print_backtrace ();
05039 *timestamp = meta_display_get_current_time_roundtrip (display);
05040 return FALSE;
05041 }
05042 else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
05043 {
05044 if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
05045 {
05046 meta_topic (META_DEBUG_FOCUS,
05047 "Ignoring focus request for %s since %u "
05048 "is less than %u and %u.\n",
05049 window ? window->desc : "the no_focus_window",
05050 *timestamp,
05051 display->last_user_time,
05052 display->last_focus_time);
05053 return TRUE;
05054 }
05055 else
05056 {
05057 meta_topic (META_DEBUG_FOCUS,
05058 "Received focus request for %s which is newer than most "
05059 "recent user_time, but less recent than "
05060 "last_focus_time (%u < %u < %u); adjusting "
05061 "accordingly. (See bug 167358)\n",
05062 window ? window->desc : "the no_focus_window",
05063 display->last_user_time,
05064 *timestamp,
05065 display->last_focus_time);
05066 *timestamp = display->last_focus_time;
05067 return FALSE;
05068 }
05069 }
05070
05071 return FALSE;
05072 }
05073
05074 void
05075 meta_display_set_input_focus_window (MetaDisplay *display,
05076 MetaWindow *window,
05077 gboolean focus_frame,
05078 guint32 timestamp)
05079 {
05080 if (timestamp_too_old (display, window, ×tamp))
05081 return;
05082
05083 meta_error_trap_push (display);
05084 XSetInputFocus (display->xdisplay,
05085 focus_frame ? window->frame->xwindow : window->xwindow,
05086 RevertToPointerRoot,
05087 timestamp);
05088 meta_error_trap_pop (display, FALSE);
05089
05090 display->expected_focus_window = window;
05091 display->last_focus_time = timestamp;
05092 display->active_screen = window->screen;
05093
05094 if (window != display->autoraise_window)
05095 meta_display_remove_autoraise_callback (window->display);
05096 }
05097
05098 void
05099 meta_display_focus_the_no_focus_window (MetaDisplay *display,
05100 MetaScreen *screen,
05101 guint32 timestamp)
05102 {
05103 if (timestamp_too_old (display, NULL, ×tamp))
05104 return;
05105
05106 XSetInputFocus (display->xdisplay,
05107 screen->no_focus_window,
05108 RevertToPointerRoot,
05109 timestamp);
05110 display->expected_focus_window = NULL;
05111 display->last_focus_time = timestamp;
05112 display->active_screen = screen;
05113
05114 meta_display_remove_autoraise_callback (display);
05115 }
05116
05117 void
05118 meta_display_remove_autoraise_callback (MetaDisplay *display)
05119 {
05120 if (display->autoraise_timeout_id != 0)
05121 {
05122 g_source_remove (display->autoraise_timeout_id);
05123 display->autoraise_timeout_id = 0;
05124 display->autoraise_window = NULL;
05125 }
05126 }
05127
05128 #ifdef HAVE_COMPOSITE_EXTENSIONS
05129 void
05130 meta_display_get_compositor_version (MetaDisplay *display,
05131 int *major,
05132 int *minor)
05133 {
05134 *major = display->composite_major_version;
05135 *minor = display->composite_minor_version;
05136 }
05137 #endif
05138
05139 Display *
05140 meta_display_get_xdisplay (MetaDisplay *display)
05141 {
05142 return display->xdisplay;
05143 }
05144
05145 MetaCompositor *
05146 meta_display_get_compositor (MetaDisplay *display)
05147 {
05148 return display->compositor;
05149 }
05150
05151 GSList *
05152 meta_display_get_screens (MetaDisplay *display)
05153 {
05154 return display->screens;
05155 }
05156
05157 gboolean
05158 meta_display_has_shape (MetaDisplay *display)
05159 {
05160 return META_DISPLAY_HAS_SHAPE (display);
05161 }
05162
05163 MetaWindow *
05164 meta_display_get_focus_window (MetaDisplay *display)
05165 {
05166 return display->focus_window;
05167 }
05168
05169 #ifdef HAVE_COMPOSITE_EXTENSIONS
05170 int
05171 meta_display_get_damage_event_base (MetaDisplay *display)
05172 {
05173 return display->damage_event_base;
05174 }
05175 #endif
05176
05177 #ifdef HAVE_COMPOSITE_EXTENSIONS
05178 #ifdef HAVE_SHAPE
05179 int
05180 meta_display_get_shape_event_base (MetaDisplay *display)
05181 {
05182 return display->shape_event_base;
05183 }
05184 #endif
05185 #endif