diff --git a/ChangeLog b/ChangeLog index 37b218b79..9f8aab794 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2002-03-02 Havoc Pennington + + * src/display.c: Add hacking to fix the problem that we made our + XGrabPointer() during Alt+Tab actually succeed, so on popping down + Alt+Tab we got an EnterNotify from the ungrab, which resulted in + focusing the window under the mouse. i.e. Alt+Tab didn't work with + sloppy focus. + 2002-02-26 Havoc Pennington Screw around with Anders's ping patch so he'll get plenty of CVS diff --git a/src/display.c b/src/display.c index 4f226263b..c48554e1e 100644 --- a/src/display.c +++ b/src/display.c @@ -143,6 +143,7 @@ meta_display_open (const char *name) Display *xdisplay; GSList *screens; GSList *tmp; + int i; /* Remember to edit code that assigns each atom to display struct * when adding an atom name here. */ @@ -376,7 +377,14 @@ meta_display_open (const char *name) display->last_button_num = 0; display->is_double_click = FALSE; - display->last_ignored_unmap_serial = 0; + i = 0; + while (i < N_IGNORED_SERIALS) + { + display->ignored_serials[i] = 0; + ++i; + } + display->ungrab_should_not_cause_focus_window = None; + display->current_time = CurrentTime; display->grab_op = META_GRAB_OP_NONE; @@ -721,6 +729,58 @@ meta_display_get_current_time (MetaDisplay *display) return display->current_time; } +static void +add_ignored_serial (MetaDisplay *display, + unsigned long serial) +{ + int i; + + /* don't add the same serial more than once */ + if (display->ignored_serials[N_IGNORED_SERIALS-1] == serial) + return; + + /* shift serials to the left */ + i = 0; + while (i < (N_IGNORED_SERIALS - 1)) + { + display->ignored_serials[i] = display->ignored_serials[i+1]; + ++i; + } + /* put new one on the end */ + display->ignored_serials[i] = serial; +} + +static gboolean +serial_is_ignored (MetaDisplay *display, + unsigned long serial) +{ + int i; + + i = 0; + while (i < N_IGNORED_SERIALS) + { + if (display->ignored_serials[i] == serial) + return TRUE; + ++i; + } + return FALSE; +} + +static void +reset_ignores (MetaDisplay *display) +{ + int i; + + i = 0; + while (i < N_IGNORED_SERIALS) + { + display->ignored_serials[i] = 0; + ++i; + } + + display->ungrab_should_not_cause_focus_window = None; +} + static gboolean event_callback (XEvent *event, gpointer data) @@ -738,6 +798,8 @@ event_callback (XEvent *event, filter_out_event = FALSE; display->current_time = event_get_time (display, event); + + modified = event_get_modified_window (display, event); if (event->type == ButtonPress) { @@ -768,16 +830,23 @@ event_callback (XEvent *event, else if (event->type == UnmapNotify) { if (meta_ui_window_should_not_cause_focus (display->xdisplay, - event->xunmap.window)) + modified)) { - display->last_ignored_unmap_serial = event->xany.serial; + add_ignored_serial (display, event->xany.serial); meta_topic (META_DEBUG_FOCUS, - "Will not focus on EnterNotify with serial %lu\n", - display->last_ignored_unmap_serial); + "Adding EnterNotify serial %lu to ignored focus serials\n", + event->xany.serial); } } - - modified = event_get_modified_window (display, event); + else if (event->type == LeaveNotify && + event->xcrossing.mode == NotifyUngrab && + modified == display->ungrab_should_not_cause_focus_window) + { + add_ignored_serial (display, event->xany.serial); + meta_topic (META_DEBUG_FOCUS, + "Adding LeaveNotify serial %lu to ignored focus serials\n", + event->xany.serial); + } if (modified != None) window = meta_display_lookup_x_window (display, modified); @@ -914,7 +983,7 @@ event_callback (XEvent *event, break; case EnterNotify: /* do this even if window->has_focus to avoid races */ - if (window && event->xany.serial != display->last_ignored_unmap_serial) + if (window && !serial_is_ignored (display, event->xany.serial)) { switch (meta_prefs_get_focus_mode ()) { @@ -924,9 +993,12 @@ event_callback (XEvent *event, window->type != META_WINDOW_DESKTOP) { meta_topic (META_DEBUG_FOCUS, - "Focusing %s due to enter notify\n", - window->desc); + "Focusing %s due to enter notify with serial %lu\n", + window->desc, event->xany.serial); meta_window_focus (window, event->xcrossing.time); + + /* stop ignoring stuff */ + reset_ignores (display); } break; case META_FOCUS_MODE_CLICK: @@ -985,8 +1057,8 @@ event_callback (XEvent *event, event->type == FocusOut ? "out" : "???", event->xany.window, - meta_focus_mode_to_string (event->xfocus.mode), - meta_focus_detail_to_string (event->xfocus.mode)); + meta_event_mode_to_string (event->xfocus.mode), + meta_event_detail_to_string (event->xfocus.mode)); } else if (meta_display_screen_for_root (display, event->xany.window) != NULL) @@ -998,8 +1070,8 @@ event_callback (XEvent *event, event->type == FocusOut ? "out" : "???", event->xany.window, - meta_focus_mode_to_string (event->xfocus.mode), - meta_focus_detail_to_string (event->xfocus.mode)); + meta_event_mode_to_string (event->xfocus.mode), + meta_event_detail_to_string (event->xfocus.mode)); } break; case KeymapNotify: @@ -1358,7 +1430,7 @@ event_get_time (MetaDisplay *display, } const char* -meta_focus_detail_to_string (int d) +meta_event_detail_to_string (int d) { const char *detail = "???"; switch (d) @@ -1395,7 +1467,7 @@ meta_focus_detail_to_string (int d) } const char* -meta_focus_mode_to_string (int m) +meta_event_mode_to_string (int m) { const char *mode = "???"; switch (m) @@ -1473,33 +1545,35 @@ meta_spew_event (MetaDisplay *display, break; case EnterNotify: name = "EnterNotify"; - extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d", + extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %s detail: %s focus: %d", event->xcrossing.window, event->xcrossing.root, event->xcrossing.subwindow, - event->xcrossing.mode, - event->xcrossing.detail); + meta_event_mode_to_string (event->xcrossing.mode), + meta_event_detail_to_string (event->xcrossing.detail), + event->xcrossing.focus); break; case LeaveNotify: name = "LeaveNotify"; - extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d", + extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %s detail: %s focus: %d", event->xcrossing.window, event->xcrossing.root, event->xcrossing.subwindow, - event->xcrossing.mode, - event->xcrossing.detail); + meta_event_mode_to_string (event->xcrossing.mode), + meta_event_detail_to_string (event->xcrossing.detail), + event->xcrossing.focus); break; case FocusIn: name = "FocusIn"; extra = g_strdup_printf ("detail: %s mode: %s\n", - meta_focus_detail_to_string (event->xfocus.detail), - meta_focus_mode_to_string (event->xfocus.mode)); + meta_event_detail_to_string (event->xfocus.detail), + meta_event_mode_to_string (event->xfocus.mode)); break; case FocusOut: name = "FocusOut"; extra = g_strdup_printf ("detail: %s mode: %s\n", - meta_focus_detail_to_string (event->xfocus.detail), - meta_focus_mode_to_string (event->xfocus.mode)); + meta_event_detail_to_string (event->xfocus.detail), + meta_event_mode_to_string (event->xfocus.mode)); break; case KeymapNotify: name = "KeymapNotify"; @@ -1631,8 +1705,8 @@ meta_spew_event (MetaDisplay *display, name = "MappingNotify"; break; default: - meta_verbose ("Unknown event type %d\n", event->xany.type); - name = "Unknown event type"; + name = "(Unknown event)"; + extra = g_strdup_printf ("type: %d", event->xany.type); break; } @@ -1644,8 +1718,9 @@ meta_spew_event (MetaDisplay *display, winname = g_strdup_printf ("0x%lx", event->xany.window); meta_topic (META_DEBUG_EVENTS, - "%s on %s%s %s serial %lu\n", name, winname, + "%s on %s%s %s %sserial %lu\n", name, winname, extra ? ":" : "", extra ? extra : "", + event->xany.send_event ? "SEND " : "", event->xany.serial); g_free (winname); @@ -1832,15 +1907,13 @@ meta_display_begin_grab_op (MetaDisplay *display, int root_x, int root_y) { - Window grabwindow; + Window grab_xwindow; Cursor cursor; meta_topic (META_DEBUG_WINDOW_OPS, "Doing grab op %d on window %s button %d pointer already grabbed: %d\n", op, window->desc, button, pointer_already_grabbed); - grabwindow = window->frame ? window->frame->xwindow : window->xwindow; - if (display->grab_op != META_GRAB_OP_NONE) { meta_warning ("Attempt to perform window operation %d on window %s when operation %d on %s already in effect\n", @@ -1848,6 +1921,8 @@ meta_display_begin_grab_op (MetaDisplay *display, return FALSE; } + grab_xwindow = window->frame ? window->frame->xwindow : window->xwindow; + if (pointer_already_grabbed) display->grab_have_pointer = TRUE; @@ -1858,7 +1933,7 @@ meta_display_begin_grab_op (MetaDisplay *display, meta_error_trap_push (display); if (XGrabPointer (display->xdisplay, - grabwindow, + grab_xwindow, False, GRAB_MASK, GrabModeAsync, GrabModeAsync, @@ -1903,6 +1978,7 @@ meta_display_begin_grab_op (MetaDisplay *display, display->grab_op = op; display->grab_window = window; + display->grab_xwindow = grab_xwindow; display->grab_button = button; display->grab_root_x = root_x; display->grab_root_y = root_y; @@ -1936,15 +2012,30 @@ meta_display_end_grab_op (MetaDisplay *display, { meta_ui_tab_popup_free (display->grab_window->screen->tab_popup); display->grab_window->screen->tab_popup = NULL; + + /* If the ungrab here causes an EnterNotify, ignore it for + * sloppy focus + */ + display->ungrab_should_not_cause_focus_window = display->grab_xwindow; } if (display->grab_have_pointer) - XUngrabPointer (display->xdisplay, timestamp); + { + meta_topic (META_DEBUG_WINDOW_OPS, + "Ungrabbing pointer with timestamp %lu\n", + timestamp); + XUngrabPointer (display->xdisplay, timestamp); + } if (display->grab_have_keyboard) - meta_window_ungrab_all_keys (display->grab_window); + { + meta_topic (META_DEBUG_WINDOW_OPS, + "Ungrabbing all keys\n"); + meta_window_ungrab_all_keys (display->grab_window); + } display->grab_window = NULL; + display->grab_xwindow = None; display->grab_op = META_GRAB_OP_NONE; } diff --git a/src/display.h b/src/display.h index 669bfb1e7..167bef4e5 100644 --- a/src/display.h +++ b/src/display.h @@ -57,6 +57,13 @@ typedef void (* MetaWindowPingFunc) (MetaDisplay *display, #define _NET_WM_STATE_ADD 1 /* add/set property */ #define _NET_WM_STATE_TOGGLE 2 /* toggle property */ +/* This is basically a bogus number, just has to be large enough + * to handle the expected case of the alt+tab operation, where + * we want to ignore serials from UnmapNotify on the tab popup, + * and the LeaveNotify/EnterNotify from the pointer ungrab + */ +#define N_IGNORED_SERIALS 4 + struct _MetaDisplay { char *name; @@ -155,8 +162,13 @@ struct _MetaDisplay int last_button_num; guint is_double_click : 1; - unsigned long last_ignored_unmap_serial; - + /* serials of leave/unmap events that may + * correspond to an enter event we should + * ignore + */ + unsigned long ignored_serials[N_IGNORED_SERIALS]; + Window ungrab_should_not_cause_focus_window; + guint32 current_time; /* Pings which we're waiting for a reply from */ @@ -165,6 +177,7 @@ struct _MetaDisplay /* current window operation */ MetaGrabOp grab_op; MetaWindow *grab_window; + Window grab_xwindow; int grab_button; int grab_root_x; int grab_root_y; @@ -243,8 +256,8 @@ void meta_display_unshow_desktop (MetaDisplay *display); guint32 meta_display_get_current_time (MetaDisplay *display); /* utility goo */ -const char* meta_focus_mode_to_string (int m); -const char* meta_focus_detail_to_string (int d); +const char* meta_event_mode_to_string (int m); +const char* meta_event_detail_to_string (int d); void meta_display_queue_retheme_all_windows (MetaDisplay *display); void meta_display_retheme_all (void); diff --git a/src/keybindings.c b/src/keybindings.c index 7ec20b0fa..423e54039 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -426,17 +426,21 @@ meta_window_ungrab_all_keys (MetaWindow *window) if (window->all_keys_grabbed) { Window grabwindow; + Time timestamp; grabwindow = (window->frame && window->grab_on_frame) ? window->frame->xwindow : window->xwindow; + + timestamp = meta_display_get_current_time (window->display); meta_error_trap_push (window->display); XUngrabKey (window->display->xdisplay, AnyKey, AnyModifier, grabwindow); - XUngrabKeyboard (window->display->xdisplay, - meta_display_get_current_time (window->display)); + meta_verbose ("Ungrabbing keyboard with timestamp %lu\n", + timestamp); + XUngrabKeyboard (window->display->xdisplay, timestamp); meta_error_trap_pop (window->display); window->grab_on_frame = FALSE; diff --git a/src/tabpopup.c b/src/tabpopup.c index ddd7553f3..c5db90203 100644 --- a/src/tabpopup.c +++ b/src/tabpopup.c @@ -258,6 +258,8 @@ free_entry (gpointer data, gpointer user_data) void meta_ui_tab_popup_free (MetaTabPopup *popup) { + meta_verbose ("Destroying tab popup window\n"); + gtk_widget_destroy (popup->outline_window); gtk_widget_destroy (popup->window); @@ -273,9 +275,12 @@ meta_ui_tab_popup_set_showing (MetaTabPopup *popup, gboolean showing) { if (showing) - gtk_widget_show_all (popup->window); + { + gtk_widget_show_all (popup->window); + } else { + meta_verbose ("Hiding tab popup window\n"); gtk_widget_hide (popup->window); meta_core_increment_event_serial (gdk_display); } diff --git a/src/util.c b/src/util.c index db4ae6b1a..54fb3b744 100644 --- a/src/util.c +++ b/src/util.c @@ -165,7 +165,8 @@ topic_name (MetaDebugTopic topic) return "PLACEMENT"; case META_DEBUG_GEOMETRY: return "GEOMETRY"; - break; + case META_DEBUG_PING: + return "PING"; } return "Window manager"; diff --git a/src/window.c b/src/window.c index e2aa4a004..a2fdb9f95 100644 --- a/src/window.c +++ b/src/window.c @@ -3151,9 +3151,9 @@ meta_window_notify_focus (MetaWindow *window, "frame window" : "unknown window", event->type != UnmapNotify ? - meta_focus_mode_to_string (event->xfocus.mode) : "n/a", + meta_event_mode_to_string (event->xfocus.mode) : "n/a", event->type != UnmapNotify ? - meta_focus_detail_to_string (event->xfocus.detail) : "n/a"); + meta_event_detail_to_string (event->xfocus.detail) : "n/a"); if ((event->type == FocusIn || event->type == FocusOut) &&