Commit b263b51b authored by James Cook's avatar James Cook Committed by Commit Bot

cros: Move ChromeVoxPanel bounds management into ash

ChromeVoxPanel depends on knowledge of fullscreen state and docked
magnifier state in order to compute its bounds. In addition it can
update the window manager's work area. Under go/mustash this knowledge
lives in the ash process, not in the browser. Therefore move the
bounds and work area management into ash.

Next steps include introducing a mojo interface for setting the
ChromeVox panel's fullscreen state and moving AccessibilityObserver
support to ash::AccessibilityController from the system tray code.

Bug: 628655, 819351
Test: added to ash_unittests
Change-Id: Ibb27a0b8ab6b998ecd305b7e7bfbad8b35853613
Reviewed-on: https://chromium-review.googlesource.com/952263
Commit-Queue: James Cook <jamescook@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#541614}
parent aff665fc
......@@ -62,8 +62,8 @@ component("ash") {
"accessibility/accessibility_highlight_layer.h",
"accessibility/accessibility_layer.cc",
"accessibility/accessibility_layer.h",
"accessibility/chromevox_layout_manager.cc",
"accessibility/chromevox_layout_manager.h",
"accessibility/accessibility_panel_layout_manager.cc",
"accessibility/accessibility_panel_layout_manager.h",
"accessibility/default_accessibility_delegate.cc",
"accessibility/default_accessibility_delegate.h",
"accessibility/focus_ring_controller.cc",
......@@ -1404,7 +1404,7 @@ test("ash_unittests") {
"accessibility/accessibility_controller_unittest.cc",
"accessibility/accessibility_focus_ring_controller_unittest.cc",
"accessibility/accessibility_highlight_controller_unittest.cc",
"accessibility/chromevox_layout_manager_unittest.cc",
"accessibility/accessibility_panel_layout_manager_unittest.cc",
"accessibility/touch_accessibility_enabler_unittest.cc",
"accessibility/touch_exploration_controller_unittest.cc",
"app_list/app_list_presenter_delegate_unittest.cc",
......
......@@ -8,11 +8,13 @@
#include <utility>
#include "ash/accessibility/accessibility_highlight_controller.h"
#include "ash/accessibility/accessibility_panel_layout_manager.h"
#include "ash/autoclick/autoclick_controller.h"
#include "ash/components/autoclick/public/mojom/autoclick.mojom.h"
#include "ash/high_contrast/high_contrast_controller.h"
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/public/cpp/config.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/session/session_controller.h"
#include "ash/session/session_observer.h"
#include "ash/shell.h"
......@@ -31,6 +33,7 @@
#include "services/service_manager/public/cpp/connector.h"
#include "services/ui/public/interfaces/accessibility_manager.mojom.h"
#include "services/ui/public/interfaces/constants.mojom.h"
#include "ui/aura/window.h"
#include "ui/base/cursor/cursor_type.h"
#include "ui/keyboard/keyboard_util.h"
......@@ -314,6 +317,19 @@ void AccessibilityController::PlaySpokenFeedbackToggleCountdown(
client_->PlaySpokenFeedbackToggleCountdown(tick_count);
}
void AccessibilityController::SetAccessibilityPanelFullscreen(bool fullscreen) {
// The accessibility panel is only shown on the primary display.
aura::Window* root = Shell::GetPrimaryRootWindow();
aura::Window* container =
Shell::GetContainer(root, kShellWindowId_AccessibilityPanelContainer);
// TODO(jamescook): Avoid this cast by moving ash::AccessibilityObserver
// ownership to this class and notifying it on ChromeVox fullscreen updates.
AccessibilityPanelLayoutManager* layout =
static_cast<AccessibilityPanelLayoutManager*>(
container->layout_manager());
layout->SetPanelFullscreen(fullscreen);
}
void AccessibilityController::SetClient(
mojom::AccessibilityControllerClientPtr client) {
client_ = std::move(client);
......
......@@ -124,6 +124,10 @@ class ASH_EXPORT AccessibilityController
// countdown.
void PlaySpokenFeedbackToggleCountdown(int tick_count);
// Sets whether the accessibility panel is filling the entire screen.
// TODO(jamescook): Convert to mojo interface.
void SetAccessibilityPanelFullscreen(bool fullscreen);
// mojom::AccessibilityController:
void SetClient(mojom::AccessibilityControllerClientPtr client) override;
void SetDarkenScreen(bool darken) override;
......
// Copyright 2018 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/accessibility/accessibility_panel_layout_manager.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "base/logging.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"
namespace ash {
AccessibilityPanelLayoutManager::AccessibilityPanelLayoutManager() {
display::Screen::GetScreen()->AddObserver(this);
Shell::Get()->activation_client()->AddObserver(this);
Shell::Get()->AddShellObserver(this);
}
AccessibilityPanelLayoutManager::~AccessibilityPanelLayoutManager() {
Shell::Get()->RemoveShellObserver(this);
Shell::Get()->activation_client()->RemoveObserver(this);
display::Screen::GetScreen()->RemoveObserver(this);
}
void AccessibilityPanelLayoutManager::SetPanelFullscreen(bool fullscreen) {
panel_fullscreen_ = fullscreen;
UpdateWindowBounds();
}
void AccessibilityPanelLayoutManager::OnWindowAddedToLayout(
aura::Window* child) {
panel_window_ = child;
// Defer setting the window bounds until the extension is loaded and Chrome
// shows the widget.
}
void AccessibilityPanelLayoutManager::OnWindowRemovedFromLayout(
aura::Window* child) {
// NOTE: In browser_tests a second ChromeVoxPanel can be created while the
// first one is closing due to races between loading the extension and
// closing the widget. We only track the latest panel.
if (child == panel_window_)
panel_window_ = nullptr;
UpdateWorkArea();
}
void AccessibilityPanelLayoutManager::OnChildWindowVisibilityChanged(
aura::Window* child,
bool visible) {
if (child == panel_window_ && visible) {
UpdateWindowBounds();
UpdateWorkArea();
}
}
void AccessibilityPanelLayoutManager::SetChildBounds(
aura::Window* child,
const gfx::Rect& requested_bounds) {
SetChildBoundsDirect(child, requested_bounds);
}
void AccessibilityPanelLayoutManager::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t changed_metrics) {
UpdateWindowBounds();
}
void AccessibilityPanelLayoutManager::OnWindowActivated(
ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) {
UpdateWindowBounds();
}
void AccessibilityPanelLayoutManager::OnFullscreenStateChanged(
bool is_fullscreen,
aura::Window* root_window) {
UpdateWindowBounds();
}
void AccessibilityPanelLayoutManager::UpdateWindowBounds() {
if (!panel_window_)
return;
aura::Window* root_window = panel_window_->GetRootWindow();
RootWindowController* root_controller =
RootWindowController::ForWindow(root_window);
// By default the panel sits at the top of the screen.
DCHECK(panel_window_->bounds().origin().IsOrigin());
gfx::Rect bounds(0, 0, root_window->bounds().width(), kPanelHeight);
// The panel can make itself fill the screen (including covering the shelf).
if (panel_fullscreen_)
bounds.set_height(root_window->bounds().height());
// If a fullscreen browser window is open, give the panel a height of 0
// unless it's active.
if (root_controller->GetWindowForFullscreenMode() &&
!::wm::IsActiveWindow(panel_window_)) {
bounds.set_height(0);
}
// Make sure the ChromeVox panel is always below the Docked Magnifier viewport
// so it shows up and gets magnified.
bounds.Offset(0, root_controller->shelf()->GetDockedMagnifierHeight());
panel_window_->SetBounds(bounds);
}
void AccessibilityPanelLayoutManager::UpdateWorkArea() {
Shell::GetPrimaryRootWindowController()->shelf()->SetAccessibilityPanelHeight(
panel_window_ ? panel_window_->bounds().height() : 0);
}
} // namespace ash
// Copyright 2018 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_ACCESSIBILITY_ACCESSIBILITY_PANEL_LAYOUT_MANAGER_H_
#define ASH_ACCESSIBILITY_ACCESSIBILITY_PANEL_LAYOUT_MANAGER_H_
#include "ash/ash_export.h"
#include "ash/shell_observer.h"
#include "base/macros.h"
#include "ui/aura/layout_manager.h"
#include "ui/display/display_observer.h"
#include "ui/wm/public/activation_change_observer.h"
namespace aura {
class Window;
}
namespace ash {
// AccessibilityPanelLayoutManager manages the container window used for the
// ChromeVox spoken feedback panel, which sits at the top of the display. It
// insets the display work area bounds when ChromeVox is visible. The ChromeVox
// panel is created by Chrome because spoken feedback is implemented by an
// extension. Exported for test.
class ASH_EXPORT AccessibilityPanelLayoutManager
: public aura::LayoutManager,
public display::DisplayObserver,
public ::wm::ActivationChangeObserver,
public ash::ShellObserver {
public:
// Height of the panel in DIPs. Public for test.
static constexpr int kPanelHeight = 35;
AccessibilityPanelLayoutManager();
~AccessibilityPanelLayoutManager() override;
// Sets whether the panel covers the entire display.
void SetPanelFullscreen(bool fullscreen);
// aura::LayoutManager:
void OnWindowResized() override {}
void OnWindowAddedToLayout(aura::Window* child) override;
void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
void OnWindowRemovedFromLayout(aura::Window* child) override;
void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) override;
void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) override;
// DisplayObserver:
void OnDisplayAdded(const display::Display& new_display) override {}
void OnDisplayRemoved(const display::Display& old_display) override {}
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override;
// ::wm::ActivationChangeObserver:
void OnWindowActivated(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override;
// ShellObserver:
void OnFullscreenStateChanged(bool is_fullscreen,
aura::Window* root_window) override;
aura::Window* panel_window_for_test() { return panel_window_; }
private:
// Updates the panel window bounds.
void UpdateWindowBounds();
// Updates the display work area to account for the panel.
void UpdateWorkArea();
// The panel being managed (e.g. the ChromeVoxPanel's native aura window).
aura::Window* panel_window_ = nullptr;
// Whether the panel itself is filling the display.
bool panel_fullscreen_ = false;
DISALLOW_COPY_AND_ASSIGN(AccessibilityPanelLayoutManager);
};
} // namespace ash
#endif // ASH_ACCESSIBILITY_ACCESSIBILITY_PANEL_LAYOUT_MANAGER_H_
// Copyright 2018 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/accessibility/accessibility_panel_layout_manager.h"
#include <memory>
#include "ash/shelf/shelf_constants.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace {
// Shorten the name for better line wrapping.
constexpr int kPanelHeight = AccessibilityPanelLayoutManager::kPanelHeight;
AccessibilityPanelLayoutManager* GetLayoutManager() {
aura::Window* container =
Shell::GetContainer(Shell::GetPrimaryRootWindow(),
kShellWindowId_AccessibilityPanelContainer);
return static_cast<AccessibilityPanelLayoutManager*>(
container->layout_manager());
}
// Simulates Chrome creating the ChromeVoxPanel widget.
std::unique_ptr<views::Widget> CreateChromeVoxPanel() {
std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>();
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
aura::Window* root_window = Shell::GetPrimaryRootWindow();
params.parent = Shell::GetContainer(
root_window, kShellWindowId_AccessibilityPanelContainer);
params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
params.bounds = gfx::Rect(0, 0, root_window->bounds().width(),
root_window->bounds().height());
widget->Init(params);
return widget;
}
using AccessibilityPanelLayoutManagerTest = AshTestBase;
TEST_F(AccessibilityPanelLayoutManagerTest, Basics) {
AccessibilityPanelLayoutManager* layout_manager = GetLayoutManager();
ASSERT_TRUE(layout_manager);
// The layout manager doesn't track anything at startup.
EXPECT_FALSE(layout_manager->panel_window_for_test());
// Simulate chrome creating the ChromeVox widget. The layout manager starts
// managing it.
std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel();
widget->Show();
EXPECT_EQ(widget->GetNativeWindow(), layout_manager->panel_window_for_test());
// The layout manager doesn't track anything after the widget closes.
widget.reset();
EXPECT_FALSE(layout_manager->panel_window_for_test());
}
TEST_F(AccessibilityPanelLayoutManagerTest, Shutdown) {
// Simulate chrome creating the ChromeVox widget.
std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel();
widget->Show();
// Don't close the window.
widget.release();
// Ash should not crash if the window is still open at shutdown.
}
TEST_F(AccessibilityPanelLayoutManagerTest, InitialBounds) {
display::Screen* screen = display::Screen::GetScreen();
gfx::Rect initial_work_area = screen->GetPrimaryDisplay().work_area();
// Simulate Chrome creating the ChromeVox window, but don't show it yet.
std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel();
// The layout manager has not adjusted the work area yet.
EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), initial_work_area);
// Showing the panel causes the layout manager to adjust the panel bounds and
// the display work area.
widget->Show();
gfx::Rect expected_bounds(0, 0, screen->GetPrimaryDisplay().bounds().width(),
kPanelHeight);
EXPECT_EQ(widget->GetNativeWindow()->bounds(), expected_bounds);
gfx::Rect expected_work_area = initial_work_area;
expected_work_area.Inset(0, kPanelHeight, 0, 0);
EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), expected_work_area);
}
TEST_F(AccessibilityPanelLayoutManagerTest, PanelFullscreen) {
AccessibilityPanelLayoutManager* layout_manager = GetLayoutManager();
display::Screen* screen = display::Screen::GetScreen();
std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel();
widget->Show();
gfx::Rect expected_work_area = screen->GetPrimaryDisplay().work_area();
// When the panel is fullscreen it fills the display and does not change the
// work area.
layout_manager->SetPanelFullscreen(true);
EXPECT_EQ(widget->GetNativeWindow()->bounds(),
screen->GetPrimaryDisplay().bounds());
EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), expected_work_area);
// Restoring the panel to default size restores the bounds and does not change
// the work area.
layout_manager->SetPanelFullscreen(false);
gfx::Rect expected_bounds(0, 0, screen->GetPrimaryDisplay().bounds().width(),
kPanelHeight);
EXPECT_EQ(widget->GetNativeWindow()->bounds(), expected_bounds);
EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), expected_work_area);
}
TEST_F(AccessibilityPanelLayoutManagerTest, DisplayBoundsChange) {
std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel();
widget->Show();
// When the display resolution changes the panel still sits at the top of the
// screen.
UpdateDisplay("1234,567");
display::Screen* screen = display::Screen::GetScreen();
gfx::Rect expected_bounds(0, 0, screen->GetPrimaryDisplay().bounds().width(),
kPanelHeight);
EXPECT_EQ(widget->GetNativeWindow()->bounds(), expected_bounds);
gfx::Rect expected_work_area = screen->GetPrimaryDisplay().bounds();
expected_work_area.Inset(0, kPanelHeight, 0, kShelfSize);
EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), expected_work_area);
}
} // namespace
} // namespace ash
// Copyright 2018 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/accessibility/chromevox_layout_manager.h"
#include "base/logging.h"
namespace ash {
ChromeVoxLayoutManager::ChromeVoxLayoutManager() = default;
ChromeVoxLayoutManager::~ChromeVoxLayoutManager() = default;
void ChromeVoxLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
chromevox_window_ = child;
UpdateLayout();
}
void ChromeVoxLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
// NOTE: In browser_tests a second ChromeVoxPanel can be created while the
// first one in closing due to races between loading the extension and
// closing the widget. We only track the latest panel.
if (child == chromevox_window_)
chromevox_window_ = nullptr;
UpdateLayout();
}
void ChromeVoxLayoutManager::SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) {
SetChildBoundsDirect(child, requested_bounds);
}
void ChromeVoxLayoutManager::UpdateLayout() {
// TODO: Implement by moving the code out of ChromeVoxPanel.
}
} // namespace ash
// Copyright 2018 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_ACCESSIBILITY_CHROMEVOX_LAYOUT_MANAGER_H_
#define ASH_ACCESSIBILITY_CHROMEVOX_LAYOUT_MANAGER_H_
#include "ash/ash_export.h"
#include "base/macros.h"
#include "ui/aura/layout_manager.h"
namespace ash {
// ChromeVoxLayoutManager manages the container window used for the ChromeVox
// spoken feedback panel, which sits at the top of the display. It insets the
// display work area bounds when ChromeVox is visible. The ChromeVox panel is
// created by Chrome because spoken feedback is implemented by an extension.
// Exported for test.
class ASH_EXPORT ChromeVoxLayoutManager : public aura::LayoutManager {
public:
ChromeVoxLayoutManager();
~ChromeVoxLayoutManager() override;
// aura::LayoutManager:
void OnWindowResized() override {}
void OnWindowAddedToLayout(aura::Window* child) override;
void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
void OnWindowRemovedFromLayout(aura::Window* child) override;
void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) override {}
void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) override;
aura::Window* chromevox_window_for_test() { return chromevox_window_; }
private:
// Updates the ChromeVox window bounds and the display work area.
void UpdateLayout();
aura::Window* chromevox_window_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ChromeVoxLayoutManager);
};
} // namespace ash
#endif // ASH_ACCESSIBILITY_CHROMEVOX_LAYOUT_MANAGER_H_
// Copyright 2018 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/accessibility/chromevox_layout_manager.h"
#include <memory>
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace {
ChromeVoxLayoutManager* GetLayoutManager() {
aura::Window* container = Shell::GetContainer(
Shell::GetPrimaryRootWindow(), kShellWindowId_ChromeVoxContainer);
return static_cast<ChromeVoxLayoutManager*>(container->layout_manager());
}
using ChromeVoxLayoutManagerTest = AshTestBase;
TEST_F(ChromeVoxLayoutManagerTest, Basics) {
ChromeVoxLayoutManager* layout_manager = GetLayoutManager();
ASSERT_TRUE(layout_manager);
// The layout manager doesn't track anything at startup.
EXPECT_FALSE(layout_manager->chromevox_window_for_test());
// Simulate chrome creating the ChromeVox widget. The layout manager starts
// managing it.
std::unique_ptr<views::Widget> widget =
CreateTestWidget(nullptr, kShellWindowId_ChromeVoxContainer);
EXPECT_EQ(widget->GetNativeWindow(),
layout_manager->chromevox_window_for_test());
// The layout manager doesn't track anything after the widget closes.
widget.reset();
EXPECT_FALSE(layout_manager->chromevox_window_for_test());
}
TEST_F(ChromeVoxLayoutManagerTest, Shutdown) {
ChromeVoxLayoutManager* layout_manager = GetLayoutManager();
ASSERT_TRUE(layout_manager);
// Simulate chrome creating the ChromeVox widget. The layout manager starts
// managing it.
std::unique_ptr<views::Widget> widget =
CreateTestWidget(nullptr, kShellWindowId_ChromeVoxContainer);
EXPECT_EQ(widget->GetNativeWindow(),
layout_manager->chromevox_window_for_test());
// Don't close the window.
widget.release();
// Ash should not crash if the window is still open at shutdown.
}
// TODO: Test the following:
// - Initial ChromeVox window bounds.
// - Display work area updates.
// - Bounds and work area updates during fullscreen.
} // namespace
} // namespace ash
......@@ -13,7 +13,8 @@ namespace ash {
// containers appearing later in the list.
const int32_t kActivatableShellWindowIds[] = {
kShellWindowId_OverlayContainer, kShellWindowId_LockSystemModalContainer,
kShellWindowId_ChromeVoxContainer, kShellWindowId_SettingBubbleContainer,
kShellWindowId_AccessibilityPanelContainer,
kShellWindowId_SettingBubbleContainer,
kShellWindowId_LockActionHandlerContainer,
kShellWindowId_LockScreenContainer, kShellWindowId_SystemModalContainer,
kShellWindowId_AlwaysOnTopContainer, kShellWindowId_AppListContainer,
......
......@@ -108,8 +108,10 @@ enum ShellWindowId {
// changes (volume, brightness, input method bubbles, etc.).
kShellWindowId_SettingBubbleContainer,
// Contains the ChromeVox spoken feedback window.
kShellWindowId_ChromeVoxContainer,
// Contains special accessibility windows that can inset the display work area
// (e.g. the ChromeVox spoken feedback window).
// TODO(jamescook): Consolidate this with DockedMagnifierContainer.
kShellWindowId_AccessibilityPanelContainer,
// The container for special components overlaid onscreen, such as the
// region selector for partial screenshots.
......@@ -160,7 +162,7 @@ const int32_t kAllShellContainerIds[] = {
kShellWindowId_MenuContainer,
kShellWindowId_DragImageAndTooltipContainer,
kShellWindowId_SettingBubbleContainer,
kShellWindowId_ChromeVoxContainer,
kShellWindowId_AccessibilityPanelContainer,
kShellWindowId_OverlayContainer,
kShellWindowId_DockedMagnifierContainer,
kShellWindowId_MouseCursorContainer,
......
......@@ -9,7 +9,7 @@
#include <queue>
#include <vector>
#include "ash/accessibility/chromevox_layout_manager.h"
#include "ash/accessibility/accessibility_panel_layout_manager.h"
#include "ash/accessibility/touch_exploration_controller.h"
#include "ash/ash_constants.h"
#include "ash/ash_touch_exploration_manager_chromeos.h"
......@@ -714,7 +714,8 @@ void RootWindowController::Init(RootWindowType root_window_type) {
}
void RootWindowController::InitLayoutManagers() {
// Create the shelf and status area widgets.
// Create the shelf and status area widgets. Creates the ShelfLayoutManager
// as a side-effect.
DCHECK(!shelf_->shelf_widget());
aura::Window* root = GetRootWindow();
shelf_->CreateShelfWidget(root);
......@@ -924,13 +925,14 @@ void RootWindowController::CreateContainers() {
settings_bubble_container->SetProperty(kUsesScreenCoordinatesKey, true);
settings_bubble_container->SetProperty(kLockedToRootKey, true);
aura::Window* chromevox_container =
CreateContainer(kShellWindowId_ChromeVoxContainer, "ChromeVoxContainer",
lock_screen_related_containers);
::wm::SetChildWindowVisibilityChangesAnimated(chromevox_container);
chromevox_container->SetProperty(kUsesScreenCoordinatesKey, true);
chromevox_container->SetProperty(kLockedToRootKey, true);
chromevox_container->SetLayoutManager(new ChromeVoxLayoutManager());
aura::Window* accessibility_panel_container = CreateContainer(
kShellWindowId_AccessibilityPanelContainer, "AccessibilityPanelContainer",
lock_screen_related_containers);
::wm::SetChildWindowVisibilityChangesAnimated(accessibility_panel_container);
accessibility_panel_container->SetProperty(kUsesScreenCoordinatesKey, true);
accessibility_panel_container->SetProperty(kLockedToRootKey, true);
accessibility_panel_container->SetLayoutManager(
new AccessibilityPanelLayoutManager());
aura::Window* virtual_keyboard_parent_container = CreateContainer(
kShellWindowId_ImeWindowParentContainer, "VirtualKeyboardParentContainer",
......
......@@ -189,8 +189,14 @@ ShelfVisibilityState Shelf::GetVisibilityState() const {
}
int Shelf::GetAccessibilityPanelHeight() const {
return shelf_layout_manager_ ? shelf_layout_manager_->chromevox_panel_height()
: 0;
return shelf_layout_manager_
? shelf_layout_manager_->accessibility_panel_height()
: 0;
}
void Shelf::SetAccessibilityPanelHeight(int height) {
if (shelf_layout_manager_)
shelf_layout_manager_->SetAccessibilityPanelHeight(height);
}
int Shelf::GetDockedMagnifierHeight() const {
......
......@@ -95,6 +95,7 @@ class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver {
ShelfVisibilityState GetVisibilityState() const;
int GetAccessibilityPanelHeight() const;
void SetAccessibilityPanelHeight(int height);
// Returns the height of the Docked Magnifier viewport.
int GetDockedMagnifierHeight() const;
......
......@@ -220,6 +220,11 @@ void ShelfLayoutManager::LayoutShelfAndUpdateBounds(bool change_work_area) {
}
void ShelfLayoutManager::LayoutShelf() {
// The ShelfWidget may be partially closed (no native widget) during shutdown
// so skip layout.
if (in_shutdown_)
return;
LayoutShelfAndUpdateBounds(true);
}
......@@ -507,8 +512,8 @@ ShelfBackgroundType ShelfLayoutManager::GetShelfBackgroundType() const {
return SHELF_BACKGROUND_DEFAULT;
}
void ShelfLayoutManager::SetChromeVoxPanelHeight(int height) {
chromevox_panel_height_ = height;
void ShelfLayoutManager::SetAccessibilityPanelHeight(int height) {
accessibility_panel_height_ = height;
LayoutShelf();
}
......@@ -709,8 +714,8 @@ void ShelfLayoutManager::CalculateTargetBounds(const State& state,
aura::Window* shelf_window = shelf_widget_->GetNativeWindow();
gfx::Rect available_bounds =
screen_util::GetDisplayBoundsWithShelf(shelf_window);
available_bounds.Inset(0, chromevox_panel_height_ + docked_magnifier_height_,
0, 0);
available_bounds.Inset(
0, accessibility_panel_height_ + docked_magnifier_height_, 0, 0);
int shelf_width = PrimaryAxisValue(available_bounds.width(), shelf_size);
int shelf_height = PrimaryAxisValue(shelf_size, available_bounds.height());
int bottom_shelf_vertical_offset = available_bounds.bottom() - shelf_height;
......@@ -755,8 +760,8 @@ void ShelfLayoutManager::CalculateTargetBounds(const State& state,
// Also push in the work area insets for both the ChromeVox panel and the
// Docked Magnifier.
target_bounds->work_area_insets +=
gfx::Insets(chromevox_panel_height_ + docked_magnifier_height_, 0, 0, 0);
target_bounds->work_area_insets += gfx::Insets(
accessibility_panel_height_ + docked_magnifier_height_, 0, 0, 0);
target_bounds->opacity = ComputeTargetOpacity(state);
target_bounds->status_opacity =
......
......@@ -123,7 +123,7 @@ class ASH_EXPORT ShelfLayoutManager
}
ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; }
int chromevox_panel_height() const { return chromevox_panel_height_; }
int accessibility_panel_height() const { return accessibility_panel_height_; }
int docked_magnifier_height() const { return docked_magnifier_height_; }
......@@ -198,9 +198,9 @@ class ASH_EXPORT ShelfLayoutManager
// Returns how the shelf background should be painted.
ShelfBackgroundType GetShelfBackgroundType() const;
// Set the height of the ChromeVox panel, which takes away space from the
// available work area from the top of the screen.
void SetChromeVoxPanelHeight(int height);
// Set the height of the accessibility panel, which takes away space from the
// available work area from the top of the screen. Used by ChromeVox.
void SetAccessibilityPanelHeight(int height);
// Set the height of the Docked Magnifier viewport at the top of the screen,
// which will reduce the available screen work area similarly to the ChromeVox
......@@ -393,12 +393,12 @@ class ASH_EXPORT ShelfLayoutManager
// keyboard.
gfx::Rect user_work_area_bounds_;
// The height of the ChromeVox panel at the top of the screen, which
// needs to be removed from the available work area.
int chromevox_panel_height_ = 0;
// The height of the accessibility panel at the top of the screen, which
// needs to be removed from the available work area. Used by ChromeVox.
int accessibility_panel_height_ = 0;
// The height of the Docked Magnifier viewport at the top of the screen, which
// similarly to |chromevox_panel_height_| needs to be removed from the
// similarly to |accessibility_panel_height_| needs to be removed from the
// available work area.
int docked_magnifier_height_ = 0;
......
......@@ -327,10 +327,10 @@ TEST_F(LockActionHandlerLayoutManagerTest, KeyboardBounds) {
GetPrimaryShelf()->shelf_layout_manager();
ASSERT_TRUE(shelf_layout_manager);
const int chromevox_panel_height = 45;
shelf_layout_manager->SetChromeVoxPanelHeight(chromevox_panel_height);
const int accessibility_panel_height = 45;
shelf_layout_manager->SetAccessibilityPanelHeight(accessibility_panel_height);
target_bounds.Inset(0 /* left */, chromevox_panel_height /* top */,
target_bounds.Inset(0 /* left */, accessibility_panel_height /* top */,
0 /* right */, 0 /* bottom */);
EXPECT_EQ(target_bounds.ToString(), window->GetBoundsInScreen().ToString());
......
......@@ -186,8 +186,8 @@ TEST_F(LockLayoutManagerTest, AccessibilityPanel) {
ASSERT_TRUE(shelf_layout_manager);
// Set the accessibility panel height.
int chromevox_panel_height = 45;
shelf_layout_manager->SetChromeVoxPanelHeight(chromevox_panel_height);
int accessibility_panel_height = 45;
shelf_layout_manager->SetAccessibilityPanelHeight(accessibility_panel_height);
views::Widget::InitParams widget_params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
......@@ -199,18 +199,18 @@ TEST_F(LockLayoutManagerTest, AccessibilityPanel) {
display::Screen::GetScreen()->GetPrimaryDisplay();
gfx::Rect target_bounds = primary_display.bounds();
target_bounds.Inset(0 /* left */, chromevox_panel_height /* top */,
target_bounds.Inset(0 /* left */, accessibility_panel_height /* top */,
0 /* right */, 0 /* bottom */);
EXPECT_EQ(target_bounds, window->GetBoundsInScreen());
// Update the accessibility panel height, and verify the window bounds are
// updated accordingly.
chromevox_panel_height = 25;
shelf_layout_manager->SetChromeVoxPanelHeight(chromevox_panel_height);
accessibility_panel_height = 25;
shelf_layout_manager->SetAccessibilityPanelHeight(accessibility_panel_height);
target_bounds = primary_display.bounds();
target_bounds.Inset(0 /* left */, chromevox_panel_height /* top */,
target_bounds.Inset(0 /* left */, accessibility_panel_height /* top */,
0 /* right */, 0 /* bottom */);
EXPECT_EQ(target_bounds, window->GetBoundsInScreen());
......@@ -343,8 +343,8 @@ TEST_F(LockLayoutManagerTest, AccessibilityPanelWithMultipleMonitors) {
GetPrimaryShelf()->shelf_layout_manager();
ASSERT_TRUE(shelf_layout_manager);
int chromevox_panel_height = 45;
shelf_layout_manager->SetChromeVoxPanelHeight(chromevox_panel_height);
int accessibility_panel_height = 45;
shelf_layout_manager->SetAccessibilityPanelHeight(accessibility_panel_height);
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
......@@ -358,7 +358,7 @@ TEST_F(LockLayoutManagerTest, AccessibilityPanelWithMultipleMonitors) {
gfx::Rect target_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
target_bounds.Inset(0, chromevox_panel_height, 0, 0);
target_bounds.Inset(0, accessibility_panel_height, 0, 0);
EXPECT_EQ(target_bounds, window->GetBoundsInScreen());
// Restore window with bounds in the second display, the window should be
......
......@@ -1056,11 +1056,6 @@ void AccessibilityManager::SetProfile(Profile* profile) {
// ash.
OnSpokenFeedbackChanged();
OnSelectToSpeakChanged();
// Update the panel height in the shelf layout manager when the profile
// changes, since the shelf layout manager doesn't exist in the login profile.
if (chromevox_panel_)
chromevox_panel_->UpdatePanelHeight();
}
void AccessibilityManager::ActiveUserChanged(
......@@ -1314,8 +1309,6 @@ void AccessibilityManager::ReloadChromeVoxPanel() {
}
void AccessibilityManager::OnChromeVoxPanelClosing() {
// TODO: Handle this in ash::ChromeVoxLayoutManager.
chromevox_panel_->ResetPanelHeight();
chromevox_panel_widget_observer_.reset();
chromevox_panel_ = nullptr;
}
......
......@@ -4,11 +4,8 @@
#include "chrome/browser/chromeos/accessibility/chromevox_panel.h"
#include "ash/public/cpp/accessibility_types.h"
#include "ash/accessibility/accessibility_controller.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h"
#include "base/macros.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
......@@ -27,7 +24,6 @@
namespace {
const int kPanelHeight = 35;
const char kChromeVoxPanelRelativeUrl[] = "/cvox2/background/panel.html";
const char kChromeVoxPanelBlockedUserSessionQuery[] =
"?blockedUserSession=true";
......@@ -75,7 +71,6 @@ ChromeVoxPanel::ChromeVoxPanel(content::BrowserContext* browser_context,
bool for_blocked_user_session)
: widget_(nullptr),
web_view_(nullptr),
panel_fullscreen_(false),
for_blocked_user_session_(for_blocked_user_session) {
std::string url("chrome-extension://");
url += extension_misc::kChromeVoxExtensionId;
......@@ -103,7 +98,7 @@ ChromeVoxPanel::ChromeVoxPanel(content::BrowserContext* browser_context,
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
aura::Window* root_window = ash::Shell::GetPrimaryRootWindow();
params.parent = ash::Shell::GetContainer(
root_window, ash::kShellWindowId_ChromeVoxContainer);
root_window, ash::kShellWindowId_AccessibilityPanelContainer);
params.delegate = this;
params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
params.bounds = gfx::Rect(0, 0, root_window->bounds().width(),
......@@ -112,15 +107,9 @@ ChromeVoxPanel::ChromeVoxPanel(content::BrowserContext* browser_context,
widget_->Init(params);
wm::SetShadowElevation(widget_->GetNativeWindow(),
wm::kShadowElevationInactiveWindow);
display::Screen::GetScreen()->AddObserver(this);
ash::Shell::Get()->AddShellObserver(this);
}
ChromeVoxPanel::~ChromeVoxPanel() {
ash::Shell::Get()->RemoveShellObserver(this);
display::Screen::GetScreen()->RemoveObserver(this);
}
ChromeVoxPanel::~ChromeVoxPanel() = default;
aura::Window* ChromeVoxPanel::GetRootWindow() {
return GetWidget()->GetNativeWindow()->GetRootWindow();
......@@ -133,14 +122,6 @@ void ChromeVoxPanel::Close() {
widget_->Close();
}
void ChromeVoxPanel::UpdatePanelHeight() {
SendPanelHeightToAsh(kPanelHeight);
}
void ChromeVoxPanel::ResetPanelHeight() {
SendPanelHeightToAsh(0);
}
const views::Widget* ChromeVoxPanel::GetWidget() const {
return widget_;
}
......@@ -157,32 +138,25 @@ views::View* ChromeVoxPanel::GetContentsView() {
return web_view_;
}
void ChromeVoxPanel::OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) {
UpdateWidgetBounds();
}
void ChromeVoxPanel::OnFullscreenStateChanged(bool is_fullscreen,
aura::Window* root_window) {
UpdateWidgetBounds();
}
void ChromeVoxPanel::DidFirstVisuallyNonEmptyPaint() {
widget_->Show();
UpdatePanelHeight();
}
void ChromeVoxPanel::EnterFullscreen() {
Focus();
panel_fullscreen_ = true;
UpdateWidgetBounds();
// TODO(jamescook): Convert to mojo.
ash::Shell::Get()
->accessibility_controller()
->SetAccessibilityPanelFullscreen(true);
}
void ChromeVoxPanel::ExitFullscreen() {
widget_->Deactivate();
widget_->widget_delegate()->set_can_activate(false);
panel_fullscreen_ = false;
UpdateWidgetBounds();
// TODO(jamescook): Convert to mojo.
ash::Shell::Get()
->accessibility_controller()
->SetAccessibilityPanelFullscreen(false);
}
void ChromeVoxPanel::DisableSpokenFeedback() {
......@@ -196,36 +170,3 @@ void ChromeVoxPanel::Focus() {
web_view_->RequestFocus();
}
void ChromeVoxPanel::UpdateWidgetBounds() {
gfx::Rect bounds(GetRootWindow()->bounds().size());
if (!panel_fullscreen_)
bounds.set_height(kPanelHeight);
// If we're in full-screen mode, give the panel a height of 0 unless
// it's active.
if (ash::RootWindowController::ForWindow(GetRootWindow())
->GetWindowForFullscreenMode() &&
!widget_->IsActive()) {
bounds.set_height(0);
}
// Make sure the ChromeVox panel is always below the Docked Magnifier viewport
// so it shows up and gets magnified.
const int docked_magnifier_height =
ash::Shelf::ForWindow(GetRootWindow())->GetDockedMagnifierHeight();
bounds.Offset(0, docked_magnifier_height);
widget_->SetBounds(bounds);
}
void ChromeVoxPanel::SendPanelHeightToAsh(int panel_height) {
ash::Shelf* shelf = ash::Shelf::ForWindow(GetRootWindow());
ash::ShelfLayoutManager* shelf_layout_manager =
shelf ? shelf->shelf_layout_manager() : nullptr;
if (shelf_layout_manager)
shelf_layout_manager->SetChromeVoxPanelHeight(panel_height);
// NOTE: Setting the panel height causes a display work area change,
// which causes a display::DisplayManager::NotifyMetricsChanged, which calls
// OnDisplayMetricsChanged which calls UpdateWidgetBounds. This can result
// in multiple bounds updates when the window is opened and closed.
}
......@@ -7,9 +7,7 @@
#include <stdint.h>
#include "ash/shell_observer.h"
#include "base/macros.h"
#include "ui/display/display_observer.h"
#include "ui/views/widget/widget_delegate.h"
namespace content {
......@@ -21,12 +19,8 @@ class Widget;
}
// Displays spoken feedback UI controls for the ChromeVox component extension
// in a small panel at the top of the display. Insets the display work area
// when visible.
// TODO(jamescook): Convert the ash::ShellObserver to a mojo interface for mash.
class ChromeVoxPanel : public views::WidgetDelegate,
public display::DisplayObserver,
public ash::ShellObserver {
// in a small panel at the top of the display. Widget bounds are managed by ash.
class ChromeVoxPanel : public views::WidgetDelegate {
public:
ChromeVoxPanel(content::BrowserContext* browser_context,
bool for_blocked_user_session);
......@@ -35,8 +29,6 @@ class ChromeVoxPanel : public views::WidgetDelegate,
aura::Window* GetRootWindow();
void Close();
void UpdatePanelHeight();
void ResetPanelHeight();
// WidgetDelegate overrides.
const views::Widget* GetWidget() const override;
......@@ -44,16 +36,6 @@ class ChromeVoxPanel : public views::WidgetDelegate,
void DeleteDelegate() override;
views::View* GetContentsView() override;
// DisplayObserver overrides:
void OnDisplayAdded(const display::Display& new_display) override {}
void OnDisplayRemoved(const display::Display& old_display) override {}
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override;
// ash::ShellObserver overrides:
void OnFullscreenStateChanged(bool is_fullscreen,
aura::Window* root_window) override;
bool for_blocked_user_session() const { return for_blocked_user_session_; }
private:
......@@ -66,16 +48,9 @@ class ChromeVoxPanel : public views::WidgetDelegate,
void DisableSpokenFeedback();
void Focus();
void UpdateWidgetBounds();
// Sends the height of the ChromeVox panel, which takes away space from the
// available window manager work area at the top of the screen.
void SendPanelHeightToAsh(int panel_height);
views::Widget* widget_;
std::unique_ptr<ChromeVoxPanelWebContentsObserver> web_contents_observer_;
views::View* web_view_;
bool panel_fullscreen_;
const bool for_blocked_user_session_;
DISALLOW_COPY_AND_ASSIGN(ChromeVoxPanel);
......
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