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 }
88
~DesktopWindowTreeHostWin()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
GetContentWindowForHWND(HWND hwnd)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
GetNativeTheme(aura::Window * window)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
Init(aura::Window * content_window,const Widget::InitParams & params)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
OnNativeWidgetCreated(const Widget::InitParams & params)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
CreateTooltip()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>
CreateDragDropClient(DesktopNativeCursorManager * cursor_manager)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
Close()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
CloseNow()197 void DesktopWindowTreeHostWin::CloseNow() {
198 message_handler_->CloseNow();
199 }
200
AsWindowTreeHost()201 aura::WindowTreeHost* DesktopWindowTreeHostWin::AsWindowTreeHost() {
202 return this;
203 }
204
ShowWindowWithState(ui::WindowShowState show_state)205 void DesktopWindowTreeHostWin::ShowWindowWithState(
206 ui::WindowShowState show_state) {
207 message_handler_->ShowWindowWithState(show_state);
208 }
209
ShowMaximizedWithBounds(const gfx::Rect & restored_bounds)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
IsVisible() const216 bool DesktopWindowTreeHostWin::IsVisible() const {
217 return message_handler_->IsVisible();
218 }
219
SetSize(const gfx::Size & size)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
StackAtTop()230 void DesktopWindowTreeHostWin::StackAtTop() {
231 message_handler_->StackAtTop();
232 }
233
CenterWindow(const gfx::Size & size)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
GetWindowPlacement(gfx::Rect * bounds,ui::WindowShowState * show_state) const245 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
GetWindowBoundsInScreen() const253 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
GetClientAreaBoundsInScreen() const259 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
GetRestoredBounds() const265 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
GetWorkAreaBoundsInScreen() const271 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
SetShape(gfx::NativeRegion native_region)281 void DesktopWindowTreeHostWin::SetShape(gfx::NativeRegion native_region) {
282 if (native_region) {
283 message_handler_->SetRegion(gfx::CreateHRGNFromSkRegion(*native_region));
284 } else {
285 message_handler_->SetRegion(NULL);
286 }
287
288 delete native_region;
289 }
290
Activate()291 void DesktopWindowTreeHostWin::Activate() {
292 message_handler_->Activate();
293 }
294
Deactivate()295 void DesktopWindowTreeHostWin::Deactivate() {
296 message_handler_->Deactivate();
297 }
298
IsActive() const299 bool DesktopWindowTreeHostWin::IsActive() const {
300 return message_handler_->IsActive();
301 }
302
Maximize()303 void DesktopWindowTreeHostWin::Maximize() {
304 message_handler_->Maximize();
305 }
306
Minimize()307 void DesktopWindowTreeHostWin::Minimize() {
308 message_handler_->Minimize();
309 }
310
Restore()311 void DesktopWindowTreeHostWin::Restore() {
312 message_handler_->Restore();
313 }
314
IsMaximized() const315 bool DesktopWindowTreeHostWin::IsMaximized() const {
316 return message_handler_->IsMaximized();
317 }
318
IsMinimized() const319 bool DesktopWindowTreeHostWin::IsMinimized() const {
320 return message_handler_->IsMinimized();
321 }
322
HasCapture() const323 bool DesktopWindowTreeHostWin::HasCapture() const {
324 return message_handler_->HasCapture();
325 }
326
SetAlwaysOnTop(bool always_on_top)327 void DesktopWindowTreeHostWin::SetAlwaysOnTop(bool always_on_top) {
328 message_handler_->SetAlwaysOnTop(always_on_top);
329 }
330
IsAlwaysOnTop() const331 bool DesktopWindowTreeHostWin::IsAlwaysOnTop() const {
332 return message_handler_->IsAlwaysOnTop();
333 }
334
SetVisibleOnAllWorkspaces(bool always_visible)335 void DesktopWindowTreeHostWin::SetVisibleOnAllWorkspaces(bool always_visible) {
336 // Windows does not have the concept of workspaces.
337 }
338
SetWindowTitle(const base::string16 & title)339 bool DesktopWindowTreeHostWin::SetWindowTitle(const base::string16& title) {
340 return message_handler_->SetTitle(title);
341 }
342
ClearNativeFocus()343 void DesktopWindowTreeHostWin::ClearNativeFocus() {
344 message_handler_->ClearNativeFocus();
345 }
346
RunMoveLoop(const gfx::Vector2d & drag_offset,Widget::MoveLoopSource source,Widget::MoveLoopEscapeBehavior escape_behavior)347 Widget::MoveLoopResult DesktopWindowTreeHostWin::RunMoveLoop(
348 const gfx::Vector2d& drag_offset,
349 Widget::MoveLoopSource source,
350 Widget::MoveLoopEscapeBehavior escape_behavior) {
351 const bool hide_on_escape =
352 escape_behavior == Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE;
353 return message_handler_->RunMoveLoop(drag_offset, hide_on_escape) ?
354 Widget::MOVE_LOOP_SUCCESSFUL : Widget::MOVE_LOOP_CANCELED;
355 }
356
EndMoveLoop()357 void DesktopWindowTreeHostWin::EndMoveLoop() {
358 message_handler_->EndMoveLoop();
359 }
360
SetVisibilityChangedAnimationsEnabled(bool value)361 void DesktopWindowTreeHostWin::SetVisibilityChangedAnimationsEnabled(
362 bool value) {
363 message_handler_->SetVisibilityChangedAnimationsEnabled(value);
364 content_window_->SetProperty(aura::client::kAnimationsDisabledKey, !value);
365 }
366
ShouldUseNativeFrame() const367 bool DesktopWindowTreeHostWin::ShouldUseNativeFrame() const {
368 return IsTranslucentWindowOpacitySupported();
369 }
370
ShouldWindowContentsBeTransparent() const371 bool DesktopWindowTreeHostWin::ShouldWindowContentsBeTransparent() const {
372 // If the window has a native frame, we assume it is an Aero Glass window, and
373 // is therefore transparent. Note: This is not equivalent to calling
374 // IsAeroGlassEnabled, because ShouldUseNativeFrame is overridden in a
375 // subclass.
376 return ShouldUseNativeFrame();
377 }
378
FrameTypeChanged()379 void DesktopWindowTreeHostWin::FrameTypeChanged() {
380 message_handler_->FrameTypeChanged();
381 SetWindowTransparency();
382 }
383
SetFullscreen(bool fullscreen)384 void DesktopWindowTreeHostWin::SetFullscreen(bool fullscreen) {
385 message_handler_->fullscreen_handler()->SetFullscreen(fullscreen);
386 // TODO(sky): workaround for ScopedFullscreenVisibility showing window
387 // directly. Instead of this should listen for visibility changes and then
388 // update window.
389 if (message_handler_->IsVisible() && !content_window_->TargetVisibility())
390 content_window_->Show();
391 SetWindowTransparency();
392 }
393
IsFullscreen() const394 bool DesktopWindowTreeHostWin::IsFullscreen() const {
395 return message_handler_->fullscreen_handler()->fullscreen();
396 }
397
SetOpacity(unsigned char opacity)398 void DesktopWindowTreeHostWin::SetOpacity(unsigned char opacity) {
399 message_handler_->SetOpacity(static_cast<BYTE>(opacity));
400 content_window_->layer()->SetOpacity(opacity / 255.0);
401 }
402
SetWindowIcons(const gfx::ImageSkia & window_icon,const gfx::ImageSkia & app_icon)403 void DesktopWindowTreeHostWin::SetWindowIcons(
404 const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) {
405 message_handler_->SetWindowIcons(window_icon, app_icon);
406 }
407
InitModalType(ui::ModalType modal_type)408 void DesktopWindowTreeHostWin::InitModalType(ui::ModalType modal_type) {
409 message_handler_->InitModalType(modal_type);
410 }
411
FlashFrame(bool flash_frame)412 void DesktopWindowTreeHostWin::FlashFrame(bool flash_frame) {
413 message_handler_->FlashFrame(flash_frame);
414 }
415
OnRootViewLayout() const416 void DesktopWindowTreeHostWin::OnRootViewLayout() const {
417 }
418
OnNativeWidgetFocus()419 void DesktopWindowTreeHostWin::OnNativeWidgetFocus() {
420 // HWNDMessageHandler will perform the proper updating on its own.
421 }
422
OnNativeWidgetBlur()423 void DesktopWindowTreeHostWin::OnNativeWidgetBlur() {
424 }
425
IsAnimatingClosed() const426 bool DesktopWindowTreeHostWin::IsAnimatingClosed() const {
427 return pending_close_;
428 }
429
IsTranslucentWindowOpacitySupported() const430 bool DesktopWindowTreeHostWin::IsTranslucentWindowOpacitySupported() const {
431 return ui::win::IsAeroGlassEnabled();
432 }
433
434 ////////////////////////////////////////////////////////////////////////////////
435 // DesktopWindowTreeHostWin, WindowTreeHost implementation:
436
GetEventSource()437 ui::EventSource* DesktopWindowTreeHostWin::GetEventSource() {
438 return this;
439 }
440
GetAcceleratedWidget()441 gfx::AcceleratedWidget DesktopWindowTreeHostWin::GetAcceleratedWidget() {
442 return message_handler_->hwnd();
443 }
444
Show()445 void DesktopWindowTreeHostWin::Show() {
446 message_handler_->Show();
447 }
448
Hide()449 void DesktopWindowTreeHostWin::Hide() {
450 if (!pending_close_)
451 message_handler_->Hide();
452 }
453
454 // GetBounds and SetBounds work in pixel coordinates, whereas other get/set
455 // methods work in DIP.
456
GetBounds() const457 gfx::Rect DesktopWindowTreeHostWin::GetBounds() const {
458 gfx::Rect bounds(message_handler_->GetClientAreaBounds());
459 // If the window bounds were expanded we need to return the original bounds
460 // To achieve this we do the reverse of the expansion, i.e. add the
461 // window_expansion_top_left_delta_ to the origin and subtract the
462 // window_expansion_bottom_right_delta_ from the width and height.
463 gfx::Rect without_expansion(
464 bounds.x() + window_expansion_top_left_delta_.x(),
465 bounds.y() + window_expansion_top_left_delta_.y(),
466 bounds.width() - window_expansion_bottom_right_delta_.x() -
467 window_enlargement_.x(),
468 bounds.height() - window_expansion_bottom_right_delta_.y() -
469 window_enlargement_.y());
470 return without_expansion;
471 }
472
SetBounds(const gfx::Rect & bounds)473 void DesktopWindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
474 // If the window bounds have to be expanded we need to subtract the
475 // window_expansion_top_left_delta_ from the origin and add the
476 // window_expansion_bottom_right_delta_ to the width and height
477 gfx::Size old_hwnd_size(message_handler_->GetClientAreaBounds().size());
478 gfx::Size old_content_size = GetBounds().size();
479
480 gfx::Rect expanded(
481 bounds.x() - window_expansion_top_left_delta_.x(),
482 bounds.y() - window_expansion_top_left_delta_.y(),
483 bounds.width() + window_expansion_bottom_right_delta_.x(),
484 bounds.height() + window_expansion_bottom_right_delta_.y());
485
486 gfx::Rect new_expanded(
487 expanded.origin(),
488 GetExpandedWindowSize(message_handler_->window_ex_style(),
489 expanded.size()));
490 window_enlargement_ =
491 gfx::Vector2d(new_expanded.width() - expanded.width(),
492 new_expanded.height() - expanded.height());
493 message_handler_->SetBounds(new_expanded, old_content_size != bounds.size());
494 }
495
GetLocationOnNativeScreen() const496 gfx::Point DesktopWindowTreeHostWin::GetLocationOnNativeScreen() const {
497 return GetBounds().origin();
498 }
499
SetCapture()500 void DesktopWindowTreeHostWin::SetCapture() {
501 message_handler_->SetCapture();
502 }
503
ReleaseCapture()504 void DesktopWindowTreeHostWin::ReleaseCapture() {
505 message_handler_->ReleaseCapture();
506 }
507
PostNativeEvent(const base::NativeEvent & native_event)508 void DesktopWindowTreeHostWin::PostNativeEvent(
509 const base::NativeEvent& native_event) {
510 }
511
OnDeviceScaleFactorChanged(float device_scale_factor)512 void DesktopWindowTreeHostWin::OnDeviceScaleFactorChanged(
513 float device_scale_factor) {
514 }
515
SetCursorNative(gfx::NativeCursor cursor)516 void DesktopWindowTreeHostWin::SetCursorNative(gfx::NativeCursor cursor) {
517 ui::CursorLoaderWin cursor_loader;
518 cursor_loader.SetPlatformCursor(&cursor);
519
520 message_handler_->SetCursor(cursor.platform());
521 }
522
OnCursorVisibilityChangedNative(bool show)523 void DesktopWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
524 if (is_cursor_visible_ == show)
525 return;
526 is_cursor_visible_ = show;
527 ::ShowCursor(!!show);
528 }
529
MoveCursorToNative(const gfx::Point & location)530 void DesktopWindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
531 POINT cursor_location = location.ToPOINT();
532 ::ClientToScreen(GetHWND(), &cursor_location);
533 ::SetCursorPos(cursor_location.x, cursor_location.y);
534 }
535
536 ////////////////////////////////////////////////////////////////////////////////
537 // DesktopWindowTreeHostWin, ui::EventSource implementation:
538
GetEventProcessor()539 ui::EventProcessor* DesktopWindowTreeHostWin::GetEventProcessor() {
540 return dispatcher();
541 }
542
543 ////////////////////////////////////////////////////////////////////////////////
544 // DesktopWindowTreeHostWin, aura::AnimationHost implementation:
545
SetHostTransitionOffsets(const gfx::Vector2d & top_left_delta,const gfx::Vector2d & bottom_right_delta)546 void DesktopWindowTreeHostWin::SetHostTransitionOffsets(
547 const gfx::Vector2d& top_left_delta,
548 const gfx::Vector2d& bottom_right_delta) {
549 gfx::Rect bounds_without_expansion = GetBounds();
550 window_expansion_top_left_delta_ = top_left_delta;
551 window_expansion_bottom_right_delta_ = bottom_right_delta;
552 SetBounds(bounds_without_expansion);
553 }
554
OnWindowHidingAnimationCompleted()555 void DesktopWindowTreeHostWin::OnWindowHidingAnimationCompleted() {
556 if (pending_close_)
557 message_handler_->Close();
558 }
559
560 ////////////////////////////////////////////////////////////////////////////////
561 // DesktopWindowTreeHostWin, HWNDMessageHandlerDelegate implementation:
562
IsWidgetWindow() const563 bool DesktopWindowTreeHostWin::IsWidgetWindow() const {
564 return has_non_client_view_;
565 }
566
IsUsingCustomFrame() const567 bool DesktopWindowTreeHostWin::IsUsingCustomFrame() const {
568 return !GetWidget()->ShouldUseNativeFrame();
569 }
570
SchedulePaint()571 void DesktopWindowTreeHostWin::SchedulePaint() {
572 GetWidget()->GetRootView()->SchedulePaint();
573 }
574
EnableInactiveRendering()575 void DesktopWindowTreeHostWin::EnableInactiveRendering() {
576 native_widget_delegate_->EnableInactiveRendering();
577 }
578
IsInactiveRenderingDisabled()579 bool DesktopWindowTreeHostWin::IsInactiveRenderingDisabled() {
580 return native_widget_delegate_->IsInactiveRenderingDisabled();
581 }
582
CanResize() const583 bool DesktopWindowTreeHostWin::CanResize() const {
584 return GetWidget()->widget_delegate()->CanResize();
585 }
586
CanMaximize() const587 bool DesktopWindowTreeHostWin::CanMaximize() const {
588 return GetWidget()->widget_delegate()->CanMaximize();
589 }
590
CanActivate() const591 bool DesktopWindowTreeHostWin::CanActivate() const {
592 if (IsModalWindowActive())
593 return true;
594 return native_widget_delegate_->CanActivate();
595 }
596
WidgetSizeIsClientSize() const597 bool DesktopWindowTreeHostWin::WidgetSizeIsClientSize() const {
598 const Widget* widget = GetWidget()->GetTopLevelWidget();
599 return IsMaximized() || (widget && widget->ShouldUseNativeFrame());
600 }
601
IsModal() const602 bool DesktopWindowTreeHostWin::IsModal() const {
603 return native_widget_delegate_->IsModal();
604 }
605
GetInitialShowState() const606 int DesktopWindowTreeHostWin::GetInitialShowState() const {
607 return CanActivate() ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
608 }
609
WillProcessWorkAreaChange() const610 bool DesktopWindowTreeHostWin::WillProcessWorkAreaChange() const {
611 return GetWidget()->widget_delegate()->WillProcessWorkAreaChange();
612 }
613
GetNonClientComponent(const gfx::Point & point) const614 int DesktopWindowTreeHostWin::GetNonClientComponent(
615 const gfx::Point& point) const {
616 gfx::Point dip_position = gfx::win::ScreenToDIPPoint(point);
617 return native_widget_delegate_->GetNonClientComponent(dip_position);
618 }
619
GetWindowMask(const gfx::Size & size,gfx::Path * path)620 void DesktopWindowTreeHostWin::GetWindowMask(const gfx::Size& size,
621 gfx::Path* path) {
622 if (GetWidget()->non_client_view()) {
623 GetWidget()->non_client_view()->GetWindowMask(size, path);
624 } else if (!window_enlargement_.IsZero()) {
625 gfx::Rect bounds(WidgetSizeIsClientSize()
626 ? message_handler_->GetClientAreaBoundsInScreen()
627 : message_handler_->GetWindowBoundsInScreen());
628 InsetBottomRight(&bounds, window_enlargement_);
629 path->addRect(SkRect::MakeXYWH(0, 0, bounds.width(), bounds.height()));
630 }
631 }
632
GetClientAreaInsets(gfx::Insets * insets) const633 bool DesktopWindowTreeHostWin::GetClientAreaInsets(gfx::Insets* insets) const {
634 return false;
635 }
636
GetMinMaxSize(gfx::Size * min_size,gfx::Size * max_size) const637 void DesktopWindowTreeHostWin::GetMinMaxSize(gfx::Size* min_size,
638 gfx::Size* max_size) const {
639 *min_size = native_widget_delegate_->GetMinimumSize();
640 *max_size = native_widget_delegate_->GetMaximumSize();
641 }
642
GetRootViewSize() const643 gfx::Size DesktopWindowTreeHostWin::GetRootViewSize() const {
644 return GetWidget()->GetRootView()->size();
645 }
646
ResetWindowControls()647 void DesktopWindowTreeHostWin::ResetWindowControls() {
648 GetWidget()->non_client_view()->ResetWindowControls();
649 }
650
PaintLayeredWindow(gfx::Canvas * canvas)651 void DesktopWindowTreeHostWin::PaintLayeredWindow(gfx::Canvas* canvas) {
652 GetWidget()->GetRootView()->Paint(canvas, views::CullSet());
653 }
654
GetNativeViewAccessible()655 gfx::NativeViewAccessible DesktopWindowTreeHostWin::GetNativeViewAccessible() {
656 return GetWidget()->GetRootView()->GetNativeViewAccessible();
657 }
658
GetInputMethod()659 InputMethod* DesktopWindowTreeHostWin::GetInputMethod() {
660 return GetWidget()->GetInputMethodDirect();
661 }
662
ShouldHandleSystemCommands() const663 bool DesktopWindowTreeHostWin::ShouldHandleSystemCommands() const {
664 return GetWidget()->widget_delegate()->ShouldHandleSystemCommands();
665 }
666
HandleAppDeactivated()667 void DesktopWindowTreeHostWin::HandleAppDeactivated() {
668 native_widget_delegate_->EnableInactiveRendering();
669 }
670
HandleActivationChanged(bool active)671 void DesktopWindowTreeHostWin::HandleActivationChanged(bool active) {
672 // This can be invoked from HWNDMessageHandler::Init(), at which point we're
673 // not in a good state and need to ignore it.
674 // TODO(beng): Do we need this still now the host owns the dispatcher?
675 if (!dispatcher())
676 return;
677
678 if (active)
679 OnHostActivated();
680 desktop_native_widget_aura_->HandleActivationChanged(active);
681 }
682
HandleAppCommand(short command)683 bool DesktopWindowTreeHostWin::HandleAppCommand(short command) {
684 // We treat APPCOMMAND ids as an extension of our command namespace, and just
685 // let the delegate figure out what to do...
686 return GetWidget()->widget_delegate() &&
687 GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
688 }
689
HandleCancelMode()690 void DesktopWindowTreeHostWin::HandleCancelMode() {
691 dispatcher()->DispatchCancelModeEvent();
692 }
693
HandleCaptureLost()694 void DesktopWindowTreeHostWin::HandleCaptureLost() {
695 OnHostLostWindowCapture();
696 native_widget_delegate_->OnMouseCaptureLost();
697 }
698
HandleClose()699 void DesktopWindowTreeHostWin::HandleClose() {
700 GetWidget()->Close();
701 }
702
HandleCommand(int command)703 bool DesktopWindowTreeHostWin::HandleCommand(int command) {
704 return GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
705 }
706
HandleAccelerator(const ui::Accelerator & accelerator)707 void DesktopWindowTreeHostWin::HandleAccelerator(
708 const ui::Accelerator& accelerator) {
709 GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator);
710 }
711
HandleCreate()712 void DesktopWindowTreeHostWin::HandleCreate() {
713 native_widget_delegate_->OnNativeWidgetCreated(true);
714 }
715
HandleDestroying()716 void DesktopWindowTreeHostWin::HandleDestroying() {
717 drag_drop_client_->OnNativeWidgetDestroying(GetHWND());
718 native_widget_delegate_->OnNativeWidgetDestroying();
719
720 // Destroy the compositor before destroying the HWND since shutdown
721 // may try to swap to the window.
722 DestroyCompositor();
723 }
724
HandleDestroyed()725 void DesktopWindowTreeHostWin::HandleDestroyed() {
726 desktop_native_widget_aura_->OnHostClosed();
727 }
728
HandleInitialFocus(ui::WindowShowState show_state)729 bool DesktopWindowTreeHostWin::HandleInitialFocus(
730 ui::WindowShowState show_state) {
731 return GetWidget()->SetInitialFocus(show_state);
732 }
733
HandleDisplayChange()734 void DesktopWindowTreeHostWin::HandleDisplayChange() {
735 GetWidget()->widget_delegate()->OnDisplayChanged();
736 }
737
HandleBeginWMSizeMove()738 void DesktopWindowTreeHostWin::HandleBeginWMSizeMove() {
739 native_widget_delegate_->OnNativeWidgetBeginUserBoundsChange();
740 }
741
HandleEndWMSizeMove()742 void DesktopWindowTreeHostWin::HandleEndWMSizeMove() {
743 native_widget_delegate_->OnNativeWidgetEndUserBoundsChange();
744 }
745
HandleMove()746 void DesktopWindowTreeHostWin::HandleMove() {
747 native_widget_delegate_->OnNativeWidgetMove();
748 OnHostMoved(GetBounds().origin());
749 }
750
HandleWorkAreaChanged()751 void DesktopWindowTreeHostWin::HandleWorkAreaChanged() {
752 GetWidget()->widget_delegate()->OnWorkAreaChanged();
753 }
754
HandleVisibilityChanging(bool visible)755 void DesktopWindowTreeHostWin::HandleVisibilityChanging(bool visible) {
756 native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible);
757 }
758
HandleVisibilityChanged(bool visible)759 void DesktopWindowTreeHostWin::HandleVisibilityChanged(bool visible) {
760 native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
761 }
762
HandleClientSizeChanged(const gfx::Size & new_size)763 void DesktopWindowTreeHostWin::HandleClientSizeChanged(
764 const gfx::Size& new_size) {
765 if (dispatcher())
766 OnHostResized(new_size);
767 }
768
HandleFrameChanged()769 void DesktopWindowTreeHostWin::HandleFrameChanged() {
770 SetWindowTransparency();
771 // Replace the frame and layout the contents.
772 GetWidget()->non_client_view()->UpdateFrame();
773 }
774
HandleNativeFocus(HWND last_focused_window)775 void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) {
776 // TODO(beng): inform the native_widget_delegate_.
777 InputMethod* input_method = GetInputMethod();
778 if (input_method)
779 input_method->OnFocus();
780 }
781
HandleNativeBlur(HWND focused_window)782 void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) {
783 // TODO(beng): inform the native_widget_delegate_.
784 InputMethod* input_method = GetInputMethod();
785 if (input_method)
786 input_method->OnBlur();
787 }
788
HandleMouseEvent(const ui::MouseEvent & event)789 bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) {
790 SendEventToProcessor(const_cast<ui::MouseEvent*>(&event));
791 return event.handled();
792 }
793
HandleKeyEvent(const ui::KeyEvent & event)794 bool DesktopWindowTreeHostWin::HandleKeyEvent(const ui::KeyEvent& event) {
795 return false;
796 }
797
HandleUntranslatedKeyEvent(const ui::KeyEvent & event)798 bool DesktopWindowTreeHostWin::HandleUntranslatedKeyEvent(
799 const ui::KeyEvent& event) {
800 ui::KeyEvent duplicate_event(event);
801 SendEventToProcessor(&duplicate_event);
802 return duplicate_event.handled();
803 }
804
HandleTouchEvent(const ui::TouchEvent & event)805 void DesktopWindowTreeHostWin::HandleTouchEvent(
806 const ui::TouchEvent& event) {
807 // HWNDMessageHandler asynchronously processes touch events. Because of this
808 // it's possible for the aura::WindowEventDispatcher to have been destroyed
809 // by the time we attempt to process them.
810 if (!GetWidget()->GetNativeView())
811 return;
812
813 // Currently we assume the window that has capture gets touch events too.
814 aura::WindowTreeHost* host =
815 aura::WindowTreeHost::GetForAcceleratedWidget(GetCapture());
816 if (host) {
817 DesktopWindowTreeHostWin* target =
818 host->window()->GetProperty(kDesktopWindowTreeHostKey);
819 if (target && target->HasCapture() && target != this) {
820 POINT target_location(event.location().ToPOINT());
821 ClientToScreen(GetHWND(), &target_location);
822 ScreenToClient(target->GetHWND(), &target_location);
823 ui::TouchEvent target_event(event, static_cast<View*>(NULL),
824 static_cast<View*>(NULL));
825 target_event.set_location(gfx::Point(target_location));
826 target_event.set_root_location(target_event.location());
827 target->SendEventToProcessor(&target_event);
828 return;
829 }
830 }
831 SendEventToProcessor(const_cast<ui::TouchEvent*>(&event));
832 }
833
HandleIMEMessage(UINT message,WPARAM w_param,LPARAM l_param,LRESULT * result)834 bool DesktopWindowTreeHostWin::HandleIMEMessage(UINT message,
835 WPARAM w_param,
836 LPARAM l_param,
837 LRESULT* result) {
838 MSG msg = {};
839 msg.hwnd = GetHWND();
840 msg.message = message;
841 msg.wParam = w_param;
842 msg.lParam = l_param;
843 return desktop_native_widget_aura_->input_method_event_filter()->
844 input_method()->OnUntranslatedIMEMessage(msg, result);
845 }
846
HandleInputLanguageChange(DWORD character_set,HKL input_language_id)847 void DesktopWindowTreeHostWin::HandleInputLanguageChange(
848 DWORD character_set,
849 HKL input_language_id) {
850 desktop_native_widget_aura_->input_method_event_filter()->
851 input_method()->OnInputLocaleChanged();
852 }
853
HandlePaintAccelerated(const gfx::Rect & invalid_rect)854 bool DesktopWindowTreeHostWin::HandlePaintAccelerated(
855 const gfx::Rect& invalid_rect) {
856 return native_widget_delegate_->OnNativeWidgetPaintAccelerated(invalid_rect);
857 }
858
HandlePaint(gfx::Canvas * canvas)859 void DesktopWindowTreeHostWin::HandlePaint(gfx::Canvas* canvas) {
860 // It appears possible to get WM_PAINT after WM_DESTROY.
861 if (compositor())
862 compositor()->ScheduleRedrawRect(gfx::Rect());
863 }
864
HandleTooltipNotify(int w_param,NMHDR * l_param,LRESULT * l_result)865 bool DesktopWindowTreeHostWin::HandleTooltipNotify(int w_param,
866 NMHDR* l_param,
867 LRESULT* l_result) {
868 return tooltip_ && tooltip_->HandleNotify(w_param, l_param, l_result);
869 }
870
HandleTooltipMouseMove(UINT message,WPARAM w_param,LPARAM l_param)871 void DesktopWindowTreeHostWin::HandleTooltipMouseMove(UINT message,
872 WPARAM w_param,
873 LPARAM l_param) {
874 // TooltipWin implementation doesn't need this.
875 // TODO(sky): remove from HWNDMessageHandler once non-aura path nuked.
876 }
877
HandleMenuLoop(bool in_menu_loop)878 void DesktopWindowTreeHostWin::HandleMenuLoop(bool in_menu_loop) {
879 if (in_menu_loop) {
880 tooltip_disabler_.reset(
881 new aura::client::ScopedTooltipDisabler(window()));
882 } else {
883 tooltip_disabler_.reset();
884 }
885 }
886
PreHandleMSG(UINT message,WPARAM w_param,LPARAM l_param,LRESULT * result)887 bool DesktopWindowTreeHostWin::PreHandleMSG(UINT message,
888 WPARAM w_param,
889 LPARAM l_param,
890 LRESULT* result) {
891 return false;
892 }
893
PostHandleMSG(UINT message,WPARAM w_param,LPARAM l_param)894 void DesktopWindowTreeHostWin::PostHandleMSG(UINT message,
895 WPARAM w_param,
896 LPARAM l_param) {
897 }
898
HandleScrollEvent(const ui::ScrollEvent & event)899 bool DesktopWindowTreeHostWin::HandleScrollEvent(
900 const ui::ScrollEvent& event) {
901 SendEventToProcessor(const_cast<ui::ScrollEvent*>(&event));
902 return event.handled();
903 }
904
HandleWindowSizeChanging()905 void DesktopWindowTreeHostWin::HandleWindowSizeChanging() {
906 if (compositor())
907 compositor()->FinishAllRendering();
908 }
909
910 ////////////////////////////////////////////////////////////////////////////////
911 // DesktopWindowTreeHostWin, private:
912
GetWidget()913 Widget* DesktopWindowTreeHostWin::GetWidget() {
914 return native_widget_delegate_->AsWidget();
915 }
916
GetWidget() const917 const Widget* DesktopWindowTreeHostWin::GetWidget() const {
918 return native_widget_delegate_->AsWidget();
919 }
920
GetHWND() const921 HWND DesktopWindowTreeHostWin::GetHWND() const {
922 return message_handler_->hwnd();
923 }
924
SetWindowTransparency()925 void DesktopWindowTreeHostWin::SetWindowTransparency() {
926 bool transparent = ShouldUseNativeFrame() && !IsFullscreen();
927 compositor()->SetHostHasTransparentBackground(transparent);
928 window()->SetTransparent(transparent);
929 content_window_->SetTransparent(transparent);
930 }
931
IsModalWindowActive() const932 bool DesktopWindowTreeHostWin::IsModalWindowActive() const {
933 // This function can get called during window creation which occurs before
934 // dispatcher() has been created.
935 if (!dispatcher())
936 return false;
937
938 aura::Window::Windows::const_iterator index;
939 for (index = window()->children().begin();
940 index != window()->children().end();
941 ++index) {
942 if ((*index)->GetProperty(aura::client::kModalKey) !=
943 ui:: MODAL_TYPE_NONE && (*index)->TargetVisibility())
944 return true;
945 }
946 return false;
947 }
948
949 ////////////////////////////////////////////////////////////////////////////////
950 // DesktopWindowTreeHost, public:
951
952 // static
Create(internal::NativeWidgetDelegate * native_widget_delegate,DesktopNativeWidgetAura * desktop_native_widget_aura)953 DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
954 internal::NativeWidgetDelegate* native_widget_delegate,
955 DesktopNativeWidgetAura* desktop_native_widget_aura) {
956 return new DesktopWindowTreeHostWin(native_widget_delegate,
957 desktop_native_widget_aura);
958 }
959
960 } // namespace views
961