Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Unified Diff: components/exo/shell_surface.cc

Issue 2361993003: Draw underlay behind android apps using talkback (Closed)
Patch Set: underlay always handles events Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/exo/shell_surface.h ('k') | components/exo/shell_surface_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/exo/shell_surface.cc
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 465477e79c488da48e2b777eaafd631ae51591a8..2027afdc95cefa71592fedd06a1681c7bc6043ee 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -4,9 +4,13 @@
#include "components/exo/shell_surface.h"
+#include <algorithm>
+
#include "ash/aura/wm_window_aura.h"
+#include "ash/common/accessibility_delegate.h"
#include "ash/common/shelf/wm_shelf.h"
#include "ash/common/shell_window_ids.h"
+#include "ash/common/system/tray/system_tray_notifier.h"
#include "ash/common/wm/window_resizer.h"
#include "ash/common/wm/window_state.h"
#include "ash/common/wm/window_state_delegate.h"
@@ -37,6 +41,10 @@
#include "ui/wm/core/shadow_types.h"
#include "ui/wm/core/window_util.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/audio/chromeos_sounds.h"
+#endif
+
DECLARE_WINDOW_PROPERTY_TYPE(std::string*)
namespace exo {
@@ -87,7 +95,7 @@ class CustomFrameView : public views::NonClientFrameView {
class CustomWindowTargeter : public aura::WindowTargeter {
public:
- CustomWindowTargeter() {}
+ CustomWindowTargeter(views::Widget* widget) : widget_(widget) {}
~CustomWindowTargeter() override {}
// Overridden from aura::WindowTargeter:
@@ -98,6 +106,20 @@ class CustomWindowTargeter : public aura::WindowTargeter {
return false;
gfx::Point local_point = event.location();
+
+ // If there is an underlay, test against it's bounds instead since it will
+ // be equal or larger than the surface's bounds.
+ aura::Window* shadow_underlay =
+ static_cast<ShellSurface*>(
+ widget_->widget_delegate()->GetContentsView())
+ ->shadow_underlay();
+ if (shadow_underlay) {
+ if (window->parent())
+ aura::Window::ConvertPointToTarget(window->parent(), shadow_underlay,
+ &local_point);
+ return gfx::Rect(shadow_underlay->layer()->size()).Contains(local_point);
+ }
+
if (window->parent())
aura::Window::ConvertPointToTarget(window->parent(), window,
&local_point);
@@ -106,7 +128,29 @@ class CustomWindowTargeter : public aura::WindowTargeter {
return surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1)));
}
+ ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
+ ui::Event* event) override {
+ aura::Window* window = static_cast<aura::Window*>(root);
+ Surface* surface = ShellSurface::GetMainSurface(window);
+
+ // Send events which are outside of the surface's bounds to the underlay.
+ aura::Window* shadow_underlay =
+ static_cast<ShellSurface*>(
+ widget_->widget_delegate()->GetContentsView())
+ ->shadow_underlay();
+ if (surface && event->IsLocatedEvent() && shadow_underlay) {
+ gfx::Point local_point = event->AsLocatedEvent()->location();
+ aura::Window::ConvertPointToTarget(window, surface->window(),
+ &local_point);
+ if (!surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1))))
+ return shadow_underlay;
+ }
+ return aura::WindowTargeter::FindTargetForEvent(root, event);
+ }
+
private:
+ views::Widget* const widget_;
+
DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter);
};
@@ -166,6 +210,42 @@ class ShellSurfaceWidget : public views::Widget {
DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWidget);
};
+class ShadowUnderlayEventHandler : public ui::EventHandler {
+ public:
+ ShadowUnderlayEventHandler() {}
+ ~ShadowUnderlayEventHandler() override {}
+
+ // Overridden from ui::EventHandler:
+ void OnEvent(ui::Event* event) override {
+ // If the event is targeted at the underlay, it means the user has made an
+ // interaction that is outside the surface's bounds and we want to capture
+ // it (usually when in spoken feedback mode). Handle the event (to prevent
+ // behind-windows from receiving it) and play an earcon to notify the user.
+ if (event->IsLocatedEvent()) {
+#if defined(OS_CHROMEOS)
+ const ui::EventType kEarconEventTypes[] = {ui::ET_MOUSE_PRESSED,
+ ui::ET_MOUSEWHEEL,
+ ui::ET_TOUCH_PRESSED,
+ ui::ET_POINTER_DOWN,
+ ui::ET_POINTER_WHEEL_CHANGED,
+ ui::ET_GESTURE_BEGIN,
+ ui::ET_SCROLL,
+ ui::ET_SCROLL_FLING_START};
+ bool is_earcon_event_type =
+ std::find(std::begin(kEarconEventTypes), std::end(kEarconEventTypes),
+ event->type()) != std::end(kEarconEventTypes);
+ if (is_earcon_event_type)
+ ash::WmShell::Get()->accessibility_delegate()->PlayEarcon(
+ chromeos::SOUND_VOLUME_ADJUST);
+#endif
+ event->SetHandled();
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShadowUnderlayEventHandler);
+};
+
} // namespace
// Helper class used to coalesce a number of changes into one "configure"
@@ -302,6 +382,8 @@ ShellSurface::~ShellSurface() {
surface_->SetSurfaceDelegate(nullptr);
surface_->RemoveSurfaceObserver(this);
}
+ ash::WmShell::Get()->system_tray_notifier()->RemoveAccessibilityObserver(
+ this);
}
void ShellSurface::AcknowledgeConfigure(uint32_t serial) {
@@ -726,6 +808,14 @@ gfx::Size ShellSurface::GetPreferredSize() const {
}
////////////////////////////////////////////////////////////////////////////////
+// ash::AccessibilityObserver overrides:
+
+void ShellSurface::OnAccessibilityModeChanged(
+ ash::AccessibilityNotificationVisibility) {
+ UpdateShadow();
+}
+
+////////////////////////////////////////////////////////////////////////////////
// ash::wm::WindowStateObserver overrides:
void ShellSurface::OnPreWindowStateTypeChange(
@@ -821,6 +911,7 @@ void ShellSurface::OnWindowActivated(
lost_active == widget_->GetNativeWindow()) {
DCHECK(activatable_);
Configure();
+ UpdateShadow();
}
}
@@ -936,7 +1027,7 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) {
aura::Window* window = widget_->GetNativeWindow();
window->SetName("ExoShellSurface");
window->AddChild(surface_->window());
- window->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter));
+ window->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter(widget_)));
SetApplicationId(window, &application_id_);
SetMainSurface(window, surface_);
@@ -982,6 +1073,9 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) {
window_state->SetDelegate(std::unique_ptr<ash::wm::WindowStateDelegate>(
new CustomWindowStateDelegate(widget_)));
+ // Receive accessibility changes to update shadow underlay.
+ ash::WmShell::Get()->system_tray_notifier()->AddAccessibilityObserver(this);
+
// Show widget next time Commit() is called.
pending_show_widget_ = true;
}
@@ -1241,8 +1335,10 @@ void ShellSurface::UpdateShadow() {
// Always create and show the underlay, even in maximized/fullscreen.
if (!shadow_underlay_) {
shadow_underlay_ = new aura::Window(nullptr);
+ shadow_underlay_event_handler_ =
+ base::MakeUnique<ShadowUnderlayEventHandler>();
+ shadow_underlay_->SetTargetHandler(shadow_underlay_event_handler_.get());
DCHECK(shadow_underlay_->owned_by_parent());
- shadow_underlay_->set_ignore_events(true);
// Ensure the background area inside the shadow is solid black.
// Clients that provide translucent contents should not be using
// rectangular shadows as this method requires opaque contents to
@@ -1254,16 +1350,22 @@ void ShellSurface::UpdateShadow() {
window->StackChildAtBottom(shadow_underlay_);
}
+ bool underlay_capture_events = ash::WmShell::Get()
+ ->accessibility_delegate()
+ ->IsSpokenFeedbackEnabled() &&
+ widget_->IsActive();
+
float shadow_underlay_opacity = rectangular_shadow_background_opacity_;
// Put the black background layer behind the window if
- // 1) the window is in immersive fullscreen.
+ // 1) the window is in immersive fullscreen or is active with
+ // spoken feedback enabled.
// 2) the window can control the bounds of the window in fullscreen (
// thus the background can be visible).
// 3) the window has no transform (the transformed background may
// not cover the entire background, e.g. overview mode).
- if (widget_->IsFullscreen() &&
+ if ((widget_->IsFullscreen() || underlay_capture_events) &&
ash::wm::GetWindowState(window)->allow_set_bounds_in_maximized() &&
- window->layer()->transform().IsIdentity()) {
+ window->layer()->GetTargetTransform().IsIdentity()) {
gfx::Point origin;
origin -= window->bounds().origin().OffsetFromOrigin();
shadow_bounds.set_origin(origin);
« no previous file with comments | « components/exo/shell_surface.h ('k') | components/exo/shell_surface_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698