Commit f68053f5 authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

chromeos: implements ReorderWindow for ws2

BUG=837700
TEST=covered by tests

Change-Id: Ie188a430a9596a520e0643083d89aaf4f09f4215
Reviewed-on: https://chromium-review.googlesource.com/1089112
Commit-Queue: Scott Violet <sky@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#564966}
parent 3b86c1f8
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "services/ui/ws2/window_service_client.h" #include "services/ui/ws2/window_service_client.h"
#include <algorithm>
#include "base/auto_reset.h" #include "base/auto_reset.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/surface_info.h" #include "components/viz/common/surfaces/surface_info.h"
...@@ -69,22 +71,6 @@ WindowServiceClient::WindowServiceClient(WindowService* window_service, ...@@ -69,22 +71,6 @@ WindowServiceClient::WindowServiceClient(WindowService* window_service,
wm::CaptureController::Get()->AddObserver(this); wm::CaptureController::Get()->AddObserver(this);
} }
void WindowServiceClient::InitForEmbed(aura::Window* root,
mojom::WindowTreePtr window_tree_ptr) {
// Force ClientWindow to be created for |root|.
ClientWindow* client_window =
window_service_->GetClientWindowForWindowCreateIfNecessary(root);
const ClientWindowId client_window_id = client_window->frame_sink_id();
AddWindowToKnownWindows(root, client_window_id);
const bool is_top_level = false;
CreateClientRoot(root, is_top_level, std::move(window_tree_ptr));
}
void WindowServiceClient::InitFromFactory() {
connection_type_ = ConnectionType::kOther;
}
WindowServiceClient::~WindowServiceClient() { WindowServiceClient::~WindowServiceClient() {
wm::CaptureController::Get()->RemoveObserver(this); wm::CaptureController::Get()->RemoveObserver(this);
...@@ -104,6 +90,22 @@ WindowServiceClient::~WindowServiceClient() { ...@@ -104,6 +90,22 @@ WindowServiceClient::~WindowServiceClient() {
} }
} }
void WindowServiceClient::InitForEmbed(aura::Window* root,
mojom::WindowTreePtr window_tree_ptr) {
// Force ClientWindow to be created for |root|.
ClientWindow* client_window =
window_service_->GetClientWindowForWindowCreateIfNecessary(root);
const ClientWindowId client_window_id = client_window->frame_sink_id();
AddWindowToKnownWindows(root, client_window_id);
const bool is_top_level = false;
CreateClientRoot(root, is_top_level, std::move(window_tree_ptr));
}
void WindowServiceClient::InitFromFactory() {
connection_type_ = ConnectionType::kOther;
}
void WindowServiceClient::SendEventToClient(aura::Window* window, void WindowServiceClient::SendEventToClient(aura::Window* window,
const Event& event) { const Event& event) {
uint32_t event_id = kDefaultEventId; uint32_t event_id = kDefaultEventId;
...@@ -346,6 +348,26 @@ void WindowServiceClient::RemoveWindowFromKnownWindows(aura::Window* window, ...@@ -346,6 +348,26 @@ void WindowServiceClient::RemoveWindowFromKnownWindows(aura::Window* window,
window_to_client_window_id_map_.erase(iter); window_to_client_window_id_map_.erase(iter);
} }
void WindowServiceClient::RemoveWindowFromKnownWindowsRecursive(
aura::Window* window,
std::vector<aura::Window*>* created_windows) {
if (IsClientCreatedWindow(window)) {
// Stop iterating at windows created by this client. We assume the client
// will keep seeing any descendants.
if (created_windows)
created_windows->push_back(window);
return;
}
if (IsWindowKnown(window)) {
const bool delete_if_owned = true;
RemoveWindowFromKnownWindows(window, delete_if_owned);
}
for (aura::Window* child : window->children())
RemoveWindowFromKnownWindowsRecursive(child, created_windows);
}
bool WindowServiceClient::IsValidIdForNewWindow( bool WindowServiceClient::IsValidIdForNewWindow(
const ClientWindowId& id) const { const ClientWindowId& id) const {
return client_window_id_to_window_map_.count(id) == 0u && return client_window_id_to_window_map_.count(id) == 0u &&
...@@ -375,24 +397,9 @@ ClientWindowId WindowServiceClient::MakeClientWindowId( ...@@ -375,24 +397,9 @@ ClientWindowId WindowServiceClient::MakeClientWindowId(
ClientWindowIdFromTransportId(transport_window_id)); ClientWindowIdFromTransportId(transport_window_id));
} }
void WindowServiceClient::RemoveWindowFromKnownWindowsRecursive( bool WindowServiceClient::IsLocalSurfaceIdAssignedByClient(
aura::Window* window, aura::Window* window) {
std::vector<aura::Window*>* created_windows) { return !IsTopLevel(window) && IsClientCreatedWindow(window);
if (IsClientCreatedWindow(window)) {
// Stop iterating at windows created by this client. We assume the client
// will keep seeing any descendants.
if (created_windows)
created_windows->push_back(window);
return;
}
if (IsWindowKnown(window)) {
const bool delete_if_owned = true;
RemoveWindowFromKnownWindows(window, delete_if_owned);
}
for (aura::Window* child : window->children())
RemoveWindowFromKnownWindowsRecursive(child, created_windows);
} }
std::vector<mojom::WindowDataPtr> WindowServiceClient::WindowsToWindowDatas( std::vector<mojom::WindowDataPtr> WindowServiceClient::WindowsToWindowDatas(
...@@ -686,6 +693,37 @@ bool WindowServiceClient::SetWindowPropertyImpl( ...@@ -686,6 +693,37 @@ bool WindowServiceClient::SetWindowPropertyImpl(
return true; return true;
} }
bool WindowServiceClient::EmbedImpl(
const ClientWindowId& window_id,
mojom::WindowTreeClientPtr window_tree_client_ptr,
mojom::WindowTreeClient* window_tree_client,
uint32_t flags) {
DVLOG(3) << "Embed window_id=" << window_id;
aura::Window* window = GetWindowByClientId(window_id);
if (!window) {
DVLOG(1) << "Embed failed (no window)";
return false;
}
if (!IsClientCreatedWindow(window) || IsTopLevel(window)) {
DVLOG(1) << "Embed failed (access denied)";
return false;
}
const bool owner_intercept_events =
(flags & mojom::kEmbedFlagEmbedderInterceptsEvents) != 0;
std::unique_ptr<Embedding> embedding =
std::make_unique<Embedding>(this, window, owner_intercept_events);
embedding->Init(
window_service_, std::move(window_tree_client_ptr), window_tree_client,
base::BindOnce(&WindowServiceClient::OnEmbeddedClientConnectionLost,
base::Unretained(this), embedding.get()));
if (flags & mojom::kEmbedFlagEmbedderControlsVisibility)
embedding->embedded_client()->can_change_root_window_visibility_ = false;
ClientWindow::GetMayBeNull(window)->SetEmbedding(std::move(embedding));
return true;
}
bool WindowServiceClient::SetWindowOpacityImpl(const ClientWindowId& window_id, bool WindowServiceClient::SetWindowOpacityImpl(const ClientWindowId& window_id,
float opacity) { float opacity) {
aura::Window* window = GetWindowByClientId(window_id); aura::Window* window = GetWindowByClientId(window_id);
...@@ -702,11 +740,6 @@ bool WindowServiceClient::SetWindowOpacityImpl(const ClientWindowId& window_id, ...@@ -702,11 +740,6 @@ bool WindowServiceClient::SetWindowOpacityImpl(const ClientWindowId& window_id,
return false; return false;
} }
bool WindowServiceClient::IsLocalSurfaceIdAssignedByClient(
aura::Window* window) {
return !IsTopLevel(window) && IsClientCreatedWindow(window);
}
bool WindowServiceClient::SetWindowBoundsImpl( bool WindowServiceClient::SetWindowBoundsImpl(
const ClientWindowId& window_id, const ClientWindowId& window_id,
const gfx::Rect& bounds, const gfx::Rect& bounds,
...@@ -772,34 +805,27 @@ bool WindowServiceClient::SetWindowBoundsImpl( ...@@ -772,34 +805,27 @@ bool WindowServiceClient::SetWindowBoundsImpl(
return false; return false;
} }
bool WindowServiceClient::EmbedImpl( bool WindowServiceClient::ReorderWindowImpl(
const ClientWindowId& window_id, const ClientWindowId& window_id,
mojom::WindowTreeClientPtr window_tree_client_ptr, const ClientWindowId& relative_window_id,
mojom::WindowTreeClient* window_tree_client, mojom::OrderDirection direction) {
uint32_t flags) { DVLOG(3) << "ReorderWindow window_id=" << window_id
DVLOG(3) << "Embed window_id=" << window_id; << " relative_window_id=" << relative_window_id;
aura::Window* window = GetWindowByClientId(window_id); aura::Window* window = GetWindowByClientId(window_id);
if (!window) { aura::Window* relative_window = GetWindowByClientId(relative_window_id);
DVLOG(1) << "Embed failed (no window)"; // Only allow reordering of windows the client created, and windows that are
return false; // siblings.
} if (!IsClientCreatedWindow(window) ||
if (!IsClientCreatedWindow(window) || IsTopLevel(window)) { !IsClientCreatedWindow(relative_window) ||
DVLOG(1) << "Embed failed (access denied)"; window->parent() != relative_window->parent() || !window->parent() ||
!IsClientCreatedWindow(window->parent())) {
DVLOG(1) << "ReorderWindow failed (invalid windows)";
return false; return false;
} }
if (direction == mojom::OrderDirection::ABOVE)
const bool owner_intercept_events = window->parent()->StackChildAbove(window, relative_window);
(flags & mojom::kEmbedFlagEmbedderInterceptsEvents) != 0; else
std::unique_ptr<Embedding> embedding = window->parent()->StackChildBelow(window, relative_window);
std::make_unique<Embedding>(this, window, owner_intercept_events);
embedding->Init(
window_service_, std::move(window_tree_client_ptr), window_tree_client,
base::BindOnce(&WindowServiceClient::OnEmbeddedClientConnectionLost,
base::Unretained(this), embedding.get()));
if (flags & mojom::kEmbedFlagEmbedderControlsVisibility)
embedding->embedded_client()->can_change_root_window_visibility_ = false;
ClientWindow::GetMayBeNull(window)->SetEmbedding(std::move(embedding));
return true; return true;
} }
...@@ -1136,10 +1162,13 @@ void WindowServiceClient::SetChildModalParent(uint32_t change_id, ...@@ -1136,10 +1162,13 @@ void WindowServiceClient::SetChildModalParent(uint32_t change_id,
} }
void WindowServiceClient::ReorderWindow(uint32_t change_id, void WindowServiceClient::ReorderWindow(uint32_t change_id,
Id window_id, Id transport_window_id,
Id relative_window_id, Id transport_relative_window_id,
::ui::mojom::OrderDirection direction) { mojom::OrderDirection direction) {
NOTIMPLEMENTED_LOG_ONCE(); const bool result = ReorderWindowImpl(
MakeClientWindowId(transport_window_id),
MakeClientWindowId(transport_relative_window_id), direction);
window_tree_client_->OnChangeCompleted(change_id, result);
} }
void WindowServiceClient::GetWindowTree(Id window_id, void WindowServiceClient::GetWindowTree(Id window_id,
......
...@@ -230,6 +230,9 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowServiceClient ...@@ -230,6 +230,9 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowServiceClient
const ClientWindowId& window_id, const ClientWindowId& window_id,
const gfx::Rect& bounds, const gfx::Rect& bounds,
const base::Optional<viz::LocalSurfaceId>& local_surface_id); const base::Optional<viz::LocalSurfaceId>& local_surface_id);
bool ReorderWindowImpl(const ClientWindowId& window_id,
const ClientWindowId& relative_window_id,
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 StackAtTopImpl(const ClientWindowId& window_id); bool StackAtTopImpl(const ClientWindowId& window_id);
...@@ -308,9 +311,9 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowServiceClient ...@@ -308,9 +311,9 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowServiceClient
Id window_id, Id window_id,
Id parent_window_id) override; Id parent_window_id) override;
void ReorderWindow(uint32_t change_id, void ReorderWindow(uint32_t change_id,
Id window_id, Id transport_window_id,
Id relative_window_id, Id transport_relative_window_id,
::ui::mojom::OrderDirection direction) override; mojom::OrderDirection direction) override;
void GetWindowTree(Id window_id, GetWindowTreeCallback callback) override; void GetWindowTree(Id window_id, GetWindowTreeCallback callback) override;
void Embed(Id transport_window_id, void Embed(Id transport_window_id,
mojom::WindowTreeClientPtr client_ptr, mojom::WindowTreeClientPtr client_ptr,
......
...@@ -69,6 +69,15 @@ bool WindowServiceClientTestHelper::ReleaseCapture(aura::Window* window) { ...@@ -69,6 +69,15 @@ bool WindowServiceClientTestHelper::ReleaseCapture(aura::Window* window) {
ClientWindowIdForWindow(window)); ClientWindowIdForWindow(window));
} }
bool WindowServiceClientTestHelper::ReorderWindow(
aura::Window* window,
aura::Window* relative_window,
mojom::OrderDirection direction) {
return window_service_client_->ReorderWindowImpl(
ClientWindowIdForWindow(window), ClientWindowIdForWindow(relative_window),
direction);
}
bool WindowServiceClientTestHelper::SetWindowBounds( bool WindowServiceClientTestHelper::SetWindowBounds(
aura::Window* window, aura::Window* window,
const gfx::Rect& bounds, const gfx::Rect& bounds,
......
...@@ -59,6 +59,9 @@ class WindowServiceClientTestHelper { ...@@ -59,6 +59,9 @@ class WindowServiceClientTestHelper {
const base::flat_map<std::string, std::vector<uint8_t>>& properties); const base::flat_map<std::string, std::vector<uint8_t>>& properties);
bool SetCapture(aura::Window* window); bool SetCapture(aura::Window* window);
bool ReleaseCapture(aura::Window* window); bool ReleaseCapture(aura::Window* window);
bool ReorderWindow(aura::Window* window,
aura::Window* relative_window,
mojom::OrderDirection direction);
bool SetWindowBounds( bool SetWindowBounds(
aura::Window* window, aura::Window* window,
const gfx::Rect& bounds, const gfx::Rect& bounds,
......
...@@ -1021,6 +1021,54 @@ TEST(WindowServiceClientTest, OnUnhandledKeyEvent) { ...@@ -1021,6 +1021,54 @@ TEST(WindowServiceClientTest, OnUnhandledKeyEvent) {
EXPECT_TRUE(setup.delegate()->unhandled_key_events()->empty()); EXPECT_TRUE(setup.delegate()->unhandled_key_events()->empty());
} }
TEST(WindowServiceClientTest, ReorderWindow) {
// Create a top-level and two child windows.
WindowServiceTestSetup setup;
aura::Window* top_level = setup.client_test_helper()->NewTopLevelWindow();
ASSERT_TRUE(top_level);
aura::Window* window1 = setup.client_test_helper()->NewWindow();
ASSERT_TRUE(window1);
top_level->AddChild(window1);
aura::Window* window2 = setup.client_test_helper()->NewWindow();
ASSERT_TRUE(window2);
top_level->AddChild(window2);
// Reorder |window1| on top of |window2|.
EXPECT_TRUE(setup.client_test_helper()->ReorderWindow(
window1, window2, mojom::OrderDirection::ABOVE));
EXPECT_EQ(window2, top_level->children()[0]);
EXPECT_EQ(window1, top_level->children()[1]);
// Reorder |window2| on top of |window1|.
EXPECT_TRUE(setup.client_test_helper()->ReorderWindow(
window2, window1, mojom::OrderDirection::ABOVE));
EXPECT_EQ(window1, top_level->children()[0]);
EXPECT_EQ(window2, top_level->children()[1]);
// Repeat, but use the WindowTree interface, which should result in an ack.
setup.changes()->clear();
uint32_t change_id = 101;
setup.client_test_helper()->window_tree()->ReorderWindow(
change_id, setup.client_test_helper()->TransportIdForWindow(window1),
setup.client_test_helper()->TransportIdForWindow(window2),
mojom::OrderDirection::ABOVE);
EXPECT_EQ("ChangeCompleted id=101 success=true",
SingleChangeToDescription(*setup.changes()));
setup.changes()->clear();
// Supply invalid window ids, which should fail.
setup.client_test_helper()->window_tree()->ReorderWindow(
change_id, 0, 1, mojom::OrderDirection::ABOVE);
EXPECT_EQ("ChangeCompleted id=101 success=false",
SingleChangeToDescription(*setup.changes()));
// These calls should fail as the windows are not siblings.
EXPECT_FALSE(setup.client_test_helper()->ReorderWindow(
window1, top_level, mojom::OrderDirection::ABOVE));
EXPECT_FALSE(setup.client_test_helper()->ReorderWindow(
top_level, window2, mojom::OrderDirection::ABOVE));
}
} // namespace } // namespace
} // namespace ws2 } // namespace ws2
} // namespace ui } // namespace ui
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