Home | History | Annotate | Download | only in native
      1 // Copyright (c) 2012 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/controls/native/native_view_host_aura.h"
      6 
      7 #include "base/logging.h"
      8 #include "ui/aura/client/aura_constants.h"
      9 #include "ui/aura/client/focus_client.h"
     10 #include "ui/aura/window.h"
     11 #include "ui/aura/window_delegate.h"
     12 #include "ui/base/cursor/cursor.h"
     13 #include "ui/base/hit_test.h"
     14 #include "ui/views/controls/native/native_view_host.h"
     15 #include "ui/views/view_constants_aura.h"
     16 #include "ui/views/widget/widget.h"
     17 
     18 namespace views {
     19 
     20 class NativeViewHostAura::ClippingWindowDelegate : public aura::WindowDelegate {
     21  public:
     22   ClippingWindowDelegate() : native_view_(NULL) {}
     23   virtual ~ClippingWindowDelegate() {}
     24 
     25   void set_native_view(aura::Window* native_view) {
     26     native_view_ = native_view;
     27   }
     28 
     29   virtual gfx::Size GetMinimumSize() const OVERRIDE { return gfx::Size(); }
     30   virtual gfx::Size GetMaximumSize() const OVERRIDE { return gfx::Size(); }
     31   virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
     32                                const gfx::Rect& new_bounds) OVERRIDE {}
     33   virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
     34     return gfx::kNullCursor;
     35   }
     36   virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
     37     return HTCLIENT;
     38   }
     39   virtual bool ShouldDescendIntoChildForEventHandling(
     40       aura::Window* child,
     41       const gfx::Point& location) OVERRIDE { return true; }
     42   virtual bool CanFocus() OVERRIDE {
     43     // Ask the hosted native view's delegate because directly calling
     44     // aura::Window::CanFocus() will call back into this when checking whether
     45     // parents can focus.
     46     return native_view_ && native_view_->delegate()
     47         ? native_view_->delegate()->CanFocus()
     48         : true;
     49   }
     50   virtual void OnCaptureLost() OVERRIDE {}
     51   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {}
     52   virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
     53   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {}
     54   virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {}
     55   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
     56   virtual bool HasHitTestMask() const OVERRIDE { return false; }
     57   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
     58 
     59  private:
     60   aura::Window* native_view_;
     61 };
     62 
     63 NativeViewHostAura::NativeViewHostAura(NativeViewHost* host)
     64     : host_(host),
     65       clipping_window_delegate_(new ClippingWindowDelegate()),
     66       clipping_window_(clipping_window_delegate_.get()) {
     67   // Set the type so descendant views (including popups) get positioned
     68   // appropriately.
     69   clipping_window_.SetType(ui::wm::WINDOW_TYPE_CONTROL);
     70   clipping_window_.Init(aura::WINDOW_LAYER_NOT_DRAWN);
     71   clipping_window_.set_owned_by_parent(false);
     72   clipping_window_.SetName("NativeViewHostAuraClip");
     73   clipping_window_.layer()->SetMasksToBounds(true);
     74   clipping_window_.SetProperty(views::kHostViewKey, static_cast<View*>(host_));
     75 }
     76 
     77 NativeViewHostAura::~NativeViewHostAura() {
     78   if (host_->native_view()) {
     79     host_->native_view()->RemoveObserver(this);
     80     host_->native_view()->ClearProperty(views::kHostViewKey);
     81     host_->native_view()->ClearProperty(aura::client::kHostWindowKey);
     82     clipping_window_.ClearProperty(views::kHostViewKey);
     83     if (host_->native_view()->parent() == &clipping_window_)
     84       clipping_window_.RemoveChild(host_->native_view());
     85   }
     86 }
     87 
     88 ////////////////////////////////////////////////////////////////////////////////
     89 // NativeViewHostAura, NativeViewHostWrapper implementation:
     90 void NativeViewHostAura::AttachNativeView() {
     91   clipping_window_delegate_->set_native_view(host_->native_view());
     92   host_->native_view()->AddObserver(this);
     93   host_->native_view()->SetProperty(views::kHostViewKey,
     94       static_cast<View*>(host_));
     95   AddClippingWindow();
     96 }
     97 
     98 void NativeViewHostAura::NativeViewDetaching(bool destroyed) {
     99   clipping_window_delegate_->set_native_view(NULL);
    100   RemoveClippingWindow();
    101   if (!destroyed) {
    102     host_->native_view()->RemoveObserver(this);
    103     host_->native_view()->ClearProperty(views::kHostViewKey);
    104     host_->native_view()->ClearProperty(aura::client::kHostWindowKey);
    105     host_->native_view()->Hide();
    106     if (host_->native_view()->parent())
    107       Widget::ReparentNativeView(host_->native_view(), NULL);
    108   }
    109 }
    110 
    111 void NativeViewHostAura::AddedToWidget() {
    112   if (!host_->native_view())
    113     return;
    114 
    115   AddClippingWindow();
    116   if (host_->IsDrawn())
    117     host_->native_view()->Show();
    118   else
    119     host_->native_view()->Hide();
    120   host_->Layout();
    121 }
    122 
    123 void NativeViewHostAura::RemovedFromWidget() {
    124   if (host_->native_view()) {
    125     host_->native_view()->Hide();
    126     host_->native_view()->ClearProperty(aura::client::kHostWindowKey);
    127     if (host_->native_view()->parent())
    128       host_->native_view()->parent()->RemoveChild(host_->native_view());
    129     RemoveClippingWindow();
    130   }
    131 }
    132 
    133 void NativeViewHostAura::InstallClip(int x, int y, int w, int h) {
    134   clip_rect_.reset(
    135       new gfx::Rect(host_->ConvertRectToWidget(gfx::Rect(x, y, w, h))));
    136 }
    137 
    138 bool NativeViewHostAura::HasInstalledClip() {
    139   return clip_rect_;
    140 }
    141 
    142 void NativeViewHostAura::UninstallClip() {
    143   clip_rect_.reset();
    144 }
    145 
    146 void NativeViewHostAura::ShowWidget(int x, int y, int w, int h) {
    147   int width = w;
    148   int height = h;
    149   if (host_->fast_resize()) {
    150     gfx::Point origin(x, y);
    151     views::View::ConvertPointFromWidget(host_, &origin);
    152     InstallClip(origin.x(), origin.y(), w, h);
    153     width = host_->native_view()->bounds().width();
    154     height = host_->native_view()->bounds().height();
    155   }
    156   clipping_window_.SetBounds(clip_rect_ ? *clip_rect_
    157                                         : gfx::Rect(x, y, w, h));
    158 
    159   gfx::Point clip_offset = clipping_window_.bounds().origin();
    160   host_->native_view()->SetBounds(
    161       gfx::Rect(x - clip_offset.x(), y - clip_offset.y(), width, height));
    162   host_->native_view()->Show();
    163   clipping_window_.Show();
    164 }
    165 
    166 void NativeViewHostAura::HideWidget() {
    167   host_->native_view()->Hide();
    168   clipping_window_.Hide();
    169 }
    170 
    171 void NativeViewHostAura::SetFocus() {
    172   aura::Window* window = host_->native_view();
    173   aura::client::FocusClient* client = aura::client::GetFocusClient(window);
    174   if (client)
    175     client->FocusWindow(window);
    176 }
    177 
    178 gfx::NativeViewAccessible NativeViewHostAura::GetNativeViewAccessible() {
    179   return NULL;
    180 }
    181 
    182 gfx::NativeCursor NativeViewHostAura::GetCursor(int x, int y) {
    183   if (host_->native_view())
    184     return host_->native_view()->GetCursor(gfx::Point(x, y));
    185   return gfx::kNullCursor;
    186 }
    187 
    188 void NativeViewHostAura::OnWindowDestroying(aura::Window* window) {
    189   DCHECK(window == host_->native_view());
    190   clipping_window_delegate_->set_native_view(NULL);
    191 }
    192 
    193 void NativeViewHostAura::OnWindowDestroyed(aura::Window* window) {
    194   DCHECK(window == host_->native_view());
    195   host_->NativeViewDestroyed();
    196 }
    197 
    198 // static
    199 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
    200     NativeViewHost* host) {
    201   return new NativeViewHostAura(host);
    202 }
    203 
    204 void NativeViewHostAura::AddClippingWindow() {
    205   RemoveClippingWindow();
    206 
    207   host_->native_view()->SetProperty(aura::client::kHostWindowKey,
    208                                     host_->GetWidget()->GetNativeView());
    209   Widget::ReparentNativeView(host_->native_view(),
    210                              &clipping_window_);
    211   if (host_->GetWidget()->GetNativeView()) {
    212     Widget::ReparentNativeView(&clipping_window_,
    213                                host_->GetWidget()->GetNativeView());
    214   }
    215 }
    216 
    217 void NativeViewHostAura::RemoveClippingWindow() {
    218   clipping_window_.Hide();
    219   if (host_->native_view())
    220     host_->native_view()->ClearProperty(aura::client::kHostWindowKey);
    221 
    222   if (host_->native_view()->parent() == &clipping_window_) {
    223     if (host_->GetWidget() && host_->GetWidget()->GetNativeView()) {
    224       Widget::ReparentNativeView(host_->native_view(),
    225                                  host_->GetWidget()->GetNativeView());
    226     } else {
    227       clipping_window_.RemoveChild(host_->native_view());
    228     }
    229     host_->native_view()->SetBounds(clipping_window_.bounds());
    230   }
    231   if (clipping_window_.parent())
    232     clipping_window_.parent()->RemoveChild(&clipping_window_);
    233 }
    234 
    235 }  // namespace views
    236