Home | History | Annotate | Download | only in desktop_aura
      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/widget/desktop_aura/desktop_window_tree_host_win.h"
      6 
      7 #include "base/win/metro.h"
      8 #include "third_party/skia/include/core/SkPath.h"
      9 #include "third_party/skia/include/core/SkRegion.h"
     10 #include "ui/aura/client/aura_constants.h"
     11 #include "ui/aura/client/cursor_client.h"
     12 #include "ui/aura/client/focus_client.h"
     13 #include "ui/aura/window_event_dispatcher.h"
     14 #include "ui/aura/window_property.h"
     15 #include "ui/base/cursor/cursor_loader_win.h"
     16 #include "ui/base/ime/input_method.h"
     17 #include "ui/base/win/shell.h"
     18 #include "ui/compositor/compositor_constants.h"
     19 #include "ui/gfx/insets.h"
     20 #include "ui/gfx/native_widget_types.h"
     21 #include "ui/gfx/path.h"
     22 #include "ui/gfx/path_win.h"
     23 #include "ui/gfx/vector2d.h"
     24 #include "ui/gfx/win/dpi.h"
     25 #include "ui/native_theme/native_theme_aura.h"
     26 #include "ui/native_theme/native_theme_win.h"
     27 #include "ui/views/corewm/tooltip_win.h"
     28 #include "ui/views/ime/input_method_bridge.h"
     29 #include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h"
     30 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h"
     31 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
     32 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
     33 #include "ui/views/widget/root_view.h"
     34 #include "ui/views/widget/widget_delegate.h"
     35 #include "ui/views/widget/widget_hwnd_utils.h"
     36 #include "ui/views/win/fullscreen_handler.h"
     37 #include "ui/views/win/hwnd_message_handler.h"
     38 #include "ui/wm/core/compound_event_filter.h"
     39 #include "ui/wm/core/input_method_event_filter.h"
     40 #include "ui/wm/core/window_animations.h"
     41 #include "ui/wm/public/scoped_tooltip_disabler.h"
     42 
     43 namespace views {
     44 
     45 namespace {
     46 
     47 gfx::Size GetExpandedWindowSize(DWORD window_style, gfx::Size size) {
     48   if (!(window_style & WS_EX_COMPOSITED) || !ui::win::IsAeroGlassEnabled())
     49     return size;
     50 
     51   // Some AMD drivers can't display windows that are less than 64x64 pixels,
     52   // so expand them to be at least that size. http://crbug.com/286609
     53   gfx::Size expanded(std::max(size.width(), 64), std::max(size.height(), 64));
     54   return expanded;
     55 }
     56 
     57 void InsetBottomRight(gfx::Rect* rect, gfx::Vector2d vector) {
     58   rect->Inset(0, 0, vector.x(), vector.y());
     59 }
     60 
     61 }  // namespace
     62 
     63 DEFINE_WINDOW_PROPERTY_KEY(aura::Window*, kContentWindowForRootWindow, NULL);
     64 
     65 // Identifies the DesktopWindowTreeHostWin associated with the
     66 // WindowEventDispatcher.
     67 DEFINE_WINDOW_PROPERTY_KEY(DesktopWindowTreeHostWin*, kDesktopWindowTreeHostKey,
     68                            NULL);
     69 
     70 ////////////////////////////////////////////////////////////////////////////////
     71 // DesktopWindowTreeHostWin, public:
     72 
     73 bool DesktopWindowTreeHostWin::is_cursor_visible_ = true;
     74 
     75 DesktopWindowTreeHostWin::DesktopWindowTreeHostWin(
     76     internal::NativeWidgetDelegate* native_widget_delegate,
     77     DesktopNativeWidgetAura* desktop_native_widget_aura)
     78     : message_handler_(new HWNDMessageHandler(this)),
     79       native_widget_delegate_(native_widget_delegate),
     80       desktop_native_widget_aura_(desktop_native_widget_aura),
     81       content_window_(NULL),
     82       drag_drop_client_(NULL),
     83       should_animate_window_close_(false),
     84       pending_close_(false),
     85       has_non_client_view_(false),
     86       tooltip_(NULL),
     87       need_synchronous_paint_(false),
     88       in_sizing_loop_(false) {
     89 }
     90 
     91 DesktopWindowTreeHostWin::~DesktopWindowTreeHostWin() {
     92   // WARNING: |content_window_| has been destroyed by the time we get here.
     93   desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
     94   DestroyDispatcher();
     95 }
     96 
     97 // static
     98 aura::Window* DesktopWindowTreeHostWin::GetContentWindowForHWND(HWND hwnd) {
     99   aura::WindowTreeHost* host =
    100       aura::WindowTreeHost::GetForAcceleratedWidget(hwnd);
    101   return host ? host->window()->GetProperty(kContentWindowForRootWindow) : NULL;
    102 }
    103 
    104 // static
    105 ui::NativeTheme* DesktopWindowTreeHost::GetNativeTheme(aura::Window* window) {
    106   // Use NativeThemeWin for windows shown on the desktop, those not on the
    107   // desktop come from Ash and get NativeThemeAura.
    108   aura::WindowTreeHost* host = window ? window->GetHost() : NULL;
    109   if (host) {
    110     HWND host_hwnd = host->GetAcceleratedWidget();
    111     if (host_hwnd &&
    112         DesktopWindowTreeHostWin::GetContentWindowForHWND(host_hwnd)) {
    113       return ui::NativeThemeWin::instance();
    114     }
    115   }
    116   return ui::NativeThemeAura::instance();
    117 }
    118 
    119 ////////////////////////////////////////////////////////////////////////////////
    120 // DesktopWindowTreeHostWin, DesktopWindowTreeHost implementation:
    121 
    122 void DesktopWindowTreeHostWin::Init(aura::Window* content_window,
    123                                     const Widget::InitParams& params) {
    124   // TODO(beng): SetInitParams().
    125   content_window_ = content_window;
    126 
    127   aura::client::SetAnimationHost(content_window_, this);
    128 
    129   ConfigureWindowStyles(message_handler_.get(), params,
    130                         GetWidget()->widget_delegate(),
    131                         native_widget_delegate_);
    132 
    133   HWND parent_hwnd = NULL;
    134   if (params.parent && params.parent->GetHost())
    135     parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget();
    136 
    137   message_handler_->set_remove_standard_frame(params.remove_standard_frame);
    138 
    139   has_non_client_view_ = Widget::RequiresNonClientView(params.type);
    140 
    141   gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds);
    142   message_handler_->Init(parent_hwnd, pixel_bounds);
    143   if (params.type == Widget::InitParams::TYPE_MENU) {
    144     ::SetProp(GetAcceleratedWidget(),
    145               kForceSoftwareCompositor,
    146               reinterpret_cast<HANDLE>(true));
    147   }
    148   CreateCompositor(GetAcceleratedWidget());
    149 }
    150 
    151 void DesktopWindowTreeHostWin::OnNativeWidgetCreated(
    152     const Widget::InitParams& params) {
    153   // The cursor is not necessarily visible when the root window is created.
    154   aura::client::CursorClient* cursor_client =
    155       aura::client::GetCursorClient(window());
    156   if (cursor_client)
    157     is_cursor_visible_ = cursor_client->IsCursorVisible();
    158 
    159   window()->SetProperty(kContentWindowForRootWindow, content_window_);
    160   window()->SetProperty(kDesktopWindowTreeHostKey, this);
    161 
    162   should_animate_window_close_ =
    163       content_window_->type() != ui::wm::WINDOW_TYPE_NORMAL &&
    164       !wm::WindowAnimationsDisabled(content_window_);
    165 
    166 // TODO this is not invoked *after* Init(), but should be ok.
    167   SetWindowTransparency();
    168 }
    169 
    170 scoped_ptr<corewm::Tooltip> DesktopWindowTreeHostWin::CreateTooltip() {
    171   DCHECK(!tooltip_);
    172   tooltip_ = new corewm::TooltipWin(GetAcceleratedWidget());
    173   return scoped_ptr<corewm::Tooltip>(tooltip_);
    174 }
    175 
    176 scoped_ptr<aura::client::DragDropClient>
    177 DesktopWindowTreeHostWin::CreateDragDropClient(
    178     DesktopNativeCursorManager* cursor_manager) {
    179   drag_drop_client_ = new DesktopDragDropClientWin(window(), GetHWND());
    180   return scoped_ptr<aura::client::DragDropClient>(drag_drop_client_).Pass();
    181 }
    182 
    183 void DesktopWindowTreeHostWin::Close() {
    184   // TODO(beng): Move this entire branch to DNWA so it can be shared with X11.
    185   if (should_animate_window_close_) {
    186     pending_close_ = true;
    187     const bool is_animating =
    188         content_window_->layer()->GetAnimator()->IsAnimatingProperty(
    189             ui::LayerAnimationElement::VISIBILITY);
    190     // Animation may not start for a number of reasons.
    191     if (!is_animating)
    192       message_handler_->Close();
    193     // else case, OnWindowHidingAnimationCompleted does the actual Close.
    194   } else {
    195     message_handler_->Close();
    196   }
    197 }
    198 
    199 void DesktopWindowTreeHostWin::CloseNow() {
    200   message_handler_->CloseNow();
    201 }
    202 
    203 aura::WindowTreeHost* DesktopWindowTreeHostWin::AsWindowTreeHost() {
    204   return this;
    205 }
    206 
    207 void DesktopWindowTreeHostWin::ShowWindowWithState(
    208     ui::WindowShowState show_state) {
    209   message_handler_->ShowWindowWithState(show_state);
    210 }
    211 
    212 void DesktopWindowTreeHostWin::ShowMaximizedWithBounds(
    213     const gfx::Rect& restored_bounds) {
    214   gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(restored_bounds);
    215   message_handler_->ShowMaximizedWithBounds(pixel_bounds);
    216 }
    217 
    218 bool DesktopWindowTreeHostWin::IsVisible() const {
    219   return message_handler_->IsVisible();
    220 }
    221 
    222 void DesktopWindowTreeHostWin::SetSize(const gfx::Size& size) {
    223   gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size);
    224   gfx::Size expanded = GetExpandedWindowSize(
    225       message_handler_->window_ex_style(), size_in_pixels);
    226   window_enlargement_ =
    227       gfx::Vector2d(expanded.width() - size_in_pixels.width(),
    228                     expanded.height() - size_in_pixels.height());
    229   message_handler_->SetSize(expanded);
    230 }
    231 
    232 void DesktopWindowTreeHostWin::StackAtTop() {
    233   message_handler_->StackAtTop();
    234 }
    235 
    236 void DesktopWindowTreeHostWin::CenterWindow(const gfx::Size& size) {
    237   gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size);
    238   gfx::Size expanded_size;
    239   expanded_size = GetExpandedWindowSize(message_handler_->window_ex_style(),
    240                                         size_in_pixels);
    241   window_enlargement_ =
    242       gfx::Vector2d(expanded_size.width() - size_in_pixels.width(),
    243                     expanded_size.height() - size_in_pixels.height());
    244   message_handler_->CenterWindow(expanded_size);
    245 }
    246 
    247 void DesktopWindowTreeHostWin::GetWindowPlacement(
    248     gfx::Rect* bounds,
    249     ui::WindowShowState* show_state) const {
    250   message_handler_->GetWindowPlacement(bounds, show_state);
    251   InsetBottomRight(bounds, window_enlargement_);
    252   *bounds = gfx::win::ScreenToDIPRect(*bounds);
    253 }
    254 
    255 gfx::Rect DesktopWindowTreeHostWin::GetWindowBoundsInScreen() const {
    256   gfx::Rect pixel_bounds = message_handler_->GetWindowBoundsInScreen();
    257   InsetBottomRight(&pixel_bounds, window_enlargement_);
    258   return gfx::win::ScreenToDIPRect(pixel_bounds);
    259 }
    260 
    261 gfx::Rect DesktopWindowTreeHostWin::GetClientAreaBoundsInScreen() const {
    262   gfx::Rect pixel_bounds = message_handler_->GetClientAreaBoundsInScreen();
    263   InsetBottomRight(&pixel_bounds, window_enlargement_);
    264   return gfx::win::ScreenToDIPRect(pixel_bounds);
    265 }
    266 
    267 gfx::Rect DesktopWindowTreeHostWin::GetRestoredBounds() const {
    268   gfx::Rect pixel_bounds = message_handler_->GetRestoredBounds();
    269   InsetBottomRight(&pixel_bounds, window_enlargement_);
    270   return gfx::win::ScreenToDIPRect(pixel_bounds);
    271 }
    272 
    273 gfx::Rect DesktopWindowTreeHostWin::GetWorkAreaBoundsInScreen() const {
    274   MONITORINFO monitor_info;
    275   monitor_info.cbSize = sizeof(monitor_info);
    276   GetMonitorInfo(MonitorFromWindow(message_handler_->hwnd(),
    277                                    MONITOR_DEFAULTTONEAREST),
    278                  &monitor_info);
    279   gfx::Rect pixel_bounds = gfx::Rect(monitor_info.rcWork);
    280   return gfx::win::ScreenToDIPRect(pixel_bounds);
    281 }
    282 
    283 void DesktopWindowTreeHostWin::SetShape(gfx::NativeRegion native_region) {
    284   if (native_region) {
    285     // TODO(wez): This would be a lot simpler if we were passed an SkPath.
    286     // See crbug.com/410593.
    287     gfx::NativeRegion shape = native_region;
    288     SkRegion device_region;
    289     if (gfx::IsInHighDPIMode()) {
    290       shape = &device_region;
    291       const float& scale = gfx::GetDPIScale();
    292       std::vector<SkIRect> rects;
    293       for (SkRegion::Iterator it(*native_region); !it.done(); it.next()) {
    294         const SkIRect& rect = it.rect();
    295         SkRect scaled_rect =
    296             SkRect::MakeLTRB(rect.left() * scale, rect.top() * scale,
    297                              rect.right() * scale, rect.bottom() * scale);
    298         SkIRect rounded_scaled_rect;
    299         scaled_rect.roundOut(&rounded_scaled_rect);
    300         rects.push_back(rounded_scaled_rect);
    301       }
    302       if (!rects.empty())
    303         device_region.setRects(&rects[0], rects.size());
    304     }
    305 
    306     message_handler_->SetRegion(gfx::CreateHRGNFromSkRegion(*shape));
    307   } else {
    308     message_handler_->SetRegion(NULL);
    309   }
    310 
    311   delete native_region;
    312 }
    313 
    314 void DesktopWindowTreeHostWin::Activate() {
    315   message_handler_->Activate();
    316 }
    317 
    318 void DesktopWindowTreeHostWin::Deactivate() {
    319   message_handler_->Deactivate();
    320 }
    321 
    322 bool DesktopWindowTreeHostWin::IsActive() const {
    323   return message_handler_->IsActive();
    324 }
    325 
    326 void DesktopWindowTreeHostWin::Maximize() {
    327   message_handler_->Maximize();
    328 }
    329 
    330 void DesktopWindowTreeHostWin::Minimize() {
    331   message_handler_->Minimize();
    332 }
    333 
    334 void DesktopWindowTreeHostWin::Restore() {
    335   message_handler_->Restore();
    336 }
    337 
    338 bool DesktopWindowTreeHostWin::IsMaximized() const {
    339   return message_handler_->IsMaximized();
    340 }
    341 
    342 bool DesktopWindowTreeHostWin::IsMinimized() const {
    343   return message_handler_->IsMinimized();
    344 }
    345 
    346 bool DesktopWindowTreeHostWin::HasCapture() const {
    347   return message_handler_->HasCapture();
    348 }
    349 
    350 void DesktopWindowTreeHostWin::SetAlwaysOnTop(bool always_on_top) {
    351   message_handler_->SetAlwaysOnTop(always_on_top);
    352 }
    353 
    354 bool DesktopWindowTreeHostWin::IsAlwaysOnTop() const {
    355   return message_handler_->IsAlwaysOnTop();
    356 }
    357 
    358 void DesktopWindowTreeHostWin::SetVisibleOnAllWorkspaces(bool always_visible) {
    359   // Windows does not have the concept of workspaces.
    360 }
    361 
    362 bool DesktopWindowTreeHostWin::SetWindowTitle(const base::string16& title) {
    363   return message_handler_->SetTitle(title);
    364 }
    365 
    366 void DesktopWindowTreeHostWin::ClearNativeFocus() {
    367   message_handler_->ClearNativeFocus();
    368 }
    369 
    370 Widget::MoveLoopResult DesktopWindowTreeHostWin::RunMoveLoop(
    371     const gfx::Vector2d& drag_offset,
    372     Widget::MoveLoopSource source,
    373     Widget::MoveLoopEscapeBehavior escape_behavior) {
    374   const bool hide_on_escape =
    375       escape_behavior == Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE;
    376   return message_handler_->RunMoveLoop(drag_offset, hide_on_escape) ?
    377       Widget::MOVE_LOOP_SUCCESSFUL : Widget::MOVE_LOOP_CANCELED;
    378 }
    379 
    380 void DesktopWindowTreeHostWin::EndMoveLoop() {
    381   message_handler_->EndMoveLoop();
    382 }
    383 
    384 void DesktopWindowTreeHostWin::SetVisibilityChangedAnimationsEnabled(
    385     bool value) {
    386   message_handler_->SetVisibilityChangedAnimationsEnabled(value);
    387   content_window_->SetProperty(aura::client::kAnimationsDisabledKey, !value);
    388 }
    389 
    390 bool DesktopWindowTreeHostWin::ShouldUseNativeFrame() const {
    391   return IsTranslucentWindowOpacitySupported();
    392 }
    393 
    394 bool DesktopWindowTreeHostWin::ShouldWindowContentsBeTransparent() const {
    395   // If the window has a native frame, we assume it is an Aero Glass window, and
    396   // is therefore transparent. Note: This is not equivalent to calling
    397   // IsAeroGlassEnabled, because ShouldUseNativeFrame is overridden in a
    398   // subclass.
    399   return ShouldUseNativeFrame();
    400 }
    401 
    402 void DesktopWindowTreeHostWin::FrameTypeChanged() {
    403   message_handler_->FrameTypeChanged();
    404   SetWindowTransparency();
    405 }
    406 
    407 void DesktopWindowTreeHostWin::SetFullscreen(bool fullscreen) {
    408   message_handler_->SetFullscreen(fullscreen);
    409   // TODO(sky): workaround for ScopedFullscreenVisibility showing window
    410   // directly. Instead of this should listen for visibility changes and then
    411   // update window.
    412   if (message_handler_->IsVisible() && !content_window_->TargetVisibility())
    413     content_window_->Show();
    414   SetWindowTransparency();
    415 }
    416 
    417 bool DesktopWindowTreeHostWin::IsFullscreen() const {
    418   return message_handler_->fullscreen_handler()->fullscreen();
    419 }
    420 
    421 void DesktopWindowTreeHostWin::SetOpacity(unsigned char opacity) {
    422   message_handler_->SetOpacity(static_cast<BYTE>(opacity));
    423   content_window_->layer()->SetOpacity(opacity / 255.0);
    424 }
    425 
    426 void DesktopWindowTreeHostWin::SetWindowIcons(
    427     const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) {
    428   message_handler_->SetWindowIcons(window_icon, app_icon);
    429 }
    430 
    431 void DesktopWindowTreeHostWin::InitModalType(ui::ModalType modal_type) {
    432   message_handler_->InitModalType(modal_type);
    433 }
    434 
    435 void DesktopWindowTreeHostWin::FlashFrame(bool flash_frame) {
    436   message_handler_->FlashFrame(flash_frame);
    437 }
    438 
    439 void DesktopWindowTreeHostWin::OnRootViewLayout() {
    440 }
    441 
    442 void DesktopWindowTreeHostWin::OnNativeWidgetFocus() {
    443   // HWNDMessageHandler will perform the proper updating on its own.
    444 }
    445 
    446 void DesktopWindowTreeHostWin::OnNativeWidgetBlur() {
    447 }
    448 
    449 bool DesktopWindowTreeHostWin::IsAnimatingClosed() const {
    450   return pending_close_;
    451 }
    452 
    453 bool DesktopWindowTreeHostWin::IsTranslucentWindowOpacitySupported() const {
    454   return ui::win::IsAeroGlassEnabled();
    455 }
    456 
    457 void DesktopWindowTreeHostWin::SizeConstraintsChanged() {
    458   message_handler_->SizeConstraintsChanged();
    459 }
    460 
    461 ////////////////////////////////////////////////////////////////////////////////
    462 // DesktopWindowTreeHostWin, WindowTreeHost implementation:
    463 
    464 ui::EventSource* DesktopWindowTreeHostWin::GetEventSource() {
    465   return this;
    466 }
    467 
    468 gfx::AcceleratedWidget DesktopWindowTreeHostWin::GetAcceleratedWidget() {
    469   return message_handler_->hwnd();
    470 }
    471 
    472 void DesktopWindowTreeHostWin::Show() {
    473   message_handler_->Show();
    474 }
    475 
    476 void DesktopWindowTreeHostWin::Hide() {
    477   if (!pending_close_)
    478     message_handler_->Hide();
    479 }
    480 
    481 // GetBounds and SetBounds work in pixel coordinates, whereas other get/set
    482 // methods work in DIP.
    483 
    484 gfx::Rect DesktopWindowTreeHostWin::GetBounds() const {
    485   gfx::Rect bounds(message_handler_->GetClientAreaBounds());
    486   // If the window bounds were expanded we need to return the original bounds
    487   // To achieve this we do the reverse of the expansion, i.e. add the
    488   // window_expansion_top_left_delta_ to the origin and subtract the
    489   // window_expansion_bottom_right_delta_ from the width and height.
    490   gfx::Rect without_expansion(
    491       bounds.x() + window_expansion_top_left_delta_.x(),
    492       bounds.y() + window_expansion_top_left_delta_.y(),
    493       bounds.width() - window_expansion_bottom_right_delta_.x() -
    494           window_enlargement_.x(),
    495       bounds.height() - window_expansion_bottom_right_delta_.y() -
    496           window_enlargement_.y());
    497   return without_expansion;
    498 }
    499 
    500 void DesktopWindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
    501   // If the window bounds have to be expanded we need to subtract the
    502   // window_expansion_top_left_delta_ from the origin and add the
    503   // window_expansion_bottom_right_delta_ to the width and height
    504   gfx::Size old_hwnd_size(message_handler_->GetClientAreaBounds().size());
    505   gfx::Size old_content_size = GetBounds().size();
    506 
    507   gfx::Rect expanded(
    508       bounds.x() - window_expansion_top_left_delta_.x(),
    509       bounds.y() - window_expansion_top_left_delta_.y(),
    510       bounds.width() + window_expansion_bottom_right_delta_.x(),
    511       bounds.height() + window_expansion_bottom_right_delta_.y());
    512 
    513   gfx::Rect new_expanded(
    514       expanded.origin(),
    515       GetExpandedWindowSize(message_handler_->window_ex_style(),
    516                             expanded.size()));
    517   window_enlargement_ =
    518       gfx::Vector2d(new_expanded.width() - expanded.width(),
    519                     new_expanded.height() - expanded.height());
    520   message_handler_->SetBounds(new_expanded, old_content_size != bounds.size());
    521 }
    522 
    523 gfx::Point DesktopWindowTreeHostWin::GetLocationOnNativeScreen() const {
    524   return GetBounds().origin();
    525 }
    526 
    527 void DesktopWindowTreeHostWin::SetCapture() {
    528   message_handler_->SetCapture();
    529 }
    530 
    531 void DesktopWindowTreeHostWin::ReleaseCapture() {
    532   message_handler_->ReleaseCapture();
    533 }
    534 
    535 void DesktopWindowTreeHostWin::PostNativeEvent(
    536     const base::NativeEvent& native_event) {
    537 }
    538 
    539 void DesktopWindowTreeHostWin::SetCursorNative(gfx::NativeCursor cursor) {
    540   ui::CursorLoaderWin cursor_loader;
    541   cursor_loader.SetPlatformCursor(&cursor);
    542 
    543   message_handler_->SetCursor(cursor.platform());
    544 }
    545 
    546 void DesktopWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
    547   if (is_cursor_visible_ == show)
    548     return;
    549   is_cursor_visible_ = show;
    550   ::ShowCursor(!!show);
    551 }
    552 
    553 void DesktopWindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
    554   POINT cursor_location = location.ToPOINT();
    555   ::ClientToScreen(GetHWND(), &cursor_location);
    556   ::SetCursorPos(cursor_location.x, cursor_location.y);
    557 }
    558 
    559 ////////////////////////////////////////////////////////////////////////////////
    560 // DesktopWindowTreeHostWin, ui::EventSource implementation:
    561 
    562 ui::EventProcessor* DesktopWindowTreeHostWin::GetEventProcessor() {
    563   return dispatcher();
    564 }
    565 
    566 ////////////////////////////////////////////////////////////////////////////////
    567 // DesktopWindowTreeHostWin, aura::AnimationHost implementation:
    568 
    569 void DesktopWindowTreeHostWin::SetHostTransitionOffsets(
    570     const gfx::Vector2d& top_left_delta,
    571     const gfx::Vector2d& bottom_right_delta) {
    572   gfx::Rect bounds_without_expansion = GetBounds();
    573   window_expansion_top_left_delta_ = top_left_delta;
    574   window_expansion_bottom_right_delta_ = bottom_right_delta;
    575   SetBounds(bounds_without_expansion);
    576 }
    577 
    578 void DesktopWindowTreeHostWin::OnWindowHidingAnimationCompleted() {
    579   if (pending_close_)
    580     message_handler_->Close();
    581 }
    582 
    583 ////////////////////////////////////////////////////////////////////////////////
    584 // DesktopWindowTreeHostWin, HWNDMessageHandlerDelegate implementation:
    585 
    586 bool DesktopWindowTreeHostWin::IsWidgetWindow() const {
    587   return has_non_client_view_;
    588 }
    589 
    590 bool DesktopWindowTreeHostWin::IsUsingCustomFrame() const {
    591   return !GetWidget()->ShouldUseNativeFrame();
    592 }
    593 
    594 void DesktopWindowTreeHostWin::SchedulePaint() {
    595   GetWidget()->GetRootView()->SchedulePaint();
    596 }
    597 
    598 void DesktopWindowTreeHostWin::EnableInactiveRendering() {
    599   native_widget_delegate_->EnableInactiveRendering();
    600 }
    601 
    602 bool DesktopWindowTreeHostWin::IsInactiveRenderingDisabled() {
    603   return native_widget_delegate_->IsInactiveRenderingDisabled();
    604 }
    605 
    606 bool DesktopWindowTreeHostWin::CanResize() const {
    607   return GetWidget()->widget_delegate()->CanResize();
    608 }
    609 
    610 bool DesktopWindowTreeHostWin::CanMaximize() const {
    611   return GetWidget()->widget_delegate()->CanMaximize();
    612 }
    613 
    614 bool DesktopWindowTreeHostWin::CanMinimize() const {
    615   return GetWidget()->widget_delegate()->CanMinimize();
    616 }
    617 
    618 bool DesktopWindowTreeHostWin::CanActivate() const {
    619   if (IsModalWindowActive())
    620     return true;
    621   return native_widget_delegate_->CanActivate();
    622 }
    623 
    624 bool DesktopWindowTreeHostWin::WidgetSizeIsClientSize() const {
    625   const Widget* widget = GetWidget()->GetTopLevelWidget();
    626   return IsMaximized() || (widget && widget->ShouldUseNativeFrame());
    627 }
    628 
    629 bool DesktopWindowTreeHostWin::IsModal() const {
    630   return native_widget_delegate_->IsModal();
    631 }
    632 
    633 int DesktopWindowTreeHostWin::GetInitialShowState() const {
    634   return CanActivate() ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
    635 }
    636 
    637 bool DesktopWindowTreeHostWin::WillProcessWorkAreaChange() const {
    638   return GetWidget()->widget_delegate()->WillProcessWorkAreaChange();
    639 }
    640 
    641 int DesktopWindowTreeHostWin::GetNonClientComponent(
    642     const gfx::Point& point) const {
    643   gfx::Point dip_position = gfx::win::ScreenToDIPPoint(point);
    644   return native_widget_delegate_->GetNonClientComponent(dip_position);
    645 }
    646 
    647 void DesktopWindowTreeHostWin::GetWindowMask(const gfx::Size& size,
    648                                              gfx::Path* path) {
    649   if (GetWidget()->non_client_view()) {
    650     GetWidget()->non_client_view()->GetWindowMask(size, path);
    651   } else if (!window_enlargement_.IsZero()) {
    652     gfx::Rect bounds(WidgetSizeIsClientSize()
    653                          ? message_handler_->GetClientAreaBoundsInScreen()
    654                          : message_handler_->GetWindowBoundsInScreen());
    655     InsetBottomRight(&bounds, window_enlargement_);
    656     path->addRect(SkRect::MakeXYWH(0, 0, bounds.width(), bounds.height()));
    657   }
    658 }
    659 
    660 bool DesktopWindowTreeHostWin::GetClientAreaInsets(gfx::Insets* insets) const {
    661   return false;
    662 }
    663 
    664 void DesktopWindowTreeHostWin::GetMinMaxSize(gfx::Size* min_size,
    665                                              gfx::Size* max_size) const {
    666   *min_size = native_widget_delegate_->GetMinimumSize();
    667   *max_size = native_widget_delegate_->GetMaximumSize();
    668 }
    669 
    670 gfx::Size DesktopWindowTreeHostWin::GetRootViewSize() const {
    671   return GetWidget()->GetRootView()->size();
    672 }
    673 
    674 void DesktopWindowTreeHostWin::ResetWindowControls() {
    675   GetWidget()->non_client_view()->ResetWindowControls();
    676 }
    677 
    678 void DesktopWindowTreeHostWin::PaintLayeredWindow(gfx::Canvas* canvas) {
    679   GetWidget()->GetRootView()->Paint(canvas, views::CullSet());
    680 }
    681 
    682 gfx::NativeViewAccessible DesktopWindowTreeHostWin::GetNativeViewAccessible() {
    683   return GetWidget()->GetRootView()->GetNativeViewAccessible();
    684 }
    685 
    686 InputMethod* DesktopWindowTreeHostWin::GetInputMethod() {
    687   return GetWidget()->GetInputMethodDirect();
    688 }
    689 
    690 bool DesktopWindowTreeHostWin::ShouldHandleSystemCommands() const {
    691   return GetWidget()->widget_delegate()->ShouldHandleSystemCommands();
    692 }
    693 
    694 void DesktopWindowTreeHostWin::HandleAppDeactivated() {
    695   native_widget_delegate_->EnableInactiveRendering();
    696 }
    697 
    698 void DesktopWindowTreeHostWin::HandleActivationChanged(bool active) {
    699   // This can be invoked from HWNDMessageHandler::Init(), at which point we're
    700   // not in a good state and need to ignore it.
    701   // TODO(beng): Do we need this still now the host owns the dispatcher?
    702   if (!dispatcher())
    703     return;
    704 
    705   if (active)
    706     OnHostActivated();
    707   desktop_native_widget_aura_->HandleActivationChanged(active);
    708 }
    709 
    710 bool DesktopWindowTreeHostWin::HandleAppCommand(short command) {
    711   // We treat APPCOMMAND ids as an extension of our command namespace, and just
    712   // let the delegate figure out what to do...
    713   return GetWidget()->widget_delegate() &&
    714       GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
    715 }
    716 
    717 void DesktopWindowTreeHostWin::HandleCancelMode() {
    718   dispatcher()->DispatchCancelModeEvent();
    719 }
    720 
    721 void DesktopWindowTreeHostWin::HandleCaptureLost() {
    722   OnHostLostWindowCapture();
    723 }
    724 
    725 void DesktopWindowTreeHostWin::HandleClose() {
    726   GetWidget()->Close();
    727 }
    728 
    729 bool DesktopWindowTreeHostWin::HandleCommand(int command) {
    730   // Windows uses the 4 lower order bits of |notification_code| for type-
    731   // specific information so we must exclude this when comparing.
    732   static const int sc_mask = 0xFFF0;
    733   switch (command & sc_mask) {
    734     case SC_RESTORE:
    735     case SC_MAXIMIZE:
    736       need_synchronous_paint_ = true;
    737       break;
    738 
    739     case SC_SIZE:
    740       in_sizing_loop_ = true;
    741       break;
    742 
    743     default:
    744       break;
    745   }
    746   return GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
    747 }
    748 
    749 void DesktopWindowTreeHostWin::HandleAccelerator(
    750     const ui::Accelerator& accelerator) {
    751   GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator);
    752 }
    753 
    754 void DesktopWindowTreeHostWin::HandleCreate() {
    755   native_widget_delegate_->OnNativeWidgetCreated(true);
    756 }
    757 
    758 void DesktopWindowTreeHostWin::HandleDestroying() {
    759   drag_drop_client_->OnNativeWidgetDestroying(GetHWND());
    760   native_widget_delegate_->OnNativeWidgetDestroying();
    761 
    762   // Destroy the compositor before destroying the HWND since shutdown
    763   // may try to swap to the window.
    764   DestroyCompositor();
    765 }
    766 
    767 void DesktopWindowTreeHostWin::HandleDestroyed() {
    768   desktop_native_widget_aura_->OnHostClosed();
    769 }
    770 
    771 bool DesktopWindowTreeHostWin::HandleInitialFocus(
    772     ui::WindowShowState show_state) {
    773   return GetWidget()->SetInitialFocus(show_state);
    774 }
    775 
    776 void DesktopWindowTreeHostWin::HandleDisplayChange() {
    777   GetWidget()->widget_delegate()->OnDisplayChanged();
    778 }
    779 
    780 void DesktopWindowTreeHostWin::HandleBeginWMSizeMove() {
    781   if (in_sizing_loop_)
    782     need_synchronous_paint_ = true;
    783   native_widget_delegate_->OnNativeWidgetBeginUserBoundsChange();
    784 }
    785 
    786 void DesktopWindowTreeHostWin::HandleEndWMSizeMove() {
    787   if (in_sizing_loop_) {
    788     need_synchronous_paint_ = false;
    789     in_sizing_loop_ = false;
    790   }
    791   native_widget_delegate_->OnNativeWidgetEndUserBoundsChange();
    792 }
    793 
    794 void DesktopWindowTreeHostWin::HandleMove() {
    795   native_widget_delegate_->OnNativeWidgetMove();
    796   OnHostMoved(GetBounds().origin());
    797 }
    798 
    799 void DesktopWindowTreeHostWin::HandleWorkAreaChanged() {
    800   GetWidget()->widget_delegate()->OnWorkAreaChanged();
    801 }
    802 
    803 void DesktopWindowTreeHostWin::HandleVisibilityChanging(bool visible) {
    804   native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible);
    805 }
    806 
    807 void DesktopWindowTreeHostWin::HandleVisibilityChanged(bool visible) {
    808   native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
    809 }
    810 
    811 void DesktopWindowTreeHostWin::HandleClientSizeChanged(
    812     const gfx::Size& new_size) {
    813   if (dispatcher())
    814     OnHostResized(new_size);
    815 }
    816 
    817 void DesktopWindowTreeHostWin::HandleFrameChanged() {
    818   SetWindowTransparency();
    819   // Replace the frame and layout the contents.
    820   GetWidget()->non_client_view()->UpdateFrame();
    821 }
    822 
    823 void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) {
    824   // TODO(beng): inform the native_widget_delegate_.
    825   InputMethod* input_method = GetInputMethod();
    826   if (input_method)
    827     input_method->OnFocus();
    828 }
    829 
    830 void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) {
    831   // TODO(beng): inform the native_widget_delegate_.
    832   InputMethod* input_method = GetInputMethod();
    833   if (input_method)
    834     input_method->OnBlur();
    835 }
    836 
    837 bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) {
    838   SendEventToProcessor(const_cast<ui::MouseEvent*>(&event));
    839   return event.handled();
    840 }
    841 
    842 bool DesktopWindowTreeHostWin::HandleKeyEvent(const ui::KeyEvent& event) {
    843   return false;
    844 }
    845 
    846 bool DesktopWindowTreeHostWin::HandleUntranslatedKeyEvent(
    847     const ui::KeyEvent& event) {
    848   ui::KeyEvent duplicate_event(event);
    849   SendEventToProcessor(&duplicate_event);
    850   return duplicate_event.handled();
    851 }
    852 
    853 void DesktopWindowTreeHostWin::HandleTouchEvent(
    854     const ui::TouchEvent& event) {
    855   // HWNDMessageHandler asynchronously processes touch events. Because of this
    856   // it's possible for the aura::WindowEventDispatcher to have been destroyed
    857   // by the time we attempt to process them.
    858   if (!GetWidget()->GetNativeView())
    859     return;
    860 
    861   // Currently we assume the window that has capture gets touch events too.
    862   aura::WindowTreeHost* host =
    863       aura::WindowTreeHost::GetForAcceleratedWidget(GetCapture());
    864   if (host) {
    865     DesktopWindowTreeHostWin* target =
    866         host->window()->GetProperty(kDesktopWindowTreeHostKey);
    867     if (target && target->HasCapture() && target != this) {
    868       POINT target_location(event.location().ToPOINT());
    869       ClientToScreen(GetHWND(), &target_location);
    870       ScreenToClient(target->GetHWND(), &target_location);
    871       ui::TouchEvent target_event(event, static_cast<View*>(NULL),
    872                                   static_cast<View*>(NULL));
    873       target_event.set_location(gfx::Point(target_location));
    874       target_event.set_root_location(target_event.location());
    875       target->SendEventToProcessor(&target_event);
    876       return;
    877     }
    878   }
    879   SendEventToProcessor(const_cast<ui::TouchEvent*>(&event));
    880 }
    881 
    882 bool DesktopWindowTreeHostWin::HandleIMEMessage(UINT message,
    883                                                 WPARAM w_param,
    884                                                 LPARAM l_param,
    885                                                 LRESULT* result) {
    886   MSG msg = {};
    887   msg.hwnd = GetHWND();
    888   msg.message = message;
    889   msg.wParam = w_param;
    890   msg.lParam = l_param;
    891   return desktop_native_widget_aura_->input_method_event_filter()->
    892       input_method()->OnUntranslatedIMEMessage(msg, result);
    893 }
    894 
    895 void DesktopWindowTreeHostWin::HandleInputLanguageChange(
    896     DWORD character_set,
    897     HKL input_language_id) {
    898   desktop_native_widget_aura_->input_method_event_filter()->
    899       input_method()->OnInputLocaleChanged();
    900 }
    901 
    902 bool DesktopWindowTreeHostWin::HandlePaintAccelerated(
    903     const gfx::Rect& invalid_rect) {
    904   return native_widget_delegate_->OnNativeWidgetPaintAccelerated(invalid_rect);
    905 }
    906 
    907 void DesktopWindowTreeHostWin::HandlePaint(gfx::Canvas* canvas) {
    908   // It appears possible to get WM_PAINT after WM_DESTROY.
    909   if (compositor())
    910     compositor()->ScheduleRedrawRect(gfx::Rect());
    911 }
    912 
    913 bool DesktopWindowTreeHostWin::HandleTooltipNotify(int w_param,
    914                                                    NMHDR* l_param,
    915                                                    LRESULT* l_result) {
    916   return tooltip_ && tooltip_->HandleNotify(w_param, l_param, l_result);
    917 }
    918 
    919 void DesktopWindowTreeHostWin::HandleMenuLoop(bool in_menu_loop) {
    920   if (in_menu_loop) {
    921     tooltip_disabler_.reset(
    922         new aura::client::ScopedTooltipDisabler(window()));
    923   } else {
    924     tooltip_disabler_.reset();
    925   }
    926 }
    927 
    928 bool DesktopWindowTreeHostWin::PreHandleMSG(UINT message,
    929                                             WPARAM w_param,
    930                                             LPARAM l_param,
    931                                             LRESULT* result) {
    932   return false;
    933 }
    934 
    935 void DesktopWindowTreeHostWin::PostHandleMSG(UINT message,
    936                                              WPARAM w_param,
    937                                              LPARAM l_param) {
    938 }
    939 
    940 bool DesktopWindowTreeHostWin::HandleScrollEvent(
    941     const ui::ScrollEvent& event) {
    942   SendEventToProcessor(const_cast<ui::ScrollEvent*>(&event));
    943   return event.handled();
    944 }
    945 
    946 void DesktopWindowTreeHostWin::HandleWindowSizeChanging() {
    947   if (compositor() && need_synchronous_paint_) {
    948     compositor()->FinishAllRendering();
    949     // If we received the window size changing notification due to a restore or
    950     // maximize operation, then we can reset the need_synchronous_paint_ flag
    951     // here. For a sizing operation, the flag will be reset at the end of the
    952     // operation.
    953     if (!in_sizing_loop_)
    954       need_synchronous_paint_ = false;
    955   }
    956 }
    957 
    958 ////////////////////////////////////////////////////////////////////////////////
    959 // DesktopWindowTreeHostWin, private:
    960 
    961 Widget* DesktopWindowTreeHostWin::GetWidget() {
    962   return native_widget_delegate_->AsWidget();
    963 }
    964 
    965 const Widget* DesktopWindowTreeHostWin::GetWidget() const {
    966   return native_widget_delegate_->AsWidget();
    967 }
    968 
    969 HWND DesktopWindowTreeHostWin::GetHWND() const {
    970   return message_handler_->hwnd();
    971 }
    972 
    973 void DesktopWindowTreeHostWin::SetWindowTransparency() {
    974   bool transparent = ShouldUseNativeFrame() && !IsFullscreen();
    975   compositor()->SetHostHasTransparentBackground(transparent);
    976   window()->SetTransparent(transparent);
    977   content_window_->SetTransparent(transparent);
    978 }
    979 
    980 bool DesktopWindowTreeHostWin::IsModalWindowActive() const {
    981   // This function can get called during window creation which occurs before
    982   // dispatcher() has been created.
    983   if (!dispatcher())
    984     return false;
    985 
    986   aura::Window::Windows::const_iterator index;
    987   for (index = window()->children().begin();
    988        index != window()->children().end();
    989        ++index) {
    990     if ((*index)->GetProperty(aura::client::kModalKey) !=
    991         ui:: MODAL_TYPE_NONE && (*index)->TargetVisibility())
    992       return true;
    993   }
    994   return false;
    995 }
    996 
    997 ////////////////////////////////////////////////////////////////////////////////
    998 // DesktopWindowTreeHost, public:
    999 
   1000 // static
   1001 DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
   1002     internal::NativeWidgetDelegate* native_widget_delegate,
   1003     DesktopNativeWidgetAura* desktop_native_widget_aura) {
   1004   return new DesktopWindowTreeHostWin(native_widget_delegate,
   1005                                       desktop_native_widget_aura);
   1006 }
   1007 
   1008 }  // namespace views
   1009