Fix for the "mangles focus window when switching workspaces and using

2003-01-21  Havoc Pennington  <hp@pobox.com>

        Fix for the "mangles focus window when switching workspaces
	and using mouse focus" bug

	* src/stack.c (meta_stack_get_default_focus_window_at_point): new
	function

	* src/screen.c (meta_screen_focus_mouse_window): new function
	(meta_screen_focus_default_window): new function

	* src/workspace.c (meta_workspace_activate): use the
	new meta_screen_focus_default_window()

2003-01-17  Havoc Pennington  <hp@pobox.com>

	* src/window.c (meta_window_handle_mouse_grab_op_event): fix event
	compression code to use GDK algorithm suggested by Owen, should be
	more efficient.
This commit is contained in:
Havoc Pennington 2003-01-22 04:54:04 +00:00 committed by Havoc Pennington
parent 95d747269b
commit 82bd20911c
9 changed files with 219 additions and 69 deletions

View File

@ -1,3 +1,23 @@
2003-01-21 Havoc Pennington <hp@pobox.com>
Fix for the "mangles focus window when switching workspaces
and using mouse focus" bug
* src/stack.c (meta_stack_get_default_focus_window_at_point): new
function
* src/screen.c (meta_screen_focus_mouse_window): new function
(meta_screen_focus_default_window): new function
* src/workspace.c (meta_workspace_activate): use the
new meta_screen_focus_default_window()
2003-01-17 Havoc Pennington <hp@pobox.com>
* src/window.c (meta_window_handle_mouse_grab_op_event): fix event
compression code to use GDK algorithm suggested by Owen, should be
more efficient.
2003-01-22 Christian Rose <menthos@menthos.com> 2003-01-22 Christian Rose <menthos@menthos.com>
* configure.in: Added "mn" to ALL_LINGUAS. * configure.in: Added "mn" to ALL_LINGUAS.

View File

@ -2798,6 +2798,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_latest_motion_y = root_y; display->grab_latest_motion_y = root_y;
display->grab_last_moveresize_time.tv_sec = 0; display->grab_last_moveresize_time.tv_sec = 0;
display->grab_last_moveresize_time.tv_usec = 0; display->grab_last_moveresize_time.tv_usec = 0;
display->grab_motion_notify_time = 0;
#ifdef HAVE_XSYNC #ifdef HAVE_XSYNC
display->grab_update_alarm = None; display->grab_update_alarm = None;
#endif #endif

View File

@ -245,6 +245,7 @@ struct _MetaDisplay
MetaRectangle grab_current_window_pos; MetaRectangle grab_current_window_pos;
MetaResizePopup *grab_resize_popup; MetaResizePopup *grab_resize_popup;
GTimeVal grab_last_moveresize_time; GTimeVal grab_last_moveresize_time;
Time grab_motion_notify_time;
#ifdef HAVE_XSYNC #ifdef HAVE_XSYNC
/* alarm monitoring client's _METACITY_UPDATE_COUNTER */ /* alarm monitoring client's _METACITY_UPDATE_COUNTER */
XSyncAlarm grab_update_alarm; XSyncAlarm grab_update_alarm;

View File

@ -1220,6 +1220,66 @@ meta_screen_focus_top_window (MetaScreen *screen,
} }
} }
void
meta_screen_focus_mouse_window (MetaScreen *screen,
MetaWindow *not_this_one)
{
MetaWindow *window;
Window root_return, child_return;
int root_x_return, root_y_return;
int win_x_return, win_y_return;
unsigned int mask_return;
if (not_this_one)
meta_topic (META_DEBUG_FOCUS,
"Focusing mouse window excluding %s\n", not_this_one->desc);
meta_error_trap_push (screen->display);
XQueryPointer (screen->display->xdisplay,
screen->xroot,
&root_return,
&child_return,
&root_x_return,
&root_y_return,
&win_x_return,
&win_y_return,
&mask_return);
meta_error_trap_pop (screen->display, TRUE);
window = meta_stack_get_default_focus_window_at_point (screen->stack,
screen->active_workspace,
not_this_one,
root_x_return,
root_y_return);
/* FIXME I'm a loser on the CurrentTime front */
if (window)
{
meta_topic (META_DEBUG_FOCUS,
"Focusing mouse window %s\n", window->desc);
meta_window_focus (window, meta_display_get_current_time (screen->display));
/* Also raise the window if in click-to-focus */
if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
meta_window_raise (window);
}
else
{
meta_topic (META_DEBUG_FOCUS, "No mouse window to focus found\n");
}
}
void
meta_screen_focus_default_window (MetaScreen *screen,
MetaWindow *not_this_one)
{
if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
meta_screen_focus_top_window (screen, not_this_one);
else
meta_screen_focus_mouse_window (screen, not_this_one);
}
const MetaXineramaScreenInfo* const MetaXineramaScreenInfo*
meta_screen_get_xinerama_for_window (MetaScreen *screen, meta_screen_get_xinerama_for_window (MetaScreen *screen,
MetaWindow *window) MetaWindow *window)

