15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/dock_info.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_gdi_object.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/ash/tabs/dock_info_ash.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_view.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/win/hwnd_util.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BaseWindowFinder ----------------------------------------------------------- 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Base class used to locate a window. This is intended to be used with the 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// various win32 functions that iterate over windows. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A subclass need only override ShouldStopIterating to determine when 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// iteration should stop. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BaseWindowFinder { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a BaseWindowFinder with the specified set of HWNDs to ignore. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit BaseWindowFinder(const std::set<HWND>& ignore) : ignore_(ignore) {} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~BaseWindowFinder() {} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cast must match that in as_lparam(). 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BaseWindowFinder* finder = reinterpret_cast<BaseWindowFinder*>(lParam); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (finder->ignore_.find(hwnd) != finder->ignore_.end()) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return finder->ShouldStopIterating(hwnd) ? FALSE : TRUE; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPARAM as_lparam() { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cast must match that in WindowCallbackProc(). 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<LPARAM>(static_cast<BaseWindowFinder*>(this)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if iteration should stop, false if iteration should continue. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool ShouldStopIterating(HWND window) = 0; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<HWND>& ignore_; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TopMostFinder -------------------------------------------------------------- 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class to determine if a particular point of a window is not obscured 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by another window. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TopMostFinder : public BaseWindowFinder { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if |window| is the topmost window at the location 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |screen_loc|, not including the windows in |ignore|. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsTopMostWindowAtPoint(HWND window, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& screen_loc, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<HWND>& ignore) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TopMostFinder finder(window, screen_loc, ignore); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return finder.is_top_most_; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool ShouldStopIterating(HWND hwnd) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hwnd == target_) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Window is topmost, stop iterating. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_top_most_ = true; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsWindowVisible(hwnd)) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window isn't visible, keep iterating. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RECT r; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetWindowRect(hwnd, &r) || !PtInRect(&r, screen_loc_.ToPOINT())) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window doesn't contain the point, keep iterating. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONG ex_styles = GetWindowLong(hwnd, GWL_EXSTYLE); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ex_styles & WS_EX_TRANSPARENT || ex_styles & WS_EX_LAYERED) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mouse events fall through WS_EX_TRANSPARENT windows, so we ignore them. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WS_EX_LAYERED is trickier. Apps like Switcher create a totally 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transparent WS_EX_LAYERED window that is always on top. If we don't 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ignore WS_EX_LAYERED windows and there are totally transparent 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WS_EX_LAYERED windows then there are effectively holes on the screen 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the user can't reattach tabs to. So we ignore them. This is a bit 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // problematic in so far as WS_EX_LAYERED windows need not be totally 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transparent in which case we treat chrome windows as not being obscured 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when they really are, but this is better than not being able to 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reattach tabs. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hwnd is at the point. Make sure the point is within the windows region. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetWindowRgn(hwnd, tmp_region_.Get()) == ERROR) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's no region on the window and the window contains the point. Stop 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iterating. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The region is relative to the window's rect. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL is_point_in_region = PtInRegion(tmp_region_.Get(), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_loc_.x() - r.left, screen_loc_.y() - r.top); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_region_ = CreateRectRgn(0, 0, 0, 0); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop iterating if the region contains the point. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !!is_point_in_region; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TopMostFinder(HWND window, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& screen_loc, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<HWND>& ignore) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : BaseWindowFinder(ignore), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_(window), 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_loc_(screen_loc), 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_top_most_(false), 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_region_(CreateRectRgn(0, 0, 0, 0)) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumWindows(WindowCallbackProc, as_lparam()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window we're looking for. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND target_; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Location of window to find. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point screen_loc_; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Is target_ the top most window? This is initially false but set to true 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in ShouldStopIterating if target_ is passed in. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_top_most_; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedRegion tmp_region_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TopMostFinder); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WindowFinder --------------------------------------------------------------- 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class to determine if a particular point contains a window from our 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// process. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LocalProcessWindowFinder : public BaseWindowFinder { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the hwnd from our process at screen_loc that is not obscured by 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // another window. Returns NULL otherwise. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static gfx::NativeWindow GetProcessWindowAtPoint( 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& screen_loc, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<HWND>& ignore) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalProcessWindowFinder finder(screen_loc, ignore); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows 8 has a window that appears first in the list of iterated 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows, yet is not visually on top of everything. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky): figure out a better way to ignore this window. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (finder.result_ && 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((base::win::OSInfo::GetInstance()->version() >= 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::VERSION_WIN8) || 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore))) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return views::DesktopRootWindowHostWin::GetContentWindowForHWND( 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) finder.result_); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return finder.result_; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool ShouldStopIterating(HWND hwnd) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RECT r; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsWindowVisible(hwnd) && GetWindowRect(hwnd, &r) && 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PtInRect(&r, screen_loc_.ToPOINT())) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_ = hwnd; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalProcessWindowFinder(const gfx::Point& screen_loc, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<HWND>& ignore) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : BaseWindowFinder(ignore), 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_loc_(screen_loc), 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_(NULL) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, as_lparam()); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Position of the mouse. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point screen_loc_; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The resulting window. This is initially null but set to true in 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ShouldStopIterating if an appropriate window is found. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND result_; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DockToWindowFinder --------------------------------------------------------- 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class for creating a DockInfo from a specified point. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DockToWindowFinder : public BaseWindowFinder { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the DockInfo for the specified point. If there is no docking 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // position for the specified point the returned DockInfo has a type of NONE. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static DockInfo GetDockInfoAtPoint(const gfx::Point& screen_loc, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<HWND>& ignore) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockToWindowFinder finder(screen_loc, ignore); 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HWND hwnd = views::HWNDForNativeWindow(finder.result_.window()); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!finder.result_.window() || 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !TopMostFinder::IsTopMostWindowAtPoint(hwnd, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) finder.result_.hot_spot(), 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore)) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) finder.result_.set_type(DockInfo::NONE); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return finder.result_; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool ShouldStopIterating(HWND hwnd) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserView* window = BrowserView::GetBrowserViewForNativeWindow( 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::DesktopRootWindowHostWin::GetContentWindowForHWND(hwnd)); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserView* window = BrowserView::GetBrowserViewForNativeWindow(hwnd); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RECT bounds; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window || !IsWindowVisible(hwnd) || 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !GetWindowRect(hwnd, &bounds)) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the three corners we allow docking to. We don't currently allow 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // docking to top of window as it conflicts with docking to the tab strip. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CheckPoint(hwnd, bounds.left, (bounds.top + bounds.bottom) / 2, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo::LEFT_OF_WINDOW) || 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckPoint(hwnd, bounds.right - 1, (bounds.top + bounds.bottom) / 2, 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo::RIGHT_OF_WINDOW) || 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckPoint(hwnd, (bounds.left + bounds.right) / 2, bounds.bottom - 1, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo::BOTTOM_OF_WINDOW)) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockToWindowFinder(const gfx::Point& screen_loc, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<HWND>& ignore) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : BaseWindowFinder(ignore), 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_loc_(screen_loc) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect work_area = gfx::Screen::GetNativeScreen()-> 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDisplayNearestPoint(screen_loc).bounds(); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!work_area.IsEmpty()) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.set_monitor_bounds(work_area); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, as_lparam()); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool CheckPoint(HWND hwnd, int x, int y, DockInfo::Type type) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool in_enable_area; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DockInfo::IsCloseToPoint(screen_loc_, x, y, &in_enable_area)) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.set_in_enable_area(in_enable_area); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.set_window( 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::DesktopRootWindowHostWin::GetContentWindowForHWND(hwnd)); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.set_window(hwnd); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.set_type(type); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.set_hot_spot(gfx::Point(x, y)); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only show the hotspot if the monitor contains the bounds of the popup 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // window. Otherwise we end with a weird situation where the popup window 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // isn't completely visible. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result_.monitor_bounds().Contains(result_.GetPopupRect()); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The location to look for. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point screen_loc_; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The resulting DockInfo. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo result_; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DockToWindowFinder); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::set<HWND> RemapIgnoreSet(const std::set<gfx::NativeView>& ignore) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<HWND> hwnd_set; 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<gfx::NativeView>::const_iterator it = ignore.begin(); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (; it != ignore.end(); ++it) { 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) HWND w = (*it)->GetDispatcher()->host()->GetAcceleratedWidget(); 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (w) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hwnd_set.insert(w); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hwnd_set; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NativeViews are already HWNDs on non-Aura Windows. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ignore; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DockInfo ------------------------------------------------------------------- 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DockInfo DockInfo::GetDockInfoAtPoint(chrome::HostDesktopType host_desktop_type, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& screen_point, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<gfx::NativeView>& ignore) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return chrome::ash::GetDockInfoAtPointAsh(screen_point, ignore); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try docking to a window first. 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo info = DockToWindowFinder::GetDockInfoAtPoint( 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_point, RemapIgnoreSet(ignore)); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info.type() != DockInfo::NONE) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return info; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No window relative positions. Try monitor relative positions. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& m_bounds = info.monitor_bounds(); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int mid_x = m_bounds.x() + m_bounds.width() / 2; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int mid_y = m_bounds.y() + m_bounds.height() / 2; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.CheckMonitorPoint(screen_point, mid_x, m_bounds.y(), 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo::MAXIMIZE) || 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.CheckMonitorPoint(screen_point, mid_x, m_bounds.bottom(), 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo::BOTTOM_HALF) || 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.CheckMonitorPoint(screen_point, m_bounds.x(), mid_y, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo::LEFT_HALF) || 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.CheckMonitorPoint(screen_point, m_bounds.right(), mid_y, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DockInfo::RIGHT_HALF); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return info; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::NativeView DockInfo::GetLocalProcessWindowAtPoint( 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::HostDesktopType host_desktop_type, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& screen_point, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<gfx::NativeView>& ignore) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return chrome::ash::GetLocalProcessWindowAtPointAsh(screen_point, ignore); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalProcessWindowFinder::GetProcessWindowAtPoint( 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_point, RemapIgnoreSet(ignore)); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DockInfo::GetWindowBounds(gfx::Rect* bounds) const { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window()) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bounds = window_->bounds(); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DockInfo::SizeOtherWindowTo(const gfx::Rect& bounds) const { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_->SetBounds(bounds); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // USE_AURA 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DockInfo::GetWindowBounds(gfx::Rect* bounds) const { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RECT window_rect; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window() || !GetWindowRect(window(), &window_rect)) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bounds = gfx::Rect(window_rect); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DockInfo::SizeOtherWindowTo(const gfx::Rect& bounds) const { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsZoomed(window())) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're docking relative to another window, we need to make sure the 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // window we're docking to isn't maximized. 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShowWindow(window(), SW_RESTORE | SW_SHOWNA); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPos(window(), HWND_TOP, bounds.x(), bounds.y(), bounds.width(), 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds.height(), SWP_NOACTIVATE | SWP_NOOWNERZORDER); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DockInfo::GetHotSpotDeltaY() { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Tab::GetMinimumUnselectedSize().height() - 1; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !USE_AURA 406