window_finder_x11.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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 "chrome/browser/ui/views/tabs/window_finder.h" 6 7#include "base/debug/trace_event.h" 8#include "chrome/browser/ui/host_desktop.h" 9#include "ui/aura/window.h" 10#include "ui/aura/window_tree_host.h" 11#include "ui/base/x/x11_util.h" 12#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" 13 14#if defined(USE_ASH) 15aura::Window* GetLocalProcessWindowAtPointAsh( 16 const gfx::Point& screen_point, 17 const std::set<aura::Window*>& ignore); 18#endif 19 20namespace { 21 22//////////////////////////////////////////////////////////////////////////////// 23// BaseWindowFinder 24// 25// Base class used to locate a window. A subclass need only override 26// ShouldStopIterating to determine when iteration should stop. 27class BaseWindowFinder : public ui::EnumerateWindowsDelegate { 28 public: 29 explicit BaseWindowFinder(const std::set<aura::Window*>& ignore) { 30 std::set<aura::Window*>::iterator iter; 31 for (iter = ignore.begin(); iter != ignore.end(); iter++) { 32 XID xid = (*iter)->GetHost()->GetAcceleratedWidget(); 33 ignore_.insert(xid); 34 } 35 } 36 37 virtual ~BaseWindowFinder() {} 38 39 protected: 40 // Returns true if |window| is in the ignore list. 41 bool ShouldIgnoreWindow(XID window) { 42 return (ignore_.find(window) != ignore_.end()); 43 } 44 45 // Returns true if iteration should stop, false otherwise. 46 virtual bool ShouldStopIterating(XID window) OVERRIDE { 47 return false; 48 } 49 50 private: 51 std::set<XID> ignore_; 52 53 DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder); 54}; 55 56//////////////////////////////////////////////////////////////////////////////// 57// TopMostFinder 58// 59// Helper class to determine if a particular point of a window is not obscured 60// by another window. 61class TopMostFinder : public BaseWindowFinder { 62 public: 63 // Returns true if |window| is not obscured by another window at the 64 // location |screen_loc|, not including the windows in |ignore|. 65 static bool IsTopMostWindowAtPoint(XID window, 66 const gfx::Point& screen_loc, 67 const std::set<aura::Window*>& ignore) { 68 TopMostFinder finder(window, screen_loc, ignore); 69 return finder.is_top_most_; 70 } 71 72 protected: 73 virtual bool ShouldStopIterating(XID window) OVERRIDE { 74 if (BaseWindowFinder::ShouldIgnoreWindow(window)) 75 return false; 76 77 if (window == target_) { 78 // Window is topmost, stop iterating. 79 is_top_most_ = true; 80 return true; 81 } 82 83 if (!ui::IsWindowVisible(window)) { 84 // The window isn't visible, keep iterating. 85 return false; 86 } 87 88 // At this point we haven't found our target window, so this window is 89 // higher in the z-order than the target window. If this window contains 90 // the point, then we can stop the search now because this window is 91 // obscuring the target window at this point. 92 return ui::WindowContainsPoint(window, screen_loc_); 93 } 94 95 private: 96 TopMostFinder(XID window, 97 const gfx::Point& screen_loc, 98 const std::set<aura::Window*>& ignore) 99 : BaseWindowFinder(ignore), 100 target_(window), 101 screen_loc_(screen_loc), 102 is_top_most_(false) { 103 ui::EnumerateTopLevelWindows(this); 104 } 105 106 // The window we're looking for. 107 XID target_; 108 109 // Location of window to find. 110 gfx::Point screen_loc_; 111 112 // Is target_ the top most window? This is initially false but set to true 113 // in ShouldStopIterating if target_ is passed in. 114 bool is_top_most_; 115 116 DISALLOW_COPY_AND_ASSIGN(TopMostFinder); 117}; 118 119//////////////////////////////////////////////////////////////////////////////// 120// LocalProcessWindowFinder 121// 122// Helper class to determine if a particular point of a window from our process 123// is not obscured by another window. 124class LocalProcessWindowFinder : public BaseWindowFinder { 125 public: 126 // Returns the XID from our process at screen_loc that is not obscured by 127 // another window. Returns 0 otherwise. 128 static XID GetProcessWindowAtPoint(const gfx::Point& screen_loc, 129 const std::set<aura::Window*>& ignore) { 130 LocalProcessWindowFinder finder(screen_loc, ignore); 131 if (finder.result_ && 132 TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc, 133 ignore)) { 134 return finder.result_; 135 } 136 return 0; 137 } 138 139 protected: 140 virtual bool ShouldStopIterating(XID window) OVERRIDE { 141 if (BaseWindowFinder::ShouldIgnoreWindow(window)) 142 return false; 143 144 // Check if this window is in our process. 145 if (!aura::WindowTreeHost::GetForAcceleratedWidget(window)) 146 return false; 147 148 if (!ui::IsWindowVisible(window)) 149 return false; 150 151 if (ui::WindowContainsPoint(window, screen_loc_)) { 152 result_ = window; 153 return true; 154 } 155 156 return false; 157 } 158 159 private: 160 LocalProcessWindowFinder(const gfx::Point& screen_loc, 161 const std::set<aura::Window*>& ignore) 162 : BaseWindowFinder(ignore), 163 screen_loc_(screen_loc), 164 result_(0) { 165 ui::EnumerateTopLevelWindows(this); 166 } 167 168 // Position of the mouse. 169 gfx::Point screen_loc_; 170 171 // The resulting window. This is initially null but set to true in 172 // ShouldStopIterating if an appropriate window is found. 173 XID result_; 174 175 DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder); 176}; 177 178} // namespace 179 180aura::Window* GetLocalProcessWindowAtPoint( 181 chrome::HostDesktopType host_desktop_type, 182 const gfx::Point& screen_point, 183 const std::set<aura::Window*>& ignore) { 184#if defined(USE_ASH) 185 if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) 186 return GetLocalProcessWindowAtPointAsh(screen_point, ignore); 187#endif 188 // The X11 server is the canonical state of what the window stacking order 189 // is. 190 XID xid = 191 LocalProcessWindowFinder::GetProcessWindowAtPoint(screen_point, ignore); 192 return views::DesktopWindowTreeHostX11::GetContentWindowForXID(xid); 193} 194