diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/display.c | 1 | ||||
-rw-r--r-- | src/display.h | 1 | ||||
-rw-r--r-- | src/screen.c | 60 | ||||
-rw-r--r-- | src/screen.h | 8 | ||||
-rw-r--r-- | src/stack.c | 57 | ||||
-rw-r--r-- | src/stack.h | 13 | ||||
-rw-r--r-- | src/window.c | 117 | ||||
-rw-r--r-- | src/workspace.c | 7 |
8 files changed, 197 insertions, 67 deletions
diff --git a/src/display.c b/src/display.c index 9dac79f6..a19e9e48 100644 --- a/src/display.c +++ b/src/display.c @@ -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 diff --git a/src/display.h b/src/display.h index 803f0213..8bcf50d8 100644 --- a/src/display.h +++ b/src/display.h @@ -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; diff --git a/src/screen.c b/src/screen.c index 483f66a3..3dcefb5c 100644 --- a/src/screen.c +++ b/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) diff --git a/src/screen.h b/src/screen.h index 5ab5ec38..16e90707 100644 --- a/src/screen.h +++ b/src/screen.h @@ -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, diff --git a/src/stack.c b/src/stack.c index e91c6201..5cb5dba5 100644 --- a/src/stack.c +++ b/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) diff --git a/src/stack.h b/src/stack.h index 89b8aff0..b0c21e56 100644 --- a/src/stack.h +++ b/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); diff --git a/src/window.c b/src/window.c index cd46f6c9..daca2941 100644 --- a/src/window.c +++ b/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) - { - ced->count += 1; - return True; - } - else if (xevent->type != Expose && - xevent->type != ConfigureNotify && - xevent->type != PropertyNotify) + EventScannerData *esd = (void*) arg; + + if (esd->current_event->type == xevent->type && + esd->current_event->xany.window == xevent->xany.window) { - /* Don't compress across most unrelated events, just to be safe */ - ced->done = TRUE; - return False; + esd->count += 1; + esd->last_time = xevent->xmotion.time; } - 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. */ + + if (window->display->grab_motion_notify_time != 0) + { + /* == 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 */ + } - /* Chew up all events of the same type on the same window */ + esd.current_event = event; + esd.count = 0; + esd.last_time = 0; - 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; + /* "useless" isn't filled in because the predicate never returns True */ + XCheckIfEvent (window->display->xdisplay, + &useless, + find_last_time_predicate, + (XPointer) &esd); - if (ced.count > 0) + 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 { - meta_topic (META_DEBUG_RESIZING, - "Compressed %d motion events\n", ced.count); - *event = ced.prev_event; + /* 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; diff --git a/src/workspace.c b/src/workspace.c index 40e445da..f6eacc92 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -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 |