OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 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/dock_info.h" | |
6 | |
7 #include <gtk/gtk.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/task.h" | |
11 #include "chrome/browser/browser_list.h" | |
12 #include "chrome/browser/browser_window.h" | |
13 #include "chrome/browser/gtk/browser_window_gtk.h" | |
14 #include "chrome/browser/gtk/gtk_util.h" | |
15 #include "gfx/native_widget_types.h" | |
16 | |
17 //////////////////////////////////////////////////////////////////////////////// | |
18 // BaseWindowFinder | |
19 // | |
20 // Base class used to locate a window. A subclass need only override | |
21 // ShouldStopIterating to determine when iteration should stop. | |
22 class BaseWindowFinder : public x11_util::EnumerateWindowsDelegate { | |
23 public: | |
24 explicit BaseWindowFinder(const std::set<GtkWidget*>& ignore) { | |
25 std::set<GtkWidget*>::iterator iter; | |
26 for (iter = ignore.begin(); iter != ignore.end(); iter++) { | |
27 XID xid = x11_util::GetX11WindowFromGtkWidget(*iter); | |
28 ignore_.insert(xid); | |
29 } | |
30 } | |
31 | |
32 virtual ~BaseWindowFinder() {} | |
33 | |
34 protected: | |
35 // Returns true if |window| is in the ignore list. | |
36 bool ShouldIgnoreWindow(XID window) { | |
37 return (ignore_.find(window) != ignore_.end()); | |
38 } | |
39 | |
40 // Returns true if iteration should stop, false otherwise. | |
41 virtual bool ShouldStopIterating(XID window) { | |
42 return false; | |
43 } | |
44 | |
45 private: | |
46 std::set<XID> ignore_; | |
47 | |
48 DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder); | |
49 }; | |
50 | |
51 //////////////////////////////////////////////////////////////////////////////// | |
52 // TopMostFinder | |
53 // | |
54 // Helper class to determine if a particular point of a window is not obscured | |
55 // by another window. | |
56 class TopMostFinder : public BaseWindowFinder { | |
57 public: | |
58 // Returns true if |window| is not obscured by another window at the | |
59 // location |screen_loc|, not including the windows in |ignore|. | |
60 static bool IsTopMostWindowAtPoint(XID window, | |
61 const gfx::Point& screen_loc, | |
62 const std::set<GtkWidget*>& ignore) { | |
63 TopMostFinder finder(window, screen_loc, ignore); | |
64 return finder.is_top_most_; | |
65 } | |
66 | |
67 protected: | |
68 virtual bool ShouldStopIterating(XID window) { | |
69 if (BaseWindowFinder::ShouldIgnoreWindow(window)) | |
70 return false; | |
71 | |
72 if (window == target_) { | |
73 // Window is topmost, stop iterating. | |
74 is_top_most_ = true; | |
75 return true; | |
76 } | |
77 | |
78 if (!x11_util::IsWindowVisible(window)) { | |
79 // The window isn't visible, keep iterating. | |
80 return false; | |
81 } | |
82 | |
83 gfx::Rect rect; | |
84 if (x11_util::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) { | |
85 // At this point we haven't found our target window, so this window is | |
86 // higher in the z-order than the target window. If this window contains | |
87 // the point, then we can stop the search now because this window is | |
88 // obscuring the target window at this point. | |
89 return true; | |
90 } | |
91 | |
92 return false; | |
93 } | |
94 | |
95 private: | |
96 TopMostFinder(XID window, | |
97 const gfx::Point& screen_loc, | |
98 const std::set<GtkWidget*>& ignore) | |
99 : BaseWindowFinder(ignore), | |
100 target_(window), | |
101 screen_loc_(screen_loc), | |
102 is_top_most_(false) { | |
103 gtk_util::EnumerateTopLevelWindows(this); | |
104 } | |
105 | |
106 // The window we're looking for. | |
107 XID target_; | |
108 | |
109 // Location of window to find. | |
110 gfx::Point screen_loc_; | |
111 | |
112 // Is target_ the top most window? This is initially false but set to true | |
113 // in ShouldStopIterating if target_ is passed in. | |
114 bool is_top_most_; | |
115 | |
116 DISALLOW_COPY_AND_ASSIGN(TopMostFinder); | |
117 }; | |
118 | |
119 //////////////////////////////////////////////////////////////////////////////// | |
120 // LocalProcessWindowFinder | |
121 // | |
122 // Helper class to determine if a particular point of a window from our process | |
123 // is not obscured by another window. | |
124 class LocalProcessWindowFinder : public BaseWindowFinder { | |
125 public: | |
126 // Returns the XID from our process at screen_loc that is not obscured by | |
127 // another window. Returns 0 otherwise. | |
128 static XID GetProcessWindowAtPoint(const gfx::Point& screen_loc, | |
129 const std::set<GtkWidget*>& ignore) { | |
130 LocalProcessWindowFinder finder(screen_loc, ignore); | |
131 if (finder.result_ && | |
132 TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc, | |
133 ignore)) { | |
134 return finder.result_; | |
135 } | |
136 return 0; | |
137 } | |
138 | |
139 protected: | |
140 virtual bool ShouldStopIterating(XID window) { | |
141 if (BaseWindowFinder::ShouldIgnoreWindow(window)) | |
142 return false; | |
143 | |
144 // Check if this window is in our process. | |
145 if (!BrowserWindowGtk::GetBrowserWindowForXID(window)) | |
146 return false; | |
147 | |
148 if (!x11_util::IsWindowVisible(window)) | |
149 return false; | |
150 | |
151 gfx::Rect rect; | |
152 if (x11_util::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) { | |
153 result_ = window; | |
154 return true; | |
155 } | |
156 | |
157 return false; | |
158 } | |
159 | |
160 private: | |
161 LocalProcessWindowFinder(const gfx::Point& screen_loc, | |
162 const std::set<GtkWidget*>& ignore) | |
163 : BaseWindowFinder(ignore), | |
164 screen_loc_(screen_loc), | |
165 result_(0) { | |
166 gtk_util::EnumerateTopLevelWindows(this); | |
167 } | |
168 | |
169 // Position of the mouse. | |
170 gfx::Point screen_loc_; | |
171 | |
172 // The resulting window. This is initially null but set to true in | |
173 // ShouldStopIterating if an appropriate window is found. | |
174 XID result_; | |
175 | |
176 DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder); | |
177 }; | |
178 | |
179 // static | |
180 DockInfo DockInfo::GetDockInfoAtPoint(const gfx::Point& screen_point, | |
181 const std::set<GtkWidget*>& ignore) { | |
182 if (factory_) | |
183 return factory_->GetDockInfoAtPoint(screen_point, ignore); | |
184 | |
185 NOTIMPLEMENTED(); | |
186 return DockInfo(); | |
187 } | |
188 | |
189 // static | |
190 GtkWindow* DockInfo::GetLocalProcessWindowAtPoint( | |
191 const gfx::Point& screen_point, | |
192 const std::set<GtkWidget*>& ignore) { | |
193 if (factory_) | |
194 return factory_->GetLocalProcessWindowAtPoint(screen_point, ignore); | |
195 | |
196 #if defined(OS_CHROMEOS) || defined(TOOLKIT_VIEWS) | |
197 return NULL; | |
198 #else | |
199 XID xid = | |
200 LocalProcessWindowFinder::GetProcessWindowAtPoint(screen_point, ignore); | |
201 return BrowserWindowGtk::GetBrowserWindowForXID(xid); | |
202 #endif | |
203 } | |
204 | |
205 bool DockInfo::GetWindowBounds(gfx::Rect* bounds) const { | |
206 if (!window()) | |
207 return false; | |
208 | |
209 int x, y, w, h; | |
210 gtk_window_get_position(window(), &x, &y); | |
211 gtk_window_get_size(window(), &w, &h); | |
212 bounds->SetRect(x, y, w, h); | |
213 return true; | |
214 } | |
215 | |
216 void DockInfo::SizeOtherWindowTo(const gfx::Rect& bounds) const { | |
217 gtk_window_move(window(), bounds.x(), bounds.y()); | |
218 gtk_window_resize(window(), bounds.width(), bounds.height()); | |
219 } | |
OLD | NEW |