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