Commit c835718d authored by Alex Newcomer's avatar Alex Newcomer Committed by Commit Bot

cros: Move container focus logic to shelf_focus_cycler

This will make it easier to consolidate the logic when the components
are split into different widgets.

Change-Id: I367bee362632ad015f73c1da8637ac71942bdc9e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1674657
Commit-Queue: Alex Newcomer <newcomer@chromium.org>
Reviewed-by: default avatarJenny Zhang <jennyz@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#672609}
parent 94613f32
...@@ -561,6 +561,8 @@ component("ash") { ...@@ -561,6 +561,8 @@ component("ash") {
"shelf/shelf_control_button.h", "shelf/shelf_control_button.h",
"shelf/shelf_controller.cc", "shelf/shelf_controller.cc",
"shelf/shelf_controller.h", "shelf/shelf_controller.h",
"shelf/shelf_focus_cycler.cc",
"shelf/shelf_focus_cycler.h",
"shelf/shelf_layout_manager.cc", "shelf/shelf_layout_manager.cc",
"shelf/shelf_layout_manager.h", "shelf/shelf_layout_manager.h",
"shelf/shelf_layout_manager_observer.h", "shelf/shelf_layout_manager_observer.h",
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "ash/root_window_controller.h" #include "ash/root_window_controller.h"
#include "ash/shelf/shelf_bezel_event_handler.h" #include "ash/shelf/shelf_bezel_event_handler.h"
#include "ash/shelf/shelf_controller.h" #include "ash/shelf/shelf_controller.h"
#include "ash/shelf/shelf_focus_cycler.h"
#include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_observer.h" #include "ash/shelf/shelf_observer.h"
#include "ash/shelf/shelf_widget.h" #include "ash/shelf/shelf_widget.h"
...@@ -60,7 +61,8 @@ class Shelf::AutoHideEventHandler : public ui::EventHandler { ...@@ -60,7 +61,8 @@ class Shelf::AutoHideEventHandler : public ui::EventHandler {
Shelf::Shelf() Shelf::Shelf()
: shelf_locking_manager_(this), : shelf_locking_manager_(this),
bezel_event_handler_(std::make_unique<ShelfBezelEventHandler>(this)) {} bezel_event_handler_(std::make_unique<ShelfBezelEventHandler>(this)),
shelf_focus_cycler_(std::make_unique<ShelfFocusCycler>(this)) {}
Shelf::~Shelf() = default; Shelf::~Shelf() = default;
......
...@@ -31,6 +31,7 @@ namespace ash { ...@@ -31,6 +31,7 @@ namespace ash {
enum class AnimationChangeType; enum class AnimationChangeType;
class ShelfBezelEventHandler; class ShelfBezelEventHandler;
class ShelfFocusCycler;
class ShelfLayoutManager; class ShelfLayoutManager;
class ShelfLayoutManagerTest; class ShelfLayoutManagerTest;
class ShelfLockingManager; class ShelfLockingManager;
...@@ -174,6 +175,9 @@ class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver { ...@@ -174,6 +175,9 @@ class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver {
ShelfAutoHideBehavior auto_hide_behavior() const { ShelfAutoHideBehavior auto_hide_behavior() const {
return auto_hide_behavior_; return auto_hide_behavior_;
} }
ShelfFocusCycler* shelf_focus_cycler() { return shelf_focus_cycler_.get(); }
void set_is_tablet_mode_animation_running(bool value) { void set_is_tablet_mode_animation_running(bool value) {
is_tablet_mode_animation_running_ = value; is_tablet_mode_animation_running_ = value;
} }
...@@ -220,6 +224,9 @@ class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver { ...@@ -220,6 +224,9 @@ class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver {
// Forwards touch gestures on a bezel sensor to the shelf. // Forwards touch gestures on a bezel sensor to the shelf.
std::unique_ptr<ShelfBezelEventHandler> bezel_event_handler_; std::unique_ptr<ShelfBezelEventHandler> bezel_event_handler_;
// Hands focus off to different parts of the shelf.
std::unique_ptr<ShelfFocusCycler> shelf_focus_cycler_;
// True while the animation to enter or exit tablet mode is running. Sometimes // True while the animation to enter or exit tablet mode is running. Sometimes
// this value is true when the shelf movements are not actually animating // this value is true when the shelf movements are not actually animating
// (animation value = 0.0). This is because this is set to true when we // (animation value = 0.0). This is because this is set to true when we
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/shelf/shelf_focus_cycler.h"
#include "ash/focus_cycler.h"
#include "ash/shelf/login_shelf_view.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/status_area_widget_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
namespace ash {
ShelfFocusCycler::ShelfFocusCycler(Shelf* shelf) : shelf_(shelf) {}
void ShelfFocusCycler::FocusOut(bool reverse, SourceView source_view) {
switch (source_view) {
case SourceView::kShelfView: {
StatusAreaWidget* status_area_widget = shelf_->GetStatusAreaWidget();
status_area_widget->status_area_widget_delegate()
->set_default_last_focusable_child(reverse);
Shell::Get()->focus_cycler()->FocusWidget(status_area_widget);
break;
}
case SourceView::kSystemTrayView: {
// Focus can move to the shelf, or the focus will be delegated to system
// tray focus observers.
bool should_focus_shelf = true;
// If we are using a views-based shelf:
// * If we're in an active session, always bring focus to the shelf
// whether we are going in reverse or not.
// * Otherwise (login/lock screen, OOBE), bring focus to the shelf only
// if we're going in reverse; if we're going forward, let the system
// tray focus observers focus the lock/login view.
ShelfWidget* shelf_widget = shelf_->shelf_widget();
if (shelf_widget->login_shelf_view()->GetVisible()) {
// Login/lock screen or OOBE.
should_focus_shelf = reverse;
}
if (should_focus_shelf) {
shelf_widget->set_default_last_focusable_child(reverse);
shelf_widget->set_activated_from_other_widget(true);
Shell::Get()->focus_cycler()->FocusWidget(shelf_widget);
shelf_widget->FocusFirstOrLastFocusableChild(reverse);
} else {
Shell::Get()->system_tray_notifier()->NotifyFocusOut(reverse);
}
break;
}
}
}
} // namespace ash
\ No newline at end of file
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SHELF_SHELF_FOCUS_CYCLER_H_
#define ASH_SHELF_SHELF_FOCUS_CYCLER_H_
#include "base/macros.h"
namespace ash {
class Shelf;
// The containers that rely on ShelfFocusCycler to move focus outside of their
// view trees.
enum class SourceView {
kShelfView = 0,
kSystemTrayView,
};
// ShelfFocusCycler handles the special focus transitions from the Login UI,
// Shelf, and Status Tray.
class ShelfFocusCycler {
public:
explicit ShelfFocusCycler(Shelf* shelf);
~ShelfFocusCycler() = default;
// Moves focus from one container to the next. |reverse| will move the focus
// to the container to the left in LTR. RTL does not need to be accounted
// for when calling this function.
void FocusOut(bool reverse, SourceView source_view);
private:
// Owned by RootWindowController.
Shelf* shelf_;
DISALLOW_COPY_AND_ASSIGN(ShelfFocusCycler);
};
} // namespace ash
#endif // ASH_SHELF_SHELF_FOCUS_CYCLER_H_
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "ash/shelf/shelf_constants.h" #include "ash/shelf/shelf_constants.h"
#include "ash/shelf/shelf_context_menu_model.h" #include "ash/shelf/shelf_context_menu_model.h"
#include "ash/shelf/shelf_controller.h" #include "ash/shelf/shelf_controller.h"
#include "ash/shelf/shelf_focus_cycler.h"
#include "ash/shelf/shelf_menu_model_adapter.h" #include "ash/shelf/shelf_menu_model_adapter.h"
#include "ash/shelf/shelf_widget.h" #include "ash/shelf/shelf_widget.h"
#include "ash/shell.h" #include "ash/shell.h"
...@@ -38,8 +39,6 @@ ...@@ -38,8 +39,6 @@
#include "ash/strings/grit/ash_strings.h" #include "ash/strings/grit/ash_strings.h"
#include "ash/system/model/system_tray_model.h" #include "ash/system/model/system_tray_model.h"
#include "ash/system/model/virtual_keyboard_model.h" #include "ash/system/model/virtual_keyboard_model.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/status_area_widget_delegate.h"
#include "ash/wm/mru_window_tracker.h" #include "ash/wm/mru_window_tracker.h"
#include "ash/wm/root_window_finder.h" #include "ash/wm/root_window_finder.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
...@@ -885,18 +884,8 @@ void ShelfView::OnShelfButtonAboutToRequestFocusFromTabTraversal( ...@@ -885,18 +884,8 @@ void ShelfView::OnShelfButtonAboutToRequestFocusFromTabTraversal(
return; return;
} }
// The logic here seems backwards, but is actually correct. For instance if if (ShouldFocusOut(reverse, button))
// the ShelfView's internal focus cycling logic attemmpts to focus the first shelf_->shelf_focus_cycler()->FocusOut(reverse, SourceView::kShelfView);
// child (e.g. app list button) after hitting Tab, we intercept that and
// instead, advance through to the status area.
if ((reverse && button == FindLastFocusableChild()) ||
(!reverse && button == FindFirstFocusableChild())) {
StatusAreaWidget* status_area_widget =
Shelf::ForWindow(GetWidget()->GetNativeWindow())->GetStatusAreaWidget();
status_area_widget->status_area_widget_delegate()
->set_default_last_focusable_child(reverse);
Shell::Get()->focus_cycler()->FocusWidget(status_area_widget);
}
} }
int64_t ShelfView::GetDisplayId() const { int64_t ShelfView::GetDisplayId() const {
...@@ -1640,6 +1629,15 @@ bool ShelfView::SameDragType(ShelfItemType typea, ShelfItemType typeb) const { ...@@ -1640,6 +1629,15 @@ bool ShelfView::SameDragType(ShelfItemType typea, ShelfItemType typeb) const {
return false; return false;
} }
bool ShelfView::ShouldFocusOut(bool reverse, views::View* button) {
// The logic here seems backwards, but is actually correct. For instance if
// the ShelfView's internal focus cycling logic attemmpts to focus the first
// child (e.g. app list button) after hitting Tab, we intercept that and
// instead, advance through to the status area.
return (reverse && button == FindLastFocusableChild()) ||
(!reverse && button == FindFirstFocusableChild());
}
std::pair<int, int> ShelfView::GetDragRange(int index) { std::pair<int, int> ShelfView::GetDragRange(int index) {
int min_index = -1; int min_index = -1;
int max_index = -1; int max_index = -1;
......
...@@ -294,6 +294,7 @@ class ASH_EXPORT ShelfView : public views::View, ...@@ -294,6 +294,7 @@ class ASH_EXPORT ShelfView : public views::View,
// Returns the main shelf. This can be called on either the main shelf // Returns the main shelf. This can be called on either the main shelf
// or the overflow shelf. // or the overflow shelf.
ShelfView* main_shelf() { return main_shelf_ ? main_shelf_ : this; } ShelfView* main_shelf() { return main_shelf_ ? main_shelf_ : this; }
// Returns the overflow shelf. This can be called on either the main shelf // Returns the overflow shelf. This can be called on either the main shelf
// or the overflow shelf. Returns nullptr if the overflow shelf isn't visible. // or the overflow shelf. Returns nullptr if the overflow shelf isn't visible.
ShelfView* overflow_shelf() { ShelfView* overflow_shelf() {
...@@ -425,6 +426,9 @@ class ASH_EXPORT ShelfView : public views::View, ...@@ -425,6 +426,9 @@ class ASH_EXPORT ShelfView : public views::View,
// Returns true if |typea| and |typeb| should be in the same drag range. // Returns true if |typea| and |typeb| should be in the same drag range.
bool SameDragType(ShelfItemType typea, ShelfItemType typeb) const; bool SameDragType(ShelfItemType typea, ShelfItemType typeb) const;
// Returns true if focus should move out of the ShelfView view tree.
bool ShouldFocusOut(bool reverse, views::View* button);
// Returns the range (in the model) the item at the specified index can be // Returns the range (in the model) the item at the specified index can be
// dragged to. // dragged to.
std::pair<int, int> GetDragRange(int index); std::pair<int, int> GetDragRange(int index);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "ash/root_window_controller.h" #include "ash/root_window_controller.h"
#include "ash/shelf/shelf.h" #include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_constants.h" #include "ash/shelf/shelf_constants.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget.h"
#include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_constants.h"
...@@ -65,6 +66,10 @@ void StatusAreaWidgetDelegate::SetFocusCyclerForTesting( ...@@ -65,6 +66,10 @@ void StatusAreaWidgetDelegate::SetFocusCyclerForTesting(
} }
bool StatusAreaWidgetDelegate::ShouldFocusOut(bool reverse) { bool StatusAreaWidgetDelegate::ShouldFocusOut(bool reverse) {
// Never bring the focus out if it's not a views-based shelf as it is visually
// not on par with the status widget.
if (!ShelfWidget::IsUsingViewsShelf())
return false;
views::View* focused_view = GetFocusManager()->GetFocusedView(); views::View* focused_view = GetFocusManager()->GetFocusedView();
return (reverse && focused_view == GetFirstFocusableChild()) || return (reverse && focused_view == GetFirstFocusableChild()) ||
(!reverse && focused_view == GetLastFocusableChild()); (!reverse && focused_view == GetLastFocusableChild());
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/shell_window_ids.h"
#include "ash/shelf/login_shelf_view.h" #include "ash/shelf/login_shelf_view.h"
#include "ash/shelf/shelf_constants.h" #include "ash/shelf/shelf_constants.h"
#include "ash/shelf/shelf_focus_cycler.h"
#include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_widget.h" #include "ash/shelf/shelf_widget.h"
#include "ash/shell.h" #include "ash/shell.h"
...@@ -270,37 +271,7 @@ void TrayBackgroundView::AboutToRequestFocusFromTabTraversal(bool reverse) { ...@@ -270,37 +271,7 @@ void TrayBackgroundView::AboutToRequestFocusFromTabTraversal(bool reverse) {
if (!delegate || !delegate->ShouldFocusOut(reverse)) if (!delegate || !delegate->ShouldFocusOut(reverse))
return; return;
// At this point, we know we should focus out of the status widget. It shelf_->shelf_focus_cycler()->FocusOut(reverse, SourceView::kSystemTrayView);
// remains to be determined whether we should bring focus to the shelf, or
// whether we should delegate to system tray focus observers to decide
// where the focus goes next.
bool should_focus_shelf = true;
if (!ShelfWidget::IsUsingViewsShelf()) {
// Never bring the focus to the shelf if it's not a views-based shelf as
// it is visually not on par with the status widget.
return;
}
// If we are using a views-based shelf:
// * If we're in an active session, always bring focus to the shelf whether
// we are going in reverse or not.
// * Otherwise (login/lock screen, OOBE), bring focus to the shelf only
// if we're going in reverse; if we're going forward, let the system tray
// focus observers focus the lock/login view.
if (shelf->shelf_widget()->login_shelf_view()->GetVisible()) {
// Login/lock screen or OOBE.
should_focus_shelf = reverse;
}
if (should_focus_shelf) {
shelf->shelf_widget()->set_default_last_focusable_child(reverse);
shelf->shelf_widget()->set_activated_from_other_widget(true);
Shell::Get()->focus_cycler()->FocusWidget(shelf->shelf_widget());
shelf->shelf_widget()->FocusFirstOrLastFocusableChild(reverse);
} else {
Shell::Get()->system_tray_notifier()->NotifyFocusOut(reverse);
}
} }
void TrayBackgroundView::GetAccessibleNodeData(ui::AXNodeData* node_data) { void TrayBackgroundView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment