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_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