Commit 3e10172c authored by Maksim Sisov (GMT+3)'s avatar Maksim Sisov (GMT+3) Committed by Commit Bot

Revert "X11 and Ozone: rework topwindowfinder tests"

This reverts commit 2e54b5b0.

Reason for revert: 1) we can't move the tests to x11_unittests as we wanted before. 2) they became flaky and require x11wmstartupcheck program to check if openbox started. This check only happens for x11_unittests and we don't want to other test suites to run that now.

Original change's description:
> X11 and Ozone: rework topwindowfinder tests
> 
> Remove dependency on ui/views and ui/aura. This is required to be
> able to move them down to ui/platform_window/x11/tests
> 
> Bug: 789065
> Change-Id: Ie4c0bd3056f9627b13b4bdfc9511010aaf249515
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2367072
> Commit-Queue: Maksim Sisov (GMT+3) <msisov@igalia.com>
> Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#800488}

TBR=thomasanderson@chromium.org,msisov@igalia.com

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 789065
Change-Id: If7fcf7756d5e4da53d21d5b0ad29e2752c0f9bd4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2371622Reviewed-by: default avatarMaksim Sisov (GMT+3) <msisov@igalia.com>
Commit-Queue: Maksim Sisov (GMT+3) <msisov@igalia.com>
Cr-Commit-Position: refs/heads/master@{#800921}
parent 17dfed85
...@@ -11,107 +11,28 @@ ...@@ -11,107 +11,28 @@
#include <vector> #include <vector>
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRegion.h" #include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/x/test/x11_property_change_waiter.h" #include "ui/base/x/test/x11_property_change_waiter.h"
#include "ui/base/x/x11_util.h" #include "ui/base/x/x11_util.h"
#include "ui/events/platform/x11/x11_event_source.h" #include "ui/events/platform/x11/x11_event_source.h"
#include "ui/events/x/x11_window_event_manager.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/x/connection.h" #include "ui/gfx/x/connection.h"
#include "ui/gfx/x/event.h" #include "ui/gfx/x/event.h"
#include "ui/gfx/x/shape.h" #include "ui/gfx/x/shape.h"
#include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_path.h" #include "ui/gfx/x/x11_path.h"
#include "ui/platform_window/x11/x11_window.h" #include "ui/views/test/widget_test.h"
#include "ui/platform_window/x11/x11_window_manager.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
#include "ui/views/widget/widget.h"
namespace views { namespace views {
namespace { namespace {
// Waits until the |x11_window| is mapped and becomes viewable.
class X11VisibilityWaiter : public ui::XEventDispatcher {
public:
X11VisibilityWaiter() = default;
X11VisibilityWaiter(const X11VisibilityWaiter&) = delete;
X11VisibilityWaiter& operator=(const X11VisibilityWaiter&) = delete;
~X11VisibilityWaiter() override = default;
void WaitUntilWindowIsVisible(x11::Window x11_window) {
if (ui::IsWindowVisible(x11_window))
return;
auto events = std::make_unique<ui::XScopedEventSelector>(
x11_window, StructureNotifyMask | SubstructureNotifyMask);
x11_window_ = x11_window;
dispatcher_ =
ui::X11EventSource::GetInstance()->OverrideXEventDispatcher(this);
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
run_loop.Run();
}
private:
// XEventDispatcher:
bool DispatchXEvent(x11::Event* event) override {
auto* map = event->As<x11::MapNotifyEvent>();
if (map && map->window == x11_window_) {
if (!quit_closure_.is_null())
std::move(quit_closure_).Run();
dispatcher_.reset();
return true;
}
return false;
}
x11::Window x11_window_;
std::unique_ptr<ui::ScopedXEventDispatcher> dispatcher_;
// Ends the run loop.
base::OnceClosure quit_closure_;
};
class TestPlatformWindowDelegate : public ui::PlatformWindowDelegate {
public:
TestPlatformWindowDelegate() = default;
TestPlatformWindowDelegate(const TestPlatformWindowDelegate&) = delete;
TestPlatformWindowDelegate& operator=(const TestPlatformWindowDelegate&) =
delete;
~TestPlatformWindowDelegate() override = default;
ui::PlatformWindowState state() { return state_; }
// PlatformWindowDelegate:
void OnBoundsChanged(const gfx::Rect& new_bounds) override {}
void OnDamageRect(const gfx::Rect& damaged_region) override {}
void DispatchEvent(ui::Event* event) override {}
void OnCloseRequest() override {}
void OnClosed() override {}
void OnWindowStateChanged(ui::PlatformWindowState new_state) override {
state_ = new_state;
}
void OnLostCapture() override {}
void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override {
widget_ = widget;
}
void OnWillDestroyAcceleratedWidget() override {}
void OnAcceleratedWidgetDestroyed() override {
widget_ = gfx::kNullAcceleratedWidget;
}
void OnActivationChanged(bool active) override {}
void OnMouseEnter() override {}
private:
gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
ui::PlatformWindowState state_ = ui::PlatformWindowState::kUnknown;
};
// Waits till |window| is minimized. // Waits till |window| is minimized.
class MinimizeWaiter : public ui::X11PropertyChangeWaiter { class MinimizeWaiter : public ui::X11PropertyChangeWaiter {
public: public:
...@@ -171,44 +92,36 @@ class StackingClientListWaiter : public ui::X11PropertyChangeWaiter { ...@@ -171,44 +92,36 @@ class StackingClientListWaiter : public ui::X11PropertyChangeWaiter {
} // namespace } // namespace
class X11TopmostWindowFinderTest : public testing::Test { class X11TopmostWindowFinderTest : public test::DesktopWidgetTestInteractive {
public: public:
X11TopmostWindowFinderTest() X11TopmostWindowFinderTest() = default;
: task_env_(base::test::TaskEnvironment::MainThreadType::UI) {}
~X11TopmostWindowFinderTest() override = default; ~X11TopmostWindowFinderTest() override = default;
// DesktopWidgetTestInteractive // DesktopWidgetTestInteractive
void SetUp() override { void SetUp() override {
auto* connection = x11::Connection::Get();
event_source_ = std::make_unique<ui::X11EventSource>(connection);
// Make X11 synchronous for our display connection. This does not force the // Make X11 synchronous for our display connection. This does not force the
// window manager to behave synchronously. // window manager to behave synchronously.
XSynchronize(xdisplay(), x11::True); XSynchronize(xdisplay(), x11::True);
DesktopWidgetTestInteractive::SetUp();
} }
void TearDown() override { void TearDown() override {
XSynchronize(xdisplay(), x11::False); XSynchronize(xdisplay(), x11::False);
DesktopWidgetTestInteractive::TearDown();
} }
// Creates and shows an X11Window with |bounds|. The caller takes ownership of // Creates and shows a Widget with |bounds|. The caller takes ownership of
// the returned window. // the returned widget.
std::unique_ptr<ui::X11Window> CreateAndShowX11Window( std::unique_ptr<Widget> CreateAndShowWidget(const gfx::Rect& bounds) {
ui::PlatformWindowDelegate* delegate, std::unique_ptr<Widget> toplevel(new Widget);
const gfx::Rect& bounds) { Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
ui::PlatformWindowInitProperties init_params(bounds); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
init_params.remove_standard_frame = true; params.native_widget = new DesktopNativeWidgetAura(toplevel.get());
auto window = std::make_unique<ui::X11Window>(delegate); params.bounds = bounds;
window->Initialize(std::move(init_params)); params.remove_standard_frame = true;
window->Show(false); toplevel->Init(std::move(params));
toplevel->Show();
// Wait until the window becomes visible so that window finder doesn't skip return toplevel;
// these windows (it's required to wait because mapping and searching for
// toplevel window is a subject to races).
X11VisibilityWaiter waiter;
waiter.WaitUntilWindowIsVisible(
static_cast<x11::Window>(window->GetWidget()));
return window;
} }
// Creates and shows an X window with |bounds|. // Creates and shows an X window with |bounds|.
...@@ -222,11 +135,6 @@ class X11TopmostWindowFinderTest : public testing::Test { ...@@ -222,11 +135,6 @@ class X11TopmostWindowFinderTest : public testing::Test {
ui::SetUseOSWindowFrame(window, false); ui::SetUseOSWindowFrame(window, false);
ShowAndSetXWindowBounds(window, bounds); ShowAndSetXWindowBounds(window, bounds);
// Wait until the window becomes visible so that window finder doesn't skip
// these windows (it's required to wait because mapping and searching for
// toplevel window is a subject to races).
X11VisibilityWaiter waiter;
waiter.WaitUntilWindowIsVisible(static_cast<x11::Window>(window));
return window; return window;
} }
...@@ -251,40 +159,38 @@ class X11TopmostWindowFinderTest : public testing::Test { ...@@ -251,40 +159,38 @@ class X11TopmostWindowFinderTest : public testing::Test {
return finder.FindWindowAt(gfx::Point(screen_x, screen_y)); return finder.FindWindowAt(gfx::Point(screen_x, screen_y));
} }
// Returns the topmost ui::X11Window at the passed in screen position. Returns // Returns the topmost aura::Window at the passed in screen position. Returns
// nullptr if the topmost window does not have an associated ui::X11Window. // NULL if the topmost window does not have an associated aura::Window.
ui::X11Window* FindTopmostLocalProcessWindowAt(int screen_x, int screen_y) { aura::Window* FindTopmostLocalProcessWindowAt(int screen_x, int screen_y) {
ui::X11TopmostWindowFinder finder; ui::X11TopmostWindowFinder finder;
auto x11_window = auto widget = static_cast<gfx::AcceleratedWidget>(
finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y), {}); finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y), {}));
return x11_window == x11::Window::None return widget != gfx::kNullAcceleratedWidget
? nullptr ? DesktopWindowTreeHostPlatform::GetContentWindowForWidget(
: ui::X11WindowManager::GetInstance()->GetWindow( widget)
static_cast<gfx::AcceleratedWidget>(x11_window)); : nullptr;
} }
// Returns the topmost ui::X11Window at the passed in screen position ignoring // Returns the topmost aura::Window at the passed in screen position ignoring
// |ignore_window|. Returns nullptr if the topmost window does not have an // |ignore_window|. Returns NULL if the topmost window does not have an
// associated ui::X11Window. // associated aura::Window.
ui::X11Window* FindTopmostLocalProcessWindowWithIgnore( aura::Window* FindTopmostLocalProcessWindowWithIgnore(
int screen_x, int screen_x,
int screen_y, int screen_y,
x11::Window ignore_window) { aura::Window* ignore_window) {
std::set<gfx::AcceleratedWidget> ignore; std::set<gfx::AcceleratedWidget> ignore;
ignore.insert(static_cast<gfx::AcceleratedWidget>(ignore_window)); ignore.insert(ignore_window->GetHost()->GetAcceleratedWidget());
ui::X11TopmostWindowFinder finder; ui::X11TopmostWindowFinder finder;
auto x11_window = auto widget =
finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y), ignore); static_cast<gfx::AcceleratedWidget>(finder.FindLocalProcessWindowAt(
return x11_window == x11::Window::None gfx::Point(screen_x, screen_y), ignore));
? nullptr return widget != gfx::kNullAcceleratedWidget
: ui::X11WindowManager::GetInstance()->GetWindow( ? DesktopWindowTreeHostPlatform::GetContentWindowForWidget(
static_cast<gfx::AcceleratedWidget>(x11_window)); widget)
: nullptr;
} }
private: private:
base::test::TaskEnvironment task_env_;
std::unique_ptr<ui::X11EventSource> event_source_;
DISALLOW_COPY_AND_ASSIGN(X11TopmostWindowFinderTest); DISALLOW_COPY_AND_ASSIGN(X11TopmostWindowFinderTest);
}; };
...@@ -292,16 +198,19 @@ TEST_F(X11TopmostWindowFinderTest, Basic) { ...@@ -292,16 +198,19 @@ TEST_F(X11TopmostWindowFinderTest, Basic) {
// Avoid positioning test windows at 0x0 because window managers often have a // Avoid positioning test windows at 0x0 because window managers often have a
// panel/launcher along one of the screen edges and do not allow windows to // panel/launcher along one of the screen edges and do not allow windows to
// position themselves to overlap the panel/launcher. // position themselves to overlap the panel/launcher.
TestPlatformWindowDelegate delegate; std::unique_ptr<Widget> widget1(
auto window1 = CreateAndShowX11Window(&delegate, {100, 100, 200, 100}); CreateAndShowWidget(gfx::Rect(100, 100, 200, 100)));
auto x11_window1 = static_cast<x11::Window>(window1->GetWidget()); aura::Window* window1 = widget1->GetNativeWindow();
x11::Window x11_window1 =
static_cast<x11::Window>(window1->GetHost()->GetAcceleratedWidget());
x11::Window x11_window2 = CreateAndShowXWindow(gfx::Rect(200, 100, 100, 200)); x11::Window x11_window2 = CreateAndShowXWindow(gfx::Rect(200, 100, 100, 200));
TestPlatformWindowDelegate delegate2; std::unique_ptr<Widget> widget3(
auto window3 = CreateAndShowX11Window(&delegate2, {100, 190, 200, 110}); CreateAndShowWidget(gfx::Rect(100, 190, 200, 110)));
window3->Show(false); aura::Window* window3 = widget3->GetNativeWindow();
auto x11_window3 = static_cast<x11::Window>(window3->GetWidget()); x11::Window x11_window3 =
static_cast<x11::Window>(window3->GetHost()->GetAcceleratedWidget());
x11::Window windows[] = {x11_window1, x11_window2, x11_window3}; x11::Window windows[] = {x11_window1, x11_window2, x11_window3};
StackingClientListWaiter waiter(windows, base::size(windows)); StackingClientListWaiter waiter(windows, base::size(windows));
...@@ -309,41 +218,42 @@ TEST_F(X11TopmostWindowFinderTest, Basic) { ...@@ -309,41 +218,42 @@ TEST_F(X11TopmostWindowFinderTest, Basic) {
ui::X11EventSource::GetInstance()->DispatchXEvents(); ui::X11EventSource::GetInstance()->DispatchXEvents();
EXPECT_EQ(x11_window1, FindTopmostXWindowAt(150, 150)); EXPECT_EQ(x11_window1, FindTopmostXWindowAt(150, 150));
EXPECT_EQ(window1.get(), FindTopmostLocalProcessWindowAt(150, 150)); EXPECT_EQ(window1, FindTopmostLocalProcessWindowAt(150, 150));
EXPECT_EQ(x11_window2, FindTopmostXWindowAt(250, 150)); EXPECT_EQ(x11_window2, FindTopmostXWindowAt(250, 150));
EXPECT_FALSE(FindTopmostLocalProcessWindowAt(250, 150)); EXPECT_FALSE(FindTopmostLocalProcessWindowAt(250, 150));
EXPECT_EQ(x11_window3, FindTopmostXWindowAt(250, 250)); EXPECT_EQ(x11_window3, FindTopmostXWindowAt(250, 250));
EXPECT_EQ(window3.get(), FindTopmostLocalProcessWindowAt(250, 250)); EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(250, 250));
EXPECT_EQ(x11_window3, FindTopmostXWindowAt(150, 250)); EXPECT_EQ(x11_window3, FindTopmostXWindowAt(150, 250));
EXPECT_EQ(window3.get(), FindTopmostLocalProcessWindowAt(150, 250)); EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 250));
EXPECT_EQ(x11_window3, FindTopmostXWindowAt(150, 195)); EXPECT_EQ(x11_window3, FindTopmostXWindowAt(150, 195));
EXPECT_EQ(window3.get(), FindTopmostLocalProcessWindowAt(150, 195)); EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 195));
EXPECT_NE(x11_window1, FindTopmostXWindowAt(1000, 1000)); EXPECT_NE(x11_window1, FindTopmostXWindowAt(1000, 1000));
EXPECT_NE(x11_window2, FindTopmostXWindowAt(1000, 1000)); EXPECT_NE(x11_window2, FindTopmostXWindowAt(1000, 1000));
EXPECT_NE(x11_window3, FindTopmostXWindowAt(1000, 1000)); EXPECT_NE(x11_window3, FindTopmostXWindowAt(1000, 1000));
EXPECT_FALSE(FindTopmostLocalProcessWindowAt(1000, 1000)); EXPECT_FALSE(FindTopmostLocalProcessWindowAt(1000, 1000));
EXPECT_EQ(window1.get(), EXPECT_EQ(window1,
FindTopmostLocalProcessWindowWithIgnore(150, 150, x11_window3)); FindTopmostLocalProcessWindowWithIgnore(150, 150, window3));
EXPECT_FALSE(FindTopmostLocalProcessWindowWithIgnore(250, 250, x11_window3)); EXPECT_FALSE(FindTopmostLocalProcessWindowWithIgnore(250, 250, window3));
EXPECT_FALSE(FindTopmostLocalProcessWindowWithIgnore(150, 250, x11_window3)); EXPECT_FALSE(FindTopmostLocalProcessWindowWithIgnore(150, 250, window3));
EXPECT_EQ(window1.get(), EXPECT_EQ(window1,
FindTopmostLocalProcessWindowWithIgnore(150, 195, x11_window3)); FindTopmostLocalProcessWindowWithIgnore(150, 195, window3));
XDestroyWindow(xdisplay(), static_cast<uint32_t>(x11_window2)); XDestroyWindow(xdisplay(), static_cast<uint32_t>(x11_window2));
} }
// Test that the minimized state is properly handled. // Test that the minimized state is properly handled.
TEST_F(X11TopmostWindowFinderTest, Minimized) { TEST_F(X11TopmostWindowFinderTest, Minimized) {
TestPlatformWindowDelegate delegate; std::unique_ptr<Widget> widget1(
auto window1 = CreateAndShowX11Window(&delegate, {100, 100, 100, 100}); CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
auto x11_window1 = static_cast<x11::Window>(window1->GetWidget()); aura::Window* window1 = widget1->GetNativeWindow();
x11::Window x11_window1 =
static_cast<x11::Window>(window1->GetHost()->GetAcceleratedWidget());
x11::Window x11_window2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100)); x11::Window x11_window2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100));
x11::Window windows[] = {x11_window1, x11_window2}; x11::Window windows[] = {x11_window1, x11_window2};
...@@ -379,16 +289,14 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangular) { ...@@ -379,16 +289,14 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangular) {
if (!ui::IsShapeExtensionAvailable()) if (!ui::IsShapeExtensionAvailable())
return; return;
TestPlatformWindowDelegate delegate; std::unique_ptr<Widget> widget1(
auto x11_window1 = CreateAndShowX11Window(&delegate, {100, 100, 100, 100}); CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
auto window1 = static_cast<x11::Window>(x11_window1->GetWidget()); x11::Window window1 = static_cast<x11::Window>(
widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
auto shape1 = std::make_unique<std::vector<gfx::Rect>>(); auto shape1 = std::make_unique<Widget::ShapeRects>();
shape1->emplace_back(0, 10, 10, 90); shape1->emplace_back(0, 10, 10, 90);
shape1->emplace_back(10, 0, 90, 100); shape1->emplace_back(10, 0, 90, 100);
gfx::Transform transform; widget1->SetShape(std::move(shape1));
transform.Scale(1.0f, 1.0f);
x11_window1->SetShape(std::move(shape1), transform);
SkRegion skregion2; SkRegion skregion2;
skregion2.op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op); skregion2.op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op);
...@@ -425,15 +333,14 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangularEmptyShape) { ...@@ -425,15 +333,14 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangularEmptyShape) {
if (!ui::IsShapeExtensionAvailable()) if (!ui::IsShapeExtensionAvailable())
return; return;
TestPlatformWindowDelegate delegate; std::unique_ptr<Widget> widget1(
auto x11_window1 = CreateAndShowX11Window(&delegate, {100, 100, 100, 100}); CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
auto window1 = static_cast<x11::Window>(x11_window1->GetWidget()); x11::Window window1 = static_cast<x11::Window>(
widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
auto shape1 = std::make_unique<std::vector<gfx::Rect>>(); auto shape1 = std::make_unique<Widget::ShapeRects>();
shape1->emplace_back(); shape1->emplace_back();
gfx::Transform transform; // Widget takes ownership of |shape1|.
transform.Scale(1.0f, 1.0f); widget1->SetShape(std::move(shape1));
x11_window1->SetShape(std::move(shape1), transform);
x11::Window windows[] = {window1}; x11::Window windows[] = {window1};
StackingClientListWaiter stack_waiter(windows, base::size(windows)); StackingClientListWaiter stack_waiter(windows, base::size(windows));
...@@ -448,18 +355,16 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangularNullShape) { ...@@ -448,18 +355,16 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangularNullShape) {
if (!ui::IsShapeExtensionAvailable()) if (!ui::IsShapeExtensionAvailable())
return; return;
TestPlatformWindowDelegate delegate; std::unique_ptr<Widget> widget1(
auto x11_window1 = CreateAndShowX11Window(&delegate, {100, 100, 100, 100}); CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
auto window1 = static_cast<x11::Window>(x11_window1->GetWidget()); x11::Window window1 = static_cast<x11::Window>(
widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
auto shape1 = std::make_unique<std::vector<gfx::Rect>>(); auto shape1 = std::make_unique<Widget::ShapeRects>();
shape1->emplace_back(); shape1->emplace_back();
gfx::Transform transform; widget1->SetShape(std::move(shape1));
transform.Scale(1.0f, 1.0f);
x11_window1->SetShape(std::move(shape1), transform);
// Remove the shape - this is now just a normal window. // Remove the shape - this is now just a normal window.
x11_window1->SetShape(nullptr, transform); widget1->SetShape(nullptr);
x11::Window windows[] = {window1}; x11::Window windows[] = {window1};
StackingClientListWaiter stack_waiter(windows, base::size(windows)); StackingClientListWaiter stack_waiter(windows, base::size(windows));
......
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