Chromium Code Reviews| 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; |