• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetExpandedWindowSize(DWORD window_style,gfx::Size size)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 
InsetBottomRight(gfx::Rect * rect,gfx::Vector2d vector)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 
DesktopWindowTreeHostWin(internal::NativeWidgetDelegate * native_widget_delegate,DesktopNativeWidgetAura * desktop_native_widget_aura)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 
~DesktopWindowTreeHostWin()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
GetContentWindowForHWND(HWND hwnd)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
GetNativeTheme(aura::Window * window)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 
Init(aura::Window * content_window,const Widget::InitParams & params)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 
OnNativeWidgetCreated(const Widget::InitParams & params)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 
CreateTooltip()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>
CreateDragDropClient(DesktopNativeCursorManager * cursor_manager)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 
Close()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 
CloseNow()199 void DesktopWindowTreeHostWin::CloseNow() {
200   message_handler_->CloseNow();
201 }
202 
AsWindowTreeHost()203 aura::WindowTreeHost* DesktopWindowTreeHostWin::AsWindowTreeHost() {
204   return this;
205 }
206 
ShowWindowWithState(ui::WindowShowState show_state)207 void DesktopWindowTreeHostWin::ShowWindowWithState(
208     ui::WindowShowState show_state) {
209   message_handler_->ShowWindowWithState(show_state);
210 }
211 
ShowMaximizedWithBounds(const gfx::Rect & restored_bounds)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 
IsVisible() const218 bool DesktopWindowTreeHostWin::IsVisible() const {
219   return message_handler_->IsVisible();
220 }
221 
SetSize(const gfx::Size & size)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 
StackAtTop()232 void DesktopWindowTreeHostWin::StackAtTop() {
233   message_handler_->StackAtTop();
234 }
235 
CenterWindow(const gfx::Size & size)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 
GetWindowPlacement(gfx::Rect * bounds,ui::WindowShowState * show_state) const247 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 
GetWindowBoundsInScreen() const255 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 
GetClientAreaBoundsInScreen() const261 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 
GetRestoredBounds() const267 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 
GetWorkAreaBoundsInScreen() const273 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 
SetShape(gfx::NativeRegion native_region)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 
Activate()314 void DesktopWindowTreeHostWin::Activate() {
315   message_handler_->Activate();
316 }
317 
Deactivate()318 void DesktopWindowTreeHostWin::Deactivate() {
319   message_handler_->Deactivate();
320 }
321 
IsActive() const322 bool DesktopWindowTreeHostWin::IsActive() const {
323   return message_handler_->IsActive();
324 }
325 
Maximize()326 void DesktopWindowTreeHostWin::Maximize() {
327   message_handler_->Maximize();
328 }
329 
Minimize()330 void DesktopWindowTreeHostWin::Minimize() {
331   message_handler_->Minimize();
332 }
333 
Restore()334 void DesktopWindowTreeHostWin::Restore() {
335   message_handler_->Restore();
336 }
337 
IsMaximized() const338 bool DesktopWindowTreeHostWin::IsMaximized() const {
339   return message_handler_->IsMaximized();
340 }
341 
IsMinimized() const342 bool DesktopWindowTreeHostWin::IsMinimized() const {
343   return message_handler_->IsMinimized();
344 }
345 
HasCapture() const346 bool DesktopWindowTreeHostWin::HasCapture() const {
347   return message_handler_->HasCapture();
348 }
349 
SetAlwaysOnTop(bool always_on_top)350 void DesktopWindowTreeHostWin::SetAlwaysOnTop(bool always_on_top) {
351   message_handler_->SetAlwaysOnTop(always_on_top);
352 }
353 
IsAlwaysOnTop() const354 bool DesktopWindowTreeHostWin::IsAlwaysOnTop() const {
355   return message_handler_->IsAlwaysOnTop();
356 }
357 
SetVisibleOnAllWorkspaces(bool always_visible)358 void DesktopWindowTreeHostWin::SetVisibleOnAllWorkspaces(bool always_visible) {
359   // Windows does not have the concept of workspaces.
360 }
361 
SetWindowTitle(const base::string16 & title)362 bool DesktopWindowTreeHostWin::SetWindowTitle(const base::string16& title) {
363   return message_handler_->SetTitle(title);
364 }
365 
ClearNativeFocus()366 void DesktopWindowTreeHostWin::ClearNativeFocus() {
367   message_handler_->ClearNativeFocus();
368 }
369 
RunMoveLoop(const gfx::Vector2d & drag_offset,Widget::MoveLoopSource source,Widget::MoveLoopEscapeBehavior escape_behavior)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 
EndMoveLoop()380 void DesktopWindowTreeHostWin::EndMoveLoop() {
381   message_handler_->EndMoveLoop();
382 }
383 
SetVisibilityChangedAnimationsEnabled(bool value)384 void DesktopWindowTreeHostWin::SetVisibilityChangedAnimationsEnabled(
385     bool value) {
386   message_handler_->SetVisibilityChangedAnimationsEnabled(value);
387   content_window_->SetProperty(aura::client::kAnimationsDisabledKey, !value);
388 }
389 
ShouldUseNativeFrame() const390 bool DesktopWindowTreeHostWin::ShouldUseNativeFrame() const {
391   return IsTranslucentWindowOpacitySupported();
392 }
393 
ShouldWindowContentsBeTransparent() const394 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 
FrameTypeChanged()402 void DesktopWindowTreeHostWin::FrameTypeChanged() {
403   message_handler_->FrameTypeChanged();
404   SetWindowTransparency();
405 }
406 
SetFullscreen(bool fullscreen)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 
IsFullscreen() const417 bool DesktopWindowTreeHostWin::IsFullscreen() const {
418   return message_handler_->fullscreen_handler()->fullscreen();
419 }
420 
SetOpacity(unsigned char opacity)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 
SetWindowIcons(const gfx::ImageSkia & window_icon,const gfx::ImageSkia & app_icon)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 
InitModalType(ui::ModalType modal_type)431 void DesktopWindowTreeHostWin::InitModalType(ui::ModalType modal_type) {
432   message_handler_->InitModalType(modal_type);
433 }
434 
FlashFrame(bool flash_frame)435 void DesktopWindowTreeHostWin::FlashFrame(bool flash_frame) {
436   message_handler_->FlashFrame(flash_frame);
437 }
438 
OnRootViewLayout()439 void DesktopWindowTreeHostWin::OnRootViewLayout() {
440 }
441 
OnNativeWidgetFocus()442 void DesktopWindowTreeHostWin::OnNativeWidgetFocus() {
443   // HWNDMessageHandler will perform the proper updating on its own.
444 }
445 
OnNativeWidgetBlur()446 void DesktopWindowTreeHostWin::OnNativeWidgetBlur() {
447 }
448 
IsAnimatingClosed() const449 bool DesktopWindowTreeHostWin::IsAnimatingClosed() const {
450   return pending_close_;
451 }
452 
IsTranslucentWindowOpacitySupported() const453 bool DesktopWindowTreeHostWin::IsTranslucentWindowOpacitySupported() const {
454   return ui::win::IsAeroGlassEnabled();
455 }
456 
SizeConstraintsChanged()457 void DesktopWindowTreeHostWin::SizeConstraintsChanged() {
458   message_handler_->SizeConstraintsChanged();
459 }
460 
461 ////////////////////////////////////////////////////////////////////////////////
462 // DesktopWindowTreeHostWin, WindowTreeHost implementation:
463 
GetEventSource()464 ui::EventSource* DesktopWindowTreeHostWin::GetEventSource() {
465   return this;
466 }
467 
GetAcceleratedWidget()468 gfx::AcceleratedWidget DesktopWindowTreeHostWin::GetAcceleratedWidget() {
469   return message_handler_->hwnd();
470 }
471 
Show()472 void DesktopWindowTreeHostWin::Show() {
473   message_handler_->Show();
474 }
475 
Hide()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 
GetBounds() const484 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 
SetBounds(const gfx::Rect & bounds)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 
GetLocationOnNativeScreen() const523 gfx::Point DesktopWindowTreeHostWin::GetLocationOnNativeScreen() const {
524   return GetBounds().origin();
525 }
526 
SetCapture()527 void DesktopWindowTreeHostWin::SetCapture() {
528   message_handler_->SetCapture();
529 }
530 
ReleaseCapture()531 void DesktopWindowTreeHostWin::ReleaseCapture() {
532   message_handler_->ReleaseCapture();
533 }
534 
PostNativeEvent(const base::NativeEvent & native_event)535 void DesktopWindowTreeHostWin::PostNativeEvent(
536     const base::NativeEvent& native_event) {
537 }
538 
SetCursorNative(gfx::NativeCursor cursor)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 
OnCursorVisibilityChangedNative(bool show)546 void DesktopWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
547   if (is_cursor_visible_ == show)
548     return;
549   is_cursor_visible_ = show;
550   ::ShowCursor(!!show);
551 }
552 
MoveCursorToNative(const gfx::Point & location)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 
GetEventProcessor()562 ui::EventProcessor* DesktopWindowTreeHostWin::GetEventProcessor() {
563   return dispatcher();
564 }
565 
566 ////////////////////////////////////////////////////////////////////////////////
567 // DesktopWindowTreeHostWin, aura::AnimationHost implementation:
568 
SetHostTransitionOffsets(const gfx::Vector2d & top_left_delta,const gfx::Vector2d & bottom_right_delta)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 
OnWindowHidingAnimationCompleted()578 void DesktopWindowTreeHostWin::OnWindowHidingAnimationCompleted() {
579   if (pending_close_)
580     message_handler_->Close();
581 }
582 
583 ////////////////////////////////////////////////////////////////////////////////
584 // DesktopWindowTreeHostWin, HWNDMessageHandlerDelegate implementation:
585 
IsWidgetWindow() const586 bool DesktopWindowTreeHostWin::IsWidgetWindow() const {
587   return has_non_client_view_;
588 }
589 
IsUsingCustomFrame() const590 bool DesktopWindowTreeHostWin::IsUsingCustomFrame() const {
591   return !GetWidget()->ShouldUseNativeFrame();
592 }
593 
SchedulePaint()594 void DesktopWindowTreeHostWin::SchedulePaint() {
595   GetWidget()->GetRootView()->SchedulePaint();
596 }
597 
EnableInactiveRendering()598 void DesktopWindowTreeHostWin::EnableInactiveRendering() {
599   native_widget_delegate_->EnableInactiveRendering();
600 }
601 
IsInactiveRenderingDisabled()602 bool DesktopWindowTreeHostWin::IsInactiveRenderingDisabled() {
603   return native_widget_delegate_->IsInactiveRenderingDisabled();
604 }
605 
CanResize() const606 bool DesktopWindowTreeHostWin::CanResize() const {
607   return GetWidget()->widget_delegate()->CanResize();
608 }
609 
CanMaximize() const610 bool DesktopWindowTreeHostWin::CanMaximize() const {
611   return GetWidget()->widget_delegate()->CanMaximize();
612 }
613 
CanMinimize() const614 bool DesktopWindowTreeHostWin::CanMinimize() const {
615   return GetWidget()->widget_delegate()->CanMinimize();
616 }
617 
CanActivate() const618 bool DesktopWindowTreeHostWin::CanActivate() const {
619   if (IsModalWindowActive())
620     return true;
621   return native_widget_delegate_->CanActivate();
622 }
623 
WidgetSizeIsClientSize() const624 bool DesktopWindowTreeHostWin::WidgetSizeIsClientSize() const {
625   const Widget* widget = GetWidget()->GetTopLevelWidget();
626   return IsMaximized() || (widget && widget->ShouldUseNativeFrame());
627 }
628 
IsModal() const629 bool DesktopWindowTreeHostWin::IsModal() const {
630   return native_widget_delegate_->IsModal();
631 }
632 
GetInitialShowState() const633 int DesktopWindowTreeHostWin::GetInitialShowState() const {
634   return CanActivate() ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
635 }
636 
WillProcessWorkAreaChange() const637 bool DesktopWindowTreeHostWin::WillProcessWorkAreaChange() const {
638   return GetWidget()->widget_delegate()->WillProcessWorkAreaChange();
639 }
640 
GetNonClientComponent(const gfx::Point & point) const641 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 
GetWindowMask(const gfx::Size & size,gfx::Path * path)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 
GetClientAreaInsets(gfx::Insets * insets) const660 bool DesktopWindowTreeHostWin::GetClientAreaInsets(gfx::Insets* insets) const {
661   return false;
662 }
663 
GetMinMaxSize(gfx::Size * min_size,gfx::Size * max_size) const664 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 
GetRootViewSize() const670 gfx::Size DesktopWindowTreeHostWin::GetRootViewSize() const {
671   return GetWidget()->GetRootView()->size();
672 }
673 
ResetWindowControls()674 void DesktopWindowTreeHostWin::ResetWindowControls() {
675   GetWidget()->non_client_view()->ResetWindowControls();
676 }
677 
PaintLayeredWindow(gfx::Canvas * canvas)678 void DesktopWindowTreeHostWin::PaintLayeredWindow(gfx::Canvas* canvas) {
679   GetWidget()->GetRootView()->Paint(canvas, views::CullSet());
680 }
681 
GetNativeViewAccessible()682 gfx::NativeViewAccessible DesktopWindowTreeHostWin::GetNativeViewAccessible() {
683   return GetWidget()->GetRootView()->GetNativeViewAccessible();
684 }
685 
GetInputMethod()686 InputMethod* DesktopWindowTreeHostWin::GetInputMethod() {
687   return GetWidget()->GetInputMethodDirect();
688 }
689 
ShouldHandleSystemCommands() const690 bool DesktopWindowTreeHostWin::ShouldHandleSystemCommands() const {
691   return GetWidget()->widget_delegate()->ShouldHandleSystemCommands();
692 }
693 
HandleAppDeactivated()694 void DesktopWindowTreeHostWin::HandleAppDeactivated() {
695   native_widget_delegate_->EnableInactiveRendering();
696 }
697 
HandleActivationChanged(bool active)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 
HandleAppCommand(short command)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 
HandleCancelMode()717 void DesktopWindowTreeHostWin::HandleCancelMode() {
718   dispatcher()->DispatchCancelModeEvent();
719 }
720 
HandleCaptureLost()721 void DesktopWindowTreeHostWin::HandleCaptureLost() {
722   OnHostLostWindowCapture();
723 }
724 
HandleClose()725 void DesktopWindowTreeHostWin::HandleClose() {
726   GetWidget()->Close();
727 }
728 
HandleCommand(int command)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 
HandleAccelerator(const ui::Accelerator & accelerator)749 void DesktopWindowTreeHostWin::HandleAccelerator(
750     const ui::Accelerator& accelerator) {
751   GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator);
752 }
753 
HandleCreate()754 void DesktopWindowTreeHostWin::HandleCreate() {
755   native_widget_delegate_->OnNativeWidgetCreated(true);
756 }
757 
HandleDestroying()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 
HandleDestroyed()767 void DesktopWindowTreeHostWin::HandleDestroyed() {
768   desktop_native_widget_aura_->OnHostClosed();
769 }
770 
HandleInitialFocus(ui::WindowShowState show_state)771 bool DesktopWindowTreeHostWin::HandleInitialFocus(
772     ui::WindowShowState show_state) {
773   return GetWidget()->SetInitialFocus(show_state);
774 }
775 
HandleDisplayChange()776 void DesktopWindowTreeHostWin::HandleDisplayChange() {
777   GetWidget()->widget_delegate()->OnDisplayChanged();
778 }
779 
HandleBeginWMSizeMove()780 void DesktopWindowTreeHostWin::HandleBeginWMSizeMove() {
781   if (in_sizing_loop_)
782     need_synchronous_paint_ = true;
783   native_widget_delegate_->OnNativeWidgetBeginUserBoundsChange();
784 }
785 
HandleEndWMSizeMove()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 
HandleMove()794 void DesktopWindowTreeHostWin::HandleMove() {
795   native_widget_delegate_->OnNativeWidgetMove();
796   OnHostMoved(GetBounds().origin());
797 }
798 
HandleWorkAreaChanged()799 void DesktopWindowTreeHostWin::HandleWorkAreaChanged() {
800   GetWidget()->widget_delegate()->OnWorkAreaChanged();
801 }
802 
HandleVisibilityChanging(bool visible)803 void DesktopWindowTreeHostWin::HandleVisibilityChanging(bool visible) {
804   native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible);
805 }
806 
HandleVisibilityChanged(bool visible)807 void DesktopWindowTreeHostWin::HandleVisibilityChanged(bool visible) {
808   native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
809 }
810 
HandleClientSizeChanged(const gfx::Size & new_size)811 void DesktopWindowTreeHostWin::HandleClientSizeChanged(
812     const gfx::Size& new_size) {
813   if (dispatcher())
814     OnHostResized(new_size);
815 }
816 
HandleFrameChanged()817 void DesktopWindowTreeHostWin::HandleFrameChanged() {
818   SetWindowTransparency();
819   // Replace the frame and layout the contents.
820   GetWidget()->non_client_view()->UpdateFrame();
821 }
822 
HandleNativeFocus(HWND last_focused_window)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 
HandleNativeBlur(HWND focused_window)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 
HandleMouseEvent(const ui::MouseEvent & event)837 bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) {
838   SendEventToProcessor(const_cast<ui::MouseEvent*>(&event));
839   return event.handled();
840 }
841 
HandleKeyEvent(const ui::KeyEvent & event)842 bool DesktopWindowTreeHostWin::HandleKeyEvent(const ui::KeyEvent& event) {
843   return false;
844 }
845 
HandleUntranslatedKeyEvent(const ui::KeyEvent & event)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 
HandleTouchEvent(const ui::TouchEvent & event)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 
HandleIMEMessage(UINT message,WPARAM w_param,LPARAM l_param,LRESULT * result)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 
HandleInputLanguageChange(DWORD character_set,HKL input_language_id)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 
HandlePaintAccelerated(const gfx::Rect & invalid_rect)902 bool DesktopWindowTreeHostWin::HandlePaintAccelerated(
903     const gfx::Rect& invalid_rect) {
904   return native_widget_delegate_->OnNativeWidgetPaintAccelerated(invalid_rect);
905 }
906 
HandlePaint(gfx::Canvas * canvas)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 
HandleTooltipNotify(int w_param,NMHDR * l_param,LRESULT * l_result)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 
HandleMenuLoop(bool in_menu_loop)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 
PreHandleMSG(UINT message,WPARAM w_param,LPARAM l_param,LRESULT * result)928 bool DesktopWindowTreeHostWin::PreHandleMSG(UINT message,
929                                             WPARAM w_param,
930                                             LPARAM l_param,
931                                             LRESULT* result) {
932   return false;
933 }
934 
PostHandleMSG(UINT message,WPARAM w_param,LPARAM l_param)935 void DesktopWindowTreeHostWin::PostHandleMSG(UINT message,
936                                              WPARAM w_param,
937                                              LPARAM l_param) {
938 }
939 
HandleScrollEvent(const ui::ScrollEvent & event)940 bool DesktopWindowTreeHostWin::HandleScrollEvent(
941     const ui::ScrollEvent& event) {
942   SendEventToProcessor(const_cast<ui::ScrollEvent*>(&event));
943   return event.handled();
944 }
945 
HandleWindowSizeChanging()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 
GetWidget()961 Widget* DesktopWindowTreeHostWin::GetWidget() {
962   return native_widget_delegate_->AsWidget();
963 }
964 
GetWidget() const965 const Widget* DesktopWindowTreeHostWin::GetWidget() const {
966   return native_widget_delegate_->AsWidget();
967 }
968 
GetHWND() const969 HWND DesktopWindowTreeHostWin::GetHWND() const {
970   return message_handler_->hwnd();
971 }
972 
SetWindowTransparency()973 void DesktopWindowTreeHostWin::SetWindowTransparency() {
974   bool transparent = ShouldUseNativeFrame() && !IsFullscreen();
975   compositor()->SetHostHasTransparentBackground(transparent);
976   window()->SetTransparent(transparent);
977   content_window_->SetTransparent(transparent);
978 }
979 
IsModalWindowActive() const980 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
Create(internal::NativeWidgetDelegate * native_widget_delegate,DesktopNativeWidgetAura * desktop_native_widget_aura)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