1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/system/accessibility/floating_menu_utils.h"
6
7 #include "ash/public/cpp/accessibility_controller_enums.h"
8 #include "ash/shell.h"
9 #include "ash/wm/collision_detection/collision_detection_utils.h"
10 #include "ash/wm/work_area_insets.h"
11 #include "base/i18n/rtl.h"
12
13 namespace ash {
14
DefaultSystemFloatingMenuPosition()15 FloatingMenuPosition DefaultSystemFloatingMenuPosition() {
16 return base::i18n::IsRTL() ? FloatingMenuPosition::kBottomLeft
17 : FloatingMenuPosition::kBottomRight;
18 }
19
GetOnScreenBoundsForFloatingMenuPosition(const gfx::Size & menu_bounds,FloatingMenuPosition position)20 gfx::Rect GetOnScreenBoundsForFloatingMenuPosition(
21 const gfx::Size& menu_bounds,
22 FloatingMenuPosition position) {
23 // Calculates the ideal bounds.
24 aura::Window* window = Shell::GetPrimaryRootWindow();
25 gfx::Rect work_area =
26 WorkAreaInsets::ForWindow(window)->user_work_area_bounds();
27
28 switch (position) {
29 case FloatingMenuPosition::kBottomRight:
30 return gfx::Rect(work_area.right() - menu_bounds.width(),
31 work_area.bottom() - menu_bounds.height(),
32 menu_bounds.width(), menu_bounds.height());
33 case FloatingMenuPosition::kBottomLeft:
34 return gfx::Rect(work_area.x(), work_area.bottom() - menu_bounds.height(),
35 menu_bounds.width(), menu_bounds.height());
36 case FloatingMenuPosition::kTopLeft:
37 // Because there is no inset at the top of the widget, add
38 // 2 * kCollisionWindowWorkAreaInsetsDp to the top of the work area.
39 // to ensure correct padding.
40 return gfx::Rect(work_area.x(),
41 work_area.y() + 2 * kCollisionWindowWorkAreaInsetsDp,
42 menu_bounds.width(), menu_bounds.height());
43 case FloatingMenuPosition::kTopRight:
44 // Because there is no inset at the top of the widget, add
45 // 2 * kCollisionWindowWorkAreaInsetsDp to the top of the work area.
46 // to ensure correct padding.
47 return gfx::Rect(work_area.right() - menu_bounds.width(),
48 work_area.y() + 2 * kCollisionWindowWorkAreaInsetsDp,
49 menu_bounds.width(), menu_bounds.height());
50 case FloatingMenuPosition::kSystemDefault:
51 NOTREACHED();
52 return gfx::Rect();
53 }
54 }
55
GetAnchorAlignmentForFloatingMenuPosition(FloatingMenuPosition position)56 views::BubbleBorder::Arrow GetAnchorAlignmentForFloatingMenuPosition(
57 FloatingMenuPosition position) {
58 // If this is the default system position, pick the position based on the
59 // language direction.
60 if (position == FloatingMenuPosition::kSystemDefault) {
61 position = DefaultSystemFloatingMenuPosition();
62 }
63 // Mirror arrow in RTL languages so that it always stays near the screen
64 // edge.
65 switch (position) {
66 case FloatingMenuPosition::kBottomLeft:
67 return base::i18n::IsRTL() ? views::BubbleBorder::Arrow::TOP_RIGHT
68 : views::BubbleBorder::Arrow::TOP_LEFT;
69 case FloatingMenuPosition::kTopLeft:
70 return base::i18n::IsRTL() ? views::BubbleBorder::Arrow::BOTTOM_RIGHT
71 : views::BubbleBorder::Arrow::BOTTOM_LEFT;
72 case FloatingMenuPosition::kBottomRight:
73 return base::i18n::IsRTL() ? views::BubbleBorder::Arrow::TOP_LEFT
74 : views::BubbleBorder::Arrow::TOP_RIGHT;
75 case FloatingMenuPosition::kTopRight:
76 return base::i18n::IsRTL() ? views::BubbleBorder::Arrow::BOTTOM_LEFT
77 : views::BubbleBorder::Arrow::BOTTOM_RIGHT;
78 case FloatingMenuPosition::kSystemDefault:
79 // It's not possible for position to be kSystemDefault here because we've
80 // set it via DefaultSystemPosition() above if it was kSystemDefault.
81 NOTREACHED();
82 return views::BubbleBorder::Arrow::TOP_LEFT;
83 }
84 }
85
86 } // namespace ash
87