File: shelf_focus_cycler.cc

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (135 lines) | stat: -rw-r--r-- 5,032 bytes parent folder | download
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
125
126
127
128
129
130
131
132
133
134
135
// 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_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.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()) {
    // Update the desk button and desk switch buttons before focus change.
    if (!shelf_->IsHorizontalAlignment()) {
      desk_button_widget->SetExpanded(true);
    }
    desk_button_widget->GetDeskButton()->SetFocused(true);

    // Focus `default_child_to_focus` within the desk button widget.
    views::View* default_child_to_focus =
        last_element ? desk_button_widget->GetLastFocusableView()
                     : desk_button_widget->GetFirstFocusableView();
    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()) {
    // TODO(https://crbug.com/1343114): refactor the code below after the login
    // shelf widget is ready.

    if (features::IsUseLoginShelfWidgetEnabled()) {
      LoginShelfWidget* login_shelf_widget = shelf_->login_shelf_widget();
      login_shelf_widget->SetDefaultLastFocusableChild(last_element);
      Shell::Get()->focus_cycler()->FocusWidget(login_shelf_widget);
    } else {
      ShelfWidget* shelf_widget = shelf_->shelf_widget();
      shelf_widget->set_default_last_focusable_child(last_element);
      Shell::Get()->focus_cycler()->FocusWidget(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