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

Unified Diff: components/exo/shell_surface.cc

Issue 2645663004: exo: Initial support for multiple displays in ARC (Closed)
Patch Set: Address nits Created 3 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/exo/shell_surface.cc
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 8b61a9d121e7169dea7f1cf3e1f7be42053fc4b9..7016042a4f8faee91424ac3e8eaa6c03a45f1579 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -10,8 +10,10 @@
#include "ash/common/shelf/wm_shelf.h"
#include "ash/common/wm/window_resizer.h"
#include "ash/common/wm/window_state.h"
+#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"
@@ -29,6 +31,8 @@
#include "ui/aura/window_tree_host.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/class_property.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
#include "ui/gfx/path.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
@@ -143,6 +147,27 @@ class CustomWindowTargeter : public aura::WindowTargeter {
DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter);
};
+// Minimal WindowResizer that unlike DefaultWindowResizer does not handle
+// dragging and resizing windows.
+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(); }
+
+ // Overridden from 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)
@@ -299,11 +324,14 @@ ShellSurface::ShellSurface(Surface* surface,
surface_(surface),
parent_(parent ? parent->GetWidget()->GetNativeWindow() : nullptr),
bounds_mode_(bounds_mode),
+ primary_display_id_(
+ display::Screen::GetScreen()->GetPrimaryDisplay().id()),
origin_(origin),
activatable_(activatable),
can_minimize_(can_minimize),
container_(container) {
WMHelper::GetInstance()->AddActivationObserver(this);
+ WMHelper::GetInstance()->AddDisplayConfigurationObserver(this);
surface_->SetSurfaceDelegate(this);
surface_->AddSurfaceObserver(this);
surface_->window()->Show();
@@ -336,6 +364,7 @@ ShellSurface::~ShellSurface() {
widget_->CloseNow();
}
WMHelper::GetInstance()->RemoveActivationObserver(this);
+ WMHelper::GetInstance()->RemoveDisplayConfigurationObserver(this);
if (parent_)
parent_->RemoveObserver(this);
if (surface_) {
@@ -542,9 +571,9 @@ void ShellSurface::Move() {
switch (bounds_mode_) {
case BoundsMode::SHELL:
+ case BoundsMode::CLIENT:
AttemptToStartDrag(HTCAPTION);
return;
- case BoundsMode::CLIENT:
case BoundsMode::FIXED:
return;
}
@@ -644,29 +673,7 @@ void ShellSurface::SetTopInset(int height) {
void ShellSurface::SetOrigin(const gfx::Point& origin) {
TRACE_EVENT1("exo", "ShellSurface::SetOrigin", "origin", origin.ToString());
- if (origin == origin_)
- return;
-
- if (bounds_mode_ != BoundsMode::CLIENT) {
- origin_ = 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.
- gfx::Vector2d delta = origin - origin_;
- origin_offset_ -= delta;
- pending_origin_offset_accumulator_ += delta;
-
origin_ = origin;
-
- if (widget_) {
- UpdateWidgetBounds();
- UpdateShadow();
- }
-
- Configure();
}
void ShellSurface::SetActivatable(bool activatable) {
@@ -913,8 +920,8 @@ void ShellSurface::OnPreWindowStateTypeChange(
// the client to inform us that a frame has taken the state change into
// account and without this cross-fade animations are unreliable.
- // TODO(domlaskowski): For shell surfaces whose bounds are controlled by the
- // client, the configure callback does not yet support window state changes.
+ // TODO(domlaskowski): For BoundsMode::CLIENT, the configure callback does
+ // not yet support window state changes. See crbug.com/699746.
if (configure_callback_.is_null() || bounds_mode_ == BoundsMode::CLIENT)
scoped_animations_disabled_.reset(new ScopedAnimationsDisabled(this));
}
@@ -947,8 +954,8 @@ void ShellSurface::OnPostWindowStateTypeChange(
void ShellSurface::OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {
- // TODO(domlaskowski): For shell surfaces whose bounds are controlled by the
- // client, the configure callback does not yet support resizing.
+ // TODO(domlaskowski): For BoundsMode::CLIENT, the configure callback does not
+ // yet support resizing. See crbug.com/699746.
if (bounds_mode_ == BoundsMode::CLIENT)
return;
@@ -1013,6 +1020,39 @@ void ShellSurface::OnAccessibilityModeChanged() {
}
////////////////////////////////////////////////////////////////////////////////
+// WMHelper::DisplayConfigurationObserver overrides:
+
+void ShellSurface::OnDisplayConfigurationChanged() {
+ if (bounds_mode_ != BoundsMode::CLIENT)
+ return;
+
+ const display::Screen* screen = display::Screen::GetScreen();
+ int64_t primary_display_id = screen->GetPrimaryDisplay().id();
+ if (primary_display_id == primary_display_id_)
+ return;
+
+ display::Display old_primary_display;
+ if (screen->GetDisplayWithDisplayId(primary_display_id_,
+ &old_primary_display)) {
+ // 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.
+ gfx::Vector2d delta = gfx::Point() - old_primary_display.bounds().origin();
+ origin_offset_ -= delta;
+ pending_origin_offset_accumulator_ += delta;
+
+ if (widget_) {
+ UpdateWidgetBounds();
+ UpdateShadow();
+ }
+
+ Configure();
+ }
+
+ primary_display_id_ = primary_display_id;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// ui::EventHandler overrides:
void ShellSurface::OnKeyEvent(ui::KeyEvent* event) {
@@ -1021,6 +1061,9 @@ void ShellSurface::OnKeyEvent(ui::KeyEvent* event) {
return;
}
+ // TODO(domlaskowski): For BoundsMode::CLIENT, synchronize the revert with the
+ // client, instead of having the client destroy the window on VKEY_ESCAPE. See
+ // crbug.com/699746.
if (event->type() == ui::ET_KEY_PRESSED &&
event->key_code() == ui::VKEY_ESCAPE) {
EndDrag(true /* revert */);
@@ -1050,6 +1093,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(),
@@ -1203,11 +1249,11 @@ void ShellSurface::Configure() {
serial = configure_callback_.Run(
non_client_view->frame_view()->GetBoundsForClientView().size(),
ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(),
- IsResizing(), widget_->IsActive(), origin_);
+ IsResizing(), widget_->IsActive(), origin_offset);
} else {
serial = configure_callback_.Run(gfx::Size(),
ash::wm::WINDOW_STATE_TYPE_NORMAL, false,
- false, origin_);
+ false, origin_offset);
}
}
@@ -1225,6 +1271,22 @@ void ShellSurface::Configure() {
<< pending_configs_.size();
}
+aura::Window* ShellSurface::GetDragWindow() const {
+ switch (bounds_mode_) {
+ case BoundsMode::SHELL:
+ return widget_->GetNativeWindow();
+
+ case BoundsMode::CLIENT:
+ return surface_ ? surface_->window() : nullptr;
+
+ case BoundsMode::FIXED:
+ return nullptr;
+ }
+
+ NOTREACHED();
+ return nullptr;
+}
+
void ShellSurface::AttemptToStartDrag(int component) {
DCHECK(widget_);
@@ -1232,69 +1294,81 @@ void ShellSurface::AttemptToStartDrag(int component) {
if (resizer_)
return;
- if (widget_->GetNativeWindow()->HasCapture())
+ aura::Window* window = GetDragWindow();
+ if (!window || window->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);
- DCHECK(cursor_client);
+ if (bounds_mode_ == BoundsMode::SHELL) {
+ // 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(window->GetRootWindow());
+ DCHECK(cursor_client);
+
+ switch (component) {
+ case HTCAPTION:
+ cursor_client->SetCursor(ui::kCursorPointer);
+ break;
+ case HTTOP:
+ cursor_client->SetCursor(ui::kCursorNorthResize);
+ break;
+ case HTTOPRIGHT:
+ cursor_client->SetCursor(ui::kCursorNorthEastResize);
+ break;
+ case HTRIGHT:
+ cursor_client->SetCursor(ui::kCursorEastResize);
+ break;
+ case HTBOTTOMRIGHT:
+ cursor_client->SetCursor(ui::kCursorSouthEastResize);
+ break;
+ case HTBOTTOM:
+ cursor_client->SetCursor(ui::kCursorSouthResize);
+ break;
+ case HTBOTTOMLEFT:
+ cursor_client->SetCursor(ui::kCursorSouthWestResize);
+ break;
+ case HTLEFT:
+ cursor_client->SetCursor(ui::kCursorWestResize);
+ break;
+ case HTTOPLEFT:
+ cursor_client->SetCursor(ui::kCursorNorthWestResize);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
- switch (component) {
- case HTCAPTION:
- cursor_client->SetCursor(ui::kCursorPointer);
- break;
- case HTTOP:
- cursor_client->SetCursor(ui::kCursorNorthResize);
- break;
- case HTTOPRIGHT:
- cursor_client->SetCursor(ui::kCursorNorthEastResize);
- break;
- case HTRIGHT:
- cursor_client->SetCursor(ui::kCursorEastResize);
- break;
- case HTBOTTOMRIGHT:
- cursor_client->SetCursor(ui::kCursorSouthEastResize);
- break;
- case HTBOTTOM:
- cursor_client->SetCursor(ui::kCursorSouthResize);
- break;
- case HTBOTTOMLEFT:
- cursor_client->SetCursor(ui::kCursorSouthWestResize);
- break;
- case HTLEFT:
- cursor_client->SetCursor(ui::kCursorWestResize);
- break;
- case HTTOPLEFT:
- cursor_client->SetCursor(ui::kCursorNorthWestResize);
- break;
- default:
- NOTREACHED();
- break;
- }
+ resizer_ = ash::CreateWindowResizer(ash::WmWindow::Get(window),
+ GetMouseLocation(), component,
+ aura::client::WINDOW_MOVE_SOURCE_MOUSE);
+ if (!resizer_)
+ return;
- resizer_ = ash::CreateWindowResizer(
- ash::WmWindow::Get(widget_->GetNativeWindow()), drag_location, 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_offset_ += pending_origin_offset_;
+ pending_origin_offset_ = gfx::Vector2d();
+ resize_component_ = pending_resize_component_;
+ } else {
+ DCHECK(bounds_mode_ == BoundsMode::CLIENT);
- // 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_offset_ += pending_origin_offset_;
- pending_origin_offset_ = gfx::Vector2d();
- resize_component_ = pending_resize_component_;
+ ash::wm::WindowState* window_state =
+ ash::wm::GetWindowState(widget_->GetNativeWindow());
+ DCHECK(!window_state->drag_details());
+ DCHECK(component == HTCAPTION);
+ window_state->CreateDragDetails(GetMouseLocation(), component,
+ aura::client::WINDOW_MOVE_SOURCE_MOUSE);
+
+ // Chained with a CustomWindowResizer, DragWindowResizer does not handle
+ // dragging. It only renders phantom windows and moves the window to the
+ // target root window when dragging ends.
+ resizer_.reset(ash::DragWindowResizer::Create(
+ new CustomWindowResizer(window_state), window_state));
+ }
WMHelper::GetInstance()->AddPreTargetHandler(this);
- widget_->GetNativeWindow()->SetCapture();
+ window->SetCapture();
// Notify client that resizing state has changed.
if (IsResizing())
@@ -1305,6 +1379,10 @@ void ShellSurface::EndDrag(bool revert) {
DCHECK(widget_);
DCHECK(resizer_);
+ aura::Window* window = GetDragWindow();
+ DCHECK(window);
+ DCHECK(window->HasCapture());
+
bool was_resizing = IsResizing();
if (revert)
@@ -1313,7 +1391,7 @@ void ShellSurface::EndDrag(bool revert) {
resizer_->CompleteDrag();
WMHelper::GetInstance()->RemovePreTargetHandler(this);
- widget_->GetNativeWindow()->ReleaseCapture();
+ window->ReleaseCapture();
resizer_.reset();
// Notify client that resizing state has changed.
@@ -1426,8 +1504,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);
+ 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. See
+ // crbug.com/699746.
+ DLOG_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;
}
@@ -1591,4 +1693,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
« 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