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 @@
#include "services/ui/ws2/window_service_client.h"
#include <algorithm>
#include "base/auto_reset.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/surface_info.h"
......@@ -69,22 +71,6 @@ WindowServiceClient::WindowServiceClient(WindowService* window_service,
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() {
wm::CaptureController::Get()->RemoveObserver(this);
......@@ -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,
const Event& event) {
uint32_t event_id = kDefaultEventId;
......@@ -346,6 +348,26 @@ void WindowServiceClient::RemoveWindowFromKnownWindows(aura::Window* window,
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(
const ClientWindowId& id) const {
return client_window_id_to_window_map_.count(id) == 0u &&
......@@ -375,24 +397,9 @@ ClientWindowId WindowServiceClient::MakeClientWindowId(
ClientWindowIdFromTransportId(transport_window_id));
}
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::IsLocalSurfaceIdAssignedByClient(
aura::Window* window) {
return !IsTopLevel(window) && IsClientCreatedWindow(window);
}
std::vector<mojom::WindowDataPtr> WindowServiceClient::WindowsToWindowDatas(
......@@ -686,6 +693,37 @@ bool WindowServiceClient::SetWindowPropertyImpl(
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,
float opacity) {
aura::Window* window = GetWindowByClientId(window_id);
......@@ -702,11 +740,6 @@ bool WindowServiceClient::SetWindowOpacityImpl(const ClientWindowId& window_id,
return false;
}
bool WindowServiceClient::IsLocalSurfaceIdAssignedByClient(
aura::Window* window) {
return !IsTopLevel(window) && IsClientCreatedWindow(window);
}
bool WindowServiceClient::SetWindowBoundsImpl(
const ClientWindowId& window_id,
const gfx::Rect& bounds,
......@@ -772,34 +805,27 @@ bool WindowServiceClient::SetWindowBoundsImpl(
return false;
}
bool WindowServiceClient::EmbedImpl(
bool WindowServiceClient::ReorderWindowImpl(
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;
const ClientWindowId& relative_window_id,
mojom::OrderDirection direction) {
DVLOG(3) << "ReorderWindow window_id=" << window_id
<< " relative_window_id=" << relative_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)";
aura::Window* relative_window = GetWindowByClientId(relative_window_id);
// Only allow reordering of windows the client created, and windows that are
// siblings.
if (!IsClientCreatedWindow(window) ||
!IsClientCreatedWindow(relative_window) ||
window->parent() != relative_window->parent() || !window->parent() ||
!IsClientCreatedWindow(window->parent())) {
DVLOG(1) << "ReorderWindow failed (invalid windows)";
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));
if (direction == mojom::OrderDirection::ABOVE)
window->parent()->StackChildAbove(window, relative_window);
else
window->parent()->StackChildBelow(window, relative_window);
return true;
}
......@@ -1136,10 +1162,13 @@ void WindowServiceClient::SetChildModalParent(uint32_t change_id,
}
void WindowServiceClient::ReorderWindow(uint32_t change_id,
Id window_id,
Id relative_window_id,
::ui::mojom::OrderDirection direction) {
NOTIMPLEMENTED_LOG_ONCE();
Id transport_window_id,
Id transport_relative_window_id,
mojom::OrderDirection direction) {
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,
......
......@@ -230,6 +230,9 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowServiceClient
const ClientWindowId& window_id,
const gfx::Rect& bounds,
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);
bool SetFocusImpl(const ClientWindowId& window_id);
bool StackAtTopImpl(const ClientWindowId& window_id);
......@@ -308,9 +311,9 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowServiceClient
Id window_id,
Id parent_window_id) override;
void ReorderWindow(uint32_t change_id,
Id window_id,
Id relative_window_id,
::ui::mojom::OrderDirection direction) override;
Id transport_window_id,
Id transport_relative_window_id,
mojom::OrderDirection direction) override;
void GetWindowTree(Id window_id, GetWindowTreeCallback callback) override;
void Embed(Id transport_window_id,
mojom::WindowTreeClientPtr client_ptr,
......
......@@ -69,6 +69,15 @@ bool WindowServiceClientTestHelper::ReleaseCapture(aura::Window* 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(
aura::Window* window,
const gfx::Rect& bounds,
......
......@@ -59,6 +59,9 @@ class WindowServiceClientTestHelper {
const base::flat_map<std::string, std::vector<uint8_t>>& properties);
bool SetCapture(aura::Window* window);
bool ReleaseCapture(aura::Window* window);
bool ReorderWindow(aura::Window* window,
aura::Window* relative_window,
mojom::OrderDirection direction);
bool SetWindowBounds(
aura::Window* window,
const gfx::Rect& bounds,
......
......@@ -1021,6 +1021,54 @@ TEST(WindowServiceClientTest, OnUnhandledKeyEvent) {
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 ws2
} // 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