Add hacking to fix the problem that we made our XGrabPointer() during

2002-03-02  Havoc Pennington  <hp@pobox.com>

	* 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.
This commit is contained in:
Havoc Pennington 2002-03-02 15:26:07 +00:00 committed by Havoc Pennington
parent efa0ae8373
commit ac2aa5337d
7 changed files with 167 additions and 45 deletions

View File

@ -1,3 +1,11 @@
2002-03-02 Havoc Pennington <hp@pobox.com>
* 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 <hp@pobox.com> 2002-02-26 Havoc Pennington <hp@pobox.com>
Screw around with Anders's ping patch so he'll get plenty of CVS Screw around with Anders's ping patch so he'll get plenty of CVS

View File

@ -143,6 +143,7 @@ meta_display_open (const char *name)
Display *xdisplay; Display *xdisplay;
GSList *screens; GSList *screens;
GSList *tmp; GSList *tmp;
int i;
/* Remember to edit code that assigns each atom to display struct /* Remember to edit code that assigns each atom to display struct
* when adding an atom name here. * when adding an atom name here.
*/ */
@ -376,7 +377,14 @@ meta_display_open (const char *name)
display->last_button_num = 0; display->last_button_num = 0;
display->is_double_click = FALSE; 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->current_time = CurrentTime;
display->grab_op = META_GRAB_OP_NONE; display->grab_op = META_GRAB_OP_NONE;
@ -721,6 +729,58 @@ meta_display_get_current_time (MetaDisplay *display)
return display->current_time; 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 static gboolean
event_callback (XEvent *event, event_callback (XEvent *event,
gpointer data) gpointer data)
@ -738,6 +798,8 @@ event_callback (XEvent *event,
filter_out_event = FALSE; filter_out_event = FALSE;
display->current_time = event_get_time (display, event); display->current_time = event_get_time (display, event);
modified = event_get_modified_window (display, event);
if (event->type == ButtonPress) if (event->type == ButtonPress)
{ {
@ -768,16 +830,23 @@ event_callback (XEvent *event,
else if (event->type == UnmapNotify) else if (event->type == UnmapNotify)
{ {
if (meta_ui_window_should_not_cause_focus (display->xdisplay, 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, meta_topic (META_DEBUG_FOCUS,
"Will not focus on EnterNotify with serial %lu\n", "Adding EnterNotify serial %lu to ignored focus serials\n",
display->last_ignored_unmap_serial); event->xany.serial);
} }
} }
else if (event->type == LeaveNotify &&
modified = event_get_modified_window (display, event); 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) if (modified != None)
window = meta_display_lookup_x_window (display, modified); window = meta_display_lookup_x_window (display, modified);
@ -914,7 +983,7 @@ event_callback (XEvent *event,
break; break;
case EnterNotify: case EnterNotify:
/* do this even if window->has_focus to avoid races */ /* 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 ()) switch (meta_prefs_get_focus_mode ())
{ {
@ -924,9 +993,12 @@ event_callback (XEvent *event,
window->type != META_WINDOW_DESKTOP) window->type != META_WINDOW_DESKTOP)
{ {
meta_topic (META_DEBUG_FOCUS, meta_topic (META_DEBUG_FOCUS,
"Focusing %s due to enter notify\n", "Focusing %s due to enter notify with serial %lu\n",
window->desc); window->desc, event->xany.serial);
meta_window_focus (window, event->xcrossing.time); meta_window_focus (window, event->xcrossing.time);
/* stop ignoring stuff */
reset_ignores (display);
} }
break; break;
case META_FOCUS_MODE_CLICK: case META_FOCUS_MODE_CLICK:
@ -985,8 +1057,8 @@ event_callback (XEvent *event,
event->type == FocusOut ? "out" : event->type == FocusOut ? "out" :
"???", "???",
event->xany.window, event->xany.window,
meta_focus_mode_to_string (event->xfocus.mode), meta_event_mode_to_string (event->xfocus.mode),
meta_focus_detail_to_string (event->xfocus.mode)); meta_event_detail_to_string (event->xfocus.mode));
} }
else if (meta_display_screen_for_root (display, else if (meta_display_screen_for_root (display,
event->xany.window) != NULL) event->xany.window) != NULL)
@ -998,8 +1070,8 @@ event_callback (XEvent *event,
event->type == FocusOut ? "out" : event->type == FocusOut ? "out" :
"???", "???",
event->xany.window, event->xany.window,
meta_focus_mode_to_string (event->xfocus.mode), meta_event_mode_to_string (event->xfocus.mode),
meta_focus_detail_to_string (event->xfocus.mode)); meta_event_detail_to_string (event->xfocus.mode));
} }
break; break;
case KeymapNotify: case KeymapNotify:
@ -1358,7 +1430,7 @@ event_get_time (MetaDisplay *display,
} }
const char* const char*
meta_focus_detail_to_string (int d) meta_event_detail_to_string (int d)
{ {
const char *detail = "???"; const char *detail = "???";
switch (d) switch (d)
@ -1395,7 +1467,7 @@ meta_focus_detail_to_string (int d)
} }
const char* const char*
meta_focus_mode_to_string (int m) meta_event_mode_to_string (int m)
{ {
const char *mode = "???"; const char *mode = "???";
switch (m) switch (m)
@ -1473,33 +1545,35 @@ meta_spew_event (MetaDisplay *display,
break; break;
case EnterNotify: case EnterNotify:
name = "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.window,
event->xcrossing.root, event->xcrossing.root,
event->xcrossing.subwindow, event->xcrossing.subwindow,
event->xcrossing.mode, meta_event_mode_to_string (event->xcrossing.mode),
event->xcrossing.detail); meta_event_detail_to_string (event->xcrossing.detail),
event->xcrossing.focus);
break; break;
case LeaveNotify: case LeaveNotify:
name = "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.window,
event->xcrossing.root, event->xcrossing.root,
event->xcrossing.subwindow, event->xcrossing.subwindow,
event->xcrossing.mode, meta_event_mode_to_string (event->xcrossing.mode),
event->xcrossing.detail); meta_event_detail_to_string (event->xcrossing.detail),
event->xcrossing.focus);
break; break;
case FocusIn: case FocusIn:
name = "FocusIn"; name = "FocusIn";
extra = g_strdup_printf ("detail: %s mode: %s\n", extra = g_strdup_printf ("detail: %s mode: %s\n",
meta_focus_detail_to_string (event->xfocus.detail), meta_event_detail_to_string (event->xfocus.detail),
meta_focus_mode_to_string (event->xfocus.mode)); meta_event_mode_to_string (event->xfocus.mode));
break; break;
case FocusOut: case FocusOut:
name = "FocusOut"; name = "FocusOut";
extra = g_strdup_printf ("detail: %s mode: %s\n", extra = g_strdup_printf ("detail: %s mode: %s\n",
meta_focus_detail_to_string (event->xfocus.detail), meta_event_detail_to_string (event->xfocus.detail),
meta_focus_mode_to_string (event->xfocus.mode)); meta_event_mode_to_string (event->xfocus.mode));
break; break;
case KeymapNotify: case KeymapNotify:
name = "KeymapNotify"; name = "KeymapNotify";
@ -1631,8 +1705,8 @@ meta_spew_event (MetaDisplay *display,
name = "MappingNotify"; name = "MappingNotify";
break; break;
default: default:
meta_verbose ("Unknown event type %d\n", event->xany.type); name = "(Unknown event)";
name = "Unknown event type"; extra = g_strdup_printf ("type: %d", event->xany.type);
break; break;
} }
@ -1644,8 +1718,9 @@ meta_spew_event (MetaDisplay *display,
winname = g_strdup_printf ("0x%lx", event->xany.window); winname = g_strdup_printf ("0x%lx", event->xany.window);
meta_topic (META_DEBUG_EVENTS, 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 : "", extra ? ":" : "", extra ? extra : "",
event->xany.send_event ? "SEND " : "",
event->xany.serial); event->xany.serial);
g_free (winname); g_free (winname);
@ -1832,15 +1907,13 @@ meta_display_begin_grab_op (MetaDisplay *display,
int root_x, int root_x,
int root_y) int root_y)
{ {
Window grabwindow; Window grab_xwindow;
Cursor cursor; Cursor cursor;
meta_topic (META_DEBUG_WINDOW_OPS, meta_topic (META_DEBUG_WINDOW_OPS,
"Doing grab op %d on window %s button %d pointer already grabbed: %d\n", "Doing grab op %d on window %s button %d pointer already grabbed: %d\n",
op, window->desc, button, pointer_already_grabbed); op, window->desc, button, pointer_already_grabbed);
grabwindow = window->frame ? window->frame->xwindow : window->xwindow;
if (display->grab_op != META_GRAB_OP_NONE) 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", 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; return FALSE;
} }
grab_xwindow = window->frame ? window->frame->xwindow : window->xwindow;
if (pointer_already_grabbed) if (pointer_already_grabbed)
display->grab_have_pointer = TRUE; display->grab_have_pointer = TRUE;
@ -1858,7 +1933,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
meta_error_trap_push (display); meta_error_trap_push (display);
if (XGrabPointer (display->xdisplay, if (XGrabPointer (display->xdisplay,
grabwindow, grab_xwindow,
False, False,
GRAB_MASK, GRAB_MASK,
GrabModeAsync, GrabModeAsync, GrabModeAsync, GrabModeAsync,
@ -1903,6 +1978,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_op = op; display->grab_op = op;
display->grab_window = window; display->grab_window = window;
display->grab_xwindow = grab_xwindow;
display->grab_button = button; display->grab_button = button;
display->grab_root_x = root_x; display->grab_root_x = root_x;
display->grab_root_y = root_y; 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); meta_ui_tab_popup_free (display->grab_window->screen->tab_popup);
display->grab_window->screen->tab_popup = NULL; 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) 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) 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_window = NULL;
display->grab_xwindow = None;
display->grab_op = META_GRAB_OP_NONE; display->grab_op = META_GRAB_OP_NONE;
} }

