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