Home | History | Annotate | Download | only in window_manager
      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