Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: ui/views/widget/desktop_aura/x11_topmost_window_finder_unittest.cc

Issue 356353002: Reenable X11TopmostWindowFinderTests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
6
7 #include <algorithm>
8 #include <vector>
9 #include <X11/extensions/shape.h>
10 #include <X11/Xlib.h>
11 #include <X11/Xregion.h>
12
13 // Get rid of X11 macros which conflict with gtest.
14 #undef Bool
15 #undef None
16
17 #include "base/memory/scoped_ptr.h"
18 #include "third_party/skia/include/core/SkRect.h"
19 #include "third_party/skia/include/core/SkRegion.h"
20 #include "ui/aura/window.h"
21 #include "ui/aura/window_tree_host.h"
22 #include "ui/events/platform/x11/x11_event_source.h"
23 #include "ui/gfx/path.h"
24 #include "ui/gfx/path_x11.h"
25 #include "ui/gfx/x/x11_atom_cache.h"
26 #include "ui/views/test/views_test_base.h"
27 #include "ui/views/test/x11_property_change_waiter.h"
28 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
29 #include "ui/views/widget/desktop_aura/x11_desktop_handler.h"
30 #include "ui/views/widget/widget.h"
31
32 namespace views {
33
34 namespace {
35
36 // Waits till |window| is minimized.
37 class MinimizeWaiter : public X11PropertyChangeWaiter {
38 public:
39 explicit MinimizeWaiter(XID window)
40 : X11PropertyChangeWaiter(window, "_NET_WM_STATE") {
41 const char* kAtomsToCache[] = { "_NET_WM_STATE_HIDDEN", NULL };
42 atom_cache_.reset(new ui::X11AtomCache(gfx::GetXDisplay(), kAtomsToCache));
43 }
44
45 virtual ~MinimizeWaiter() {
46 }
47
48 private:
49 // X11PropertyChangeWaiter:
50 virtual bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) OVERRIDE {
51 std::vector<Atom> wm_states;
52 if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) {
53 std::vector<Atom>::iterator it = std::find(
54 wm_states.begin(),
55 wm_states.end(),
56 atom_cache_->GetAtom("_NET_WM_STATE_HIDDEN"));
57 return it == wm_states.end();
58 }
59 return true;
60 }
61
62 scoped_ptr<ui::X11AtomCache> atom_cache_;
63
64 DISALLOW_COPY_AND_ASSIGN(MinimizeWaiter);
65 };
66
67 // Waits till |_NET_CLIENT_LIST_STACKING| is updated to include
68 // |expected_windows|.
69 class StackingClientListWaiter : public X11PropertyChangeWaiter {
70 public:
71 StackingClientListWaiter(XID* expected_windows, size_t count)
72 : X11PropertyChangeWaiter(ui::GetX11RootWindow(),
73 "_NET_CLIENT_LIST_STACKING"),
74 expected_windows_(expected_windows, expected_windows + count) {
75 }
76
77 virtual ~StackingClientListWaiter() {
78 }
79
80 // X11PropertyChangeWaiter:
81 virtual void Wait() OVERRIDE {
82 // StackingClientListWaiter may be created after
83 // _NET_CLIENT_LIST_STACKING already contains |expected_windows|.
84 if (!ShouldKeepOnWaiting(NULL))
85 return;
86
87 X11PropertyChangeWaiter::Wait();
88 }
89
90 private:
91 // X11PropertyChangeWaiter:
92 virtual bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) OVERRIDE {
93 std::vector<XID> stack;
94 ui::GetXWindowStack(ui::GetX11RootWindow(), &stack);
95 for (size_t i = 0; i < expected_windows_.size(); ++i) {
96 std::vector<XID>::iterator it = std::find(
97 stack.begin(), stack.end(), expected_windows_[i]);
98 if (it == stack.end())
99 return true;
100 }
101 return false;
102 }
103
104 std::vector<XID> expected_windows_;
105
106 DISALLOW_COPY_AND_ASSIGN(StackingClientListWaiter);
107 };
108
109 } // namespace
110
111 class X11TopmostWindowFinderTest : public ViewsTestBase {
112 public:
113 X11TopmostWindowFinderTest() {
114 }
115
116 virtual ~X11TopmostWindowFinderTest() {
117 }
118
119 // Creates and shows a Widget with |bounds|. The caller takes ownership of
120 // the returned widget.
121 scoped_ptr<Widget> CreateAndShowWidget(const gfx::Rect& bounds) {
122 scoped_ptr<Widget> toplevel(new Widget);
123 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
124 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
125 params.native_widget = new DesktopNativeWidgetAura(toplevel.get());
126 params.bounds = bounds;
127 params.remove_standard_frame = true;
128 toplevel->Init(params);
129 toplevel->Show();
130 return toplevel.Pass();
131 }
132
133 // Creates and shows an X window with |bounds|.
134 XID CreateAndShowXWindow(const gfx::Rect& bounds) {
135 XID root = DefaultRootWindow(xdisplay());
136 XID xid = XCreateSimpleWindow(xdisplay(),
137 root,
138 0, 0, 1, 1,
139 0, // border_width
140 0, // border
141 0); // background
142
143 ui::SetUseOSWindowFrame(xid, false);
144 ShowAndSetXWindowBounds(xid, bounds);
145 return xid;
146 }
147
148 // Shows |xid| and sets its bounds.
149 void ShowAndSetXWindowBounds(XID xid, const gfx::Rect& bounds) {
150 XMapWindow(xdisplay(), xid);
151
152 XWindowChanges changes = {0};
153 changes.x = bounds.x();
154 changes.y = bounds.y();
155 changes.width = bounds.width();
156 changes.height = bounds.height();
157 XConfigureWindow(xdisplay(),
158 xid,
159 CWX | CWY | CWWidth | CWHeight,
160 &changes);
161 }
162
163 Display* xdisplay() {
164 return gfx::GetXDisplay();
165 }
166
167 // Returns the topmost X window at the passed in screen position.
168 XID FindTopmostXWindowAt(int screen_x, int screen_y) {
169 X11TopmostWindowFinder finder;
170 return finder.FindWindowAt(gfx::Point(screen_x, screen_y));
171 }
172
173 // Returns the topmost aura::Window at the passed in screen position. Returns
174 // NULL if the topmost window does not have an associated aura::Window.
175 aura::Window* FindTopmostLocalProcessWindowAt(int screen_x, int screen_y) {
176 X11TopmostWindowFinder finder;
177 return finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y),
178 std::set<aura::Window*>());
179 }
180
181 // Returns the topmost aura::Window at the passed in screen position ignoring
182 // |ignore_window|. Returns NULL if the topmost window does not have an
183 // associated aura::Window.
184 aura::Window* FindTopmostLocalProcessWindowWithIgnore(
185 int screen_x,
186 int screen_y,
187 aura::Window* ignore_window) {
188 std::set<aura::Window*> ignore;
189 ignore.insert(ignore_window);
190 X11TopmostWindowFinder finder;
191 return finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y),
192 ignore);
193 }
194
195 // ViewsTestBase:
196 virtual void SetUp() OVERRIDE {
197 ViewsTestBase::SetUp();
198
199 // Make X11 synchronous for our display connection. This does not force the
200 // window manager to behave synchronously.
201 XSynchronize(xdisplay(), True);
202
203 // Ensure that the X11DesktopHandler exists. The X11DesktopHandler is
204 // necessary to properly track menu windows.
205 X11DesktopHandler::get();
206 }
207
208 virtual void TearDown() OVERRIDE {
209 XSynchronize(xdisplay(), False);
210 ViewsTestBase::TearDown();
211 }
212
213 private:
214 DISALLOW_COPY_AND_ASSIGN(X11TopmostWindowFinderTest);
215 };
216
217 // Flaky on Linux. http://crbug.com/388241
218 TEST_F(X11TopmostWindowFinderTest, DISABLED_Basic) {
219 // Avoid positioning test windows at 0x0 because window managers often have a
220 // panel/launcher along one of the screen edges and do not allow windows to
221 // position themselves to overlap the panel/launcher.
222 scoped_ptr<Widget> widget1(
223 CreateAndShowWidget(gfx::Rect(100, 100, 200, 100)));
224 aura::Window* window1 = widget1->GetNativeWindow();
225 XID xid1 = window1->GetHost()->GetAcceleratedWidget();
226
227 XID xid2 = CreateAndShowXWindow(gfx::Rect(200, 100, 100, 200));
228
229 scoped_ptr<Widget> widget3(
230 CreateAndShowWidget(gfx::Rect(100, 190, 200, 110)));
231 aura::Window* window3 = widget3->GetNativeWindow();
232 XID xid3 = window3->GetHost()->GetAcceleratedWidget();
233
234 XID xids[] = { xid1, xid2, xid3 };
235 StackingClientListWaiter waiter(xids, arraysize(xids));
236 waiter.Wait();
237 ui::X11EventSource::GetInstance()->DispatchXEvents();
238
239 EXPECT_EQ(xid1, FindTopmostXWindowAt(150, 150));
240 EXPECT_EQ(window1, FindTopmostLocalProcessWindowAt(150, 150));
241
242 EXPECT_EQ(xid2, FindTopmostXWindowAt(250, 150));
243 EXPECT_EQ(NULL, FindTopmostLocalProcessWindowAt(250, 150));
244
245 EXPECT_EQ(xid3, FindTopmostXWindowAt(250, 250));
246 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(250, 250));
247
248 EXPECT_EQ(xid3, FindTopmostXWindowAt(150, 250));
249 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 250));
250
251 EXPECT_EQ(xid3, FindTopmostXWindowAt(150, 195));
252 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 195));
253
254 EXPECT_NE(xid1, FindTopmostXWindowAt(1000, 1000));
255 EXPECT_NE(xid2, FindTopmostXWindowAt(1000, 1000));
256 EXPECT_NE(xid3, FindTopmostXWindowAt(1000, 1000));
257 EXPECT_EQ(NULL, FindTopmostLocalProcessWindowAt(1000, 1000));
258
259 EXPECT_EQ(window1,
260 FindTopmostLocalProcessWindowWithIgnore(150, 150, window3));
261 EXPECT_EQ(NULL,
262 FindTopmostLocalProcessWindowWithIgnore(250, 250, window3));
263 EXPECT_EQ(NULL,
264 FindTopmostLocalProcessWindowWithIgnore(150, 250, window3));
265 EXPECT_EQ(window1,
266 FindTopmostLocalProcessWindowWithIgnore(150, 195, window3));
267
268 XDestroyWindow(xdisplay(), xid2);
269 }
270
271 // Test that the minimized state is properly handled.
272 // Flaky on Linux. http://crbug.com/388241
273 TEST_F(X11TopmostWindowFinderTest, DISABLED_Minimized) {
274 scoped_ptr<Widget> widget1(
275 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
276 aura::Window* window1 = widget1->GetNativeWindow();
277 XID xid1 = window1->GetHost()->GetAcceleratedWidget();
278 XID xid2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100));
279
280 XID xids[] = { xid1, xid2 };
281 StackingClientListWaiter stack_waiter(xids, arraysize(xids));
282 stack_waiter.Wait();
283 ui::X11EventSource::GetInstance()->DispatchXEvents();
284
285 EXPECT_EQ(xid1, FindTopmostXWindowAt(150, 150));
286 {
287 MinimizeWaiter minimize_waiter(xid1);
288 XIconifyWindow(xdisplay(), xid1, 0);
289 minimize_waiter.Wait();
290 }
291 EXPECT_NE(xid1, FindTopmostXWindowAt(150, 150));
292 EXPECT_NE(xid2, FindTopmostXWindowAt(150, 150));
293
294 // Repeat test for an X window which does not belong to a views::Widget
295 // because the code path is different.
296 EXPECT_EQ(xid2, FindTopmostXWindowAt(350, 150));
297 {
298 MinimizeWaiter minimize_waiter(xid2);
299 XIconifyWindow(xdisplay(), xid2, 0);
300 minimize_waiter.Wait();
301 }
302 EXPECT_NE(xid1, FindTopmostXWindowAt(350, 150));
303 EXPECT_NE(xid2, FindTopmostXWindowAt(350, 150));
304
305 XDestroyWindow(xdisplay(), xid2);
306 }
307
308 // Test that non-rectangular windows are properly handled.
309 // Flaky on Linux. http://crbug.com/388241
310 TEST_F(X11TopmostWindowFinderTest, DISABLED_NonRectangular) {
311 if (!ui::IsShapeExtensionAvailable())
312 return;
313
314 scoped_ptr<Widget> widget1(
315 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
316 XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
317 SkRegion* skregion1 = new SkRegion;
318 skregion1->op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op);
319 skregion1->op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op);
320 // Widget takes ownership of |skregion1|.
321 widget1->SetShape(skregion1);
322
323 SkRegion skregion2;
324 skregion2.op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op);
325 skregion2.op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op);
326 XID xid2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100));
327 REGION* region2 = gfx::CreateRegionFromSkRegion(skregion2);
328 XShapeCombineRegion(xdisplay(), xid2, ShapeBounding, 0, 0, region2,
329 false);
330 XDestroyRegion(region2);
331
332 XID xids[] = { xid1, xid2 };
333 StackingClientListWaiter stack_waiter(xids, arraysize(xids));
334 stack_waiter.Wait();
335 ui::X11EventSource::GetInstance()->DispatchXEvents();
336
337 EXPECT_EQ(xid1, FindTopmostXWindowAt(105, 120));
338 EXPECT_NE(xid1, FindTopmostXWindowAt(105, 105));
339 EXPECT_NE(xid2, FindTopmostXWindowAt(105, 105));
340
341 // Repeat test for an X window which does not belong to a views::Widget
342 // because the code path is different.
343 EXPECT_EQ(xid2, FindTopmostXWindowAt(305, 120));
344 EXPECT_NE(xid1, FindTopmostXWindowAt(305, 105));
345 EXPECT_NE(xid2, FindTopmostXWindowAt(305, 105));
346
347 XDestroyWindow(xdisplay(), xid2);
348 }
349
350 // Test that the TopmostWindowFinder finds windows which belong to menus
351 // (which may or may not belong to Chrome).
352 // Flaky on Linux. http://crbug.com/388241
353 TEST_F(X11TopmostWindowFinderTest, DISABLED_Menu) {
354 XID xid = CreateAndShowXWindow(gfx::Rect(100, 100, 100, 100));
355
356 XID root = DefaultRootWindow(xdisplay());
357 XSetWindowAttributes swa;
358 swa.override_redirect = True;
359 XID menu_xid = XCreateWindow(xdisplay(),
360 root,
361 0, 0, 1, 1,
362 0, // border width
363 CopyFromParent, // depth
364 InputOutput,
365 CopyFromParent, // visual
366 CWOverrideRedirect,
367 &swa);
368 {
369 const char* kAtomsToCache[] = { "_NET_WM_WINDOW_TYPE_MENU", NULL };
370 ui::X11AtomCache atom_cache(gfx::GetXDisplay(), kAtomsToCache);
371 ui::SetAtomProperty(menu_xid,
372 "_NET_WM_WINDOW_TYPE",
373 "ATOM",
374 atom_cache.GetAtom("_NET_WM_WINDOW_TYPE_MENU"));
375 }
376 ui::SetUseOSWindowFrame(menu_xid, false);
377 ShowAndSetXWindowBounds(menu_xid, gfx::Rect(140, 110, 100, 100));
378 ui::X11EventSource::GetInstance()->DispatchXEvents();
379
380 // |menu_xid| is never added to _NET_CLIENT_LIST_STACKING.
381 XID xids[] = { xid };
382 StackingClientListWaiter stack_waiter(xids, arraysize(xids));
383 stack_waiter.Wait();
384
385 EXPECT_EQ(xid, FindTopmostXWindowAt(110, 110));
386 EXPECT_EQ(menu_xid, FindTopmostXWindowAt(150, 120));
387 EXPECT_EQ(menu_xid, FindTopmostXWindowAt(210, 120));
388
389 XDestroyWindow(xdisplay(), xid);
390 XDestroyWindow(xdisplay(), menu_xid);
391 }
392
393 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698