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