1 // Copyright 2014 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 "mojo/services/window_manager/window_manager_app.h"
6
7 #include "base/message_loop/message_loop.h"
8 #include "base/stl_util.h"
9 #include "mojo/aura/aura_init.h"
10 #include "mojo/public/cpp/application/application_connection.h"
11 #include "mojo/public/cpp/application/application_impl.h"
12 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
13 #include "mojo/services/public/cpp/view_manager/view.h"
14 #include "mojo/services/public/cpp/view_manager/view_manager.h"
15 #include "ui/aura/window.h"
16 #include "ui/aura/window_delegate.h"
17 #include "ui/aura/window_property.h"
18 #include "ui/base/hit_test.h"
19 #include "ui/wm/core/capture_controller.h"
20 #include "ui/wm/core/focus_controller.h"
21 #include "ui/wm/core/focus_rules.h"
22 #include "ui/wm/public/activation_client.h"
23
24 DECLARE_WINDOW_PROPERTY_TYPE(mojo::View*);
25
26 namespace mojo {
27
28 // The aura::Windows we use to track Views don't render, so we don't actually
29 // need to supply a fully functional WindowDelegate. We do need to provide _a_
30 // delegate however, otherwise the event dispatcher won't dispatch events to
31 // these windows. (The aura WindowTargeter won't allow a delegate-less window
32 // to be the target of an event, since the window delegate is considered the
33 // "target handler").
34 class DummyDelegate : public aura::WindowDelegate {
35 public:
DummyDelegate()36 DummyDelegate() {}
~DummyDelegate()37 virtual ~DummyDelegate() {}
38
39 private:
40 // WindowDelegate overrides:
GetMinimumSize() const41 virtual gfx::Size GetMinimumSize() const OVERRIDE { return gfx::Size(); }
GetMaximumSize() const42 virtual gfx::Size GetMaximumSize() const OVERRIDE { return gfx::Size(); }
OnBoundsChanged(const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)43 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
44 const gfx::Rect& new_bounds) OVERRIDE {}
GetCursor(const gfx::Point & point)45 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
46 return gfx::kNullCursor;
47 }
GetNonClientComponent(const gfx::Point & point) const48 virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
49 return HTCAPTION;
50 }
ShouldDescendIntoChildForEventHandling(aura::Window * child,const gfx::Point & location)51 virtual bool ShouldDescendIntoChildForEventHandling(
52 aura::Window* child,
53 const gfx::Point& location) OVERRIDE { return true; }
CanFocus()54 virtual bool CanFocus() OVERRIDE { return true; }
OnCaptureLost()55 virtual void OnCaptureLost() OVERRIDE {}
OnPaint(gfx::Canvas * canvas)56 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {}
OnDeviceScaleFactorChanged(float device_scale_factor)57 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
OnWindowDestroying(aura::Window * window)58 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {}
OnWindowDestroyed(aura::Window * window)59 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {}
OnWindowTargetVisibilityChanged(bool visible)60 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
HasHitTestMask() const61 virtual bool HasHitTestMask() const OVERRIDE { return false; }
GetHitTestMask(gfx::Path * mask) const62 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
63
64 DISALLOW_COPY_AND_ASSIGN(DummyDelegate);
65 };
66
67 namespace {
68
69 DEFINE_WINDOW_PROPERTY_KEY(View*, kViewKey, NULL);
70
GetIdForWindow(aura::Window * window)71 Id GetIdForWindow(aura::Window* window) {
72 return window ? WindowManagerApp::GetViewForWindow(window)->id() : 0;
73 }
74
75 class WMFocusRules : public wm::FocusRules {
76 public:
WMFocusRules()77 WMFocusRules() {}
~WMFocusRules()78 virtual ~WMFocusRules() {}
79
80 private:
81 // Overridden from wm::FocusRules:
IsToplevelWindow(aura::Window * window) const82 virtual bool IsToplevelWindow(aura::Window* window) const MOJO_OVERRIDE {
83 return true;
84 }
CanActivateWindow(aura::Window * window) const85 virtual bool CanActivateWindow(aura::Window* window) const MOJO_OVERRIDE {
86 return true;
87 }
CanFocusWindow(aura::Window * window) const88 virtual bool CanFocusWindow(aura::Window* window) const MOJO_OVERRIDE {
89 return true;
90 }
GetToplevelWindow(aura::Window * window) const91 virtual aura::Window* GetToplevelWindow(
92 aura::Window* window) const MOJO_OVERRIDE {
93 return window;
94 }
GetActivatableWindow(aura::Window * window) const95 virtual aura::Window* GetActivatableWindow(
96 aura::Window* window) const MOJO_OVERRIDE {
97 return window;
98 }
GetFocusableWindow(aura::Window * window) const99 virtual aura::Window* GetFocusableWindow(
100 aura::Window* window) const MOJO_OVERRIDE {
101 return window;
102 }
GetNextActivatableWindow(aura::Window * ignore) const103 virtual aura::Window* GetNextActivatableWindow(
104 aura::Window* ignore) const MOJO_OVERRIDE {
105 return NULL;
106 }
107
108 DISALLOW_COPY_AND_ASSIGN(WMFocusRules);
109 };
110
111 } // namespace
112
113 ////////////////////////////////////////////////////////////////////////////////
114 // WindowManagerApp, public:
115
WindowManagerApp(ViewManagerDelegate * view_manager_delegate,WindowManagerDelegate * window_manager_delegate)116 WindowManagerApp::WindowManagerApp(
117 ViewManagerDelegate* view_manager_delegate,
118 WindowManagerDelegate* window_manager_delegate)
119 : window_manager_service_factory_(this),
120 wrapped_view_manager_delegate_(view_manager_delegate),
121 wrapped_window_manager_delegate_(window_manager_delegate),
122 view_manager_(NULL),
123 root_(NULL),
124 dummy_delegate_(new DummyDelegate) {
125 }
126
~WindowManagerApp()127 WindowManagerApp::~WindowManagerApp() {}
128
129 // static
GetViewForWindow(aura::Window * window)130 View* WindowManagerApp::GetViewForWindow(aura::Window* window) {
131 return window->GetProperty(kViewKey);
132 }
133
AddConnection(WindowManagerServiceImpl * connection)134 void WindowManagerApp::AddConnection(WindowManagerServiceImpl* connection) {
135 DCHECK(connections_.find(connection) == connections_.end());
136 connections_.insert(connection);
137 }
138
RemoveConnection(WindowManagerServiceImpl * connection)139 void WindowManagerApp::RemoveConnection(WindowManagerServiceImpl* connection) {
140 DCHECK(connections_.find(connection) != connections_.end());
141 connections_.erase(connection);
142 }
143
SetCapture(Id view)144 void WindowManagerApp::SetCapture(Id view) {
145 capture_client_->capture_client()->SetCapture(GetWindowForViewId(view));
146 // TODO(beng): notify connected clients that capture has changed, probably
147 // by implementing some capture-client observer.
148 }
149
FocusWindow(Id view)150 void WindowManagerApp::FocusWindow(Id view) {
151 aura::Window* window = GetWindowForViewId(view);
152 DCHECK(window);
153 focus_client_->FocusWindow(window);
154 }
155
ActivateWindow(Id view)156 void WindowManagerApp::ActivateWindow(Id view) {
157 aura::Window* window = GetWindowForViewId(view);
158 DCHECK(window);
159 activation_client_->ActivateWindow(window);
160 }
161
IsReady() const162 bool WindowManagerApp::IsReady() const {
163 return view_manager_ && root_;
164 }
165
166 ////////////////////////////////////////////////////////////////////////////////
167 // WindowManagerApp, ApplicationDelegate implementation:
168
Initialize(ApplicationImpl * impl)169 void WindowManagerApp::Initialize(ApplicationImpl* impl) {
170 aura_init_.reset(new AuraInit);
171 view_manager_client_factory_.reset(
172 new ViewManagerClientFactory(impl->shell(), this));
173 }
174
ConfigureIncomingConnection(ApplicationConnection * connection)175 bool WindowManagerApp::ConfigureIncomingConnection(
176 ApplicationConnection* connection) {
177 connection->AddService(&window_manager_service_factory_);
178 connection->AddService(view_manager_client_factory_.get());
179 return true;
180 }
181
182 ////////////////////////////////////////////////////////////////////////////////
183 // WindowManagerApp, ViewManagerDelegate implementation:
184
OnEmbed(ViewManager * view_manager,View * root,ServiceProviderImpl * exported_services,scoped_ptr<ServiceProvider> imported_services)185 void WindowManagerApp::OnEmbed(ViewManager* view_manager,
186 View* root,
187 ServiceProviderImpl* exported_services,
188 scoped_ptr<ServiceProvider> imported_services) {
189 DCHECK(!view_manager_ && !root_);
190 view_manager_ = view_manager;
191 view_manager_->SetWindowManagerDelegate(this);
192 root_ = root;
193
194 window_tree_host_.reset(new WindowTreeHostMojo(root_, this));
195 window_tree_host_->window()->SetBounds(root->bounds());
196 window_tree_host_->window()->Show();
197
198 RegisterSubtree(root_, window_tree_host_->window());
199
200 capture_client_.reset(
201 new wm::ScopedCaptureClient(window_tree_host_->window()));
202 wm::FocusController* focus_controller =
203 new wm::FocusController(new WMFocusRules);
204 activation_client_ = focus_controller;
205 focus_client_.reset(focus_controller);
206 aura::client::SetFocusClient(window_tree_host_->window(), focus_controller);
207
208 focus_client_->AddObserver(this);
209 activation_client_->AddObserver(this);
210
211 if (wrapped_view_manager_delegate_) {
212 wrapped_view_manager_delegate_->OnEmbed(
213 view_manager, root, exported_services, imported_services.Pass());
214 }
215
216 for (Connections::const_iterator it = connections_.begin();
217 it != connections_.end(); ++it) {
218 (*it)->NotifyReady();
219 }
220 }
221
OnViewManagerDisconnected(ViewManager * view_manager)222 void WindowManagerApp::OnViewManagerDisconnected(
223 ViewManager* view_manager) {
224 DCHECK_EQ(view_manager_, view_manager);
225 if (wrapped_view_manager_delegate_)
226 wrapped_view_manager_delegate_->OnViewManagerDisconnected(view_manager);
227 view_manager_ = NULL;
228 base::MessageLoop::current()->Quit();
229 }
230
231 ////////////////////////////////////////////////////////////////////////////////
232 // WindowManagerApp, WindowManagerDelegate implementation:
233
Embed(const String & url,InterfaceRequest<ServiceProvider> service_provider)234 void WindowManagerApp::Embed(
235 const String& url,
236 InterfaceRequest<ServiceProvider> service_provider) {
237 if (wrapped_window_manager_delegate_)
238 wrapped_window_manager_delegate_->Embed(url, service_provider.Pass());
239 }
240
DispatchEvent(EventPtr event)241 void WindowManagerApp::DispatchEvent(EventPtr event) {
242 scoped_ptr<ui::Event> ui_event = event.To<scoped_ptr<ui::Event> >();
243 if (ui_event)
244 window_tree_host_->SendEventToProcessor(ui_event.get());
245 }
246
247 ////////////////////////////////////////////////////////////////////////////////
248 // WindowManagerApp, ViewObserver implementation:
249
OnTreeChanged(const ViewObserver::TreeChangeParams & params)250 void WindowManagerApp::OnTreeChanged(
251 const ViewObserver::TreeChangeParams& params) {
252 if (params.receiver != root_)
253 return;
254 DCHECK(params.old_parent || params.new_parent);
255 if (!params.target)
256 return;
257
258 if (params.new_parent) {
259 if (view_id_to_window_map_.find(params.target->id()) ==
260 view_id_to_window_map_.end()) {
261 ViewIdToWindowMap::const_iterator it =
262 view_id_to_window_map_.find(params.new_parent->id());
263 DCHECK(it != view_id_to_window_map_.end());
264 RegisterSubtree(params.target, it->second);
265 }
266 } else if (params.old_parent) {
267 UnregisterSubtree(params.target);
268 }
269 }
270
OnViewDestroyed(View * view)271 void WindowManagerApp::OnViewDestroyed(View* view) {
272 if (view != root_)
273 return;
274 aura::Window* window = GetWindowForViewId(view->id());
275 window->RemovePreTargetHandler(this);
276 root_ = NULL;
277 STLDeleteValues(&view_id_to_window_map_);
278 if (focus_client_.get())
279 focus_client_->RemoveObserver(this);
280 if (activation_client_)
281 activation_client_->RemoveObserver(this);
282 window_tree_host_.reset();
283 }
284
OnViewBoundsChanged(View * view,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)285 void WindowManagerApp::OnViewBoundsChanged(View* view,
286 const gfx::Rect& old_bounds,
287 const gfx::Rect& new_bounds) {
288 aura::Window* window = GetWindowForViewId(view->id());
289 window->SetBounds(new_bounds);
290 }
291
292 ////////////////////////////////////////////////////////////////////////////////
293 // WindowManagerApp, WindowTreeHostMojoDelegate implementation:
294
CompositorContentsChanged(const SkBitmap & bitmap)295 void WindowManagerApp::CompositorContentsChanged(const SkBitmap& bitmap) {
296 // We draw nothing.
297 NOTREACHED();
298 }
299
300 ////////////////////////////////////////////////////////////////////////////////
301 // WindowManagerApp, ui::EventHandler implementation:
302
OnEvent(ui::Event * event)303 void WindowManagerApp::OnEvent(ui::Event* event) {
304 aura::Window* window = static_cast<aura::Window*>(event->target());
305 view_manager_->DispatchEvent(GetViewForWindow(window), Event::From(*event));
306 }
307
308 ////////////////////////////////////////////////////////////////////////////////
309 // WindowManagerApp, aura::client::FocusChangeObserver implementation:
310
OnWindowFocused(aura::Window * gained_focus,aura::Window * lost_focus)311 void WindowManagerApp::OnWindowFocused(aura::Window* gained_focus,
312 aura::Window* lost_focus) {
313 for (Connections::const_iterator it = connections_.begin();
314 it != connections_.end(); ++it) {
315 (*it)->NotifyViewFocused(GetIdForWindow(gained_focus),
316 GetIdForWindow(lost_focus));
317 }
318 }
319
320 ////////////////////////////////////////////////////////////////////////////////
321 // WindowManagerApp, aura::client::ActivationChangeObserver implementation:
322
OnWindowActivated(aura::Window * gained_active,aura::Window * lost_active)323 void WindowManagerApp::OnWindowActivated(aura::Window* gained_active,
324 aura::Window* lost_active) {
325 for (Connections::const_iterator it = connections_.begin();
326 it != connections_.end(); ++it) {
327 (*it)->NotifyWindowActivated(GetIdForWindow(gained_active),
328 GetIdForWindow(lost_active));
329 }
330 }
331
332 ////////////////////////////////////////////////////////////////////////////////
333 // WindowManagerApp, private:
334
GetWindowForViewId(Id view) const335 aura::Window* WindowManagerApp::GetWindowForViewId(Id view) const {
336 ViewIdToWindowMap::const_iterator it = view_id_to_window_map_.find(view);
337 return it != view_id_to_window_map_.end() ? it->second : NULL;
338 }
339
RegisterSubtree(View * view,aura::Window * parent)340 void WindowManagerApp::RegisterSubtree(View* view, aura::Window* parent) {
341 view->AddObserver(this);
342 DCHECK(view_id_to_window_map_.find(view->id()) ==
343 view_id_to_window_map_.end());
344 aura::Window* window = new aura::Window(dummy_delegate_.get());
345 window->set_id(view->id());
346 window->SetProperty(kViewKey, view);
347 // All events pass through the root during dispatch, so we only need a handler
348 // installed there.
349 if (view == root_)
350 window->AddPreTargetHandler(this);
351 parent->AddChild(window);
352 window->SetBounds(view->bounds());
353 window->Show();
354 view_id_to_window_map_[view->id()] = window;
355 View::Children::const_iterator it = view->children().begin();
356 for (; it != view->children().end(); ++it)
357 RegisterSubtree(*it, window);
358 }
359
UnregisterSubtree(View * view)360 void WindowManagerApp::UnregisterSubtree(View* view) {
361 view->RemoveObserver(this);
362 ViewIdToWindowMap::iterator it = view_id_to_window_map_.find(view->id());
363 DCHECK(it != view_id_to_window_map_.end());
364 scoped_ptr<aura::Window> window(it->second);
365 view_id_to_window_map_.erase(it);
366 View::Children::const_iterator child = view->children().begin();
367 for (; child != view->children().end(); ++child)
368 UnregisterSubtree(*child);
369 }
370
371 } // namespace mojo
372