Skip to content

Commit

Permalink
cros: Move ChromeVoxPanel bounds management into ash
Browse files Browse the repository at this point in the history
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: Michael Wasserman <msw@chromium.org>
Reviewed-by: David Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#541614}
  • Loading branch information
James Cook authored and Commit Bot committed Mar 7, 2018
1 parent aff665f commit b263b51
Show file tree
Hide file tree
Showing 21 changed files with 441 additions and 299 deletions.
6 changes: 3 additions & 3 deletions ash/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
16 changes: 16 additions & 0 deletions ash/accessibility/accessibility_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"

Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions ash/accessibility/accessibility_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
120 changes: 120 additions & 0 deletions ash/accessibility/accessibility_panel_layout_manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// 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
86 changes: 86 additions & 0 deletions ash/accessibility/accessibility_panel_layout_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// 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_
Loading

0 comments on commit b263b51

Please sign in to comment.