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

Unified Diff: components/exo/shell_surface.cc

Issue 2361993003: Draw underlay behind android apps using talkback (Closed)
Patch Set: Addressed some CL comments and added some comments Created 4 years, 3 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 941bdbc94689b47889aeb6ddaaf3bf13f0c68226..0ea00afdbe8ec3c320d450c66199a1f4af519b98 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -4,11 +4,16 @@
#include "components/exo/shell_surface.h"
+#include <algorithm>
+
#include "ash/aura/wm_window_aura.h"
+#include "ash/common/accessibility_delegate.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"
+#include "ash/common/wm_shell.h"
#include "ash/shell.h"
#include "ash/wm/window_state_aura.h"
#include "ash/wm/window_util.h"
@@ -36,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 {
@@ -86,7 +95,7 @@ class CustomFrameView : public views::NonClientFrameView {
class CustomWindowTargeter : public aura::WindowTargeter {
public:
- CustomWindowTargeter() {}
+ CustomWindowTargeter() : shadow_underlay_(nullptr) {}
~CustomWindowTargeter() override {}
// Overridden from aura::WindowTargeter:
@@ -97,15 +106,45 @@ class CustomWindowTargeter : public aura::WindowTargeter {
return false;
gfx::Point local_point = event.location();
- if (window->parent())
reveman 2016/09/30 05:59:10 where did this check go? can you instead keep this
erosky 2016/09/30 18:38:40 ConvertPointToTarget already does the check, but I
- aura::Window::ConvertPointToTarget(window->parent(), window,
+
+ // If the underlay is accepting events, test against it's bounds instead
+ // since it will be larger than (and contain) the surface's bounds.
+ if (shadow_underlay_ && !shadow_underlay_->ignore_events()) {
+ aura::Window::ConvertPointToTarget(window->parent(), shadow_underlay_,
&local_point);
+ return gfx::Rect(shadow_underlay_->layer()->size()).Contains(local_point);
+ }
+
+ aura::Window::ConvertPointToTarget(window->parent(), window, &local_point);
aura::Window::ConvertPointToTarget(window, surface->window(), &local_point);
return surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1)));
}
+ ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
reveman 2016/09/30 05:59:10 Why do we need to override this? What would it tak
erosky 2016/09/30 18:38:40 The default implementation clips the event at the
+ 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.
+ if (surface && event->IsLocatedEvent() && shadow_underlay_ &&
+ !shadow_underlay_->ignore_events()) {
+ 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);
+ }
+
+ void set_shadow_underlay(aura::Window* shadow_underlay) {
+ shadow_underlay_ = shadow_underlay;
+ }
+
private:
+ aura::Window* shadow_underlay_;
reveman 2016/09/30 05:59:10 Instead of tracking this state here and having to
erosky 2016/09/30 18:38:40 It can't get out of sync because there is a 1-to-1
+
DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter);
};
@@ -301,6 +340,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 +767,14 @@ gfx::Size ShellSurface::GetPreferredSize() const {
}
////////////////////////////////////////////////////////////////////////////////
+// ash::AccessibilityObserver overrides:
+
+void ShellSurface::OnAccessibilityModeChanged(
+ ash::AccessibilityNotificationVisibility) {
+ UpdateShadow();
+}
+
+////////////////////////////////////////////////////////////////////////////////
// ash::wm::WindowStateObserver overrides:
void ShellSurface::OnPreWindowStateTypeChange(
@@ -821,12 +870,39 @@ void ShellSurface::OnWindowActivated(
lost_active == widget_->GetNativeWindow()) {
DCHECK(activatable_);
Configure();
+ UpdateShadow();
}
}
////////////////////////////////////////////////////////////////////////////////
// ui::EventHandler overrides:
+void ShellSurface::OnEvent(ui::Event* event) {
+ // 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
reveman 2016/09/30 05:59:10 nit: s/spoken_feedback/spoken feedback/
erosky 2016/09/30 18:38:40 Done.
+ // behind-windows from receiving it) and play an earcon to notify the user.
+ if (event->IsLocatedEvent() && event->target() == shadow_underlay_ &&
+ shadow_underlay_ && !shadow_underlay_->ignore_events()) {
+#if defined(OS_CHROMEOS)
+ const ui::EventType kEarconEventTypes[] = {
reveman 2016/09/30 05:59:10 nit: are these elements sorted in a way that I'm f
erosky 2016/09/30 18:38:40 Done.
+ ui::ET_TOUCH_PRESSED, ui::ET_POINTER_DOWN,
+ ui::ET_POINTER_WHEEL_CHANGED, ui::ET_SCROLL,
+ ui::ET_SCROLL_FLING_START, ui::ET_GESTURE_BEGIN,
+ ui::ET_MOUSE_PRESSED, ui::ET_MOUSEWHEEL};
+ 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();
+ return;
+ }
+ views::View::OnEvent(event);
+}
+
void ShellSurface::OnKeyEvent(ui::KeyEvent* event) {
if (!resizer_) {
views::View::OnKeyEvent(event);
@@ -982,6 +1058,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 +1320,8 @@ void ShellSurface::UpdateShadow() {
// Always create and show the underlay, even in maximized/fullscreen.
if (!shadow_underlay_) {
shadow_underlay_ = new aura::Window(nullptr);
+ shadow_underlay_->SetTargetHandler(this);
reveman 2016/09/30 05:59:10 Can we use a different aura::WindowDelegate for th
erosky 2016/09/30 18:38:40 Done.
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
@@ -1252,18 +1331,28 @@ void ShellSurface::UpdateShadow() {
DCHECK(shadow_underlay_->layer()->fills_bounds_opaquely());
window->AddChild(shadow_underlay_);
window->StackChildAtBottom(shadow_underlay_);
+ static_cast<CustomWindowTargeter*>(
+ static_cast<ui::EventTarget*>(window)->GetEventTargeter())
+ ->set_shadow_underlay(shadow_underlay_);
}
+ bool underlay_capture_events = ash::WmShell::Get()
+ ->accessibility_delegate()
+ ->IsSpokenFeedbackEnabled() &&
+ widget_->IsActive();
+ shadow_underlay_->set_ignore_events(!underlay_capture_events);
+
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