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/native_widget_win.h" 6 7 #include <dwmapi.h> 8 #include <shellapi.h> 9 10 #include <algorithm> 11 12 #include "base/bind.h" 13 #include "base/strings/string_util.h" 14 #include "base/win/scoped_gdi_object.h" 15 #include "base/win/win_util.h" 16 #include "base/win/windows_version.h" 17 #include "ui/base/dragdrop/drag_drop_types.h" 18 #include "ui/base/dragdrop/drag_source_win.h" 19 #include "ui/base/dragdrop/os_exchange_data.h" 20 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" 21 #include "ui/base/ime/input_method_factory.h" 22 #include "ui/base/l10n/l10n_util_win.h" 23 #include "ui/base/theme_provider.h" 24 #include "ui/base/view_prop.h" 25 #include "ui/base/win/mouse_wheel_util.h" 26 #include "ui/base/win/shell.h" 27 #include "ui/events/event.h" 28 #include "ui/events/keycodes/keyboard_code_conversion_win.h" 29 #include "ui/gfx/canvas.h" 30 #include "ui/gfx/canvas_skia_paint.h" 31 #include "ui/gfx/path.h" 32 #include "ui/gfx/point_conversions.h" 33 #include "ui/gfx/screen.h" 34 #include "ui/gfx/size_conversions.h" 35 #include "ui/gfx/win/dpi.h" 36 #include "ui/gfx/win/hwnd_util.h" 37 #include "ui/native_theme/native_theme.h" 38 #include "ui/views/controls/native_control_win.h" 39 #include "ui/views/controls/textfield/textfield.h" 40 #include "ui/views/drag_utils.h" 41 #include "ui/views/focus/accelerator_handler.h" 42 #include "ui/views/focus/view_storage.h" 43 #include "ui/views/focus/widget_focus_manager.h" 44 #include "ui/views/ime/input_method_bridge.h" 45 #include "ui/views/widget/aero_tooltip_manager.h" 46 #include "ui/views/widget/drop_target_win.h" 47 #include "ui/views/widget/monitor_win.h" 48 #include "ui/views/widget/native_widget_delegate.h" 49 #include "ui/views/widget/root_view.h" 50 #include "ui/views/widget/widget_delegate.h" 51 #include "ui/views/widget/widget_hwnd_utils.h" 52 #include "ui/views/win/fullscreen_handler.h" 53 #include "ui/views/win/hwnd_message_handler.h" 54 #include "ui/views/window/native_frame_view.h" 55 56 #pragma comment(lib, "dwmapi.lib") 57 58 using ui::ViewProp; 59 60 namespace views { 61 62 namespace { 63 64 // Enumeration callback for NativeWidget::GetAllChildWidgets() and 65 // NativeWidget::GetAllOwnedWidgets. Adds any HWNDs that correspond to 66 // Widgets to a set. 67 BOOL CALLBACK EnumerateNativeWidgets(HWND hwnd, LPARAM l_param) { 68 Widget* widget = Widget::GetWidgetForNativeView(hwnd); 69 if (widget) { 70 Widget::Widgets* widgets = reinterpret_cast<Widget::Widgets*>(l_param); 71 widgets->insert(widget); 72 } 73 return TRUE; 74 } 75 76 // Links the HWND to its NativeWidget. 77 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; 78 79 const int kDragFrameWindowAlpha = 200; 80 81 } // namespace 82 83 //////////////////////////////////////////////////////////////////////////////// 84 // NativeWidgetWin, public: 85 86 NativeWidgetWin::NativeWidgetWin(internal::NativeWidgetDelegate* delegate) 87 : delegate_(delegate), 88 ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), 89 drag_frame_saved_window_style_(0), 90 drag_frame_saved_window_ex_style_(0), 91 has_non_client_view_(false), 92 message_handler_(new HWNDMessageHandler(this)) { 93 } 94 95 NativeWidgetWin::~NativeWidgetWin() { 96 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) 97 delete delegate_; 98 else 99 CloseNow(); 100 message_handler_.reset(); 101 } 102 103 // static 104 gfx::Font NativeWidgetWin::GetWindowTitleFont() { 105 NONCLIENTMETRICS ncm; 106 base::win::GetNonClientMetrics(&ncm); 107 l10n_util::AdjustUIFont(&(ncm.lfCaptionFont)); 108 base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont))); 109 return gfx::Font(caption_font); 110 } 111 112 void NativeWidgetWin::Show(int show_state) { 113 message_handler_->Show(show_state); 114 } 115 116 //////////////////////////////////////////////////////////////////////////////// 117 // NativeWidgetWin, NativeWidget implementation: 118 119 void NativeWidgetWin::InitNativeWidget(const Widget::InitParams& params) { 120 gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds); 121 Widget::InitParams params_in_pixel(params); 122 params_in_pixel.bounds = pixel_bounds; 123 SetInitParams(params_in_pixel); 124 message_handler_->Init(params.parent, pixel_bounds); 125 } 126 127 NonClientFrameView* NativeWidgetWin::CreateNonClientFrameView() { 128 return GetWidget()->ShouldUseNativeFrame() ? 129 new NativeFrameView(GetWidget()) : NULL; 130 } 131 132 bool NativeWidgetWin::ShouldUseNativeFrame() const { 133 return ui::win::IsAeroGlassEnabled(); 134 } 135 136 void NativeWidgetWin::FrameTypeChanged() { 137 message_handler_->FrameTypeChanged(); 138 } 139 140 Widget* NativeWidgetWin::GetWidget() { 141 return delegate_->AsWidget(); 142 } 143 144 const Widget* NativeWidgetWin::GetWidget() const { 145 return delegate_->AsWidget(); 146 } 147 148 gfx::NativeView NativeWidgetWin::GetNativeView() const { 149 return message_handler_->hwnd(); 150 } 151 152 gfx::NativeWindow NativeWidgetWin::GetNativeWindow() const { 153 return message_handler_->hwnd(); 154 } 155 156 Widget* NativeWidgetWin::GetTopLevelWidget() { 157 NativeWidgetPrivate* native_widget = GetTopLevelNativeWidget(GetNativeView()); 158 return native_widget ? native_widget->GetWidget() : NULL; 159 } 160 161 const ui::Compositor* NativeWidgetWin::GetCompositor() const { 162 return NULL; 163 } 164 165 ui::Compositor* NativeWidgetWin::GetCompositor() { 166 return NULL; 167 } 168 169 ui::Layer* NativeWidgetWin::GetLayer() { 170 return NULL; 171 } 172 173 void NativeWidgetWin::ReorderNativeViews() { 174 } 175 176 void NativeWidgetWin::ViewRemoved(View* view) { 177 if (drop_target_.get()) 178 drop_target_->ResetTargetViewIfEquals(view); 179 } 180 181 void NativeWidgetWin::SetNativeWindowProperty(const char* name, void* value) { 182 // Remove the existing property (if any). 183 for (ViewProps::iterator i = props_.begin(); i != props_.end(); ++i) { 184 if ((*i)->Key() == name) { 185 props_.erase(i); 186 break; 187 } 188 } 189 190 if (value) 191 props_.push_back(new ViewProp(GetNativeView(), name, value)); 192 } 193 194 void* NativeWidgetWin::GetNativeWindowProperty(const char* name) const { 195 return ViewProp::GetValue(GetNativeView(), name); 196 } 197 198 TooltipManager* NativeWidgetWin::GetTooltipManager() const { 199 return tooltip_manager_.get(); 200 } 201 202 void NativeWidgetWin::SetCapture() { 203 message_handler_->SetCapture(); 204 } 205 206 void NativeWidgetWin::ReleaseCapture() { 207 message_handler_->ReleaseCapture(); 208 } 209 210 bool NativeWidgetWin::HasCapture() const { 211 return message_handler_->HasCapture(); 212 } 213 214 InputMethod* NativeWidgetWin::CreateInputMethod() { 215 return new InputMethodBridge(GetMessageHandler(), ui::GetSharedInputMethod(), 216 true); 217 } 218 219 internal::InputMethodDelegate* NativeWidgetWin::GetInputMethodDelegate() { 220 return message_handler_.get(); 221 } 222 223 void NativeWidgetWin::CenterWindow(const gfx::Size& size) { 224 gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size); 225 message_handler_->CenterWindow(size_in_pixels); 226 } 227 228 void NativeWidgetWin::GetWindowPlacement( 229 gfx::Rect* bounds, 230 ui::WindowShowState* show_state) const { 231 message_handler_->GetWindowPlacement(bounds, show_state); 232 *bounds = gfx::win::ScreenToDIPRect(*bounds); 233 } 234 235 bool NativeWidgetWin::SetWindowTitle(const string16& title) { 236 return message_handler_->SetTitle(title); 237 } 238 239 void NativeWidgetWin::SetWindowIcons(const gfx::ImageSkia& window_icon, 240 const gfx::ImageSkia& app_icon) { 241 message_handler_->SetWindowIcons(window_icon, app_icon); 242 } 243 244 void NativeWidgetWin::InitModalType(ui::ModalType modal_type) { 245 message_handler_->InitModalType(modal_type); 246 } 247 248 gfx::Rect NativeWidgetWin::GetWindowBoundsInScreen() const { 249 gfx::Rect bounds_in_pixels = message_handler_->GetWindowBoundsInScreen(); 250 return gfx::win::ScreenToDIPRect(bounds_in_pixels); 251 } 252 253 gfx::Rect NativeWidgetWin::GetClientAreaBoundsInScreen() const { 254 gfx::Rect bounds_in_pixels = message_handler_->GetClientAreaBoundsInScreen(); 255 return gfx::win::ScreenToDIPRect(bounds_in_pixels); 256 } 257 258 gfx::Rect NativeWidgetWin::GetRestoredBounds() const { 259 gfx::Rect bounds_in_pixels = message_handler_->GetRestoredBounds(); 260 return gfx::win::ScreenToDIPRect(bounds_in_pixels); 261 } 262 263 void NativeWidgetWin::SetBounds(const gfx::Rect& bounds) { 264 float scale = gfx::win::GetDeviceScaleFactor(); 265 gfx::Rect bounds_in_pixels( 266 gfx::ToCeiledPoint(gfx::ScalePoint(bounds.origin(), scale)), 267 gfx::ToFlooredSize(gfx::ScaleSize(bounds.size(), scale))); 268 message_handler_->SetBounds(bounds_in_pixels); 269 } 270 271 void NativeWidgetWin::SetSize(const gfx::Size& size) { 272 message_handler_->SetSize(size); 273 } 274 275 void NativeWidgetWin::StackAbove(gfx::NativeView native_view) { 276 message_handler_->StackAbove(native_view); 277 } 278 279 void NativeWidgetWin::StackAtTop() { 280 message_handler_->StackAtTop(); 281 } 282 283 void NativeWidgetWin::StackBelow(gfx::NativeView native_view) { 284 NOTIMPLEMENTED(); 285 } 286 287 void NativeWidgetWin::SetShape(gfx::NativeRegion region) { 288 message_handler_->SetRegion(region); 289 } 290 291 void NativeWidgetWin::Close() { 292 message_handler_->Close(); 293 } 294 295 void NativeWidgetWin::CloseNow() { 296 message_handler_->CloseNow(); 297 } 298 299 void NativeWidgetWin::Show() { 300 message_handler_->Show(); 301 } 302 303 void NativeWidgetWin::Hide() { 304 message_handler_->Hide(); 305 } 306 307 void NativeWidgetWin::ShowMaximizedWithBounds( 308 const gfx::Rect& restored_bounds) { 309 gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(restored_bounds); 310 message_handler_->ShowMaximizedWithBounds(pixel_bounds); 311 } 312 313 void NativeWidgetWin::ShowWithWindowState(ui::WindowShowState show_state) { 314 message_handler_->ShowWindowWithState(show_state); 315 } 316 317 bool NativeWidgetWin::IsVisible() const { 318 return message_handler_->IsVisible(); 319 } 320 321 void NativeWidgetWin::Activate() { 322 message_handler_->Activate(); 323 } 324 325 void NativeWidgetWin::Deactivate() { 326 message_handler_->Deactivate(); 327 } 328 329 bool NativeWidgetWin::IsActive() const { 330 return message_handler_->IsActive(); 331 } 332 333 void NativeWidgetWin::SetAlwaysOnTop(bool on_top) { 334 message_handler_->SetAlwaysOnTop(on_top); 335 } 336 337 bool NativeWidgetWin::IsAlwaysOnTop() const { 338 return message_handler_->IsAlwaysOnTop(); 339 } 340 341 void NativeWidgetWin::Maximize() { 342 message_handler_->Maximize(); 343 } 344 345 void NativeWidgetWin::Minimize() { 346 message_handler_->Minimize(); 347 } 348 349 bool NativeWidgetWin::IsMaximized() const { 350 return message_handler_->IsMaximized(); 351 } 352 353 bool NativeWidgetWin::IsMinimized() const { 354 return message_handler_->IsMinimized(); 355 } 356 357 void NativeWidgetWin::Restore() { 358 message_handler_->Restore(); 359 } 360 361 void NativeWidgetWin::SetFullscreen(bool fullscreen) { 362 message_handler_->fullscreen_handler()->SetFullscreen(fullscreen); 363 } 364 365 void NativeWidgetWin::SetMetroSnapFullscreen(bool metro_snap) { 366 message_handler_->fullscreen_handler()->SetMetroSnap(metro_snap); 367 } 368 369 bool NativeWidgetWin::IsFullscreen() const { 370 return message_handler_->fullscreen_handler()->fullscreen(); 371 } 372 373 bool NativeWidgetWin::IsInMetroSnapMode() const { 374 return message_handler_->fullscreen_handler()->metro_snap(); 375 } 376 377 void NativeWidgetWin::SetCanUpdateLayeredWindow(bool can_update) { 378 message_handler_->set_can_update_layered_window(can_update); 379 } 380 381 void NativeWidgetWin::SetOpacity(unsigned char opacity) { 382 message_handler_->SetOpacity(static_cast<BYTE>(opacity)); 383 GetWidget()->GetRootView()->SchedulePaint(); 384 } 385 386 void NativeWidgetWin::SetUseDragFrame(bool use_drag_frame) { 387 if (use_drag_frame) { 388 // Make the frame slightly transparent during the drag operation. 389 drag_frame_saved_window_style_ = GetWindowLong(GetNativeView(), GWL_STYLE); 390 drag_frame_saved_window_ex_style_ = 391 GetWindowLong(GetNativeView(), GWL_EXSTYLE); 392 SetWindowLong(GetNativeView(), GWL_EXSTYLE, 393 drag_frame_saved_window_ex_style_ | WS_EX_LAYERED); 394 // Remove the captions tyle so the window doesn't have window controls for a 395 // more "transparent" look. 396 SetWindowLong(GetNativeView(), GWL_STYLE, 397 drag_frame_saved_window_style_ & ~WS_CAPTION); 398 SetLayeredWindowAttributes(GetNativeView(), RGB(0xFF, 0xFF, 0xFF), 399 kDragFrameWindowAlpha, LWA_ALPHA); 400 } else { 401 SetWindowLong(GetNativeView(), GWL_STYLE, drag_frame_saved_window_style_); 402 SetWindowLong(GetNativeView(), GWL_EXSTYLE, 403 drag_frame_saved_window_ex_style_); 404 } 405 } 406 407 void NativeWidgetWin::FlashFrame(bool flash) { 408 message_handler_->FlashFrame(flash); 409 } 410 411 void NativeWidgetWin::RunShellDrag(View* view, 412 const ui::OSExchangeData& data, 413 const gfx::Point& location, 414 int operation, 415 ui::DragDropTypes::DragEventSource source) { 416 views::RunShellDrag(NULL, data, location, operation, source); 417 } 418 419 void NativeWidgetWin::SchedulePaintInRect(const gfx::Rect& rect) { 420 gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(rect); 421 message_handler_->SchedulePaintInRect(pixel_rect); 422 } 423 424 void NativeWidgetWin::SetCursor(gfx::NativeCursor cursor) { 425 message_handler_->SetCursor(cursor); 426 } 427 428 bool NativeWidgetWin::IsMouseEventsEnabled() const { 429 return true; 430 } 431 432 void NativeWidgetWin::ClearNativeFocus() { 433 message_handler_->ClearNativeFocus(); 434 } 435 436 gfx::Rect NativeWidgetWin::GetWorkAreaBoundsInScreen() const { 437 return gfx::win::ScreenToDIPRect( 438 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 439 GetNativeView()).work_area()); 440 } 441 442 Widget::MoveLoopResult NativeWidgetWin::RunMoveLoop( 443 const gfx::Vector2d& drag_offset, 444 Widget::MoveLoopSource source, 445 Widget::MoveLoopEscapeBehavior escape_behavior) { 446 const bool hide_on_escape = 447 escape_behavior == Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE; 448 return message_handler_->RunMoveLoop(drag_offset, hide_on_escape) ? 449 Widget::MOVE_LOOP_SUCCESSFUL : Widget::MOVE_LOOP_CANCELED; 450 } 451 452 void NativeWidgetWin::EndMoveLoop() { 453 message_handler_->EndMoveLoop(); 454 } 455 456 void NativeWidgetWin::SetVisibilityChangedAnimationsEnabled(bool value) { 457 message_handler_->SetVisibilityChangedAnimationsEnabled(value); 458 } 459 460 ui::NativeTheme* NativeWidgetWin::GetNativeTheme() const { 461 return ui::NativeTheme::instance(); 462 } 463 464 void NativeWidgetWin::OnRootViewLayout() const { 465 } 466 467 //////////////////////////////////////////////////////////////////////////////// 468 // NativeWidgetWin, NativeWidget implementation: 469 470 ui::EventHandler* NativeWidgetWin::GetEventHandler() { 471 NOTIMPLEMENTED(); 472 return NULL; 473 } 474 475 //////////////////////////////////////////////////////////////////////////////// 476 // NativeWidgetWin, protected: 477 478 void NativeWidgetWin::OnFinalMessage(HWND window) { 479 // We don't destroy props in WM_DESTROY as we may still get messages after 480 // WM_DESTROY that assume the properties are still valid (such as WM_CLOSE). 481 props_.clear(); 482 delegate_->OnNativeWidgetDestroyed(); 483 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) 484 delete this; 485 } 486 487 //////////////////////////////////////////////////////////////////////////////// 488 // NativeWidgetWin, protected: 489 490 HWNDMessageHandler* NativeWidgetWin::GetMessageHandler() { 491 return message_handler_.get(); 492 } 493 494 //////////////////////////////////////////////////////////////////////////////// 495 // NativeWidgetWin, HWNDMessageHandlerDelegate implementation: 496 497 bool NativeWidgetWin::IsWidgetWindow() const { 498 // We don't NULL check GetWidget()->non_client_view() here because this 499 // function can be called before the widget is fully constructed. 500 return has_non_client_view_; 501 } 502 503 bool NativeWidgetWin::IsUsingCustomFrame() const { 504 return !GetWidget()->ShouldUseNativeFrame(); 505 } 506 507 void NativeWidgetWin::SchedulePaint() { 508 GetWidget()->GetRootView()->SchedulePaint(); 509 } 510 511 void NativeWidgetWin::EnableInactiveRendering() { 512 delegate_->EnableInactiveRendering(); 513 } 514 515 bool NativeWidgetWin::IsInactiveRenderingDisabled() { 516 return delegate_->IsInactiveRenderingDisabled(); 517 } 518 519 bool NativeWidgetWin::CanResize() const { 520 return GetWidget()->widget_delegate()->CanResize(); 521 } 522 523 bool NativeWidgetWin::CanMaximize() const { 524 return GetWidget()->widget_delegate()->CanMaximize(); 525 } 526 527 bool NativeWidgetWin::CanActivate() const { 528 return delegate_->CanActivate(); 529 } 530 531 bool NativeWidgetWin::WidgetSizeIsClientSize() const { 532 const Widget* widget = GetWidget()->GetTopLevelWidget(); 533 return IsZoomed(GetNativeView()) || 534 (widget && widget->ShouldUseNativeFrame()); 535 } 536 537 bool NativeWidgetWin::CanSaveFocus() const { 538 return GetWidget()->is_top_level(); 539 } 540 541 void NativeWidgetWin::SaveFocusOnDeactivate() { 542 GetWidget()->GetFocusManager()->StoreFocusedView(true); 543 } 544 545 void NativeWidgetWin::RestoreFocusOnActivate() { 546 // Mysteriously, this only appears to be needed support restoration of focus 547 // to a child hwnd when restoring its top level window from the minimized 548 // state. If we don't do this, then ::SetFocus() to that child HWND returns 549 // ERROR_INVALID_PARAMETER, despite both HWNDs being of the same thread. 550 // See http://crbug.com/125976 and 551 // chrome/browser/ui/views/native_widget_win_interactive_uitest.cc . 552 { 553 // Since this is a synthetic reset, we don't need to tell anyone about it. 554 AutoNativeNotificationDisabler disabler; 555 GetWidget()->GetFocusManager()->ClearFocus(); 556 } 557 RestoreFocusOnEnable(); 558 } 559 560 void NativeWidgetWin::RestoreFocusOnEnable() { 561 GetWidget()->GetFocusManager()->RestoreFocusedView(); 562 } 563 564 bool NativeWidgetWin::IsModal() const { 565 return delegate_->IsModal(); 566 } 567 568 int NativeWidgetWin::GetInitialShowState() const { 569 return SW_SHOWNORMAL; 570 } 571 572 bool NativeWidgetWin::WillProcessWorkAreaChange() const { 573 return GetWidget()->widget_delegate()->WillProcessWorkAreaChange(); 574 } 575 576 int NativeWidgetWin::GetNonClientComponent(const gfx::Point& point) const { 577 gfx::Point point_in_dip = gfx::win::ScreenToDIPPoint(point); 578 return delegate_->GetNonClientComponent(point_in_dip); 579 } 580 581 void NativeWidgetWin::GetWindowMask(const gfx::Size& size, gfx::Path* path) { 582 if (GetWidget()->non_client_view()) 583 GetWidget()->non_client_view()->GetWindowMask(size, path); 584 } 585 586 bool NativeWidgetWin::GetClientAreaInsets(gfx::Insets* insets) const { 587 return false; 588 } 589 590 void NativeWidgetWin::GetMinMaxSize(gfx::Size* min_size, 591 gfx::Size* max_size) const { 592 *min_size = gfx::win::ScreenToDIPSize(delegate_->GetMinimumSize()); 593 *max_size = gfx::win::ScreenToDIPSize(delegate_->GetMaximumSize()); 594 } 595 596 gfx::Size NativeWidgetWin::GetRootViewSize() const { 597 gfx::Size pixel_size = GetWidget()->GetRootView()->size(); 598 return gfx::win::ScreenToDIPSize(pixel_size); 599 } 600 601 void NativeWidgetWin::ResetWindowControls() { 602 GetWidget()->non_client_view()->ResetWindowControls(); 603 } 604 605 void NativeWidgetWin::PaintLayeredWindow(gfx::Canvas* canvas) { 606 GetWidget()->GetRootView()->Paint(canvas); 607 } 608 609 InputMethod* NativeWidgetWin::GetInputMethod() { 610 return GetWidget()->GetInputMethodDirect(); 611 } 612 613 gfx::NativeViewAccessible NativeWidgetWin::GetNativeViewAccessible() { 614 return GetWidget()->GetRootView()->GetNativeViewAccessible(); 615 } 616 617 bool NativeWidgetWin::ShouldHandleSystemCommands() const { 618 return GetWidget()->widget_delegate()->ShouldHandleSystemCommands(); 619 } 620 621 void NativeWidgetWin::HandleAppDeactivated() { 622 if (IsInactiveRenderingDisabled()) { 623 delegate_->EnableInactiveRendering(); 624 } else { 625 // TODO(pkotwicz): Remove need for SchedulePaint(). crbug.com/165841 626 View* non_client_view = GetWidget()->non_client_view(); 627 if (non_client_view) 628 non_client_view->SchedulePaint(); 629 } 630 } 631 632 void NativeWidgetWin::HandleActivationChanged(bool active) { 633 delegate_->OnNativeWidgetActivationChanged(active); 634 } 635 636 bool NativeWidgetWin::HandleAppCommand(short command) { 637 // We treat APPCOMMAND ids as an extension of our command namespace, and just 638 // let the delegate figure out what to do... 639 return GetWidget()->widget_delegate() && 640 GetWidget()->widget_delegate()->ExecuteWindowsCommand(command); 641 } 642 643 void NativeWidgetWin::HandleCancelMode() { 644 } 645 646 void NativeWidgetWin::HandleCaptureLost() { 647 delegate_->OnMouseCaptureLost(); 648 } 649 650 void NativeWidgetWin::HandleClose() { 651 GetWidget()->Close(); 652 } 653 654 bool NativeWidgetWin::HandleCommand(int command) { 655 return GetWidget()->widget_delegate()->ExecuteWindowsCommand(command); 656 } 657 658 void NativeWidgetWin::HandleAccelerator(const ui::Accelerator& accelerator) { 659 GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator); 660 } 661 662 void NativeWidgetWin::HandleCreate() { 663 // TODO(beng): much of this could/should maybe move to HWNDMessageHandler. 664 665 SetNativeWindowProperty(kNativeWidgetKey, this); 666 CHECK_EQ(this, GetNativeWidgetForNativeView(GetNativeView())); 667 668 props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(GetNativeView())); 669 670 drop_target_ = new DropTargetWin( 671 static_cast<internal::RootView*>(GetWidget()->GetRootView())); 672 673 // Windows special DWM window frame requires a special tooltip manager so 674 // that window controls in Chrome windows don't flicker when you move your 675 // mouse over them. See comment in aero_tooltip_manager.h. 676 Widget* widget = GetWidget()->GetTopLevelWidget(); 677 if (widget && widget->ShouldUseNativeFrame()) { 678 tooltip_manager_.reset(new AeroTooltipManager(GetWidget())); 679 } else { 680 tooltip_manager_.reset(new TooltipManagerWin(GetWidget())); 681 } 682 if (!tooltip_manager_->Init()) { 683 // There was a problem creating the TooltipManager. Common error is 127. 684 // See 82193 for details. 685 LOG_GETLASTERROR(WARNING) << "tooltip creation failed, disabling tooltips"; 686 tooltip_manager_.reset(); 687 } 688 689 delegate_->OnNativeWidgetCreated(true); 690 } 691 692 void NativeWidgetWin::HandleDestroying() { 693 delegate_->OnNativeWidgetDestroying(); 694 if (drop_target_.get()) { 695 RevokeDragDrop(GetNativeView()); 696 drop_target_ = NULL; 697 } 698 } 699 700 void NativeWidgetWin::HandleDestroyed() { 701 OnFinalMessage(GetNativeView()); 702 } 703 704 bool NativeWidgetWin::HandleInitialFocus() { 705 return GetWidget()->SetInitialFocus(); 706 } 707 708 void NativeWidgetWin::HandleDisplayChange() { 709 GetWidget()->widget_delegate()->OnDisplayChanged(); 710 } 711 712 void NativeWidgetWin::HandleBeginWMSizeMove() { 713 delegate_->OnNativeWidgetBeginUserBoundsChange(); 714 } 715 716 void NativeWidgetWin::HandleEndWMSizeMove() { 717 delegate_->OnNativeWidgetEndUserBoundsChange(); 718 } 719 720 void NativeWidgetWin::HandleMove() { 721 delegate_->OnNativeWidgetMove(); 722 } 723 724 void NativeWidgetWin::HandleWorkAreaChanged() { 725 GetWidget()->widget_delegate()->OnWorkAreaChanged(); 726 } 727 728 void NativeWidgetWin::HandleVisibilityChanging(bool visible) { 729 delegate_->OnNativeWidgetVisibilityChanging(visible); 730 } 731 732 void NativeWidgetWin::HandleVisibilityChanged(bool visible) { 733 delegate_->OnNativeWidgetVisibilityChanged(visible); 734 } 735 736 void NativeWidgetWin::HandleClientSizeChanged(const gfx::Size& new_size) { 737 gfx::Size size_in_dip = gfx::win::ScreenToDIPSize(new_size); 738 delegate_->OnNativeWidgetSizeChanged(size_in_dip); 739 } 740 741 void NativeWidgetWin::HandleFrameChanged() { 742 // Replace the frame and layout the contents. 743 GetWidget()->non_client_view()->UpdateFrame(); 744 } 745 746 void NativeWidgetWin::HandleNativeFocus(HWND last_focused_window) { 747 delegate_->OnNativeFocus(last_focused_window); 748 InputMethod* input_method = GetInputMethod(); 749 if (input_method) 750 input_method->OnFocus(); 751 } 752 753 void NativeWidgetWin::HandleNativeBlur(HWND focused_window) { 754 delegate_->OnNativeBlur(focused_window); 755 InputMethod* input_method = GetInputMethod(); 756 if (input_method) 757 input_method->OnBlur(); 758 } 759 760 bool NativeWidgetWin::HandleMouseEvent(const ui::MouseEvent& event) { 761 static gfx::Transform scale_transform( 762 1/gfx::win::GetDeviceScaleFactor(), 0.0, 763 0.0, 1/gfx::win::GetDeviceScaleFactor(), 764 0.0, 0.0); 765 if (event.IsMouseWheelEvent()) { 766 ui::MouseWheelEvent dpi_event( 767 static_cast<const ui::MouseWheelEvent&>(event)); 768 dpi_event.UpdateForRootTransform(scale_transform); 769 delegate_->OnMouseEvent(&dpi_event); 770 return dpi_event.handled(); 771 } else if (event.IsMouseEvent()) { 772 ui::MouseEvent dpi_event(event); 773 if (!(dpi_event.flags() & ui::EF_IS_NON_CLIENT)) 774 dpi_event.UpdateForRootTransform(scale_transform); 775 delegate_->OnMouseEvent(&dpi_event); 776 return dpi_event.handled(); 777 } 778 NOTREACHED(); 779 return false; 780 } 781 782 bool NativeWidgetWin::HandleKeyEvent(const ui::KeyEvent& event) { 783 delegate_->OnKeyEvent(const_cast<ui::KeyEvent*>(&event)); 784 return event.handled(); 785 } 786 787 bool NativeWidgetWin::HandleUntranslatedKeyEvent(const ui::KeyEvent& event) { 788 InputMethod* input_method = GetInputMethod(); 789 if (input_method) 790 input_method->DispatchKeyEvent(event); 791 return !!input_method; 792 } 793 794 void NativeWidgetWin::HandleTouchEvent(const ui::TouchEvent& event) { 795 NOTREACHED() << "Touch events are not supported"; 796 } 797 798 bool NativeWidgetWin::HandleIMEMessage(UINT message, 799 WPARAM w_param, 800 LPARAM l_param, 801 LRESULT* result) { 802 InputMethod* input_method = GetInputMethod(); 803 if (!input_method || input_method->IsMock()) { 804 *result = 0; 805 return false; 806 } 807 808 MSG msg = {}; 809 msg.hwnd = message_handler_->hwnd(); 810 msg.message = message; 811 msg.wParam = w_param; 812 msg.lParam = l_param; 813 return input_method->OnUntranslatedIMEMessage(msg, result); 814 } 815 816 void NativeWidgetWin::HandleInputLanguageChange(DWORD character_set, 817 HKL input_language_id) { 818 InputMethod* input_method = GetInputMethod(); 819 if (input_method && !input_method->IsMock()) { 820 input_method->OnInputLocaleChanged(); 821 } 822 } 823 824 bool NativeWidgetWin::HandlePaintAccelerated(const gfx::Rect& invalid_rect) { 825 gfx::Rect dpi_rect = gfx::win::ScreenToDIPRect(invalid_rect); 826 return delegate_->OnNativeWidgetPaintAccelerated(dpi_rect); 827 } 828 829 void NativeWidgetWin::HandlePaint(gfx::Canvas* canvas) { 830 delegate_->OnNativeWidgetPaint(canvas); 831 } 832 833 bool NativeWidgetWin::HandleTooltipNotify(int w_param, 834 NMHDR* l_param, 835 LRESULT* l_result) { 836 // We can be sent this message before the tooltip manager is created, if a 837 // subclass overrides OnCreate and creates some kind of Windows control there 838 // that sends WM_NOTIFY messages. 839 if (tooltip_manager_.get()) { 840 bool handled; 841 *l_result = tooltip_manager_->OnNotify(w_param, l_param, &handled); 842 return handled; 843 } 844 return false; 845 } 846 847 void NativeWidgetWin::HandleTooltipMouseMove(UINT message, 848 WPARAM w_param, 849 LPARAM l_param) { 850 if (tooltip_manager_.get()) 851 tooltip_manager_->OnMouse(message, w_param, l_param); 852 } 853 854 bool NativeWidgetWin::PreHandleMSG(UINT message, 855 WPARAM w_param, 856 LPARAM l_param, 857 LRESULT* result) { 858 return false; 859 } 860 861 void NativeWidgetWin::PostHandleMSG(UINT message, 862 WPARAM w_param, 863 LPARAM l_param) { 864 } 865 866 bool NativeWidgetWin::HandleScrollEvent(const ui::ScrollEvent& event) { 867 delegate_->OnScrollEvent(const_cast<ui::ScrollEvent*>(&event)); 868 return event.handled(); 869 } 870 871 //////////////////////////////////////////////////////////////////////////////// 872 // NativeWidgetWin, private: 873 874 void NativeWidgetWin::SetInitParams(const Widget::InitParams& params) { 875 // Set non-style attributes. 876 ownership_ = params.ownership; 877 878 ConfigureWindowStyles(message_handler_.get(), params, 879 GetWidget()->widget_delegate(), delegate_); 880 881 has_non_client_view_ = Widget::RequiresNonClientView(params.type); 882 message_handler_->set_remove_standard_frame(params.remove_standard_frame); 883 message_handler_->set_use_system_default_icon(params.use_system_default_icon); 884 } 885 886 //////////////////////////////////////////////////////////////////////////////// 887 // Widget, public: 888 889 // static 890 void Widget::NotifyLocaleChanged() { 891 NOTIMPLEMENTED(); 892 } 893 894 namespace { 895 BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) { 896 Widget* widget = Widget::GetWidgetForNativeView(hwnd); 897 if (widget && widget->is_secondary_widget()) 898 widget->Close(); 899 return TRUE; 900 } 901 } // namespace 902 903 // static 904 void Widget::CloseAllSecondaryWidgets() { 905 EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0); 906 } 907 908 bool Widget::ConvertRect(const Widget* source, 909 const Widget* target, 910 gfx::Rect* rect) { 911 DCHECK(source); 912 DCHECK(target); 913 DCHECK(rect); 914 915 HWND source_hwnd = source->GetNativeView(); 916 HWND target_hwnd = target->GetNativeView(); 917 if (source_hwnd == target_hwnd) 918 return true; 919 920 RECT win_rect = gfx::win::DIPToScreenRect(*rect).ToRECT(); 921 if (::MapWindowPoints(source_hwnd, target_hwnd, 922 reinterpret_cast<LPPOINT>(&win_rect), 923 sizeof(RECT)/sizeof(POINT))) { 924 *rect = gfx::win::ScreenToDIPRect(gfx::Rect(win_rect)); 925 return true; 926 } 927 return false; 928 } 929 930 namespace internal { 931 932 //////////////////////////////////////////////////////////////////////////////// 933 // internal::NativeWidgetPrivate, public: 934 935 // static 936 NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget( 937 internal::NativeWidgetDelegate* delegate) { 938 return new NativeWidgetWin(delegate); 939 } 940 941 // static 942 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView( 943 gfx::NativeView native_view) { 944 return reinterpret_cast<NativeWidgetWin*>( 945 ViewProp::GetValue(native_view, kNativeWidgetKey)); 946 } 947 948 // static 949 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow( 950 gfx::NativeWindow native_window) { 951 return GetNativeWidgetForNativeView(native_window); 952 } 953 954 // static 955 NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget( 956 gfx::NativeView native_view) { 957 if (!native_view) 958 return NULL; 959 960 // First, check if the top-level window is a Widget. 961 HWND root = ::GetAncestor(native_view, GA_ROOT); 962 if (!root) 963 return NULL; 964 965 NativeWidgetPrivate* widget = GetNativeWidgetForNativeView(root); 966 if (widget) 967 return widget; 968 969 // Second, try to locate the last Widget window in the parent hierarchy. 970 HWND parent_hwnd = native_view; 971 // If we fail to find the native widget pointer for the root then it probably 972 // means that the root belongs to a different process in which case we walk up 973 // the native view chain looking for a parent window which corresponds to a 974 // valid native widget. We only do this if we fail to find the native widget 975 // for the current native view which means it is being destroyed. 976 if (!widget && !GetNativeWidgetForNativeView(native_view)) { 977 parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT); 978 if (!parent_hwnd) 979 return NULL; 980 } 981 NativeWidgetPrivate* parent_widget; 982 do { 983 parent_widget = GetNativeWidgetForNativeView(parent_hwnd); 984 if (parent_widget) { 985 widget = parent_widget; 986 parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT); 987 } 988 } while (parent_hwnd != NULL && parent_widget != NULL); 989 990 return widget; 991 } 992 993 // static 994 void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view, 995 Widget::Widgets* children) { 996 if (!native_view) 997 return; 998 999 Widget* widget = Widget::GetWidgetForNativeView(native_view); 1000 if (widget) 1001 children->insert(widget); 1002 EnumChildWindows(native_view, EnumerateNativeWidgets, 1003 reinterpret_cast<LPARAM>(children)); 1004 } 1005 1006 // static 1007 void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view, 1008 Widget::Widgets* owned) { 1009 if (!native_view) 1010 return; 1011 1012 Widget::Widgets all; 1013 EnumWindows(EnumerateNativeWidgets, reinterpret_cast<LPARAM>(&all)); 1014 for (Widget::Widgets::const_iterator iter = all.begin(); 1015 iter != all.end(); ++iter) { 1016 if (native_view == GetWindow((*iter)->GetNativeView(), GW_OWNER)) 1017 owned->insert(*iter); 1018 } 1019 } 1020 1021 // static 1022 void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view, 1023 gfx::NativeView new_parent) { 1024 if (!native_view) 1025 return; 1026 1027 HWND previous_parent = ::GetParent(native_view); 1028 if (previous_parent == new_parent) 1029 return; 1030 1031 Widget::Widgets widgets; 1032 GetAllChildWidgets(native_view, &widgets); 1033 1034 // First notify all the widgets that they are being disassociated 1035 // from their previous parent. 1036 for (Widget::Widgets::iterator it = widgets.begin(); 1037 it != widgets.end(); ++it) { 1038 (*it)->NotifyNativeViewHierarchyWillChange(); 1039 } 1040 1041 ::SetParent(native_view, new_parent); 1042 1043 // And now, notify them that they have a brand new parent. 1044 for (Widget::Widgets::iterator it = widgets.begin(); 1045 it != widgets.end(); ++it) { 1046 (*it)->NotifyNativeViewHierarchyChanged(); 1047 } 1048 } 1049 1050 // static 1051 bool NativeWidgetPrivate::IsMouseButtonDown() { 1052 return (GetKeyState(VK_LBUTTON) & 0x80) || 1053 (GetKeyState(VK_RBUTTON) & 0x80) || 1054 (GetKeyState(VK_MBUTTON) & 0x80) || 1055 (GetKeyState(VK_XBUTTON1) & 0x80) || 1056 (GetKeyState(VK_XBUTTON2) & 0x80); 1057 } 1058 1059 // static 1060 bool NativeWidgetPrivate::IsTouchDown() { 1061 // This currently isn't necessary because we're not generating touch events on 1062 // windows. When we do, this will need to be updated. 1063 return false; 1064 } 1065 1066 } // namespace internal 1067 1068 } // namespace views 1069