OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "ui/views/desktop/desktop_window_manager.h" | |
6 | |
7 #include "ui/base/hit_test.h" | |
8 #include "ui/gfx/point.h" | |
9 #include "ui/gfx/rect.h" | |
10 #include "ui/views/events/event.h" | |
11 #include "ui/views/window/non_client_view.h" | |
12 #include "views/widget/native_widget_private.h" | |
13 #include "views/widget/native_widget_view.h" | |
14 #include "views/widget/native_widget_views.h" | |
15 #include "views/widget/widget_delegate.h" | |
16 | |
17 namespace { | |
18 | |
19 class MoveWindowController : public views::desktop::WindowController { | |
20 public: | |
21 MoveWindowController(views::Widget* widget, const gfx::Point& start) | |
22 : target_(widget), | |
23 offset_(start) { | |
24 } | |
25 | |
26 virtual ~MoveWindowController() { | |
27 } | |
28 | |
29 bool OnMouseEvent(const views::MouseEvent& event) { | |
30 if (event.type()== ui::ET_MOUSE_DRAGGED) { | |
31 gfx::Point origin = event.location().Subtract(offset_); | |
32 gfx::Rect rect = target_->GetWindowScreenBounds(); | |
33 rect.set_origin(origin); | |
34 target_->SetBounds(rect); | |
35 return true; | |
36 } | |
37 return false; | |
38 } | |
39 | |
40 private: | |
41 views::Widget* target_; | |
42 gfx::Point offset_; | |
43 | |
44 DISALLOW_COPY_AND_ASSIGN(MoveWindowController); | |
45 }; | |
46 | |
47 // Simple resize controller that handle all resize as if the bottom | |
48 // right corner is selected. | |
49 class ResizeWindowController : public views::desktop::WindowController { | |
50 public: | |
51 ResizeWindowController(views::Widget* widget) | |
52 : target_(widget) { | |
53 } | |
54 | |
55 virtual ~ResizeWindowController() { | |
56 } | |
57 | |
58 bool OnMouseEvent(const views::MouseEvent& event) OVERRIDE { | |
59 if (event.type()== ui::ET_MOUSE_DRAGGED) { | |
60 gfx::Point location = event.location(); | |
61 gfx::Rect rect = target_->GetWindowScreenBounds(); | |
62 gfx::Point size = location.Subtract(rect.origin()); | |
63 target_->SetSize(gfx::Size(std::max(10, size.x()), | |
64 std::max(10, size.y()))); | |
65 return true; | |
66 } | |
67 return false; | |
68 } | |
69 | |
70 private: | |
71 views::Widget* target_; | |
72 | |
73 DISALLOW_COPY_AND_ASSIGN(ResizeWindowController); | |
74 }; | |
75 | |
76 } // namespace | |
77 | |
78 namespace views { | |
79 namespace desktop { | |
80 | |
81 WindowController::WindowController() { | |
82 } | |
83 | |
84 WindowController::~WindowController() { | |
85 } | |
86 | |
87 //////////////////////////////////////////////////////////////////////////////// | |
88 // DesktopWindowManager, public: | |
89 | |
90 DesktopWindowManager::DesktopWindowManager(Widget* desktop) | |
91 : desktop_(desktop), | |
92 mouse_capture_(NULL), | |
93 active_widget_(NULL) { | |
94 } | |
95 | |
96 DesktopWindowManager::~DesktopWindowManager() { | |
97 DCHECK_EQ(0U, toplevels_.size()) << "Window manager getting destroyed " | |
98 << "before all the windows are closed."; | |
99 } | |
100 | |
101 void DesktopWindowManager::UpdateWindowsAfterScreenSizeChanged( | |
102 const gfx::Rect& new_size) { | |
103 for (std::vector<Widget*>::iterator i = toplevels_.begin(); | |
104 i != toplevels_.end(); ++i) { | |
105 Widget* toplevel = *i; | |
106 if (!toplevel->IsMaximized()) | |
107 continue; | |
108 | |
109 // If the window is maximized, then resize it! | |
110 toplevel->SetSize(new_size.size()); | |
111 } | |
112 } | |
113 | |
114 //////////////////////////////////////////////////////////////////////////////// | |
115 // DesktopWindowManager, WindowManager implementation: | |
116 | |
117 void DesktopWindowManager::StartMoveDrag( | |
118 views::Widget* widget, | |
119 const gfx::Point& point) { | |
120 DCHECK(!window_controller_.get()); | |
121 DCHECK(!HasMouseCapture()); | |
122 if (!widget->IsMaximized() && !widget->IsMinimized()) { | |
123 gfx::Point new_point = point; | |
124 if (desktop_->non_client_view()) { | |
125 gfx::Rect client = | |
126 desktop_->non_client_view()->frame_view()->GetBoundsForClientView(); | |
127 new_point.Offset(client.x(), client.y()); | |
128 } | |
129 SetMouseCapture(); | |
130 window_controller_.reset(new MoveWindowController(widget, new_point)); | |
131 } | |
132 } | |
133 | |
134 void DesktopWindowManager::StartResizeDrag( | |
135 views::Widget* widget, const gfx::Point& point, int hittest_code) { | |
136 DCHECK(!window_controller_.get()); | |
137 DCHECK(!HasMouseCapture()); | |
138 if (!widget->IsMaximized() && | |
139 !widget->IsMinimized() && | |
140 (widget->widget_delegate() || widget->widget_delegate()->CanResize())) { | |
141 SetMouseCapture(); | |
142 window_controller_.reset(new ResizeWindowController(widget)); | |
143 } | |
144 } | |
145 | |
146 bool DesktopWindowManager::SetMouseCapture(views::Widget* widget) { | |
147 if (mouse_capture_) | |
148 return false; | |
149 if (mouse_capture_ == widget) | |
150 return true; | |
151 DCHECK(!HasMouseCapture()); | |
152 SetMouseCapture(); | |
153 mouse_capture_ = widget; | |
154 return true; | |
155 } | |
156 | |
157 bool DesktopWindowManager::ReleaseMouseCapture(views::Widget* widget) { | |
158 if (!widget || mouse_capture_ != widget) | |
159 return false; | |
160 DCHECK(HasMouseCapture()); | |
161 ReleaseMouseCapture(); | |
162 mouse_capture_ = NULL; | |
163 return true; | |
164 } | |
165 | |
166 bool DesktopWindowManager::HasMouseCapture(const views::Widget* widget) const { | |
167 return widget && mouse_capture_ == widget; | |
168 } | |
169 | |
170 bool DesktopWindowManager::HandleKeyEvent( | |
171 views::Widget* widget, const views::KeyEvent& event) { | |
172 return active_widget_ ? | |
173 static_cast<NativeWidgetViews*>(active_widget_->native_widget_private()) | |
174 ->OnKeyEvent(event) : false; | |
175 } | |
176 | |
177 bool DesktopWindowManager::HandleMouseEvent( | |
178 views::Widget* widget, const views::MouseEvent& event) { | |
179 if (mouse_capture_) { | |
180 views::MouseEvent translated(event, widget->GetRootView(), | |
181 mouse_capture_->GetRootView()); | |
182 mouse_capture_->OnMouseEvent(translated); | |
183 return true; | |
184 } | |
185 | |
186 if (event.type() == ui::ET_MOUSE_PRESSED) | |
187 ActivateWidgetAtLocation(widget, event.location()); | |
188 else if (event.type() == ui::ET_MOUSEWHEEL && active_widget_) | |
189 return active_widget_->OnMouseEvent(event); | |
190 | |
191 if (window_controller_.get()) { | |
192 if (!window_controller_->OnMouseEvent(event)) { | |
193 ReleaseMouseCapture(); | |
194 window_controller_.reset(); | |
195 } | |
196 return true; | |
197 } | |
198 | |
199 return false; | |
200 } | |
201 | |
202 ui::TouchStatus DesktopWindowManager::HandleTouchEvent(Widget* widget, | |
203 const TouchEvent& event) { | |
204 // If there is a widget capturing mouse events, the widget should also receive | |
205 // touch events. | |
206 if (mouse_capture_) { | |
207 views::TouchEvent translated(event, widget->GetRootView(), | |
208 mouse_capture_->GetRootView()); | |
209 return mouse_capture_->OnTouchEvent(translated); | |
210 } | |
211 | |
212 // If a touch event activates a Widget, let the event still go through to the | |
213 // activated Widget. | |
214 if (event.type() == ui::ET_TOUCH_PRESSED) | |
215 ActivateWidgetAtLocation(widget, event.location()); | |
216 return ui::TOUCH_STATUS_UNKNOWN; | |
217 } | |
218 | |
219 void DesktopWindowManager::Register(Widget* widget) { | |
220 DCHECK(!widget->HasObserver(this)); | |
221 if (widget->is_top_level()) | |
222 toplevels_.push_back(widget); | |
223 widget->AddObserver(this); | |
224 } | |
225 | |
226 //////////////////////////////////////////////////////////////////////////////// | |
227 // DesktopWindowManager, private: | |
228 | |
229 void DesktopWindowManager::OnWidgetClosing(Widget* widget) { | |
230 if (active_widget_ && active_widget_ == widget) | |
231 active_widget_ = NULL; | |
232 if (widget->is_top_level()) { | |
233 for (std::vector<Widget*>::iterator i = toplevels_.begin(); | |
234 i != toplevels_.end(); ++i) { | |
235 if (*i == widget) { | |
236 toplevels_.erase(i); | |
237 break; | |
238 } | |
239 } | |
240 } | |
241 } | |
242 | |
243 void DesktopWindowManager::OnWidgetVisibilityChanged(Widget* widget, | |
244 bool visible) { | |
245 // If there's no active Widget, then activate the first visible toplevel | |
246 // Widget. | |
247 if (widget->is_top_level() && widget->CanActivate() && visible && | |
248 active_widget_ == NULL) { | |
249 Activate(widget); | |
250 } | |
251 } | |
252 | |
253 void DesktopWindowManager::OnWidgetActivationChanged(Widget* widget, | |
254 bool active) { | |
255 if (active) { | |
256 if (active_widget_) | |
257 active_widget_->Deactivate(); | |
258 active_widget_ = widget; | |
259 } else if (widget == active_widget_) { | |
260 active_widget_ = NULL; | |
261 } | |
262 } | |
263 | |
264 void DesktopWindowManager::SetMouseCapture() { | |
265 return desktop_->native_widget_private()->SetMouseCapture(); | |
266 } | |
267 | |
268 void DesktopWindowManager::ReleaseMouseCapture() { | |
269 return desktop_->native_widget_private()->ReleaseMouseCapture(); | |
270 } | |
271 | |
272 bool DesktopWindowManager::HasMouseCapture() const { | |
273 return desktop_->native_widget_private()->HasMouseCapture(); | |
274 } | |
275 | |
276 void DesktopWindowManager::Activate(Widget* widget) { | |
277 if (widget && widget->IsActive()) | |
278 return; | |
279 | |
280 if (widget) { | |
281 if (!widget->HasObserver(this)) | |
282 widget->AddObserver(this); | |
283 widget->Activate(); | |
284 } | |
285 } | |
286 | |
287 bool DesktopWindowManager::ActivateWidgetAtLocation(Widget* widget, | |
288 const gfx::Point& point) { | |
289 View* target = widget->GetRootView()->GetEventHandlerForPoint(point); | |
290 | |
291 if (target->GetClassName() == internal::NativeWidgetView::kViewClassName) { | |
292 internal::NativeWidgetView* native_widget_view = | |
293 static_cast<internal::NativeWidgetView*>(target); | |
294 views::Widget* target_widget = native_widget_view->GetAssociatedWidget(); | |
295 if (!target_widget->IsActive() && target_widget->CanActivate()) { | |
296 Activate(target_widget); | |
297 return true; | |
298 } | |
299 } | |
300 | |
301 return false; | |
302 } | |
303 | |
304 } // namespace desktop | |
305 } // namespace views | |
OLD | NEW |