summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser.vcproj4
-rw-r--r--chrome/browser/dock_info.cc371
-rw-r--r--chrome/browser/dock_info.h56
-rw-r--r--chrome/browser/dock_info_win.cc311
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.cc59
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.h3
-rw-r--r--chrome/chrome.gyp8
-rw-r--r--chrome/common/temp_scaffolding_stubs.h2
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 {