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