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:
parent
95d747269b
commit
82bd20911c
20
ChangeLog
20
ChangeLog
@ -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>
|
||||
|
||||
* configure.in: Added "mn" to ALL_LINGUAS.
|
||||
|
@ -2798,6 +2798,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
display->grab_latest_motion_y = root_y;
|
||||
display->grab_last_moveresize_time.tv_sec = 0;
|
||||
display->grab_last_moveresize_time.tv_usec = 0;
|
||||
display->grab_motion_notify_time = 0;
|
||||
#ifdef HAVE_XSYNC
|
||||
display->grab_update_alarm = None;
|
||||
#endif
|
||||
|
@ -245,6 +245,7 @@ struct _MetaDisplay
|
||||
MetaRectangle grab_current_window_pos;
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
Time grab_motion_notify_time;
|
||||
#ifdef HAVE_XSYNC
|
||||
/* alarm monitoring client's _METACITY_UPDATE_COUNTER */
|
||||
XSyncAlarm grab_update_alarm;
|
||||
|
60
src/screen.c
60
src/screen.c
@ -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*
|
||||
meta_screen_get_xinerama_for_window (MetaScreen *screen,
|
||||
MetaWindow *window)
|
||||
|
@ -124,8 +124,12 @@ void meta_screen_ensure_tab_popup (MetaScreen *scree
|
||||
|
||||
void meta_screen_ensure_workspace_popup (MetaScreen *screen);
|
||||
|
||||
void meta_screen_focus_top_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one);
|
||||
void meta_screen_focus_top_window (MetaScreen *screen,
|
||||
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_xinerama_for_window (MetaScreen *screen,
|
||||
|
57
src/stack.c
57
src/stack.c
@ -1299,12 +1299,27 @@ meta_stack_get_below (MetaStack *stack,
|
||||
return NULL;
|
||||
else
|
||||
return below;
|
||||
}
|
||||
}
|
||||
|
||||
MetaWindow*
|
||||
meta_stack_get_default_focus_window (MetaStack *stack,
|
||||
MetaWorkspace *workspace,
|
||||
MetaWindow *not_this_one)
|
||||
static gboolean
|
||||
window_contains_point (MetaWindow *window,
|
||||
int root_x,
|
||||
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.
|
||||
* 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 &&
|
||||
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;
|
||||
|
||||
if (topmost_in_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;
|
||||
}
|
||||
|
||||
@ -1367,7 +1386,9 @@ meta_stack_get_default_focus_window (MetaStack *stack,
|
||||
* focusing dock, even though docks are stacked higher.
|
||||
*/
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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*
|
||||
meta_stack_list_windows (MetaStack *stack,
|
||||
MetaWorkspace *workspace)
|
||||
|
13
src/stack.h
13
src/stack.h
@ -118,9 +118,16 @@ MetaWindow* meta_stack_get_above (MetaStack *stack,
|
||||
MetaWindow* meta_stack_get_below (MetaStack *stack,
|
||||
MetaWindow *window,
|
||||
gboolean only_within_layer);
|
||||
MetaWindow* meta_stack_get_default_focus_window (MetaStack *stack,
|
||||
MetaWorkspace *workspace,
|
||||
MetaWindow *not_this_one);
|
||||
|
||||
MetaWindow* meta_stack_get_default_focus_window (MetaStack *stack,
|
||||
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,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
|
121
src/window.c
121
src/window.c
@ -6315,61 +6315,78 @@ update_resize (MetaWindow *window,
|
||||
|
||||
typedef struct
|
||||
{
|
||||
XEvent prev_event;
|
||||
gboolean done;
|
||||
const XEvent *current_event;
|
||||
int count;
|
||||
} CompressEventData;
|
||||
Time last_time;
|
||||
} EventScannerData;
|
||||
|
||||
static Bool
|
||||
compress_event_predicate (Display *display,
|
||||
find_last_time_predicate (Display *display,
|
||||
XEvent *xevent,
|
||||
XPointer arg)
|
||||
{
|
||||
CompressEventData *ced = (void*) arg;
|
||||
|
||||
if (ced->done)
|
||||
return False;
|
||||
else if (ced->prev_event.type == xevent->type &&
|
||||
ced->prev_event.xany.window == xevent->xany.window)
|
||||
EventScannerData *esd = (void*) arg;
|
||||
|
||||
if (esd->current_event->type == xevent->type &&
|
||||
esd->current_event->xany.window == xevent->xany.window)
|
||||
{
|
||||
ced->count += 1;
|
||||
return True;
|
||||
esd->count += 1;
|
||||
esd->last_time = xevent->xmotion.time;
|
||||
}
|
||||
else if (xevent->type != Expose &&
|
||||
xevent->type != ConfigureNotify &&
|
||||
xevent->type != PropertyNotify)
|
||||
{
|
||||
/* Don't compress across most unrelated events, just to be safe */
|
||||
ced->done = TRUE;
|
||||
return False;
|
||||
}
|
||||
else
|
||||
return False;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_replace_with_newer_event (MetaWindow *window,
|
||||
XEvent *event)
|
||||
static gboolean
|
||||
check_use_this_motion_notify (MetaWindow *window,
|
||||
XEvent *event)
|
||||
{
|
||||
XEvent new_event;
|
||||
CompressEventData ced;
|
||||
EventScannerData esd;
|
||||
XEvent useless;
|
||||
|
||||
/* This code is copied from Owen's GDK code. */
|
||||
|
||||
/* Chew up all events of the same type on the same window */
|
||||
|
||||
ced.count = 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)
|
||||
if (window->display->grab_motion_notify_time != 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_RESIZING,
|
||||
"Compressed %d motion events\n", ced.count);
|
||||
*event = ced.prev_event;
|
||||
/* == is really the right test, but I'm all for paranoia */
|
||||
if (window->display->grab_motion_notify_time <=
|
||||
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)
|
||||
{
|
||||
maybe_replace_with_newer_event (window, event);
|
||||
update_move (window,
|
||||
event->xmotion.state,
|
||||
event->xmotion.x_root,
|
||||
event->xmotion.y_root);
|
||||
if (check_use_this_motion_notify (window,
|
||||
event))
|
||||
update_move (window,
|
||||
event->xmotion.state,
|
||||
event->xmotion.x_root,
|
||||
event->xmotion.y_root);
|
||||
}
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (event->xmotion.root == window->screen->xroot)
|
||||
{
|
||||
maybe_replace_with_newer_event (window, event);
|
||||
update_resize (window,
|
||||
event->xmotion.x_root,
|
||||
event->xmotion.y_root);
|
||||
if (check_use_this_motion_notify (window,
|
||||
event))
|
||||
update_resize (window,
|
||||
event->xmotion.x_root,
|
||||
event->xmotion.y_root);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -216,11 +216,8 @@ meta_workspace_activate (MetaWorkspace *workspace)
|
||||
meta_workspace_queue_calc_showing (old);
|
||||
meta_workspace_queue_calc_showing (workspace);
|
||||
|
||||
/* in mouse focus modes, this will probably get undone by an EnterNotify,
|
||||
* but that's OK
|
||||
*/
|
||||
meta_topic (META_DEBUG_FOCUS, "Focusing top window on new workspace\n");
|
||||
meta_screen_focus_top_window (workspace->screen, NULL);
|
||||
meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
|
||||
meta_screen_focus_default_window (workspace->screen, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user