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: 36 DummyDelegate() {} 37 virtual ~DummyDelegate() {} 38 39 private: 40 // WindowDelegate overrides: 41 virtual gfx::Size GetMinimumSize() const OVERRIDE { return gfx::Size(); } 42 virtual gfx::Size GetMaximumSize() const OVERRIDE { return gfx::Size(); } 43 virtual void OnBoundsChanged(const gfx::Rect& old_bounds, 44 const gfx::Rect& new_bounds) OVERRIDE {} 45 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE { 46 return gfx::kNullCursor; 47 } 48 virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE { 49 return HTCAPTION; 50 } 51 virtual bool ShouldDescendIntoChildForEventHandling( 52 aura::Window* child, 53 const gfx::Point& location) OVERRIDE { return true; } 54 virtual bool CanFocus() OVERRIDE { return true; } 55 virtual void OnCaptureLost() OVERRIDE {} 56 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {} 57 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {} 58 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {} 59 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {} 60 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {} 61 virtual bool HasHitTestMask() const OVERRIDE { return false; } 62 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 71 Id GetIdForWindow(aura::Window* window) { 72 return window ? WindowManagerApp::GetViewForWindow(window)->id() : 0; 73 } 74 75 class WMFocusRules : public wm::FocusRules { 76 public: 77 WMFocusRules() {} 78 virtual ~WMFocusRules() {} 79 80 private: 81 // Overridden from wm::FocusRules: 82 virtual bool IsToplevelWindow(aura::Window* window) const MOJO_OVERRIDE { 83 return true; 84 } 85 virtual bool CanActivateWindow(aura::Window* window) const MOJO_OVERRIDE { 86 return true; 87 } 88 virtual bool CanFocusWindow(aura::Window* window) const MOJO_OVERRIDE { 89 return true; 90 } 91 virtual aura::Window* GetToplevelWindow( 92 aura::Window* window) const MOJO_OVERRIDE { 93 return window; 94 } 95 virtual aura::Window* GetActivatableWindow( 96 aura::Window* window) const MOJO_OVERRIDE { 97 return window; 98 } 99 virtual aura::Window* GetFocusableWindow( 100 aura::Window* window) const MOJO_OVERRIDE { 101 return window; 102 } 103 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 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 127 WindowManagerApp::~WindowManagerApp() {} 128 129 // static 130 View* WindowManagerApp::GetViewForWindow(aura::Window* window) { 131 return window->GetProperty(kViewKey); 132 } 133 134 void WindowManagerApp::AddConnection(WindowManagerServiceImpl* connection) { 135 DCHECK(connections_.find(connection) == connections_.end()); 136 connections_.insert(connection); 137 } 138 139 void WindowManagerApp::RemoveConnection(WindowManagerServiceImpl* connection) { 140 DCHECK(connections_.find(connection) != connections_.end()); 141 connections_.erase(connection); 142 } 143 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 150 void WindowManagerApp::FocusWindow(Id view) { 151 aura::Window* window = GetWindowForViewId(view); 152 DCHECK(window); 153 focus_client_->FocusWindow(window); 154 } 155 156 void WindowManagerApp::ActivateWindow(Id view) { 157 aura::Window* window = GetWindowForViewId(view); 158 DCHECK(window); 159 activation_client_->ActivateWindow(window); 160 } 161 162 bool WindowManagerApp::IsReady() const { 163 return view_manager_ && root_; 164 } 165 166 //////////////////////////////////////////////////////////////////////////////// 167 // WindowManagerApp, ApplicationDelegate implementation: 168 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 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 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 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 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 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 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 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 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 295 void WindowManagerApp::CompositorContentsChanged(const SkBitmap& bitmap) { 296 // We draw nothing. 297 NOTREACHED(); 298 } 299 300 //////////////////////////////////////////////////////////////////////////////// 301 // WindowManagerApp, ui::EventHandler implementation: 302 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 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 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 335 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 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 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