Chromium Code Reviews| Index: components/exo/shell_surface.cc |
| diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc |
| index 82f2f5db68fdedaf96c12cd14dc1f7d468b5c088..fbf549201816c4bd5850c4bb626330f5fe47d00f 100644 |
| --- a/components/exo/shell_surface.cc |
| +++ b/components/exo/shell_surface.cc |
| @@ -14,6 +14,7 @@ |
| #include "ash/common/wm_shell.h" |
| #include "ash/common/wm_window.h" |
| #include "ash/public/cpp/shell_window_ids.h" |
| +#include "ash/wm/drag_window_resizer.h" |
|
reveman
2017/02/06 19:49:34
please remove from this patch
Dominik Laskowski
2017/02/08 18:07:40
See comment below.
|
| #include "ash/wm/window_state_aura.h" |
| #include "ash/wm/window_util.h" |
| #include "base/logging.h" |
| @@ -188,6 +189,26 @@ class CustomWindowStateDelegate : public ash::wm::WindowStateDelegate, |
| DISALLOW_COPY_AND_ASSIGN(CustomWindowStateDelegate); |
| }; |
| +class CustomWindowResizer : public ash::WindowResizer { |
|
reveman
2017/02/06 19:49:34
please remove from this patch
Dominik Laskowski
2017/02/08 18:07:40
Dragging and multi-display positioning are interde
|
| + public: |
| + explicit CustomWindowResizer(ash::wm::WindowState* window_state) |
| + : WindowResizer(window_state), shell_(GetTarget()->GetShell()) { |
| + shell_->LockCursor(); |
| + } |
| + |
| + ~CustomWindowResizer() override { shell_->UnlockCursor(); } |
| + |
| + // ash::WindowResizer: |
| + void Drag(const gfx::Point& location, int event_flags) override {} |
| + void CompleteDrag() override {} |
| + void RevertDrag() override {} |
| + |
| + private: |
| + ash::WmShell* const shell_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(CustomWindowResizer); |
| +}; |
| + |
| class ShellSurfaceWidget : public views::Widget { |
| public: |
| explicit ShellSurfaceWidget(ShellSurface* shell_surface) |
| @@ -335,14 +356,16 @@ DEFINE_LOCAL_UI_CLASS_PROPERTY_KEY(Surface*, kMainSurfaceKey, nullptr) |
| ShellSurface::ShellSurface(Surface* surface, |
| ShellSurface* parent, |
| - const gfx::Rect& initial_bounds, |
| + BoundsMode bounds_mode, |
| + const gfx::Point& origin, |
| bool activatable, |
| bool can_minimize, |
| int container) |
| : widget_(nullptr), |
| surface_(surface), |
| parent_(parent ? parent->GetWidget()->GetNativeWindow() : nullptr), |
| - initial_bounds_(initial_bounds), |
| + bounds_mode_(bounds_mode), |
| + origin_(origin), |
| activatable_(activatable), |
| can_minimize_(can_minimize), |
| container_(container) { |
| @@ -358,15 +381,15 @@ ShellSurface::ShellSurface(Surface* surface, |
| ShellSurface::ShellSurface(Surface* surface) |
| : ShellSurface(surface, |
| nullptr, |
| - gfx::Rect(), |
| + BoundsMode::SHELL, |
| + gfx::Point(), |
| true, |
| true, |
| ash::kShellWindowId_DefaultContainer) {} |
| ShellSurface::~ShellSurface() { |
| DCHECK(!scoped_configure_); |
| - if (resizer_) |
| - EndDrag(false /* revert */); |
| + EndDragOrMove(false /* revert */); |
| if (widget_) { |
| ash::wm::GetWindowState(widget_->GetNativeWindow())->RemoveObserver(this); |
| widget_->GetNativeWindow()->RemoveObserver(this); |
| @@ -387,6 +410,9 @@ ShellSurface::~ShellSurface() { |
| surface_->RemoveSurfaceObserver(this); |
| } |
| WMHelper::GetInstance()->RemoveAccessibilityObserver(this); |
| + |
| + if (!destroyed_callback_.is_null()) |
| + destroyed_callback_.Run(); |
| } |
| void ShellSurface::AcknowledgeConfigure(uint32_t serial) { |
| @@ -411,8 +437,10 @@ void ShellSurface::AcknowledgeConfigure(uint32_t serial) { |
| break; |
| } |
| - if (widget_) |
| + if (widget_) { |
| UpdateWidgetBounds(); |
| + UpdateShadow(); |
| + } |
| } |
| void ShellSurface::SetParent(ShellSurface* parent) { |
| @@ -481,6 +509,41 @@ void ShellSurface::Restore() { |
| widget_->Restore(); |
| } |
| +void ShellSurface::SetMoving() { |
| + TRACE_EVENT0("exo", "ShellSurface::SetMoving"); |
| + |
| + if (move_resizer_) |
| + return; |
| + |
| + ash::wm::WindowState* const window_state = |
| + ash::wm::GetWindowState(widget_->GetNativeWindow()); |
| + |
| + DCHECK(!window_state->drag_details()); |
| + window_state->CreateDragDetails(GetMouseLocation(), HTCAPTION, |
| + aura::client::WINDOW_MOVE_SOURCE_MOUSE); |
| + |
| + // The resizer renders phantom windows, but does not control window movement. |
| + move_resizer_.reset(ash::DragWindowResizer::Create( |
| + new CustomWindowResizer(window_state), window_state)); |
| + |
| + surface_->window()->SetCapture(); |
| +} |
| + |
| +void ShellSurface::UnsetMoving(bool revert) { |
| + TRACE_EVENT1("exo", "ShellSurface::UnsetMoving", "revert", revert); |
| + |
| + if (!move_resizer_) |
| + return; |
| + |
| + if (revert) |
| + move_resizer_->RevertDrag(); |
| + else |
| + move_resizer_->CompleteDrag(); |
| + |
| + move_resizer_.reset(); |
| + surface_->window()->ReleaseCapture(); |
| +} |
| + |
| void ShellSurface::SetFullscreen(bool fullscreen) { |
| TRACE_EVENT1("exo", "ShellSurface::SetFullscreen", "fullscreen", fullscreen); |
| @@ -639,7 +702,25 @@ void ShellSurface::SetTopInset(int height) { |
| void ShellSurface::SetOrigin(const gfx::Point& origin) { |
| TRACE_EVENT1("exo", "ShellSurface::SetOrigin", "origin", origin.ToString()); |
| - initial_bounds_ = gfx::Rect(origin, gfx::Size(1, 1)); |
| + const gfx::Point old_origin = origin_; |
| + origin_ = origin; |
| + |
| + if (bounds_mode_ != BoundsMode::CLIENT || origin == old_origin) |
| + return; |
| + |
| + // If the origin changed, give the client a chance to adjust window positions |
| + // before switching to the new coordinate system. Retain the old origin by |
| + // reverting the origin delta until the next configure is acknowledged. |
| + const gfx::Vector2d delta = origin - old_origin; |
| + origin_offset_ -= delta; |
| + pending_origin_offset_accumulator_ += delta; |
| + |
| + if (widget_) { |
| + UpdateWidgetBounds(); |
| + UpdateShadow(); |
| + } |
| + |
| + Configure(); |
| } |
| void ShellSurface::SetActivatable(bool activatable) { |
| @@ -686,15 +767,17 @@ void ShellSurface::OnSurfaceCommit() { |
| if (enabled() && !widget_) { |
| // Defer widget creation until surface contains some contents. |
| - if (surface_->content_size().IsEmpty()) |
| + if (surface_->content_size().IsEmpty()) { |
| Configure(); |
| - else |
| - CreateShellSurfaceWidget(ui::SHOW_STATE_NORMAL); |
| + return; |
| + } |
| + |
| + CreateShellSurfaceWidget(ui::SHOW_STATE_NORMAL); |
| } |
| // Apply the accumulated pending origin offset to reflect acknowledged |
| // configure requests. |
| - origin_ += pending_origin_offset_; |
| + origin_offset_ += pending_origin_offset_; |
| pending_origin_offset_ = gfx::Vector2d(); |
| // Update resize direction to reflect acknowledged configure requests. |
| @@ -733,13 +816,7 @@ void ShellSurface::OnSurfaceCommit() { |
| } |
| } |
| - gfx::Rect client_view_bounds = |
| - widget_->non_client_view()->frame_view()->GetBoundsForClientView(); |
| - |
| - // Update surface bounds. |
| - surface_->window()->SetBounds( |
| - gfx::Rect(GetSurfaceOrigin() + client_view_bounds.OffsetFromOrigin(), |
| - surface_->window()->layer()->size())); |
| + UpdateSurfaceBounds(); |
| // Update surface scale. |
| if (pending_scale_ != scale_) { |
| @@ -769,8 +846,7 @@ bool ShellSurface::IsSurfaceSynchronized() const { |
| // SurfaceObserver overrides: |
| void ShellSurface::OnSurfaceDestroying(Surface* surface) { |
| - if (resizer_) |
| - EndDrag(false /* revert */); |
| + EndDragOrMove(false /* revert */); |
| if (widget_) |
| SetMainSurface(widget_->GetNativeWindow(), nullptr); |
| surface->RemoveSurfaceObserver(this); |
| @@ -796,7 +872,7 @@ void ShellSurface::OnSurfaceDestroying(Surface* surface) { |
| // views::WidgetDelegate overrides: |
| bool ShellSurface::CanResize() const { |
| - return initial_bounds_.IsEmpty(); |
| + return bounds_mode_ == BoundsMode::SHELL; |
| } |
| bool ShellSurface::CanMaximize() const { |
| @@ -817,8 +893,7 @@ base::string16 ShellSurface::GetWindowTitle() const { |
| } |
| void ShellSurface::WindowClosing() { |
| - if (resizer_) |
| - EndDrag(true /* revert */); |
| + EndDragOrMove(true /* revert */); |
| SetEnabled(false); |
| widget_ = nullptr; |
| shadow_overlay_ = nullptr; |
| @@ -890,7 +965,10 @@ void ShellSurface::OnPreWindowStateTypeChange( |
| // cross-fade animations. The configure callback provides a mechanism for |
| // the client to inform us that a frame has taken the state change into |
| // account and without this cross-fade animations are unreliable. |
| - if (configure_callback_.is_null()) |
| + |
| + // TODO(domlaskowski): For shell surfaces whose bounds are controlled by the |
|
reveman
2017/02/06 19:49:34
Please remove this as it shouldn't hurt to trigger
Dominik Laskowski
2017/02/08 18:07:40
The TODO alludes to the above comment, i.e. animat
|
| + // client, the configure callback does not yet support window state changes. |
| + if (configure_callback_.is_null() || bounds_mode_ == BoundsMode::CLIENT) |
| scoped_animations_disabled_.reset(new ScopedAnimationsDisabled(this)); |
| } |
| } |
| @@ -922,7 +1000,8 @@ void ShellSurface::OnPostWindowStateTypeChange( |
| void ShellSurface::OnWindowBoundsChanged(aura::Window* window, |
| const gfx::Rect& old_bounds, |
| const gfx::Rect& new_bounds) { |
| - if (!widget_ || !surface_ || ignore_window_bounds_changes_) |
| + if (bounds_mode_ != BoundsMode::SHELL || !widget_ || !surface_ || |
|
reveman
2017/02/06 19:49:34
why is this needed. should ignore_window_bounds_ch
Dominik Laskowski
2017/02/08 18:07:40
The origin offset should not be modified for size
|
| + ignore_window_bounds_changes_) |
| return; |
| if (window == widget_->GetNativeWindow()) { |
| @@ -930,19 +1009,13 @@ void ShellSurface::OnWindowBoundsChanged(aura::Window* window, |
| return; |
| // If size changed then give the client a chance to produce new contents |
| - // before origin on screen is changed by adding offset to the next configure |
| - // request and offset |origin_| by the same distance. |
| - gfx::Vector2d origin_offset = new_bounds.origin() - old_bounds.origin(); |
| - pending_origin_config_offset_ += origin_offset; |
| - origin_ -= origin_offset; |
| - |
| - gfx::Rect client_view_bounds = |
| - widget_->non_client_view()->frame_view()->GetBoundsForClientView(); |
| + // before origin on screen is changed. Retain the old origin by reverting |
| + // the origin delta until the next configure is acknowledged. |
| + const gfx::Vector2d delta = new_bounds.origin() - old_bounds.origin(); |
| + origin_offset_ -= delta; |
| + pending_origin_offset_accumulator_ += delta; |
| - // Update surface bounds. |
| - surface_->window()->SetBounds( |
| - gfx::Rect(GetSurfaceOrigin() + client_view_bounds.OffsetFromOrigin(), |
| - surface_->window()->layer()->size())); |
| + UpdateSurfaceBounds(); |
|
reveman
2017/02/06 19:49:33
is this change needed?
Dominik Laskowski
2017/02/08 18:07:40
Yes, UpdateSurfaceBounds is called from several pl
|
| // The shadow size may be updated to match the widget. Change it back |
| // to the shadow content size. |
| @@ -973,6 +1046,9 @@ void ShellSurface::OnWindowActivated( |
| if (!widget_) |
| return; |
| + if (lost_active == widget_->GetNativeWindow()) |
| + UnsetMoving(false /* revert */); |
| + |
| if (gained_active == widget_->GetNativeWindow() || |
| lost_active == widget_->GetNativeWindow()) { |
| DCHECK(activatable_); |
| @@ -1084,7 +1160,7 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) { |
| // Make shell surface a transient child if |parent_| has been set. |
| params.parent = |
| parent_ ? parent_ : WMHelper::GetInstance()->GetContainer(container_); |
| - params.bounds = initial_bounds_; |
| + params.bounds = gfx::Rect(origin_, gfx::Size()); |
| bool activatable = activatable_; |
| // ShellSurfaces in system modal container are only activatable if input |
| // region is non-empty. See OnCommitSurface() for more details. |
| @@ -1111,11 +1187,10 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) { |
| ash::wm::WindowState* window_state = ash::wm::GetWindowState(window); |
| window_state->AddObserver(this); |
| - // Absolete positioned shell surfaces may request the bounds that does not |
| - // fill the entire work area / display in maximized / fullscreen state. |
| - // Allow such clients to update the bounds in these states. |
| - if (!initial_bounds_.IsEmpty()) |
| - window_state->set_allow_set_bounds_in_maximized(true); |
| + // Allow the client to request bounds that do not fill the entire work area |
| + // when maximized, or the entire display when fullscreen. |
| + window_state->set_allow_set_bounds_in_maximized(bounds_mode_ == |
| + BoundsMode::CLIENT); |
| // Notify client of initial state if different than normal. |
| if (window_state->GetStateType() != ash::wm::WINDOW_STATE_TYPE_NORMAL && |
| @@ -1124,9 +1199,10 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) { |
| window_state->GetStateType()); |
| } |
| - // Disable movement if initial bounds were specified. |
| - widget_->set_movement_disabled(!initial_bounds_.IsEmpty()); |
| - window_state->set_ignore_keyboard_bounds_change(!initial_bounds_.IsEmpty()); |
| + // Disable movement if bounds are controlled by the client or fixed. |
| + widget_->set_movement_disabled(bounds_mode_ != BoundsMode::SHELL); |
|
reveman
2017/02/06 19:49:33
nit: consider "bool shell_controls_bounds = bounds
Dominik Laskowski
2017/02/08 18:07:40
Done.
|
| + window_state->set_ignore_keyboard_bounds_change(bounds_mode_ != |
| + BoundsMode::SHELL); |
| // AutoHide shelf in fullscreen state. |
| window_state->set_hide_shelf_when_fullscreen(false); |
| @@ -1159,8 +1235,8 @@ void ShellSurface::Configure() { |
| return; |
| } |
| - gfx::Vector2d origin_offset = pending_origin_config_offset_; |
| - pending_origin_config_offset_ = gfx::Vector2d(); |
| + const gfx::Vector2d origin_offset = pending_origin_offset_accumulator_; |
| + pending_origin_offset_accumulator_ = gfx::Vector2d(); |
| int resize_component = HTCAPTION; |
| if (widget_) { |
| @@ -1179,10 +1255,11 @@ void ShellSurface::Configure() { |
| serial = configure_callback_.Run( |
| non_client_view->frame_view()->GetBoundsForClientView().size(), |
| ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(), |
| - IsResizing(), widget_->IsActive()); |
| + IsResizing(), widget_->IsActive(), origin_); |
| } else { |
| - serial = configure_callback_.Run( |
| - gfx::Size(), ash::wm::WINDOW_STATE_TYPE_NORMAL, false, false); |
| + serial = configure_callback_.Run(gfx::Size(), |
| + ash::wm::WINDOW_STATE_TYPE_NORMAL, false, |
| + false, origin_); |
| } |
| } |
| @@ -1210,16 +1287,10 @@ void ShellSurface::AttemptToStartDrag(int component) { |
| if (widget_->GetNativeWindow()->HasCapture()) |
| return; |
| - aura::Window* root_window = widget_->GetNativeWindow()->GetRootWindow(); |
| - gfx::Point drag_location = |
| - root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot(); |
| - aura::Window::ConvertPointToTarget( |
| - root_window, widget_->GetNativeWindow()->parent(), &drag_location); |
| - |
| // Set the cursor before calling CreateWindowResizer(), as that will |
| // eventually call LockCursor() and prevent the cursor from changing. |
| - aura::client::CursorClient* cursor_client = |
| - aura::client::GetCursorClient(root_window); |
| + aura::client::CursorClient* cursor_client = aura::client::GetCursorClient( |
| + widget_->GetNativeWindow()->GetRootWindow()); |
| DCHECK(cursor_client); |
| switch (component) { |
| @@ -1256,15 +1327,15 @@ void ShellSurface::AttemptToStartDrag(int component) { |
| } |
| resizer_ = ash::CreateWindowResizer( |
| - ash::WmWindow::Get(widget_->GetNativeWindow()), drag_location, component, |
| - aura::client::WINDOW_MOVE_SOURCE_MOUSE); |
| + ash::WmWindow::Get(widget_->GetNativeWindow()), GetMouseLocation(), |
| + component, aura::client::WINDOW_MOVE_SOURCE_MOUSE); |
| if (!resizer_) |
| return; |
| // Apply pending origin offsets and resize direction before starting a new |
| // resize operation. These can still be pending if the client has acknowledged |
| // the configure request but not yet called Commit(). |
| - origin_ += pending_origin_offset_; |
| + origin_offset_ += pending_origin_offset_; |
| pending_origin_offset_ = gfx::Vector2d(); |
| resize_component_ = pending_resize_component_; |
| @@ -1298,6 +1369,13 @@ void ShellSurface::EndDrag(bool revert) { |
| UpdateWidgetBounds(); |
| } |
| +void ShellSurface::EndDragOrMove(bool revert) { |
| + if (resizer_) |
| + EndDrag(revert); |
| + else |
| + UnsetMoving(revert); |
| +} |
| + |
| bool ShellSurface::IsResizing() const { |
| ash::wm::WindowState* window_state = |
| ash::wm::GetWindowState(widget_->GetNativeWindow()); |
| @@ -1315,12 +1393,15 @@ gfx::Rect ShellSurface::GetVisibleBounds() const { |
| } |
| gfx::Point ShellSurface::GetSurfaceOrigin() const { |
| - // If initial bounds were specified then surface origin is always relative |
| - // to those bounds. |
| - if (!initial_bounds_.IsEmpty()) { |
| - gfx::Point origin = widget_->GetNativeWindow()->bounds().origin(); |
| - wm::ConvertPointToScreen(widget_->GetNativeWindow()->parent(), &origin); |
| - return initial_bounds_.origin() - origin.OffsetFromOrigin(); |
| + // For client-positioned shell surfaces, the surface origin corresponds to the |
| + // widget position relative to the origin specified by the client. Since the |
| + // surface is positioned relative to the widget, negate this vector to align |
| + // the surface with the widget. Note that the widget position must have been |
| + // adjusted by the |origin_offset_| prior to this call. |
| + if (bounds_mode_ != BoundsMode::SHELL) { |
| + gfx::Point position = widget_->GetNativeWindow()->bounds().origin(); |
| + wm::ConvertPointToScreen(widget_->GetNativeWindow()->parent(), &position); |
| + return origin_ - position.OffsetFromOrigin(); |
| } |
| gfx::Rect visible_bounds = GetVisibleBounds(); |
| @@ -1328,7 +1409,7 @@ gfx::Point ShellSurface::GetSurfaceOrigin() const { |
| widget_->non_client_view()->frame_view()->GetBoundsForClientView(); |
| switch (resize_component_) { |
| case HTCAPTION: |
| - return origin_ - visible_bounds.OffsetFromOrigin(); |
| + return gfx::Point() + origin_offset_ - visible_bounds.OffsetFromOrigin(); |
| case HTBOTTOM: |
| case HTRIGHT: |
| case HTBOTTOMRIGHT: |
| @@ -1355,18 +1436,12 @@ gfx::Point ShellSurface::GetSurfaceOrigin() const { |
| void ShellSurface::UpdateWidgetBounds() { |
| DCHECK(widget_); |
| - // Return early if the shell is currently managing the bounds of the widget. |
| - // 1) When a window is either maximized/fullscreen/pinned, and the bounds |
| - // isn't controlled by a client. |
| - ash::wm::WindowState* window_state = |
| - ash::wm::GetWindowState(widget_->GetNativeWindow()); |
| - if (window_state->IsMaximizedOrFullscreenOrPinned() && |
| - !window_state->allow_set_bounds_in_maximized()) { |
| - return; |
| - } |
| - |
| - // 2) When a window is being dragged. |
| - if (IsResizing()) |
| + // Return early if the shell is currently managing the bounds of the widget, |
| + // and the window is maximized/fullscreen/pinned or being dragged. |
| + if (bounds_mode_ == BoundsMode::SHELL && |
|
reveman
2017/02/06 19:49:33
please split this into multiple lines as before. t
Dominik Laskowski
2017/02/08 18:07:40
Done, but it's "&&" so there's no third case.
|
| + (ash::wm::GetWindowState(widget_->GetNativeWindow()) |
| + ->IsMaximizedOrFullscreenOrPinned() || |
| + IsResizing())) |
| return; |
| // Return early if there is pending configure requests. |
| @@ -1378,13 +1453,15 @@ void ShellSurface::UpdateWidgetBounds() { |
| widget_->non_client_view()->GetWindowBoundsForClientBounds( |
| visible_bounds); |
| - // Avoid changing widget origin unless initial bounds were specified and |
| - // widget origin is always relative to it. |
| - if (initial_bounds_.IsEmpty()) { |
| - new_widget_bounds.set_origin(widget_->GetWindowBoundsInScreen().origin()); |
| + if (bounds_mode_ == BoundsMode::CLIENT) { |
|
reveman
2017/02/06 19:49:33
nit: use a switch statement
Dominik Laskowski
2017/02/08 18:07:40
Done. I've also merged the case below so it's clea
|
| + // Position is relative to the latest origin acknowledged by the client. |
| + new_widget_bounds -= origin_offset_; |
| + } else if (bounds_mode_ == BoundsMode::FIXED) { |
| + // Position is relative to the origin. |
| + new_widget_bounds += origin_.OffsetFromOrigin(); |
| } else { |
| - new_widget_bounds.set_origin(initial_bounds_.origin() + |
| - visible_bounds.OffsetFromOrigin()); |
| + // Preserve widget position. |
| + new_widget_bounds.set_origin(widget_->GetWindowBoundsInScreen().origin()); |
| } |
| // Update widget origin using the surface origin if the current location of |
| @@ -1401,14 +1478,32 @@ void ShellSurface::UpdateWidgetBounds() { |
| // should not result in a configure request. |
| DCHECK(!ignore_window_bounds_changes_); |
| ignore_window_bounds_changes_ = true; |
| - if (widget_->GetWindowBoundsInScreen() != new_widget_bounds) |
| - widget_->SetBounds(new_widget_bounds); |
| + if (widget_->GetWindowBoundsInScreen() != new_widget_bounds) { |
| + if (!move_resizer_) { |
| + widget_->SetBounds(new_widget_bounds); |
| + UpdateSurfaceBounds(); |
| + } else { |
| + // Convert from screen to display coordinates. |
| + gfx::Point origin = new_widget_bounds.origin(); |
| + wm::ConvertPointFromScreen(widget_->GetNativeWindow()->parent(), &origin); |
| + new_widget_bounds.set_origin(origin); |
| + |
| + // Move the window relative to the current display. |
| + widget_->GetNativeWindow()->SetBounds(new_widget_bounds); |
| + UpdateSurfaceBounds(); |
| + |
| + // Render phantom windows when beyond the current display. |
| + move_resizer_->Drag(GetMouseLocation(), 0); |
| + } |
| + } |
| + |
| ignore_window_bounds_changes_ = false; |
| +} |
| - gfx::Rect client_view_bounds = |
| +void ShellSurface::UpdateSurfaceBounds() { |
| + const gfx::Rect client_view_bounds = |
| widget_->non_client_view()->frame_view()->GetBoundsForClientView(); |
| - // A change to the widget size requires surface bounds to be re-adjusted. |
| surface_->window()->SetBounds( |
| gfx::Rect(GetSurfaceOrigin() + client_view_bounds.OffsetFromOrigin(), |
| surface_->window()->layer()->size())); |
| @@ -1429,11 +1524,9 @@ void ShellSurface::UpdateShadow() { |
| if (shadow_content_bounds.IsEmpty()) |
| shadow_content_bounds = window->bounds(); |
| - // TODO(oshima): Adjust the coordinates from client screen to |
| - // chromeos screen when multi displays are supported. |
| - gfx::Point origin = window->bounds().origin(); |
| - gfx::Point shadow_origin = shadow_content_bounds.origin(); |
| - shadow_origin -= origin.OffsetFromOrigin(); |
| + gfx::Point shadow_origin = shadow_content_bounds.origin() - origin_offset_; |
| + wm::ConvertPointFromScreen(window->parent(), &shadow_origin); |
| + shadow_origin -= window->bounds().OffsetFromOrigin(); |
| gfx::Rect shadow_bounds(shadow_origin, shadow_content_bounds.size()); |
| // Always create and show the underlay, even in maximized/fullscreen. |
| @@ -1523,4 +1616,13 @@ void ShellSurface::UpdateShadow() { |
| } |
| } |
| +gfx::Point ShellSurface::GetMouseLocation() const { |
| + aura::Window* const root_window = widget_->GetNativeWindow()->GetRootWindow(); |
| + gfx::Point location = |
| + root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot(); |
| + aura::Window::ConvertPointToTarget( |
| + root_window, widget_->GetNativeWindow()->parent(), &location); |
| + return location; |
| +} |
| + |
| } // namespace exo |