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/widget.h" 6 7 #include "base/debug/trace_event.h" 8 #include "base/logging.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "ui/base/default_theme_provider.h" 12 #include "ui/base/events/event.h" 13 #include "ui/base/hit_test.h" 14 #include "ui/base/l10n/l10n_font_util.h" 15 #include "ui/base/resource/resource_bundle.h" 16 #include "ui/compositor/compositor.h" 17 #include "ui/compositor/layer.h" 18 #include "ui/gfx/screen.h" 19 #include "ui/views/focus/focus_manager.h" 20 #include "ui/views/focus/focus_manager_factory.h" 21 #include "ui/views/focus/view_storage.h" 22 #include "ui/views/focus/widget_focus_manager.h" 23 #include "ui/views/ime/input_method.h" 24 #include "ui/views/views_delegate.h" 25 #include "ui/views/widget/native_widget_private.h" 26 #include "ui/views/widget/root_view.h" 27 #include "ui/views/widget/tooltip_manager.h" 28 #include "ui/views/widget/widget_delegate.h" 29 #include "ui/views/widget/widget_deletion_observer.h" 30 #include "ui/views/widget/widget_observer.h" 31 #include "ui/views/window/custom_frame_view.h" 32 33 #if !defined(OS_MACOSX) 34 #include "ui/views/controls/menu/menu_controller.h" 35 #endif 36 37 namespace views { 38 39 namespace { 40 41 // If |view| has a layer the layer is added to |layers|. Else this recurses 42 // through the children. This is used to build a list of the layers created by 43 // views that are direct children of the Widgets layer. 44 void BuildRootLayers(View* view, std::vector<ui::Layer*>* layers) { 45 if (view->layer()) { 46 layers->push_back(view->layer()); 47 } else { 48 for (int i = 0; i < view->child_count(); ++i) 49 BuildRootLayers(view->child_at(i), layers); 50 } 51 } 52 53 // Create a native widget implementation. 54 // First, use the supplied one if non-NULL. 55 // Finally, make a default one. 56 NativeWidget* CreateNativeWidget(NativeWidget* native_widget, 57 internal::NativeWidgetDelegate* delegate) { 58 if (!native_widget) { 59 native_widget = 60 internal::NativeWidgetPrivate::CreateNativeWidget(delegate); 61 } 62 return native_widget; 63 } 64 65 } // namespace 66 67 // A default implementation of WidgetDelegate, used by Widget when no 68 // WidgetDelegate is supplied. 69 class DefaultWidgetDelegate : public WidgetDelegate { 70 public: 71 DefaultWidgetDelegate(Widget* widget, const Widget::InitParams& params) 72 : widget_(widget), 73 can_activate_(!params.child && 74 params.type != Widget::InitParams::TYPE_POPUP) { 75 } 76 virtual ~DefaultWidgetDelegate() {} 77 78 // Overridden from WidgetDelegate: 79 virtual void DeleteDelegate() OVERRIDE { 80 delete this; 81 } 82 virtual Widget* GetWidget() OVERRIDE { 83 return widget_; 84 } 85 virtual const Widget* GetWidget() const OVERRIDE { 86 return widget_; 87 } 88 89 virtual bool CanActivate() const OVERRIDE { 90 return can_activate_; 91 } 92 93 private: 94 Widget* widget_; 95 bool can_activate_; 96 97 DISALLOW_COPY_AND_ASSIGN(DefaultWidgetDelegate); 98 }; 99 100 //////////////////////////////////////////////////////////////////////////////// 101 // Widget, InitParams: 102 103 Widget::InitParams::InitParams() 104 : type(TYPE_WINDOW), 105 delegate(NULL), 106 child(false), 107 opacity((ViewsDelegate::views_delegate && 108 ViewsDelegate::views_delegate->UseTransparentWindows()) ? 109 TRANSLUCENT_WINDOW : INFER_OPACITY), 110 accept_events(true), 111 can_activate(true), 112 keep_on_top(false), 113 ownership(NATIVE_WIDGET_OWNS_WIDGET), 114 mirror_origin_in_rtl(false), 115 has_dropshadow(false), 116 remove_standard_frame(false), 117 use_system_default_icon(false), 118 show_state(ui::SHOW_STATE_DEFAULT), 119 double_buffer(false), 120 parent(NULL), 121 native_widget(NULL), 122 desktop_root_window_host(NULL), 123 top_level(false), 124 layer_type(ui::LAYER_TEXTURED), 125 context(NULL) { 126 } 127 128 Widget::InitParams::InitParams(Type type) 129 : type(type), 130 delegate(NULL), 131 child(type == TYPE_CONTROL), 132 opacity(((type == TYPE_WINDOW || type == TYPE_PANEL) && 133 ViewsDelegate::views_delegate && 134 ViewsDelegate::views_delegate->UseTransparentWindows()) ? 135 TRANSLUCENT_WINDOW : INFER_OPACITY), 136 accept_events(true), 137 can_activate(type != TYPE_POPUP && type != TYPE_MENU), 138 keep_on_top(type == TYPE_MENU), 139 ownership(NATIVE_WIDGET_OWNS_WIDGET), 140 mirror_origin_in_rtl(false), 141 has_dropshadow(false), 142 remove_standard_frame(false), 143 use_system_default_icon(false), 144 show_state(ui::SHOW_STATE_DEFAULT), 145 double_buffer(false), 146 parent(NULL), 147 native_widget(NULL), 148 desktop_root_window_host(NULL), 149 top_level(false), 150 layer_type(ui::LAYER_TEXTURED), 151 context(NULL) { 152 } 153 154 //////////////////////////////////////////////////////////////////////////////// 155 // Widget, public: 156 157 Widget::Widget() 158 : native_widget_(NULL), 159 widget_delegate_(NULL), 160 non_client_view_(NULL), 161 dragged_view_(NULL), 162 ownership_(InitParams::NATIVE_WIDGET_OWNS_WIDGET), 163 is_secondary_widget_(true), 164 frame_type_(FRAME_TYPE_DEFAULT), 165 disable_inactive_rendering_(false), 166 widget_closed_(false), 167 saved_show_state_(ui::SHOW_STATE_DEFAULT), 168 focus_on_creation_(true), 169 is_top_level_(false), 170 native_widget_initialized_(false), 171 native_widget_destroyed_(false), 172 is_mouse_button_pressed_(false), 173 is_touch_down_(false), 174 last_mouse_event_was_move_(false), 175 root_layers_dirty_(false), 176 movement_disabled_(false) { 177 } 178 179 Widget::~Widget() { 180 DestroyRootView(); 181 if (ownership_ == InitParams::WIDGET_OWNS_NATIVE_WIDGET) { 182 delete native_widget_; 183 } else { 184 DCHECK(native_widget_destroyed_) 185 << "Destroying a widget with a live native widget. " 186 << "Widget probably should use WIDGET_OWNS_NATIVE_WIDGET ownership."; 187 } 188 } 189 190 // static 191 Widget* Widget::CreateWindow(WidgetDelegate* delegate) { 192 return CreateWindowWithBounds(delegate, gfx::Rect()); 193 } 194 195 // static 196 Widget* Widget::CreateWindowWithBounds(WidgetDelegate* delegate, 197 const gfx::Rect& bounds) { 198 Widget* widget = new Widget; 199 Widget::InitParams params; 200 params.bounds = bounds; 201 params.delegate = delegate; 202 params.top_level = true; 203 widget->Init(params); 204 return widget; 205 } 206 207 // static 208 Widget* Widget::CreateWindowWithParent(WidgetDelegate* delegate, 209 gfx::NativeWindow parent) { 210 return CreateWindowWithParentAndBounds(delegate, parent, gfx::Rect()); 211 } 212 213 // static 214 Widget* Widget::CreateWindowWithParentAndBounds(WidgetDelegate* delegate, 215 gfx::NativeWindow parent, 216 const gfx::Rect& bounds) { 217 Widget* widget = new Widget; 218 Widget::InitParams params; 219 params.delegate = delegate; 220 params.parent = parent; 221 params.bounds = bounds; 222 widget->Init(params); 223 return widget; 224 } 225 226 // static 227 Widget* Widget::CreateWindowWithContext(WidgetDelegate* delegate, 228 gfx::NativeView context) { 229 return CreateWindowWithContextAndBounds(delegate, context, gfx::Rect()); 230 } 231 232 // static 233 Widget* Widget::CreateWindowWithContextAndBounds(WidgetDelegate* delegate, 234 gfx::NativeView context, 235 const gfx::Rect& bounds) { 236 Widget* widget = new Widget; 237 Widget::InitParams params; 238 params.delegate = delegate; 239 params.context = context; 240 params.bounds = bounds; 241 widget->Init(params); 242 return widget; 243 } 244 245 // static 246 Widget* Widget::GetWidgetForNativeView(gfx::NativeView native_view) { 247 internal::NativeWidgetPrivate* native_widget = 248 internal::NativeWidgetPrivate::GetNativeWidgetForNativeView(native_view); 249 return native_widget ? native_widget->GetWidget() : NULL; 250 } 251 252 // static 253 Widget* Widget::GetWidgetForNativeWindow(gfx::NativeWindow native_window) { 254 internal::NativeWidgetPrivate* native_widget = 255 internal::NativeWidgetPrivate::GetNativeWidgetForNativeWindow( 256 native_window); 257 return native_widget ? native_widget->GetWidget() : NULL; 258 } 259 260 // static 261 Widget* Widget::GetTopLevelWidgetForNativeView(gfx::NativeView native_view) { 262 internal::NativeWidgetPrivate* native_widget = 263 internal::NativeWidgetPrivate::GetTopLevelNativeWidget(native_view); 264 return native_widget ? native_widget->GetWidget() : NULL; 265 } 266 267 268 // static 269 void Widget::GetAllChildWidgets(gfx::NativeView native_view, 270 Widgets* children) { 271 internal::NativeWidgetPrivate::GetAllChildWidgets(native_view, children); 272 } 273 274 // static 275 void Widget::ReparentNativeView(gfx::NativeView native_view, 276 gfx::NativeView new_parent) { 277 internal::NativeWidgetPrivate::ReparentNativeView(native_view, new_parent); 278 } 279 280 // static 281 int Widget::GetLocalizedContentsWidth(int col_resource_id) { 282 return ui::GetLocalizedContentsWidthForFont(col_resource_id, 283 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); 284 } 285 286 // static 287 int Widget::GetLocalizedContentsHeight(int row_resource_id) { 288 return ui::GetLocalizedContentsHeightForFont(row_resource_id, 289 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); 290 } 291 292 // static 293 gfx::Size Widget::GetLocalizedContentsSize(int col_resource_id, 294 int row_resource_id) { 295 return gfx::Size(GetLocalizedContentsWidth(col_resource_id), 296 GetLocalizedContentsHeight(row_resource_id)); 297 } 298 299 // static 300 bool Widget::RequiresNonClientView(InitParams::Type type) { 301 return type == InitParams::TYPE_WINDOW || 302 type == InitParams::TYPE_PANEL || 303 type == InitParams::TYPE_BUBBLE; 304 } 305 306 void Widget::Init(const InitParams& in_params) { 307 TRACE_EVENT0("views", "Widget::Init"); 308 InitParams params = in_params; 309 310 is_top_level_ = params.top_level || 311 (!params.child && 312 params.type != InitParams::TYPE_CONTROL && 313 params.type != InitParams::TYPE_TOOLTIP); 314 params.top_level = is_top_level_; 315 if (params.opacity == InitParams::INFER_OPACITY) { 316 #if defined(OS_WIN) && defined(USE_AURA) 317 // By default, make all top-level windows but the main window transparent 318 // initially so that they can be made to fade in. 319 if (is_top_level_ && params.type != InitParams::TYPE_WINDOW) 320 params.opacity = InitParams::TRANSLUCENT_WINDOW; 321 else 322 params.opacity = InitParams::OPAQUE_WINDOW; 323 #else 324 params.opacity = InitParams::OPAQUE_WINDOW; 325 #endif 326 } 327 328 if (ViewsDelegate::views_delegate) 329 ViewsDelegate::views_delegate->OnBeforeWidgetInit(¶ms, this); 330 331 widget_delegate_ = params.delegate ? 332 params.delegate : new DefaultWidgetDelegate(this, params); 333 ownership_ = params.ownership; 334 native_widget_ = CreateNativeWidget(params.native_widget, this)-> 335 AsNativeWidgetPrivate(); 336 root_view_.reset(CreateRootView()); 337 default_theme_provider_.reset(new ui::DefaultThemeProvider); 338 if (params.type == InitParams::TYPE_MENU) { 339 is_mouse_button_pressed_ = 340 internal::NativeWidgetPrivate::IsMouseButtonDown(); 341 } 342 native_widget_->InitNativeWidget(params); 343 if (RequiresNonClientView(params.type)) { 344 non_client_view_ = new NonClientView; 345 non_client_view_->SetFrameView(CreateNonClientFrameView()); 346 // Create the ClientView, add it to the NonClientView and add the 347 // NonClientView to the RootView. This will cause everything to be parented. 348 non_client_view_->set_client_view(widget_delegate_->CreateClientView(this)); 349 non_client_view_->SetOverlayView(widget_delegate_->CreateOverlayView()); 350 SetContentsView(non_client_view_); 351 // Initialize the window's title before setting the window's initial bounds; 352 // the frame view's preferred height may depend on the presence of a title. 353 UpdateWindowTitle(); 354 SetInitialBounds(params.bounds); 355 if (params.show_state == ui::SHOW_STATE_MAXIMIZED) 356 Maximize(); 357 else if (params.show_state == ui::SHOW_STATE_MINIMIZED) 358 Minimize(); 359 } else if (params.delegate) { 360 SetContentsView(params.delegate->GetContentsView()); 361 SetInitialBoundsForFramelessWindow(params.bounds); 362 } 363 native_widget_initialized_ = true; 364 } 365 366 // Unconverted methods (see header) -------------------------------------------- 367 368 gfx::NativeView Widget::GetNativeView() const { 369 return native_widget_->GetNativeView(); 370 } 371 372 gfx::NativeWindow Widget::GetNativeWindow() const { 373 return native_widget_->GetNativeWindow(); 374 } 375 376 void Widget::AddObserver(WidgetObserver* observer) { 377 observers_.AddObserver(observer); 378 } 379 380 void Widget::RemoveObserver(WidgetObserver* observer) { 381 observers_.RemoveObserver(observer); 382 } 383 384 bool Widget::HasObserver(WidgetObserver* observer) { 385 return observers_.HasObserver(observer); 386 } 387 388 bool Widget::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { 389 return false; 390 } 391 392 void Widget::ViewHierarchyChanged( 393 const View::ViewHierarchyChangedDetails& details) { 394 if (!details.is_add) { 395 if (details.child == dragged_view_) 396 dragged_view_ = NULL; 397 FocusManager* focus_manager = GetFocusManager(); 398 if (focus_manager) 399 focus_manager->ViewRemoved(details.child); 400 ViewStorage::GetInstance()->ViewRemoved(details.child); 401 native_widget_->ViewRemoved(details.child); 402 } 403 } 404 405 void Widget::NotifyNativeViewHierarchyChanged(bool attached, 406 gfx::NativeView native_view) { 407 if (!attached) { 408 FocusManager* focus_manager = GetFocusManager(); 409 // We are being removed from a window hierarchy. Treat this as 410 // the root_view_ being removed. 411 if (focus_manager) 412 focus_manager->ViewRemoved(root_view_.get()); 413 } 414 root_view_->NotifyNativeViewHierarchyChanged(attached, native_view); 415 } 416 417 // Converted methods (see header) ---------------------------------------------- 418 419 Widget* Widget::GetTopLevelWidget() { 420 return const_cast<Widget*>( 421 static_cast<const Widget*>(this)->GetTopLevelWidget()); 422 } 423 424 const Widget* Widget::GetTopLevelWidget() const { 425 // GetTopLevelNativeWidget doesn't work during destruction because 426 // property is gone after gobject gets deleted. Short circuit here 427 // for toplevel so that InputMethod can remove itself from 428 // focus manager. 429 return is_top_level() ? this : native_widget_->GetTopLevelWidget(); 430 } 431 432 void Widget::SetContentsView(View* view) { 433 // Do not SetContentsView() again if it is already set to the same view. 434 if (view == GetContentsView()) 435 return; 436 root_view_->SetContentsView(view); 437 if (non_client_view_ != view) { 438 // |non_client_view_| can only be non-NULL here if RequiresNonClientView() 439 // was true when the widget was initialized. Creating widgets with non 440 // client views and then setting the contents view can cause subtle 441 // problems on Windows, where the native widget thinks there is still a 442 // |non_client_view_|. If you get this error, either use a different type 443 // when initializing the widget, or don't call SetContentsView(). 444 DCHECK(!non_client_view_); 445 non_client_view_ = NULL; 446 } 447 } 448 449 View* Widget::GetContentsView() { 450 return root_view_->GetContentsView(); 451 } 452 453 gfx::Rect Widget::GetWindowBoundsInScreen() const { 454 return native_widget_->GetWindowBoundsInScreen(); 455 } 456 457 gfx::Rect Widget::GetClientAreaBoundsInScreen() const { 458 return native_widget_->GetClientAreaBoundsInScreen(); 459 } 460 461 gfx::Rect Widget::GetRestoredBounds() const { 462 return native_widget_->GetRestoredBounds(); 463 } 464 465 void Widget::SetBounds(const gfx::Rect& bounds) { 466 native_widget_->SetBounds(bounds); 467 } 468 469 void Widget::SetSize(const gfx::Size& size) { 470 native_widget_->SetSize(size); 471 } 472 473 void Widget::CenterWindow(const gfx::Size& size) { 474 native_widget_->CenterWindow(size); 475 } 476 477 void Widget::SetBoundsConstrained(const gfx::Rect& bounds) { 478 gfx::Rect work_area = 479 gfx::Screen::GetScreenFor(GetNativeView())->GetDisplayNearestPoint( 480 bounds.origin()).work_area(); 481 if (work_area.IsEmpty()) { 482 SetBounds(bounds); 483 } else { 484 // Inset the work area slightly. 485 work_area.Inset(10, 10, 10, 10); 486 work_area.AdjustToFit(bounds); 487 SetBounds(work_area); 488 } 489 } 490 491 void Widget::SetVisibilityChangedAnimationsEnabled(bool value) { 492 native_widget_->SetVisibilityChangedAnimationsEnabled(value); 493 } 494 495 Widget::MoveLoopResult Widget::RunMoveLoop(const gfx::Vector2d& drag_offset, 496 MoveLoopSource source) { 497 return native_widget_->RunMoveLoop(drag_offset, source); 498 } 499 500 void Widget::EndMoveLoop() { 501 native_widget_->EndMoveLoop(); 502 } 503 504 void Widget::StackAboveWidget(Widget* widget) { 505 native_widget_->StackAbove(widget->GetNativeView()); 506 } 507 508 void Widget::StackAbove(gfx::NativeView native_view) { 509 native_widget_->StackAbove(native_view); 510 } 511 512 void Widget::StackAtTop() { 513 native_widget_->StackAtTop(); 514 } 515 516 void Widget::StackBelow(gfx::NativeView native_view) { 517 native_widget_->StackBelow(native_view); 518 } 519 520 void Widget::SetShape(gfx::NativeRegion shape) { 521 native_widget_->SetShape(shape); 522 } 523 524 void Widget::Close() { 525 if (widget_closed_) { 526 // It appears we can hit this code path if you close a modal dialog then 527 // close the last browser before the destructor is hit, which triggers 528 // invoking Close again. 529 return; 530 } 531 532 bool can_close = true; 533 if (non_client_view_) 534 can_close = non_client_view_->CanClose(); 535 if (can_close) { 536 SaveWindowPlacement(); 537 538 // During tear-down the top-level focus manager becomes unavailable to 539 // GTK tabbed panes and their children, so normal deregistration via 540 // |FormManager::ViewRemoved()| calls are fouled. We clear focus here 541 // to avoid these redundant steps and to avoid accessing deleted views 542 // that may have been in focus. 543 if (is_top_level() && focus_manager_.get()) 544 focus_manager_->SetFocusedView(NULL); 545 546 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetClosing(this)); 547 native_widget_->Close(); 548 widget_closed_ = true; 549 } 550 } 551 552 void Widget::CloseNow() { 553 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetClosing(this)); 554 native_widget_->CloseNow(); 555 } 556 557 bool Widget::IsClosed() const { 558 return widget_closed_; 559 } 560 561 void Widget::Show() { 562 TRACE_EVENT0("views", "Widget::Show"); 563 if (non_client_view_) { 564 #if defined(OS_MACOSX) 565 // On the Mac the FullScreenBookmarkBar test is different then for any other 566 // OS. Since the new maximize logic from ash does not apply to the mac, we 567 // continue to ignore the fullscreen mode here. 568 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED && 569 !initial_restored_bounds_.IsEmpty()) { 570 native_widget_->ShowMaximizedWithBounds(initial_restored_bounds_); 571 } else { 572 native_widget_->ShowWithWindowState(saved_show_state_); 573 } 574 #else 575 // While initializing, the kiosk mode will go to full screen before the 576 // widget gets shown. In that case we stay in full screen mode, regardless 577 // of the |saved_show_state_| member. 578 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED && 579 !initial_restored_bounds_.IsEmpty() && 580 !IsFullscreen()) { 581 native_widget_->ShowMaximizedWithBounds(initial_restored_bounds_); 582 } else { 583 native_widget_->ShowWithWindowState( 584 IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN : saved_show_state_); 585 } 586 #endif 587 // |saved_show_state_| only applies the first time the window is shown. 588 // If we don't reset the value the window may be shown maximized every time 589 // it is subsequently shown after being hidden. 590 saved_show_state_ = ui::SHOW_STATE_NORMAL; 591 } else { 592 native_widget_->Show(); 593 } 594 } 595 596 void Widget::Hide() { 597 native_widget_->Hide(); 598 } 599 600 void Widget::ShowInactive() { 601 // If this gets called with saved_show_state_ == ui::SHOW_STATE_MAXIMIZED, 602 // call SetBounds()with the restored bounds to set the correct size. This 603 // normally should not happen, but if it does we should avoid showing unsized 604 // windows. 605 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED && 606 !initial_restored_bounds_.IsEmpty()) { 607 SetBounds(initial_restored_bounds_); 608 saved_show_state_ = ui::SHOW_STATE_NORMAL; 609 } 610 native_widget_->ShowWithWindowState(ui::SHOW_STATE_INACTIVE); 611 } 612 613 void Widget::Activate() { 614 native_widget_->Activate(); 615 } 616 617 void Widget::Deactivate() { 618 native_widget_->Deactivate(); 619 } 620 621 bool Widget::IsActive() const { 622 return native_widget_->IsActive(); 623 } 624 625 void Widget::DisableInactiveRendering() { 626 SetInactiveRenderingDisabled(true); 627 } 628 629 void Widget::SetAlwaysOnTop(bool on_top) { 630 native_widget_->SetAlwaysOnTop(on_top); 631 } 632 633 void Widget::Maximize() { 634 native_widget_->Maximize(); 635 } 636 637 void Widget::Minimize() { 638 native_widget_->Minimize(); 639 } 640 641 void Widget::Restore() { 642 native_widget_->Restore(); 643 } 644 645 bool Widget::IsMaximized() const { 646 return native_widget_->IsMaximized(); 647 } 648 649 bool Widget::IsMinimized() const { 650 return native_widget_->IsMinimized(); 651 } 652 653 void Widget::SetFullscreen(bool fullscreen) { 654 native_widget_->SetFullscreen(fullscreen); 655 } 656 657 bool Widget::IsFullscreen() const { 658 return native_widget_->IsFullscreen(); 659 } 660 661 void Widget::SetOpacity(unsigned char opacity) { 662 native_widget_->SetOpacity(opacity); 663 } 664 665 void Widget::SetUseDragFrame(bool use_drag_frame) { 666 native_widget_->SetUseDragFrame(use_drag_frame); 667 } 668 669 void Widget::FlashFrame(bool flash) { 670 native_widget_->FlashFrame(flash); 671 } 672 673 View* Widget::GetRootView() { 674 return root_view_.get(); 675 } 676 677 const View* Widget::GetRootView() const { 678 return root_view_.get(); 679 } 680 681 bool Widget::IsVisible() const { 682 return native_widget_->IsVisible(); 683 } 684 685 ui::ThemeProvider* Widget::GetThemeProvider() const { 686 const Widget* root_widget = GetTopLevelWidget(); 687 if (root_widget && root_widget != this) { 688 // Attempt to get the theme provider, and fall back to the default theme 689 // provider if not found. 690 ui::ThemeProvider* provider = root_widget->GetThemeProvider(); 691 if (provider) 692 return provider; 693 694 provider = root_widget->default_theme_provider_.get(); 695 if (provider) 696 return provider; 697 } 698 return default_theme_provider_.get(); 699 } 700 701 const ui::NativeTheme* Widget::GetNativeTheme() const { 702 return native_widget_->GetNativeTheme(); 703 } 704 705 FocusManager* Widget::GetFocusManager() { 706 Widget* toplevel_widget = GetTopLevelWidget(); 707 return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; 708 } 709 710 const FocusManager* Widget::GetFocusManager() const { 711 const Widget* toplevel_widget = GetTopLevelWidget(); 712 return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; 713 } 714 715 InputMethod* Widget::GetInputMethod() { 716 return const_cast<InputMethod*>( 717 const_cast<const Widget*>(this)->GetInputMethod()); 718 } 719 720 const InputMethod* Widget::GetInputMethod() const { 721 if (is_top_level()) { 722 if (!input_method_.get()) 723 input_method_ = const_cast<Widget*>(this)->CreateInputMethod().Pass(); 724 return input_method_.get(); 725 } else { 726 const Widget* toplevel = GetTopLevelWidget(); 727 // If GetTopLevelWidget() returns itself which is not toplevel, 728 // the widget is detached from toplevel widget. 729 // TODO(oshima): Fix GetTopLevelWidget() to return NULL 730 // if there is no toplevel. We probably need to add GetTopMostWidget() 731 // to replace some use cases. 732 return (toplevel && toplevel != this) ? toplevel->GetInputMethod() : NULL; 733 } 734 } 735 736 void Widget::RunShellDrag(View* view, 737 const ui::OSExchangeData& data, 738 const gfx::Point& location, 739 int operation, 740 ui::DragDropTypes::DragEventSource source) { 741 dragged_view_ = view; 742 native_widget_->RunShellDrag(view, data, location, operation, source); 743 // If the view is removed during the drag operation, dragged_view_ is set to 744 // NULL. 745 if (view && dragged_view_ == view) { 746 dragged_view_ = NULL; 747 view->OnDragDone(); 748 } 749 } 750 751 void Widget::SchedulePaintInRect(const gfx::Rect& rect) { 752 native_widget_->SchedulePaintInRect(rect); 753 } 754 755 void Widget::SetCursor(gfx::NativeCursor cursor) { 756 native_widget_->SetCursor(cursor); 757 } 758 759 bool Widget::IsMouseEventsEnabled() const { 760 return native_widget_->IsMouseEventsEnabled(); 761 } 762 763 void Widget::SetNativeWindowProperty(const char* name, void* value) { 764 native_widget_->SetNativeWindowProperty(name, value); 765 } 766 767 void* Widget::GetNativeWindowProperty(const char* name) const { 768 return native_widget_->GetNativeWindowProperty(name); 769 } 770 771 void Widget::UpdateWindowTitle() { 772 if (!non_client_view_) 773 return; 774 775 // Update the native frame's text. We do this regardless of whether or not 776 // the native frame is being used, since this also updates the taskbar, etc. 777 string16 window_title = widget_delegate_->GetWindowTitle(); 778 base::i18n::AdjustStringForLocaleDirection(&window_title); 779 native_widget_->SetWindowTitle(window_title); 780 non_client_view_->UpdateWindowTitle(); 781 782 // If the non-client view is rendering its own title, it'll need to relayout 783 // now and to get a paint update later on. 784 non_client_view_->Layout(); 785 } 786 787 void Widget::UpdateWindowIcon() { 788 if (non_client_view_) 789 non_client_view_->UpdateWindowIcon(); 790 native_widget_->SetWindowIcons(widget_delegate_->GetWindowIcon(), 791 widget_delegate_->GetWindowAppIcon()); 792 } 793 794 FocusTraversable* Widget::GetFocusTraversable() { 795 return static_cast<internal::RootView*>(root_view_.get()); 796 } 797 798 void Widget::ThemeChanged() { 799 root_view_->ThemeChanged(); 800 } 801 802 void Widget::LocaleChanged() { 803 root_view_->LocaleChanged(); 804 } 805 806 void Widget::SetFocusTraversableParent(FocusTraversable* parent) { 807 root_view_->SetFocusTraversableParent(parent); 808 } 809 810 void Widget::SetFocusTraversableParentView(View* parent_view) { 811 root_view_->SetFocusTraversableParentView(parent_view); 812 } 813 814 void Widget::ClearNativeFocus() { 815 native_widget_->ClearNativeFocus(); 816 } 817 818 NonClientFrameView* Widget::CreateNonClientFrameView() { 819 NonClientFrameView* frame_view = 820 widget_delegate_->CreateNonClientFrameView(this); 821 if (!frame_view) 822 frame_view = native_widget_->CreateNonClientFrameView(); 823 if (!frame_view && ViewsDelegate::views_delegate) { 824 frame_view = 825 ViewsDelegate::views_delegate->CreateDefaultNonClientFrameView(this); 826 } 827 if (frame_view) 828 return frame_view; 829 830 CustomFrameView* custom_frame_view = new CustomFrameView; 831 custom_frame_view->Init(this); 832 return custom_frame_view; 833 } 834 835 bool Widget::ShouldUseNativeFrame() const { 836 if (frame_type_ != FRAME_TYPE_DEFAULT) 837 return frame_type_ == FRAME_TYPE_FORCE_NATIVE; 838 return native_widget_->ShouldUseNativeFrame(); 839 } 840 841 void Widget::DebugToggleFrameType() { 842 if (frame_type_ == FRAME_TYPE_DEFAULT) { 843 frame_type_ = ShouldUseNativeFrame() ? FRAME_TYPE_FORCE_CUSTOM : 844 FRAME_TYPE_FORCE_NATIVE; 845 } else { 846 frame_type_ = frame_type_ == FRAME_TYPE_FORCE_CUSTOM ? 847 FRAME_TYPE_FORCE_NATIVE : FRAME_TYPE_FORCE_CUSTOM; 848 } 849 FrameTypeChanged(); 850 } 851 852 void Widget::FrameTypeChanged() { 853 native_widget_->FrameTypeChanged(); 854 } 855 856 const ui::Compositor* Widget::GetCompositor() const { 857 return native_widget_->GetCompositor(); 858 } 859 860 ui::Compositor* Widget::GetCompositor() { 861 return native_widget_->GetCompositor(); 862 } 863 864 ui::Layer* Widget::GetLayer() { 865 return native_widget_->GetLayer(); 866 } 867 868 void Widget::ReorderNativeViews() { 869 native_widget_->ReorderNativeViews(); 870 } 871 872 void Widget::UpdateRootLayers() { 873 // Calculate the layers requires traversing the tree, and since nearly any 874 // mutation of the tree can trigger this call we delay until absolutely 875 // necessary. 876 root_layers_dirty_ = true; 877 } 878 879 const NativeWidget* Widget::native_widget() const { 880 return native_widget_; 881 } 882 883 NativeWidget* Widget::native_widget() { 884 return native_widget_; 885 } 886 887 void Widget::SetCapture(View* view) { 888 if (internal::NativeWidgetPrivate::IsMouseButtonDown()) 889 is_mouse_button_pressed_ = true; 890 if (internal::NativeWidgetPrivate::IsTouchDown()) 891 is_touch_down_ = true; 892 root_view_->SetMouseHandler(view); 893 if (!native_widget_->HasCapture()) 894 native_widget_->SetCapture(); 895 } 896 897 void Widget::ReleaseCapture() { 898 if (native_widget_->HasCapture()) 899 native_widget_->ReleaseCapture(); 900 } 901 902 bool Widget::HasCapture() { 903 return native_widget_->HasCapture(); 904 } 905 906 void Widget::TooltipTextChanged(View* view) { 907 TooltipManager* manager = native_widget_private()->GetTooltipManager(); 908 if (manager) 909 manager->TooltipTextChanged(view); 910 } 911 912 bool Widget::SetInitialFocus() { 913 View* v = widget_delegate_->GetInitiallyFocusedView(); 914 if (!focus_on_creation_) { 915 // If not focusing the window now, tell the focus manager which view to 916 // focus when the window is restored. 917 if (v) 918 focus_manager_->SetStoredFocusView(v); 919 return true; 920 } 921 if (v) 922 v->RequestFocus(); 923 return !!v; 924 } 925 926 View* Widget::GetChildViewParent() { 927 return GetContentsView() ? GetContentsView() : GetRootView(); 928 } 929 930 gfx::Rect Widget::GetWorkAreaBoundsInScreen() const { 931 return native_widget_->GetWorkAreaBoundsInScreen(); 932 } 933 934 void Widget::SynthesizeMouseMoveEvent() { 935 last_mouse_event_was_move_ = false; 936 ui::MouseEvent mouse_event(ui::ET_MOUSE_MOVED, 937 last_mouse_event_position_, 938 last_mouse_event_position_, 939 ui::EF_IS_SYNTHESIZED); 940 root_view_->OnMouseMoved(mouse_event); 941 } 942 943 void Widget::OnOwnerClosing() { 944 } 945 946 //////////////////////////////////////////////////////////////////////////////// 947 // Widget, NativeWidgetDelegate implementation: 948 949 bool Widget::IsModal() const { 950 return widget_delegate_->GetModalType() != ui::MODAL_TYPE_NONE; 951 } 952 953 bool Widget::IsDialogBox() const { 954 return !!widget_delegate_->AsDialogDelegate(); 955 } 956 957 bool Widget::CanActivate() const { 958 return widget_delegate_->CanActivate(); 959 } 960 961 bool Widget::IsInactiveRenderingDisabled() const { 962 return disable_inactive_rendering_; 963 } 964 965 void Widget::EnableInactiveRendering() { 966 SetInactiveRenderingDisabled(false); 967 } 968 969 void Widget::OnNativeWidgetActivationChanged(bool active) { 970 // On windows we may end up here before we've completed initialization (from 971 // an WM_NCACTIVATE). If that happens the WidgetDelegate likely doesn't know 972 // the Widget and will crash attempting to access it. 973 if (!active && native_widget_initialized_) 974 SaveWindowPlacement(); 975 976 FOR_EACH_OBSERVER(WidgetObserver, observers_, 977 OnWidgetActivationChanged(this, active)); 978 } 979 980 void Widget::OnNativeFocus(gfx::NativeView old_focused_view) { 981 WidgetFocusManager::GetInstance()->OnWidgetFocusEvent(old_focused_view, 982 GetNativeView()); 983 } 984 985 void Widget::OnNativeBlur(gfx::NativeView new_focused_view) { 986 WidgetFocusManager::GetInstance()->OnWidgetFocusEvent(GetNativeView(), 987 new_focused_view); 988 } 989 990 void Widget::OnNativeWidgetVisibilityChanged(bool visible) { 991 View* root = GetRootView(); 992 if (root) 993 root->PropagateVisibilityNotifications(root, visible); 994 FOR_EACH_OBSERVER(WidgetObserver, observers_, 995 OnWidgetVisibilityChanged(this, visible)); 996 if (GetCompositor() && root && root->layer()) 997 root->layer()->SetVisible(visible); 998 } 999 1000 void Widget::OnNativeWidgetCreated(bool desktop_widget) { 1001 if (is_top_level()) 1002 focus_manager_.reset(FocusManagerFactory::Create(this, desktop_widget)); 1003 1004 native_widget_->InitModalType(widget_delegate_->GetModalType()); 1005 1006 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetCreated(this)); 1007 } 1008 1009 void Widget::OnNativeWidgetDestroying() { 1010 // Tell the focus manager (if any) that root_view is being removed 1011 // in case that the focused view is under this root view. 1012 if (GetFocusManager()) 1013 GetFocusManager()->ViewRemoved(root_view_.get()); 1014 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetDestroying(this)); 1015 if (non_client_view_) 1016 non_client_view_->WindowClosing(); 1017 widget_delegate_->WindowClosing(); 1018 } 1019 1020 void Widget::OnNativeWidgetDestroyed() { 1021 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetDestroyed(this)); 1022 widget_delegate_->DeleteDelegate(); 1023 widget_delegate_ = NULL; 1024 native_widget_destroyed_ = true; 1025 } 1026 1027 gfx::Size Widget::GetMinimumSize() { 1028 return non_client_view_ ? non_client_view_->GetMinimumSize() : gfx::Size(); 1029 } 1030 1031 gfx::Size Widget::GetMaximumSize() { 1032 return non_client_view_ ? non_client_view_->GetMaximumSize() : gfx::Size(); 1033 } 1034 1035 void Widget::OnNativeWidgetMove() { 1036 widget_delegate_->OnWidgetMove(); 1037 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetBoundsChanged( 1038 this, 1039 GetWindowBoundsInScreen())); 1040 } 1041 1042 void Widget::OnNativeWidgetSizeChanged(const gfx::Size& new_size) { 1043 root_view_->SetSize(new_size); 1044 1045 // Size changed notifications can fire prior to full initialization 1046 // i.e. during session restore. Avoid saving session state during these 1047 // startup procedures. 1048 if (native_widget_initialized_) 1049 SaveWindowPlacement(); 1050 1051 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetBoundsChanged( 1052 this, 1053 GetWindowBoundsInScreen())); 1054 } 1055 1056 void Widget::OnNativeWidgetBeginUserBoundsChange() { 1057 widget_delegate_->OnWindowBeginUserBoundsChange(); 1058 } 1059 1060 void Widget::OnNativeWidgetEndUserBoundsChange() { 1061 widget_delegate_->OnWindowEndUserBoundsChange(); 1062 } 1063 1064 bool Widget::HasFocusManager() const { 1065 return !!focus_manager_.get(); 1066 } 1067 1068 bool Widget::OnNativeWidgetPaintAccelerated(const gfx::Rect& dirty_region) { 1069 ui::Compositor* compositor = GetCompositor(); 1070 if (!compositor) 1071 return false; 1072 1073 compositor->ScheduleRedrawRect(dirty_region); 1074 return true; 1075 } 1076 1077 void Widget::OnNativeWidgetPaint(gfx::Canvas* canvas) { 1078 // On Linux Aura, we can get here during Init() because of the 1079 // SetInitialBounds call. 1080 if (native_widget_initialized_) 1081 GetRootView()->Paint(canvas); 1082 } 1083 1084 int Widget::GetNonClientComponent(const gfx::Point& point) { 1085 int component = non_client_view_ ? 1086 non_client_view_->NonClientHitTest(point) : 1087 HTNOWHERE; 1088 1089 if (movement_disabled_ && (component == HTCAPTION || component == HTSYSMENU)) 1090 return HTNOWHERE; 1091 1092 return component; 1093 } 1094 1095 void Widget::OnKeyEvent(ui::KeyEvent* event) { 1096 static_cast<internal::RootView*>(GetRootView())-> 1097 DispatchKeyEvent(event); 1098 } 1099 1100 void Widget::OnMouseEvent(ui::MouseEvent* event) { 1101 if (!IsMouseEventsEnabled()) 1102 return; 1103 1104 View* root_view = GetRootView(); 1105 switch (event->type()) { 1106 case ui::ET_MOUSE_PRESSED: { 1107 last_mouse_event_was_move_ = false; 1108 1109 // We may get deleted by the time we return from OnMousePressed. So we 1110 // use an observer to make sure we are still alive. 1111 WidgetDeletionObserver widget_deletion_observer(this); 1112 1113 // Make sure we're still visible before we attempt capture as the mouse 1114 // press processing may have made the window hide (as happens with menus). 1115 1116 // It is possible for a View to show a context menu on mouse-press. Since 1117 // the menu does a capture and starts a nested message-loop, the release 1118 // would go to the menu. The next click (i.e. both mouse-press and release 1119 // events) also go to the menu. The menu (and the nested message-loop) 1120 // gets closed after this second release event. The code then resumes from 1121 // here. So make sure that the mouse-button is still down before doing a 1122 // capture. 1123 if (root_view && root_view->OnMousePressed(*event) && 1124 widget_deletion_observer.IsWidgetAlive() && IsVisible() && 1125 internal::NativeWidgetPrivate::IsMouseButtonDown()) { 1126 is_mouse_button_pressed_ = true; 1127 if (!native_widget_->HasCapture()) 1128 native_widget_->SetCapture(); 1129 event->SetHandled(); 1130 } 1131 return; 1132 } 1133 case ui::ET_MOUSE_RELEASED: 1134 last_mouse_event_was_move_ = false; 1135 is_mouse_button_pressed_ = false; 1136 // Release capture first, to avoid confusion if OnMouseReleased blocks. 1137 if (native_widget_->HasCapture() && 1138 ShouldReleaseCaptureOnMouseReleased()) { 1139 native_widget_->ReleaseCapture(); 1140 } 1141 if (root_view) 1142 root_view->OnMouseReleased(*event); 1143 if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) 1144 event->SetHandled(); 1145 return; 1146 case ui::ET_MOUSE_MOVED: 1147 case ui::ET_MOUSE_DRAGGED: 1148 if (native_widget_->HasCapture() && is_mouse_button_pressed_) { 1149 last_mouse_event_was_move_ = false; 1150 if (root_view) 1151 root_view->OnMouseDragged(*event); 1152 } else if (!last_mouse_event_was_move_ || 1153 last_mouse_event_position_ != event->location()) { 1154 last_mouse_event_position_ = event->location(); 1155 last_mouse_event_was_move_ = true; 1156 if (root_view) 1157 root_view->OnMouseMoved(*event); 1158 } 1159 return; 1160 case ui::ET_MOUSE_EXITED: 1161 last_mouse_event_was_move_ = false; 1162 if (root_view) 1163 root_view->OnMouseExited(*event); 1164 return; 1165 case ui::ET_MOUSEWHEEL: 1166 if (root_view && root_view->OnMouseWheel( 1167 static_cast<const ui::MouseWheelEvent&>(*event))) 1168 event->SetHandled(); 1169 return; 1170 default: 1171 return; 1172 } 1173 event->SetHandled(); 1174 } 1175 1176 void Widget::OnMouseCaptureLost() { 1177 if (is_mouse_button_pressed_ || is_touch_down_) { 1178 View* root_view = GetRootView(); 1179 if (root_view) 1180 root_view->OnMouseCaptureLost(); 1181 } 1182 is_touch_down_ = false; 1183 is_mouse_button_pressed_ = false; 1184 } 1185 1186 void Widget::OnTouchEvent(ui::TouchEvent* event) { 1187 static_cast<internal::RootView*>(GetRootView())-> 1188 DispatchTouchEvent(event); 1189 } 1190 1191 void Widget::OnScrollEvent(ui::ScrollEvent* event) { 1192 static_cast<internal::RootView*>(GetRootView())-> 1193 DispatchScrollEvent(event); 1194 } 1195 1196 void Widget::OnGestureEvent(ui::GestureEvent* event) { 1197 switch (event->type()) { 1198 case ui::ET_GESTURE_TAP_DOWN: 1199 is_touch_down_ = true; 1200 // We explicitly don't capture here. Not capturing enables multiple 1201 // widgets to get tap events at the same time. Views (such as tab 1202 // dragging) may explicitly capture. 1203 break; 1204 1205 case ui::ET_GESTURE_END: 1206 if (event->details().touch_points() == 1) { 1207 is_touch_down_ = false; 1208 if (ShouldReleaseCaptureOnMouseReleased()) 1209 ReleaseCapture(); 1210 } 1211 break; 1212 1213 default: 1214 break; 1215 } 1216 static_cast<internal::RootView*>(GetRootView())->DispatchGestureEvent(event); 1217 } 1218 1219 bool Widget::ExecuteCommand(int command_id) { 1220 return widget_delegate_->ExecuteWindowsCommand(command_id); 1221 } 1222 1223 InputMethod* Widget::GetInputMethodDirect() { 1224 return input_method_.get(); 1225 } 1226 1227 const std::vector<ui::Layer*>& Widget::GetRootLayers() { 1228 if (root_layers_dirty_) { 1229 root_layers_dirty_ = false; 1230 root_layers_.clear(); 1231 BuildRootLayers(GetRootView(), &root_layers_); 1232 } 1233 return root_layers_; 1234 } 1235 1236 bool Widget::HasHitTestMask() const { 1237 return widget_delegate_->WidgetHasHitTestMask(); 1238 } 1239 1240 void Widget::GetHitTestMask(gfx::Path* mask) const { 1241 DCHECK(mask); 1242 widget_delegate_->GetWidgetHitTestMask(mask); 1243 } 1244 1245 Widget* Widget::AsWidget() { 1246 return this; 1247 } 1248 1249 const Widget* Widget::AsWidget() const { 1250 return this; 1251 } 1252 1253 //////////////////////////////////////////////////////////////////////////////// 1254 // Widget, FocusTraversable implementation: 1255 1256 FocusSearch* Widget::GetFocusSearch() { 1257 return root_view_->GetFocusSearch(); 1258 } 1259 1260 FocusTraversable* Widget::GetFocusTraversableParent() { 1261 // We are a proxy to the root view, so we should be bypassed when traversing 1262 // up and as a result this should not be called. 1263 NOTREACHED(); 1264 return NULL; 1265 } 1266 1267 View* Widget::GetFocusTraversableParentView() { 1268 // We are a proxy to the root view, so we should be bypassed when traversing 1269 // up and as a result this should not be called. 1270 NOTREACHED(); 1271 return NULL; 1272 } 1273 1274 //////////////////////////////////////////////////////////////////////////////// 1275 // Widget, protected: 1276 1277 internal::RootView* Widget::CreateRootView() { 1278 return new internal::RootView(this); 1279 } 1280 1281 void Widget::DestroyRootView() { 1282 non_client_view_ = NULL; 1283 root_view_.reset(); 1284 // Input method has to be destroyed before focus manager. 1285 input_method_.reset(); 1286 } 1287 1288 //////////////////////////////////////////////////////////////////////////////// 1289 // Widget, private: 1290 1291 bool Widget::ShouldReleaseCaptureOnMouseReleased() const { 1292 return true; 1293 } 1294 1295 void Widget::SetInactiveRenderingDisabled(bool value) { 1296 if (value == disable_inactive_rendering_) 1297 return; 1298 1299 disable_inactive_rendering_ = value; 1300 if (non_client_view_) 1301 non_client_view_->SetInactiveRenderingDisabled(value); 1302 native_widget_->SetInactiveRenderingDisabled(value); 1303 } 1304 1305 void Widget::SaveWindowPlacement() { 1306 // The window delegate does the actual saving for us. It seems like (judging 1307 // by go/crash) that in some circumstances we can end up here after 1308 // WM_DESTROY, at which point the window delegate is likely gone. So just 1309 // bail. 1310 if (!widget_delegate_) 1311 return; 1312 1313 ui::WindowShowState show_state = ui::SHOW_STATE_NORMAL; 1314 gfx::Rect bounds; 1315 native_widget_->GetWindowPlacement(&bounds, &show_state); 1316 widget_delegate_->SaveWindowPlacement(bounds, show_state); 1317 } 1318 1319 void Widget::SetInitialBounds(const gfx::Rect& bounds) { 1320 if (!non_client_view_) 1321 return; 1322 1323 gfx::Rect saved_bounds; 1324 if (GetSavedWindowPlacement(&saved_bounds, &saved_show_state_)) { 1325 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED) { 1326 // If we're going to maximize, wait until Show is invoked to set the 1327 // bounds. That way we avoid a noticeable resize. 1328 initial_restored_bounds_ = saved_bounds; 1329 } else if (!saved_bounds.IsEmpty()) { 1330 // If the saved bounds are valid, use them. 1331 SetBounds(saved_bounds); 1332 } 1333 } else { 1334 if (bounds.IsEmpty()) { 1335 // No initial bounds supplied, so size the window to its content and 1336 // center over its parent. 1337 native_widget_->CenterWindow(non_client_view_->GetPreferredSize()); 1338 } else { 1339 // Use the supplied initial bounds. 1340 SetBoundsConstrained(bounds); 1341 } 1342 } 1343 } 1344 1345 void Widget::SetInitialBoundsForFramelessWindow(const gfx::Rect& bounds) { 1346 if (bounds.IsEmpty()) { 1347 View* contents_view = GetContentsView(); 1348 DCHECK(contents_view); 1349 // No initial bounds supplied, so size the window to its content and 1350 // center over its parent if preferred size is provided. 1351 gfx::Size size = contents_view->GetPreferredSize(); 1352 if (!size.IsEmpty()) 1353 native_widget_->CenterWindow(size); 1354 } else { 1355 // Use the supplied initial bounds. 1356 SetBoundsConstrained(bounds); 1357 } 1358 } 1359 1360 bool Widget::GetSavedWindowPlacement(gfx::Rect* bounds, 1361 ui::WindowShowState* show_state) { 1362 // First we obtain the window's saved show-style and store it. We need to do 1363 // this here, rather than in Show() because by the time Show() is called, 1364 // the window's size will have been reset (below) and the saved maximized 1365 // state will have been lost. Sadly there's no way to tell on Windows when 1366 // a window is restored from maximized state, so we can't more accurately 1367 // track maximized state independently of sizing information. 1368 1369 // Restore the window's placement from the controller. 1370 if (widget_delegate_->GetSavedWindowPlacement(bounds, show_state)) { 1371 if (!widget_delegate_->ShouldRestoreWindowSize()) { 1372 bounds->set_size(non_client_view_->GetPreferredSize()); 1373 } else { 1374 gfx::Size minimum_size = GetMinimumSize(); 1375 // Make sure the bounds are at least the minimum size. 1376 if (bounds->width() < minimum_size.width()) 1377 bounds->set_width(minimum_size.width()); 1378 1379 if (bounds->height() < minimum_size.height()) 1380 bounds->set_height(minimum_size.height()); 1381 } 1382 return true; 1383 } 1384 return false; 1385 } 1386 1387 scoped_ptr<InputMethod> Widget::CreateInputMethod() { 1388 scoped_ptr<InputMethod> input_method(native_widget_->CreateInputMethod()); 1389 if (input_method.get()) 1390 input_method->Init(this); 1391 return input_method.Pass(); 1392 } 1393 1394 void Widget::ReplaceInputMethod(InputMethod* input_method) { 1395 input_method_.reset(input_method); 1396 input_method->SetDelegate(native_widget_->GetInputMethodDelegate()); 1397 input_method->Init(this); 1398 } 1399 1400 namespace internal { 1401 1402 //////////////////////////////////////////////////////////////////////////////// 1403 // internal::NativeWidgetPrivate, NativeWidget implementation: 1404 1405 internal::NativeWidgetPrivate* NativeWidgetPrivate::AsNativeWidgetPrivate() { 1406 return this; 1407 } 1408 1409 } // namespace internal 1410 } // namespace views 1411