View File

@ -57,6 +57,13 @@ typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
#define _NET_WM_STATE_ADD 1 /* add/set property */ #define _NET_WM_STATE_ADD 1 /* add/set property */
#define _NET_WM_STATE_TOGGLE 2 /* toggle 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 struct _MetaDisplay
{ {
char *name; char *name;
@ -155,8 +162,13 @@ struct _MetaDisplay
int last_button_num; int last_button_num;
guint is_double_click : 1; 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; guint32 current_time;
/* Pings which we're waiting for a reply from */ /* Pings which we're waiting for a reply from */
@ -165,6 +177,7 @@ struct _MetaDisplay
/* current window operation */ /* current window operation */
MetaGrabOp grab_op; MetaGrabOp grab_op;
MetaWindow *grab_window; MetaWindow *grab_window;
Window grab_xwindow;
int grab_button; int grab_button;
int grab_root_x; int grab_root_x;
int grab_root_y; int grab_root_y;
@ -243,8 +256,8 @@ void meta_display_unshow_desktop (MetaDisplay *display);
guint32 meta_display_get_current_time (MetaDisplay *display); guint32 meta_display_get_current_time (MetaDisplay *display);
/* utility goo */ /* utility goo */
const char* meta_focus_mode_to_string (int m); const char* meta_event_mode_to_string (int m);
const char* meta_focus_detail_to_string (int d); const char* meta_event_detail_to_string (int d);
void meta_display_queue_retheme_all_windows (MetaDisplay *display); void meta_display_queue_retheme_all_windows (MetaDisplay *display);
void meta_display_retheme_all (void); void meta_display_retheme_all (void);

View File

@ -426,17 +426,21 @@ meta_window_ungrab_all_keys (MetaWindow *window)
if (window->all_keys_grabbed) if (window->all_keys_grabbed)
{ {
Window grabwindow; Window grabwindow;
Time timestamp;
grabwindow = (window->frame && window->grab_on_frame) ? grabwindow = (window->frame && window->grab_on_frame) ?
window->frame->xwindow : window->xwindow; window->frame->xwindow : window->xwindow;
timestamp = meta_display_get_current_time (window->display);
meta_error_trap_push (window->display); meta_error_trap_push (window->display);
XUngrabKey (window->display->xdisplay, XUngrabKey (window->display->xdisplay,
AnyKey, AnyModifier, AnyKey, AnyModifier,
grabwindow); grabwindow);
XUngrabKeyboard (window->display->xdisplay, meta_verbose ("Ungrabbing keyboard with timestamp %lu\n",
meta_display_get_current_time (window->display)); timestamp);
XUngrabKeyboard (window->display->xdisplay, timestamp);
meta_error_trap_pop (window->display); meta_error_trap_pop (window->display);
window->grab_on_frame = FALSE; window->grab_on_frame = FALSE;

View File

@ -258,6 +258,8 @@ free_entry (gpointer data, gpointer user_data)
void void
meta_ui_tab_popup_free (MetaTabPopup *popup) meta_ui_tab_popup_free (MetaTabPopup *popup)
{ {
meta_verbose ("Destroying tab popup window\n");
gtk_widget_destroy (popup->outline_window); gtk_widget_destroy (popup->outline_window);
gtk_widget_destroy (popup->window); gtk_widget_destroy (popup->window);
@ -273,9 +275,12 @@ meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
gboolean showing) gboolean showing)
{ {
if (showing) if (showing)
gtk_widget_show_all (popup->window); {
gtk_widget_show_all (popup->window);
}
else else
{ {
meta_verbose ("Hiding tab popup window\n");
gtk_widget_hide (popup->window); gtk_widget_hide (popup->window);
meta_core_increment_event_serial (gdk_display); meta_core_increment_event_serial (gdk_display);
} }

View File

@ -165,7 +165,8 @@ topic_name (MetaDebugTopic topic)
return "PLACEMENT"; return "PLACEMENT";
case META_DEBUG_GEOMETRY: case META_DEBUG_GEOMETRY:
return "GEOMETRY"; return "GEOMETRY";
break; case META_DEBUG_PING:
return "PING";
} }
return "Window manager"; return "Window manager";

View File

@ -3151,9 +3151,9 @@ meta_window_notify_focus (MetaWindow *window,
"frame window" : "frame window" :
"unknown window", "unknown window",
event->type != UnmapNotify ? 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 ? 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 || if ((event->type == FocusIn ||
event->type == FocusOut) && event->type == FocusOut) &&