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