Index: components/exo/shell_surface.cc |
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc |
index 544eb5a6f66e9058c273285e303a25f675d5f37e..72e30856ddd9db8852af1442d9198b4ea03040ca 100644 |
--- a/components/exo/shell_surface.cc |
+++ b/components/exo/shell_surface.cc |
@@ -19,6 +19,7 @@ |
#include "ui/base/hit_test.h" |
#include "ui/gfx/path.h" |
#include "ui/views/widget/widget.h" |
+#include "ui/wm/core/window_util.h" |
#include "ui/wm/public/activation_client.h" |
DECLARE_WINDOW_PROPERTY_TYPE(std::string*) |
@@ -60,32 +61,20 @@ class CustomWindowTargeter : public aura::WindowTargeter { |
// Overridden from aura::WindowTargeter: |
bool EventLocationInsideBounds(aura::Window* window, |
const ui::LocatedEvent& event) const override { |
- return PointInsideBounds(window, event.location()); |
- } |
- |
- private: |
- bool PointInsideBounds(const aura::Window* window, |
- const gfx::Point& point) const { |
Surface* surface = ShellSurface::GetMainSurface(window); |
if (!surface) |
return false; |
- gfx::Point local_point = point; |
- if (window->parent()) { |
+ gfx::Point local_point = event.location(); |
+ if (window->parent()) |
aura::Window::ConvertPointToTarget(window->parent(), window, |
&local_point); |
- } |
- |
- // If point is inside a child window then it's also inside the parent. |
- for (const aura::Window* child : window->children()) { |
- if (PointInsideBounds(child, local_point)) |
- return true; |
- } |
aura::Window::ConvertPointToTarget(window, surface, &local_point); |
return surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1))); |
} |
+ private: |
DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter); |
}; |
@@ -113,10 +102,13 @@ DEFINE_LOCAL_WINDOW_PROPERTY_KEY(Surface*, kMainSurfaceKey, nullptr) |
ShellSurface::ShellSurface(Surface* surface, |
ShellSurface* parent, |
- const gfx::Rect& initial_bounds) |
- : surface_(surface), |
+ const gfx::Rect& initial_bounds, |
+ bool activatable) |
+ : widget_(nullptr), |
+ surface_(surface), |
parent_(parent ? parent->GetWidget()->GetNativeWindow() : nullptr), |
- initial_bounds_(initial_bounds) { |
+ initial_bounds_(initial_bounds), |
+ activatable_(activatable) { |
ash::Shell::GetInstance()->activation_client()->AddObserver(this); |
surface_->SetSurfaceDelegate(this); |
surface_->AddSurfaceObserver(this); |
@@ -127,7 +119,7 @@ ShellSurface::ShellSurface(Surface* surface, |
} |
ShellSurface::ShellSurface(Surface* surface) |
- : ShellSurface(surface, nullptr, gfx::Rect()) {} |
+ : ShellSurface(surface, nullptr, gfx::Rect(), true) {} |
ShellSurface::~ShellSurface() { |
ash::Shell::GetInstance()->activation_client()->RemoveObserver(this); |
@@ -149,11 +141,17 @@ void ShellSurface::SetParent(ShellSurface* parent) { |
TRACE_EVENT1("exo", "ShellSurface::SetParent", "parent", |
parent ? base::UTF16ToASCII(parent->title_) : "null"); |
- if (parent_) |
+ if (parent_) { |
parent_->RemoveObserver(this); |
+ if (widget_) |
+ wm::RemoveTransientChild(parent_, widget_->GetNativeWindow()); |
+ } |
parent_ = parent ? parent->GetWidget()->GetNativeWindow() : nullptr; |
- if (parent_) |
+ if (parent_) { |
parent_->AddObserver(this); |
+ if (widget_) |
+ wm::AddTransientChild(parent_, widget_->GetNativeWindow()); |
+ } |
} |
void ShellSurface::Maximize() { |
@@ -284,14 +282,11 @@ void ShellSurface::OnSurfaceCommit() { |
if (widget_) { |
// Update surface bounds and widget size. |
- gfx::Point origin; |
- views::View::ConvertPointToWidget(this, &origin); |
- // Use |geometry_| if set, otherwise use the visual bounds of the surface. |
- gfx::Rect geometry = |
- geometry_.IsEmpty() ? surface_->GetVisibleBounds() : geometry_; |
- surface_->SetBounds(gfx::Rect(origin - geometry.OffsetFromOrigin(), |
- surface_->layer()->size())); |
- widget_->SetSize(geometry.size()); |
+ gfx::Rect visible_bounds = GetVisibleBounds(); |
+ surface_->SetBounds( |
+ gfx::Rect(gfx::Point() - visible_bounds.OffsetFromOrigin(), |
+ surface_->layer()->size())); |
+ widget_->SetSize(visible_bounds.size()); |
// Show widget if not already visible. |
if (!widget_->IsClosed() && !widget_->IsVisible()) |
@@ -332,12 +327,17 @@ base::string16 ShellSurface::GetWindowTitle() const { |
return title_; |
} |
+void ShellSurface::WindowClosing() { |
+ SetEnabled(false); |
+ widget_ = nullptr; |
+} |
+ |
views::Widget* ShellSurface::GetWidget() { |
- return widget_.get(); |
+ return widget_; |
} |
const views::Widget* ShellSurface::GetWidget() const { |
- return widget_.get(); |
+ return widget_; |
} |
views::View* ShellSurface::GetContentsView() { |
@@ -403,6 +403,8 @@ void ShellSurface::OnWindowActivated( |
aura::client::ActivationChangeObserver::ActivationReason reason, |
aura::Window* gained_active, |
aura::Window* lost_active) { |
+ DCHECK(activatable_); |
+ |
if (!widget_) |
return; |
@@ -421,26 +423,28 @@ void ShellSurface::CreateShellSurfaceWidget() { |
views::Widget::InitParams params; |
params.type = views::Widget::InitParams::TYPE_WINDOW; |
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET; |
params.delegate = this; |
params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE; |
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
params.show_state = ui::SHOW_STATE_NORMAL; |
- gfx::Point position(initial_bounds_.origin()); |
- if (parent_) { |
- params.child = true; |
- params.parent = parent_; |
- aura::Window::ConvertPointToTarget(GetMainSurface(parent_), parent_, |
- &position); |
- } else { |
- params.parent = |
- ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(), |
- ash::kShellWindowId_DefaultContainer); |
+ params.parent = ash::Shell::GetContainer( |
+ ash::Shell::GetPrimaryRootWindow(), ash::kShellWindowId_DefaultContainer); |
+ if (!initial_bounds_.IsEmpty()) { |
+ gfx::Point position(initial_bounds_.origin()); |
+ if (parent_) { |
+ aura::Window::ConvertPointToTarget(GetMainSurface(parent_), params.parent, |
+ &position); |
+ } |
+ params.bounds = gfx::Rect(position + GetVisibleBounds().OffsetFromOrigin(), |
+ initial_bounds_.size()); |
} |
- params.bounds = gfx::Rect(position, initial_bounds_.size()); |
- widget_.reset(new ShellSurfaceWidget(this)); |
+ params.activatable = activatable_ ? views::Widget::InitParams::ACTIVATABLE_YES |
+ : views::Widget::InitParams::ACTIVATABLE_NO; |
+ |
+ // Note: NativeWidget owns this widget. |
+ widget_ = new ShellSurfaceWidget(this); |
widget_->Init(params); |
- widget_->GetNativeWindow()->set_owned_by_parent(false); |
widget_->GetNativeWindow()->SetName("ExoShellSurface"); |
widget_->GetNativeWindow()->AddChild(surface_); |
widget_->GetNativeWindow()->SetEventTargeter( |
@@ -451,9 +455,16 @@ void ShellSurface::CreateShellSurfaceWidget() { |
// Start tracking window state changes. |
ash::wm::GetWindowState(widget_->GetNativeWindow())->AddObserver(this); |
- // The position of a top-level shell surface is managed by Ash. |
- ash::wm::GetWindowState(widget_->GetNativeWindow()) |
- ->set_window_position_managed(true); |
+ // Make shell surface a transient child if |parent_| has been set. |
+ if (parent_) |
+ wm::AddTransientChild(parent_, widget_->GetNativeWindow()); |
+ |
+ // Ash manages the position of a top-level shell surfaces unless |
+ // |initial_bounds_| has been set. |
+ if (initial_bounds_.IsEmpty()) { |
+ ash::wm::GetWindowState(widget_->GetNativeWindow()) |
+ ->set_window_position_managed(true); |
+ } |
} |
void ShellSurface::Configure() { |
@@ -468,4 +479,9 @@ void ShellSurface::Configure() { |
widget_->IsActive()); |
} |
+gfx::Rect ShellSurface::GetVisibleBounds() const { |
+ // Use |geometry_| if set, otherwise use the visual bounds of the surface. |
+ return geometry_.IsEmpty() ? surface_->GetVisibleBounds() : geometry_; |
+} |
+ |
} // namespace exo |