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_win.h" 6 7 #include <oleacc.h> 8 9 #include "base/logging.h" 10 #include "ui/base/win/dpi.h" 11 #include "ui/base/win/hidden_window.h" 12 #include "ui/base/win/window_impl.h" 13 #include "ui/gfx/canvas.h" 14 #include "ui/views/controls/native/native_view_host.h" 15 #include "ui/views/focus/focus_manager.h" 16 #include "ui/views/widget/native_widget.h" 17 #include "ui/views/widget/root_view.h" 18 #include "ui/views/widget/widget.h" 19 20 namespace views { 21 22 //////////////////////////////////////////////////////////////////////////////// 23 // NativeViewHostWin, public: 24 25 NativeViewHostWin::NativeViewHostWin(NativeViewHost* host) 26 : host_(host), 27 installed_clip_(false) { 28 } 29 30 NativeViewHostWin::~NativeViewHostWin() { 31 } 32 33 //////////////////////////////////////////////////////////////////////////////// 34 // NativeViewHostWin, NativeViewHostWrapper implementation: 35 void NativeViewHostWin::NativeViewWillAttach() { 36 // First hide the new window. We don't want anything to draw (like sub-hwnd 37 // borders), when NativeViewHost changes the parent. 38 ShowWindow(host_->native_view(), SW_HIDE); 39 } 40 41 void NativeViewHostWin::NativeViewDetaching(bool destroyed) { 42 if (!destroyed) { 43 if (installed_clip_) 44 UninstallClip(); 45 Widget::ReparentNativeView(host_->native_view(), ui::GetHiddenWindow()); 46 } 47 installed_clip_ = false; 48 } 49 50 void NativeViewHostWin::AddedToWidget() { 51 if (!IsWindow(host_->native_view())) 52 return; 53 HWND parent_hwnd = GetParent(host_->native_view()); 54 HWND widget_hwnd = host_->GetWidget()->GetNativeView(); 55 if (parent_hwnd != widget_hwnd) 56 SetParent(host_->native_view(), widget_hwnd); 57 if (host_->IsDrawn()) 58 ShowWindow(host_->native_view(), SW_SHOW); 59 else 60 ShowWindow(host_->native_view(), SW_HIDE); 61 host_->Layout(); 62 } 63 64 void NativeViewHostWin::RemovedFromWidget() { 65 if (!IsWindow(host_->native_view())) 66 return; 67 ShowWindow(host_->native_view(), SW_HIDE); 68 SetParent(host_->native_view(), NULL); 69 } 70 71 void NativeViewHostWin::InstallClip(int x, int y, int w, int h) { 72 HRGN clip_region = CreateRectRgn(x, y, x + w, y + h); 73 // NOTE: SetWindowRgn owns the region (as well as the deleting the 74 // current region), as such we don't delete the old region. 75 SetWindowRgn(host_->native_view(), clip_region, TRUE); 76 installed_clip_ = true; 77 } 78 79 bool NativeViewHostWin::HasInstalledClip() { 80 return installed_clip_; 81 } 82 83 void NativeViewHostWin::UninstallClip() { 84 SetWindowRgn(host_->native_view(), 0, TRUE); 85 installed_clip_ = false; 86 } 87 88 void NativeViewHostWin::ShowWidget(int x, int y, int w, int h) { 89 UINT swp_flags = SWP_DEFERERASE | 90 SWP_NOACTIVATE | 91 SWP_NOCOPYBITS | 92 SWP_NOOWNERZORDER | 93 SWP_NOZORDER; 94 gfx::Rect bounds = ui::win::DIPToScreenRect(gfx::Rect(x,y,w,h)); 95 96 // Only send the SHOWWINDOW flag if we're invisible, to avoid flashing. 97 if (!IsWindowVisible(host_->native_view())) 98 swp_flags = (swp_flags | SWP_SHOWWINDOW) & ~SWP_NOREDRAW; 99 100 if (host_->fast_resize()) { 101 // In a fast resize, we move the window and clip it with SetWindowRgn. 102 RECT win_rect; 103 GetWindowRect(host_->native_view(), &win_rect); 104 gfx::Rect rect(win_rect); 105 SetWindowPos(host_->native_view(), 0, bounds.x(), bounds.y(), 106 rect.width(), rect.height(), 107 swp_flags); 108 109 InstallClip(0, 0, bounds.width(), bounds.height()); 110 } else { 111 SetWindowPos(host_->native_view(), 0, bounds.x(), bounds.y(), 112 bounds.width(), bounds.height(), swp_flags); 113 } 114 } 115 116 void NativeViewHostWin::HideWidget() { 117 if (!IsWindowVisible(host_->native_view())) 118 return; // Currently not visible, nothing to do. 119 120 // The window is currently visible, but its clipped by another view. Hide 121 // it. 122 SetWindowPos(host_->native_view(), 0, 0, 0, 0, 0, 123 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | 124 SWP_NOREDRAW | SWP_NOOWNERZORDER); 125 } 126 127 void NativeViewHostWin::SetFocus() { 128 ::SetFocus(host_->native_view()); 129 } 130 131 gfx::NativeViewAccessible NativeViewHostWin::GetNativeViewAccessible() { 132 HWND hwnd = host_->native_view(); 133 if (!IsWindow(hwnd)) 134 return NULL; 135 136 IAccessible* accessible = NULL; 137 HRESULT success = ::AccessibleObjectFromWindow( 138 hwnd, OBJID_CLIENT, IID_IAccessible, 139 reinterpret_cast<void**>(&accessible)); 140 141 if (success == S_OK) { 142 return accessible; 143 } else { 144 return NULL; 145 } 146 } 147 148 //////////////////////////////////////////////////////////////////////////////// 149 // NativeViewHostWrapper, public: 150 151 // static 152 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper( 153 NativeViewHost* host) { 154 return new NativeViewHostWin(host); 155 } 156 157 } // namespace views 158