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

Side by Side Diff: components/exo/shell_surface.cc

Issue 2361993003: Draw underlay behind android apps using talkback (Closed)
Patch Set: Draw underlay behind android apps using talkback 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/exo/shell_surface.h" 5 #include "components/exo/shell_surface.h"
6 6
7 #include "ash/aura/wm_window_aura.h" 7 #include "ash/aura/wm_window_aura.h"
8 #include "ash/common/accessibility_delegate.h"
8 #include "ash/common/shell_window_ids.h" 9 #include "ash/common/shell_window_ids.h"
10 #include "ash/common/system/tray/system_tray_notifier.h"
9 #include "ash/common/wm/window_resizer.h" 11 #include "ash/common/wm/window_resizer.h"
10 #include "ash/common/wm/window_state.h" 12 #include "ash/common/wm/window_state.h"
11 #include "ash/common/wm/window_state_delegate.h" 13 #include "ash/common/wm/window_state_delegate.h"
14 #include "ash/common/wm_shell.h"
12 #include "ash/shell.h" 15 #include "ash/shell.h"
13 #include "ash/wm/window_state_aura.h" 16 #include "ash/wm/window_state_aura.h"
14 #include "ash/wm/window_util.h" 17 #include "ash/wm/window_util.h"
15 #include "base/logging.h" 18 #include "base/logging.h"
16 #include "base/macros.h" 19 #include "base/macros.h"
17 #include "base/memory/ptr_util.h" 20 #include "base/memory/ptr_util.h"
18 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
19 #include "base/trace_event/trace_event.h" 22 #include "base/trace_event/trace_event.h"
20 #include "base/trace_event/trace_event_argument.h" 23 #include "base/trace_event/trace_event_argument.h"
21 #include "components/exo/surface.h" 24 #include "components/exo/surface.h"
22 #include "ui/aura/client/aura_constants.h" 25 #include "ui/aura/client/aura_constants.h"
23 #include "ui/aura/client/cursor_client.h" 26 #include "ui/aura/client/cursor_client.h"
24 #include "ui/aura/window.h" 27 #include "ui/aura/window.h"
25 #include "ui/aura/window_event_dispatcher.h" 28 #include "ui/aura/window_event_dispatcher.h"
26 #include "ui/aura/window_property.h" 29 #include "ui/aura/window_property.h"
27 #include "ui/aura/window_targeter.h" 30 #include "ui/aura/window_targeter.h"
28 #include "ui/aura/window_tree_host.h" 31 #include "ui/aura/window_tree_host.h"
29 #include "ui/base/accelerators/accelerator.h" 32 #include "ui/base/accelerators/accelerator.h"
30 #include "ui/gfx/path.h" 33 #include "ui/gfx/path.h"
31 #include "ui/views/widget/widget.h" 34 #include "ui/views/widget/widget.h"
32 #include "ui/views/widget/widget_observer.h" 35 #include "ui/views/widget/widget_observer.h"
33 #include "ui/wm/core/coordinate_conversion.h" 36 #include "ui/wm/core/coordinate_conversion.h"
34 #include "ui/wm/core/shadow.h" 37 #include "ui/wm/core/shadow.h"
35 #include "ui/wm/core/shadow_controller.h" 38 #include "ui/wm/core/shadow_controller.h"
36 #include "ui/wm/core/shadow_types.h" 39 #include "ui/wm/core/shadow_types.h"
37 #include "ui/wm/core/window_util.h" 40 #include "ui/wm/core/window_util.h"
38 41
42 #if defined(OS_CHROMEOS)
43 #include "chromeos/audio/chromeos_sounds.h"
44 #endif
45
39 DECLARE_WINDOW_PROPERTY_TYPE(std::string*) 46 DECLARE_WINDOW_PROPERTY_TYPE(std::string*)
40 47
41 namespace exo { 48 namespace exo {
42 namespace { 49 namespace {
43 50
44 // This is a struct for accelerator keys used to close ShellSurfaces. 51 // This is a struct for accelerator keys used to close ShellSurfaces.
45 const struct Accelerator { 52 const struct Accelerator {
46 ui::KeyboardCode keycode; 53 ui::KeyboardCode keycode;
47 int modifiers; 54 int modifiers;
48 } kCloseWindowAccelerators[] = { 55 } kCloseWindowAccelerators[] = {
(...skipping 30 matching lines...) Expand all
79 void SizeConstraintsChanged() override {} 86 void SizeConstraintsChanged() override {}
80 87
81 private: 88 private:
82 views::Widget* const widget_; 89 views::Widget* const widget_;
83 90
84 DISALLOW_COPY_AND_ASSIGN(CustomFrameView); 91 DISALLOW_COPY_AND_ASSIGN(CustomFrameView);
85 }; 92 };
86 93
87 class CustomWindowTargeter : public aura::WindowTargeter { 94 class CustomWindowTargeter : public aura::WindowTargeter {
88 public: 95 public:
89 CustomWindowTargeter() {} 96 CustomWindowTargeter() : shadow_underlay_(nullptr) {}
90 ~CustomWindowTargeter() override {} 97 ~CustomWindowTargeter() override {}
91 98
92 // Overridden from aura::WindowTargeter: 99 // Overridden from aura::WindowTargeter:
93 bool EventLocationInsideBounds(aura::Window* window, 100 bool EventLocationInsideBounds(aura::Window* window,
94 const ui::LocatedEvent& event) const override { 101 const ui::LocatedEvent& event) const override {
95 Surface* surface = ShellSurface::GetMainSurface(window); 102 Surface* surface = ShellSurface::GetMainSurface(window);
96 if (!surface) 103 if (!surface)
97 return false; 104 return false;
98 105
99 gfx::Point local_point = event.location(); 106 gfx::Point local_point = event.location();
100 if (window->parent()) 107
101 aura::Window::ConvertPointToTarget(window->parent(), window, 108 if (shadow_underlay_ && !shadow_underlay_->ignore_events()) {
109 aura::Window::ConvertPointToTarget(window->parent(), shadow_underlay_,
102 &local_point); 110 &local_point);
111 return gfx::Rect(local_point, gfx::Size(1, 1))
112 .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.
113 }
114
115 aura::Window::ConvertPointToTarget(window->parent(), window, &local_point);
103 116
104 aura::Window::ConvertPointToTarget(window, surface->window(), &local_point); 117 aura::Window::ConvertPointToTarget(window, surface->window(), &local_point);
105 return surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1))); 118 return surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1)));
106 } 119 }
107 120
121 ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
122 ui::Event* event) override {
123 aura::Window* window = static_cast<aura::Window*>(root);
124 Surface* surface = ShellSurface::GetMainSurface(window);
125 if (surface && event->IsLocatedEvent() && shadow_underlay_ &&
126 !shadow_underlay_->ignore_events()) {
127 gfx::Point local_point = event->AsLocatedEvent()->location();
128 aura::Window::ConvertPointToTarget(window, surface->window(),
129 &local_point);
130 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.
131 return shadow_underlay_;
132 }
133 return aura::WindowTargeter::FindTargetForEvent(root, event);
134 }
135
136 void set_shadow_underlay(aura::Window* shadow_underlay) {
137 shadow_underlay_ = shadow_underlay;
138 }
139
108 private: 140 private:
141 aura::Window* shadow_underlay_;
109 DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter); 142 DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter);
110 }; 143 };
111 144
112 // Handles a user's fullscreen request (Shift+F4/F4). 145 // Handles a user's fullscreen request (Shift+F4/F4).
113 class CustomWindowStateDelegate : public ash::wm::WindowStateDelegate, 146 class CustomWindowStateDelegate : public ash::wm::WindowStateDelegate,
114 public views::WidgetObserver { 147 public views::WidgetObserver {
115 public: 148 public:
116 explicit CustomWindowStateDelegate(views::Widget* widget) : widget_(widget) { 149 explicit CustomWindowStateDelegate(views::Widget* widget) : widget_(widget) {
117 widget_->AddObserver(this); 150 widget_->AddObserver(this);
118 } 151 }
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 } 327 }
295 WMHelper::GetInstance()->RemoveActivationObserver(this); 328 WMHelper::GetInstance()->RemoveActivationObserver(this);
296 if (parent_) 329 if (parent_)
297 parent_->RemoveObserver(this); 330 parent_->RemoveObserver(this);
298 if (surface_) { 331 if (surface_) {
299 if (scale_ != 1.0) 332 if (scale_ != 1.0)
300 surface_->window()->SetTransform(gfx::Transform()); 333 surface_->window()->SetTransform(gfx::Transform());
301 surface_->SetSurfaceDelegate(nullptr); 334 surface_->SetSurfaceDelegate(nullptr);
302 surface_->RemoveSurfaceObserver(this); 335 surface_->RemoveSurfaceObserver(this);
303 } 336 }
337 if (ash::WmShell::HasInstance() &&
338 ash::WmShell::Get()->system_tray_notifier()) {
339 ash::WmShell::Get()->system_tray_notifier()->RemoveAccessibilityObserver(
340 this);
341 }
304 } 342 }
305 343
306 void ShellSurface::AcknowledgeConfigure(uint32_t serial) { 344 void ShellSurface::AcknowledgeConfigure(uint32_t serial) {
307 TRACE_EVENT1("exo", "ShellSurface::AcknowledgeConfigure", "serial", serial); 345 TRACE_EVENT1("exo", "ShellSurface::AcknowledgeConfigure", "serial", serial);
308 346
309 // Apply all configs that are older or equal to |serial|. The result is that 347 // Apply all configs that are older or equal to |serial|. The result is that
310 // the origin of the main surface will move and the resize direction will 348 // the origin of the main surface will move and the resize direction will
311 // change to reflect the acknowledgement of configure request with |serial| 349 // change to reflect the acknowledgement of configure request with |serial|
312 // at the next call to Commit(). 350 // at the next call to Commit().
313 while (!pending_configs_.empty()) { 351 while (!pending_configs_.empty()) {
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 // views::Views overrides: 756 // views::Views overrides:
719 757
720 gfx::Size ShellSurface::GetPreferredSize() const { 758 gfx::Size ShellSurface::GetPreferredSize() const {
721 if (!geometry_.IsEmpty()) 759 if (!geometry_.IsEmpty())
722 return geometry_.size(); 760 return geometry_.size();
723 761
724 return surface_ ? surface_->window()->layer()->size() : gfx::Size(); 762 return surface_ ? surface_->window()->layer()->size() : gfx::Size();
725 } 763 }
726 764
727 //////////////////////////////////////////////////////////////////////////////// 765 ////////////////////////////////////////////////////////////////////////////////
766 // ash::AccessibilityObserver overrides:
767
768 void ShellSurface::OnAccessibilityModeChanged(
769 ash::AccessibilityNotificationVisibility) {
770 audio_feedback_ =
771 ash::WmShell::Get()->accessibility_delegate()->IsSpokenFeedbackEnabled();
772 UpdateShadow();
773 }
774
775 ////////////////////////////////////////////////////////////////////////////////
728 // ash::wm::WindowStateObserver overrides: 776 // ash::wm::WindowStateObserver overrides:
729 777
730 void ShellSurface::OnPreWindowStateTypeChange( 778 void ShellSurface::OnPreWindowStateTypeChange(
731 ash::wm::WindowState* window_state, 779 ash::wm::WindowState* window_state,
732 ash::wm::WindowStateType old_type) { 780 ash::wm::WindowStateType old_type) {
733 ash::wm::WindowStateType new_type = window_state->GetStateType(); 781 ash::wm::WindowStateType new_type = window_state->GetStateType();
734 if (ash::wm::IsMaximizedOrFullscreenOrPinnedWindowStateType(old_type) || 782 if (ash::wm::IsMaximizedOrFullscreenOrPinnedWindowStateType(old_type) ||
735 ash::wm::IsMaximizedOrFullscreenOrPinnedWindowStateType(new_type)) { 783 ash::wm::IsMaximizedOrFullscreenOrPinnedWindowStateType(new_type)) {
736 // When transitioning in/out of maximized or fullscreen mode we need to 784 // When transitioning in/out of maximized or fullscreen mode we need to
737 // make sure we have a configure callback before we allow the default 785 // make sure we have a configure callback before we allow the default
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 if (gained_active == widget_->GetNativeWindow() || 867 if (gained_active == widget_->GetNativeWindow() ||
820 lost_active == widget_->GetNativeWindow()) { 868 lost_active == widget_->GetNativeWindow()) {
821 DCHECK(activatable_); 869 DCHECK(activatable_);
822 Configure(); 870 Configure();
823 } 871 }
824 } 872 }
825 873
826 //////////////////////////////////////////////////////////////////////////////// 874 ////////////////////////////////////////////////////////////////////////////////
827 // ui::EventHandler overrides: 875 // ui::EventHandler overrides:
828 876
877 void ShellSurface::OnEvent(ui::Event* event) {
878 if (event->IsLocatedEvent() && event->target() == shadow_underlay_ &&
879 shadow_underlay_ && !shadow_underlay_->ignore_events()) {
880 #if defined(OS_CHROMEOS)
881 ui::EventType sound_types[] = {
882 ui::ET_TOUCH_PRESSED, ui::ET_POINTER_DOWN,
883 ui::ET_POINTER_WHEEL_CHANGED, ui::ET_SCROLL,
884 ui::ET_SCROLL_FLING_START, ui::ET_GESTURE_BEGIN,
885 ui::ET_MOUSE_PRESSED, ui::ET_MOUSEWHEEL};
886 for (ui::EventType e : sound_types) {
887 if (event->type() == e) {
888 ash::WmShell::Get()->accessibility_delegate()->PlayEarcon(
889 chromeos::SOUND_VOLUME_ADJUST);
890 break;
891 }
892 }
893 #endif
894 event->SetHandled();
895 return;
896 }
897 views::View::OnEvent(event);
898 }
899
829 void ShellSurface::OnKeyEvent(ui::KeyEvent* event) { 900 void ShellSurface::OnKeyEvent(ui::KeyEvent* event) {
830 if (!resizer_) { 901 if (!resizer_) {
831 views::View::OnKeyEvent(event); 902 views::View::OnKeyEvent(event);
832 return; 903 return;
833 } 904 }
834 905
835 if (event->type() == ui::ET_KEY_PRESSED && 906 if (event->type() == ui::ET_KEY_PRESSED &&
836 event->key_code() == ui::VKEY_ESCAPE) { 907 event->key_code() == ui::VKEY_ESCAPE) {
837 EndDrag(true /* revert */); 908 EndDrag(true /* revert */);
838 } 909 }
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
974 for (const auto& entry : kCloseWindowAccelerators) { 1045 for (const auto& entry : kCloseWindowAccelerators) {
975 focus_manager->RegisterAccelerator( 1046 focus_manager->RegisterAccelerator(
976 ui::Accelerator(entry.keycode, entry.modifiers), 1047 ui::Accelerator(entry.keycode, entry.modifiers),
977 ui::AcceleratorManager::kNormalPriority, this); 1048 ui::AcceleratorManager::kNormalPriority, this);
978 } 1049 }
979 1050
980 // Set delegate for handling of fullscreening. 1051 // Set delegate for handling of fullscreening.
981 window_state->SetDelegate(std::unique_ptr<ash::wm::WindowStateDelegate>( 1052 window_state->SetDelegate(std::unique_ptr<ash::wm::WindowStateDelegate>(
982 new CustomWindowStateDelegate(widget_))); 1053 new CustomWindowStateDelegate(widget_)));
983 1054
1055 // Receive accessibility changes to update shadow underlay.
1056 ash::WmShell::Get()->system_tray_notifier()->AddAccessibilityObserver(this);
1057
984 // Show widget next time Commit() is called. 1058 // Show widget next time Commit() is called.
985 pending_show_widget_ = true; 1059 pending_show_widget_ = true;
986 } 1060 }
987 1061
988 void ShellSurface::Configure() { 1062 void ShellSurface::Configure() {
989 DCHECK(widget_); 1063 DCHECK(widget_);
990 1064
991 // Delay configure callback if |scoped_configure_| is set. 1065 // Delay configure callback if |scoped_configure_| is set.
992 if (scoped_configure_) { 1066 if (scoped_configure_) {
993 scoped_configure_->set_needs_configure(); 1067 scoped_configure_->set_needs_configure();
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 // TODO(oshima): Adjust the coordinates from client screen to 1307 // TODO(oshima): Adjust the coordinates from client screen to
1234 // chromeos screen when multi displays are supported. 1308 // chromeos screen when multi displays are supported.
1235 gfx::Point origin = window->bounds().origin(); 1309 gfx::Point origin = window->bounds().origin();
1236 gfx::Point shadow_origin = shadow_content_bounds_.origin(); 1310 gfx::Point shadow_origin = shadow_content_bounds_.origin();
1237 shadow_origin -= origin.OffsetFromOrigin(); 1311 shadow_origin -= origin.OffsetFromOrigin();
1238 gfx::Rect shadow_bounds(shadow_origin, shadow_content_bounds_.size()); 1312 gfx::Rect shadow_bounds(shadow_origin, shadow_content_bounds_.size());
1239 1313
1240 // Always create and show the underlay, even in maximized/fullscreen. 1314 // Always create and show the underlay, even in maximized/fullscreen.
1241 if (!shadow_underlay_) { 1315 if (!shadow_underlay_) {
1242 shadow_underlay_ = new aura::Window(nullptr); 1316 shadow_underlay_ = new aura::Window(nullptr);
1317 shadow_underlay_->SetTargetHandler(this);
1243 DCHECK(shadow_underlay_->owned_by_parent()); 1318 DCHECK(shadow_underlay_->owned_by_parent());
1244 shadow_underlay_->set_ignore_events(true);
1245 // Ensure the background area inside the shadow is solid black. 1319 // Ensure the background area inside the shadow is solid black.
1246 // Clients that provide translucent contents should not be using 1320 // Clients that provide translucent contents should not be using
1247 // rectangular shadows as this method requires opaque contents to 1321 // rectangular shadows as this method requires opaque contents to
1248 // cast a shadow that represent it correctly. 1322 // cast a shadow that represent it correctly.
1249 shadow_underlay_->Init(ui::LAYER_SOLID_COLOR); 1323 shadow_underlay_->Init(ui::LAYER_SOLID_COLOR);
1250 shadow_underlay_->layer()->SetColor(SK_ColorBLACK); 1324 shadow_underlay_->layer()->SetColor(SK_ColorBLACK);
1251 DCHECK(shadow_underlay_->layer()->fills_bounds_opaquely()); 1325 DCHECK(shadow_underlay_->layer()->fills_bounds_opaquely());
1252 window->AddChild(shadow_underlay_); 1326 window->AddChild(shadow_underlay_);
1253 window->StackChildAtBottom(shadow_underlay_); 1327 window->StackChildAtBottom(shadow_underlay_);
1328 static_cast<CustomWindowTargeter*>(
1329 static_cast<ui::EventTarget*>(window)->GetEventTargeter())
1330 ->set_shadow_underlay(shadow_underlay_);
1254 } 1331 }
1255 1332
1333 bool underlay_capture_events = audio_feedback_ && widget_->IsActive();
1334 shadow_underlay_->set_ignore_events(!underlay_capture_events);
1335
1256 float shadow_underlay_opacity = rectangular_shadow_background_opacity_; 1336 float shadow_underlay_opacity = rectangular_shadow_background_opacity_;
1257 // Put the black background layer behind the window if 1337 // Put the black background layer behind the window if
1258 // 1) the window is in immersive fullscreen. 1338 // 1) the window is in immersive fullscreen or spoken_feedback/talkback
1339 // is enabled.
1259 // 2) the window can control the bounds of the window in fullscreen ( 1340 // 2) the window can control the bounds of the window in fullscreen (
1260 // thus the background can be visible). 1341 // thus the background can be visible).
1261 // 3) the window has no transform (the transformed background may 1342 // 3) the window has no transform (the transformed background may
1262 // not cover the entire background, e.g. overview mode). 1343 // not cover the entire background, e.g. overview mode).
1263 if (widget_->IsFullscreen() && 1344 if ((widget_->IsFullscreen() || underlay_capture_events) &&
1264 ash::wm::GetWindowState(window)->allow_set_bounds_in_maximized() && 1345 ash::wm::GetWindowState(window)->allow_set_bounds_in_maximized() &&
1265 window->layer()->transform().IsIdentity()) { 1346 window->layer()->transform().IsIdentity()) {
1266 gfx::Point origin; 1347 gfx::Point origin;
1267 origin -= window->bounds().origin().OffsetFromOrigin(); 1348 origin -= window->bounds().origin().OffsetFromOrigin();
1268 shadow_bounds.set_origin(origin); 1349 shadow_bounds.set_origin(origin);
1269 shadow_bounds.set_size(window->parent()->bounds().size()); 1350 shadow_bounds.set_size(window->parent()->bounds().size());
1270 shadow_underlay_opacity = 1.0f; 1351 shadow_underlay_opacity = 1.0f;
1271 } 1352 }
1272 1353
1273 shadow_underlay_->SetBounds(shadow_bounds); 1354 shadow_underlay_->SetBounds(shadow_bounds);
(...skipping 20 matching lines...) Expand all
1294 shadow_overlay_->layer()->Add(shadow->layer()); 1375 shadow_overlay_->layer()->Add(shadow->layer());
1295 window->AddChild(shadow_overlay_); 1376 window->AddChild(shadow_overlay_);
1296 shadow_overlay_->Show(); 1377 shadow_overlay_->Show();
1297 } 1378 }
1298 shadow_overlay_->SetBounds(shadow_bounds); 1379 shadow_overlay_->SetBounds(shadow_bounds);
1299 shadow->SetContentBounds(gfx::Rect(shadow_bounds.size())); 1380 shadow->SetContentBounds(gfx::Rect(shadow_bounds.size()));
1300 } 1381 }
1301 } 1382 }
1302 1383
1303 } // namespace exo 1384 } // namespace exo
OLDNEW
« 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