View File

@ -124,8 +124,12 @@ void meta_screen_ensure_tab_popup (MetaScreen *scree
void meta_screen_ensure_workspace_popup (MetaScreen *screen); void meta_screen_ensure_workspace_popup (MetaScreen *screen);
void meta_screen_focus_top_window (MetaScreen *screen, void meta_screen_focus_top_window (MetaScreen *screen,
MetaWindow *not_this_one); MetaWindow *not_this_one);
void meta_screen_focus_mouse_window (MetaScreen *screen,
MetaWindow *not_this_one);
void meta_screen_focus_default_window (MetaScreen *screen,
MetaWindow *not_this_one);
const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen); const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen);
const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen, const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen,

View File

@ -1301,10 +1301,25 @@ meta_stack_get_below (MetaStack *stack,
return below; return below;
} }
MetaWindow* static gboolean
meta_stack_get_default_focus_window (MetaStack *stack, window_contains_point (MetaWindow *window,
MetaWorkspace *workspace, int root_x,
MetaWindow *not_this_one) int root_y)
{
MetaRectangle rect;
meta_window_get_outer_rect (window, &rect);
return POINT_IN_RECT (root_x, root_y, rect);
}
static MetaWindow*
get_default_focus_window (MetaStack *stack,
MetaWorkspace *workspace,
MetaWindow *not_this_one,
gboolean must_be_at_point,
int root_x,
int root_y)
{ {
/* Find the topmost, focusable, mapped, window. /* Find the topmost, focusable, mapped, window.
* not_this_one is being unfocused or going away, so exclude it. * not_this_one is being unfocused or going away, so exclude it.
@ -1353,12 +1368,16 @@ meta_stack_get_default_focus_window (MetaStack *stack,
{ {
if (transient_parent == NULL && if (transient_parent == NULL &&
not_this_one->xtransient_for != None && not_this_one->xtransient_for != None &&
not_this_one->xtransient_for == window->xwindow) not_this_one->xtransient_for == window->xwindow &&
(!must_be_at_point ||
window_contains_point (window, root_x, root_y)))
transient_parent = window; transient_parent = window;
if (topmost_in_group == NULL && if (topmost_in_group == NULL &&
not_this_one_group != NULL && not_this_one_group != NULL &&
not_this_one_group == meta_window_get_group (window)) not_this_one_group == meta_window_get_group (window) &&
(!must_be_at_point ||
window_contains_point (window, root_x, root_y)))
topmost_in_group = window; topmost_in_group = window;
} }
@ -1367,7 +1386,9 @@ meta_stack_get_default_focus_window (MetaStack *stack,
* focusing dock, even though docks are stacked higher. * focusing dock, even though docks are stacked higher.
*/ */
if (topmost_overall == NULL && if (topmost_overall == NULL &&
window->type != META_WINDOW_DOCK) window->type != META_WINDOW_DOCK &&
(!must_be_at_point ||
window_contains_point (window, root_x, root_y)))
topmost_overall = window; topmost_overall = window;
/* We could try to bail out early here for efficiency in /* We could try to bail out early here for efficiency in
@ -1388,6 +1409,26 @@ meta_stack_get_default_focus_window (MetaStack *stack,
return topmost_dock; return topmost_dock;
} }
MetaWindow*
meta_stack_get_default_focus_window_at_point (MetaStack *stack,
MetaWorkspace *workspace,
MetaWindow *not_this_one,
int root_x,
int root_y)
{
return get_default_focus_window (stack, workspace, not_this_one,
TRUE, root_x, root_y);
}
MetaWindow*
meta_stack_get_default_focus_window (MetaStack *stack,
MetaWorkspace *workspace,
MetaWindow *not_this_one)
{
return get_default_focus_window (stack, workspace, not_this_one,
FALSE, 0, 0);
}
GList* GList*
meta_stack_list_windows (MetaStack *stack, meta_stack_list_windows (MetaStack *stack,
MetaWorkspace *workspace) MetaWorkspace *workspace)

View File

@ -118,9 +118,16 @@ MetaWindow* meta_stack_get_above (MetaStack *stack,
MetaWindow* meta_stack_get_below (MetaStack *stack, MetaWindow* meta_stack_get_below (MetaStack *stack,
MetaWindow *window, MetaWindow *window,
gboolean only_within_layer); gboolean only_within_layer);
MetaWindow* meta_stack_get_default_focus_window (MetaStack *stack,
MetaWorkspace *workspace, MetaWindow* meta_stack_get_default_focus_window (MetaStack *stack,
MetaWindow *not_this_one); MetaWorkspace *workspace,
MetaWindow *not_this_one);
MetaWindow* meta_stack_get_default_focus_window_at_point (MetaStack *stack,
MetaWorkspace *workspace,
MetaWindow *not_this_one,
int root_x,
int root_y);
GList* meta_stack_list_windows (MetaStack *stack, GList* meta_stack_list_windows (MetaStack *stack,
MetaWorkspace *workspace); MetaWorkspace *workspace);

View File

@ -6315,61 +6315,78 @@ update_resize (MetaWindow *window,
typedef struct typedef struct
{ {
XEvent prev_event; const XEvent *current_event;
gboolean done;
int count; int count;
} CompressEventData; Time last_time;
} EventScannerData;
static Bool static Bool
compress_event_predicate (Display *display, find_last_time_predicate (Display *display,
XEvent *xevent, XEvent *xevent,
XPointer arg) XPointer arg)
{ {
CompressEventData *ced = (void*) arg; EventScannerData *esd = (void*) arg;
if (ced->done) if (esd->current_event->type == xevent->type &&
return False; esd->current_event->xany.window == xevent->xany.window)
else if (ced->prev_event.type == xevent->type &&
ced->prev_event.xany.window == xevent->xany.window)
{ {
ced->count += 1; esd->count += 1;
return True; esd->last_time = xevent->xmotion.time;
} }
else if (xevent->type != Expose &&
xevent->type != ConfigureNotify && return False;
xevent->type != PropertyNotify)
{
/* Don't compress across most unrelated events, just to be safe */
ced->done = TRUE;
return False;
}
else
return False;
} }
static void static gboolean
maybe_replace_with_newer_event (MetaWindow *window, check_use_this_motion_notify (MetaWindow *window,
XEvent *event) XEvent *event)
{ {
XEvent new_event; EventScannerData esd;
CompressEventData ced; XEvent useless;
/* Chew up all events of the same type on the same window */ /* This code is copied from Owen's GDK code. */
ced.count = 0; if (window->display->grab_motion_notify_time != 0)
ced.done = FALSE;
ced.prev_event = *event;
while (XCheckIfEvent (window->display->xdisplay,
&new_event,
compress_event_predicate,
(void*) &ced.prev_event))
ced.prev_event = new_event;
if (ced.count > 0)
{ {
meta_topic (META_DEBUG_RESIZING, /* == is really the right test, but I'm all for paranoia */
"Compressed %d motion events\n", ced.count); if (window->display->grab_motion_notify_time <=
*event = ced.prev_event; event->xmotion.time)
{
meta_topic (META_DEBUG_RESIZING,
"Arrived at event with time %lu (waiting for %lu), using it\n",
(unsigned long) event->xmotion.time,
(unsigned long) window->display->grab_motion_notify_time);
window->display->grab_motion_notify_time = 0;
return TRUE;
}
else
return FALSE; /* haven't reached the saved timestamp yet */
}
esd.current_event = event;
esd.count = 0;
esd.last_time = 0;
/* "useless" isn't filled in because the predicate never returns True */
XCheckIfEvent (window->display->xdisplay,
&useless,
find_last_time_predicate,
(XPointer) &esd);
if (esd.count > 0)
meta_topic (META_DEBUG_RESIZING,
"Will skip %d motion events and use the event with time %lu\n",
esd.count, (unsigned long) esd.last_time);
if (esd.last_time == 0)
return TRUE;
else
{
/* Save this timestamp, and ignore all motion notify
* until we get to the one with this stamp.
*/
window->display->grab_motion_notify_time = esd.last_time;
return FALSE;
} }
} }
@ -6443,21 +6460,23 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
{ {
if (event->xmotion.root == window->screen->xroot) if (event->xmotion.root == window->screen->xroot)
{ {
maybe_replace_with_newer_event (window, event); if (check_use_this_motion_notify (window,
update_move (window, event))
event->xmotion.state, update_move (window,
event->xmotion.x_root, event->xmotion.state,
event->xmotion.y_root); event->xmotion.x_root,
event->xmotion.y_root);
} }
} }
else if (meta_grab_op_is_resizing (window->display->grab_op)) else if (meta_grab_op_is_resizing (window->display->grab_op))
{ {
if (event->xmotion.root == window->screen->xroot) if (event->xmotion.root == window->screen->xroot)
{ {
maybe_replace_with_newer_event (window, event); if (check_use_this_motion_notify (window,
update_resize (window, event))
event->xmotion.x_root, update_resize (window,
event->xmotion.y_root); event->xmotion.x_root,
event->xmotion.y_root);
} }
} }
break; break;

View File

@ -216,11 +216,8 @@ meta_workspace_activate (MetaWorkspace *workspace)
meta_workspace_queue_calc_showing (old); meta_workspace_queue_calc_showing (old);
meta_workspace_queue_calc_showing (workspace); meta_workspace_queue_calc_showing (workspace);
/* in mouse focus modes, this will probably get undone by an EnterNotify, meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
* but that's OK meta_screen_focus_default_window (workspace->screen, NULL);
*/
meta_topic (META_DEBUG_FOCUS, "Focusing top window on new workspace\n");
meta_screen_focus_top_window (workspace->screen, NULL);
} }
int int