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