This source file includes following definitions.
- WindowCallbackProc
- as_lparam
- IsTopMostWindowAtPoint
- ShouldStopIterating
- tmp_region_
- GetProcessWindowAtPoint
- ShouldStopIterating
- result_
- RemapIgnoreSet
- GetLocalProcessWindowAtPoint
#include "chrome/browser/ui/views/tabs/window_finder.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/windows_version.h"
#include "ui/aura/window.h"
#include "ui/gfx/screen.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
#include "ui/views/win/hwnd_util.h"
#if defined(USE_ASH)
aura::Window* GetLocalProcessWindowAtPointAsh(
const gfx::Point& screen_point,
const std::set<aura::Window*>& ignore);
#endif
namespace {
class BaseWindowFinder {
public:
explicit BaseWindowFinder(const std::set<HWND>& ignore) : ignore_(ignore) {}
virtual ~BaseWindowFinder() {}
protected:
static BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) {
BaseWindowFinder* finder = reinterpret_cast<BaseWindowFinder*>(lParam);
if (finder->ignore_.find(hwnd) != finder->ignore_.end())
return TRUE;
return finder->ShouldStopIterating(hwnd) ? FALSE : TRUE;
}
LPARAM as_lparam() {
return reinterpret_cast<LPARAM>(static_cast<BaseWindowFinder*>(this));
}
virtual bool ShouldStopIterating(HWND window) = 0;
private:
const std::set<HWND>& ignore_;
DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder);
};
class TopMostFinder : public BaseWindowFinder {
public:
static bool IsTopMostWindowAtPoint(HWND window,
const gfx::Point& screen_loc,
const std::set<HWND>& ignore) {
TopMostFinder finder(window, screen_loc, ignore);
return finder.is_top_most_;
}
virtual bool ShouldStopIterating(HWND hwnd) {
if (hwnd == target_) {
is_top_most_ = true;
return true;
}
if (!IsWindowVisible(hwnd)) {
return false;
}
RECT r;
if (!GetWindowRect(hwnd, &r) || !PtInRect(&r, screen_loc_.ToPOINT())) {
return false;
}
LONG ex_styles = GetWindowLong(hwnd, GWL_EXSTYLE);
if (ex_styles & WS_EX_TRANSPARENT || ex_styles & WS_EX_LAYERED) {
return false;
}
if (GetWindowRgn(hwnd, tmp_region_.Get()) == ERROR) {
return true;
}
BOOL is_point_in_region = PtInRegion(tmp_region_.Get(),
screen_loc_.x() - r.left, screen_loc_.y() - r.top);
tmp_region_ = CreateRectRgn(0, 0, 0, 0);
return !!is_point_in_region;
}
private:
TopMostFinder(HWND window,
const gfx::Point& screen_loc,
const std::set<HWND>& ignore)
: BaseWindowFinder(ignore),
target_(window),
screen_loc_(screen_loc),
is_top_most_(false),
tmp_region_(CreateRectRgn(0, 0, 0, 0)) {
EnumWindows(WindowCallbackProc, as_lparam());
}
HWND target_;
gfx::Point screen_loc_;
bool is_top_most_;
base::win::ScopedRegion tmp_region_;
DISALLOW_COPY_AND_ASSIGN(TopMostFinder);
};
class LocalProcessWindowFinder : public BaseWindowFinder {
public:
static gfx::NativeWindow GetProcessWindowAtPoint(
const gfx::Point& screen_loc,
const std::set<HWND>& ignore) {
LocalProcessWindowFinder finder(screen_loc, ignore);
if (finder.result_ &&
((base::win::OSInfo::GetInstance()->version() >=
base::win::VERSION_WIN8) ||
TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc,
ignore))) {
return views::DesktopWindowTreeHostWin::GetContentWindowForHWND(
finder.result_);
}
return NULL;
}
protected:
virtual bool ShouldStopIterating(HWND hwnd) {
RECT r;
if (IsWindowVisible(hwnd) && GetWindowRect(hwnd, &r) &&
PtInRect(&r, screen_loc_.ToPOINT())) {
result_ = hwnd;
return true;
}
return false;
}
private:
LocalProcessWindowFinder(const gfx::Point& screen_loc,
const std::set<HWND>& ignore)
: BaseWindowFinder(ignore),
screen_loc_(screen_loc),
result_(NULL) {
EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, as_lparam());
}
gfx::Point screen_loc_;
HWND result_;
DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder);
};
std::set<HWND> RemapIgnoreSet(const std::set<gfx::NativeView>& ignore) {
std::set<HWND> hwnd_set;
std::set<gfx::NativeView>::const_iterator it = ignore.begin();
for (; it != ignore.end(); ++it) {
HWND w = (*it)->GetHost()->GetAcceleratedWidget();
if (w)
hwnd_set.insert(w);
}
return hwnd_set;
}
}
aura::Window* GetLocalProcessWindowAtPoint(
chrome::HostDesktopType host_desktop_type,
const gfx::Point& screen_point,
const std::set<aura::Window*>& ignore) {
#if defined(USE_ASH)
if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH)
return GetLocalProcessWindowAtPointAsh(screen_point, ignore);
#endif
return LocalProcessWindowFinder::GetProcessWindowAtPoint(
screen_point, RemapIgnoreSet(ignore));
}