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

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

Issue 1819273002: exo: Improved implementation of child surfaces and popups. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix deps Created 4 years, 9 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/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
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
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
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
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
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