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