| OLD | NEW |
| 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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "ash/frame/custom_frame_view_ash.h" | 9 #include "ash/frame/custom_frame_view_ash.h" |
| 10 #include "ash/public/cpp/shell_window_ids.h" | 10 #include "ash/public/cpp/shell_window_ids.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "ui/display/screen.h" | 37 #include "ui/display/screen.h" |
| 38 #include "ui/gfx/path.h" | 38 #include "ui/gfx/path.h" |
| 39 #include "ui/views/widget/widget.h" | 39 #include "ui/views/widget/widget.h" |
| 40 #include "ui/wm/core/coordinate_conversion.h" | 40 #include "ui/wm/core/coordinate_conversion.h" |
| 41 #include "ui/wm/core/shadow.h" | 41 #include "ui/wm/core/shadow.h" |
| 42 #include "ui/wm/core/shadow_controller.h" | 42 #include "ui/wm/core/shadow_controller.h" |
| 43 #include "ui/wm/core/shadow_types.h" | 43 #include "ui/wm/core/shadow_types.h" |
| 44 #include "ui/wm/core/window_animations.h" | 44 #include "ui/wm/core/window_animations.h" |
| 45 #include "ui/wm/core/window_util.h" | 45 #include "ui/wm/core/window_util.h" |
| 46 | 46 |
| 47 #if defined(OS_CHROMEOS) |
| 48 #include "chromeos/audio/chromeos_sounds.h" |
| 49 #endif |
| 50 |
| 47 namespace exo { | 51 namespace exo { |
| 48 namespace { | 52 namespace { |
| 49 | 53 |
| 50 // This is a struct for accelerator keys used to close ShellSurfaces. | 54 // This is a struct for accelerator keys used to close ShellSurfaces. |
| 51 const struct Accelerator { | 55 const struct Accelerator { |
| 52 ui::KeyboardCode keycode; | 56 ui::KeyboardCode keycode; |
| 53 int modifiers; | 57 int modifiers; |
| 54 } kCloseWindowAccelerators[] = { | 58 } kCloseWindowAccelerators[] = { |
| 55 {ui::VKEY_W, ui::EF_CONTROL_DOWN}, | 59 {ui::VKEY_W, ui::EF_CONTROL_DOWN}, |
| 56 {ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}, | 60 {ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}, |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 if (GetFocusManager()->ProcessAccelerator(ui::Accelerator(*event))) | 183 if (GetFocusManager()->ProcessAccelerator(ui::Accelerator(*event))) |
| 180 event->StopPropagation(); | 184 event->StopPropagation(); |
| 181 } | 185 } |
| 182 | 186 |
| 183 private: | 187 private: |
| 184 ShellSurface* const shell_surface_; | 188 ShellSurface* const shell_surface_; |
| 185 | 189 |
| 186 DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWidget); | 190 DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWidget); |
| 187 }; | 191 }; |
| 188 | 192 |
| 193 class ShadowUnderlayEventHandler : public ui::EventHandler { |
| 194 public: |
| 195 ShadowUnderlayEventHandler() {} |
| 196 ~ShadowUnderlayEventHandler() override {} |
| 197 |
| 198 // Overridden from ui::EventHandler: |
| 199 void OnEvent(ui::Event* event) override { |
| 200 // If the event is targeted at the underlay, it means the user has made an |
| 201 // interaction that is outside the surface's bounds and we want to capture |
| 202 // it (usually when in spoken feedback mode). Handle the event (to prevent |
| 203 // behind-windows from receiving it) and play an earcon to notify the user. |
| 204 if (event->IsLocatedEvent()) { |
| 205 #if defined(OS_CHROMEOS) |
| 206 const ui::EventType kEarconEventTypes[] = {ui::ET_MOUSE_PRESSED, |
| 207 ui::ET_MOUSEWHEEL, |
| 208 ui::ET_TOUCH_PRESSED, |
| 209 ui::ET_POINTER_DOWN, |
| 210 ui::ET_POINTER_WHEEL_CHANGED, |
| 211 ui::ET_GESTURE_BEGIN, |
| 212 ui::ET_SCROLL, |
| 213 ui::ET_SCROLL_FLING_START}; |
| 214 bool is_earcon_event_type = |
| 215 std::find(std::begin(kEarconEventTypes), std::end(kEarconEventTypes), |
| 216 event->type()) != std::end(kEarconEventTypes); |
| 217 if (is_earcon_event_type) |
| 218 WMHelper::GetInstance()->PlayEarcon(chromeos::SOUND_VOLUME_ADJUST); |
| 219 #endif |
| 220 event->SetHandled(); |
| 221 } |
| 222 } |
| 223 |
| 224 private: |
| 225 DISALLOW_COPY_AND_ASSIGN(ShadowUnderlayEventHandler); |
| 226 }; |
| 227 |
| 189 } // namespace | 228 } // namespace |
| 190 | 229 |
| 191 // Helper class used to coalesce a number of changes into one "configure" | 230 // Helper class used to coalesce a number of changes into one "configure" |
| 192 // callback. Callbacks are suppressed while an instance of this class is | 231 // callback. Callbacks are suppressed while an instance of this class is |
| 193 // instantiated and instead called when the instance is destroyed. | 232 // instantiated and instead called when the instance is destroyed. |
| 194 // If |force_configure_| is true ShellSurface::Configure() will be called | 233 // If |force_configure_| is true ShellSurface::Configure() will be called |
| 195 // even if no changes to shell surface took place during the lifetime of the | 234 // even if no changes to shell surface took place during the lifetime of the |
| 196 // ScopedConfigure instance. | 235 // ScopedConfigure instance. |
| 197 class ShellSurface::ScopedConfigure { | 236 class ShellSurface::ScopedConfigure { |
| 198 public: | 237 public: |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 WMHelper::GetInstance()->RemoveActivationObserver(this); | 366 WMHelper::GetInstance()->RemoveActivationObserver(this); |
| 328 WMHelper::GetInstance()->RemoveDisplayConfigurationObserver(this); | 367 WMHelper::GetInstance()->RemoveDisplayConfigurationObserver(this); |
| 329 if (parent_) | 368 if (parent_) |
| 330 parent_->RemoveObserver(this); | 369 parent_->RemoveObserver(this); |
| 331 if (surface_) { | 370 if (surface_) { |
| 332 if (scale_ != 1.0) | 371 if (scale_ != 1.0) |
| 333 surface_->window()->SetTransform(gfx::Transform()); | 372 surface_->window()->SetTransform(gfx::Transform()); |
| 334 surface_->SetSurfaceDelegate(nullptr); | 373 surface_->SetSurfaceDelegate(nullptr); |
| 335 surface_->RemoveSurfaceObserver(this); | 374 surface_->RemoveSurfaceObserver(this); |
| 336 } | 375 } |
| 376 WMHelper::GetInstance()->RemoveAccessibilityObserver(this); |
| 337 } | 377 } |
| 338 | 378 |
| 339 void ShellSurface::AcknowledgeConfigure(uint32_t serial) { | 379 void ShellSurface::AcknowledgeConfigure(uint32_t serial) { |
| 340 TRACE_EVENT1("exo", "ShellSurface::AcknowledgeConfigure", "serial", serial); | 380 TRACE_EVENT1("exo", "ShellSurface::AcknowledgeConfigure", "serial", serial); |
| 341 | 381 |
| 342 // Apply all configs that are older or equal to |serial|. The result is that | 382 // Apply all configs that are older or equal to |serial|. The result is that |
| 343 // the origin of the main surface will move and the resize direction will | 383 // the origin of the main surface will move and the resize direction will |
| 344 // change to reflect the acknowledgement of configure request with |serial| | 384 // change to reflect the acknowledgement of configure request with |serial| |
| 345 // at the next call to Commit(). | 385 // at the next call to Commit(). |
| 346 while (!pending_configs_.empty()) { | 386 while (!pending_configs_.empty()) { |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 | 1032 |
| 993 if (gained_active == widget_->GetNativeWindow() || | 1033 if (gained_active == widget_->GetNativeWindow() || |
| 994 lost_active == widget_->GetNativeWindow()) { | 1034 lost_active == widget_->GetNativeWindow()) { |
| 995 DCHECK(activatable_); | 1035 DCHECK(activatable_); |
| 996 Configure(); | 1036 Configure(); |
| 997 UpdateShadow(); | 1037 UpdateShadow(); |
| 998 } | 1038 } |
| 999 } | 1039 } |
| 1000 | 1040 |
| 1001 //////////////////////////////////////////////////////////////////////////////// | 1041 //////////////////////////////////////////////////////////////////////////////// |
| 1042 // WMHelper::AccessibilityObserver overrides: |
| 1043 |
| 1044 void ShellSurface::OnAccessibilityModeChanged() { |
| 1045 UpdateShadow(); |
| 1046 } |
| 1047 |
| 1048 //////////////////////////////////////////////////////////////////////////////// |
| 1002 // WMHelper::DisplayConfigurationObserver overrides: | 1049 // WMHelper::DisplayConfigurationObserver overrides: |
| 1003 | 1050 |
| 1004 void ShellSurface::OnDisplayConfigurationChanged() { | 1051 void ShellSurface::OnDisplayConfigurationChanged() { |
| 1005 if (bounds_mode_ != BoundsMode::CLIENT) | 1052 if (bounds_mode_ != BoundsMode::CLIENT) |
| 1006 return; | 1053 return; |
| 1007 | 1054 |
| 1008 const display::Screen* screen = display::Screen::GetScreen(); | 1055 const display::Screen* screen = display::Screen::GetScreen(); |
| 1009 int64_t primary_display_id = screen->GetPrimaryDisplay().id(); | 1056 int64_t primary_display_id = screen->GetPrimaryDisplay().id(); |
| 1010 if (primary_display_id == primary_display_id_) | 1057 if (primary_display_id == primary_display_id_) |
| 1011 return; | 1058 return; |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1186 } | 1233 } |
| 1187 | 1234 |
| 1188 // Register close window accelerators. | 1235 // Register close window accelerators. |
| 1189 views::FocusManager* focus_manager = widget_->GetFocusManager(); | 1236 views::FocusManager* focus_manager = widget_->GetFocusManager(); |
| 1190 for (const auto& entry : kCloseWindowAccelerators) { | 1237 for (const auto& entry : kCloseWindowAccelerators) { |
| 1191 focus_manager->RegisterAccelerator( | 1238 focus_manager->RegisterAccelerator( |
| 1192 ui::Accelerator(entry.keycode, entry.modifiers), | 1239 ui::Accelerator(entry.keycode, entry.modifiers), |
| 1193 ui::AcceleratorManager::kNormalPriority, this); | 1240 ui::AcceleratorManager::kNormalPriority, this); |
| 1194 } | 1241 } |
| 1195 | 1242 |
| 1243 // Receive accessibility changes to update shadow underlay. |
| 1244 WMHelper::GetInstance()->AddAccessibilityObserver(this); |
| 1245 |
| 1196 // Show widget next time Commit() is called. | 1246 // Show widget next time Commit() is called. |
| 1197 pending_show_widget_ = true; | 1247 pending_show_widget_ = true; |
| 1198 } | 1248 } |
| 1199 | 1249 |
| 1200 void ShellSurface::Configure() { | 1250 void ShellSurface::Configure() { |
| 1201 // Delay configure callback if |scoped_configure_| is set. | 1251 // Delay configure callback if |scoped_configure_| is set. |
| 1202 if (scoped_configure_) { | 1252 if (scoped_configure_) { |
| 1203 scoped_configure_->set_needs_configure(); | 1253 scoped_configure_->set_needs_configure(); |
| 1204 return; | 1254 return; |
| 1205 } | 1255 } |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1524 if (!widget_ || !surface_) | 1574 if (!widget_ || !surface_) |
| 1525 return; | 1575 return; |
| 1526 if (shadow_underlay_in_surface_ != pending_shadow_underlay_in_surface_) { | 1576 if (shadow_underlay_in_surface_ != pending_shadow_underlay_in_surface_) { |
| 1527 shadow_underlay_in_surface_ = pending_shadow_underlay_in_surface_; | 1577 shadow_underlay_in_surface_ = pending_shadow_underlay_in_surface_; |
| 1528 shadow_overlay_.reset(); | 1578 shadow_overlay_.reset(); |
| 1529 shadow_underlay_.reset(); | 1579 shadow_underlay_.reset(); |
| 1530 } | 1580 } |
| 1531 | 1581 |
| 1532 aura::Window* window = widget_->GetNativeWindow(); | 1582 aura::Window* window = widget_->GetNativeWindow(); |
| 1533 | 1583 |
| 1534 // Enable the black backdrop layer behind the window if the window | 1584 bool underlay_capture_events = |
| 1535 // is in immersive fullscreen, maximized, yet the window can control | 1585 WMHelper::GetInstance()->IsSpokenFeedbackEnabled() && widget_->IsActive(); |
| 1536 // the bounds of the window in fullscreen/maximize mode (thus the | 1586 bool black_background_enabled = |
| 1537 // background can be visible). | 1587 ((widget_->IsFullscreen() || widget_->IsMaximized()) || |
| 1538 bool enable_backdrop = | 1588 underlay_capture_events) && |
| 1539 (widget_->IsFullscreen() || widget_->IsMaximized()) && | 1589 ash::wm::GetWindowState(window)->allow_set_bounds_direct() && |
| 1540 ash::wm::GetWindowState(window)->allow_set_bounds_direct(); | 1590 window->layer()->GetTargetTransform().IsIdentity(); |
| 1541 if (window->GetProperty(aura::client::kHasBackdrop) != enable_backdrop) | |
| 1542 window->SetProperty(aura::client::kHasBackdrop, enable_backdrop); | |
| 1543 | 1591 |
| 1544 if (!shadow_enabled_) { | 1592 if (!shadow_enabled_ && !black_background_enabled) { |
| 1545 wm::SetShadowElevation(window, wm::ShadowElevation::NONE); | 1593 wm::SetShadowElevation(window, wm::ShadowElevation::NONE); |
| 1546 if (shadow_underlay_) | 1594 if (shadow_underlay_) |
| 1547 shadow_underlay_->Hide(); | 1595 shadow_underlay_->Hide(); |
| 1548 } else { | 1596 } else { |
| 1549 wm::SetShadowElevation(window, wm::ShadowElevation::DEFAULT); | 1597 wm::SetShadowElevation(window, wm::ShadowElevation::DEFAULT); |
| 1550 gfx::Rect shadow_content_bounds = | 1598 gfx::Rect shadow_content_bounds = |
| 1551 gfx::ScaleToEnclosedRect(shadow_content_bounds_, 1.f / scale_); | 1599 gfx::ScaleToEnclosedRect(shadow_content_bounds_, 1.f / scale_); |
| 1552 | 1600 |
| 1553 // Convert from screen to display coordinates. | 1601 // Convert from screen to display coordinates. |
| 1554 if (!shadow_content_bounds.IsEmpty()) { | 1602 if (!shadow_content_bounds.IsEmpty()) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1583 } | 1631 } |
| 1584 | 1632 |
| 1585 gfx::Point shadow_origin = shadow_content_bounds.origin(); | 1633 gfx::Point shadow_origin = shadow_content_bounds.origin(); |
| 1586 shadow_origin -= window->bounds().OffsetFromOrigin(); | 1634 shadow_origin -= window->bounds().OffsetFromOrigin(); |
| 1587 gfx::Rect shadow_bounds(shadow_origin, shadow_content_bounds.size()); | 1635 gfx::Rect shadow_bounds(shadow_origin, shadow_content_bounds.size()); |
| 1588 | 1636 |
| 1589 // Always create and show the underlay, even in maximized/fullscreen. | 1637 // Always create and show the underlay, even in maximized/fullscreen. |
| 1590 if (!shadow_underlay_) { | 1638 if (!shadow_underlay_) { |
| 1591 shadow_underlay_ = base::MakeUnique<aura::Window>(nullptr); | 1639 shadow_underlay_ = base::MakeUnique<aura::Window>(nullptr); |
| 1592 shadow_underlay_->set_owned_by_parent(false); | 1640 shadow_underlay_->set_owned_by_parent(false); |
| 1641 shadow_underlay_event_handler_ = |
| 1642 base::MakeUnique<ShadowUnderlayEventHandler>(); |
| 1643 shadow_underlay_->SetTargetHandler(shadow_underlay_event_handler_.get()); |
| 1593 DCHECK(!shadow_underlay_->owned_by_parent()); | 1644 DCHECK(!shadow_underlay_->owned_by_parent()); |
| 1594 // Ensure the background area inside the shadow is solid black. | 1645 // Ensure the background area inside the shadow is solid black. |
| 1595 // Clients that provide translucent contents should not be using | 1646 // Clients that provide translucent contents should not be using |
| 1596 // rectangular shadows as this method requires opaque contents to | 1647 // rectangular shadows as this method requires opaque contents to |
| 1597 // cast a shadow that represent it correctly. | 1648 // cast a shadow that represent it correctly. |
| 1598 shadow_underlay_->Init(ui::LAYER_SOLID_COLOR); | 1649 shadow_underlay_->Init(ui::LAYER_SOLID_COLOR); |
| 1599 shadow_underlay_->layer()->SetColor(SK_ColorBLACK); | 1650 shadow_underlay_->layer()->SetColor(SK_ColorBLACK); |
| 1600 DCHECK(shadow_underlay_->layer()->fills_bounds_opaquely()); | 1651 DCHECK(shadow_underlay_->layer()->fills_bounds_opaquely()); |
| 1601 if (shadow_underlay_in_surface_) { | 1652 if (shadow_underlay_in_surface_) { |
| 1602 surface_->window()->AddChild(shadow_underlay()); | 1653 surface_->window()->AddChild(shadow_underlay()); |
| 1603 surface_->window()->StackChildAtBottom(shadow_underlay()); | 1654 surface_->window()->StackChildAtBottom(shadow_underlay()); |
| 1604 } else { | 1655 } else { |
| 1605 window->AddChild(shadow_underlay()); | 1656 window->AddChild(shadow_underlay()); |
| 1606 window->StackChildAtBottom(shadow_underlay()); | 1657 window->StackChildAtBottom(shadow_underlay()); |
| 1607 } | 1658 } |
| 1608 } | 1659 } |
| 1609 | 1660 |
| 1610 float shadow_underlay_opacity = shadow_background_opacity_; | 1661 float shadow_underlay_opacity = shadow_background_opacity_; |
| 1611 | 1662 |
| 1663 // Put the black background layer behind the window if |
| 1664 // 1) the window is in immersive fullscreen, maximized or is active with |
| 1665 // spoken feedback enabled. |
| 1666 // 2) the window can control the bounds of the window in fullscreen ( |
| 1667 // thus the background can be visible). |
| 1668 // 3) the window has no transform (the transformed background may |
| 1669 // not cover the entire background, e.g. overview mode). |
| 1670 if (black_background_enabled) { |
| 1671 if (shadow_underlay_in_surface_) { |
| 1672 shadow_underlay_bounds = gfx::Rect(surface_->window()->bounds().size()); |
| 1673 } else { |
| 1674 gfx::Point origin; |
| 1675 origin -= window->bounds().origin().OffsetFromOrigin(); |
| 1676 shadow_bounds.set_origin(origin); |
| 1677 shadow_bounds.set_size(window->parent()->bounds().size()); |
| 1678 } |
| 1679 shadow_underlay_opacity = 1.0f; |
| 1680 } |
| 1681 |
| 1612 if (!shadow_underlay_in_surface_) | 1682 if (!shadow_underlay_in_surface_) |
| 1613 shadow_underlay_bounds = shadow_bounds; | 1683 shadow_underlay_bounds = shadow_bounds; |
| 1614 | 1684 |
| 1615 // Constrain the underlay bounds to the client area in case shell surface | 1685 // Constrain the underlay bounds to the client area in case shell surface |
| 1616 // frame is enabled. | 1686 // frame is enabled. |
| 1617 if (frame_enabled_) { | 1687 if (frame_enabled_) { |
| 1618 shadow_underlay_bounds.Intersect( | 1688 shadow_underlay_bounds.Intersect( |
| 1619 widget_->non_client_view()->frame_view()->GetBoundsForClientView()); | 1689 widget_->non_client_view()->frame_view()->GetBoundsForClientView()); |
| 1620 } | 1690 } |
| 1621 | 1691 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1667 gfx::Point ShellSurface::GetMouseLocation() const { | 1737 gfx::Point ShellSurface::GetMouseLocation() const { |
| 1668 aura::Window* const root_window = widget_->GetNativeWindow()->GetRootWindow(); | 1738 aura::Window* const root_window = widget_->GetNativeWindow()->GetRootWindow(); |
| 1669 gfx::Point location = | 1739 gfx::Point location = |
| 1670 root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot(); | 1740 root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot(); |
| 1671 aura::Window::ConvertPointToTarget( | 1741 aura::Window::ConvertPointToTarget( |
| 1672 root_window, widget_->GetNativeWindow()->parent(), &location); | 1742 root_window, widget_->GetNativeWindow()->parent(), &location); |
| 1673 return location; | 1743 return location; |
| 1674 } | 1744 } |
| 1675 | 1745 |
| 1676 } // namespace exo | 1746 } // namespace exo |
| OLD | NEW |