1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
// Copyright 2019 The Chromium Authors
// 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/focus_cycler.h"
#include "ash/shelf/desk_button_widget.h"
#include "ash/shelf/login_shelf_view.h"
#include "ash/shelf/login_shelf_widget.h"
#include "ash/shelf/scrollable_shelf_view.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_navigation_widget.h"
#include "ash/shelf/shelf_view.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"
#include "ash/wm/desks/desk_button/desk_button_container.h"
#include "base/i18n/rtl.h"
namespace ash {
ShelfFocusCycler::ShelfFocusCycler(Shelf* shelf) : shelf_(shelf) {}
void ShelfFocusCycler::FocusOut(bool reverse, SourceView source_view) {
// TODO(manucornet): Once the non-views-based shelf is gone, make this a
// simple cycling logic instead of a long switch.
switch (source_view) {
case SourceView::kShelfNavigationView:
if (reverse) {
FocusStatusArea(reverse);
} else {
FocusDeskButton(reverse);
}
break;
case SourceView::kDeskButton:
if (reverse) {
FocusNavigation(reverse);
} else {
FocusShelf(reverse);
}
break;
case SourceView::kShelfView:
if (reverse)
FocusDeskButton(reverse);
else
FocusStatusArea(reverse);
break;
case SourceView::kStatusAreaView: {
// If we are using a views-based shelf:
// * If we're in an active session, either focus the navigation widget
// (going forward) or the shelf (reverse).
// * 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()->GetLoginShelfView()->GetVisible() &&
(!reverse ||
(!shelf_->shelf_widget()->GetLoginShelfView()->IsFocusable() &&
reverse))) {
// Login/lock screen or OOBE.
Shell::Get()->system_tray_notifier()->NotifyFocusOut(reverse);
} else if (reverse) {
FocusShelf(reverse);
} else {
FocusNavigation(reverse);
}
break;
}
}
}
void ShelfFocusCycler::FocusNavigation(bool last_element) {
ShelfNavigationWidget* navigation_widget = shelf_->navigation_widget();
if (!navigation_widget->GetHomeButton() &&
!navigation_widget->GetBackButton()) {
FocusOut(last_element, SourceView::kShelfNavigationView);
return;
}
navigation_widget->PrepareForGettingFocus(last_element);
Shell::Get()->focus_cycler()->FocusWidget(navigation_widget);
}
void ShelfFocusCycler::FocusDeskButton(bool last_element) {
DeskButtonWidget* desk_button_widget = shelf_->desk_button_widget();
if (desk_button_widget && desk_button_widget->ShouldBeVisible()) {
// For LTR layout, last/first element means last/first element in the view
// hierarchy; for RTL, last/first element means first/last.
views::View* default_child_to_focus =
desk_button_widget->GetFocusManager()->GetNextFocusableView(
/*starting_view=*/nullptr, /*starting_widget=*/nullptr,
/*reverse=*/base::i18n::IsRTL() != last_element,
/*dont_loop=*/false);
desk_button_widget->SetDefaultChildToFocus(default_child_to_focus);
Shell::Get()->focus_cycler()->FocusWidget(desk_button_widget);
} else if (last_element) {
FocusNavigation(last_element);
} else {
FocusShelf(last_element);
}
}
void ShelfFocusCycler::FocusShelf(bool last_element) {
if (shelf_->shelf_widget()->GetLoginShelfView()->GetVisible()) {
LoginShelfWidget* login_shelf_widget = shelf_->login_shelf_widget();
login_shelf_widget->SetDefaultLastFocusableChild(last_element);
Shell::Get()->focus_cycler()->FocusWidget(login_shelf_widget);
} else {
HotseatWidget* hotseat_widget = shelf_->hotseat_widget();
hotseat_widget->scrollable_shelf_view()->set_default_last_focusable_child(
last_element);
Shell::Get()->focus_cycler()->FocusWidget(hotseat_widget);
}
}
void ShelfFocusCycler::FocusStatusArea(bool last_element) {
StatusAreaWidget* status_area_widget = shelf_->GetStatusAreaWidget();
status_area_widget->status_area_widget_delegate()
->set_default_last_focusable_child(last_element);
Shell::Get()->focus_cycler()->FocusWidget(status_area_widget);
}
} // namespace ash
|