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 38 namespace views { 39 40 namespace { 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. 45 void 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. 57 NativeWidget* 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. 70 class 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 102 Widget::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 126 Widget::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 150 Widget::InitParams::~InitParams() { 151 } 152 153 //////////////////////////////////////////////////////////////////////////////// 154 // Widget, public: 155 156 Widget::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 is_touch_down_(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 180 Widget::~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 192 Widget* Widget::CreateWindow(WidgetDelegate* delegate) { 193 return CreateWindowWithBounds(delegate, gfx::Rect()); 194 } 195 196 // static 197 Widget* 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 208 Widget* Widget::CreateWindowWithParent(WidgetDelegate* delegate, 209 gfx::NativeView parent) { 210 return CreateWindowWithParentAndBounds(delegate, parent, gfx::Rect()); 211 } 212 213 // static 214 Widget* 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 227 Widget* Widget::CreateWindowWithContext(WidgetDelegate* delegate, 228 gfx::NativeView context) { 229 return CreateWindowWithContextAndBounds(delegate, context, gfx::Rect()); 230 } 231 232 // static 233 Widget* Widget::CreateWindowWithContextAndBounds(WidgetDelegate* delegate, 234 gfx::NativeView context, 235 const gfx::Rect& bounds) { 236 Widget* widget = new Widget; 237 Widget::InitParams params; 238 params.delegate = delegate; 239 params.context = context; 240 params.bounds = bounds; 241 widget->Init(params); 242 return widget; 243 } 244 245 // static 246 Widget* Widget::GetWidgetForNativeView(gfx::NativeView native_view) { 247 internal::NativeWidgetPrivate* native_widget = 248 internal::NativeWidgetPrivate::GetNativeWidgetForNativeView(native_view); 249 return native_widget ? native_widget->GetWidget() : NULL; 250 } 251 252 // static 253 Widget* Widget::GetWidgetForNativeWindow(gfx::NativeWindow native_window) { 254 internal::NativeWidgetPrivate* native_widget = 255 internal::NativeWidgetPrivate::GetNativeWidgetForNativeWindow( 256 native_window); 257 return native_widget ? native_widget->GetWidget() : NULL; 258 } 259 260 // static 261 Widget* Widget::GetTopLevelWidgetForNativeView(gfx::NativeView native_view) { 262 internal::NativeWidgetPrivate* native_widget = 263 internal::NativeWidgetPrivate::GetTopLevelNativeWidget(native_view); 264 return native_widget ? native_widget->GetWidget() : NULL; 265 } 266 267 268 // static 269 void Widget::GetAllChildWidgets(gfx::NativeView native_view, 270 Widgets* children) { 271 internal::NativeWidgetPrivate::GetAllChildWidgets(native_view, children); 272 } 273 274 // static 275 void Widget::GetAllOwnedWidgets(gfx::NativeView native_view, 276 Widgets* owned) { 277 internal::NativeWidgetPrivate::GetAllOwnedWidgets(native_view, owned); 278 } 279 280 // static 281 void Widget::ReparentNativeView(gfx::NativeView native_view, 282 gfx::NativeView new_parent) { 283 internal::NativeWidgetPrivate::ReparentNativeView(native_view, new_parent); 284 } 285 286 // static 287 int Widget::GetLocalizedContentsWidth(int col_resource_id) { 288 return ui::GetLocalizedContentsWidthForFont(col_resource_id, 289 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); 290 } 291 292 // static 293 int Widget::GetLocalizedContentsHeight(int row_resource_id) { 294 return ui::GetLocalizedContentsHeightForFont(row_resource_id, 295 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); 296 } 297 298 // static 299 gfx::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 306 bool Widget::RequiresNonClientView(InitParams::Type type) { 307 return type == InitParams::TYPE_WINDOW || 308 type == InitParams::TYPE_PANEL || 309 type == InitParams::TYPE_BUBBLE; 310 } 311 312 void 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 388 gfx::NativeView Widget::GetNativeView() const { 389 return native_widget_->GetNativeView(); 390 } 391 392 gfx::NativeWindow Widget::GetNativeWindow() const { 393 return native_widget_->GetNativeWindow(); 394 } 395 396 void Widget::AddObserver(WidgetObserver* observer) { 397 observers_.AddObserver(observer); 398 } 399 400 void Widget::RemoveObserver(WidgetObserver* observer) { 401 observers_.RemoveObserver(observer); 402 } 403 404 bool Widget::HasObserver(WidgetObserver* observer) { 405 return observers_.HasObserver(observer); 406 } 407 408 void Widget::AddRemovalsObserver(WidgetRemovalsObserver* observer) { 409 removals_observers_.AddObserver(observer); 410 } 411 412 void Widget::RemoveRemovalsObserver(WidgetRemovalsObserver* observer) { 413 removals_observers_.RemoveObserver(observer); 414 } 415 416 bool Widget::HasRemovalsObserver(WidgetRemovalsObserver* observer) { 417 return removals_observers_.HasObserver(observer); 418 } 419 420 bool Widget::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) const { 421 return false; 422 } 423 424 void 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 437 void 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 445 void Widget::NotifyNativeViewHierarchyChanged() { 446 root_view_->NotifyNativeViewHierarchyChanged(); 447 } 448 449 void Widget::NotifyWillRemoveView(View* view) { 450 FOR_EACH_OBSERVER(WidgetRemovalsObserver, 451 removals_observers_, 452 OnWillRemoveView(this, view)); 453 } 454 455 // Converted methods (see header) ---------------------------------------------- 456 457 Widget* Widget::GetTopLevelWidget() { 458 return const_cast<Widget*>( 459 static_cast<const Widget*>(this)->GetTopLevelWidget()); 460 } 461 462 const 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 470 void 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 487 View* Widget::GetContentsView() { 488 return root_view_->GetContentsView(); 489 } 490 491 gfx::Rect Widget::GetWindowBoundsInScreen() const { 492 return native_widget_->GetWindowBoundsInScreen(); 493 } 494 495 gfx::Rect Widget::GetClientAreaBoundsInScreen() const { 496 return native_widget_->GetClientAreaBoundsInScreen(); 497 } 498 499 gfx::Rect Widget::GetRestoredBounds() const { 500 return native_widget_->GetRestoredBounds(); 501 } 502 503 void Widget::SetBounds(const gfx::Rect& bounds) { 504 native_widget_->SetBounds(bounds); 505 } 506 507 void Widget::SetSize(const gfx::Size& size) { 508 native_widget_->SetSize(size); 509 } 510 511 void Widget::CenterWindow(const gfx::Size& size) { 512 native_widget_->CenterWindow(size); 513 } 514 515 void 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 529 void Widget::SetVisibilityChangedAnimationsEnabled(bool value) { 530 native_widget_->SetVisibilityChangedAnimationsEnabled(value); 531 } 532 533 Widget::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 540 void Widget::EndMoveLoop() { 541 native_widget_->EndMoveLoop(); 542 } 543 544 void Widget::StackAboveWidget(Widget* widget) { 545 native_widget_->StackAbove(widget->GetNativeView()); 546 } 547 548 void Widget::StackAbove(gfx::NativeView native_view) { 549 native_widget_->StackAbove(native_view); 550 } 551 552 void Widget::StackAtTop() { 553 native_widget_->StackAtTop(); 554 } 555 556 void Widget::StackBelow(gfx::NativeView native_view) { 557 native_widget_->StackBelow(native_view); 558 } 559 560 void Widget::SetShape(gfx::NativeRegion shape) { 561 native_widget_->SetShape(shape); 562 } 563 564 void 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 592 void Widget::CloseNow() { 593 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetClosing(this)); 594 native_widget_->CloseNow(); 595 } 596 597 bool Widget::IsClosed() const { 598 return widget_closed_; 599 } 600 601 void 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 626 void Widget::Hide() { 627 native_widget_->Hide(); 628 } 629 630 void 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 643 void Widget::Activate() { 644 native_widget_->Activate(); 645 } 646 647 void Widget::Deactivate() { 648 native_widget_->Deactivate(); 649 } 650 651 bool Widget::IsActive() const { 652 return native_widget_->IsActive(); 653 } 654 655 void Widget::DisableInactiveRendering() { 656 SetInactiveRenderingDisabled(true); 657 } 658 659 void Widget::SetAlwaysOnTop(bool on_top) { 660 native_widget_->SetAlwaysOnTop(on_top); 661 } 662 663 bool Widget::IsAlwaysOnTop() const { 664 return native_widget_->IsAlwaysOnTop(); 665 } 666 667 void Widget::SetVisibleOnAllWorkspaces(bool always_visible) { 668 native_widget_->SetVisibleOnAllWorkspaces(always_visible); 669 } 670 671 void Widget::Maximize() { 672 native_widget_->Maximize(); 673 } 674 675 void Widget::Minimize() { 676 native_widget_->Minimize(); 677 } 678 679 void Widget::Restore() { 680 native_widget_->Restore(); 681 } 682 683 bool Widget::IsMaximized() const { 684 return native_widget_->IsMaximized(); 685 } 686 687 bool Widget::IsMinimized() const { 688 return native_widget_->IsMinimized(); 689 } 690 691 void 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 701 bool Widget::IsFullscreen() const { 702 return native_widget_->IsFullscreen(); 703 } 704 705 void Widget::SetOpacity(unsigned char opacity) { 706 native_widget_->SetOpacity(opacity); 707 } 708 709 void Widget::SetUseDragFrame(bool use_drag_frame) { 710 native_widget_->SetUseDragFrame(use_drag_frame); 711 } 712 713 void Widget::FlashFrame(bool flash) { 714 native_widget_->FlashFrame(flash); 715 } 716 717 View* Widget::GetRootView() { 718 return root_view_.get(); 719 } 720 721 const View* Widget::GetRootView() const { 722 return root_view_.get(); 723 } 724 725 bool Widget::IsVisible() const { 726 return native_widget_->IsVisible(); 727 } 728 729 ui::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 745 const ui::NativeTheme* Widget::GetNativeTheme() const { 746 return native_widget_->GetNativeTheme(); 747 } 748 749 FocusManager* Widget::GetFocusManager() { 750 Widget* toplevel_widget = GetTopLevelWidget(); 751 return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; 752 } 753 754 const FocusManager* Widget::GetFocusManager() const { 755 const Widget* toplevel_widget = GetTopLevelWidget(); 756 return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; 757 } 758 759 InputMethod* Widget::GetInputMethod() { 760 return const_cast<InputMethod*>( 761 const_cast<const Widget*>(this)->GetInputMethod()); 762 } 763 764 const 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 780 ui::InputMethod* Widget::GetHostInputMethod() { 781 return native_widget_private()->GetHostInputMethod(); 782 } 783 784 void 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 native_widget_->RunShellDrag(view, data, location, operation, source); 791 // If the view is removed during the drag operation, dragged_view_ is set to 792 // NULL. 793 if (view && dragged_view_ == view) { 794 dragged_view_ = NULL; 795 view->OnDragDone(); 796 } 797 } 798 799 void Widget::SchedulePaintInRect(const gfx::Rect& rect) { 800 native_widget_->SchedulePaintInRect(rect); 801 } 802 803 void Widget::SetCursor(gfx::NativeCursor cursor) { 804 native_widget_->SetCursor(cursor); 805 } 806 807 bool Widget::IsMouseEventsEnabled() const { 808 return native_widget_->IsMouseEventsEnabled(); 809 } 810 811 void Widget::SetNativeWindowProperty(const char* name, void* value) { 812 native_widget_->SetNativeWindowProperty(name, value); 813 } 814 815 void* Widget::GetNativeWindowProperty(const char* name) const { 816 return native_widget_->GetNativeWindowProperty(name); 817 } 818 819 void Widget::UpdateWindowTitle() { 820 if (!non_client_view_) 821 return; 822 823 // Update the native frame's text. We do this regardless of whether or not 824 // the native frame is being used, since this also updates the taskbar, etc. 825 base::string16 window_title = widget_delegate_->GetWindowTitle(); 826 base::i18n::AdjustStringForLocaleDirection(&window_title); 827 if (!native_widget_->SetWindowTitle(window_title)) 828 return; 829 non_client_view_->UpdateWindowTitle(); 830 831 // If the non-client view is rendering its own title, it'll need to relayout 832 // now and to get a paint update later on. 833 non_client_view_->Layout(); 834 } 835 836 void Widget::UpdateWindowIcon() { 837 if (non_client_view_) 838 non_client_view_->UpdateWindowIcon(); 839 native_widget_->SetWindowIcons(widget_delegate_->GetWindowIcon(), 840 widget_delegate_->GetWindowAppIcon()); 841 } 842 843 FocusTraversable* Widget::GetFocusTraversable() { 844 return static_cast<internal::RootView*>(root_view_.get()); 845 } 846 847 void Widget::ThemeChanged() { 848 root_view_->ThemeChanged(); 849 } 850 851 void Widget::LocaleChanged() { 852 root_view_->LocaleChanged(); 853 } 854 855 void Widget::SetFocusTraversableParent(FocusTraversable* parent) { 856 root_view_->SetFocusTraversableParent(parent); 857 } 858 859 void Widget::SetFocusTraversableParentView(View* parent_view) { 860 root_view_->SetFocusTraversableParentView(parent_view); 861 } 862 863 void Widget::ClearNativeFocus() { 864 native_widget_->ClearNativeFocus(); 865 } 866 867 NonClientFrameView* Widget::CreateNonClientFrameView() { 868 NonClientFrameView* frame_view = 869 widget_delegate_->CreateNonClientFrameView(this); 870 if (!frame_view) 871 frame_view = native_widget_->CreateNonClientFrameView(); 872 if (!frame_view && ViewsDelegate::views_delegate) { 873 frame_view = 874 ViewsDelegate::views_delegate->CreateDefaultNonClientFrameView(this); 875 } 876 if (frame_view) 877 return frame_view; 878 879 CustomFrameView* custom_frame_view = new CustomFrameView; 880 custom_frame_view->Init(this); 881 return custom_frame_view; 882 } 883 884 bool Widget::ShouldUseNativeFrame() const { 885 if (frame_type_ != FRAME_TYPE_DEFAULT) 886 return frame_type_ == FRAME_TYPE_FORCE_NATIVE; 887 return native_widget_->ShouldUseNativeFrame(); 888 } 889 890 bool Widget::ShouldWindowContentsBeTransparent() const { 891 return native_widget_->ShouldWindowContentsBeTransparent(); 892 } 893 894 void Widget::DebugToggleFrameType() { 895 if (frame_type_ == FRAME_TYPE_DEFAULT) { 896 frame_type_ = ShouldUseNativeFrame() ? FRAME_TYPE_FORCE_CUSTOM : 897 FRAME_TYPE_FORCE_NATIVE; 898 } else { 899 frame_type_ = frame_type_ == FRAME_TYPE_FORCE_CUSTOM ? 900 FRAME_TYPE_FORCE_NATIVE : FRAME_TYPE_FORCE_CUSTOM; 901 } 902 FrameTypeChanged(); 903 } 904 905 void Widget::FrameTypeChanged() { 906 native_widget_->FrameTypeChanged(); 907 } 908 909 const ui::Compositor* Widget::GetCompositor() const { 910 return native_widget_->GetCompositor(); 911 } 912 913 ui::Compositor* Widget::GetCompositor() { 914 return native_widget_->GetCompositor(); 915 } 916 917 ui::Layer* Widget::GetLayer() { 918 return native_widget_->GetLayer(); 919 } 920 921 void Widget::ReorderNativeViews() { 922 native_widget_->ReorderNativeViews(); 923 } 924 925 void Widget::UpdateRootLayers() { 926 // Calculate the layers requires traversing the tree, and since nearly any 927 // mutation of the tree can trigger this call we delay until absolutely 928 // necessary. 929 root_layers_dirty_ = true; 930 } 931 932 const NativeWidget* Widget::native_widget() const { 933 return native_widget_; 934 } 935 936 NativeWidget* Widget::native_widget() { 937 return native_widget_; 938 } 939 940 void Widget::SetCapture(View* view) { 941 if (internal::NativeWidgetPrivate::IsMouseButtonDown()) 942 is_mouse_button_pressed_ = true; 943 if (internal::NativeWidgetPrivate::IsTouchDown()) 944 is_touch_down_ = true; 945 root_view_->SetMouseHandler(view); 946 if (!native_widget_->HasCapture()) 947 native_widget_->SetCapture(); 948 } 949 950 void Widget::ReleaseCapture() { 951 if (native_widget_->HasCapture()) 952 native_widget_->ReleaseCapture(); 953 } 954 955 bool Widget::HasCapture() { 956 return native_widget_->HasCapture(); 957 } 958 959 TooltipManager* Widget::GetTooltipManager() { 960 return native_widget_->GetTooltipManager(); 961 } 962 963 const TooltipManager* Widget::GetTooltipManager() const { 964 return native_widget_->GetTooltipManager(); 965 } 966 967 gfx::Rect Widget::GetWorkAreaBoundsInScreen() const { 968 return native_widget_->GetWorkAreaBoundsInScreen(); 969 } 970 971 void Widget::SynthesizeMouseMoveEvent() { 972 last_mouse_event_was_move_ = false; 973 ui::MouseEvent mouse_event(ui::ET_MOUSE_MOVED, 974 last_mouse_event_position_, 975 last_mouse_event_position_, 976 ui::EF_IS_SYNTHESIZED, 0); 977 root_view_->OnMouseMoved(mouse_event); 978 } 979 980 void Widget::OnRootViewLayout() { 981 native_widget_->OnRootViewLayout(); 982 } 983 984 bool Widget::IsTranslucentWindowOpacitySupported() const { 985 return native_widget_->IsTranslucentWindowOpacitySupported(); 986 } 987 988 void Widget::OnOwnerClosing() { 989 } 990 991 //////////////////////////////////////////////////////////////////////////////// 992 // Widget, NativeWidgetDelegate implementation: 993 994 bool Widget::IsModal() const { 995 return widget_delegate_->GetModalType() != ui::MODAL_TYPE_NONE; 996 } 997 998 bool Widget::IsDialogBox() const { 999 return !!widget_delegate_->AsDialogDelegate(); 1000 } 1001 1002 bool Widget::CanActivate() const { 1003 return widget_delegate_->CanActivate(); 1004 } 1005 1006 bool Widget::IsInactiveRenderingDisabled() const { 1007 return disable_inactive_rendering_; 1008 } 1009 1010 void Widget::EnableInactiveRendering() { 1011 SetInactiveRenderingDisabled(false); 1012 } 1013 1014 void Widget::OnNativeWidgetActivationChanged(bool active) { 1015 // On windows we may end up here before we've completed initialization (from 1016 // an WM_NCACTIVATE). If that happens the WidgetDelegate likely doesn't know 1017 // the Widget and will crash attempting to access it. 1018 if (!active && native_widget_initialized_) 1019 SaveWindowPlacement(); 1020 1021 FOR_EACH_OBSERVER(WidgetObserver, observers_, 1022 OnWidgetActivationChanged(this, active)); 1023 1024 // During window creation, the widget gets focused without activation, and in 1025 // that case, the focus manager cannot set the appropriate text input client 1026 // because the widget is not active. Thus we have to notify the focus manager 1027 // not only when the focus changes but also when the widget gets activated. 1028 // See crbug.com/377479 for details. 1029 views::FocusManager* focus_manager = GetFocusManager(); 1030 if (focus_manager) { 1031 if (active) 1032 focus_manager->FocusTextInputClient(focus_manager->GetFocusedView()); 1033 else 1034 focus_manager->BlurTextInputClient(focus_manager->GetFocusedView()); 1035 } 1036 1037 if (IsVisible() && non_client_view()) 1038 non_client_view()->frame_view()->SchedulePaint(); 1039 } 1040 1041 void Widget::OnNativeFocus(gfx::NativeView old_focused_view) { 1042 WidgetFocusManager::GetInstance()->OnWidgetFocusEvent(old_focused_view, 1043 GetNativeView()); 1044 } 1045 1046 void Widget::OnNativeBlur(gfx::NativeView new_focused_view) { 1047 WidgetFocusManager::GetInstance()->OnWidgetFocusEvent(GetNativeView(), 1048 new_focused_view); 1049 } 1050 1051 void Widget::OnNativeWidgetVisibilityChanging(bool visible) { 1052 FOR_EACH_OBSERVER(WidgetObserver, observers_, 1053 OnWidgetVisibilityChanging(this, visible)); 1054 } 1055 1056 void Widget::OnNativeWidgetVisibilityChanged(bool visible) { 1057 View* root = GetRootView(); 1058 if (root) 1059 root->PropagateVisibilityNotifications(root, visible); 1060 FOR_EACH_OBSERVER(WidgetObserver, observers_, 1061 OnWidgetVisibilityChanged(this, visible)); 1062 if (GetCompositor() && root && root->layer()) 1063 root->layer()->SetVisible(visible); 1064 } 1065 1066 void Widget::OnNativeWidgetCreated(bool desktop_widget) { 1067 if (is_top_level()) 1068 focus_manager_.reset(FocusManagerFactory::Create(this, desktop_widget)); 1069 1070 native_widget_->InitModalType(widget_delegate_->GetModalType()); 1071 1072 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetCreated(this)); 1073 } 1074 1075 void Widget::OnNativeWidgetDestroying() { 1076 // Tell the focus manager (if any) that root_view is being removed 1077 // in case that the focused view is under this root view. 1078 if (GetFocusManager()) 1079 GetFocusManager()->ViewRemoved(root_view_.get()); 1080 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetDestroying(this)); 1081 if (non_client_view_) 1082 non_client_view_->WindowClosing(); 1083 widget_delegate_->WindowClosing(); 1084 } 1085 1086 void Widget::OnNativeWidgetDestroyed() { 1087 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetDestroyed(this)); 1088 widget_delegate_->DeleteDelegate(); 1089 widget_delegate_ = NULL; 1090 native_widget_destroyed_ = true; 1091 } 1092 1093 gfx::Size Widget::GetMinimumSize() const { 1094 return non_client_view_ ? non_client_view_->GetMinimumSize() : gfx::Size(); 1095 } 1096 1097 gfx::Size Widget::GetMaximumSize() const { 1098 return non_client_view_ ? non_client_view_->GetMaximumSize() : gfx::Size(); 1099 } 1100 1101 void Widget::OnNativeWidgetMove() { 1102 widget_delegate_->OnWidgetMove(); 1103 View* root = GetRootView(); 1104 if (root && root->GetFocusManager()) { 1105 View* focused_view = root->GetFocusManager()->GetFocusedView(); 1106 if (focused_view && focused_view->GetInputMethod()) 1107 focused_view->GetInputMethod()->OnCaretBoundsChanged(focused_view); 1108 } 1109 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetBoundsChanged( 1110 this, 1111 GetWindowBoundsInScreen())); 1112 } 1113 1114 void Widget::OnNativeWidgetSizeChanged(const gfx::Size& new_size) { 1115 View* root = GetRootView(); 1116 if (root) { 1117 root->SetSize(new_size); 1118 if (root->GetFocusManager()) { 1119 View* focused_view = GetRootView()->GetFocusManager()->GetFocusedView(); 1120 if (focused_view && focused_view->GetInputMethod()) 1121 focused_view->GetInputMethod()->OnCaretBoundsChanged(focused_view); 1122 } 1123 } 1124 // Size changed notifications can fire prior to full initialization 1125 // i.e. during session restore. Avoid saving session state during these 1126 // startup procedures. 1127 if (native_widget_initialized_) 1128 SaveWindowPlacement(); 1129 1130 FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetBoundsChanged( 1131 this, 1132 GetWindowBoundsInScreen())); 1133 } 1134 1135 void Widget::OnNativeWidgetBeginUserBoundsChange() { 1136 widget_delegate_->OnWindowBeginUserBoundsChange(); 1137 } 1138 1139 void Widget::OnNativeWidgetEndUserBoundsChange() { 1140 widget_delegate_->OnWindowEndUserBoundsChange(); 1141 } 1142 1143 bool Widget::HasFocusManager() const { 1144 return !!focus_manager_.get(); 1145 } 1146 1147 bool Widget::OnNativeWidgetPaintAccelerated(const gfx::Rect& dirty_region) { 1148 ui::Compositor* compositor = GetCompositor(); 1149 if (!compositor) 1150 return false; 1151 1152 compositor->ScheduleRedrawRect(dirty_region); 1153 return true; 1154 } 1155 1156 void Widget::OnNativeWidgetPaint(gfx::Canvas* canvas) { 1157 // On Linux Aura, we can get here during Init() because of the 1158 // SetInitialBounds call. 1159 if (native_widget_initialized_) 1160 GetRootView()->Paint(canvas, CullSet()); 1161 } 1162 1163 int Widget::GetNonClientComponent(const gfx::Point& point) { 1164 int component = non_client_view_ ? 1165 non_client_view_->NonClientHitTest(point) : 1166 HTNOWHERE; 1167 1168 if (movement_disabled_ && (component == HTCAPTION || component == HTSYSMENU)) 1169 return HTNOWHERE; 1170 1171 return component; 1172 } 1173 1174 void Widget::OnKeyEvent(ui::KeyEvent* event) { 1175 SendEventToProcessor(event); 1176 } 1177 1178 // TODO(tdanderson): We should not be calling the OnMouse*() functions on 1179 // RootView from anywhere in Widget. Use 1180 // SendEventToProcessor() instead. See crbug.com/348087. 1181 void Widget::OnMouseEvent(ui::MouseEvent* event) { 1182 View* root_view = GetRootView(); 1183 switch (event->type()) { 1184 case ui::ET_MOUSE_PRESSED: { 1185 last_mouse_event_was_move_ = false; 1186 1187 // We may get deleted by the time we return from OnMousePressed. So we 1188 // use an observer to make sure we are still alive. 1189 WidgetDeletionObserver widget_deletion_observer(this); 1190 1191 // Make sure we're still visible before we attempt capture as the mouse 1192 // press processing may have made the window hide (as happens with menus). 1193 1194 // It is possible for a View to show a context menu on mouse-press. Since 1195 // the menu does a capture and starts a nested message-loop, the release 1196 // would go to the menu. The next click (i.e. both mouse-press and release 1197 // events) also go to the menu. The menu (and the nested message-loop) 1198 // gets closed after this second release event. The code then resumes from 1199 // here. So make sure that the mouse-button is still down before doing a 1200 // capture. 1201 if (root_view && root_view->OnMousePressed(*event) && 1202 widget_deletion_observer.IsWidgetAlive() && IsVisible() && 1203 internal::NativeWidgetPrivate::IsMouseButtonDown()) { 1204 is_mouse_button_pressed_ = true; 1205 if (!native_widget_->HasCapture()) 1206 native_widget_->SetCapture(); 1207 event->SetHandled(); 1208 } 1209 return; 1210 } 1211 1212 case ui::ET_MOUSE_RELEASED: 1213 last_mouse_event_was_move_ = false; 1214 is_mouse_button_pressed_ = false; 1215 // Release capture first, to avoid confusion if OnMouseReleased blocks. 1216 if (auto_release_capture_ && native_widget_->HasCapture()) 1217 native_widget_->ReleaseCapture(); 1218 if (root_view) 1219 root_view->OnMouseReleased(*event); 1220 if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) 1221 event->SetHandled(); 1222 return; 1223 1224 case ui::ET_MOUSE_MOVED: 1225 case ui::ET_MOUSE_DRAGGED: 1226 if (native_widget_->HasCapture() && is_mouse_button_pressed_) { 1227 last_mouse_event_was_move_ = false; 1228 if (root_view) 1229 root_view->OnMouseDragged(*event); 1230 } else if (!last_mouse_event_was_move_ || 1231 last_mouse_event_position_ != event->location()) { 1232 last_mouse_event_position_ = event->location(); 1233 last_mouse_event_was_move_ = true; 1234 if (root_view) 1235 root_view->OnMouseMoved(*event); 1236 } 1237 return; 1238 1239 case ui::ET_MOUSE_EXITED: 1240 last_mouse_event_was_move_ = false; 1241 if (root_view) 1242 root_view->OnMouseExited(*event); 1243 return; 1244 1245 case ui::ET_MOUSEWHEEL: 1246 if (root_view && root_view->OnMouseWheel( 1247 static_cast<const ui::MouseWheelEvent&>(*event))) 1248 event->SetHandled(); 1249 return; 1250 1251 default: 1252 return; 1253 } 1254 } 1255 1256 void Widget::OnMouseCaptureLost() { 1257 if (is_mouse_button_pressed_ || is_touch_down_) { 1258 View* root_view = GetRootView(); 1259 if (root_view) 1260 root_view->OnMouseCaptureLost(); 1261 } 1262 is_touch_down_ = false; 1263 is_mouse_button_pressed_ = false; 1264 } 1265 1266 void Widget::OnScrollEvent(ui::ScrollEvent* event) { 1267 ui::ScrollEvent event_copy(*event); 1268 SendEventToProcessor(&event_copy); 1269 1270 // Convert unhandled ui::ET_SCROLL events into ui::ET_MOUSEWHEEL events. 1271 if (!event_copy.handled() && event_copy.type() == ui::ET_SCROLL) { 1272 ui::MouseWheelEvent wheel(*event); 1273 OnMouseEvent(&wheel); 1274 } 1275 } 1276 1277 void Widget::OnGestureEvent(ui::GestureEvent* event) { 1278 switch (event->type()) { 1279 case ui::ET_GESTURE_TAP_DOWN: 1280 is_touch_down_ = true; 1281 // We explicitly don't capture here. Not capturing enables multiple 1282 // widgets to get tap events at the same time. Views (such as tab 1283 // dragging) may explicitly capture. 1284 break; 1285 1286 case ui::ET_GESTURE_END: 1287 if (event->details().touch_points() == 1) 1288 is_touch_down_ = false; 1289 break; 1290 1291 default: 1292 break; 1293 } 1294 SendEventToProcessor(event); 1295 } 1296 1297 bool Widget::ExecuteCommand(int command_id) { 1298 return widget_delegate_->ExecuteWindowsCommand(command_id); 1299 } 1300 1301 InputMethod* Widget::GetInputMethodDirect() { 1302 return input_method_.get(); 1303 } 1304 1305 const 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 1314 bool Widget::HasHitTestMask() const { 1315 return widget_delegate_->WidgetHasHitTestMask(); 1316 } 1317 1318 void Widget::GetHitTestMask(gfx::Path* mask) const { 1319 DCHECK(mask); 1320 widget_delegate_->GetWidgetHitTestMask(mask); 1321 } 1322 1323 Widget* Widget::AsWidget() { 1324 return this; 1325 } 1326 1327 const Widget* Widget::AsWidget() const { 1328 return this; 1329 } 1330 1331 bool 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: 1348 ui::EventProcessor* Widget::GetEventProcessor() { 1349 return root_view_.get(); 1350 } 1351 1352 //////////////////////////////////////////////////////////////////////////////// 1353 // Widget, FocusTraversable implementation: 1354 1355 FocusSearch* Widget::GetFocusSearch() { 1356 return root_view_->GetFocusSearch(); 1357 } 1358 1359 FocusTraversable* 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 1366 View* 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 1376 void 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 1391 internal::RootView* Widget::CreateRootView() { 1392 return new internal::RootView(this); 1393 } 1394 1395 void 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 1402 //////////////////////////////////////////////////////////////////////////////// 1403 // Widget, private: 1404 1405 void Widget::SetInactiveRenderingDisabled(bool value) { 1406 if (value == disable_inactive_rendering_) 1407 return; 1408 1409 disable_inactive_rendering_ = value; 1410 if (non_client_view_) 1411 non_client_view_->SetInactiveRenderingDisabled(value); 1412 } 1413 1414 void Widget::SaveWindowPlacement() { 1415 // The window delegate does the actual saving for us. It seems like (judging 1416 // by go/crash) that in some circumstances we can end up here after 1417 // WM_DESTROY, at which point the window delegate is likely gone. So just 1418 // bail. 1419 if (!widget_delegate_) 1420 return; 1421 1422 ui::WindowShowState show_state = ui::SHOW_STATE_NORMAL; 1423 gfx::Rect bounds; 1424 native_widget_->GetWindowPlacement(&bounds, &show_state); 1425 widget_delegate_->SaveWindowPlacement(bounds, show_state); 1426 } 1427 1428 void Widget::SetInitialBounds(const gfx::Rect& bounds) { 1429 if (!non_client_view_) 1430 return; 1431 1432 gfx::Rect saved_bounds; 1433 if (GetSavedWindowPlacement(&saved_bounds, &saved_show_state_)) { 1434 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED) { 1435 // If we're going to maximize, wait until Show is invoked to set the 1436 // bounds. That way we avoid a noticeable resize. 1437 initial_restored_bounds_ = saved_bounds; 1438 } else if (!saved_bounds.IsEmpty()) { 1439 // If the saved bounds are valid, use them. 1440 SetBounds(saved_bounds); 1441 } 1442 } else { 1443 if (bounds.IsEmpty()) { 1444 // No initial bounds supplied, so size the window to its content and 1445 // center over its parent. 1446 native_widget_->CenterWindow(non_client_view_->GetPreferredSize()); 1447 } else { 1448 // Use the supplied initial bounds. 1449 SetBoundsConstrained(bounds); 1450 } 1451 } 1452 } 1453 1454 void Widget::SetInitialBoundsForFramelessWindow(const gfx::Rect& bounds) { 1455 if (bounds.IsEmpty()) { 1456 View* contents_view = GetContentsView(); 1457 DCHECK(contents_view); 1458 // No initial bounds supplied, so size the window to its content and 1459 // center over its parent if preferred size is provided. 1460 gfx::Size size = contents_view->GetPreferredSize(); 1461 if (!size.IsEmpty()) 1462 native_widget_->CenterWindow(size); 1463 } else { 1464 // Use the supplied initial bounds. 1465 SetBoundsConstrained(bounds); 1466 } 1467 } 1468 1469 bool Widget::GetSavedWindowPlacement(gfx::Rect* bounds, 1470 ui::WindowShowState* show_state) { 1471 // First we obtain the window's saved show-style and store it. We need to do 1472 // this here, rather than in Show() because by the time Show() is called, 1473 // the window's size will have been reset (below) and the saved maximized 1474 // state will have been lost. Sadly there's no way to tell on Windows when 1475 // a window is restored from maximized state, so we can't more accurately 1476 // track maximized state independently of sizing information. 1477 1478 // Restore the window's placement from the controller. 1479 if (widget_delegate_->GetSavedWindowPlacement(this, bounds, show_state)) { 1480 if (!widget_delegate_->ShouldRestoreWindowSize()) { 1481 bounds->set_size(non_client_view_->GetPreferredSize()); 1482 } else { 1483 gfx::Size minimum_size = GetMinimumSize(); 1484 // Make sure the bounds are at least the minimum size. 1485 if (bounds->width() < minimum_size.width()) 1486 bounds->set_width(minimum_size.width()); 1487 1488 if (bounds->height() < minimum_size.height()) 1489 bounds->set_height(minimum_size.height()); 1490 } 1491 return true; 1492 } 1493 return false; 1494 } 1495 1496 scoped_ptr<InputMethod> Widget::CreateInputMethod() { 1497 scoped_ptr<InputMethod> input_method(native_widget_->CreateInputMethod()); 1498 if (input_method.get()) 1499 input_method->Init(this); 1500 return input_method.Pass(); 1501 } 1502 1503 void Widget::ReplaceInputMethod(InputMethod* input_method) { 1504 input_method_.reset(input_method); 1505 input_method->SetDelegate(native_widget_->GetInputMethodDelegate()); 1506 input_method->Init(this); 1507 } 1508 1509 namespace internal { 1510 1511 //////////////////////////////////////////////////////////////////////////////// 1512 // internal::NativeWidgetPrivate, NativeWidget implementation: 1513 1514 internal::NativeWidgetPrivate* NativeWidgetPrivate::AsNativeWidgetPrivate() { 1515 return this; 1516 } 1517 1518 } // namespace internal 1519 } // namespace views 1520