Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(406)

Side by Side Diff: chrome/browser/ui/tabs/dock_info_win.cc

Issue 10537097: browser: Move dock_info* into their ui/ specific directories. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/tabs/dock_info_mac.cc ('k') | chrome/browser/ui/views/tabs/dock_info_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/tabs/dock_info.h"
6
7 #include "base/win/scoped_gdi_object.h"
8 #include "base/win/windows_version.h"
9 #include "chrome/browser/ui/browser_list.h"
10 #include "chrome/browser/ui/browser_window.h"
11 #include "chrome/browser/ui/views/frame/browser_view.h"
12 #include "chrome/browser/ui/views/tabs/tab.h"
13 #include "ui/gfx/screen.h"
14
15 namespace {
16
17 // BaseWindowFinder -----------------------------------------------------------
18
19 // Base class used to locate a window. This is intended to be used with the
20 // various win32 functions that iterate over windows.
21 //
22 // A subclass need only override ShouldStopIterating to determine when
23 // iteration should stop.
24 class BaseWindowFinder {
25 public:
26 // Creates a BaseWindowFinder with the specified set of HWNDs to ignore.
27 explicit BaseWindowFinder(const std::set<HWND>& ignore) : ignore_(ignore) {}
28 virtual ~BaseWindowFinder() {}
29
30 protected:
31 static BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) {
32 // Cast must match that in as_lparam().
33 BaseWindowFinder* finder = reinterpret_cast<BaseWindowFinder*>(lParam);
34 if (finder->ignore_.find(hwnd) != finder->ignore_.end())
35 return TRUE;
36
37 return finder->ShouldStopIterating(hwnd) ? FALSE : TRUE;
38 }
39
40 LPARAM as_lparam() {
41 // Cast must match that in WindowCallbackProc().
42 return reinterpret_cast<LPARAM>(static_cast<BaseWindowFinder*>(this));
43 }
44
45 // Returns true if iteration should stop, false if iteration should continue.
46 virtual bool ShouldStopIterating(HWND window) = 0;
47
48 private:
49 const std::set<HWND>& ignore_;
50
51 DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder);
52 };
53
54 // TopMostFinder --------------------------------------------------------------
55
56 // Helper class to determine if a particular point of a window is not obscured
57 // by another window.
58 class TopMostFinder : public BaseWindowFinder {
59 public:
60 // Returns true if |window| is the topmost window at the location
61 // |screen_loc|, not including the windows in |ignore|.
62 static bool IsTopMostWindowAtPoint(HWND window,
63 const gfx::Point& screen_loc,
64 const std::set<HWND>& ignore) {
65 TopMostFinder finder(window, screen_loc, ignore);
66 return finder.is_top_most_;
67 }
68
69 virtual bool ShouldStopIterating(HWND hwnd) {
70 if (hwnd == target_) {
71 // Window is topmost, stop iterating.
72 is_top_most_ = true;
73 return true;
74 }
75
76 if (!IsWindowVisible(hwnd)) {
77 // The window isn't visible, keep iterating.
78 return false;
79 }
80
81 RECT r;
82 if (!GetWindowRect(hwnd, &r) || !PtInRect(&r, screen_loc_.ToPOINT())) {
83 // The window doesn't contain the point, keep iterating.
84 return false;
85 }
86
87 LONG ex_styles = GetWindowLong(hwnd, GWL_EXSTYLE);
88 if (ex_styles & WS_EX_TRANSPARENT || ex_styles & WS_EX_LAYERED) {
89 // Mouse events fall through WS_EX_TRANSPARENT windows, so we ignore them.
90 //
91 // WS_EX_LAYERED is trickier. Apps like Switcher create a totally
92 // transparent WS_EX_LAYERED window that is always on top. If we don't
93 // ignore WS_EX_LAYERED windows and there are totally transparent
94 // WS_EX_LAYERED windows then there are effectively holes on the screen
95 // that the user can't reattach tabs to. So we ignore them. This is a bit
96 // problematic in so far as WS_EX_LAYERED windows need not be totally
97 // transparent in which case we treat chrome windows as not being obscured
98 // when they really are, but this is better than not being able to
99 // reattach tabs.
100 return false;
101 }
102
103 // hwnd is at the point. Make sure the point is within the windows region.
104 if (GetWindowRgn(hwnd, tmp_region_.Get()) == ERROR) {
105 // There's no region on the window and the window contains the point. Stop
106 // iterating.
107 return true;
108 }
109
110 // The region is relative to the window's rect.
111 BOOL is_point_in_region = PtInRegion(tmp_region_.Get(),
112 screen_loc_.x() - r.left, screen_loc_.y() - r.top);
113 tmp_region_ = CreateRectRgn(0, 0, 0, 0);
114 // Stop iterating if the region contains the point.
115 return !!is_point_in_region;
116 }
117
118 private:
119 TopMostFinder(HWND window,
120 const gfx::Point& screen_loc,
121 const std::set<HWND>& ignore)
122 : BaseWindowFinder(ignore),
123 target_(window),
124 screen_loc_(screen_loc),
125 is_top_most_(false),
126 tmp_region_(CreateRectRgn(0, 0, 0, 0)) {
127 EnumWindows(WindowCallbackProc, as_lparam());
128 }
129
130 // The window we're looking for.
131 HWND target_;
132
133 // Location of window to find.
134 gfx::Point screen_loc_;
135
136 // Is target_ the top most window? This is initially false but set to true
137 // in ShouldStopIterating if target_ is passed in.
138 bool is_top_most_;
139
140 base::win::ScopedRegion tmp_region_;
141
142 DISALLOW_COPY_AND_ASSIGN(TopMostFinder);
143 };
144
145 // WindowFinder ---------------------------------------------------------------
146
147 // Helper class to determine if a particular point contains a window from our
148 // process.
149 class LocalProcessWindowFinder : public BaseWindowFinder {
150 public:
151 // Returns the hwnd from our process at screen_loc that is not obscured by
152 // another window. Returns NULL otherwise.
153 static HWND GetProcessWindowAtPoint(const gfx::Point& screen_loc,
154 const std::set<HWND>& ignore) {
155 LocalProcessWindowFinder finder(screen_loc, ignore);
156 // Windows 8 has a window that appears first in the list of iterated
157 // windows, yet is not visually on top of everything.
158 // TODO(sky): figure out a better way to ignore this window.
159 if (finder.result_ &&
160 ((base::win::OSInfo::GetInstance()->version() >=
161 base::win::VERSION_WIN8) ||
162 TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc,
163 ignore))) {
164 return finder.result_;
165 }
166 return NULL;
167 }
168
169 protected:
170 virtual bool ShouldStopIterating(HWND hwnd) {
171 RECT r;
172 if (IsWindowVisible(hwnd) && GetWindowRect(hwnd, &r) &&
173 PtInRect(&r, screen_loc_.ToPOINT())) {
174 result_ = hwnd;
175 return true;
176 }
177 return false;
178 }
179
180 private:
181 LocalProcessWindowFinder(const gfx::Point& screen_loc,
182 const std::set<HWND>& ignore)
183 : BaseWindowFinder(ignore),
184 screen_loc_(screen_loc),
185 result_(NULL) {
186 EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, as_lparam());
187 }
188
189 // Position of the mouse.
190 gfx::Point screen_loc_;
191
192 // The resulting window. This is initially null but set to true in
193 // ShouldStopIterating if an appropriate window is found.
194 HWND result_;
195
196 DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder);
197 };
198
199 // DockToWindowFinder ---------------------------------------------------------
200
201 // Helper class for creating a DockInfo from a specified point.
202 class DockToWindowFinder : public BaseWindowFinder {
203 public:
204 // Returns the DockInfo for the specified point. If there is no docking
205 // position for the specified point the returned DockInfo has a type of NONE.
206 static DockInfo GetDockInfoAtPoint(const gfx::Point& screen_loc,
207 const std::set<HWND>& ignore) {
208 DockToWindowFinder finder(screen_loc, ignore);
209 if (!finder.result_.window() ||
210 !TopMostFinder::IsTopMostWindowAtPoint(finder.result_.window(),
211 finder.result_.hot_spot(),
212 ignore)) {
213 finder.result_.set_type(DockInfo::NONE);
214 }
215 return finder.result_;
216 }
217
218 protected:
219 virtual bool ShouldStopIterating(HWND hwnd) {
220 BrowserView* window = BrowserView::GetBrowserViewForNativeWindow(hwnd);
221 RECT bounds;
222 if (!window || !IsWindowVisible(hwnd) ||
223 !GetWindowRect(hwnd, &bounds)) {
224 return false;
225 }
226
227 // Check the three corners we allow docking to. We don't currently allow
228 // docking to top of window as it conflicts with docking to the tab strip.
229 if (CheckPoint(hwnd, bounds.left, (bounds.top + bounds.bottom) / 2,
230 DockInfo::LEFT_OF_WINDOW) ||
231 CheckPoint(hwnd, bounds.right - 1, (bounds.top + bounds.bottom) / 2,
232 DockInfo::RIGHT_OF_WINDOW) ||
233 CheckPoint(hwnd, (bounds.left + bounds.right) / 2, bounds.bottom - 1,
234 DockInfo::BOTTOM_OF_WINDOW)) {
235 return true;
236 }
237 return false;
238 }
239
240 private:
241 DockToWindowFinder(const gfx::Point& screen_loc,
242 const std::set<HWND>& ignore)
243 : BaseWindowFinder(ignore),
244 screen_loc_(screen_loc) {
245 gfx::Rect work_area = gfx::Screen::GetMonitorNearestPoint(
246 screen_loc).bounds();
247 if (!work_area.IsEmpty()) {
248 result_.set_monitor_bounds(work_area);
249 EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, as_lparam());
250 }
251 }
252
253 bool CheckPoint(HWND hwnd, int x, int y, DockInfo::Type type) {
254 bool in_enable_area;
255 if (DockInfo::IsCloseToPoint(screen_loc_, x, y, &in_enable_area)) {
256 result_.set_in_enable_area(in_enable_area);
257 result_.set_window(hwnd);
258 result_.set_type(type);
259 result_.set_hot_spot(gfx::Point(x, y));
260 // Only show the hotspot if the monitor contains the bounds of the popup
261 // window. Otherwise we end with a weird situation where the popup window
262 // isn't completely visible.
263 return result_.monitor_bounds().Contains(result_.GetPopupRect());
264 }
265 return false;
266 }
267
268 // The location to look for.
269 gfx::Point screen_loc_;
270
271 // The resulting DockInfo.
272 DockInfo result_;
273
274 DISALLOW_COPY_AND_ASSIGN(DockToWindowFinder);
275 };
276
277 } // namespace
278
279 // DockInfo -------------------------------------------------------------------
280
281 // static
282 DockInfo DockInfo::GetDockInfoAtPoint(const gfx::Point& screen_point,
283 const std::set<HWND>& ignore) {
284 if (factory_)
285 return factory_->GetDockInfoAtPoint(screen_point, ignore);
286
287 // Try docking to a window first.
288 DockInfo info = DockToWindowFinder::GetDockInfoAtPoint(screen_point, ignore);
289 if (info.type() != DockInfo::NONE)
290 return info;
291
292 // No window relative positions. Try monitor relative positions.
293 const gfx::Rect& m_bounds = info.monitor_bounds();
294 int mid_x = m_bounds.x() + m_bounds.width() / 2;
295 int mid_y = m_bounds.y() + m_bounds.height() / 2;
296
297 bool result =
298 info.CheckMonitorPoint(screen_point, mid_x, m_bounds.y(),
299 DockInfo::MAXIMIZE) ||
300 info.CheckMonitorPoint(screen_point, mid_x, m_bounds.bottom(),
301 DockInfo::BOTTOM_HALF) ||
302 info.CheckMonitorPoint(screen_point, m_bounds.x(), mid_y,
303 DockInfo::LEFT_HALF) ||
304 info.CheckMonitorPoint(screen_point, m_bounds.right(), mid_y,
305 DockInfo::RIGHT_HALF);
306
307 return info;
308 }
309
310 HWND DockInfo::GetLocalProcessWindowAtPoint(const gfx::Point& screen_point,
311 const std::set<HWND>& ignore) {
312 if (factory_)
313 return factory_->GetLocalProcessWindowAtPoint(screen_point, ignore);
314 return
315 LocalProcessWindowFinder::GetProcessWindowAtPoint(screen_point, ignore);
316 }
317
318 bool DockInfo::GetWindowBounds(gfx::Rect* bounds) const {
319 RECT window_rect;
320 if (!window() || !GetWindowRect(window(), &window_rect))
321 return false;
322 *bounds = gfx::Rect(window_rect);
323 return true;
324 }
325
326 void DockInfo::SizeOtherWindowTo(const gfx::Rect& bounds) const {
327 if (IsZoomed(window())) {
328 // We're docking relative to another window, we need to make sure the
329 // window we're docking to isn't maximized.
330 ShowWindow(window(), SW_RESTORE | SW_SHOWNA);
331 }
332 SetWindowPos(window(), HWND_TOP, bounds.x(), bounds.y(), bounds.width(),
333 bounds.height(), SWP_NOACTIVATE | SWP_NOOWNERZORDER);
334 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/tabs/dock_info_mac.cc ('k') | chrome/browser/ui/views/tabs/dock_info_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698