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 message_handler_->SetRegion(gfx::CreateHRGNFromSkRegion(*native_region)); 284 } else { 285 message_handler_->SetRegion(NULL); 286 } 287 288 delete native_region; 289 } 290 291 void DesktopWindowTreeHostWin::Activate() { 292 message_handler_->Activate(); 293 } 294 295 void DesktopWindowTreeHostWin::Deactivate() { 296 message_handler_->Deactivate(); 297 } 298 299 bool DesktopWindowTreeHostWin::IsActive() const { 300 return message_handler_->IsActive(); 301 } 302 303 void DesktopWindowTreeHostWin::Maximize() { 304 message_handler_->Maximize(); 305 } 306 307 void DesktopWindowTreeHostWin::Minimize() { 308 message_handler_->Minimize(); 309 } 310 311 void DesktopWindowTreeHostWin::Restore() { 312 message_handler_->Restore(); 313 } 314 315 bool DesktopWindowTreeHostWin::IsMaximized() const { 316 return message_handler_->IsMaximized(); 317 } 318 319 bool DesktopWindowTreeHostWin::IsMinimized() const { 320 return message_handler_->IsMinimized(); 321 } 322 323 bool DesktopWindowTreeHostWin::HasCapture() const { 324 return message_handler_->HasCapture(); 325 } 326 327 void DesktopWindowTreeHostWin::SetAlwaysOnTop(bool always_on_top) { 328 message_handler_->SetAlwaysOnTop(always_on_top); 329 } 330 331 bool DesktopWindowTreeHostWin::IsAlwaysOnTop() const { 332 return message_handler_->IsAlwaysOnTop(); 333 } 334 335 void DesktopWindowTreeHostWin::SetVisibleOnAllWorkspaces(bool always_visible) { 336 // Windows does not have the concept of workspaces. 337 } 338 339 bool DesktopWindowTreeHostWin::SetWindowTitle(const base::string16& title) { 340 return message_handler_->SetTitle(title); 341 } 342 343 void DesktopWindowTreeHostWin::ClearNativeFocus() { 344 message_handler_->ClearNativeFocus(); 345 } 346 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 357 void DesktopWindowTreeHostWin::EndMoveLoop() { 358 message_handler_->EndMoveLoop(); 359 } 360 361 void DesktopWindowTreeHostWin::SetVisibilityChangedAnimationsEnabled( 362 bool value) { 363 message_handler_->SetVisibilityChangedAnimationsEnabled(value); 364 content_window_->SetProperty(aura::client::kAnimationsDisabledKey, !value); 365 } 366 367 bool DesktopWindowTreeHostWin::ShouldUseNativeFrame() const { 368 return IsTranslucentWindowOpacitySupported(); 369 } 370 371 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 379 void DesktopWindowTreeHostWin::FrameTypeChanged() { 380 message_handler_->FrameTypeChanged(); 381 SetWindowTransparency(); 382 } 383 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 394 bool DesktopWindowTreeHostWin::IsFullscreen() const { 395 return message_handler_->fullscreen_handler()->fullscreen(); 396 } 397 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 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 408 void DesktopWindowTreeHostWin::InitModalType(ui::ModalType modal_type) { 409 message_handler_->InitModalType(modal_type); 410 } 411 412 void DesktopWindowTreeHostWin::FlashFrame(bool flash_frame) { 413 message_handler_->FlashFrame(flash_frame); 414 } 415 416 void DesktopWindowTreeHostWin::OnRootViewLayout() const { 417 } 418 419 void DesktopWindowTreeHostWin::OnNativeWidgetFocus() { 420 // HWNDMessageHandler will perform the proper updating on its own. 421 } 422 423 void DesktopWindowTreeHostWin::OnNativeWidgetBlur() { 424 } 425 426 bool DesktopWindowTreeHostWin::IsAnimatingClosed() const { 427 return pending_close_; 428 } 429 430 bool DesktopWindowTreeHostWin::IsTranslucentWindowOpacitySupported() const { 431 return ui::win::IsAeroGlassEnabled(); 432 } 433 434 //////////////////////////////////////////////////////////////////////////////// 435 // DesktopWindowTreeHostWin, WindowTreeHost implementation: 436 437 ui::EventSource* DesktopWindowTreeHostWin::GetEventSource() { 438 return this; 439 } 440 441 gfx::AcceleratedWidget DesktopWindowTreeHostWin::GetAcceleratedWidget() { 442 return message_handler_->hwnd(); 443 } 444 445 void DesktopWindowTreeHostWin::Show() { 446 message_handler_->Show(); 447 } 448 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 457 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 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 496 gfx::Point DesktopWindowTreeHostWin::GetLocationOnNativeScreen() const { 497 return GetBounds().origin(); 498 } 499 500 void DesktopWindowTreeHostWin::SetCapture() { 501 message_handler_->SetCapture(); 502 } 503 504 void DesktopWindowTreeHostWin::ReleaseCapture() { 505 message_handler_->ReleaseCapture(); 506 } 507 508 void DesktopWindowTreeHostWin::PostNativeEvent( 509 const base::NativeEvent& native_event) { 510 } 511 512 void DesktopWindowTreeHostWin::OnDeviceScaleFactorChanged( 513 float device_scale_factor) { 514 } 515 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 523 void DesktopWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) { 524 if (is_cursor_visible_ == show) 525 return; 526 is_cursor_visible_ = show; 527 ::ShowCursor(!!show); 528 } 529 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 539 ui::EventProcessor* DesktopWindowTreeHostWin::GetEventProcessor() { 540 return dispatcher(); 541 } 542 543 //////////////////////////////////////////////////////////////////////////////// 544 // DesktopWindowTreeHostWin, aura::AnimationHost implementation: 545 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 555 void DesktopWindowTreeHostWin::OnWindowHidingAnimationCompleted() { 556 if (pending_close_) 557 message_handler_->Close(); 558 } 559 560 //////////////////////////////////////////////////////////////////////////////// 561 // DesktopWindowTreeHostWin, HWNDMessageHandlerDelegate implementation: 562 563 bool DesktopWindowTreeHostWin::IsWidgetWindow() const { 564 return has_non_client_view_; 565 } 566 567 bool DesktopWindowTreeHostWin::IsUsingCustomFrame() const { 568 return !GetWidget()->ShouldUseNativeFrame(); 569 } 570 571 void DesktopWindowTreeHostWin::SchedulePaint() { 572 GetWidget()->GetRootView()->SchedulePaint(); 573 } 574 575 void DesktopWindowTreeHostWin::EnableInactiveRendering() { 576 native_widget_delegate_->EnableInactiveRendering(); 577 } 578 579 bool DesktopWindowTreeHostWin::IsInactiveRenderingDisabled() { 580 return native_widget_delegate_->IsInactiveRenderingDisabled(); 581 } 582 583 bool DesktopWindowTreeHostWin::CanResize() const { 584 return GetWidget()->widget_delegate()->CanResize(); 585 } 586 587 bool DesktopWindowTreeHostWin::CanMaximize() const { 588 return GetWidget()->widget_delegate()->CanMaximize(); 589 } 590 591 bool DesktopWindowTreeHostWin::CanActivate() const { 592 if (IsModalWindowActive()) 593 return true; 594 return native_widget_delegate_->CanActivate(); 595 } 596 597 bool DesktopWindowTreeHostWin::WidgetSizeIsClientSize() const { 598 const Widget* widget = GetWidget()->GetTopLevelWidget(); 599 return IsMaximized() || (widget && widget->ShouldUseNativeFrame()); 600 } 601 602 bool DesktopWindowTreeHostWin::IsModal() const { 603 return native_widget_delegate_->IsModal(); 604 } 605 606 int DesktopWindowTreeHostWin::GetInitialShowState() const { 607 return CanActivate() ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE; 608 } 609 610 bool DesktopWindowTreeHostWin::WillProcessWorkAreaChange() const { 611 return GetWidget()->widget_delegate()->WillProcessWorkAreaChange(); 612 } 613 614 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 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 633 bool DesktopWindowTreeHostWin::GetClientAreaInsets(gfx::Insets* insets) const { 634 return false; 635 } 636 637 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 643 gfx::Size DesktopWindowTreeHostWin::GetRootViewSize() const { 644 return GetWidget()->GetRootView()->size(); 645 } 646 647 void DesktopWindowTreeHostWin::ResetWindowControls() { 648 GetWidget()->non_client_view()->ResetWindowControls(); 649 } 650 651 void DesktopWindowTreeHostWin::PaintLayeredWindow(gfx::Canvas* canvas) { 652 GetWidget()->GetRootView()->Paint(canvas, views::CullSet()); 653 } 654 655 gfx::NativeViewAccessible DesktopWindowTreeHostWin::GetNativeViewAccessible() { 656 return GetWidget()->GetRootView()->GetNativeViewAccessible(); 657 } 658 659 InputMethod* DesktopWindowTreeHostWin::GetInputMethod() { 660 return GetWidget()->GetInputMethodDirect(); 661 } 662 663 bool DesktopWindowTreeHostWin::ShouldHandleSystemCommands() const { 664 return GetWidget()->widget_delegate()->ShouldHandleSystemCommands(); 665 } 666 667 void DesktopWindowTreeHostWin::HandleAppDeactivated() { 668 native_widget_delegate_->EnableInactiveRendering(); 669 } 670 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 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 690 void DesktopWindowTreeHostWin::HandleCancelMode() { 691 dispatcher()->DispatchCancelModeEvent(); 692 } 693 694 void DesktopWindowTreeHostWin::HandleCaptureLost() { 695 OnHostLostWindowCapture(); 696 native_widget_delegate_->OnMouseCaptureLost(); 697 } 698 699 void DesktopWindowTreeHostWin::HandleClose() { 700 GetWidget()->Close(); 701 } 702 703 bool DesktopWindowTreeHostWin::HandleCommand(int command) { 704 return GetWidget()->widget_delegate()->ExecuteWindowsCommand(command); 705 } 706 707 void DesktopWindowTreeHostWin::HandleAccelerator( 708 const ui::Accelerator& accelerator) { 709 GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator); 710 } 711 712 void DesktopWindowTreeHostWin::HandleCreate() { 713 native_widget_delegate_->OnNativeWidgetCreated(true); 714 } 715 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 725 void DesktopWindowTreeHostWin::HandleDestroyed() { 726 desktop_native_widget_aura_->OnHostClosed(); 727 } 728 729 bool DesktopWindowTreeHostWin::HandleInitialFocus( 730 ui::WindowShowState show_state) { 731 return GetWidget()->SetInitialFocus(show_state); 732 } 733 734 void DesktopWindowTreeHostWin::HandleDisplayChange() { 735 GetWidget()->widget_delegate()->OnDisplayChanged(); 736 } 737 738 void DesktopWindowTreeHostWin::HandleBeginWMSizeMove() { 739 native_widget_delegate_->OnNativeWidgetBeginUserBoundsChange(); 740 } 741 742 void DesktopWindowTreeHostWin::HandleEndWMSizeMove() { 743 native_widget_delegate_->OnNativeWidgetEndUserBoundsChange(); 744 } 745 746 void DesktopWindowTreeHostWin::HandleMove() { 747 native_widget_delegate_->OnNativeWidgetMove(); 748 OnHostMoved(GetBounds().origin()); 749 } 750 751 void DesktopWindowTreeHostWin::HandleWorkAreaChanged() { 752 GetWidget()->widget_delegate()->OnWorkAreaChanged(); 753 } 754 755 void DesktopWindowTreeHostWin::HandleVisibilityChanging(bool visible) { 756 native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible); 757 } 758 759 void DesktopWindowTreeHostWin::HandleVisibilityChanged(bool visible) { 760 native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible); 761 } 762 763 void DesktopWindowTreeHostWin::HandleClientSizeChanged( 764 const gfx::Size& new_size) { 765 if (dispatcher()) 766 OnHostResized(new_size); 767 } 768 769 void DesktopWindowTreeHostWin::HandleFrameChanged() { 770 SetWindowTransparency(); 771 // Replace the frame and layout the contents. 772 GetWidget()->non_client_view()->UpdateFrame(); 773 } 774 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 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 789 bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) { 790 SendEventToProcessor(const_cast<ui::MouseEvent*>(&event)); 791 return event.handled(); 792 } 793 794 bool DesktopWindowTreeHostWin::HandleKeyEvent(const ui::KeyEvent& event) { 795 return false; 796 } 797 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 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 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 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 854 bool DesktopWindowTreeHostWin::HandlePaintAccelerated( 855 const gfx::Rect& invalid_rect) { 856 return native_widget_delegate_->OnNativeWidgetPaintAccelerated(invalid_rect); 857 } 858 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 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 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 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 887 bool DesktopWindowTreeHostWin::PreHandleMSG(UINT message, 888 WPARAM w_param, 889 LPARAM l_param, 890 LRESULT* result) { 891 return false; 892 } 893 894 void DesktopWindowTreeHostWin::PostHandleMSG(UINT message, 895 WPARAM w_param, 896 LPARAM l_param) { 897 } 898 899 bool DesktopWindowTreeHostWin::HandleScrollEvent( 900 const ui::ScrollEvent& event) { 901 SendEventToProcessor(const_cast<ui::ScrollEvent*>(&event)); 902 return event.handled(); 903 } 904 905 void DesktopWindowTreeHostWin::HandleWindowSizeChanging() { 906 if (compositor()) 907 compositor()->FinishAllRendering(); 908 } 909 910 //////////////////////////////////////////////////////////////////////////////// 911 // DesktopWindowTreeHostWin, private: 912 913 Widget* DesktopWindowTreeHostWin::GetWidget() { 914 return native_widget_delegate_->AsWidget(); 915 } 916 917 const Widget* DesktopWindowTreeHostWin::GetWidget() const { 918 return native_widget_delegate_->AsWidget(); 919 } 920 921 HWND DesktopWindowTreeHostWin::GetHWND() const { 922 return message_handler_->hwnd(); 923 } 924 925 void DesktopWindowTreeHostWin::SetWindowTransparency() { 926 bool transparent = ShouldUseNativeFrame() && !IsFullscreen(); 927 compositor()->SetHostHasTransparentBackground(transparent); 928 window()->SetTransparent(transparent); 929 content_window_->SetTransparent(transparent); 930 } 931 932 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 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