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 43namespace views { 44 45namespace { 46 47gfx::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 57void InsetBottomRight(gfx::Rect* rect, gfx::Vector2d vector) { 58 rect->Inset(0, 0, vector.x(), vector.y()); 59} 60 61} // namespace 62 63DEFINE_WINDOW_PROPERTY_KEY(aura::Window*, kContentWindowForRootWindow, NULL); 64 65// Identifies the DesktopWindowTreeHostWin associated with the 66// WindowEventDispatcher. 67DEFINE_WINDOW_PROPERTY_KEY(DesktopWindowTreeHostWin*, kDesktopWindowTreeHostKey, 68 NULL); 69 70//////////////////////////////////////////////////////////////////////////////// 71// DesktopWindowTreeHostWin, public: 72 73bool DesktopWindowTreeHostWin::is_cursor_visible_ = true; 74 75DesktopWindowTreeHostWin::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 91DesktopWindowTreeHostWin::~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 98aura::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 105ui::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 122void 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 151void 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 170scoped_ptr<corewm::Tooltip> DesktopWindowTreeHostWin::CreateTooltip() { 171 DCHECK(!tooltip_); 172 tooltip_ = new corewm::TooltipWin(GetAcceleratedWidget()); 173 return scoped_ptr<corewm::Tooltip>(tooltip_); 174} 175 176scoped_ptr<aura::client::DragDropClient> 177DesktopWindowTreeHostWin::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 183void 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 199void DesktopWindowTreeHostWin::CloseNow() { 200 message_handler_->CloseNow(); 201} 202 203aura::WindowTreeHost* DesktopWindowTreeHostWin::AsWindowTreeHost() { 204 return this; 205} 206 207void DesktopWindowTreeHostWin::ShowWindowWithState( 208 ui::WindowShowState show_state) { 209 message_handler_->ShowWindowWithState(show_state); 210} 211 212void 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 218bool DesktopWindowTreeHostWin::IsVisible() const { 219 return message_handler_->IsVisible(); 220} 221 222void 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 232void DesktopWindowTreeHostWin::StackAtTop() { 233 message_handler_->StackAtTop(); 234} 235 236void 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 247void 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 255gfx::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 261gfx::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 267gfx::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 273gfx::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 283void 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 314void DesktopWindowTreeHostWin::Activate() { 315 message_handler_->Activate(); 316} 317 318void DesktopWindowTreeHostWin::Deactivate() { 319 message_handler_->Deactivate(); 320} 321 322bool DesktopWindowTreeHostWin::IsActive() const { 323 return message_handler_->IsActive(); 324} 325 326void DesktopWindowTreeHostWin::Maximize() { 327 message_handler_->Maximize(); 328} 329 330void DesktopWindowTreeHostWin::Minimize() { 331 message_handler_->Minimize(); 332} 333 334void DesktopWindowTreeHostWin::Restore() { 335 message_handler_->Restore(); 336} 337 338bool DesktopWindowTreeHostWin::IsMaximized() const { 339 return message_handler_->IsMaximized(); 340} 341 342bool DesktopWindowTreeHostWin::IsMinimized() const { 343 return message_handler_->IsMinimized(); 344} 345 346bool DesktopWindowTreeHostWin::HasCapture() const { 347 return message_handler_->HasCapture(); 348} 349 350void DesktopWindowTreeHostWin::SetAlwaysOnTop(bool always_on_top) { 351 message_handler_->SetAlwaysOnTop(always_on_top); 352} 353 354bool DesktopWindowTreeHostWin::IsAlwaysOnTop() const { 355 return message_handler_->IsAlwaysOnTop(); 356} 357 358void DesktopWindowTreeHostWin::SetVisibleOnAllWorkspaces(bool always_visible) { 359 // Windows does not have the concept of workspaces. 360} 361 362bool DesktopWindowTreeHostWin::SetWindowTitle(const base::string16& title) { 363 return message_handler_->SetTitle(title); 364} 365 366void DesktopWindowTreeHostWin::ClearNativeFocus() { 367 message_handler_->ClearNativeFocus(); 368} 369 370Widget::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 380void DesktopWindowTreeHostWin::EndMoveLoop() { 381 message_handler_->EndMoveLoop(); 382} 383 384void DesktopWindowTreeHostWin::SetVisibilityChangedAnimationsEnabled( 385 bool value) { 386 message_handler_->SetVisibilityChangedAnimationsEnabled(value); 387 content_window_->SetProperty(aura::client::kAnimationsDisabledKey, !value); 388} 389 390bool DesktopWindowTreeHostWin::ShouldUseNativeFrame() const { 391 return IsTranslucentWindowOpacitySupported(); 392} 393 394bool 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 402void DesktopWindowTreeHostWin::FrameTypeChanged() { 403 message_handler_->FrameTypeChanged(); 404 SetWindowTransparency(); 405} 406 407void 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 417bool DesktopWindowTreeHostWin::IsFullscreen() const { 418 return message_handler_->fullscreen_handler()->fullscreen(); 419} 420 421void DesktopWindowTreeHostWin::SetOpacity(unsigned char opacity) { 422 message_handler_->SetOpacity(static_cast<BYTE>(opacity)); 423 content_window_->layer()->SetOpacity(opacity / 255.0); 424} 425 426void DesktopWindowTreeHostWin::SetWindowIcons( 427 const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) { 428 message_handler_->SetWindowIcons(window_icon, app_icon); 429} 430 431void DesktopWindowTreeHostWin::InitModalType(ui::ModalType modal_type) { 432 message_handler_->InitModalType(modal_type); 433} 434 435void DesktopWindowTreeHostWin::FlashFrame(bool flash_frame) { 436 message_handler_->FlashFrame(flash_frame); 437} 438 439void DesktopWindowTreeHostWin::OnRootViewLayout() { 440} 441 442void DesktopWindowTreeHostWin::OnNativeWidgetFocus() { 443 // HWNDMessageHandler will perform the proper updating on its own. 444} 445 446void DesktopWindowTreeHostWin::OnNativeWidgetBlur() { 447} 448 449bool DesktopWindowTreeHostWin::IsAnimatingClosed() const { 450 return pending_close_; 451} 452 453bool DesktopWindowTreeHostWin::IsTranslucentWindowOpacitySupported() const { 454 return ui::win::IsAeroGlassEnabled(); 455} 456 457void DesktopWindowTreeHostWin::SizeConstraintsChanged() { 458 message_handler_->SizeConstraintsChanged(); 459} 460 461//////////////////////////////////////////////////////////////////////////////// 462// DesktopWindowTreeHostWin, WindowTreeHost implementation: 463 464ui::EventSource* DesktopWindowTreeHostWin::GetEventSource() { 465 return this; 466} 467 468gfx::AcceleratedWidget DesktopWindowTreeHostWin::GetAcceleratedWidget() { 469 return message_handler_->hwnd(); 470} 471 472void DesktopWindowTreeHostWin::Show() { 473 message_handler_->Show(); 474} 475 476void 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 484gfx::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 500void 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 523gfx::Point DesktopWindowTreeHostWin::GetLocationOnNativeScreen() const { 524 return GetBounds().origin(); 525} 526 527void DesktopWindowTreeHostWin::SetCapture() { 528 message_handler_->SetCapture(); 529} 530 531void DesktopWindowTreeHostWin::ReleaseCapture() { 532 message_handler_->ReleaseCapture(); 533} 534 535void DesktopWindowTreeHostWin::PostNativeEvent( 536 const base::NativeEvent& native_event) { 537} 538 539void DesktopWindowTreeHostWin::SetCursorNative(gfx::NativeCursor cursor) { 540 ui::CursorLoaderWin cursor_loader; 541 cursor_loader.SetPlatformCursor(&cursor); 542 543 message_handler_->SetCursor(cursor.platform()); 544} 545 546void DesktopWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) { 547 if (is_cursor_visible_ == show) 548 return; 549 is_cursor_visible_ = show; 550 ::ShowCursor(!!show); 551} 552 553void 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 562ui::EventProcessor* DesktopWindowTreeHostWin::GetEventProcessor() { 563 return dispatcher(); 564} 565 566//////////////////////////////////////////////////////////////////////////////// 567// DesktopWindowTreeHostWin, aura::AnimationHost implementation: 568 569void 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 578void DesktopWindowTreeHostWin::OnWindowHidingAnimationCompleted() { 579 if (pending_close_) 580 message_handler_->Close(); 581} 582 583//////////////////////////////////////////////////////////////////////////////// 584// DesktopWindowTreeHostWin, HWNDMessageHandlerDelegate implementation: 585 586bool DesktopWindowTreeHostWin::IsWidgetWindow() const { 587 return has_non_client_view_; 588} 589 590bool DesktopWindowTreeHostWin::IsUsingCustomFrame() const { 591 return !GetWidget()->ShouldUseNativeFrame(); 592} 593 594void DesktopWindowTreeHostWin::SchedulePaint() { 595 GetWidget()->GetRootView()->SchedulePaint(); 596} 597 598void DesktopWindowTreeHostWin::EnableInactiveRendering() { 599 native_widget_delegate_->EnableInactiveRendering(); 600} 601 602bool DesktopWindowTreeHostWin::IsInactiveRenderingDisabled() { 603 return native_widget_delegate_->IsInactiveRenderingDisabled(); 604} 605 606bool DesktopWindowTreeHostWin::CanResize() const { 607 return GetWidget()->widget_delegate()->CanResize(); 608} 609 610bool DesktopWindowTreeHostWin::CanMaximize() const { 611 return GetWidget()->widget_delegate()->CanMaximize(); 612} 613 614bool DesktopWindowTreeHostWin::CanMinimize() const { 615 return GetWidget()->widget_delegate()->CanMinimize(); 616} 617 618bool DesktopWindowTreeHostWin::CanActivate() const { 619 if (IsModalWindowActive()) 620 return true; 621 return native_widget_delegate_->CanActivate(); 622} 623 624bool DesktopWindowTreeHostWin::WidgetSizeIsClientSize() const { 625 const Widget* widget = GetWidget()->GetTopLevelWidget(); 626 return IsMaximized() || (widget && widget->ShouldUseNativeFrame()); 627} 628 629bool DesktopWindowTreeHostWin::IsModal() const { 630 return native_widget_delegate_->IsModal(); 631} 632 633int DesktopWindowTreeHostWin::GetInitialShowState() const { 634 return CanActivate() ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE; 635} 636 637bool DesktopWindowTreeHostWin::WillProcessWorkAreaChange() const { 638 return GetWidget()->widget_delegate()->WillProcessWorkAreaChange(); 639} 640 641int 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 647void 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 660bool DesktopWindowTreeHostWin::GetClientAreaInsets(gfx::Insets* insets) const { 661 return false; 662} 663 664void 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 670gfx::Size DesktopWindowTreeHostWin::GetRootViewSize() const { 671 return GetWidget()->GetRootView()->size(); 672} 673 674void DesktopWindowTreeHostWin::ResetWindowControls() { 675 GetWidget()->non_client_view()->ResetWindowControls(); 676} 677 678void DesktopWindowTreeHostWin::PaintLayeredWindow(gfx::Canvas* canvas) { 679 GetWidget()->GetRootView()->Paint(canvas, views::CullSet()); 680} 681 682gfx::NativeViewAccessible DesktopWindowTreeHostWin::GetNativeViewAccessible() { 683 return GetWidget()->GetRootView()->GetNativeViewAccessible(); 684} 685 686InputMethod* DesktopWindowTreeHostWin::GetInputMethod() { 687 return GetWidget()->GetInputMethodDirect(); 688} 689 690bool DesktopWindowTreeHostWin::ShouldHandleSystemCommands() const { 691 return GetWidget()->widget_delegate()->ShouldHandleSystemCommands(); 692} 693 694void DesktopWindowTreeHostWin::HandleAppDeactivated() { 695 native_widget_delegate_->EnableInactiveRendering(); 696} 697 698void 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 710bool 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 717void DesktopWindowTreeHostWin::HandleCancelMode() { 718 dispatcher()->DispatchCancelModeEvent(); 719} 720 721void DesktopWindowTreeHostWin::HandleCaptureLost() { 722 OnHostLostWindowCapture(); 723} 724 725void DesktopWindowTreeHostWin::HandleClose() { 726 GetWidget()->Close(); 727} 728 729bool 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 749void DesktopWindowTreeHostWin::HandleAccelerator( 750 const ui::Accelerator& accelerator) { 751 GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator); 752} 753 754void DesktopWindowTreeHostWin::HandleCreate() { 755 native_widget_delegate_->OnNativeWidgetCreated(true); 756} 757 758void 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 767void DesktopWindowTreeHostWin::HandleDestroyed() { 768 desktop_native_widget_aura_->OnHostClosed(); 769} 770 771bool DesktopWindowTreeHostWin::HandleInitialFocus( 772 ui::WindowShowState show_state) { 773 return GetWidget()->SetInitialFocus(show_state); 774} 775 776void DesktopWindowTreeHostWin::HandleDisplayChange() { 777 GetWidget()->widget_delegate()->OnDisplayChanged(); 778} 779 780void DesktopWindowTreeHostWin::HandleBeginWMSizeMove() { 781 if (in_sizing_loop_) 782 need_synchronous_paint_ = true; 783 native_widget_delegate_->OnNativeWidgetBeginUserBoundsChange(); 784} 785 786void 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 794void DesktopWindowTreeHostWin::HandleMove() { 795 native_widget_delegate_->OnNativeWidgetMove(); 796 OnHostMoved(GetBounds().origin()); 797} 798 799void DesktopWindowTreeHostWin::HandleWorkAreaChanged() { 800 GetWidget()->widget_delegate()->OnWorkAreaChanged(); 801} 802 803void DesktopWindowTreeHostWin::HandleVisibilityChanging(bool visible) { 804 native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible); 805} 806 807void DesktopWindowTreeHostWin::HandleVisibilityChanged(bool visible) { 808 native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible); 809} 810 811void DesktopWindowTreeHostWin::HandleClientSizeChanged( 812 const gfx::Size& new_size) { 813 if (dispatcher()) 814 OnHostResized(new_size); 815} 816 817void DesktopWindowTreeHostWin::HandleFrameChanged() { 818 SetWindowTransparency(); 819 // Replace the frame and layout the contents. 820 GetWidget()->non_client_view()->UpdateFrame(); 821} 822 823void 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 830void 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 837bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) { 838 SendEventToProcessor(const_cast<ui::MouseEvent*>(&event)); 839 return event.handled(); 840} 841 842bool DesktopWindowTreeHostWin::HandleKeyEvent(const ui::KeyEvent& event) { 843 return false; 844} 845 846bool DesktopWindowTreeHostWin::HandleUntranslatedKeyEvent( 847 const ui::KeyEvent& event) { 848 ui::KeyEvent duplicate_event(event); 849 SendEventToProcessor(&duplicate_event); 850 return duplicate_event.handled(); 851} 852 853void 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 882bool 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 895void 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 902bool DesktopWindowTreeHostWin::HandlePaintAccelerated( 903 const gfx::Rect& invalid_rect) { 904 return native_widget_delegate_->OnNativeWidgetPaintAccelerated(invalid_rect); 905} 906 907void 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 913bool 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 919void 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 928bool DesktopWindowTreeHostWin::PreHandleMSG(UINT message, 929 WPARAM w_param, 930 LPARAM l_param, 931 LRESULT* result) { 932 return false; 933} 934 935void DesktopWindowTreeHostWin::PostHandleMSG(UINT message, 936 WPARAM w_param, 937 LPARAM l_param) { 938} 939 940bool DesktopWindowTreeHostWin::HandleScrollEvent( 941 const ui::ScrollEvent& event) { 942 SendEventToProcessor(const_cast<ui::ScrollEvent*>(&event)); 943 return event.handled(); 944} 945 946void 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 961Widget* DesktopWindowTreeHostWin::GetWidget() { 962 return native_widget_delegate_->AsWidget(); 963} 964 965const Widget* DesktopWindowTreeHostWin::GetWidget() const { 966 return native_widget_delegate_->AsWidget(); 967} 968 969HWND DesktopWindowTreeHostWin::GetHWND() const { 970 return message_handler_->hwnd(); 971} 972 973void DesktopWindowTreeHostWin::SetWindowTransparency() { 974 bool transparent = ShouldUseNativeFrame() && !IsFullscreen(); 975 compositor()->SetHostHasTransparentBackground(transparent); 976 window()->SetTransparent(transparent); 977 content_window_->SetTransparent(transparent); 978} 979 980bool 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 1001DesktopWindowTreeHost* 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