Chromium Code Reviews| Index: components/exo/shell_surface.cc |
| diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc |
| index a0c2a59d8fcb75c9960f355202e5abda625af83d..7da70bfdc6961e15c9eb7ae1c4ab51f514e20c5a 100644 |
| --- a/components/exo/shell_surface.cc |
| +++ b/components/exo/shell_surface.cc |
| @@ -335,14 +335,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 +360,8 @@ ShellSurface::ShellSurface(Surface* surface, |
| ShellSurface::ShellSurface(Surface* surface) |
| : ShellSurface(surface, |
| nullptr, |
| - gfx::Rect(), |
| + BoundsMode::SHELL, |
| + gfx::Point(), |
| true, |
| true, |
| ash::kShellWindowId_DefaultContainer) {} |
| @@ -564,15 +567,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_) |
| + return; |
| + |
| + switch (bounds_mode_) { |
| + case BoundsMode::SHELL: |
| + AttemptToStartDrag(HTCAPTION); |
| + return; |
| + case BoundsMode::CLIENT: |
| + case BoundsMode::FIXED: |
| + break; |
|
reveman
2017/02/10 02:10:53
return;
Dominik Laskowski
2017/02/10 03:05:18
Done.
|
| + } |
| + |
| + NOTREACHED(); |
| } |
| void ShellSurface::Resize(int component) { |
| TRACE_EVENT1("exo", "ShellSurface::Resize", "component", component); |
| - if (widget_ && !widget_->movement_disabled()) |
| - AttemptToStartDrag(component); |
| + if (!widget_) |
| + return; |
| + |
| + switch (bounds_mode_) { |
| + case BoundsMode::SHELL: |
| + AttemptToStartDrag(component); |
| + return; |
| + case BoundsMode::CLIENT: |
| + case BoundsMode::FIXED: |
| + break; |
|
reveman
2017/02/10 02:10:53
return;
Dominik Laskowski
2017/02/10 03:05:18
Done.
|
| + } |
| + |
| + NOTREACHED(); |
| } |
| void ShellSurface::Close() { |
| @@ -649,7 +674,7 @@ 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)); |
| + origin_ = origin; |
| } |
| void ShellSurface::SetActivatable(bool activatable) { |
| @@ -704,7 +729,7 @@ void ShellSurface::OnSurfaceCommit() { |
| // 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 +768,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 +825,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 { |
| @@ -932,7 +951,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::CLIENT || !widget_ || !surface_ || |
|
reveman
2017/02/10 02:10:53
why is this needed?
Dominik Laskowski
2017/02/10 03:05:18
Oops, this belongs to the dependent CL. Removed.
|
| + ignore_window_bounds_changes_) |
| return; |
| if (window == widget_->GetNativeWindow()) { |
| @@ -940,19 +960,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. |
| + 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(); |
| // The shadow size may be updated to match the widget. Change it back |
| // to the shadow content size. |
| @@ -1094,7 +1108,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. |
| @@ -1121,11 +1135,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 && |
| @@ -1134,9 +1147,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. |
| + 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 +1183,8 @@ void ShellSurface::Configure() { |
| return; |
| } |
| - gfx::Vector2d origin_offset = pending_origin_config_offset_; |
| - pending_origin_config_offset_ = gfx::Vector2d(); |
| + gfx::Vector2d origin_offset = pending_origin_offset_accumulator_; |
| + pending_origin_offset_accumulator_ = gfx::Vector2d(); |
| int resize_component = HTCAPTION; |
| if (widget_) { |
| @@ -1274,7 +1288,7 @@ void ShellSurface::AttemptToStartDrag(int component) { |
| // 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_; |
| @@ -1290,22 +1304,32 @@ void ShellSurface::EndDrag(bool revert) { |
| DCHECK(widget_); |
| DCHECK(resizer_); |
| - bool was_resizing = IsResizing(); |
| + switch (bounds_mode_) { |
|
reveman
2017/02/10 02:10:53
is this switch statement needed? what happens if y
Dominik Laskowski
2017/02/10 03:05:18
Not necessary but simplifies the diff of the depen
reveman
2017/02/10 05:51:54
Let's save switch statement until needed. That mak
Dominik Laskowski
2017/02/10 18:47:16
Done.
|
| + case BoundsMode::SHELL: { |
| + bool was_resizing = IsResizing(); |
| - if (revert) |
| - resizer_->RevertDrag(); |
| - else |
| - resizer_->CompleteDrag(); |
| + if (revert) |
| + resizer_->RevertDrag(); |
| + else |
| + resizer_->CompleteDrag(); |
| - WMHelper::GetInstance()->RemovePreTargetHandler(this); |
| - widget_->GetNativeWindow()->ReleaseCapture(); |
| - resizer_.reset(); |
| + WMHelper::GetInstance()->RemovePreTargetHandler(this); |
| + widget_->GetNativeWindow()->ReleaseCapture(); |
| + resizer_.reset(); |
| - // Notify client that resizing state has changed. |
| - if (was_resizing) |
| - Configure(); |
| + // Notify client that resizing state has changed. |
| + if (was_resizing) |
| + Configure(); |
| - UpdateWidgetBounds(); |
| + UpdateWidgetBounds(); |
| + return; |
| + } |
| + case BoundsMode::CLIENT: |
| + case BoundsMode::FIXED: |
| + break; |
| + } |
| + |
| + NOTREACHED(); |
| } |
| bool ShellSurface::IsResizing() const { |
| @@ -1325,12 +1349,14 @@ 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. |
| + 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 +1364,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 +1373,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 +1391,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) { |
|
reveman
2017/02/10 02:10:53
why is this check needed? should we return early i
Dominik Laskowski
2017/02/10 03:05:18
It replaces the allow_set_bounds_in_maximized chec
reveman
2017/02/10 05:51:53
Let's not make the assumption that IsResizing can
Dominik Laskowski
2017/02/10 18:47:16
Reverted.
|
| + // 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,23 +1412,27 @@ 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: |
| + 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 |
| @@ -1414,11 +1442,12 @@ void ShellSurface::UpdateWidgetBounds() { |
| if (widget_->GetWindowBoundsInScreen() != new_widget_bounds) |
| widget_->SetBounds(new_widget_bounds); |
| ignore_window_bounds_changes_ = false; |
| +} |
| +void ShellSurface::UpdateSurfaceBounds() { |
| 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())); |