| 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 "ash/shell.h" | 7 #include "ash/shell.h" |
| 8 #include "ash/shell_window_ids.h" | 8 #include "ash/shell_window_ids.h" |
| 9 #include "ash/wm/window_state.h" | 9 #include "ash/wm/window_state.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/trace_event/trace_event.h" | 13 #include "base/trace_event/trace_event.h" |
| 14 #include "base/trace_event/trace_event_argument.h" | 14 #include "base/trace_event/trace_event_argument.h" |
| 15 #include "components/exo/surface.h" | 15 #include "components/exo/surface.h" |
| 16 #include "ui/aura/window.h" | 16 #include "ui/aura/window.h" |
| 17 #include "ui/aura/window_property.h" | 17 #include "ui/aura/window_property.h" |
| 18 #include "ui/aura/window_targeter.h" | 18 #include "ui/aura/window_targeter.h" |
| 19 #include "ui/base/hit_test.h" | 19 #include "ui/base/hit_test.h" |
| 20 #include "ui/gfx/path.h" | 20 #include "ui/gfx/path.h" |
| 21 #include "ui/views/widget/widget.h" | 21 #include "ui/views/widget/widget.h" |
| 22 #include "ui/wm/core/window_util.h" |
| 22 #include "ui/wm/public/activation_client.h" | 23 #include "ui/wm/public/activation_client.h" |
| 23 | 24 |
| 24 DECLARE_WINDOW_PROPERTY_TYPE(std::string*) | 25 DECLARE_WINDOW_PROPERTY_TYPE(std::string*) |
| 25 | 26 |
| 26 namespace exo { | 27 namespace exo { |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 29 class CustomFrameView : public views::NonClientFrameView { | 30 class CustomFrameView : public views::NonClientFrameView { |
| 30 public: | 31 public: |
| 31 explicit CustomFrameView(views::Widget* widget) : widget_(widget) {} | 32 explicit CustomFrameView(views::Widget* widget) : widget_(widget) {} |
| (...skipping 21 matching lines...) Expand all Loading... |
| 53 }; | 54 }; |
| 54 | 55 |
| 55 class CustomWindowTargeter : public aura::WindowTargeter { | 56 class CustomWindowTargeter : public aura::WindowTargeter { |
| 56 public: | 57 public: |
| 57 CustomWindowTargeter() {} | 58 CustomWindowTargeter() {} |
| 58 ~CustomWindowTargeter() override {} | 59 ~CustomWindowTargeter() override {} |
| 59 | 60 |
| 60 // Overridden from aura::WindowTargeter: | 61 // Overridden from aura::WindowTargeter: |
| 61 bool EventLocationInsideBounds(aura::Window* window, | 62 bool EventLocationInsideBounds(aura::Window* window, |
| 62 const ui::LocatedEvent& event) const override { | 63 const ui::LocatedEvent& event) const override { |
| 63 return PointInsideBounds(window, event.location()); | |
| 64 } | |
| 65 | |
| 66 private: | |
| 67 bool PointInsideBounds(const aura::Window* window, | |
| 68 const gfx::Point& point) const { | |
| 69 Surface* surface = ShellSurface::GetMainSurface(window); | 64 Surface* surface = ShellSurface::GetMainSurface(window); |
| 70 if (!surface) | 65 if (!surface) |
| 71 return false; | 66 return false; |
| 72 | 67 |
| 73 gfx::Point local_point = point; | 68 gfx::Point local_point = event.location(); |
| 74 if (window->parent()) { | 69 if (window->parent()) |
| 75 aura::Window::ConvertPointToTarget(window->parent(), window, | 70 aura::Window::ConvertPointToTarget(window->parent(), window, |
| 76 &local_point); | 71 &local_point); |
| 77 } | |
| 78 | |
| 79 // If point is inside a child window then it's also inside the parent. | |
| 80 for (const aura::Window* child : window->children()) { | |
| 81 if (PointInsideBounds(child, local_point)) | |
| 82 return true; | |
| 83 } | |
| 84 | 72 |
| 85 aura::Window::ConvertPointToTarget(window, surface, &local_point); | 73 aura::Window::ConvertPointToTarget(window, surface, &local_point); |
| 86 return surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1))); | 74 return surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1))); |
| 87 } | 75 } |
| 88 | 76 |
| 77 private: |
| 89 DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter); | 78 DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter); |
| 90 }; | 79 }; |
| 91 | 80 |
| 92 class ShellSurfaceWidget : public views::Widget { | 81 class ShellSurfaceWidget : public views::Widget { |
| 93 public: | 82 public: |
| 94 explicit ShellSurfaceWidget(ShellSurface* shell_surface) | 83 explicit ShellSurfaceWidget(ShellSurface* shell_surface) |
| 95 : shell_surface_(shell_surface) {} | 84 : shell_surface_(shell_surface) {} |
| 96 | 85 |
| 97 // Overridden from views::Widget | 86 // Overridden from views::Widget |
| 98 void Close() override { shell_surface_->Close(); } | 87 void Close() override { shell_surface_->Close(); } |
| 99 | 88 |
| 100 private: | 89 private: |
| 101 ShellSurface* const shell_surface_; | 90 ShellSurface* const shell_surface_; |
| 102 | 91 |
| 103 DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWidget); | 92 DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWidget); |
| 104 }; | 93 }; |
| 105 | 94 |
| 106 } // namespace | 95 } // namespace |
| 107 | 96 |
| 108 //////////////////////////////////////////////////////////////////////////////// | 97 //////////////////////////////////////////////////////////////////////////////// |
| 109 // ShellSurface, public: | 98 // ShellSurface, public: |
| 110 | 99 |
| 111 DEFINE_LOCAL_WINDOW_PROPERTY_KEY(std::string*, kApplicationIdKey, nullptr) | 100 DEFINE_LOCAL_WINDOW_PROPERTY_KEY(std::string*, kApplicationIdKey, nullptr) |
| 112 DEFINE_LOCAL_WINDOW_PROPERTY_KEY(Surface*, kMainSurfaceKey, nullptr) | 101 DEFINE_LOCAL_WINDOW_PROPERTY_KEY(Surface*, kMainSurfaceKey, nullptr) |
| 113 | 102 |
| 114 ShellSurface::ShellSurface(Surface* surface, | 103 ShellSurface::ShellSurface(Surface* surface, |
| 115 ShellSurface* parent, | 104 ShellSurface* parent, |
| 116 const gfx::Rect& initial_bounds) | 105 const gfx::Rect& initial_bounds, |
| 117 : surface_(surface), | 106 bool activatable) |
| 107 : widget_(nullptr), |
| 108 surface_(surface), |
| 118 parent_(parent ? parent->GetWidget()->GetNativeWindow() : nullptr), | 109 parent_(parent ? parent->GetWidget()->GetNativeWindow() : nullptr), |
| 119 initial_bounds_(initial_bounds) { | 110 initial_bounds_(initial_bounds), |
| 111 activatable_(activatable) { |
| 120 ash::Shell::GetInstance()->activation_client()->AddObserver(this); | 112 ash::Shell::GetInstance()->activation_client()->AddObserver(this); |
| 121 surface_->SetSurfaceDelegate(this); | 113 surface_->SetSurfaceDelegate(this); |
| 122 surface_->AddSurfaceObserver(this); | 114 surface_->AddSurfaceObserver(this); |
| 123 surface_->Show(); | 115 surface_->Show(); |
| 124 set_owned_by_client(); | 116 set_owned_by_client(); |
| 125 if (parent_) | 117 if (parent_) |
| 126 parent_->AddObserver(this); | 118 parent_->AddObserver(this); |
| 127 } | 119 } |
| 128 | 120 |
| 129 ShellSurface::ShellSurface(Surface* surface) | 121 ShellSurface::ShellSurface(Surface* surface) |
| 130 : ShellSurface(surface, nullptr, gfx::Rect()) {} | 122 : ShellSurface(surface, nullptr, gfx::Rect(), true) {} |
| 131 | 123 |
| 132 ShellSurface::~ShellSurface() { | 124 ShellSurface::~ShellSurface() { |
| 133 ash::Shell::GetInstance()->activation_client()->RemoveObserver(this); | 125 ash::Shell::GetInstance()->activation_client()->RemoveObserver(this); |
| 134 if (surface_) { | 126 if (surface_) { |
| 135 surface_->SetSurfaceDelegate(nullptr); | 127 surface_->SetSurfaceDelegate(nullptr); |
| 136 surface_->RemoveSurfaceObserver(this); | 128 surface_->RemoveSurfaceObserver(this); |
| 137 } | 129 } |
| 138 if (parent_) | 130 if (parent_) |
| 139 parent_->RemoveObserver(this); | 131 parent_->RemoveObserver(this); |
| 140 if (widget_) { | 132 if (widget_) { |
| 141 ash::wm::GetWindowState(widget_->GetNativeWindow())->RemoveObserver(this); | 133 ash::wm::GetWindowState(widget_->GetNativeWindow())->RemoveObserver(this); |
| 142 if (widget_->IsVisible()) | 134 if (widget_->IsVisible()) |
| 143 widget_->Hide(); | 135 widget_->Hide(); |
| 144 widget_->CloseNow(); | 136 widget_->CloseNow(); |
| 145 } | 137 } |
| 146 } | 138 } |
| 147 | 139 |
| 148 void ShellSurface::SetParent(ShellSurface* parent) { | 140 void ShellSurface::SetParent(ShellSurface* parent) { |
| 149 TRACE_EVENT1("exo", "ShellSurface::SetParent", "parent", | 141 TRACE_EVENT1("exo", "ShellSurface::SetParent", "parent", |
| 150 parent ? base::UTF16ToASCII(parent->title_) : "null"); | 142 parent ? base::UTF16ToASCII(parent->title_) : "null"); |
| 151 | 143 |
| 152 if (parent_) | 144 if (parent_) { |
| 153 parent_->RemoveObserver(this); | 145 parent_->RemoveObserver(this); |
| 146 if (widget_) |
| 147 wm::RemoveTransientChild(parent_, widget_->GetNativeWindow()); |
| 148 } |
| 154 parent_ = parent ? parent->GetWidget()->GetNativeWindow() : nullptr; | 149 parent_ = parent ? parent->GetWidget()->GetNativeWindow() : nullptr; |
| 155 if (parent_) | 150 if (parent_) { |
| 156 parent_->AddObserver(this); | 151 parent_->AddObserver(this); |
| 152 if (widget_) |
| 153 wm::AddTransientChild(parent_, widget_->GetNativeWindow()); |
| 154 } |
| 157 } | 155 } |
| 158 | 156 |
| 159 void ShellSurface::Maximize() { | 157 void ShellSurface::Maximize() { |
| 160 TRACE_EVENT0("exo", "ShellSurface::Maximize"); | 158 TRACE_EVENT0("exo", "ShellSurface::Maximize"); |
| 161 | 159 |
| 162 if (!widget_) | 160 if (!widget_) |
| 163 CreateShellSurfaceWidget(); | 161 CreateShellSurfaceWidget(); |
| 164 | 162 |
| 165 // Ask client to configure its surface if already maximized. | 163 // Ask client to configure its surface if already maximized. |
| 166 if (widget_->IsMaximized()) { | 164 if (widget_->IsMaximized()) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 // SurfaceDelegate overrides: | 275 // SurfaceDelegate overrides: |
| 278 | 276 |
| 279 void ShellSurface::OnSurfaceCommit() { | 277 void ShellSurface::OnSurfaceCommit() { |
| 280 surface_->CommitSurfaceHierarchy(); | 278 surface_->CommitSurfaceHierarchy(); |
| 281 | 279 |
| 282 if (enabled() && !widget_) | 280 if (enabled() && !widget_) |
| 283 CreateShellSurfaceWidget(); | 281 CreateShellSurfaceWidget(); |
| 284 | 282 |
| 285 if (widget_) { | 283 if (widget_) { |
| 286 // Update surface bounds and widget size. | 284 // Update surface bounds and widget size. |
| 287 gfx::Point origin; | 285 gfx::Rect visible_bounds = GetVisibleBounds(); |
| 288 views::View::ConvertPointToWidget(this, &origin); | 286 surface_->SetBounds( |
| 289 // Use |geometry_| if set, otherwise use the visual bounds of the surface. | 287 gfx::Rect(gfx::Point() - visible_bounds.OffsetFromOrigin(), |
| 290 gfx::Rect geometry = | 288 surface_->layer()->size())); |
| 291 geometry_.IsEmpty() ? surface_->GetVisibleBounds() : geometry_; | 289 widget_->SetSize(visible_bounds.size()); |
| 292 surface_->SetBounds(gfx::Rect(origin - geometry.OffsetFromOrigin(), | |
| 293 surface_->layer()->size())); | |
| 294 widget_->SetSize(geometry.size()); | |
| 295 | 290 |
| 296 // Show widget if not already visible. | 291 // Show widget if not already visible. |
| 297 if (!widget_->IsClosed() && !widget_->IsVisible()) | 292 if (!widget_->IsClosed() && !widget_->IsVisible()) |
| 298 widget_->Show(); | 293 widget_->Show(); |
| 299 } | 294 } |
| 300 } | 295 } |
| 301 | 296 |
| 302 bool ShellSurface::IsSurfaceSynchronized() const { | 297 bool ShellSurface::IsSurfaceSynchronized() const { |
| 303 // A shell surface is always desynchronized. | 298 // A shell surface is always desynchronized. |
| 304 return false; | 299 return false; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 325 surface_destroyed_callback_.Run(); | 320 surface_destroyed_callback_.Run(); |
| 326 } | 321 } |
| 327 | 322 |
| 328 //////////////////////////////////////////////////////////////////////////////// | 323 //////////////////////////////////////////////////////////////////////////////// |
| 329 // views::WidgetDelegate overrides: | 324 // views::WidgetDelegate overrides: |
| 330 | 325 |
| 331 base::string16 ShellSurface::GetWindowTitle() const { | 326 base::string16 ShellSurface::GetWindowTitle() const { |
| 332 return title_; | 327 return title_; |
| 333 } | 328 } |
| 334 | 329 |
| 330 void ShellSurface::WindowClosing() { |
| 331 SetEnabled(false); |
| 332 widget_ = nullptr; |
| 333 } |
| 334 |
| 335 views::Widget* ShellSurface::GetWidget() { | 335 views::Widget* ShellSurface::GetWidget() { |
| 336 return widget_.get(); | 336 return widget_; |
| 337 } | 337 } |
| 338 | 338 |
| 339 const views::Widget* ShellSurface::GetWidget() const { | 339 const views::Widget* ShellSurface::GetWidget() const { |
| 340 return widget_.get(); | 340 return widget_; |
| 341 } | 341 } |
| 342 | 342 |
| 343 views::View* ShellSurface::GetContentsView() { | 343 views::View* ShellSurface::GetContentsView() { |
| 344 return this; | 344 return this; |
| 345 } | 345 } |
| 346 | 346 |
| 347 views::NonClientFrameView* ShellSurface::CreateNonClientFrameView( | 347 views::NonClientFrameView* ShellSurface::CreateNonClientFrameView( |
| 348 views::Widget* widget) { | 348 views::Widget* widget) { |
| 349 return new CustomFrameView(widget); | 349 return new CustomFrameView(widget); |
| 350 } | 350 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 SetEnabled(false); | 396 SetEnabled(false); |
| 397 } | 397 } |
| 398 | 398 |
| 399 //////////////////////////////////////////////////////////////////////////////// | 399 //////////////////////////////////////////////////////////////////////////////// |
| 400 // aura::client::ActivationChangeObserver overrides: | 400 // aura::client::ActivationChangeObserver overrides: |
| 401 | 401 |
| 402 void ShellSurface::OnWindowActivated( | 402 void ShellSurface::OnWindowActivated( |
| 403 aura::client::ActivationChangeObserver::ActivationReason reason, | 403 aura::client::ActivationChangeObserver::ActivationReason reason, |
| 404 aura::Window* gained_active, | 404 aura::Window* gained_active, |
| 405 aura::Window* lost_active) { | 405 aura::Window* lost_active) { |
| 406 DCHECK(activatable_); |
| 407 |
| 406 if (!widget_) | 408 if (!widget_) |
| 407 return; | 409 return; |
| 408 | 410 |
| 409 if (gained_active == widget_->GetNativeWindow() || | 411 if (gained_active == widget_->GetNativeWindow() || |
| 410 lost_active == widget_->GetNativeWindow()) { | 412 lost_active == widget_->GetNativeWindow()) { |
| 411 Configure(); | 413 Configure(); |
| 412 } | 414 } |
| 413 } | 415 } |
| 414 | 416 |
| 415 //////////////////////////////////////////////////////////////////////////////// | 417 //////////////////////////////////////////////////////////////////////////////// |
| 416 // ShellSurface, private: | 418 // ShellSurface, private: |
| 417 | 419 |
| 418 void ShellSurface::CreateShellSurfaceWidget() { | 420 void ShellSurface::CreateShellSurfaceWidget() { |
| 419 DCHECK(enabled()); | 421 DCHECK(enabled()); |
| 420 DCHECK(!widget_); | 422 DCHECK(!widget_); |
| 421 | 423 |
| 422 views::Widget::InitParams params; | 424 views::Widget::InitParams params; |
| 423 params.type = views::Widget::InitParams::TYPE_WINDOW; | 425 params.type = views::Widget::InitParams::TYPE_WINDOW; |
| 424 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 426 params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET; |
| 425 params.delegate = this; | 427 params.delegate = this; |
| 426 params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE; | 428 params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE; |
| 427 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | 429 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
| 428 params.show_state = ui::SHOW_STATE_NORMAL; | 430 params.show_state = ui::SHOW_STATE_NORMAL; |
| 429 gfx::Point position(initial_bounds_.origin()); | 431 params.parent = ash::Shell::GetContainer( |
| 430 if (parent_) { | 432 ash::Shell::GetPrimaryRootWindow(), ash::kShellWindowId_DefaultContainer); |
| 431 params.child = true; | 433 if (!initial_bounds_.IsEmpty()) { |
| 432 params.parent = parent_; | 434 gfx::Point position(initial_bounds_.origin()); |
| 433 aura::Window::ConvertPointToTarget(GetMainSurface(parent_), parent_, | 435 if (parent_) { |
| 434 &position); | 436 aura::Window::ConvertPointToTarget(GetMainSurface(parent_), params.parent, |
| 435 } else { | 437 &position); |
| 436 params.parent = | 438 } |
| 437 ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(), | 439 params.bounds = gfx::Rect(position + GetVisibleBounds().OffsetFromOrigin(), |
| 438 ash::kShellWindowId_DefaultContainer); | 440 initial_bounds_.size()); |
| 439 } | 441 } |
| 440 params.bounds = gfx::Rect(position, initial_bounds_.size()); | 442 params.activatable = activatable_ ? views::Widget::InitParams::ACTIVATABLE_YES |
| 441 widget_.reset(new ShellSurfaceWidget(this)); | 443 : views::Widget::InitParams::ACTIVATABLE_NO; |
| 444 |
| 445 // Note: NativeWidget owns this widget. |
| 446 widget_ = new ShellSurfaceWidget(this); |
| 442 widget_->Init(params); | 447 widget_->Init(params); |
| 443 widget_->GetNativeWindow()->set_owned_by_parent(false); | |
| 444 widget_->GetNativeWindow()->SetName("ExoShellSurface"); | 448 widget_->GetNativeWindow()->SetName("ExoShellSurface"); |
| 445 widget_->GetNativeWindow()->AddChild(surface_); | 449 widget_->GetNativeWindow()->AddChild(surface_); |
| 446 widget_->GetNativeWindow()->SetEventTargeter( | 450 widget_->GetNativeWindow()->SetEventTargeter( |
| 447 make_scoped_ptr(new CustomWindowTargeter)); | 451 make_scoped_ptr(new CustomWindowTargeter)); |
| 448 SetApplicationId(widget_->GetNativeWindow(), &application_id_); | 452 SetApplicationId(widget_->GetNativeWindow(), &application_id_); |
| 449 SetMainSurface(widget_->GetNativeWindow(), surface_); | 453 SetMainSurface(widget_->GetNativeWindow(), surface_); |
| 450 | 454 |
| 451 // Start tracking window state changes. | 455 // Start tracking window state changes. |
| 452 ash::wm::GetWindowState(widget_->GetNativeWindow())->AddObserver(this); | 456 ash::wm::GetWindowState(widget_->GetNativeWindow())->AddObserver(this); |
| 453 | 457 |
| 454 // The position of a top-level shell surface is managed by Ash. | 458 // Make shell surface a transient child if |parent_| has been set. |
| 455 ash::wm::GetWindowState(widget_->GetNativeWindow()) | 459 if (parent_) |
| 456 ->set_window_position_managed(true); | 460 wm::AddTransientChild(parent_, widget_->GetNativeWindow()); |
| 461 |
| 462 // Ash manages the position of a top-level shell surfaces unless |
| 463 // |initial_bounds_| has been set. |
| 464 if (initial_bounds_.IsEmpty()) { |
| 465 ash::wm::GetWindowState(widget_->GetNativeWindow()) |
| 466 ->set_window_position_managed(true); |
| 467 } |
| 457 } | 468 } |
| 458 | 469 |
| 459 void ShellSurface::Configure() { | 470 void ShellSurface::Configure() { |
| 460 DCHECK(widget_); | 471 DCHECK(widget_); |
| 461 | 472 |
| 462 if (configure_callback_.is_null()) | 473 if (configure_callback_.is_null()) |
| 463 return; | 474 return; |
| 464 | 475 |
| 465 configure_callback_.Run( | 476 configure_callback_.Run( |
| 466 widget_->GetWindowBoundsInScreen().size(), | 477 widget_->GetWindowBoundsInScreen().size(), |
| 467 ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(), | 478 ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(), |
| 468 widget_->IsActive()); | 479 widget_->IsActive()); |
| 469 } | 480 } |
| 470 | 481 |
| 482 gfx::Rect ShellSurface::GetVisibleBounds() const { |
| 483 // Use |geometry_| if set, otherwise use the visual bounds of the surface. |
| 484 return geometry_.IsEmpty() ? surface_->GetVisibleBounds() : geometry_; |
| 485 } |
| 486 |
| 471 } // namespace exo | 487 } // namespace exo |
| OLD | NEW |