Commit 12c66048 authored by Evan Stade's avatar Evan Stade Committed by Commit Bot

ws2: Support cursors for embedded windows.

For top level client windows, the cursor is stored in
WmNativeWidgetAura. For embed roots, it's stored in ServerWindow.
CompoundEventFilter will retrieve the stored cursor while
handling mouse events by using aura::WindowDelegate::GetCursor.
Depending on the target of the mouse event, the WindowDelegate
will be either WindowDelegateImpl (which retrieves it from
ServerWindow or delegates to the top level's delegate) or
WmNativeWidgetAura (which returns its own copy of the cursor).

To test, hover over input field of KSV via:
1. chrome --keyboard-shortcut-viewer-app  Ctrl+Alt+/
or
2. ash_shell_with_content

Bug: 837705
Change-Id: I247b41937aada5a9b161eb469d8230d06890a63b
Reviewed-on: https://chromium-review.googlesource.com/1068661
Commit-Queue: Evan Stade <estade@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567870}
parent ca0a922c
...@@ -1672,6 +1672,7 @@ test("ash_unittests") { ...@@ -1672,6 +1672,7 @@ test("ash_unittests") {
"app_list/presenter/app_list_presenter_impl_unittest.cc", "app_list/presenter/app_list_presenter_impl_unittest.cc",
"assistant/assistant_controller_unittest.cc", "assistant/assistant_controller_unittest.cc",
"autoclick/autoclick_unittest.cc", "autoclick/autoclick_unittest.cc",
"cursor_unittest.cc",
"detachable_base/detachable_base_handler_unittest.cc", "detachable_base/detachable_base_handler_unittest.cc",
"detachable_base/detachable_base_notification_controller_unittest.cc", "detachable_base/detachable_base_notification_controller_unittest.cc",
"dip_unittest.cc", "dip_unittest.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/test/ash_test_base.h"
#include "ash/shell.h"
#include "services/ui/ws2/test_window_tree_client.h"
#include "services/ui/ws2/window_tree_test_helper.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/test/event_generator.h"
namespace ash {
using CursorTest = AshTestBase;
TEST_F(CursorTest, TopLevel) {
// Create a top level window.
std::unique_ptr<aura::Window> window =
CreateTestWindow(gfx::Rect(0, 0, 100, 100));
// Make sure the WindowTreeClient receives events.
EXPECT_EQ(0U, GetTestWindowTreeClient()->input_events().size());
ui::test::EventGenerator generator(window.get());
generator.MoveMouseToInHost(50, 50);
ASSERT_EQ(1U, GetTestWindowTreeClient()->input_events().size());
EXPECT_EQ(ui::EventType::ET_POINTER_MOVED,
GetTestWindowTreeClient()->PopInputEvent().event->type());
// Check that WindowTree actually sets the cursor.
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(window->GetRootWindow());
const ui::CursorData help_cursor(ui::CursorType::kHelp);
GetWindowTreeTestHelper()->SetCursor(window.get(), help_cursor);
EXPECT_EQ(ui::CursorType::kHelp,
window->delegate()->GetCursor({}).native_type());
EXPECT_EQ(ui::CursorType::kHelp, cursor_client->GetCursor().native_type());
// If the mouse is not over the host, then SetCursor won't update the actual
// cursor (i.e. the CursorClient).
generator.MoveMouseToInHost(500, 500);
const ui::CursorData not_allowed_cursor(ui::CursorType::kNotAllowed);
GetWindowTreeTestHelper()->SetCursor(window.get(), not_allowed_cursor);
EXPECT_EQ(ui::CursorType::kNotAllowed,
window->delegate()->GetCursor({}).native_type());
EXPECT_NE(ui::CursorType::kNotAllowed,
cursor_client->GetCursor().native_type());
}
TEST_F(CursorTest, Embedded) {
// Create a window to hold an embedding and set its cursor.
aura::Window* embed_root = GetWindowTreeTestHelper()->NewWindow();
ui::ws2::TestWindowTreeClient test_client;
GetWindowTreeTestHelper()->Embed(embed_root, nullptr, &test_client, 0);
const ui::CursorData help_cursor(ui::CursorType::kHelp);
GetWindowTreeTestHelper()->SetCursor(embed_root, help_cursor);
// Since the window isn't visible, the actual cursor shouldn't have changed.
EXPECT_FALSE(embed_root->IsVisible());
EXPECT_NE(ui::CursorType::kHelp,
ash::Shell::Get()->cursor_manager()->GetCursor().native_type());
// Create a top level window and put the embed root in it.
std::unique_ptr<aura::Window> toplevel =
CreateTestWindow(gfx::Rect(0, 0, 100, 100));
toplevel->AddChild(embed_root);
embed_root->SetBounds(toplevel->GetTargetBounds());
embed_root->Show();
EXPECT_TRUE(embed_root->IsVisible());
// Now put the cursor over it and the previously set cursor should be used.
ui::test::EventGenerator generator(toplevel.get());
generator.MoveMouseToInHost(50, 50);
EXPECT_EQ(ui::CursorType::kHelp,
ash::Shell::Get()->cursor_manager()->GetCursor().native_type());
// Setting to a new cursor should also immediately update the actual cursor.
const ui::CursorData not_allowed_cursor(ui::CursorType::kNotAllowed);
GetWindowTreeTestHelper()->SetCursor(embed_root, not_allowed_cursor);
EXPECT_EQ(ui::CursorType::kNotAllowed,
ash::Shell::Get()->cursor_manager()->GetCursor().native_type());
}
} // namespace ash
...@@ -190,7 +190,7 @@ void AshTestBase::TearDown() { ...@@ -190,7 +190,7 @@ void AshTestBase::TearDown() {
// These depend upon WindowService, which is owned by Shell, so they must // These depend upon WindowService, which is owned by Shell, so they must
// be destroyed before the Shell (owned by AshTestHelper). // be destroyed before the Shell (owned by AshTestHelper).
window_tree_test_helper.reset(); window_tree_test_helper_.reset();
window_tree_.reset(); window_tree_.reset();
// Flush the message loop to finish pending release tasks. // Flush the message loop to finish pending release tasks.
...@@ -545,7 +545,7 @@ display::Display AshTestBase::GetSecondaryDisplay() { ...@@ -545,7 +545,7 @@ display::Display AshTestBase::GetSecondaryDisplay() {
ui::ws2::WindowTreeTestHelper* AshTestBase::GetWindowTreeTestHelper() { ui::ws2::WindowTreeTestHelper* AshTestBase::GetWindowTreeTestHelper() {
CreateWindowTreeIfNecessary(); CreateWindowTreeIfNecessary();
return window_tree_test_helper.get(); return window_tree_test_helper_.get();
} }
ui::ws2::TestWindowTreeClient* AshTestBase::GetTestWindowTreeClient() { ui::ws2::TestWindowTreeClient* AshTestBase::GetTestWindowTreeClient() {
...@@ -582,7 +582,7 @@ void AshTestBase::CreateWindowTreeIfNecessary() { ...@@ -582,7 +582,7 @@ void AshTestBase::CreateWindowTreeIfNecessary() {
Shell::Get()->window_service_owner()->window_service()->CreateWindowTree( Shell::Get()->window_service_owner()->window_service()->CreateWindowTree(
window_tree_client_.get()); window_tree_client_.get());
window_tree_->InitFromFactory(); window_tree_->InitFromFactory();
window_tree_test_helper = window_tree_test_helper_ =
std::make_unique<ui::ws2::WindowTreeTestHelper>(window_tree_.get()); std::make_unique<ui::ws2::WindowTreeTestHelper>(window_tree_.get());
} }
......
...@@ -273,7 +273,7 @@ class AshTestBase : public testing::Test, ...@@ -273,7 +273,7 @@ class AshTestBase : public testing::Test,
std::unique_ptr<ui::ws2::TestWindowTreeClient> window_tree_client_; std::unique_ptr<ui::ws2::TestWindowTreeClient> window_tree_client_;
std::unique_ptr<ui::ws2::WindowTree> window_tree_; std::unique_ptr<ui::ws2::WindowTree> window_tree_;
std::unique_ptr<ui::ws2::WindowTreeTestHelper> window_tree_test_helper; std::unique_ptr<ui::ws2::WindowTreeTestHelper> window_tree_test_helper_;
DISALLOW_COPY_AND_ASSIGN(AshTestBase); DISALLOW_COPY_AND_ASSIGN(AshTestBase);
}; };
......
...@@ -192,6 +192,8 @@ class WmNativeWidgetAura : public views::NativeWidgetAura { ...@@ -192,6 +192,8 @@ class WmNativeWidgetAura : public views::NativeWidgetAura {
custom_frame_view_->SetHeaderHeight({height}); custom_frame_view_->SetHeaderHeight({height});
} }
void set_cursor(const ui::Cursor& cursor) { cursor_ = cursor; }
// views::NativeWidgetAura: // views::NativeWidgetAura:
views::NonClientFrameView* CreateNonClientFrameView() override { views::NonClientFrameView* CreateNonClientFrameView() override {
if (window_manager_client_) { if (window_manager_client_) {
...@@ -225,6 +227,10 @@ class WmNativeWidgetAura : public views::NativeWidgetAura { ...@@ -225,6 +227,10 @@ class WmNativeWidgetAura : public views::NativeWidgetAura {
return custom_frame_view_; return custom_frame_view_;
} }
gfx::NativeCursor GetCursor(const gfx::Point& point) override {
return cursor_;
}
private: private:
const bool remove_standard_frame_; const bool remove_standard_frame_;
const bool enable_immersive_; const bool enable_immersive_;
...@@ -242,6 +248,11 @@ class WmNativeWidgetAura : public views::NativeWidgetAura { ...@@ -242,6 +248,11 @@ class WmNativeWidgetAura : public views::NativeWidgetAura {
// by the Widget's view hierarchy (e.g. it's a child of Widget's root View). // by the Widget's view hierarchy (e.g. it's a child of Widget's root View).
CustomFrameViewAsh* custom_frame_view_ = nullptr; CustomFrameViewAsh* custom_frame_view_ = nullptr;
// The cursor for this widget. CompoundEventFilter will retrieve this cursor
// via GetCursor and update the CursorManager's active cursor as appropriate
// (i.e. when the mouse pointer is over this widget).
ui::Cursor cursor_;
DISALLOW_COPY_AND_ASSIGN(WmNativeWidgetAura); DISALLOW_COPY_AND_ASSIGN(WmNativeWidgetAura);
}; };
...@@ -367,6 +378,11 @@ void NonClientFrameController::SetClientArea( ...@@ -367,6 +378,11 @@ void NonClientFrameController::SetClientArea(
->SetHeaderHeight(insets.top()); ->SetHeaderHeight(insets.top());
} }
void NonClientFrameController::StoreCursor(const ui::Cursor& cursor) {
static_cast<WmNativeWidgetAura*>(widget_->native_widget())
->set_cursor(cursor);
}
NonClientFrameController::~NonClientFrameController() { NonClientFrameController::~NonClientFrameController() {
aura::client::GetTransientWindowClient()->RemoveObserver(this); aura::client::GetTransientWindowClient()->RemoveObserver(this);
if (window_) if (window_)
......
...@@ -80,6 +80,11 @@ class ASH_EXPORT NonClientFrameController ...@@ -80,6 +80,11 @@ class ASH_EXPORT NonClientFrameController
void SetClientArea(const gfx::Insets& insets, void SetClientArea(const gfx::Insets& insets,
const std::vector<gfx::Rect>& additional_client_areas); const std::vector<gfx::Rect>& additional_client_areas);
// Stores |cursor| as this window's active cursor. It does not actually update
// the active cursor by calling into CursorManager, but will update the return
// value provided by the associated window's aura::WindowDelegate::GetCursor.
void StoreCursor(const ui::Cursor& cursor);
private: private:
~NonClientFrameController() override; ~NonClientFrameController() override;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "ash/accelerators/accelerator_controller.h" #include "ash/accelerators/accelerator_controller.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/container_finder.h" #include "ash/wm/container_finder.h"
#include "ash/wm/non_client_frame_controller.h"
#include "ash/wm/top_level_window_factory.h" #include "ash/wm/top_level_window_factory.h"
#include "ash/wm/toplevel_window_event_handler.h" #include "ash/wm/toplevel_window_event_handler.h"
#include "base/bind.h" #include "base/bind.h"
...@@ -19,6 +20,8 @@ ...@@ -19,6 +20,8 @@
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/accelerators/accelerator.h" #include "ui/base/accelerators/accelerator.h"
#include "ui/base/hit_test.h" #include "ui/base/hit_test.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/compound_event_filter.h"
namespace ash { namespace ash {
namespace { namespace {
...@@ -75,6 +78,17 @@ void WindowServiceDelegateImpl::OnUnhandledKeyEvent( ...@@ -75,6 +78,17 @@ void WindowServiceDelegateImpl::OnUnhandledKeyEvent(
Shell::Get()->accelerator_controller()->Process(ui::Accelerator(key_event)); Shell::Get()->accelerator_controller()->Process(ui::Accelerator(key_event));
} }
bool WindowServiceDelegateImpl::StoreAndSetCursor(aura::Window* window,
ui::Cursor cursor) {
auto* frame = NonClientFrameController::Get(window);
if (frame)
frame->StoreCursor(cursor);
ash::Shell::Get()->env_filter()->SetCursorForWindow(window, cursor);
return !!frame;
}
void WindowServiceDelegateImpl::RunWindowMoveLoop( void WindowServiceDelegateImpl::RunWindowMoveLoop(
aura::Window* window, aura::Window* window,
ui::mojom::MoveLoopSource source, ui::mojom::MoveLoopSource source,
......
...@@ -22,6 +22,7 @@ class WindowServiceDelegateImpl : public ui::ws2::WindowServiceDelegate { ...@@ -22,6 +22,7 @@ class WindowServiceDelegateImpl : public ui::ws2::WindowServiceDelegate {
const base::flat_map<std::string, std::vector<uint8_t>>& properties) const base::flat_map<std::string, std::vector<uint8_t>>& properties)
override; override;
void OnUnhandledKeyEvent(const ui::KeyEvent& key_event) override; void OnUnhandledKeyEvent(const ui::KeyEvent& key_event) override;
bool StoreAndSetCursor(aura::Window* window, ui::Cursor cursor) override;
void RunWindowMoveLoop(aura::Window* window, void RunWindowMoveLoop(aura::Window* window,
ui::mojom::MoveLoopSource source, ui::mojom::MoveLoopSource source,
const gfx::Point& cursor, const gfx::Point& cursor,
......
...@@ -459,6 +459,10 @@ void ServerWindow::SetCaptureOwner(WindowTree* owner) { ...@@ -459,6 +459,10 @@ void ServerWindow::SetCaptureOwner(WindowTree* owner) {
->OnCaptureOwnerChanged(); ->OnCaptureOwnerChanged();
} }
void ServerWindow::StoreCursor(const ui::Cursor& cursor) {
cursor_ = cursor;
}
bool ServerWindow::DoesOwnerInterceptEvents() const { bool ServerWindow::DoesOwnerInterceptEvents() const {
return embedding_ && embedding_->embedding_tree_intercepts_events(); return embedding_ && embedding_->embedding_tree_intercepts_events();
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/frame_sink_id.h"
#include "services/ui/ws2/ids.h" #include "services/ui/ws2/ids.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "ui/base/cursor/cursor.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
...@@ -79,6 +80,11 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) ServerWindow { ...@@ -79,6 +80,11 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) ServerWindow {
void set_focus_owner(WindowTree* owner) { focus_owner_ = owner; } void set_focus_owner(WindowTree* owner) { focus_owner_ = owner; }
WindowTree* focus_owner() const { return focus_owner_; } WindowTree* focus_owner() const { return focus_owner_; }
// Save |cursor| in |cursor_|. Since this does not update the active cursor,
// and to avoid confusion, the function is not called set_cursor().
void StoreCursor(const ui::Cursor& cursor);
const ui::Cursor& cursor() const { return cursor_; }
// Returns true if the window has an embedding, and the owning client // Returns true if the window has an embedding, and the owning client
// intercepts events that would normally target descendants. // intercepts events that would normally target descendants.
bool DoesOwnerInterceptEvents() const; bool DoesOwnerInterceptEvents() const;
...@@ -167,6 +173,10 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) ServerWindow { ...@@ -167,6 +173,10 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) ServerWindow {
std::unique_ptr<DragDropDelegate> drag_drop_delegate_; std::unique_ptr<DragDropDelegate> drag_drop_delegate_;
// The last cursor that the client has requested. This is only set for embed
// roots. For top level windows, see WmNativeWidgetAura.
ui::Cursor cursor_;
DISALLOW_COPY_AND_ASSIGN(ServerWindow); DISALLOW_COPY_AND_ASSIGN(ServerWindow);
}; };
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "services/ui/ws2/window_delegate_impl.h" #include "services/ui/ws2/window_delegate_impl.h"
#include "services/ui/ws2/server_window.h"
#include "services/ui/ws2/window_properties.h" #include "services/ui/ws2/window_properties.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor.h"
...@@ -27,6 +28,24 @@ void WindowDelegateImpl::OnBoundsChanged(const gfx::Rect& old_bounds, ...@@ -27,6 +28,24 @@ void WindowDelegateImpl::OnBoundsChanged(const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {} const gfx::Rect& new_bounds) {}
gfx::NativeCursor WindowDelegateImpl::GetCursor(const gfx::Point& point) { gfx::NativeCursor WindowDelegateImpl::GetCursor(const gfx::Point& point) {
// Find the cursor of the embed root for an embedded Window, or the toplevel
// if it's not an embedded client. This is done to match the behavior of Aura,
// which sets the cursor on the root.
for (ServerWindow* server_window = ServerWindow::GetMayBeNull(window_);
server_window; server_window = ServerWindow::GetMayBeNull(
server_window->window()->parent())) {
if (server_window->IsTopLevel()) {
gfx::Point toplevel_point = point;
aura::Window::ConvertPointToTarget(window_, server_window->window(),
&toplevel_point);
return server_window->window()->delegate()->GetCursor(toplevel_point);
}
if (server_window->HasEmbedding())
return server_window->cursor();
}
NOTREACHED();
return gfx::kNullCursor; return gfx::kNullCursor;
} }
......
...@@ -7,6 +7,11 @@ ...@@ -7,6 +7,11 @@
namespace ui { namespace ui {
namespace ws2 { namespace ws2 {
bool WindowServiceDelegate::StoreAndSetCursor(aura::Window* window,
ui::Cursor cursor) {
return false;
}
void WindowServiceDelegate::RunWindowMoveLoop(aura::Window* window, void WindowServiceDelegate::RunWindowMoveLoop(aura::Window* window,
mojom::MoveLoopSource source, mojom::MoveLoopSource source,
const gfx::Point& cursor, const gfx::Point& cursor,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/component_export.h" #include "base/component_export.h"
#include "base/containers/flat_map.h" #include "base/containers/flat_map.h"
#include "services/ui/public/interfaces/window_tree_constants.mojom.h" #include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "ui/base/cursor/cursor.h"
namespace aura { namespace aura {
class PropertyConverter; class PropertyConverter;
...@@ -48,6 +49,12 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowServiceDelegate { ...@@ -48,6 +49,12 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowServiceDelegate {
// Called for KeyEvents the client does not handle. // Called for KeyEvents the client does not handle.
virtual void OnUnhandledKeyEvent(const KeyEvent& key_event) {} virtual void OnUnhandledKeyEvent(const KeyEvent& key_event) {}
// Sets the cursor for |window| to |cursor|. This will immediately change the
// actual on-screen cursor if the pointer is hovered over |window|. Also store
// |cursor| on the widget for |window| if there is one. The return value
// indicates whether the cursor was stored for |window|.
virtual bool StoreAndSetCursor(aura::Window* window, ui::Cursor cursor);
// Called to start a move operation on |window|. When done, |callback| should // Called to start a move operation on |window|. When done, |callback| should
// be run with the result (true if the move was successful). If a move is not // be run with the result (true if the move was successful). If a move is not
// allowed, the delegate should run |callback| immediately. // allowed, the delegate should run |callback| immediately.
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_observer.h" #include "ui/aura/window_observer.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/cursor.h"
#include "ui/compositor/layer.h" #include "ui/compositor/layer.h"
#include "ui/compositor/layer_type.h" #include "ui/compositor/layer_type.h"
#include "ui/display/display.h" #include "ui/display/display.h"
...@@ -888,6 +889,40 @@ bool WindowTree::SetFocusImpl(const ClientWindowId& window_id) { ...@@ -888,6 +889,40 @@ bool WindowTree::SetFocusImpl(const ClientWindowId& window_id) {
return focus_handler_.SetFocus(GetWindowByClientId(window_id)); return focus_handler_.SetFocus(GetWindowByClientId(window_id));
} }
bool WindowTree::SetCursorImpl(const ClientWindowId& window_id,
ui::CursorData cursor) {
aura::Window* window = GetWindowByClientId(window_id);
if (!window) {
DVLOG(1) << "SetCursor failed (no window)";
return false;
}
if (!IsClientCreatedWindow(window) && !IsClientRootWindow(window)) {
DVLOG(1) << "SerCursor failed (access denied)";
return false;
}
auto* server_window = ServerWindow::GetMayBeNull(window);
// Convert from CursorData to Cursor. TODO(estade): remove this conversion.
// See class level comment on CursorData. Also support kCustom, i.e. image
// cursors.
ui::Cursor old_cursor_type(cursor.cursor_type());
if (cursor.cursor_type() == ui::CursorType::kCustom)
NOTIMPLEMENTED_LOG_ONCE();
// Ask our delegate to set the cursor. This will save the cursor for toplevels
// and also update the active cursor if appropriate (i.e. if |window| is the
// last to have set the cursor/is currently hovered).
if (!window_service_->delegate()->StoreAndSetCursor(window,
old_cursor_type)) {
// Store the cursor on ServerWindow. This will later be accessed by the
// WindowDelegate for non-toplevels, i.e. WindowDelegateImpl.
server_window->StoreCursor(old_cursor_type);
}
return true;
}
bool WindowTree::StackAboveImpl(const ClientWindowId& above_window_id, bool WindowTree::StackAboveImpl(const ClientWindowId& above_window_id,
const ClientWindowId& below_window_id) { const ClientWindowId& below_window_id) {
DVLOG(3) << "StackAbove above_window_id=" << above_window_id DVLOG(3) << "StackAbove above_window_id=" << above_window_id
...@@ -1363,9 +1398,11 @@ void WindowTree::SetCanFocus(Id transport_window_id, bool can_focus) { ...@@ -1363,9 +1398,11 @@ void WindowTree::SetCanFocus(Id transport_window_id, bool can_focus) {
} }
void WindowTree::SetCursor(uint32_t change_id, void WindowTree::SetCursor(uint32_t change_id,
Id window_id, Id transport_window_id,
ui::CursorData cursor) { ui::CursorData cursor) {
NOTIMPLEMENTED_LOG_ONCE(); window_tree_client_->OnChangeCompleted(
change_id,
SetCursorImpl(MakeClientWindowId(transport_window_id), cursor));
} }
void WindowTree::SetWindowTextInputState(Id window_id, void WindowTree::SetWindowTextInputState(Id window_id,
......
...@@ -256,6 +256,7 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowTree ...@@ -256,6 +256,7 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowTree
mojom::OrderDirection direction); mojom::OrderDirection direction);
std::vector<aura::Window*> GetWindowTreeImpl(const ClientWindowId& window_id); std::vector<aura::Window*> GetWindowTreeImpl(const ClientWindowId& window_id);
bool SetFocusImpl(const ClientWindowId& window_id); bool SetFocusImpl(const ClientWindowId& window_id);
bool SetCursorImpl(const ClientWindowId& window_id, ui::CursorData cursor);
bool StackAboveImpl(const ClientWindowId& above_window_id, bool StackAboveImpl(const ClientWindowId& above_window_id,
const ClientWindowId& below_window_id); const ClientWindowId& below_window_id);
bool StackAtTopImpl(const ClientWindowId& window_id); bool StackAtTopImpl(const ClientWindowId& window_id);
...@@ -354,7 +355,7 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowTree ...@@ -354,7 +355,7 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowTree
void SetFocus(uint32_t change_id, Id transport_window_id) override; void SetFocus(uint32_t change_id, Id transport_window_id) override;
void SetCanFocus(Id transport_window_id, bool can_focus) override; void SetCanFocus(Id transport_window_id, bool can_focus) override;
void SetCursor(uint32_t change_id, void SetCursor(uint32_t change_id,
Id window_id, Id transport_window_id,
ui::CursorData cursor) override; ui::CursorData cursor) override;
void SetWindowTextInputState(Id window_id, void SetWindowTextInputState(Id window_id,
::ui::mojom::TextInputStatePtr state) override; ::ui::mojom::TextInputStatePtr state) override;
......
...@@ -151,6 +151,11 @@ void WindowTreeTestHelper::SetCanFocus(aura::Window* window, bool can_focus) { ...@@ -151,6 +151,11 @@ void WindowTreeTestHelper::SetCanFocus(aura::Window* window, bool can_focus) {
can_focus); can_focus);
} }
void WindowTreeTestHelper::SetCursor(aura::Window* window,
ui::CursorData cursor) {
window_tree_->SetCursorImpl(ClientWindowIdForWindow(window), cursor);
}
void WindowTreeTestHelper::DestroyEmbedding(Embedding* embedding) { void WindowTreeTestHelper::DestroyEmbedding(Embedding* embedding) {
// Triggers WindowTree deleting the Embedding. // Triggers WindowTree deleting the Embedding.
window_tree_->OnEmbeddedClientConnectionLost(embedding); window_tree_->OnEmbeddedClientConnectionLost(embedding);
......
...@@ -91,6 +91,7 @@ class WindowTreeTestHelper { ...@@ -91,6 +91,7 @@ class WindowTreeTestHelper {
mojom::EventTargetingPolicy policy); mojom::EventTargetingPolicy policy);
bool SetFocus(aura::Window* window); bool SetFocus(aura::Window* window);
void SetCanFocus(aura::Window* window, bool can_focus); void SetCanFocus(aura::Window* window, bool can_focus);
void SetCursor(aura::Window* window, ui::CursorData cursor);
void OnWindowInputEventAck(uint32_t event_id, mojom::EventResult result); void OnWindowInputEventAck(uint32_t event_id, mojom::EventResult result);
bool StackAbove(aura::Window* above_window, aura::Window* below_window); bool StackAbove(aura::Window* above_window, aura::Window* below_window);
bool StackAtTop(aura::Window* window); bool StackAtTop(aura::Window* window);
......
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
-AppListPresenterDelegateTest.TapAppListWithVirtualKeyboardDismissesVirtualKeyboard/1 -AppListPresenterDelegateTest.TapAppListWithVirtualKeyboardDismissesVirtualKeyboard/1
-AppListPresenterDelegateTest.WhitespaceQuery -AppListPresenterDelegateTest.WhitespaceQuery
# These tests exercise the WindowService, which is no longer applicable to mash.
-CursorTest.*
# TODO: CursorManagerTestApi. http://crbug.com/780637 # TODO: CursorManagerTestApi. http://crbug.com/780637
-CursorWindowControllerTest.DSF -CursorWindowControllerTest.DSF
-CursorWindowControllerTest.MoveToDifferentDisplay -CursorWindowControllerTest.MoveToDifferentDisplay
......
...@@ -81,6 +81,28 @@ void CompoundEventFilter::RemoveHandler(ui::EventHandler* handler) { ...@@ -81,6 +81,28 @@ void CompoundEventFilter::RemoveHandler(ui::EventHandler* handler) {
handlers_.RemoveObserver(handler); handlers_.RemoveObserver(handler);
} }
void CompoundEventFilter::SetCursorForWindow(aura::Window* window,
const ui::Cursor& cursor) {
if (last_window_that_provided_cursor_.windows().empty())
return;
aura::Window* last_window = last_window_that_provided_cursor_.windows()[0];
// Determine if the window hierarchies match, i.e. if |window| is an ancestor
// or descendent of |last_window_that_provided_cursor_|.
if (!window->Contains(last_window) && !last_window->Contains(window))
return;
aura::Window* root_window = window->GetRootWindow();
if (!root_window)
return;
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root_window);
if (cursor_client)
cursor_client->SetCursor(cursor);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// CompoundEventFilter, private: // CompoundEventFilter, private:
...@@ -94,6 +116,9 @@ void CompoundEventFilter::UpdateCursor(aura::Window* target, ...@@ -94,6 +116,9 @@ void CompoundEventFilter::UpdateCursor(aura::Window* target,
if (drag_drop_client && drag_drop_client->IsDragDropInProgress()) if (drag_drop_client && drag_drop_client->IsDragDropInProgress())
return; return;
last_window_that_provided_cursor_.RemoveAll();
last_window_that_provided_cursor_.Add(target);
aura::client::CursorClient* cursor_client = aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root_window); aura::client::GetCursorClient(root_window);
if (cursor_client) { if (cursor_client) {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "ui/aura/window_tracker.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/event_handler.h" #include "ui/events/event_handler.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
...@@ -47,6 +48,13 @@ class WM_CORE_EXPORT CompoundEventFilter : public ui::EventHandler { ...@@ -47,6 +48,13 @@ class WM_CORE_EXPORT CompoundEventFilter : public ui::EventHandler {
void AddHandler(ui::EventHandler* filter); void AddHandler(ui::EventHandler* filter);
void RemoveHandler(ui::EventHandler* filter); void RemoveHandler(ui::EventHandler* filter);
// If |window| is part of the same window hierarchy as the last window to have
// provided the cursor (i.e. for which UpdateCursor was called), updates the
// cursor manager with |cursor|. Otherwise, this call does nothing. This means
// calling SetCursorForWindow on an arbitrary window that the pointer is not
// over will do nothing.
void SetCursorForWindow(aura::Window* window, const ui::Cursor& cursor);
private: private:
// Updates the cursor if the target provides a custom one, and provides // Updates the cursor if the target provides a custom one, and provides
// default resize cursors for window edges. // default resize cursors for window edges.
...@@ -77,6 +85,9 @@ class WM_CORE_EXPORT CompoundEventFilter : public ui::EventHandler { ...@@ -77,6 +85,9 @@ class WM_CORE_EXPORT CompoundEventFilter : public ui::EventHandler {
// Additional pre-target event handlers. // Additional pre-target event handlers.
base::ObserverList<ui::EventHandler, true> handlers_; base::ObserverList<ui::EventHandler, true> handlers_;
// Holds the last window that was used to update CursorClient in UpdateCursor.
aura::WindowTracker last_window_that_provided_cursor_;
DISALLOW_COPY_AND_ASSIGN(CompoundEventFilter); DISALLOW_COPY_AND_ASSIGN(CompoundEventFilter);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment