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