| Index: components/exo/shell_surface.cc
|
| diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
|
| index a0c2a59d8fcb75c9960f355202e5abda625af83d..1be6a606a533081a0e445ae503ab9d2bb2b2388c 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"
|
| #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 {
|
| + 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,7 +381,8 @@ ShellSurface::ShellSurface(Surface* surface,
|
| ShellSurface::ShellSurface(Surface* surface)
|
| : ShellSurface(surface,
|
| nullptr,
|
| - gfx::Rect(),
|
| + BoundsMode::SHELL,
|
| + gfx::Point(),
|
| true,
|
| true,
|
| ash::kShellWindowId_DefaultContainer) {}
|
| @@ -387,6 +411,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 +438,10 @@ void ShellSurface::AcknowledgeConfigure(uint32_t serial) {
|
| break;
|
| }
|
|
|
| - if (widget_)
|
| + if (widget_) {
|
| UpdateWidgetBounds();
|
| + UpdateShadow();
|
| + }
|
| }
|
|
|
| void ShellSurface::SetParent(ShellSurface* parent) {
|
| @@ -564,15 +593,37 @@ void ShellSurface::SetApplicationId(const std::string& application_id) {
|
| void ShellSurface::Move() {
|
| TRACE_EVENT0("exo", "ShellSurface::Move");
|
|
|
| - if (widget_ && !widget_->movement_disabled())
|
| - AttemptToStartDrag(HTCAPTION);
|
| + if (!widget_ || resizer_)
|
| + return;
|
| +
|
| + switch (bounds_mode_) {
|
| + case BoundsMode::SHELL:
|
| + AttemptToStartDrag(HTCAPTION);
|
| + break;
|
| + case BoundsMode::CLIENT:
|
| + AttemptToStartClientDrag();
|
| + break;
|
| + case BoundsMode::FIXED:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| }
|
|
|
| void ShellSurface::Resize(int component) {
|
| TRACE_EVENT1("exo", "ShellSurface::Resize", "component", component);
|
|
|
| - if (widget_ && !widget_->movement_disabled())
|
| - AttemptToStartDrag(component);
|
| + if (!widget_ || resizer_)
|
| + return;
|
| +
|
| + switch (bounds_mode_) {
|
| + case BoundsMode::SHELL:
|
| + AttemptToStartDrag(component);
|
| + break;
|
| + case BoundsMode::CLIENT:
|
| + case BoundsMode::FIXED:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| }
|
|
|
| void ShellSurface::Close() {
|
| @@ -649,7 +700,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) {
|
| @@ -696,15 +765,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.
|
| @@ -743,13 +814,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_) {
|
| @@ -806,7 +871,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 {
|
| @@ -900,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
|
| + // 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));
|
| }
|
| }
|
| @@ -940,19 +1008,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;
|
| + // 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;
|
|
|
| - 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();
|
|
|
| // The shadow size may be updated to match the widget. Change it back
|
| // to the shadow content size.
|
| @@ -1007,7 +1069,8 @@ void ShellSurface::OnKeyEvent(ui::KeyEvent* event) {
|
| return;
|
| }
|
|
|
| - if (event->type() == ui::ET_KEY_PRESSED &&
|
| + if (bounds_mode_ == BoundsMode::SHELL &&
|
| + event->type() == ui::ET_KEY_PRESSED &&
|
| event->key_code() == ui::VKEY_ESCAPE) {
|
| EndDrag(true /* revert */);
|
| }
|
| @@ -1036,6 +1099,9 @@ void ShellSurface::OnMouseEvent(ui::MouseEvent* event) {
|
|
|
| switch (event->type()) {
|
| case ui::ET_MOUSE_DRAGGED: {
|
| + if (bounds_mode_ == BoundsMode::CLIENT)
|
| + break;
|
| +
|
| gfx::Point location(event->location());
|
| aura::Window::ConvertPointToTarget(widget_->GetNativeWindow(),
|
| widget_->GetNativeWindow()->parent(),
|
| @@ -1094,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.
|
| @@ -1116,16 +1182,17 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) {
|
| SetApplicationId(window, application_id_);
|
| SetMainSurface(window, surface_);
|
|
|
| + const bool client_controls_bounds = bounds_mode_ == BoundsMode::CLIENT;
|
| +
|
| // Start tracking changes to window bounds and window state.
|
| - window->AddObserver(this);
|
| + if (!client_controls_bounds)
|
| + window->AddObserver(this);
|
| 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(client_controls_bounds);
|
|
|
| // Notify client of initial state if different than normal.
|
| if (window_state->GetStateType() != ash::wm::WINDOW_STATE_TYPE_NORMAL &&
|
| @@ -1134,9 +1201,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.
|
| + const bool movement_disabled = bounds_mode_ != BoundsMode::SHELL;
|
| + widget_->set_movement_disabled(movement_disabled);
|
| + window_state->set_ignore_keyboard_bounds_change(movement_disabled);
|
|
|
| // AutoHide shelf in fullscreen state.
|
| window_state->set_hide_shelf_when_fullscreen(false);
|
| @@ -1169,8 +1237,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_) {
|
| @@ -1189,10 +1257,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_);
|
| }
|
| }
|
|
|
| @@ -1213,23 +1282,13 @@ void ShellSurface::Configure() {
|
| void ShellSurface::AttemptToStartDrag(int component) {
|
| DCHECK(widget_);
|
|
|
| - // Cannot start another drag if one is already taking place.
|
| - if (resizer_)
|
| - return;
|
| -
|
| 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) {
|
| @@ -1266,15 +1325,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_;
|
|
|
| @@ -1286,26 +1345,62 @@ void ShellSurface::AttemptToStartDrag(int component) {
|
| Configure();
|
| }
|
|
|
| +void ShellSurface::AttemptToStartClientDrag() {
|
| + DCHECK(widget_);
|
| +
|
| + if (surface_->window()->HasCapture())
|
| + 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.
|
| + resizer_.reset(ash::DragWindowResizer::Create(
|
| + new CustomWindowResizer(window_state), window_state));
|
| +
|
| + WMHelper::GetInstance()->AddPreTargetHandler(this);
|
| + surface_->window()->SetCapture();
|
| +}
|
| +
|
| void ShellSurface::EndDrag(bool revert) {
|
| DCHECK(widget_);
|
| DCHECK(resizer_);
|
|
|
| - bool was_resizing = IsResizing();
|
| + switch (bounds_mode_) {
|
| + case BoundsMode::SHELL: {
|
| + bool was_resizing = IsResizing();
|
| +
|
| + EndDrag(widget_->GetNativeWindow(), revert);
|
|
|
| + // Notify client that resizing state has changed.
|
| + if (was_resizing)
|
| + Configure();
|
| +
|
| + UpdateWidgetBounds();
|
| + break;
|
| + }
|
| + case BoundsMode::CLIENT:
|
| + EndDrag(surface_->window(), revert);
|
| + break;
|
| + case BoundsMode::FIXED:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void ShellSurface::EndDrag(aura::Window* window, bool revert) {
|
| if (revert)
|
| resizer_->RevertDrag();
|
| else
|
| resizer_->CompleteDrag();
|
|
|
| WMHelper::GetInstance()->RemovePreTargetHandler(this);
|
| - widget_->GetNativeWindow()->ReleaseCapture();
|
| + window->ReleaseCapture();
|
| resizer_.reset();
|
| -
|
| - // Notify client that resizing state has changed.
|
| - if (was_resizing)
|
| - Configure();
|
| -
|
| - UpdateWidgetBounds();
|
| }
|
|
|
| bool ShellSurface::IsResizing() const {
|
| @@ -1325,12 +1420,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();
|
| @@ -1338,7 +1436,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:
|
| @@ -1347,7 +1445,6 @@ gfx::Point ShellSurface::GetSurfaceOrigin() const {
|
| case HTTOPRIGHT:
|
| return gfx::Point(0, client_bounds.height() - visible_bounds.height()) -
|
| visible_bounds.OffsetFromOrigin();
|
| - break;
|
| case HTLEFT:
|
| case HTBOTTOMLEFT:
|
| return gfx::Point(client_bounds.width() - visible_bounds.width(), 0) -
|
| @@ -1366,18 +1463,17 @@ 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;
|
| - }
|
| + if (bounds_mode_ == BoundsMode::SHELL) {
|
| + // 1) When a window is either maximized/fullscreen/pinned.
|
| + ash::wm::WindowState* window_state =
|
| + ash::wm::GetWindowState(widget_->GetNativeWindow());
|
| + if (window_state->IsMaximizedOrFullscreenOrPinned())
|
| + return;
|
|
|
| - // 2) When a window is being dragged.
|
| - if (IsResizing())
|
| - return;
|
| + // 2) When a window is being dragged.
|
| + if (IsResizing())
|
| + return;
|
| + }
|
|
|
| // Return early if there is pending configure requests.
|
| if (!pending_configs_.empty() || scoped_configure_)
|
| @@ -1388,37 +1484,68 @@ 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());
|
| - } else {
|
| - new_widget_bounds.set_origin(initial_bounds_.origin() +
|
| - visible_bounds.OffsetFromOrigin());
|
| - }
|
| -
|
| - // Update widget origin using the surface origin if the current location of
|
| - // surface is being anchored to one side of the widget as a result of a
|
| - // resize operation.
|
| - if (resize_component_ != HTCAPTION) {
|
| - gfx::Point new_widget_origin =
|
| - GetSurfaceOrigin() + visible_bounds.OffsetFromOrigin();
|
| - wm::ConvertPointToScreen(widget_->GetNativeWindow(), &new_widget_origin);
|
| - new_widget_bounds.set_origin(new_widget_origin);
|
| + switch (bounds_mode_) {
|
| + case BoundsMode::CLIENT:
|
| + // Position is relative to the latest origin acknowledged by the client.
|
| + new_widget_bounds -= origin_offset_;
|
| + break;
|
| + case BoundsMode::FIXED:
|
| + // Position is relative to the origin.
|
| + new_widget_bounds += origin_.OffsetFromOrigin();
|
| + break;
|
| + case BoundsMode::SHELL:
|
| + // Update widget origin using the surface origin if the current location
|
| + // of surface is being anchored to one side of the widget as a result of a
|
| + // resize operation.
|
| + if (resize_component_ != HTCAPTION) {
|
| + gfx::Point widget_origin =
|
| + GetSurfaceOrigin() + visible_bounds.OffsetFromOrigin();
|
| + wm::ConvertPointToScreen(widget_->GetNativeWindow(), &widget_origin);
|
| + new_widget_bounds.set_origin(widget_origin);
|
| + } else {
|
| + // Preserve widget position.
|
| + new_widget_bounds.set_origin(
|
| + widget_->GetWindowBoundsInScreen().origin());
|
| + }
|
| + break;
|
| }
|
|
|
| // Set |ignore_window_bounds_changes_| as this change to window bounds
|
| // 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);
|
| + const gfx::Rect widget_bounds = widget_->GetWindowBoundsInScreen();
|
| + if (widget_bounds != new_widget_bounds) {
|
| + if (bounds_mode_ != BoundsMode::CLIENT || !resizer_) {
|
| + widget_->SetBounds(new_widget_bounds);
|
| + UpdateSurfaceBounds();
|
| + } else {
|
| + // TODO(domlaskowski): Synchronize window state transitions with the
|
| + // client, and abort client-side dragging on transition to fullscreen.
|
| + LOG_IF(ERROR, widget_bounds.size() != new_widget_bounds.size())
|
| + << "Window size changed during client-driven drag";
|
| +
|
| + // 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.
|
| + 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()));
|
| @@ -1447,11 +1574,9 @@ void ShellSurface::UpdateShadow() {
|
| }
|
| }
|
|
|
| - // 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.
|
| @@ -1556,4 +1681,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
|
|
|