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

Unified Diff: components/exo/shell_surface.cc

Issue 2645663004: exo: Initial support for multiple displays in ARC (Closed)
Patch Set: Fix race and refactor Created 3 years, 10 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
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

Powered by Google App Engine
This is Rietveld 408576698