diff options
-rw-r--r-- | chrome/browser/browser.vcproj | 4 | ||||
-rw-r--r-- | chrome/browser/dock_info.cc | 371 | ||||
-rw-r--r-- | chrome/browser/dock_info.h | 56 | ||||
-rw-r--r-- | chrome/browser/dock_info_win.cc | 311 | ||||
-rw-r--r-- | chrome/browser/views/tabs/dragged_tab_controller.cc | 59 | ||||
-rw-r--r-- | chrome/browser/views/tabs/dragged_tab_controller.h | 3 | ||||
-rw-r--r-- | chrome/chrome.gyp | 8 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.h | 2 |
8 files changed, 439 insertions, 375 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 87cf969..11b96c3 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -738,6 +738,10 @@ > </File> <File + RelativePath=".\dock_info_win.cc" + > + </File> + <File RelativePath=".\dock_info.cc" > </File> diff --git a/chrome/browser/dock_info.cc b/chrome/browser/dock_info.cc index a9c2561..8c4428d 100644 --- a/chrome/browser/dock_info.cc +++ b/chrome/browser/dock_info.cc @@ -4,12 +4,6 @@ #include "chrome/browser/dock_info.h" -#include "base/basictypes.h" -#include "base/logging.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_window.h" -#include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/tabs/tab.h" namespace { @@ -22,13 +16,16 @@ const int kHotSpotDeltaY = 120; const int kPopupWidth = 70; const int kPopupHeight = 70; -// Returns true if |screen_loc| is close to the hotspot at |x|, |y|. If the -// point is close enough to the hotspot true is returned and |in_enable_area| -// is set appropriately. -bool IsCloseToPoint(const gfx::Point& screen_loc, - int x, - int y, - bool* in_enable_area) { +} // namespace + +// static +DockInfo::Factory* DockInfo::factory_ = NULL; + +// static +bool DockInfo::IsCloseToPoint(const gfx::Point& screen_loc, + int x, + int y, + bool* in_enable_area) { int delta_x = abs(x - screen_loc.x()); int delta_y = abs(y - screen_loc.y()); *in_enable_area = (delta_x < kPopupWidth / 2 && delta_y < kPopupHeight / 2); @@ -36,12 +33,12 @@ bool IsCloseToPoint(const gfx::Point& screen_loc, delta_y < kHotSpotDeltaY); } -// Variant of IsCloseToPoint used for monitor relative positions. -bool IsCloseToMonitorPoint(const gfx::Point& screen_loc, - int x, - int y, - DockInfo::Type type, - bool* in_enable_area) { +// static +bool DockInfo::IsCloseToMonitorPoint(const gfx::Point& screen_loc, + int x, + int y, + DockInfo::Type type, + bool* in_enable_area) { // Because the monitor relative positions are aligned with the edge of the // monitor these need to be handled differently. int delta_x = abs(x - screen_loc.x()); @@ -89,279 +86,6 @@ bool IsCloseToMonitorPoint(const gfx::Point& screen_loc, return *in_enable_area || (max_delta_y < hot_spot_delta_y); } -// BaseWindowFinder ----------------------------------------------------------- - -// Base class used to locate a window. This is intended to be used with the -// various win32 functions that iterate over windows. -// -// A subclass need only override ShouldStopIterating to determine when -// iteration should stop. -class BaseWindowFinder { - public: - // Creates a BaseWindowFinder with the specified set of HWNDs to ignore. - BaseWindowFinder(const std::set<HWND>& ignore) : ignore_(ignore) {} - virtual ~BaseWindowFinder() {} - - protected: - // Returns true if iteration should stop, false if iteration should continue. - virtual bool ShouldStopIterating(HWND window) = 0; - - 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; - } - - private: - const std::set<HWND>& ignore_; - - DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder); -}; - -// TopMostFinder -------------------------------------------------------------- - -// Helper class to determine if a particular point of a window is not obscured -// by another window. -class TopMostFinder : public BaseWindowFinder { - public: - // Returns true if |window| is the topmost window at the location - // |screen_loc|, not including the windows in |ignore|. - 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_) { - // Window is topmost, stop iterating. - is_top_most_ = true; - return true; - } - - if (!::IsWindowVisible(hwnd)) { - // The window isn't visible, keep iterating. - return false; - } - - CRect r; - if (!::GetWindowRect(hwnd, &r) || !r.PtInRect(screen_loc_.ToPOINT())) { - // The window doesn't contain the point, keep iterating. - return false; - } - - // hwnd is at the point. Make sure the point is within the windows region. - if (GetWindowRgn(hwnd, tmp_region_.Get()) == ERROR) { - // There's no region on the window and the window contains the point. Stop - // iterating. - return true; - } - - // The region is relative to the window's rect. - 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); - // Stop iterating if the region contains the point. - 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, reinterpret_cast<LPARAM>(this)); - } - - // The window we're looking for. - HWND target_; - - // Location of window to find. - gfx::Point screen_loc_; - - // Is target_ the top most window? This is initially false but set to true - // in ShouldStopIterating if target_ is passed in. - bool is_top_most_; - - ScopedHRGN tmp_region_; - - DISALLOW_COPY_AND_ASSIGN(TopMostFinder); -}; - -// WindowFinder --------------------------------------------------------------- - -// Helper class to determine if a particular point contains a window from our -// process. -class LocalProcessWindowFinder : public BaseWindowFinder { - public: - // Returns the hwnd from our process at screen_loc that is not obscured by - // another window. Returns NULL otherwise. - static HWND GetProcessWindowAtPoint(const gfx::Point& screen_loc, - const std::set<HWND>& ignore) { - LocalProcessWindowFinder finder(screen_loc, ignore); - if (finder.result_ && - TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc, - ignore)) { - return finder.result_; - } - return NULL; - } - - protected: - virtual bool ShouldStopIterating(HWND hwnd) { - CRect r; - if (::IsWindowVisible(hwnd) && ::GetWindowRect(hwnd, &r) && - r.PtInRect(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, - reinterpret_cast<LPARAM>(this)); - } - - // Position of the mouse. - gfx::Point screen_loc_; - - // The resulting window. This is initially null but set to true in - // ShouldStopIterating if an appropriate window is found. - HWND result_; - - DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder); -}; - -// DockToWindowFinder --------------------------------------------------------- - -// Helper class for creating a DockInfo from a specified point. -class DockToWindowFinder : public BaseWindowFinder { - public: - // Returns the DockInfo for the specified point. If there is no docking - // position for the specified point the returned DockInfo has a type of NONE. - static DockInfo GetDockInfoAtPoint(const gfx::Point& screen_loc, - const std::set<HWND>& ignore) { - DockToWindowFinder finder(screen_loc, ignore); - if (!finder.result_.hwnd() || - !TopMostFinder::IsTopMostWindowAtPoint(finder.result_.hwnd(), - finder.result_.hot_spot(), - ignore)) { - finder.result_.set_type(DockInfo::NONE); - } - return finder.result_; - } - - protected: - virtual bool ShouldStopIterating(HWND hwnd) { - BrowserView* window = BrowserView::GetBrowserViewForHWND(hwnd); - CRect bounds; - if (!window || !::IsWindowVisible(hwnd) || - !::GetWindowRect(hwnd, &bounds)) { - return false; - } - - // Check the three corners we allow docking to. We don't currently allow - // docking to top of window as it conflicts with docking to the tab strip. - if (CheckPoint(hwnd, bounds.left, (bounds.top + bounds.bottom) / 2, - DockInfo::LEFT_OF_WINDOW) || - CheckPoint(hwnd, bounds.right - 1, (bounds.top + bounds.bottom) / 2, - DockInfo::RIGHT_OF_WINDOW) || - CheckPoint(hwnd, (bounds.left + bounds.right) / 2, bounds.bottom - 1, - DockInfo::BOTTOM_OF_WINDOW)) { - return true; - } - return false; - } - - private: - DockToWindowFinder(const gfx::Point& screen_loc, - const std::set<HWND>& ignore) - : BaseWindowFinder(ignore), - screen_loc_(screen_loc) { - HMONITOR monitor = MonitorFromPoint(screen_loc.ToPOINT(), - MONITOR_DEFAULTTONULL); - MONITORINFO monitor_info = {0}; - monitor_info.cbSize = sizeof(MONITORINFO); - if (monitor && GetMonitorInfo(monitor, &monitor_info)) { - result_.set_monitor_bounds(gfx::Rect(monitor_info.rcWork)); - EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, - reinterpret_cast<LPARAM>(this)); - } - } - - bool CheckPoint(HWND hwnd, int x, int y, DockInfo::Type type) { - bool in_enable_area; - if (IsCloseToPoint(screen_loc_, x, y, &in_enable_area)) { - result_.set_in_enable_area(in_enable_area); - result_.set_hwnd(hwnd); - result_.set_type(type); - result_.set_hot_spot(gfx::Point(x, y)); - // Only show the hotspot if the monitor contains the bounds of the popup - // window. Otherwise we end with a weird situation where the popup window - // isn't completely visible. - return result_.monitor_bounds().Contains(result_.GetPopupRect()); - } - return false; - } - - // The location to look for. - gfx::Point screen_loc_; - - // The resulting DockInfo. - DockInfo result_; - - DISALLOW_COPY_AND_ASSIGN(DockToWindowFinder); -}; - -} // namespace - -// DockInfo ------------------------------------------------------------------- - -// static -DockInfo::Factory* DockInfo::factory_ = NULL; - -// static -DockInfo DockInfo::GetDockInfoAtPoint(const gfx::Point& screen_point, - const std::set<HWND>& ignore) { - if (factory_) - return factory_->GetDockInfoAtPoint(screen_point, ignore); - - // Try docking to a window first. - DockInfo info = DockToWindowFinder::GetDockInfoAtPoint(screen_point, ignore); - if (info.type() != DockInfo::NONE) - return info; - - // No window relative positions. Try monitor relative positions. - const gfx::Rect& m_bounds = info.monitor_bounds(); - int mid_x = m_bounds.x() + m_bounds.width() / 2; - int mid_y = m_bounds.y() + m_bounds.height() / 2; - - bool result = - info.CheckMonitorPoint(screen_point, mid_x, m_bounds.y(), - DockInfo::MAXIMIZE) || - info.CheckMonitorPoint(screen_point, mid_x, m_bounds.bottom(), - DockInfo::BOTTOM_HALF) || - info.CheckMonitorPoint(screen_point, m_bounds.x(), mid_y, - DockInfo::LEFT_HALF) || - info.CheckMonitorPoint(screen_point, m_bounds.right(), mid_y, - DockInfo::RIGHT_HALF); - - return info; -} - // static int DockInfo::popup_width() { return kPopupWidth; @@ -372,19 +96,11 @@ int DockInfo::popup_height() { return kPopupHeight; } -HWND DockInfo::GetLocalProcessWindowAtPoint(const gfx::Point& screen_point, - const std::set<HWND>& ignore) { - if (factory_) - return factory_->GetLocalProcessWindowAtPoint(screen_point, ignore); - return - LocalProcessWindowFinder::GetProcessWindowAtPoint(screen_point, ignore); -} - bool DockInfo::IsValidForPoint(const gfx::Point& screen_point) { if (type_ == NONE) return false; - if (hwnd_) { + if (window_) { return IsCloseToPoint(screen_point, hot_spot_.x(), hot_spot_.y(), &in_enable_area_); } @@ -399,38 +115,36 @@ bool DockInfo::GetNewWindowBounds(gfx::Rect* new_window_bounds, if (type_ == NONE || !in_enable_area_) return false; - RECT window_rect; - if (hwnd_ && !GetWindowRect(hwnd_, &window_rect)) + gfx::Rect window_bounds; + if (window_ && !GetWindowBounds(&window_bounds)) return false; int half_m_width = (monitor_bounds_.right() - monitor_bounds_.x()) / 2; int half_m_height = (monitor_bounds_.bottom() - monitor_bounds_.y()) / 2; - bool unmaximize_other_window = false; *maximize_new_window = false; switch (type_) { case LEFT_OF_WINDOW: - new_window_bounds->SetRect(monitor_bounds_.x(), window_rect.top, - half_m_width, window_rect.bottom - window_rect.top); + new_window_bounds->SetRect(monitor_bounds_.x(), window_bounds.y(), + half_m_width, window_bounds.height()); break; case RIGHT_OF_WINDOW: new_window_bounds->SetRect(monitor_bounds_.x() + half_m_width, - window_rect.top, half_m_width, window_rect.bottom - window_rect.top); + window_bounds.y(), half_m_width, + window_bounds.height()); break; case TOP_OF_WINDOW: - new_window_bounds->SetRect(window_rect.left, monitor_bounds_.y(), - window_rect.right - window_rect.left, - half_m_height); + new_window_bounds->SetRect(window_bounds.x(), monitor_bounds_.y(), + window_bounds.width(), half_m_height); break; case BOTTOM_OF_WINDOW: - new_window_bounds->SetRect(window_rect.left, + new_window_bounds->SetRect(window_bounds.x(), monitor_bounds_.y() + half_m_height, - window_rect.right - window_rect.left, - half_m_height); + window_bounds.width(), half_m_height); break; case LEFT_HALF: @@ -463,8 +177,8 @@ void DockInfo::AdjustOtherWindowBounds() const { if (!in_enable_area_) return; - RECT window_rect; - if (!hwnd_ || !GetWindowRect(hwnd_, &window_rect)) + gfx::Rect window_bounds; + if (!window_ || !GetWindowBounds(&window_bounds)) return; gfx::Rect other_window_bounds; @@ -474,40 +188,31 @@ void DockInfo::AdjustOtherWindowBounds() const { switch (type_) { case LEFT_OF_WINDOW: other_window_bounds.SetRect(monitor_bounds_.x() + half_m_width, - window_rect.top, half_m_width, window_rect.bottom - window_rect.top); + window_bounds.y(), half_m_width, + window_bounds.height()); break; case RIGHT_OF_WINDOW: - other_window_bounds.SetRect(monitor_bounds_.x(), window_rect.top, - half_m_width, window_rect.bottom - window_rect.top); + other_window_bounds.SetRect(monitor_bounds_.x(), window_bounds.y(), + half_m_width, window_bounds.height()); break; case TOP_OF_WINDOW: - other_window_bounds.SetRect(window_rect.left, + other_window_bounds.SetRect(window_bounds.x(), monitor_bounds_.y() + half_m_height, - window_rect.right - window_rect.left, - half_m_height); + window_bounds.width(), half_m_height); break; case BOTTOM_OF_WINDOW: - other_window_bounds.SetRect(window_rect.left, monitor_bounds_.y(), - window_rect.right - window_rect.left, - half_m_height); + other_window_bounds.SetRect(window_bounds.x(), monitor_bounds_.y(), + window_bounds.width(), half_m_height); break; default: return; } - if (IsZoomed(hwnd_)) { - // We're docking relative to another window, we need to make sure the - // window we're docking to isn't maximized. - ShowWindow(hwnd_, SW_RESTORE | SW_SHOWNA); - } - ::SetWindowPos(hwnd_, HWND_TOP, other_window_bounds.x(), - other_window_bounds.y(), other_window_bounds.width(), - other_window_bounds.height(), - SWP_NOACTIVATE | SWP_NOOWNERZORDER); + SizeOtherWindowTo(other_window_bounds); } gfx::Rect DockInfo::GetPopupRect() const { diff --git a/chrome/browser/dock_info.h b/chrome/browser/dock_info.h index 0774e6b..158f324 100644 --- a/chrome/browser/dock_info.h +++ b/chrome/browser/dock_info.h @@ -6,13 +6,11 @@ #define CHROME_BROWSER_DOCK_INFO_H_ #include <set> -#include <windows.h> +#include "base/gfx/native_widget_types.h" #include "base/gfx/point.h" #include "base/gfx/rect.h" -class Profile; - // DockInfo is used to do determine possible dock locations for a dragged // tab. To use DockInfo invoke GetDockInfoAtPoint. This returns a new // DockInfo whose type indicates the type of dock that should occur based @@ -27,11 +25,13 @@ class DockInfo { public: class Factory { public: - virtual DockInfo GetDockInfoAtPoint(const gfx::Point& screen_point, - const std::set<HWND>& ignore) = 0; + virtual DockInfo GetDockInfoAtPoint( + const gfx::Point& screen_point, + const std::set<gfx::NativeWindow>& ignore) = 0; - virtual HWND GetLocalProcessWindowAtPoint(const gfx::Point& screen_point, - const std::set<HWND>& ignore) = 0; + virtual gfx::NativeWindow GetLocalProcessWindowAtPoint( + const gfx::Point& screen_point, + const std::set<gfx::NativeWindow>& ignore) = 0; }; // Possible dock positions. @@ -40,7 +40,7 @@ class DockInfo { NONE, // Indicates the new window should be positioned relative to the window - // identified by hwnd(). + // identified by window(). LEFT_OF_WINDOW, RIGHT_OF_WINDOW, BOTTOM_OF_WINDOW, @@ -55,7 +55,22 @@ class DockInfo { BOTTOM_HALF }; - DockInfo() : type_(NONE), hwnd_(NULL), in_enable_area_(false) {} + DockInfo() : type_(NONE), window_(NULL), in_enable_area_(false) {} + + // Returns true if |screen_loc| is close to the hotspot at |x|, |y|. If the + // point is close enough to the hotspot true is returned and |in_enable_area| + // is set appropriately. + static bool IsCloseToPoint(const gfx::Point& screen_loc, + int x, + int y, + bool* in_enable_area); + + // Variant of IsCloseToPoint used for monitor relative positions. + static bool IsCloseToMonitorPoint(const gfx::Point& screen_loc, + int x, + int y, + DockInfo::Type type, + bool* in_enable_area); // Sets the factory. static void set_factory(Factory* factory) { factory_ = factory; } @@ -65,7 +80,7 @@ class DockInfo { static int popup_height(); // Returns the DockInfo for the specified point |screen_point|. |ignore| - // contains the set of hwnds to ignore from consideration. This contains the + // contains the set of windows to ignore from consideration. This contains the // dragged window as well as any windows showing possible dock locations. // // If there is no docking position for the specified location the returned @@ -74,7 +89,7 @@ class DockInfo { // If a Factory has been set, the method of the same name is invoked on the // Factory to determine the DockInfo. static DockInfo GetDockInfoAtPoint(const gfx::Point& screen_point, - const std::set<HWND>& ignore); + const std::set<gfx::NativeWindow>& ignore); // Returns the top most window from the current process at |screen_point|. // See GetDockInfoAtPoint for a description of |ignore|. This returns NULL if @@ -83,8 +98,9 @@ class DockInfo { // // If a Factory has been set, the method of the same name is invoked on the // Factory to determine the DockInfo. - static HWND GetLocalProcessWindowAtPoint(const gfx::Point& screen_point, - const std::set<HWND>& ignore); + static gfx::NativeWindow GetLocalProcessWindowAtPoint( + const gfx::Point& screen_point, + const std::set<gfx::NativeWindow>& ignore); // Returns true if this DockInfo is valid for the specified point. This // resets in_enable_area based on the new location. @@ -107,8 +123,8 @@ class DockInfo { // The window to dock too. Is null for dock types that are relative to the // monitor. - void set_hwnd(HWND hwnd) { hwnd_ = hwnd; } - HWND hwnd() const { return hwnd_; } + void set_window(gfx::NativeWindow window) { window_ = window; } + gfx::NativeWindow window() const { return window_; } // The location of the hotspot. void set_hot_spot(const gfx::Point& hot_spot) { hot_spot_ = hot_spot; } @@ -137,9 +153,9 @@ class DockInfo { bool in_enable_area() const { return in_enable_area_; } // Returns true if |other| is considered equal to this. Two DockInfos are - // considered equal if they have the same type and same hwnd. + // considered equal if they have the same type and same window. bool equals(const DockInfo& other) const { - return type_ == other.type_ && hwnd_ == other.hwnd_ && + return type_ == other.type_ && window_ == other.window_ && monitor_bounds_ == other.monitor_bounds_; } @@ -152,8 +168,12 @@ class DockInfo { Type type); private: + // Returns the bounds of the window. + bool GetWindowBounds(gfx::Rect* bounds) const; + void SizeOtherWindowTo(const gfx::Rect& bounds) const; + Type type_; - HWND hwnd_; + gfx::NativeWindow window_; gfx::Point hot_spot_; gfx::Rect monitor_bounds_; bool in_enable_area_; diff --git a/chrome/browser/dock_info_win.cc b/chrome/browser/dock_info_win.cc new file mode 100644 index 0000000..68006f1 --- /dev/null +++ b/chrome/browser/dock_info_win.cc @@ -0,0 +1,311 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/dock_info.h" + +#include "base/basictypes.h" +#include "base/logging.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_window.h" +#include "chrome/browser/views/frame/browser_view.h" +#include "chrome/browser/views/tabs/tab.h" + +namespace { + +// BaseWindowFinder ----------------------------------------------------------- + +// Base class used to locate a window. This is intended to be used with the +// various win32 functions that iterate over windows. +// +// A subclass need only override ShouldStopIterating to determine when +// iteration should stop. +class BaseWindowFinder { + public: + // Creates a BaseWindowFinder with the specified set of HWNDs to ignore. + BaseWindowFinder(const std::set<HWND>& ignore) : ignore_(ignore) {} + virtual ~BaseWindowFinder() {} + + protected: + // Returns true if iteration should stop, false if iteration should continue. + virtual bool ShouldStopIterating(HWND window) = 0; + + 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; + } + + private: + const std::set<HWND>& ignore_; + + DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder); +}; + +// TopMostFinder -------------------------------------------------------------- + +// Helper class to determine if a particular point of a window is not obscured +// by another window. +class TopMostFinder : public BaseWindowFinder { + public: + // Returns true if |window| is the topmost window at the location + // |screen_loc|, not including the windows in |ignore|. + 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_) { + // Window is topmost, stop iterating. + is_top_most_ = true; + return true; + } + + if (!::IsWindowVisible(hwnd)) { + // The window isn't visible, keep iterating. + return false; + } + + CRect r; + if (!::GetWindowRect(hwnd, &r) || !r.PtInRect(screen_loc_.ToPOINT())) { + // The window doesn't contain the point, keep iterating. + return false; + } + + // hwnd is at the point. Make sure the point is within the windows region. + if (GetWindowRgn(hwnd, tmp_region_.Get()) == ERROR) { + // There's no region on the window and the window contains the point. Stop + // iterating. + return true; + } + + // The region is relative to the window's rect. + 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); + // Stop iterating if the region contains the point. + 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, reinterpret_cast<LPARAM>(this)); + } + + // The window we're looking for. + HWND target_; + + // Location of window to find. + gfx::Point screen_loc_; + + // Is target_ the top most window? This is initially false but set to true + // in ShouldStopIterating if target_ is passed in. + bool is_top_most_; + + ScopedHRGN tmp_region_; + + DISALLOW_COPY_AND_ASSIGN(TopMostFinder); +}; + +// WindowFinder --------------------------------------------------------------- + +// Helper class to determine if a particular point contains a window from our +// process. +class LocalProcessWindowFinder : public BaseWindowFinder { + public: + // Returns the hwnd from our process at screen_loc that is not obscured by + // another window. Returns NULL otherwise. + static HWND GetProcessWindowAtPoint(const gfx::Point& screen_loc, + const std::set<HWND>& ignore) { + LocalProcessWindowFinder finder(screen_loc, ignore); + if (finder.result_ && + TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc, + ignore)) { + return finder.result_; + } + return NULL; + } + + protected: + virtual bool ShouldStopIterating(HWND hwnd) { + CRect r; + if (::IsWindowVisible(hwnd) && ::GetWindowRect(hwnd, &r) && + r.PtInRect(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, + reinterpret_cast<LPARAM>(this)); + } + + // Position of the mouse. + gfx::Point screen_loc_; + + // The resulting window. This is initially null but set to true in + // ShouldStopIterating if an appropriate window is found. + HWND result_; + + DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder); +}; + +// DockToWindowFinder --------------------------------------------------------- + +// Helper class for creating a DockInfo from a specified point. +class DockToWindowFinder : public BaseWindowFinder { + public: + // Returns the DockInfo for the specified point. If there is no docking + // position for the specified point the returned DockInfo has a type of NONE. + static DockInfo GetDockInfoAtPoint(const gfx::Point& screen_loc, + const std::set<HWND>& ignore) { + DockToWindowFinder finder(screen_loc, ignore); + if (!finder.result_.window() || + !TopMostFinder::IsTopMostWindowAtPoint(finder.result_.window(), + finder.result_.hot_spot(), + ignore)) { + finder.result_.set_type(DockInfo::NONE); + } + return finder.result_; + } + + protected: + virtual bool ShouldStopIterating(HWND hwnd) { + BrowserView* window = BrowserView::GetBrowserViewForHWND(hwnd); + CRect bounds; + if (!window || !::IsWindowVisible(hwnd) || + !::GetWindowRect(hwnd, &bounds)) { + return false; + } + + // Check the three corners we allow docking to. We don't currently allow + // docking to top of window as it conflicts with docking to the tab strip. + if (CheckPoint(hwnd, bounds.left, (bounds.top + bounds.bottom) / 2, + DockInfo::LEFT_OF_WINDOW) || + CheckPoint(hwnd, bounds.right - 1, (bounds.top + bounds.bottom) / 2, + DockInfo::RIGHT_OF_WINDOW) || + CheckPoint(hwnd, (bounds.left + bounds.right) / 2, bounds.bottom - 1, + DockInfo::BOTTOM_OF_WINDOW)) { + return true; + } + return false; + } + + private: + DockToWindowFinder(const gfx::Point& screen_loc, + const std::set<HWND>& ignore) + : BaseWindowFinder(ignore), + screen_loc_(screen_loc) { + HMONITOR monitor = MonitorFromPoint(screen_loc.ToPOINT(), + MONITOR_DEFAULTTONULL); + MONITORINFO monitor_info = {0}; + monitor_info.cbSize = sizeof(MONITORINFO); + if (monitor && GetMonitorInfo(monitor, &monitor_info)) { + result_.set_monitor_bounds(gfx::Rect(monitor_info.rcWork)); + EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, + reinterpret_cast<LPARAM>(this)); + } + } + + bool CheckPoint(HWND hwnd, int x, int y, DockInfo::Type type) { + bool in_enable_area; + if (DockInfo::IsCloseToPoint(screen_loc_, x, y, &in_enable_area)) { + result_.set_in_enable_area(in_enable_area); + result_.set_window(hwnd); + result_.set_type(type); + result_.set_hot_spot(gfx::Point(x, y)); + // Only show the hotspot if the monitor contains the bounds of the popup + // window. Otherwise we end with a weird situation where the popup window + // isn't completely visible. + return result_.monitor_bounds().Contains(result_.GetPopupRect()); + } + return false; + } + + // The location to look for. + gfx::Point screen_loc_; + + // The resulting DockInfo. + DockInfo result_; + + DISALLOW_COPY_AND_ASSIGN(DockToWindowFinder); +}; + +} // namespace + +// DockInfo ------------------------------------------------------------------- + +// static +DockInfo DockInfo::GetDockInfoAtPoint(const gfx::Point& screen_point, + const std::set<HWND>& ignore) { + if (factory_) + return factory_->GetDockInfoAtPoint(screen_point, ignore); + + // Try docking to a window first. + DockInfo info = DockToWindowFinder::GetDockInfoAtPoint(screen_point, ignore); + if (info.type() != DockInfo::NONE) + return info; + + // No window relative positions. Try monitor relative positions. + const gfx::Rect& m_bounds = info.monitor_bounds(); + int mid_x = m_bounds.x() + m_bounds.width() / 2; + int mid_y = m_bounds.y() + m_bounds.height() / 2; + + bool result = + info.CheckMonitorPoint(screen_point, mid_x, m_bounds.y(), + DockInfo::MAXIMIZE) || + info.CheckMonitorPoint(screen_point, mid_x, m_bounds.bottom(), + DockInfo::BOTTOM_HALF) || + info.CheckMonitorPoint(screen_point, m_bounds.x(), mid_y, + DockInfo::LEFT_HALF) || + info.CheckMonitorPoint(screen_point, m_bounds.right(), mid_y, + DockInfo::RIGHT_HALF); + + return info; +} + +HWND DockInfo::GetLocalProcessWindowAtPoint(const gfx::Point& screen_point, + const std::set<HWND>& ignore) { + if (factory_) + return factory_->GetLocalProcessWindowAtPoint(screen_point, ignore); + return + LocalProcessWindowFinder::GetProcessWindowAtPoint(screen_point, ignore); +} + +bool DockInfo::GetWindowBounds(gfx::Rect* bounds) const { + RECT window_rect; + if (!window() || !GetWindowRect(window(), &window_rect)) + return false; + *bounds = gfx::Rect(window_rect); + return true; +} + +void DockInfo::SizeOtherWindowTo(const gfx::Rect& bounds) const { + if (IsZoomed(window())) { + // We're docking relative to another window, we need to make sure the + // window we're docking to isn't maximized. + ShowWindow(window(), SW_RESTORE | SW_SHOWNA); + } + ::SetWindowPos(window(), HWND_TOP, bounds.x(), bounds.y(), bounds.width(), + bounds.height(), SWP_NOACTIVATE | SWP_NOOWNERZORDER); +} diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc index bcc4b8c..f56a00f 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/views/tabs/dragged_tab_controller.cc @@ -153,25 +153,30 @@ class DraggedTabController::DockDisplayer : public AnimationDelegate { const DockInfo& info) : controller_(controller), popup_(NULL), - popup_hwnd_(NULL), + popup_window_(NULL), #pragma warning(suppress: 4355) // Okay to pass "this" here. animation_(this), hidden_(false), in_enable_area_(info.in_enable_area()) { - popup_ = new views::WidgetWin; - popup_->set_window_style(WS_POPUP); - popup_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW | - WS_EX_TOPMOST); - popup_->SetLayeredAlpha(0x00); - popup_->Init(NULL, info.GetPopupRect(), false); - popup_->SetContentsView(new DockView(info.type())); +#if defined(OS_WIN) + views::WidgetWin* popup = new views::WidgetWin; + popup_ = popup; + popup->set_window_style(WS_POPUP); + popup->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW | + WS_EX_TOPMOST); + popup->SetLayeredAlpha(0x00); + popup->Init(NULL, info.GetPopupRect(), false); + popup->SetContentsView(new DockView(info.type())); if (info.in_enable_area()) animation_.Reset(1); else animation_.Show(); - popup_->SetWindowPos(HWND_TOP, 0, 0, 0, 0, + popup->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOMOVE | SWP_SHOWWINDOW); - popup_hwnd_ = popup_->GetNativeView(); +#else + NOTIMPLEMENTED() +#endif + popup_window_ = popup_->GetNativeView(); } ~DockDisplayer() { @@ -191,8 +196,8 @@ class DraggedTabController::DockDisplayer : public AnimationDelegate { // when the DraggedTabController is destoryed. void clear_controller() { controller_ = NULL; } - // HWND of the window we create. - HWND popup_hwnd() { return popup_hwnd_; } + // NativeWindow of the window we create. + gfx::NativeWindow popup_window() { return popup_window_; } // Starts the hide animation. When the window is closed the // DraggedTabController is notified by way of the DockDisplayerDestroyed @@ -216,14 +221,22 @@ class DraggedTabController::DockDisplayer : public AnimationDelegate { virtual void AnimationEnded(const Animation* animation) { if (!hidden_) return; - popup_->Close(); +#if defined(OS_WIN) + static_cast<views::WidgetWin*>(popup_)->Close(); +#else + NOTIMPLEMENTED(); +#endif delete this; } virtual void UpdateLayeredAlpha() { double scale = in_enable_area_ ? 1 : .5; - popup_->SetLayeredAlpha( +#if defined(OS_WIN) + static_cast<views::WidgetWin*>(popup_)->SetLayeredAlpha( static_cast<BYTE>(animation_.GetCurrentValue() * scale * 255.0)); +#else + NOTIMPLEMENTED(); +#endif popup_->GetRootView()->SchedulePaint(); } @@ -232,11 +245,11 @@ class DraggedTabController::DockDisplayer : public AnimationDelegate { DraggedTabController* controller_; // Window we're showing. - views::WidgetWin* popup_; + views::Widget* popup_; - // HWND of |popup_|. We cache this to avoid the possibility of invoking a - // method on popup_ after we close it. - HWND popup_hwnd_; + // NativeWindow of |popup_|. We cache this to avoid the possibility of + // invoking a method on popup_ after we close it. + gfx::NativeWindow popup_window_; // Animation for when first made visible. SlideAnimation animation_; @@ -464,9 +477,9 @@ void DraggedTabController::UpdateDockInfo(const gfx::Point& screen_point) { if (dock_info_.type() != DockInfo::NONE) { // Show new docking position. DockDisplayer* controller = new DockDisplayer(this, dock_info_); - if (controller->popup_hwnd()) { + if (controller->popup_window()) { dock_controllers_.push_back(controller); - dock_windows_.insert(controller->popup_hwnd()); + dock_windows_.insert(controller->popup_window()); } else { delete controller; } @@ -1113,8 +1126,8 @@ void DraggedTabController::OnAnimateToBoundsComplete() { void DraggedTabController::DockDisplayerDestroyed( DockDisplayer* controller) { - std::set<HWND>::iterator dock_i = - dock_windows_.find(controller->popup_hwnd()); + DockWindows::iterator dock_i = + dock_windows_.find(controller->popup_window()); if (dock_i != dock_windows_.end()) dock_windows_.erase(dock_i); else @@ -1131,7 +1144,7 @@ void DraggedTabController::DockDisplayerDestroyed( void DraggedTabController::BringWindowUnderMouseToFront() { // If we're going to dock to another window, bring it to the front. - HWND hwnd = dock_info_.hwnd(); + HWND hwnd = dock_info_.window(); if (!hwnd) { HWND dragged_hwnd = view_->GetWidget()->GetNativeView(); dock_windows_.insert(dragged_hwnd); diff --git a/chrome/browser/views/tabs/dragged_tab_controller.h b/chrome/browser/views/tabs/dragged_tab_controller.h index 4406118..2418913 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.h +++ b/chrome/browser/views/tabs/dragged_tab_controller.h @@ -297,7 +297,8 @@ class DraggedTabController : public TabContentsDelegate, DockInfo dock_info_; - std::set<HWND> dock_windows_; + typedef std::set<gfx::NativeWindow> DockWindows; + DockWindows dock_windows_; std::vector<DockDisplayer*> dock_controllers_; // Timer used to bring the window under the cursor to front. If the user diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 0ca6e3a..2e7defb 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1673,6 +1673,14 @@ # Exclude all of views. ['exclude', '^browser/views/'], ], + 'conditions': [ + ['toolkit_views==1',{ + 'sources/': [ + ['include', '^browser/dock_info.cc'], + ['include', '^browser/dock_info.h'], + ], + }], + ], 'sources!': [ 'browser/autocomplete/autocomplete_accessibility.cc', 'browser/automation/ui_controls.cc', diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h index eda42e8..bcf4dca 100644 --- a/chrome/common/temp_scaffolding_stubs.h +++ b/chrome/common/temp_scaffolding_stubs.h @@ -350,6 +350,7 @@ class FaviconStatus { GURL url_; }; +#if !defined(TOOLKIT_VIEWS) class DockInfo { public: bool GetNewWindowBounds(gfx::Rect*, bool*) const { @@ -358,6 +359,7 @@ class DockInfo { } void AdjustOtherWindowBounds() const { NOTIMPLEMENTED(); } }; +#endif #if defined(OS_LINUX) class WindowSizer { |