| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" | 5 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" |
| 6 | 6 |
| 7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
| 8 #include <X11/Xregion.h> | 8 #include <X11/Xregion.h> |
| 9 #include <X11/extensions/shape.h> | 9 #include <X11/extensions/shape.h> |
| 10 #include <stddef.h> | 10 #include <stddef.h> |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 | 38 |
| 39 namespace views { | 39 namespace views { |
| 40 | 40 |
| 41 namespace { | 41 namespace { |
| 42 | 42 |
| 43 // Waits till |window| is minimized. | 43 // Waits till |window| is minimized. |
| 44 class MinimizeWaiter : public X11PropertyChangeWaiter { | 44 class MinimizeWaiter : public X11PropertyChangeWaiter { |
| 45 public: | 45 public: |
| 46 explicit MinimizeWaiter(XID window) | 46 explicit MinimizeWaiter(XID window) |
| 47 : X11PropertyChangeWaiter(window, "_NET_WM_STATE") { | 47 : X11PropertyChangeWaiter(window, "_NET_WM_STATE") { |
| 48 const char* kAtomsToCache[] = { "_NET_WM_STATE_HIDDEN", NULL }; | 48 const char* const kAtomsToCache[] = {"_NET_WM_STATE_HIDDEN", nullptr}; |
| 49 atom_cache_.reset(new ui::X11AtomCache(gfx::GetXDisplay(), kAtomsToCache)); | 49 atom_cache_.reset(new ui::X11AtomCache(gfx::GetXDisplay(), kAtomsToCache)); |
| 50 } | 50 } |
| 51 | 51 |
| 52 ~MinimizeWaiter() override {} | 52 ~MinimizeWaiter() override {} |
| 53 | 53 |
| 54 private: | 54 private: |
| 55 // X11PropertyChangeWaiter: | 55 // X11PropertyChangeWaiter: |
| 56 bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { | 56 bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { |
| 57 std::vector<Atom> wm_states; | 57 std::vector<Atom> wm_states; |
| 58 if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) { | 58 if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 77 "_NET_CLIENT_LIST_STACKING"), | 77 "_NET_CLIENT_LIST_STACKING"), |
| 78 expected_windows_(expected_windows, expected_windows + count) { | 78 expected_windows_(expected_windows, expected_windows + count) { |
| 79 } | 79 } |
| 80 | 80 |
| 81 ~StackingClientListWaiter() override {} | 81 ~StackingClientListWaiter() override {} |
| 82 | 82 |
| 83 // X11PropertyChangeWaiter: | 83 // X11PropertyChangeWaiter: |
| 84 void Wait() override { | 84 void Wait() override { |
| 85 // StackingClientListWaiter may be created after | 85 // StackingClientListWaiter may be created after |
| 86 // _NET_CLIENT_LIST_STACKING already contains |expected_windows|. | 86 // _NET_CLIENT_LIST_STACKING already contains |expected_windows|. |
| 87 if (!ShouldKeepOnWaiting(NULL)) | 87 if (!ShouldKeepOnWaiting(nullptr)) |
| 88 return; | 88 return; |
| 89 | 89 |
| 90 X11PropertyChangeWaiter::Wait(); | 90 X11PropertyChangeWaiter::Wait(); |
| 91 } | 91 } |
| 92 | 92 |
| 93 private: | 93 private: |
| 94 // X11PropertyChangeWaiter: | 94 // X11PropertyChangeWaiter: |
| 95 bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { | 95 bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { |
| 96 std::vector<XID> stack; | 96 std::vector<XID> stack; |
| 97 ui::GetXWindowStack(ui::GetX11RootWindow(), &stack); | 97 ui::GetXWindowStack(ui::GetX11RootWindow(), &stack); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 | 241 |
| 242 XID xids[] = { xid1, xid2, xid3 }; | 242 XID xids[] = { xid1, xid2, xid3 }; |
| 243 StackingClientListWaiter waiter(xids, arraysize(xids)); | 243 StackingClientListWaiter waiter(xids, arraysize(xids)); |
| 244 waiter.Wait(); | 244 waiter.Wait(); |
| 245 ui::X11EventSource::GetInstance()->DispatchXEvents(); | 245 ui::X11EventSource::GetInstance()->DispatchXEvents(); |
| 246 | 246 |
| 247 EXPECT_EQ(xid1, FindTopmostXWindowAt(150, 150)); | 247 EXPECT_EQ(xid1, FindTopmostXWindowAt(150, 150)); |
| 248 EXPECT_EQ(window1, FindTopmostLocalProcessWindowAt(150, 150)); | 248 EXPECT_EQ(window1, FindTopmostLocalProcessWindowAt(150, 150)); |
| 249 | 249 |
| 250 EXPECT_EQ(xid2, FindTopmostXWindowAt(250, 150)); | 250 EXPECT_EQ(xid2, FindTopmostXWindowAt(250, 150)); |
| 251 EXPECT_EQ(NULL, FindTopmostLocalProcessWindowAt(250, 150)); | 251 EXPECT_FALSE(FindTopmostLocalProcessWindowAt(250, 150)); |
| 252 | 252 |
| 253 EXPECT_EQ(xid3, FindTopmostXWindowAt(250, 250)); | 253 EXPECT_EQ(xid3, FindTopmostXWindowAt(250, 250)); |
| 254 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(250, 250)); | 254 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(250, 250)); |
| 255 | 255 |
| 256 EXPECT_EQ(xid3, FindTopmostXWindowAt(150, 250)); | 256 EXPECT_EQ(xid3, FindTopmostXWindowAt(150, 250)); |
| 257 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 250)); | 257 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 250)); |
| 258 | 258 |
| 259 EXPECT_EQ(xid3, FindTopmostXWindowAt(150, 195)); | 259 EXPECT_EQ(xid3, FindTopmostXWindowAt(150, 195)); |
| 260 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 195)); | 260 EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 195)); |
| 261 | 261 |
| 262 EXPECT_NE(xid1, FindTopmostXWindowAt(1000, 1000)); | 262 EXPECT_NE(xid1, FindTopmostXWindowAt(1000, 1000)); |
| 263 EXPECT_NE(xid2, FindTopmostXWindowAt(1000, 1000)); | 263 EXPECT_NE(xid2, FindTopmostXWindowAt(1000, 1000)); |
| 264 EXPECT_NE(xid3, FindTopmostXWindowAt(1000, 1000)); | 264 EXPECT_NE(xid3, FindTopmostXWindowAt(1000, 1000)); |
| 265 EXPECT_EQ(NULL, FindTopmostLocalProcessWindowAt(1000, 1000)); | 265 EXPECT_FALSE(FindTopmostLocalProcessWindowAt(1000, 1000)); |
| 266 | 266 |
| 267 EXPECT_EQ(window1, | 267 EXPECT_EQ(window1, |
| 268 FindTopmostLocalProcessWindowWithIgnore(150, 150, window3)); | 268 FindTopmostLocalProcessWindowWithIgnore(150, 150, window3)); |
| 269 EXPECT_EQ(NULL, | 269 EXPECT_FALSE(FindTopmostLocalProcessWindowWithIgnore(250, 250, window3)); |
| 270 FindTopmostLocalProcessWindowWithIgnore(250, 250, window3)); | 270 EXPECT_FALSE(FindTopmostLocalProcessWindowWithIgnore(150, 250, window3)); |
| 271 EXPECT_EQ(NULL, | |
| 272 FindTopmostLocalProcessWindowWithIgnore(150, 250, window3)); | |
| 273 EXPECT_EQ(window1, | 271 EXPECT_EQ(window1, |
| 274 FindTopmostLocalProcessWindowWithIgnore(150, 195, window3)); | 272 FindTopmostLocalProcessWindowWithIgnore(150, 195, window3)); |
| 275 | 273 |
| 276 XDestroyWindow(xdisplay(), xid2); | 274 XDestroyWindow(xdisplay(), xid2); |
| 277 } | 275 } |
| 278 | 276 |
| 279 // Test that the minimized state is properly handled. | 277 // Test that the minimized state is properly handled. |
| 280 TEST_F(X11TopmostWindowFinderTest, Minimized) { | 278 TEST_F(X11TopmostWindowFinderTest, Minimized) { |
| 281 std::unique_ptr<Widget> widget1( | 279 std::unique_ptr<Widget> widget1( |
| 282 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100))); | 280 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100))); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 313 } | 311 } |
| 314 | 312 |
| 315 // Test that non-rectangular windows are properly handled. | 313 // Test that non-rectangular windows are properly handled. |
| 316 TEST_F(X11TopmostWindowFinderTest, NonRectangular) { | 314 TEST_F(X11TopmostWindowFinderTest, NonRectangular) { |
| 317 if (!ui::IsShapeExtensionAvailable()) | 315 if (!ui::IsShapeExtensionAvailable()) |
| 318 return; | 316 return; |
| 319 | 317 |
| 320 std::unique_ptr<Widget> widget1( | 318 std::unique_ptr<Widget> widget1( |
| 321 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100))); | 319 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100))); |
| 322 XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); | 320 XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); |
| 323 SkRegion* skregion1 = new SkRegion; | 321 auto skregion1 = base::MakeUnique<SkRegion>(); |
| 324 skregion1->op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op); | 322 skregion1->op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op); |
| 325 skregion1->op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op); | 323 skregion1->op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op); |
| 326 // Widget takes ownership of |skregion1|. | 324 widget1->SetShape(std::move(skregion1)); |
| 327 widget1->SetShape(skregion1); | |
| 328 | 325 |
| 329 SkRegion skregion2; | 326 SkRegion skregion2; |
| 330 skregion2.op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op); | 327 skregion2.op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op); |
| 331 skregion2.op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op); | 328 skregion2.op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op); |
| 332 XID xid2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100)); | 329 XID xid2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100)); |
| 333 gfx::XScopedPtr<REGION, gfx::XObjectDeleter<REGION, int, XDestroyRegion>> | 330 gfx::XScopedPtr<REGION, gfx::XObjectDeleter<REGION, int, XDestroyRegion>> |
| 334 region2(gfx::CreateRegionFromSkRegion(skregion2)); | 331 region2(gfx::CreateRegionFromSkRegion(skregion2)); |
| 335 XShapeCombineRegion(xdisplay(), xid2, ShapeBounding, 0, 0, region2.get(), | 332 XShapeCombineRegion(xdisplay(), xid2, ShapeBounding, 0, 0, region2.get(), |
| 336 false); | 333 false); |
| 337 XID xids[] = { xid1, xid2 }; | 334 XID xids[] = { xid1, xid2 }; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 353 } | 350 } |
| 354 | 351 |
| 355 // Test that a window with an empty shape are properly handled. | 352 // Test that a window with an empty shape are properly handled. |
| 356 TEST_F(X11TopmostWindowFinderTest, NonRectangularEmptyShape) { | 353 TEST_F(X11TopmostWindowFinderTest, NonRectangularEmptyShape) { |
| 357 if (!ui::IsShapeExtensionAvailable()) | 354 if (!ui::IsShapeExtensionAvailable()) |
| 358 return; | 355 return; |
| 359 | 356 |
| 360 std::unique_ptr<Widget> widget1( | 357 std::unique_ptr<Widget> widget1( |
| 361 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100))); | 358 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100))); |
| 362 XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); | 359 XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); |
| 363 SkRegion* skregion1 = new SkRegion; | 360 auto skregion1 = base::MakeUnique<SkRegion>(); |
| 364 skregion1->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op); | 361 skregion1->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op); |
| 365 // Widget takes ownership of |skregion1|. | 362 // Widget takes ownership of |skregion1|. |
| 366 widget1->SetShape(skregion1); | 363 widget1->SetShape(std::move(skregion1)); |
| 367 | 364 |
| 368 XID xids[] = { xid1 }; | 365 XID xids[] = { xid1 }; |
| 369 StackingClientListWaiter stack_waiter(xids, arraysize(xids)); | 366 StackingClientListWaiter stack_waiter(xids, arraysize(xids)); |
| 370 stack_waiter.Wait(); | 367 stack_waiter.Wait(); |
| 371 ui::X11EventSource::GetInstance()->DispatchXEvents(); | 368 ui::X11EventSource::GetInstance()->DispatchXEvents(); |
| 372 | 369 |
| 373 EXPECT_NE(xid1, FindTopmostXWindowAt(105, 105)); | 370 EXPECT_NE(xid1, FindTopmostXWindowAt(105, 105)); |
| 374 } | 371 } |
| 375 | 372 |
| 376 // Test that setting a Null shape removes the shape. | 373 // Test that setting a Null shape removes the shape. |
| 377 TEST_F(X11TopmostWindowFinderTest, NonRectangularNullShape) { | 374 TEST_F(X11TopmostWindowFinderTest, NonRectangularNullShape) { |
| 378 if (!ui::IsShapeExtensionAvailable()) | 375 if (!ui::IsShapeExtensionAvailable()) |
| 379 return; | 376 return; |
| 380 | 377 |
| 381 std::unique_ptr<Widget> widget1( | 378 std::unique_ptr<Widget> widget1( |
| 382 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100))); | 379 CreateAndShowWidget(gfx::Rect(100, 100, 100, 100))); |
| 383 XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); | 380 XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); |
| 384 SkRegion* skregion1 = new SkRegion; | 381 auto skregion1 = base::MakeUnique<SkRegion>(); |
| 385 skregion1->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op); | 382 skregion1->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op); |
| 386 // Widget takes ownership of |skregion1|. | 383 widget1->SetShape(std::move(skregion1)); |
| 387 widget1->SetShape(skregion1); | |
| 388 | 384 |
| 389 // Remove the shape - this is now just a normal window. | 385 // Remove the shape - this is now just a normal window. |
| 390 widget1->SetShape(NULL); | 386 widget1->SetShape(nullptr); |
| 391 | 387 |
| 392 XID xids[] = { xid1 }; | 388 XID xids[] = { xid1 }; |
| 393 StackingClientListWaiter stack_waiter(xids, arraysize(xids)); | 389 StackingClientListWaiter stack_waiter(xids, arraysize(xids)); |
| 394 stack_waiter.Wait(); | 390 stack_waiter.Wait(); |
| 395 ui::X11EventSource::GetInstance()->DispatchXEvents(); | 391 ui::X11EventSource::GetInstance()->DispatchXEvents(); |
| 396 | 392 |
| 397 EXPECT_EQ(xid1, FindTopmostXWindowAt(105, 105)); | 393 EXPECT_EQ(xid1, FindTopmostXWindowAt(105, 105)); |
| 398 } | 394 } |
| 399 | 395 |
| 400 // Test that the TopmostWindowFinder finds windows which belong to menus | 396 // Test that the TopmostWindowFinder finds windows which belong to menus |
| 401 // (which may or may not belong to Chrome). | 397 // (which may or may not belong to Chrome). |
| 402 TEST_F(X11TopmostWindowFinderTest, Menu) { | 398 TEST_F(X11TopmostWindowFinderTest, Menu) { |
| 403 XID xid = CreateAndShowXWindow(gfx::Rect(100, 100, 100, 100)); | 399 XID xid = CreateAndShowXWindow(gfx::Rect(100, 100, 100, 100)); |
| 404 | 400 |
| 405 XID root = DefaultRootWindow(xdisplay()); | 401 XID root = DefaultRootWindow(xdisplay()); |
| 406 XSetWindowAttributes swa; | 402 XSetWindowAttributes swa; |
| 407 swa.override_redirect = True; | 403 swa.override_redirect = True; |
| 408 XID menu_xid = XCreateWindow(xdisplay(), | 404 XID menu_xid = XCreateWindow(xdisplay(), |
| 409 root, | 405 root, |
| 410 0, 0, 1, 1, | 406 0, 0, 1, 1, |
| 411 0, // border width | 407 0, // border width |
| 412 CopyFromParent, // depth | 408 CopyFromParent, // depth |
| 413 InputOutput, | 409 InputOutput, |
| 414 CopyFromParent, // visual | 410 CopyFromParent, // visual |
| 415 CWOverrideRedirect, | 411 CWOverrideRedirect, |
| 416 &swa); | 412 &swa); |
| 417 { | 413 { |
| 418 const char* kAtomsToCache[] = { "_NET_WM_WINDOW_TYPE_MENU", NULL }; | 414 const char* const kAtomsToCache[] = {"_NET_WM_WINDOW_TYPE_MENU", nullptr}; |
| 419 ui::X11AtomCache atom_cache(gfx::GetXDisplay(), kAtomsToCache); | 415 ui::X11AtomCache atom_cache(gfx::GetXDisplay(), kAtomsToCache); |
| 420 ui::SetAtomProperty(menu_xid, | 416 ui::SetAtomProperty(menu_xid, |
| 421 "_NET_WM_WINDOW_TYPE", | 417 "_NET_WM_WINDOW_TYPE", |
| 422 "ATOM", | 418 "ATOM", |
| 423 atom_cache.GetAtom("_NET_WM_WINDOW_TYPE_MENU")); | 419 atom_cache.GetAtom("_NET_WM_WINDOW_TYPE_MENU")); |
| 424 } | 420 } |
| 425 ui::SetUseOSWindowFrame(menu_xid, false); | 421 ui::SetUseOSWindowFrame(menu_xid, false); |
| 426 ShowAndSetXWindowBounds(menu_xid, gfx::Rect(140, 110, 100, 100)); | 422 ShowAndSetXWindowBounds(menu_xid, gfx::Rect(140, 110, 100, 100)); |
| 427 ui::X11EventSource::GetInstance()->DispatchXEvents(); | 423 ui::X11EventSource::GetInstance()->DispatchXEvents(); |
| 428 | 424 |
| 429 // |menu_xid| is never added to _NET_CLIENT_LIST_STACKING. | 425 // |menu_xid| is never added to _NET_CLIENT_LIST_STACKING. |
| 430 XID xids[] = { xid }; | 426 XID xids[] = { xid }; |
| 431 StackingClientListWaiter stack_waiter(xids, arraysize(xids)); | 427 StackingClientListWaiter stack_waiter(xids, arraysize(xids)); |
| 432 stack_waiter.Wait(); | 428 stack_waiter.Wait(); |
| 433 | 429 |
| 434 EXPECT_EQ(xid, FindTopmostXWindowAt(110, 110)); | 430 EXPECT_EQ(xid, FindTopmostXWindowAt(110, 110)); |
| 435 EXPECT_EQ(menu_xid, FindTopmostXWindowAt(150, 120)); | 431 EXPECT_EQ(menu_xid, FindTopmostXWindowAt(150, 120)); |
| 436 EXPECT_EQ(menu_xid, FindTopmostXWindowAt(210, 120)); | 432 EXPECT_EQ(menu_xid, FindTopmostXWindowAt(210, 120)); |
| 437 | 433 |
| 438 XDestroyWindow(xdisplay(), xid); | 434 XDestroyWindow(xdisplay(), xid); |
| 439 XDestroyWindow(xdisplay(), menu_xid); | 435 XDestroyWindow(xdisplay(), menu_xid); |
| 440 } | 436 } |
| 441 | 437 |
| 442 } // namespace views | 438 } // namespace views |
| OLD | NEW |