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