Index: components/exo/shell_surface.cc |
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc |
index 6248a27c13212c96588327d4db216d9844e79d12..3b7027f42c272e2c30e820aebd13d948be515eed 100644 |
--- a/components/exo/shell_surface.cc |
+++ b/components/exo/shell_surface.cc |
@@ -5,10 +5,13 @@ |
#include "components/exo/shell_surface.h" |
#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 +39,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 +93,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 +104,41 @@ class CustomWindowTargeter : public aura::WindowTargeter { |
return false; |
gfx::Point local_point = event.location(); |
- if (window->parent()) |
- aura::Window::ConvertPointToTarget(window->parent(), window, |
+ |
+ if (shadow_underlay_ && !shadow_underlay_->ignore_events()) { |
+ aura::Window::ConvertPointToTarget(window->parent(), shadow_underlay_, |
&local_point); |
+ return gfx::Rect(local_point, gfx::Size(1, 1)) |
+ .Intersects(gfx::Rect(shadow_underlay_->layer()->size())); |
hshi1
2016/09/23 21:29:05
This feels convoluted. It seems equivalent to the
erosky
2016/09/24 00:05:03
Done.
|
+ } |
+ |
+ 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, |
+ ui::Event* event) override { |
+ aura::Window* window = static_cast<aura::Window*>(root); |
+ Surface* surface = ShellSurface::GetMainSurface(window); |
+ 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)))) |
hshi1
2016/09/23 21:29:05
ditto. Why can't we just use HitTestPoint(local_po
erosky
2016/09/24 00:05:03
Surface doesn't have a hittest for just Point.
|
+ 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_; |
DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter); |
}; |
@@ -301,6 +334,11 @@ ShellSurface::~ShellSurface() { |
surface_->SetSurfaceDelegate(nullptr); |
surface_->RemoveSurfaceObserver(this); |
} |
+ if (ash::WmShell::HasInstance() && |
+ ash::WmShell::Get()->system_tray_notifier()) { |
+ ash::WmShell::Get()->system_tray_notifier()->RemoveAccessibilityObserver( |
+ this); |
+ } |
} |
void ShellSurface::AcknowledgeConfigure(uint32_t serial) { |
@@ -725,6 +763,16 @@ gfx::Size ShellSurface::GetPreferredSize() const { |
} |
//////////////////////////////////////////////////////////////////////////////// |
+// ash::AccessibilityObserver overrides: |
+ |
+void ShellSurface::OnAccessibilityModeChanged( |
+ ash::AccessibilityNotificationVisibility) { |
+ audio_feedback_ = |
+ ash::WmShell::Get()->accessibility_delegate()->IsSpokenFeedbackEnabled(); |
+ UpdateShadow(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
// ash::wm::WindowStateObserver overrides: |
void ShellSurface::OnPreWindowStateTypeChange( |
@@ -826,6 +874,29 @@ void ShellSurface::OnWindowActivated( |
//////////////////////////////////////////////////////////////////////////////// |
// ui::EventHandler overrides: |
+void ShellSurface::OnEvent(ui::Event* event) { |
+ if (event->IsLocatedEvent() && event->target() == shadow_underlay_ && |
+ shadow_underlay_ && !shadow_underlay_->ignore_events()) { |
+#if defined(OS_CHROMEOS) |
+ ui::EventType sound_types[] = { |
+ 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}; |
+ for (ui::EventType e : sound_types) { |
+ if (event->type() == e) { |
+ ash::WmShell::Get()->accessibility_delegate()->PlayEarcon( |
+ chromeos::SOUND_VOLUME_ADJUST); |
+ break; |
+ } |
+ } |
+#endif |
+ event->SetHandled(); |
+ return; |
+ } |
+ views::View::OnEvent(event); |
+} |
+ |
void ShellSurface::OnKeyEvent(ui::KeyEvent* event) { |
if (!resizer_) { |
views::View::OnKeyEvent(event); |
@@ -981,6 +1052,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; |
} |
@@ -1240,8 +1314,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); |
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 |
@@ -1251,16 +1325,23 @@ 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 = audio_feedback_ && 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 spoken_feedback/talkback |
+ // is 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()) { |
gfx::Point origin; |