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