| Index: services/ui/public/cpp/tests/window_tree_client_unittest.cc
|
| diff --git a/services/ui/public/cpp/tests/window_tree_client_unittest.cc b/services/ui/public/cpp/tests/window_tree_client_unittest.cc
|
| deleted file mode 100644
|
| index 1c4efc24f4526e33c2aa5d5b52d010cd0d4c2e90..0000000000000000000000000000000000000000
|
| --- a/services/ui/public/cpp/tests/window_tree_client_unittest.cc
|
| +++ /dev/null
|
| @@ -1,1090 +0,0 @@
|
| -// Copyright 2015 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 "services/ui/public/cpp/window_tree_client.h"
|
| -
|
| -#include <stdint.h>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/macros.h"
|
| -#include "services/ui/common/util.h"
|
| -#include "services/ui/public/cpp/input_event_handler.h"
|
| -#include "services/ui/public/cpp/property_type_converters.h"
|
| -#include "services/ui/public/cpp/tests/test_window.h"
|
| -#include "services/ui/public/cpp/tests/test_window_tree.h"
|
| -#include "services/ui/public/cpp/tests/window_tree_client_private.h"
|
| -#include "services/ui/public/cpp/window.h"
|
| -#include "services/ui/public/cpp/window_observer.h"
|
| -#include "services/ui/public/cpp/window_private.h"
|
| -#include "services/ui/public/cpp/window_property.h"
|
| -#include "services/ui/public/cpp/window_tracker.h"
|
| -#include "services/ui/public/cpp/window_tree_client_delegate.h"
|
| -#include "services/ui/public/cpp/window_tree_client_observer.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -#include "ui/display/test/test_screen.h"
|
| -#include "ui/events/event.h"
|
| -#include "ui/events/event_utils.h"
|
| -#include "ui/gfx/geometry/rect.h"
|
| -
|
| -namespace ui {
|
| -
|
| -namespace {
|
| -
|
| -void DoNothingWithEventResult(mojom::EventResult result) {}
|
| -
|
| -Id server_id(ui::Window* window) {
|
| - return WindowPrivate(window).server_id();
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -std::vector<uint8_t> Int32ToPropertyTransportValue(int32_t value) {
|
| - return mojo::ConvertTo<std::vector<uint8_t>>(value);
|
| -}
|
| -
|
| -class TestWindowTreeClientDelegate : public WindowTreeClientDelegate {
|
| - public:
|
| - TestWindowTreeClientDelegate() {}
|
| - ~TestWindowTreeClientDelegate() override {}
|
| -
|
| - ui::PointerEvent* last_event_observed() { return last_event_observed_.get(); }
|
| -
|
| - void Reset() { last_event_observed_.reset(); }
|
| -
|
| - // WindowTreeClientDelegate:
|
| - void OnEmbed(Window* root) override {}
|
| - void OnLostConnection(WindowTreeClient* client) override {}
|
| - void OnEmbedRootDestroyed(Window* root) override {}
|
| - void OnPointerEventObserved(const ui::PointerEvent& event,
|
| - Window* target) override {
|
| - last_event_observed_.reset(new ui::PointerEvent(event));
|
| - }
|
| -
|
| - private:
|
| - std::unique_ptr<ui::PointerEvent> last_event_observed_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(TestWindowTreeClientDelegate);
|
| -};
|
| -
|
| -class WindowTreeSetup {
|
| - public:
|
| - WindowTreeSetup() : tree_client_(&window_tree_delegate_, nullptr, nullptr) {
|
| - display::Screen::SetScreenInstance(&test_screen_);
|
| - WindowTreeClientPrivate(&tree_client_).OnEmbed(&window_tree_);
|
| - window_tree_.GetAndClearChangeId(nullptr);
|
| - }
|
| -
|
| - ~WindowTreeSetup() { display::Screen::SetScreenInstance(nullptr); }
|
| -
|
| - WindowTreeClient* client() {
|
| - return &tree_client_;
|
| - }
|
| -
|
| - mojom::WindowTreeClient* window_tree_client() {
|
| - return static_cast<mojom::WindowTreeClient*>(&tree_client_);
|
| - }
|
| -
|
| - TestWindowTree* window_tree() { return &window_tree_; }
|
| -
|
| - TestWindowTreeClientDelegate* window_tree_delegate() {
|
| - return &window_tree_delegate_;
|
| - }
|
| -
|
| - Window* GetFirstRoot() {
|
| - return client()->GetRoots().empty() ? nullptr
|
| - : *client()->GetRoots().begin();
|
| - }
|
| -
|
| - private:
|
| - TestWindowTree window_tree_;
|
| - TestWindowTreeClientDelegate window_tree_delegate_;
|
| - WindowTreeClient tree_client_;
|
| -
|
| - // Dummy screen required to be the screen instance.
|
| - display::test::TestScreen test_screen_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(WindowTreeSetup);
|
| -};
|
| -
|
| -class TestInputEventHandler : public InputEventHandler {
|
| - public:
|
| - TestInputEventHandler()
|
| - : received_event_(false), should_manually_ack_(false) {}
|
| - ~TestInputEventHandler() override {}
|
| -
|
| - void set_should_manually_ack() { should_manually_ack_ = true; }
|
| -
|
| - void AckEvent() {
|
| - DCHECK(should_manually_ack_);
|
| - DCHECK(!ack_callback_.is_null());
|
| - ack_callback_.Run(mojom::EventResult::HANDLED);
|
| - ack_callback_ = base::Bind(&DoNothingWithEventResult);
|
| - }
|
| -
|
| - void Reset() {
|
| - received_event_ = false;
|
| - ack_callback_ = base::Bind(&DoNothingWithEventResult);
|
| - }
|
| - bool received_event() const { return received_event_; }
|
| -
|
| - private:
|
| - // InputEventHandler:
|
| - void OnWindowInputEvent(
|
| - Window* target,
|
| - const ui::Event& event,
|
| - std::unique_ptr<base::Callback<void(mojom::EventResult)>>* ack_callback)
|
| - override {
|
| - EXPECT_FALSE(received_event_)
|
| - << "Observer was not reset after receiving event.";
|
| - received_event_ = true;
|
| - if (should_manually_ack_) {
|
| - ack_callback_ = *ack_callback->get();
|
| - ack_callback->reset();
|
| - }
|
| - }
|
| -
|
| - bool received_event_;
|
| - bool should_manually_ack_;
|
| - base::Callback<void(mojom::EventResult)> ack_callback_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(TestInputEventHandler);
|
| -};
|
| -
|
| -using WindowTreeClientTest = testing::Test;
|
| -
|
| -// Verifies bounds are reverted if the server replied that the change failed.
|
| -TEST_F(WindowTreeClientTest, SetBoundsFailed) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const gfx::Rect original_bounds(root->bounds());
|
| - const gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
|
| - ASSERT_NE(new_bounds, root->bounds());
|
| - root->SetBounds(new_bounds);
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_EQ(original_bounds, root->bounds());
|
| -}
|
| -
|
| -// Simulates a bounds change, and while the bounds change is in flight the
|
| -// server replies with a new bounds and the original bounds change fails.
|
| -TEST_F(WindowTreeClientTest, SetBoundsFailedWithPendingChange) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const gfx::Rect original_bounds(root->bounds());
|
| - const gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
|
| - ASSERT_NE(new_bounds, root->bounds());
|
| - root->SetBounds(new_bounds);
|
| - EXPECT_EQ(new_bounds, root->bounds());
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| -
|
| - // Simulate the server responding with a bounds change.
|
| - const gfx::Rect server_changed_bounds(gfx::Rect(0, 0, 101, 102));
|
| - setup.window_tree_client()->OnWindowBoundsChanged(
|
| - server_id(root), original_bounds, server_changed_bounds);
|
| -
|
| - // This shouldn't trigger the bounds changing yet.
|
| - EXPECT_EQ(new_bounds, root->bounds());
|
| -
|
| - // Tell the client the change failed, which should trigger failing to the
|
| - // most recent bounds from server.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_EQ(server_changed_bounds, root->bounds());
|
| -
|
| - // Simulate server changing back to original bounds. Should take immediately.
|
| - setup.window_tree_client()->OnWindowBoundsChanged(
|
| - server_id(root), server_changed_bounds, original_bounds);
|
| - EXPECT_EQ(original_bounds, root->bounds());
|
| -}
|
| -
|
| -TEST_F(WindowTreeClientTest, TwoInFlightBoundsChangesBothCanceled) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const gfx::Rect original_bounds(root->bounds());
|
| - const gfx::Rect bounds1(gfx::Rect(0, 0, 100, 100));
|
| - const gfx::Rect bounds2(gfx::Rect(0, 0, 100, 102));
|
| - root->SetBounds(bounds1);
|
| - EXPECT_EQ(bounds1, root->bounds());
|
| - uint32_t change_id1;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id1));
|
| -
|
| - root->SetBounds(bounds2);
|
| - EXPECT_EQ(bounds2, root->bounds());
|
| - uint32_t change_id2;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id2));
|
| -
|
| - // Tell the client change 1 failed. As there is a still a change in flight
|
| - // nothing should happen.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id1, false);
|
| - EXPECT_EQ(bounds2, root->bounds());
|
| -
|
| - // And tell the client change 2 failed too. Should now fallback to original
|
| - // bounds.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id2, false);
|
| - EXPECT_EQ(original_bounds, root->bounds());
|
| -}
|
| -
|
| -// Verifies properties are reverted if the server replied that the change
|
| -// failed.
|
| -TEST_F(WindowTreeClientTest, SetPropertyFailed) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - ASSERT_FALSE(root->HasSharedProperty("foo"));
|
| - const int32_t new_value = 11;
|
| - root->SetSharedProperty("foo", new_value);
|
| - ASSERT_TRUE(root->HasSharedProperty("foo"));
|
| - EXPECT_EQ(new_value, root->GetSharedProperty<int32_t>("foo"));
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_FALSE(root->HasSharedProperty("foo"));
|
| -}
|
| -
|
| -// Simulates a property change, and while the property change is in flight the
|
| -// server replies with a new property and the original property change fails.
|
| -TEST_F(WindowTreeClientTest, SetPropertyFailedWithPendingChange) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const int32_t value1 = 11;
|
| - root->SetSharedProperty("foo", value1);
|
| - ASSERT_TRUE(root->HasSharedProperty("foo"));
|
| - EXPECT_EQ(value1, root->GetSharedProperty<int32_t>("foo"));
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| -
|
| - // Simulate the server responding with a different value.
|
| - const int32_t server_value = 12;
|
| - setup.window_tree_client()->OnWindowSharedPropertyChanged(
|
| - server_id(root), "foo", Int32ToPropertyTransportValue(server_value));
|
| -
|
| - // This shouldn't trigger the property changing yet.
|
| - ASSERT_TRUE(root->HasSharedProperty("foo"));
|
| - EXPECT_EQ(value1, root->GetSharedProperty<int32_t>("foo"));
|
| -
|
| - // Tell the client the change failed, which should trigger failing to the
|
| - // most recent value from server.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - ASSERT_TRUE(root->HasSharedProperty("foo"));
|
| - EXPECT_EQ(server_value, root->GetSharedProperty<int32_t>("foo"));
|
| -
|
| - // Simulate server changing back to value1. Should take immediately.
|
| - setup.window_tree_client()->OnWindowSharedPropertyChanged(
|
| - server_id(root), "foo", Int32ToPropertyTransportValue(value1));
|
| - ASSERT_TRUE(root->HasSharedProperty("foo"));
|
| - EXPECT_EQ(value1, root->GetSharedProperty<int32_t>("foo"));
|
| -}
|
| -
|
| -// Verifies visible is reverted if the server replied that the change failed.
|
| -TEST_F(WindowTreeClientTest, SetVisibleFailed) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const bool original_visible = root->visible();
|
| - const bool new_visible = !original_visible;
|
| - ASSERT_NE(new_visible, root->visible());
|
| - root->SetVisible(new_visible);
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_EQ(original_visible, root->visible());
|
| -}
|
| -
|
| -// Simulates a visible change, and while the visible change is in flight the
|
| -// server replies with a new visible and the original visible change fails.
|
| -TEST_F(WindowTreeClientTest, SetVisibleFailedWithPendingChange) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const bool original_visible = root->visible();
|
| - const bool new_visible = !original_visible;
|
| - ASSERT_NE(new_visible, root->visible());
|
| - root->SetVisible(new_visible);
|
| - EXPECT_EQ(new_visible, root->visible());
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| -
|
| - // Simulate the server responding with a visible change.
|
| - const bool server_changed_visible = !new_visible;
|
| - setup.window_tree_client()->OnWindowVisibilityChanged(server_id(root),
|
| - server_changed_visible);
|
| -
|
| - // This shouldn't trigger visible changing yet.
|
| - EXPECT_EQ(new_visible, root->visible());
|
| -
|
| - // Tell the client the change failed, which should trigger failing to the
|
| - // most recent visible from server.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_EQ(server_changed_visible, root->visible());
|
| -
|
| - // Simulate server changing back to original visible. Should take immediately.
|
| - setup.window_tree_client()->OnWindowVisibilityChanged(server_id(root),
|
| - original_visible);
|
| - EXPECT_EQ(original_visible, root->visible());
|
| -}
|
| -
|
| -// Verifies that local opacity is not changed if the server replied that the
|
| -// change succeeded.
|
| -TEST_F(WindowTreeClientTest, SetOpacitySucceeds) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const float original_opacity = root->opacity();
|
| - const float new_opacity = 0.5f;
|
| - ASSERT_NE(new_opacity, original_opacity);
|
| - ASSERT_NE(new_opacity, root->opacity());
|
| - root->SetOpacity(new_opacity);
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, true);
|
| - EXPECT_EQ(new_opacity, root->opacity());
|
| -}
|
| -
|
| -// Verifies that opacity is reverted if the server replied that the change
|
| -// failed.
|
| -TEST_F(WindowTreeClientTest, SetOpacityFailed) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const float original_opacity = root->opacity();
|
| - const float new_opacity = 0.5f;
|
| - ASSERT_NE(new_opacity, root->opacity());
|
| - root->SetOpacity(new_opacity);
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_EQ(original_opacity, root->opacity());
|
| -}
|
| -
|
| -// Simulates the server changing the opacitry while there is an opacity change
|
| -// in flight, causing the requested change to fail.
|
| -TEST_F(WindowTreeClientTest, SetOpacityFailedWithPendingChange) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const float original_opacity = root->opacity();
|
| - const float new_opacity = 0.5f;
|
| - ASSERT_NE(new_opacity, root->opacity());
|
| - root->SetOpacity(new_opacity);
|
| - EXPECT_EQ(new_opacity, root->opacity());
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| -
|
| - // Simulate the server responding with an opacity change.
|
| - const float server_changed_opacity = 0.75f;
|
| - setup.window_tree_client()->OnWindowOpacityChanged(
|
| - server_id(root), original_opacity, server_changed_opacity);
|
| -
|
| - // This shouldn't trigger opacity changing yet.
|
| - EXPECT_EQ(new_opacity, root->opacity());
|
| -
|
| - // Tell the client the change failed, which should trigger failing to the
|
| - // most recent opacity from server.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_EQ(server_changed_opacity, root->opacity());
|
| -
|
| - // Simulate server changing back to original opacity. Should take immediately.
|
| - setup.window_tree_client()->OnWindowOpacityChanged(
|
| - server_id(root), server_changed_opacity, original_opacity);
|
| - EXPECT_EQ(original_opacity, root->opacity());
|
| -}
|
| -
|
| -// Tests that when there are multiple changes in flight, that failing changes
|
| -// update the revert state of subsequent changes.
|
| -TEST_F(WindowTreeClientTest, SetOpacityFailedWithMultiplePendingChange) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - const float original_opacity = root->opacity();
|
| - const float new_opacity = 0.5f;
|
| - ASSERT_NE(new_opacity, root->opacity());
|
| - root->SetOpacity(new_opacity);
|
| - uint32_t change_id1;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id1));
|
| -
|
| - const float second_new_opacity = 0.75f;
|
| - ASSERT_NE(second_new_opacity, root->opacity());
|
| - root->SetOpacity(second_new_opacity);
|
| - uint32_t change_id2;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id2));
|
| -
|
| - // Canceling the first one, while there is another in flight, should not
|
| - // change the local opacity.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id1, false);
|
| - EXPECT_EQ(second_new_opacity, root->opacity());
|
| -
|
| - // The previous cancelation should have updated the revert value of the in
|
| - // flight change.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id2, false);
|
| - EXPECT_EQ(original_opacity, root->opacity());
|
| -}
|
| -
|
| -// Verifies |is_modal| is reverted if the server replied that the change failed.
|
| -TEST_F(WindowTreeClientTest, SetModalFailed) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - EXPECT_FALSE(root->is_modal());
|
| - root->SetModal();
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - EXPECT_TRUE(root->is_modal());
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_FALSE(root->is_modal());
|
| -}
|
| -
|
| -TEST_F(WindowTreeClientTest, InputEventBasic) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| -
|
| - TestInputEventHandler event_handler;
|
| - root->set_input_event_handler(&event_handler);
|
| -
|
| - std::unique_ptr<ui::Event> ui_event(
|
| - new ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
|
| - ui::EventTimeForNow(), ui::EF_NONE, 0));
|
| - setup.window_tree_client()->OnWindowInputEvent(
|
| - 1, server_id(root), ui::Event::Clone(*ui_event.get()), 0);
|
| - EXPECT_TRUE(event_handler.received_event());
|
| - EXPECT_TRUE(setup.window_tree()->WasEventAcked(1));
|
| - event_handler.Reset();
|
| -
|
| - event_handler.set_should_manually_ack();
|
| - setup.window_tree_client()->OnWindowInputEvent(
|
| - 33, server_id(root), ui::Event::Clone(*ui_event.get()), 0);
|
| - EXPECT_TRUE(event_handler.received_event());
|
| - EXPECT_FALSE(setup.window_tree()->WasEventAcked(33));
|
| -
|
| - event_handler.AckEvent();
|
| - EXPECT_TRUE(setup.window_tree()->WasEventAcked(33));
|
| -}
|
| -
|
| -// Tests pointer watchers triggered by events that did not hit a target in this
|
| -// window tree.
|
| -TEST_F(WindowTreeClientTest, OnPointerEventObserved) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| -
|
| - // Start a pointer watcher for all events excluding move events.
|
| - setup.client()->StartPointerWatcher(false /* want_moves */);
|
| -
|
| - // Simulate the server sending an observed event.
|
| - std::unique_ptr<ui::PointerEvent> pointer_event_down(new ui::PointerEvent(
|
| - ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 1,
|
| - 0, ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH),
|
| - base::TimeTicks()));
|
| - setup.window_tree_client()->OnPointerEventObserved(
|
| - std::move(pointer_event_down), 0u);
|
| -
|
| - // Delegate sensed the event.
|
| - ui::Event* last_event = setup.window_tree_delegate()->last_event_observed();
|
| - EXPECT_EQ(ui::ET_POINTER_DOWN, last_event->type());
|
| - EXPECT_EQ(ui::EF_CONTROL_DOWN, last_event->flags());
|
| - setup.window_tree_delegate()->Reset();
|
| -
|
| - // Stop the pointer watcher.
|
| - setup.client()->StopPointerWatcher();
|
| -
|
| - // Simulate another event from the server.
|
| - std::unique_ptr<ui::PointerEvent> pointer_event_up(new ui::PointerEvent(
|
| - ui::ET_POINTER_UP, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 1, 0,
|
| - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH),
|
| - base::TimeTicks()));
|
| - setup.window_tree_client()->OnPointerEventObserved(
|
| - std::move(pointer_event_up), 0u);
|
| -
|
| - // No event was sensed.
|
| - EXPECT_FALSE(setup.window_tree_delegate()->last_event_observed());
|
| -}
|
| -
|
| -// Tests pointer watchers triggered by events that hit this window tree.
|
| -TEST_F(WindowTreeClientTest, OnWindowInputEventWithPointerWatcher) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| -
|
| - // Start a pointer watcher for all events excluding move events.
|
| - setup.client()->StartPointerWatcher(false /* want_moves */);
|
| -
|
| - // Simulate the server dispatching an event that also matched the observer.
|
| - std::unique_ptr<ui::PointerEvent> pointer_event_down(new ui::PointerEvent(
|
| - ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 1,
|
| - 0, ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH),
|
| - base::TimeTicks()));
|
| - setup.window_tree_client()->OnWindowInputEvent(
|
| - 1, server_id(root), std::move(pointer_event_down), true);
|
| -
|
| - // Delegate sensed the event.
|
| - ui::Event* last_event = setup.window_tree_delegate()->last_event_observed();
|
| - EXPECT_EQ(ui::ET_POINTER_DOWN, last_event->type());
|
| - EXPECT_EQ(ui::EF_CONTROL_DOWN, last_event->flags());
|
| -}
|
| -
|
| -// Verifies focus is reverted if the server replied that the change failed.
|
| -TEST_F(WindowTreeClientTest, SetFocusFailed) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - root->SetVisible(true);
|
| - Window* child = setup.client()->NewWindow();
|
| - child->SetVisible(true);
|
| - root->AddChild(child);
|
| - Window* original_focus = setup.client()->GetFocusedWindow();
|
| - Window* new_focus = child;
|
| - ASSERT_NE(new_focus, original_focus);
|
| - new_focus->SetFocus();
|
| - ASSERT_TRUE(new_focus->HasFocus());
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_EQ(original_focus, setup.client()->GetFocusedWindow());
|
| -}
|
| -
|
| -// Simulates a focus change, and while the focus change is in flight the server
|
| -// replies with a new focus and the original focus change fails.
|
| -TEST_F(WindowTreeClientTest, SetFocusFailedWithPendingChange) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - root->SetVisible(true);
|
| - Window* child1 = setup.client()->NewWindow();
|
| - child1->SetVisible(true);
|
| - root->AddChild(child1);
|
| - Window* child2 = setup.client()->NewWindow();
|
| - child2->SetVisible(true);
|
| - root->AddChild(child2);
|
| - Window* original_focus = setup.client()->GetFocusedWindow();
|
| - Window* new_focus = child1;
|
| - ASSERT_NE(new_focus, original_focus);
|
| - new_focus->SetFocus();
|
| - ASSERT_TRUE(new_focus->HasFocus());
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| -
|
| - // Simulate the server responding with a focus change.
|
| - setup.window_tree_client()->OnWindowFocused(server_id(child2));
|
| -
|
| - // This shouldn't trigger focus changing yet.
|
| - EXPECT_TRUE(child1->HasFocus());
|
| -
|
| - // Tell the client the change failed, which should trigger failing to the
|
| - // most recent focus from server.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, false);
|
| - EXPECT_FALSE(child1->HasFocus());
|
| - EXPECT_TRUE(child2->HasFocus());
|
| - EXPECT_EQ(child2, setup.client()->GetFocusedWindow());
|
| -
|
| - // Simulate server changing focus to child1. Should take immediately.
|
| - setup.window_tree_client()->OnWindowFocused(server_id(child1));
|
| - EXPECT_TRUE(child1->HasFocus());
|
| -}
|
| -
|
| -TEST_F(WindowTreeClientTest, FocusOnRemovedWindowWithInFlightFocusChange) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - root->SetVisible(true);
|
| - Window* child1 = setup.client()->NewWindow();
|
| - child1->SetVisible(true);
|
| - root->AddChild(child1);
|
| - Window* child2 = setup.client()->NewWindow();
|
| - child2->SetVisible(true);
|
| - root->AddChild(child2);
|
| -
|
| - child1->SetFocus();
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| -
|
| - // Destroy child1, which should set focus to null.
|
| - child1->Destroy();
|
| - EXPECT_EQ(nullptr, setup.client()->GetFocusedWindow());
|
| -
|
| - // Server changes focus to 2.
|
| - setup.window_tree_client()->OnWindowFocused(server_id(child2));
|
| - // Shouldn't take immediately.
|
| - EXPECT_FALSE(child2->HasFocus());
|
| -
|
| - // Ack the change, focus should still be null.
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, true);
|
| - EXPECT_EQ(nullptr, setup.client()->GetFocusedWindow());
|
| -
|
| - // Change to 2 again, this time it should take.
|
| - setup.window_tree_client()->OnWindowFocused(server_id(child2));
|
| - EXPECT_TRUE(child2->HasFocus());
|
| -}
|
| -
|
| -class ToggleVisibilityFromDestroyedObserver : public WindowObserver {
|
| - public:
|
| - explicit ToggleVisibilityFromDestroyedObserver(Window* window)
|
| - : window_(window) {
|
| - window_->AddObserver(this);
|
| - }
|
| -
|
| - ToggleVisibilityFromDestroyedObserver() { EXPECT_FALSE(window_); }
|
| -
|
| - // WindowObserver:
|
| - void OnWindowDestroyed(Window* window) override {
|
| - window_->SetVisible(!window->visible());
|
| - window_->RemoveObserver(this);
|
| - window_ = nullptr;
|
| - }
|
| -
|
| - private:
|
| - Window* window_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ToggleVisibilityFromDestroyedObserver);
|
| -};
|
| -
|
| -TEST_F(WindowTreeClientTest, ToggleVisibilityFromWindowDestroyed) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| - Window* child1 = setup.client()->NewWindow();
|
| - root->AddChild(child1);
|
| - ToggleVisibilityFromDestroyedObserver toggler(child1);
|
| - // Destroying the window triggers
|
| - // ToggleVisibilityFromDestroyedObserver::OnWindowDestroyed(), which toggles
|
| - // the visibility of the window. Ack the change, which should not crash or
|
| - // trigger DCHECKs.
|
| - child1->Destroy();
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, true);
|
| -}
|
| -
|
| -TEST_F(WindowTreeClientTest, NewTopLevelWindow) {
|
| - WindowTreeSetup setup;
|
| - Window* root1 = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root1);
|
| - Window* root2 = setup.client()->NewTopLevelWindow(nullptr);
|
| - ASSERT_TRUE(root2);
|
| - EXPECT_TRUE(WindowPrivate(root2).parent_drawn());
|
| - ASSERT_NE(root2, root1);
|
| - EXPECT_NE(server_id(root2), server_id(root1));
|
| - EXPECT_EQ(2u, setup.client()->GetRoots().size());
|
| - EXPECT_TRUE(setup.client()->GetRoots().count(root1) > 0u);
|
| - EXPECT_TRUE(setup.client()->GetRoots().count(root2) > 0u);
|
| -
|
| - // Ack the request to the windowtree to create the new window.
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - EXPECT_EQ(setup.window_tree()->window_id(), server_id(root2));
|
| -
|
| - mojom::WindowDataPtr data = mojom::WindowData::New();
|
| - data->window_id = server_id(root2);
|
| - const int64_t display_id = 1;
|
| - setup.window_tree_client()->OnTopLevelCreated(change_id, std::move(data),
|
| - display_id, false);
|
| -
|
| - EXPECT_FALSE(WindowPrivate(root2).parent_drawn());
|
| -
|
| - // Should not be able to add a top level as a child of another window.
|
| - root1->AddChild(root2);
|
| - ASSERT_EQ(nullptr, root2->parent());
|
| -
|
| - // Destroy the first root, shouldn't initiate tear down.
|
| - root1->Destroy();
|
| - root1 = nullptr;
|
| - EXPECT_EQ(1u, setup.client()->GetRoots().size());
|
| - EXPECT_TRUE(setup.client()->GetRoots().count(root2) > 0u);
|
| -}
|
| -
|
| -TEST_F(WindowTreeClientTest, NewTopLevelWindowGetsPropertiesFromData) {
|
| - WindowTreeSetup setup;
|
| - Window* root1 = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root1);
|
| - Window* root2 = setup.client()->NewTopLevelWindow(nullptr);
|
| - ASSERT_TRUE(root2);
|
| -
|
| - EXPECT_FALSE(root2->IsDrawn());
|
| - EXPECT_FALSE(root2->visible());
|
| -
|
| - // Ack the request to the windowtree to create the new window.
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - EXPECT_EQ(setup.window_tree()->window_id(), server_id(root2));
|
| -
|
| - mojom::WindowDataPtr data = mojom::WindowData::New();
|
| - data->window_id = server_id(root2);
|
| - data->bounds.SetRect(1, 2, 3, 4);
|
| - data->visible = true;
|
| - const int64_t display_id = 1;
|
| - setup.window_tree_client()->OnTopLevelCreated(change_id, std::move(data),
|
| - display_id, true);
|
| -
|
| - // Make sure all the properties took.
|
| - EXPECT_TRUE(root2->IsDrawn());
|
| - EXPECT_TRUE(root2->visible());
|
| - EXPECT_EQ(1, root2->display_id());
|
| - EXPECT_EQ(gfx::Rect(1, 2, 3, 4), root2->bounds());
|
| -}
|
| -
|
| -TEST_F(WindowTreeClientTest, NewTopLevelWindowGetsAllChangesInFlight) {
|
| - WindowTreeSetup setup;
|
| - Window* root1 = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root1);
|
| - Window* root2 = setup.client()->NewTopLevelWindow(nullptr);
|
| - ASSERT_TRUE(root2);
|
| -
|
| - EXPECT_FALSE(root2->IsDrawn());
|
| - EXPECT_FALSE(root2->visible());
|
| -
|
| - // Get the id of the in flight change for creating the new window.
|
| - uint32_t new_window_in_flight_change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(
|
| - &new_window_in_flight_change_id));
|
| - EXPECT_EQ(setup.window_tree()->window_id(), server_id(root2));
|
| -
|
| - // Make visibility go from false->true->false. Don't ack immediately.
|
| - root2->SetVisible(true);
|
| - uint32_t vis_in_flight_change_id1;
|
| - ASSERT_TRUE(
|
| - setup.window_tree()->GetAndClearChangeId(&vis_in_flight_change_id1));
|
| - EXPECT_NE(new_window_in_flight_change_id, vis_in_flight_change_id1);
|
| - root2->SetVisible(false);
|
| - uint32_t vis_in_flight_change_id2;
|
| - ASSERT_TRUE(
|
| - setup.window_tree()->GetAndClearChangeId(&vis_in_flight_change_id2));
|
| - EXPECT_NE(vis_in_flight_change_id1, vis_in_flight_change_id2);
|
| -
|
| - // Change bounds to 5, 6, 7, 8.
|
| - root2->SetBounds(gfx::Rect(5, 6, 7, 8));
|
| - uint32_t bounds_in_flight_change_id;
|
| - ASSERT_TRUE(
|
| - setup.window_tree()->GetAndClearChangeId(&bounds_in_flight_change_id));
|
| - EXPECT_NE(vis_in_flight_change_id2, bounds_in_flight_change_id);
|
| -
|
| - root2->SetSharedProperty<std::string>("xx", "client_xx");
|
| - uint32_t property_in_flight_change_id;
|
| - ASSERT_TRUE(
|
| - setup.window_tree()->GetAndClearChangeId(&property_in_flight_change_id));
|
| - EXPECT_NE(bounds_in_flight_change_id, property_in_flight_change_id);
|
| -
|
| - // Ack the new window top level window. Vis and bounds shouldn't change.
|
| - mojom::WindowDataPtr data = mojom::WindowData::New();
|
| - data->window_id = server_id(root2);
|
| - data->bounds.SetRect(1, 2, 3, 4);
|
| - data->visible = true;
|
| - constexpr char kXxName[] = "server_xx";
|
| - data->properties["xx"] =
|
| - std::vector<uint8_t>(kXxName, kXxName + strlen(kXxName));
|
| - constexpr char kYyName[] = "server_yy";
|
| - data->properties["yy"] =
|
| - std::vector<uint8_t>(kYyName, kYyName + strlen(kYyName));
|
| - const int64_t display_id = 1;
|
| - setup.window_tree_client()->OnTopLevelCreated(
|
| - new_window_in_flight_change_id, std::move(data), display_id, true);
|
| -
|
| - // The only value that should take effect is the property for 'yy' as it was
|
| - // not in flight.
|
| - EXPECT_TRUE(WindowPrivate(root2).parent_drawn());
|
| - EXPECT_FALSE(root2->visible());
|
| - EXPECT_EQ(1, root2->display_id());
|
| - EXPECT_EQ(gfx::Rect(5, 6, 7, 8), root2->bounds());
|
| - EXPECT_EQ(2u, root2->shared_properties().size());
|
| - ASSERT_TRUE(root2->HasSharedProperty("yy"));
|
| - EXPECT_EQ("server_yy", root2->GetSharedProperty<std::string>("yy"));
|
| - ASSERT_TRUE(root2->HasSharedProperty("xx"));
|
| - EXPECT_EQ("client_xx", root2->GetSharedProperty<std::string>("xx"));
|
| -
|
| - // Tell the client the changes failed. This should cause the values to change
|
| - // to that of the server.
|
| - setup.window_tree_client()->OnChangeCompleted(vis_in_flight_change_id1,
|
| - false);
|
| - EXPECT_FALSE(root2->visible());
|
| - setup.window_tree_client()->OnChangeCompleted(vis_in_flight_change_id2,
|
| - false);
|
| - EXPECT_TRUE(root2->visible());
|
| - setup.window_tree_client()->OnChangeCompleted(bounds_in_flight_change_id,
|
| - false);
|
| - EXPECT_EQ(gfx::Rect(1, 2, 3, 4), root2->bounds());
|
| - setup.window_tree_client()->OnChangeCompleted(property_in_flight_change_id,
|
| - false);
|
| - EXPECT_EQ(2u, root2->shared_properties().size());
|
| - ASSERT_TRUE(root2->HasSharedProperty("yy"));
|
| - EXPECT_EQ("server_yy", root2->GetSharedProperty<std::string>("yy"));
|
| - ASSERT_TRUE(root2->HasSharedProperty("xx"));
|
| - EXPECT_EQ("server_xx", root2->GetSharedProperty<std::string>("xx"));
|
| -}
|
| -
|
| -// Tests that if the client has multiple unowned windows, and one of them is a
|
| -// transient child to another, the teardown can happen cleanly.
|
| -TEST_F(WindowTreeClientTest, MultipleUnOwnedWindowsDuringDestruction) {
|
| - std::unique_ptr<WindowTreeSetup> setup(new WindowTreeSetup());
|
| - Window* root1 = setup->GetFirstRoot();
|
| - ASSERT_TRUE(root1);
|
| - Window* root2 = setup->client()->NewTopLevelWindow(nullptr);
|
| - ASSERT_TRUE(root2);
|
| - root1->AddTransientWindow(root2);
|
| -
|
| - WindowTracker tracker;
|
| - tracker.Add(root1);
|
| - tracker.Add(root2);
|
| - setup.reset();
|
| - EXPECT_TRUE(tracker.windows().empty());
|
| -}
|
| -
|
| -TEST_F(WindowTreeClientTest, TopLevelWindowDestroyedBeforeCreateComplete) {
|
| - WindowTreeSetup setup;
|
| - Window* root1 = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root1);
|
| - Window* root2 = setup.client()->NewTopLevelWindow(nullptr);
|
| - ASSERT_TRUE(root2);
|
| - ASSERT_EQ(2u, setup.client()->GetRoots().size());
|
| -
|
| - // Get the id of the in flight change for creating the new window.
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - EXPECT_EQ(setup.window_tree()->window_id(), server_id(root2));
|
| -
|
| - mojom::WindowDataPtr data = mojom::WindowData::New();
|
| - data->window_id = server_id(root2);
|
| -
|
| - // Destroy the window before the server has a chance to ack the window
|
| - // creation.
|
| - root2->Destroy();
|
| - EXPECT_EQ(1u, setup.client()->GetRoots().size());
|
| -
|
| - const int64_t display_id = 1;
|
| - setup.window_tree_client()->OnTopLevelCreated(change_id, std::move(data),
|
| - display_id, true);
|
| - EXPECT_EQ(1u, setup.client()->GetRoots().size());
|
| -}
|
| -
|
| -// Tests both SetCapture and ReleaseCapture, to ensure that Window is properly
|
| -// updated on failures.
|
| -TEST_F(WindowTreeClientTest, ExplicitCapture) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| -
|
| - root->SetCapture();
|
| - EXPECT_TRUE(root->HasCapture());
|
| - uint32_t change_id1;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id1));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id1, false);
|
| - EXPECT_FALSE(root->HasCapture());
|
| -
|
| - root->SetCapture();
|
| - EXPECT_TRUE(root->HasCapture());
|
| - uint32_t change_id2;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id2));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id2, true);
|
| - EXPECT_TRUE(root->HasCapture());
|
| -
|
| - root->ReleaseCapture();
|
| - EXPECT_FALSE(root->HasCapture());
|
| - uint32_t change_id3;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id3));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id3, false);
|
| - EXPECT_TRUE(root->HasCapture());
|
| -
|
| - root->ReleaseCapture();
|
| - uint32_t change_id4;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id4));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id4, true);
|
| - EXPECT_FALSE(root->HasCapture());
|
| -}
|
| -
|
| -// Tests that when capture is lost, that the window tree updates properly.
|
| -TEST_F(WindowTreeClientTest, LostCapture) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| -
|
| - root->SetCapture();
|
| - EXPECT_TRUE(root->HasCapture());
|
| - uint32_t change_id1;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id1));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id1, true);
|
| - EXPECT_TRUE(root->HasCapture());
|
| -
|
| - // The second SetCapture should be ignored.
|
| - root->SetCapture();
|
| - uint32_t change_id2;
|
| - ASSERT_FALSE(setup.window_tree()->GetAndClearChangeId(&change_id2));
|
| -
|
| - setup.window_tree_client()->OnCaptureChanged(0, server_id(root));
|
| - EXPECT_FALSE(root->HasCapture());
|
| -}
|
| -
|
| -// Tests that when capture is lost, while there is a release capture request
|
| -// inflight, that the revert value of that request is updated correctly.
|
| -TEST_F(WindowTreeClientTest, LostCaptureDifferentInFlightChange) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - ASSERT_TRUE(root);
|
| -
|
| - root->SetCapture();
|
| - EXPECT_TRUE(root->HasCapture());
|
| - uint32_t change_id1;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id1));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id1, true);
|
| - EXPECT_TRUE(root->HasCapture());
|
| -
|
| - // The ReleaseCapture should be updated to the revert of the SetCapture.
|
| - root->ReleaseCapture();
|
| - uint32_t change_id2;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id2));
|
| -
|
| - setup.window_tree_client()->OnCaptureChanged(0, server_id(root));
|
| - EXPECT_FALSE(root->HasCapture());
|
| -
|
| - setup.window_tree_client()->OnChangeCompleted(change_id2, false);
|
| - EXPECT_FALSE(root->HasCapture());
|
| -}
|
| -
|
| -// Tests that while two windows can inflight capture requests, that the
|
| -// WindowTreeClient only identifies one as having the current capture.
|
| -TEST_F(WindowTreeClientTest, TwoWindowsRequestCapture) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - Window* child = setup.client()->NewWindow();
|
| - child->SetVisible(true);
|
| - root->AddChild(child);
|
| -
|
| - root->SetCapture();
|
| - EXPECT_TRUE(root->HasCapture());
|
| - uint32_t change_id1;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id1));
|
| -
|
| - child->SetCapture();
|
| - EXPECT_TRUE(child->HasCapture());
|
| - EXPECT_FALSE(root->HasCapture());
|
| -
|
| - uint32_t change_id2;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id2));
|
| -
|
| - setup.window_tree_client()->OnChangeCompleted(change_id1, true);
|
| - EXPECT_FALSE(root->HasCapture());
|
| - EXPECT_TRUE(child->HasCapture());
|
| -
|
| - setup.window_tree_client()->OnChangeCompleted(change_id2, false);
|
| - EXPECT_FALSE(child->HasCapture());
|
| - EXPECT_TRUE(root->HasCapture());
|
| -
|
| - setup.window_tree_client()->OnCaptureChanged(0, server_id(root));
|
| - EXPECT_FALSE(root->HasCapture());
|
| -}
|
| -
|
| -TEST_F(WindowTreeClientTest, WindowDestroyedWhileTransientChildHasCapture) {
|
| - WindowTreeSetup setup;
|
| - Window* root = setup.GetFirstRoot();
|
| - Window* transient_parent = setup.client()->NewWindow();
|
| - Window* transient_child = setup.client()->NewWindow();
|
| - transient_parent->SetVisible(true);
|
| - transient_child->SetVisible(true);
|
| - root->AddChild(transient_parent);
|
| - root->AddChild(transient_child);
|
| -
|
| - transient_parent->AddTransientWindow(transient_child);
|
| -
|
| - WindowTracker tracker;
|
| - tracker.Add(transient_parent);
|
| - tracker.Add(transient_child);
|
| - // Request a capture on the transient child, then destroy the transient
|
| - // parent. That will destroy both windows, and should reset the capture window
|
| - // correctly.
|
| - transient_child->SetCapture();
|
| - transient_parent->Destroy();
|
| - EXPECT_TRUE(tracker.windows().empty());
|
| -
|
| - // Create a new Window, and attempt to place capture on that.
|
| - Window* child = setup.client()->NewWindow();
|
| - child->SetVisible(true);
|
| - root->AddChild(child);
|
| - child->SetCapture();
|
| - EXPECT_TRUE(child->HasCapture());
|
| -}
|
| -
|
| -namespace {
|
| -
|
| -class CaptureRecorder : public WindowTreeClientObserver {
|
| - public:
|
| - explicit CaptureRecorder(WindowTreeClient* tree_client)
|
| - : tree_client_(tree_client) {
|
| - tree_client_->AddObserver(this);
|
| - }
|
| -
|
| - ~CaptureRecorder() override { tree_client_->RemoveObserver(this); }
|
| -
|
| - void reset_capture_captured_count() { capture_changed_count_ = 0; }
|
| - int capture_changed_count() const { return capture_changed_count_; }
|
| - int last_gained_capture_window_id() const {
|
| - return last_gained_capture_window_id_;
|
| - }
|
| - int last_lost_capture_window_id() const {
|
| - return last_lost_capture_window_id_;
|
| - }
|
| -
|
| - // WindowTreeClientObserver:
|
| - void OnWindowTreeCaptureChanged(Window* gained_capture,
|
| - Window* lost_capture) override {
|
| - capture_changed_count_++;
|
| - last_gained_capture_window_id_ =
|
| - gained_capture ? gained_capture->local_id() : 0;
|
| - last_lost_capture_window_id_ = lost_capture ? lost_capture->local_id() : 0;
|
| - }
|
| -
|
| - private:
|
| - WindowTreeClient* tree_client_;
|
| - int capture_changed_count_ = 0;
|
| - int last_gained_capture_window_id_ = 0;
|
| - int last_lost_capture_window_id_ = 0;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(CaptureRecorder);
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -TEST_F(WindowTreeClientTest, OnWindowTreeCaptureChanged) {
|
| - WindowTreeSetup setup;
|
| - CaptureRecorder capture_recorder(setup.client());
|
| - Window* root = setup.GetFirstRoot();
|
| - Window* child1 = setup.client()->NewWindow();
|
| - const int child1_id = 1;
|
| - child1->set_local_id(child1_id);
|
| - child1->SetVisible(true);
|
| - root->AddChild(child1);
|
| - Window* child2 = setup.client()->NewWindow();
|
| - const int child2_id = 2;
|
| - child2->set_local_id(child2_id);
|
| - child2->SetVisible(true);
|
| - root->AddChild(child2);
|
| -
|
| - EXPECT_EQ(0, capture_recorder.capture_changed_count());
|
| - // Give capture to child1 and ensure everyone is notified correctly.
|
| - child1->SetCapture();
|
| - uint32_t change_id;
|
| - ASSERT_TRUE(setup.window_tree()->GetAndClearChangeId(&change_id));
|
| - setup.window_tree_client()->OnChangeCompleted(change_id, true);
|
| - EXPECT_EQ(1, capture_recorder.capture_changed_count());
|
| - EXPECT_EQ(child1_id, capture_recorder.last_gained_capture_window_id());
|
| - EXPECT_EQ(0, capture_recorder.last_lost_capture_window_id());
|
| - capture_recorder.reset_capture_captured_count();
|
| -
|
| - // Deleting a window with capture should notify observers as well.
|
| - child1->Destroy();
|
| - child1 = nullptr;
|
| - EXPECT_EQ(1, capture_recorder.capture_changed_count());
|
| - EXPECT_EQ(0, capture_recorder.last_gained_capture_window_id());
|
| - EXPECT_EQ(child1_id, capture_recorder.last_lost_capture_window_id());
|
| - capture_recorder.reset_capture_captured_count();
|
| -
|
| - // Changes originating from server should notify observers too.
|
| - WindowTreeClientPrivate(setup.client()).CallOnCaptureChanged(child2, nullptr);
|
| - EXPECT_EQ(1, capture_recorder.capture_changed_count());
|
| - EXPECT_EQ(child2_id, capture_recorder.last_gained_capture_window_id());
|
| - EXPECT_EQ(0, capture_recorder.last_lost_capture_window_id());
|
| - capture_recorder.reset_capture_captured_count();
|
| -}
|
| -
|
| -} // namespace ui
|
|
|