OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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 "views/widget/widget.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/message_loop.h" |
| 9 #include "base/utf_string_conversions.h" |
| 10 #include "ui/base/hit_test.h" |
| 11 #include "ui/base/l10n/l10n_font_util.h" |
| 12 #include "ui/base/resource/resource_bundle.h" |
| 13 #include "ui/gfx/compositor/compositor.h" |
| 14 #include "ui/gfx/compositor/layer.h" |
| 15 #include "ui/gfx/screen.h" |
| 16 #include "ui/views/focus/focus_manager.h" |
| 17 #include "ui/views/focus/focus_manager_factory.h" |
| 18 #include "ui/views/focus/view_storage.h" |
| 19 #include "ui/views/focus/widget_focus_manager.h" |
| 20 #include "ui/views/ime/input_method.h" |
| 21 #include "ui/views/window/custom_frame_view.h" |
| 22 #include "views/controls/menu/menu_controller.h" |
| 23 #include "views/views_delegate.h" |
| 24 #include "views/widget/default_theme_provider.h" |
| 25 #include "views/widget/native_widget_private.h" |
| 26 #include "views/widget/root_view.h" |
| 27 #include "views/widget/tooltip_manager.h" |
| 28 #include "views/widget/widget_delegate.h" |
| 29 |
| 30 namespace { |
| 31 |
| 32 // Set to true if a pure Views implementation is preferred |
| 33 bool use_pure_views = false; |
| 34 |
| 35 // True to enable debug paint that indicates where to be painted. |
| 36 bool debug_paint = false; |
| 37 |
| 38 } // namespace |
| 39 |
| 40 namespace views { |
| 41 |
| 42 // This class is used to keep track of the event a Widget is processing, and |
| 43 // restore any previously active event afterwards. |
| 44 class ScopedEvent { |
| 45 public: |
| 46 ScopedEvent(Widget* widget, const Event& event) |
| 47 : widget_(widget), |
| 48 event_(&event) { |
| 49 widget->event_stack_.push(this); |
| 50 } |
| 51 |
| 52 ~ScopedEvent() { |
| 53 if (widget_) |
| 54 widget_->event_stack_.pop(); |
| 55 } |
| 56 |
| 57 void reset() { |
| 58 widget_ = NULL; |
| 59 } |
| 60 |
| 61 const Event* event() { |
| 62 return event_; |
| 63 } |
| 64 |
| 65 private: |
| 66 Widget* widget_; |
| 67 const Event* event_; |
| 68 |
| 69 DISALLOW_COPY_AND_ASSIGN(ScopedEvent); |
| 70 }; |
| 71 |
| 72 // A default implementation of WidgetDelegate, used by Widget when no |
| 73 // WidgetDelegate is supplied. |
| 74 class DefaultWidgetDelegate : public WidgetDelegate { |
| 75 public: |
| 76 DefaultWidgetDelegate(Widget* widget, const Widget::InitParams& params) |
| 77 : widget_(widget), |
| 78 can_activate_(!params.child && |
| 79 params.type != Widget::InitParams::TYPE_POPUP) { |
| 80 } |
| 81 virtual ~DefaultWidgetDelegate() {} |
| 82 |
| 83 // Overridden from WidgetDelegate: |
| 84 virtual void DeleteDelegate() OVERRIDE { |
| 85 delete this; |
| 86 } |
| 87 virtual Widget* GetWidget() { |
| 88 return widget_; |
| 89 } |
| 90 virtual const Widget* GetWidget() const { |
| 91 return widget_; |
| 92 } |
| 93 |
| 94 virtual bool CanActivate() const { |
| 95 return can_activate_; |
| 96 } |
| 97 |
| 98 private: |
| 99 Widget* widget_; |
| 100 bool can_activate_; |
| 101 |
| 102 DISALLOW_COPY_AND_ASSIGN(DefaultWidgetDelegate); |
| 103 }; |
| 104 |
| 105 //////////////////////////////////////////////////////////////////////////////// |
| 106 // Widget, InitParams: |
| 107 |
| 108 Widget::InitParams::InitParams() |
| 109 : type(TYPE_WINDOW), |
| 110 delegate(NULL), |
| 111 child(false), |
| 112 transient(false), |
| 113 transparent(false), |
| 114 accept_events(true), |
| 115 can_activate(true), |
| 116 keep_on_top(false), |
| 117 ownership(NATIVE_WIDGET_OWNS_WIDGET), |
| 118 mirror_origin_in_rtl(false), |
| 119 has_dropshadow(false), |
| 120 show_state(ui::SHOW_STATE_DEFAULT), |
| 121 double_buffer(false), |
| 122 parent(NULL), |
| 123 parent_widget(NULL), |
| 124 native_widget(NULL), |
| 125 top_level(false), |
| 126 create_texture_for_layer(true) { |
| 127 } |
| 128 |
| 129 Widget::InitParams::InitParams(Type type) |
| 130 : type(type), |
| 131 delegate(NULL), |
| 132 child(type == TYPE_CONTROL), |
| 133 transient(type == TYPE_BUBBLE || type == TYPE_POPUP || type == TYPE_MENU), |
| 134 transparent(false), |
| 135 accept_events(true), |
| 136 can_activate(type != TYPE_POPUP && type != TYPE_MENU), |
| 137 keep_on_top(type == TYPE_MENU), |
| 138 ownership(NATIVE_WIDGET_OWNS_WIDGET), |
| 139 mirror_origin_in_rtl(false), |
| 140 has_dropshadow(false), |
| 141 show_state(ui::SHOW_STATE_DEFAULT), |
| 142 double_buffer(false), |
| 143 parent(NULL), |
| 144 parent_widget(NULL), |
| 145 native_widget(NULL), |
| 146 top_level(false), |
| 147 create_texture_for_layer(true) { |
| 148 } |
| 149 |
| 150 gfx::NativeView Widget::InitParams::GetParent() const { |
| 151 return parent_widget ? parent_widget->GetNativeView() : parent; |
| 152 } |
| 153 |
| 154 //////////////////////////////////////////////////////////////////////////////// |
| 155 // Widget, public: |
| 156 |
| 157 Widget::Widget() |
| 158 : native_widget_(NULL), |
| 159 widget_delegate_(NULL), |
| 160 non_client_view_(NULL), |
| 161 dragged_view_(NULL), |
| 162 event_stack_(), |
| 163 ownership_(InitParams::NATIVE_WIDGET_OWNS_WIDGET), |
| 164 is_secondary_widget_(true), |
| 165 frame_type_(FRAME_TYPE_DEFAULT), |
| 166 disable_inactive_rendering_(false), |
| 167 widget_closed_(false), |
| 168 saved_show_state_(ui::SHOW_STATE_DEFAULT), |
| 169 focus_on_creation_(true), |
| 170 is_top_level_(false), |
| 171 native_widget_initialized_(false), |
| 172 is_mouse_button_pressed_(false), |
| 173 last_mouse_event_was_move_(false) { |
| 174 } |
| 175 |
| 176 Widget::~Widget() { |
| 177 while (!event_stack_.empty()) { |
| 178 event_stack_.top()->reset(); |
| 179 event_stack_.pop(); |
| 180 } |
| 181 |
| 182 DestroyRootView(); |
| 183 if (ownership_ == InitParams::WIDGET_OWNS_NATIVE_WIDGET) |
| 184 delete native_widget_; |
| 185 } |
| 186 |
| 187 // static |
| 188 Widget* Widget::CreateWindow(WidgetDelegate* delegate) { |
| 189 return CreateWindowWithParentAndBounds(delegate, NULL, gfx::Rect()); |
| 190 } |
| 191 |
| 192 // static |
| 193 Widget* Widget::CreateWindowWithParent(WidgetDelegate* delegate, |
| 194 gfx::NativeWindow parent) { |
| 195 return CreateWindowWithParentAndBounds(delegate, parent, gfx::Rect()); |
| 196 } |
| 197 |
| 198 // static |
| 199 Widget* Widget::CreateWindowWithBounds(WidgetDelegate* delegate, |
| 200 const gfx::Rect& bounds) { |
| 201 return CreateWindowWithParentAndBounds(delegate, NULL, bounds); |
| 202 } |
| 203 |
| 204 // static |
| 205 Widget* Widget::CreateWindowWithParentAndBounds(WidgetDelegate* delegate, |
| 206 gfx::NativeWindow parent, |
| 207 const gfx::Rect& bounds) { |
| 208 Widget* widget = new Widget; |
| 209 Widget::InitParams params; |
| 210 params.delegate = delegate; |
| 211 #if defined(OS_WIN) || defined(USE_AURA) |
| 212 params.parent = parent; |
| 213 #endif |
| 214 params.bounds = bounds; |
| 215 widget->Init(params); |
| 216 return widget; |
| 217 } |
| 218 |
| 219 // static |
| 220 void Widget::SetPureViews(bool pure) { |
| 221 use_pure_views = pure; |
| 222 } |
| 223 |
| 224 // static |
| 225 bool Widget::IsPureViews() { |
| 226 #if defined(USE_AURA) || defined(TOUCH_UI) |
| 227 return true; |
| 228 #else |
| 229 return use_pure_views; |
| 230 #endif |
| 231 } |
| 232 |
| 233 // static |
| 234 Widget* Widget::GetWidgetForNativeView(gfx::NativeView native_view) { |
| 235 internal::NativeWidgetPrivate* native_widget = |
| 236 internal::NativeWidgetPrivate::GetNativeWidgetForNativeView(native_view); |
| 237 return native_widget ? native_widget->GetWidget() : NULL; |
| 238 } |
| 239 |
| 240 // static |
| 241 Widget* Widget::GetWidgetForNativeWindow(gfx::NativeWindow native_window) { |
| 242 internal::NativeWidgetPrivate* native_widget = |
| 243 internal::NativeWidgetPrivate::GetNativeWidgetForNativeWindow( |
| 244 native_window); |
| 245 return native_widget ? native_widget->GetWidget() : NULL; |
| 246 } |
| 247 |
| 248 // static |
| 249 Widget* Widget::GetTopLevelWidgetForNativeView(gfx::NativeView native_view) { |
| 250 internal::NativeWidgetPrivate* native_widget = |
| 251 internal::NativeWidgetPrivate::GetTopLevelNativeWidget(native_view); |
| 252 return native_widget ? native_widget->GetWidget() : NULL; |
| 253 } |
| 254 |
| 255 |
| 256 // static |
| 257 void Widget::GetAllChildWidgets(gfx::NativeView native_view, |
| 258 Widgets* children) { |
| 259 internal::NativeWidgetPrivate::GetAllChildWidgets(native_view, children); |
| 260 } |
| 261 |
| 262 // static |
| 263 void Widget::ReparentNativeView(gfx::NativeView native_view, |
| 264 gfx::NativeView new_parent) { |
| 265 internal::NativeWidgetPrivate::ReparentNativeView(native_view, new_parent); |
| 266 } |
| 267 |
| 268 // static |
| 269 int Widget::GetLocalizedContentsWidth(int col_resource_id) { |
| 270 return ui::GetLocalizedContentsWidthForFont(col_resource_id, |
| 271 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); |
| 272 } |
| 273 |
| 274 // static |
| 275 int Widget::GetLocalizedContentsHeight(int row_resource_id) { |
| 276 return ui::GetLocalizedContentsHeightForFont(row_resource_id, |
| 277 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); |
| 278 } |
| 279 |
| 280 // static |
| 281 gfx::Size Widget::GetLocalizedContentsSize(int col_resource_id, |
| 282 int row_resource_id) { |
| 283 return gfx::Size(GetLocalizedContentsWidth(col_resource_id), |
| 284 GetLocalizedContentsHeight(row_resource_id)); |
| 285 } |
| 286 |
| 287 // static |
| 288 void Widget::SetDebugPaintEnabled(bool enabled) { |
| 289 debug_paint = enabled; |
| 290 } |
| 291 |
| 292 // static |
| 293 bool Widget::IsDebugPaintEnabled() { |
| 294 return debug_paint; |
| 295 } |
| 296 |
| 297 // static |
| 298 bool Widget::RequiresNonClientView(InitParams::Type type) { |
| 299 return type == InitParams::TYPE_WINDOW || type == InitParams::TYPE_BUBBLE; |
| 300 } |
| 301 |
| 302 void Widget::Init(const InitParams& params) { |
| 303 is_top_level_ = params.top_level || |
| 304 (!params.child && |
| 305 params.type != InitParams::TYPE_CONTROL && |
| 306 params.type != InitParams::TYPE_TOOLTIP); |
| 307 widget_delegate_ = params.delegate ? |
| 308 params.delegate : new DefaultWidgetDelegate(this, params); |
| 309 ownership_ = params.ownership; |
| 310 native_widget_ = params.native_widget ? |
| 311 params.native_widget->AsNativeWidgetPrivate() : |
| 312 internal::NativeWidgetPrivate::CreateNativeWidget(this); |
| 313 GetRootView(); |
| 314 default_theme_provider_.reset(new DefaultThemeProvider); |
| 315 if (params.type == InitParams::TYPE_MENU) { |
| 316 is_mouse_button_pressed_ = |
| 317 internal::NativeWidgetPrivate::IsMouseButtonDown(); |
| 318 } |
| 319 native_widget_->InitNativeWidget(params); |
| 320 if (RequiresNonClientView(params.type)) { |
| 321 non_client_view_ = new NonClientView; |
| 322 non_client_view_->SetFrameView(CreateNonClientFrameView()); |
| 323 // Create the ClientView, add it to the NonClientView and add the |
| 324 // NonClientView to the RootView. This will cause everything to be parented. |
| 325 non_client_view_->set_client_view(widget_delegate_->CreateClientView(this)); |
| 326 SetContentsView(non_client_view_); |
| 327 SetInitialBounds(params.bounds); |
| 328 if (params.show_state == ui::SHOW_STATE_MAXIMIZED) |
| 329 Maximize(); |
| 330 else if (params.show_state == ui::SHOW_STATE_MINIMIZED) |
| 331 Minimize(); |
| 332 UpdateWindowTitle(); |
| 333 } |
| 334 native_widget_initialized_ = true; |
| 335 } |
| 336 |
| 337 // Unconverted methods (see header) -------------------------------------------- |
| 338 |
| 339 gfx::NativeView Widget::GetNativeView() const { |
| 340 return native_widget_->GetNativeView(); |
| 341 } |
| 342 |
| 343 gfx::NativeWindow Widget::GetNativeWindow() const { |
| 344 return native_widget_->GetNativeWindow(); |
| 345 } |
| 346 |
| 347 void Widget::AddObserver(Widget::Observer* observer) { |
| 348 observers_.AddObserver(observer); |
| 349 } |
| 350 |
| 351 void Widget::RemoveObserver(Widget::Observer* observer) { |
| 352 observers_.RemoveObserver(observer); |
| 353 } |
| 354 |
| 355 bool Widget::HasObserver(Widget::Observer* observer) { |
| 356 return observers_.HasObserver(observer); |
| 357 } |
| 358 |
| 359 bool Widget::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { |
| 360 return false; |
| 361 } |
| 362 |
| 363 void Widget::ViewHierarchyChanged(bool is_add, View* parent, View* child) { |
| 364 if (!is_add) { |
| 365 if (child == dragged_view_) |
| 366 dragged_view_ = NULL; |
| 367 |
| 368 FocusManager* focus_manager = GetFocusManager(); |
| 369 if (focus_manager) |
| 370 focus_manager->ViewRemoved(child); |
| 371 ViewStorage::GetInstance()->ViewRemoved(child); |
| 372 native_widget_->ViewRemoved(child); |
| 373 } |
| 374 } |
| 375 |
| 376 void Widget::NotifyNativeViewHierarchyChanged(bool attached, |
| 377 gfx::NativeView native_view) { |
| 378 if (!attached) { |
| 379 FocusManager* focus_manager = GetFocusManager(); |
| 380 // We are being removed from a window hierarchy. Treat this as |
| 381 // the root_view_ being removed. |
| 382 if (focus_manager) |
| 383 focus_manager->ViewRemoved(root_view_.get()); |
| 384 } |
| 385 root_view_->NotifyNativeViewHierarchyChanged(attached, native_view); |
| 386 } |
| 387 |
| 388 // Converted methods (see header) ---------------------------------------------- |
| 389 |
| 390 Widget* Widget::GetTopLevelWidget() { |
| 391 return const_cast<Widget*>( |
| 392 static_cast<const Widget*>(this)->GetTopLevelWidget()); |
| 393 } |
| 394 |
| 395 const Widget* Widget::GetTopLevelWidget() const { |
| 396 // GetTopLevelNativeWidget doesn't work during destruction because |
| 397 // property is gone after gobject gets deleted. Short circuit here |
| 398 // for toplevel so that InputMethod can remove itself from |
| 399 // focus manager. |
| 400 return is_top_level() ? this : native_widget_->GetTopLevelWidget(); |
| 401 } |
| 402 |
| 403 void Widget::SetContentsView(View* view) { |
| 404 root_view_->SetContentsView(view); |
| 405 if (non_client_view_ != view) |
| 406 non_client_view_ = NULL; |
| 407 } |
| 408 |
| 409 View* Widget::GetContentsView() { |
| 410 return root_view_->GetContentsView(); |
| 411 } |
| 412 |
| 413 gfx::Rect Widget::GetWindowScreenBounds() const { |
| 414 return native_widget_->GetWindowScreenBounds(); |
| 415 } |
| 416 |
| 417 gfx::Rect Widget::GetClientAreaScreenBounds() const { |
| 418 return native_widget_->GetClientAreaScreenBounds(); |
| 419 } |
| 420 |
| 421 gfx::Rect Widget::GetRestoredBounds() const { |
| 422 return native_widget_->GetRestoredBounds(); |
| 423 } |
| 424 |
| 425 void Widget::SetBounds(const gfx::Rect& bounds) { |
| 426 native_widget_->SetBounds(bounds); |
| 427 } |
| 428 |
| 429 void Widget::SetSize(const gfx::Size& size) { |
| 430 native_widget_->SetSize(size); |
| 431 } |
| 432 |
| 433 void Widget::SetBoundsConstrained(const gfx::Rect& bounds) { |
| 434 gfx::Rect work_area = |
| 435 gfx::Screen::GetMonitorWorkAreaNearestPoint(bounds.origin()); |
| 436 if (work_area.IsEmpty()) { |
| 437 SetBounds(bounds); |
| 438 } else { |
| 439 // Inset the work area slightly. |
| 440 work_area.Inset(10, 10, 10, 10); |
| 441 SetBounds(work_area.AdjustToFit(bounds)); |
| 442 } |
| 443 } |
| 444 |
| 445 void Widget::MoveAboveWidget(Widget* widget) { |
| 446 native_widget_->MoveAbove(widget->GetNativeView()); |
| 447 } |
| 448 |
| 449 void Widget::MoveAbove(gfx::NativeView native_view) { |
| 450 native_widget_->MoveAbove(native_view); |
| 451 } |
| 452 |
| 453 void Widget::MoveToTop() { |
| 454 native_widget_->MoveToTop(); |
| 455 } |
| 456 |
| 457 void Widget::SetShape(gfx::NativeRegion shape) { |
| 458 native_widget_->SetShape(shape); |
| 459 } |
| 460 |
| 461 void Widget::Close() { |
| 462 if (widget_closed_) { |
| 463 // It appears we can hit this code path if you close a modal dialog then |
| 464 // close the last browser before the destructor is hit, which triggers |
| 465 // invoking Close again. |
| 466 return; |
| 467 } |
| 468 |
| 469 bool can_close = true; |
| 470 if (non_client_view_) |
| 471 can_close = non_client_view_->CanClose(); |
| 472 if (can_close) { |
| 473 SaveWindowPlacement(); |
| 474 |
| 475 // During tear-down the top-level focus manager becomes unavailable to |
| 476 // GTK tabbed panes and their children, so normal deregistration via |
| 477 // |FormManager::ViewRemoved()| calls are fouled. We clear focus here |
| 478 // to avoid these redundant steps and to avoid accessing deleted views |
| 479 // that may have been in focus. |
| 480 if (is_top_level() && focus_manager_.get()) |
| 481 focus_manager_->SetFocusedView(NULL); |
| 482 |
| 483 native_widget_->Close(); |
| 484 widget_closed_ = true; |
| 485 } |
| 486 } |
| 487 |
| 488 void Widget::CloseNow() { |
| 489 native_widget_->CloseNow(); |
| 490 } |
| 491 |
| 492 void Widget::EnableClose(bool enable) { |
| 493 if (non_client_view_) |
| 494 non_client_view_->EnableClose(enable); |
| 495 native_widget_->EnableClose(enable); |
| 496 } |
| 497 |
| 498 void Widget::Show() { |
| 499 if (non_client_view_) { |
| 500 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED && |
| 501 !initial_restored_bounds_.IsEmpty()) { |
| 502 native_widget_->ShowMaximizedWithBounds(initial_restored_bounds_); |
| 503 } else { |
| 504 native_widget_->ShowWithWindowState(saved_show_state_); |
| 505 } |
| 506 // |saved_show_state_| only applies the first time the window is shown. |
| 507 // If we don't reset the value the window may be shown maximized every time |
| 508 // it is subsequently shown after being hidden. |
| 509 saved_show_state_ = ui::SHOW_STATE_NORMAL; |
| 510 } else { |
| 511 native_widget_->Show(); |
| 512 } |
| 513 } |
| 514 |
| 515 void Widget::Hide() { |
| 516 native_widget_->Hide(); |
| 517 } |
| 518 |
| 519 void Widget::ShowInactive() { |
| 520 // If this gets called with saved_show_state_ == ui::SHOW_STATE_MAXIMIZED, |
| 521 // call SetBounds()with the restored bounds to set the correct size. This |
| 522 // normally should not happen, but if it does we should avoid showing unsized |
| 523 // windows. |
| 524 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED && |
| 525 !initial_restored_bounds_.IsEmpty()) { |
| 526 SetBounds(initial_restored_bounds_); |
| 527 saved_show_state_ = ui::SHOW_STATE_NORMAL; |
| 528 } |
| 529 native_widget_->ShowWithWindowState(ui::SHOW_STATE_INACTIVE); |
| 530 } |
| 531 |
| 532 void Widget::Activate() { |
| 533 native_widget_->Activate(); |
| 534 } |
| 535 |
| 536 void Widget::Deactivate() { |
| 537 native_widget_->Deactivate(); |
| 538 } |
| 539 |
| 540 bool Widget::IsActive() const { |
| 541 return native_widget_->IsActive(); |
| 542 } |
| 543 |
| 544 void Widget::DisableInactiveRendering() { |
| 545 SetInactiveRenderingDisabled(true); |
| 546 } |
| 547 |
| 548 void Widget::SetAlwaysOnTop(bool on_top) { |
| 549 native_widget_->SetAlwaysOnTop(on_top); |
| 550 } |
| 551 |
| 552 void Widget::Maximize() { |
| 553 native_widget_->Maximize(); |
| 554 } |
| 555 |
| 556 void Widget::Minimize() { |
| 557 native_widget_->Minimize(); |
| 558 } |
| 559 |
| 560 void Widget::Restore() { |
| 561 native_widget_->Restore(); |
| 562 } |
| 563 |
| 564 bool Widget::IsMaximized() const { |
| 565 return native_widget_->IsMaximized(); |
| 566 } |
| 567 |
| 568 bool Widget::IsMinimized() const { |
| 569 return native_widget_->IsMinimized(); |
| 570 } |
| 571 |
| 572 void Widget::SetFullscreen(bool fullscreen) { |
| 573 native_widget_->SetFullscreen(fullscreen); |
| 574 } |
| 575 |
| 576 bool Widget::IsFullscreen() const { |
| 577 return native_widget_->IsFullscreen(); |
| 578 } |
| 579 |
| 580 void Widget::SetOpacity(unsigned char opacity) { |
| 581 native_widget_->SetOpacity(opacity); |
| 582 } |
| 583 |
| 584 void Widget::SetUseDragFrame(bool use_drag_frame) { |
| 585 native_widget_->SetUseDragFrame(use_drag_frame); |
| 586 } |
| 587 |
| 588 View* Widget::GetRootView() { |
| 589 if (!root_view_.get()) { |
| 590 // First time the root view is being asked for, create it now. |
| 591 root_view_.reset(CreateRootView()); |
| 592 } |
| 593 return root_view_.get(); |
| 594 } |
| 595 |
| 596 const View* Widget::GetRootView() const { |
| 597 return root_view_.get(); |
| 598 } |
| 599 |
| 600 bool Widget::IsVisible() const { |
| 601 return native_widget_->IsVisible(); |
| 602 } |
| 603 |
| 604 bool Widget::IsAccessibleWidget() const { |
| 605 return native_widget_->IsAccessibleWidget(); |
| 606 } |
| 607 |
| 608 ThemeProvider* Widget::GetThemeProvider() const { |
| 609 const Widget* root_widget = GetTopLevelWidget(); |
| 610 if (root_widget && root_widget != this) { |
| 611 // Attempt to get the theme provider, and fall back to the default theme |
| 612 // provider if not found. |
| 613 ThemeProvider* provider = root_widget->GetThemeProvider(); |
| 614 if (provider) |
| 615 return provider; |
| 616 |
| 617 provider = root_widget->default_theme_provider_.get(); |
| 618 if (provider) |
| 619 return provider; |
| 620 } |
| 621 return default_theme_provider_.get(); |
| 622 } |
| 623 |
| 624 FocusManager* Widget::GetFocusManager() { |
| 625 Widget* toplevel_widget = GetTopLevelWidget(); |
| 626 return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; |
| 627 } |
| 628 |
| 629 const FocusManager* Widget::GetFocusManager() const { |
| 630 const Widget* toplevel_widget = GetTopLevelWidget(); |
| 631 return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; |
| 632 } |
| 633 |
| 634 InputMethod* Widget::GetInputMethod() { |
| 635 if (is_top_level()) { |
| 636 if (!input_method_.get()) |
| 637 input_method_.reset(native_widget_->CreateInputMethod()); |
| 638 return input_method_.get(); |
| 639 } else { |
| 640 Widget* toplevel = GetTopLevelWidget(); |
| 641 // If GetTopLevelWidget() returns itself which is not toplevel, |
| 642 // the widget is detached from toplevel widget. |
| 643 // TODO(oshima): Fix GetTopLevelWidget() to return NULL |
| 644 // if there is no toplevel. We probably need to add GetTopMostWidget() |
| 645 // to replace some use cases. |
| 646 return (toplevel && toplevel != this) ? toplevel->GetInputMethod() : NULL; |
| 647 } |
| 648 } |
| 649 |
| 650 void Widget::RunShellDrag(View* view, const ui::OSExchangeData& data, |
| 651 int operation) { |
| 652 dragged_view_ = view; |
| 653 native_widget_->RunShellDrag(view, data, operation); |
| 654 // If the view is removed during the drag operation, dragged_view_ is set to |
| 655 // NULL. |
| 656 if (view && dragged_view_ == view) { |
| 657 dragged_view_ = NULL; |
| 658 view->OnDragDone(); |
| 659 } |
| 660 } |
| 661 |
| 662 void Widget::SchedulePaintInRect(const gfx::Rect& rect) { |
| 663 native_widget_->SchedulePaintInRect(rect); |
| 664 } |
| 665 |
| 666 void Widget::SetCursor(gfx::NativeCursor cursor) { |
| 667 native_widget_->SetCursor(cursor); |
| 668 } |
| 669 |
| 670 void Widget::ResetLastMouseMoveFlag() { |
| 671 last_mouse_event_was_move_ = false; |
| 672 } |
| 673 |
| 674 void Widget::SetNativeWindowProperty(const char* name, void* value) { |
| 675 native_widget_->SetNativeWindowProperty(name, value); |
| 676 } |
| 677 |
| 678 void* Widget::GetNativeWindowProperty(const char* name) const { |
| 679 return native_widget_->GetNativeWindowProperty(name); |
| 680 } |
| 681 |
| 682 void Widget::UpdateWindowTitle() { |
| 683 if (!non_client_view_) |
| 684 return; |
| 685 |
| 686 // If the non-client view is rendering its own title, it'll need to relayout |
| 687 // now. |
| 688 non_client_view_->Layout(); |
| 689 |
| 690 // Update the native frame's text. We do this regardless of whether or not |
| 691 // the native frame is being used, since this also updates the taskbar, etc. |
| 692 string16 window_title; |
| 693 if (native_widget_->IsScreenReaderActive()) { |
| 694 window_title = widget_delegate_->GetAccessibleWindowTitle(); |
| 695 } else { |
| 696 window_title = widget_delegate_->GetWindowTitle(); |
| 697 } |
| 698 base::i18n::AdjustStringForLocaleDirection(&window_title); |
| 699 native_widget_->SetWindowTitle(window_title); |
| 700 } |
| 701 |
| 702 void Widget::UpdateWindowIcon() { |
| 703 if (non_client_view_) |
| 704 non_client_view_->UpdateWindowIcon(); |
| 705 native_widget_->SetWindowIcons(widget_delegate_->GetWindowIcon(), |
| 706 widget_delegate_->GetWindowAppIcon()); |
| 707 } |
| 708 |
| 709 FocusTraversable* Widget::GetFocusTraversable() { |
| 710 return static_cast<internal::RootView*>(root_view_.get()); |
| 711 } |
| 712 |
| 713 void Widget::ThemeChanged() { |
| 714 root_view_->ThemeChanged(); |
| 715 } |
| 716 |
| 717 void Widget::LocaleChanged() { |
| 718 root_view_->LocaleChanged(); |
| 719 } |
| 720 |
| 721 void Widget::SetFocusTraversableParent(FocusTraversable* parent) { |
| 722 root_view_->SetFocusTraversableParent(parent); |
| 723 } |
| 724 |
| 725 void Widget::SetFocusTraversableParentView(View* parent_view) { |
| 726 root_view_->SetFocusTraversableParentView(parent_view); |
| 727 } |
| 728 |
| 729 void Widget::ClearNativeFocus() { |
| 730 native_widget_->ClearNativeFocus(); |
| 731 } |
| 732 |
| 733 void Widget::FocusNativeView(gfx::NativeView native_view) { |
| 734 native_widget_->FocusNativeView(native_view); |
| 735 } |
| 736 |
| 737 void Widget::UpdateFrameAfterFrameChange() { |
| 738 native_widget_->UpdateFrameAfterFrameChange(); |
| 739 } |
| 740 |
| 741 NonClientFrameView* Widget::CreateNonClientFrameView() { |
| 742 NonClientFrameView* frame_view = widget_delegate_->CreateNonClientFrameView(); |
| 743 if (!frame_view) |
| 744 frame_view = native_widget_->CreateNonClientFrameView(); |
| 745 return frame_view ? frame_view : new CustomFrameView(this); |
| 746 } |
| 747 |
| 748 bool Widget::ShouldUseNativeFrame() const { |
| 749 if (frame_type_ != FRAME_TYPE_DEFAULT) |
| 750 return frame_type_ == FRAME_TYPE_FORCE_NATIVE; |
| 751 return native_widget_->ShouldUseNativeFrame(); |
| 752 } |
| 753 |
| 754 void Widget::DebugToggleFrameType() { |
| 755 if (frame_type_ == FRAME_TYPE_DEFAULT) { |
| 756 frame_type_ = ShouldUseNativeFrame() ? FRAME_TYPE_FORCE_CUSTOM : |
| 757 FRAME_TYPE_FORCE_NATIVE; |
| 758 } else { |
| 759 frame_type_ = frame_type_ == FRAME_TYPE_FORCE_CUSTOM ? |
| 760 FRAME_TYPE_FORCE_NATIVE : FRAME_TYPE_FORCE_CUSTOM; |
| 761 } |
| 762 FrameTypeChanged(); |
| 763 } |
| 764 |
| 765 void Widget::FrameTypeChanged() { |
| 766 native_widget_->FrameTypeChanged(); |
| 767 } |
| 768 |
| 769 const ui::Compositor* Widget::GetCompositor() const { |
| 770 return native_widget_->GetCompositor(); |
| 771 } |
| 772 |
| 773 ui::Compositor* Widget::GetCompositor() { |
| 774 return native_widget_->GetCompositor(); |
| 775 } |
| 776 |
| 777 void Widget::CalculateOffsetToAncestorWithLayer(gfx::Point* offset, |
| 778 ui::Layer** layer_parent) { |
| 779 native_widget_->CalculateOffsetToAncestorWithLayer(offset, layer_parent); |
| 780 } |
| 781 |
| 782 void Widget::ReorderLayers() { |
| 783 native_widget_->ReorderLayers(); |
| 784 } |
| 785 |
| 786 void Widget::NotifyAccessibilityEvent( |
| 787 View* view, |
| 788 ui::AccessibilityTypes::Event event_type, |
| 789 bool send_native_event) { |
| 790 // Send the notification to the delegate. |
| 791 if (ViewsDelegate::views_delegate) |
| 792 ViewsDelegate::views_delegate->NotifyAccessibilityEvent(view, event_type); |
| 793 |
| 794 if (send_native_event) |
| 795 native_widget_->SendNativeAccessibilityEvent(view, event_type); |
| 796 } |
| 797 |
| 798 const NativeWidget* Widget::native_widget() const { |
| 799 return native_widget_; |
| 800 } |
| 801 |
| 802 NativeWidget* Widget::native_widget() { |
| 803 return native_widget_; |
| 804 } |
| 805 |
| 806 const Event* Widget::GetCurrentEvent() { |
| 807 return event_stack_.empty() ? NULL : event_stack_.top()->event(); |
| 808 } |
| 809 |
| 810 void Widget::TooltipTextChanged(View* view) { |
| 811 TooltipManager* manager = native_widget_private()->GetTooltipManager(); |
| 812 if (manager) |
| 813 manager->TooltipTextChanged(view); |
| 814 } |
| 815 |
| 816 bool Widget::SetInitialFocus() { |
| 817 if (!focus_on_creation_) |
| 818 return true; |
| 819 View* v = widget_delegate_->GetInitiallyFocusedView(); |
| 820 if (v) |
| 821 v->RequestFocus(); |
| 822 return !!v; |
| 823 } |
| 824 |
| 825 bool Widget::ConvertPointFromAncestor( |
| 826 const Widget* ancestor, gfx::Point* point) const { |
| 827 return native_widget_->ConvertPointFromAncestor(ancestor, point); |
| 828 } |
| 829 |
| 830 View* Widget::GetChildViewParent() { |
| 831 return GetContentsView() ? GetContentsView() : GetRootView(); |
| 832 } |
| 833 |
| 834 gfx::Rect Widget::GetWorkAreaBoundsInScreen() const { |
| 835 return native_widget_->GetWorkAreaBoundsInScreen(); |
| 836 } |
| 837 |
| 838 //////////////////////////////////////////////////////////////////////////////// |
| 839 // Widget, NativeWidgetDelegate implementation: |
| 840 |
| 841 bool Widget::IsModal() const { |
| 842 return widget_delegate_->IsModal(); |
| 843 } |
| 844 |
| 845 bool Widget::IsDialogBox() const { |
| 846 return !!widget_delegate_->AsDialogDelegate(); |
| 847 } |
| 848 |
| 849 bool Widget::CanActivate() const { |
| 850 return widget_delegate_->CanActivate(); |
| 851 } |
| 852 |
| 853 bool Widget::IsInactiveRenderingDisabled() const { |
| 854 return disable_inactive_rendering_; |
| 855 } |
| 856 |
| 857 void Widget::EnableInactiveRendering() { |
| 858 SetInactiveRenderingDisabled(false); |
| 859 } |
| 860 |
| 861 void Widget::OnNativeWidgetActivationChanged(bool active) { |
| 862 if (!active) { |
| 863 SaveWindowPlacement(); |
| 864 |
| 865 // Close any open menus. |
| 866 MenuController* menu_controller = MenuController::GetActiveInstance(); |
| 867 if (menu_controller) |
| 868 menu_controller->OnWidgetActivationChanged(); |
| 869 } |
| 870 |
| 871 FOR_EACH_OBSERVER(Observer, observers_, |
| 872 OnWidgetActivationChanged(this, active)); |
| 873 } |
| 874 |
| 875 void Widget::OnNativeFocus(gfx::NativeView focused_view) { |
| 876 WidgetFocusManager::GetInstance()->OnWidgetFocusEvent(focused_view, |
| 877 GetNativeView()); |
| 878 } |
| 879 |
| 880 void Widget::OnNativeBlur(gfx::NativeView focused_view) { |
| 881 WidgetFocusManager::GetInstance()->OnWidgetFocusEvent(GetNativeView(), |
| 882 focused_view); |
| 883 } |
| 884 |
| 885 void Widget::OnNativeWidgetVisibilityChanged(bool visible) { |
| 886 View* root = GetRootView(); |
| 887 root->PropagateVisibilityNotifications(root, visible); |
| 888 FOR_EACH_OBSERVER(Observer, observers_, |
| 889 OnWidgetVisibilityChanged(this, visible)); |
| 890 if (GetCompositor() && root->layer()) |
| 891 root->layer()->SetVisible(visible); |
| 892 } |
| 893 |
| 894 void Widget::OnNativeWidgetCreated() { |
| 895 if (is_top_level()) |
| 896 focus_manager_.reset(FocusManagerFactory::Create(this)); |
| 897 |
| 898 native_widget_->SetAccessibleRole( |
| 899 widget_delegate_->GetAccessibleWindowRole()); |
| 900 native_widget_->SetAccessibleState( |
| 901 widget_delegate_->GetAccessibleWindowState()); |
| 902 |
| 903 if (widget_delegate_->IsModal()) |
| 904 native_widget_->BecomeModal(); |
| 905 } |
| 906 |
| 907 void Widget::OnNativeWidgetDestroying() { |
| 908 FOR_EACH_OBSERVER(Observer, observers_, OnWidgetClosing(this)); |
| 909 if (non_client_view_) |
| 910 non_client_view_->WindowClosing(); |
| 911 widget_delegate_->WindowClosing(); |
| 912 } |
| 913 |
| 914 void Widget::OnNativeWidgetDestroyed() { |
| 915 widget_delegate_->DeleteDelegate(); |
| 916 widget_delegate_ = NULL; |
| 917 } |
| 918 |
| 919 gfx::Size Widget::GetMinimumSize() { |
| 920 return non_client_view_ ? non_client_view_->GetMinimumSize() : gfx::Size(); |
| 921 } |
| 922 |
| 923 void Widget::OnNativeWidgetSizeChanged(const gfx::Size& new_size) { |
| 924 root_view_->SetSize(new_size); |
| 925 |
| 926 // Size changed notifications can fire prior to full initialization |
| 927 // i.e. during session restore. Avoid saving session state during these |
| 928 // startup procedures. |
| 929 if (native_widget_initialized_) |
| 930 SaveWindowPlacement(); |
| 931 } |
| 932 |
| 933 void Widget::OnNativeWidgetBeginUserBoundsChange() { |
| 934 widget_delegate_->OnWindowBeginUserBoundsChange(); |
| 935 } |
| 936 |
| 937 void Widget::OnNativeWidgetEndUserBoundsChange() { |
| 938 widget_delegate_->OnWindowEndUserBoundsChange(); |
| 939 } |
| 940 |
| 941 bool Widget::HasFocusManager() const { |
| 942 return !!focus_manager_.get(); |
| 943 } |
| 944 |
| 945 bool Widget::OnNativeWidgetPaintAccelerated(const gfx::Rect& dirty_region) { |
| 946 ui::Compositor* compositor = GetCompositor(); |
| 947 if (!compositor) |
| 948 return false; |
| 949 |
| 950 // If the root view is animating, it is likely that it does not cover the same |
| 951 // set of pixels it did at the last frame, so we must clear when compositing |
| 952 // to avoid leaving ghosts. |
| 953 bool force_clear = false; |
| 954 if (GetRootView()->layer()) { |
| 955 const ui::Transform& layer_transform = GetRootView()->layer()->transform(); |
| 956 if (layer_transform != GetRootView()->GetTransform()) { |
| 957 // The layer has not caught up to the view (i.e., the layer is still |
| 958 // animating), and so a clear is required. |
| 959 force_clear = true; |
| 960 } else { |
| 961 // Determine if the layer fills the client area. |
| 962 gfx::Rect layer_bounds = GetRootView()->layer()->bounds(); |
| 963 layer_transform.TransformRect(&layer_bounds); |
| 964 gfx::Rect client_bounds = GetClientAreaScreenBounds(); |
| 965 // Translate bounds to origin (client area bounds are offset to account |
| 966 // for buttons, etc). |
| 967 client_bounds.set_origin(gfx::Point(0, 0)); |
| 968 if (!layer_bounds.Contains(client_bounds)) { |
| 969 // It doesn't, and so a clear is required. |
| 970 force_clear = true; |
| 971 } |
| 972 } |
| 973 } |
| 974 |
| 975 compositor->Draw(force_clear); |
| 976 return true; |
| 977 } |
| 978 |
| 979 void Widget::OnNativeWidgetPaint(gfx::Canvas* canvas) { |
| 980 GetRootView()->Paint(canvas); |
| 981 } |
| 982 |
| 983 int Widget::GetNonClientComponent(const gfx::Point& point) { |
| 984 return non_client_view_ ? |
| 985 non_client_view_->NonClientHitTest(point) : |
| 986 HTNOWHERE; |
| 987 } |
| 988 |
| 989 bool Widget::OnKeyEvent(const KeyEvent& event) { |
| 990 ScopedEvent scoped(this, event); |
| 991 return static_cast<internal::RootView*>(GetRootView())->OnKeyEvent(event); |
| 992 } |
| 993 |
| 994 bool Widget::OnMouseEvent(const MouseEvent& event) { |
| 995 ScopedEvent scoped(this, event); |
| 996 switch (event.type()) { |
| 997 case ui::ET_MOUSE_PRESSED: |
| 998 last_mouse_event_was_move_ = false; |
| 999 // Make sure we're still visible before we attempt capture as the mouse |
| 1000 // press processing may have made the window hide (as happens with menus). |
| 1001 if (GetRootView()->OnMousePressed(event) && IsVisible()) { |
| 1002 is_mouse_button_pressed_ = true; |
| 1003 if (!native_widget_->HasMouseCapture()) |
| 1004 native_widget_->SetMouseCapture(); |
| 1005 return true; |
| 1006 } |
| 1007 return false; |
| 1008 case ui::ET_MOUSE_RELEASED: |
| 1009 last_mouse_event_was_move_ = false; |
| 1010 is_mouse_button_pressed_ = false; |
| 1011 // Release capture first, to avoid confusion if OnMouseReleased blocks. |
| 1012 if (native_widget_->HasMouseCapture() && |
| 1013 ShouldReleaseCaptureOnMouseReleased()) { |
| 1014 native_widget_->ReleaseMouseCapture(); |
| 1015 } |
| 1016 GetRootView()->OnMouseReleased(event); |
| 1017 return (event.flags() & ui::EF_IS_NON_CLIENT) ? false : true; |
| 1018 case ui::ET_MOUSE_MOVED: |
| 1019 case ui::ET_MOUSE_DRAGGED: |
| 1020 if (native_widget_->HasMouseCapture() && is_mouse_button_pressed_) { |
| 1021 last_mouse_event_was_move_ = false; |
| 1022 GetRootView()->OnMouseDragged(event); |
| 1023 } else if (!last_mouse_event_was_move_ || |
| 1024 last_mouse_event_position_ != event.location()) { |
| 1025 last_mouse_event_position_ = event.location(); |
| 1026 last_mouse_event_was_move_ = true; |
| 1027 GetRootView()->OnMouseMoved(event); |
| 1028 } |
| 1029 return false; |
| 1030 case ui::ET_MOUSE_EXITED: |
| 1031 last_mouse_event_was_move_ = false; |
| 1032 GetRootView()->OnMouseExited(event); |
| 1033 return false; |
| 1034 case ui::ET_MOUSEWHEEL: |
| 1035 return GetRootView()->OnMouseWheel( |
| 1036 reinterpret_cast<const MouseWheelEvent&>(event)); |
| 1037 default: |
| 1038 return false; |
| 1039 } |
| 1040 return true; |
| 1041 } |
| 1042 |
| 1043 void Widget::OnMouseCaptureLost() { |
| 1044 if (is_mouse_button_pressed_) |
| 1045 GetRootView()->OnMouseCaptureLost(); |
| 1046 is_mouse_button_pressed_ = false; |
| 1047 } |
| 1048 |
| 1049 ui::TouchStatus Widget::OnTouchEvent(const TouchEvent& event) { |
| 1050 ScopedEvent scoped(this, event); |
| 1051 return static_cast<internal::RootView*>(GetRootView())->OnTouchEvent(event); |
| 1052 } |
| 1053 |
| 1054 bool Widget::ExecuteCommand(int command_id) { |
| 1055 return widget_delegate_->ExecuteWindowsCommand(command_id); |
| 1056 } |
| 1057 |
| 1058 InputMethod* Widget::GetInputMethodDirect() { |
| 1059 return input_method_.get(); |
| 1060 } |
| 1061 |
| 1062 Widget* Widget::AsWidget() { |
| 1063 return this; |
| 1064 } |
| 1065 |
| 1066 const Widget* Widget::AsWidget() const { |
| 1067 return this; |
| 1068 } |
| 1069 |
| 1070 //////////////////////////////////////////////////////////////////////////////// |
| 1071 // Widget, FocusTraversable implementation: |
| 1072 |
| 1073 FocusSearch* Widget::GetFocusSearch() { |
| 1074 return root_view_->GetFocusSearch(); |
| 1075 } |
| 1076 |
| 1077 FocusTraversable* Widget::GetFocusTraversableParent() { |
| 1078 // We are a proxy to the root view, so we should be bypassed when traversing |
| 1079 // up and as a result this should not be called. |
| 1080 NOTREACHED(); |
| 1081 return NULL; |
| 1082 } |
| 1083 |
| 1084 View* Widget::GetFocusTraversableParentView() { |
| 1085 // We are a proxy to the root view, so we should be bypassed when traversing |
| 1086 // up and as a result this should not be called. |
| 1087 NOTREACHED(); |
| 1088 return NULL; |
| 1089 } |
| 1090 |
| 1091 //////////////////////////////////////////////////////////////////////////////// |
| 1092 // Widget, protected: |
| 1093 |
| 1094 internal::RootView* Widget::CreateRootView() { |
| 1095 return new internal::RootView(this); |
| 1096 } |
| 1097 |
| 1098 void Widget::DestroyRootView() { |
| 1099 non_client_view_ = NULL; |
| 1100 root_view_.reset(); |
| 1101 // Input method has to be destroyed before focus manager. |
| 1102 input_method_.reset(); |
| 1103 // Defer focus manager's destruction. This is for the case when the |
| 1104 // focus manager is referenced by a child NativeWidgetGtk (e.g. TabbedPane in |
| 1105 // a dialog). When gtk_widget_destroy is called on the parent, the destroy |
| 1106 // signal reaches parent first and then the child. Thus causing the parent |
| 1107 // NativeWidgetGtk's dtor executed before the child's. If child's view |
| 1108 // hierarchy references this focus manager, it crashes. This will defer focus |
| 1109 // manager's destruction after child NativeWidgetGtk's dtor. |
| 1110 FocusManager* focus_manager = focus_manager_.release(); |
| 1111 if (focus_manager) |
| 1112 MessageLoop::current()->DeleteSoon(FROM_HERE, focus_manager); |
| 1113 } |
| 1114 |
| 1115 //////////////////////////////////////////////////////////////////////////////// |
| 1116 // Widget, private: |
| 1117 |
| 1118 bool Widget::ShouldReleaseCaptureOnMouseReleased() const { |
| 1119 return true; |
| 1120 } |
| 1121 |
| 1122 void Widget::SetInactiveRenderingDisabled(bool value) { |
| 1123 disable_inactive_rendering_ = value; |
| 1124 // We need to always notify the NonClientView so that it can trigger a paint. |
| 1125 // TODO: what's really needed is a way to know when either the active state |
| 1126 // changes or |disable_inactive_rendering_| changes. |
| 1127 if (non_client_view_) |
| 1128 non_client_view_->SetInactiveRenderingDisabled(value); |
| 1129 native_widget_->SetInactiveRenderingDisabled(value); |
| 1130 } |
| 1131 |
| 1132 void Widget::SaveWindowPlacement() { |
| 1133 // The window delegate does the actual saving for us. It seems like (judging |
| 1134 // by go/crash) that in some circumstances we can end up here after |
| 1135 // WM_DESTROY, at which point the window delegate is likely gone. So just |
| 1136 // bail. |
| 1137 if (!widget_delegate_) |
| 1138 return; |
| 1139 |
| 1140 ui::WindowShowState show_state = ui::SHOW_STATE_NORMAL; |
| 1141 gfx::Rect bounds; |
| 1142 native_widget_->GetWindowPlacement(&bounds, &show_state); |
| 1143 widget_delegate_->SaveWindowPlacement(bounds, show_state); |
| 1144 } |
| 1145 |
| 1146 void Widget::SetInitialBounds(const gfx::Rect& bounds) { |
| 1147 if (!non_client_view_) |
| 1148 return; |
| 1149 |
| 1150 gfx::Rect saved_bounds; |
| 1151 if (GetSavedWindowPlacement(&saved_bounds, &saved_show_state_)) { |
| 1152 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED) { |
| 1153 // If we're going to maximize, wait until Show is invoked to set the |
| 1154 // bounds. That way we avoid a noticable resize. |
| 1155 initial_restored_bounds_ = saved_bounds; |
| 1156 } else { |
| 1157 SetBounds(saved_bounds); |
| 1158 } |
| 1159 } else { |
| 1160 if (bounds.IsEmpty()) { |
| 1161 // No initial bounds supplied, so size the window to its content and |
| 1162 // center over its parent. |
| 1163 native_widget_->CenterWindow(non_client_view_->GetPreferredSize()); |
| 1164 } else { |
| 1165 // Use the supplied initial bounds. |
| 1166 SetBoundsConstrained(bounds); |
| 1167 } |
| 1168 } |
| 1169 } |
| 1170 |
| 1171 bool Widget::GetSavedWindowPlacement(gfx::Rect* bounds, |
| 1172 ui::WindowShowState* show_state) { |
| 1173 // First we obtain the window's saved show-style and store it. We need to do |
| 1174 // this here, rather than in Show() because by the time Show() is called, |
| 1175 // the window's size will have been reset (below) and the saved maximized |
| 1176 // state will have been lost. Sadly there's no way to tell on Windows when |
| 1177 // a window is restored from maximized state, so we can't more accurately |
| 1178 // track maximized state independently of sizing information. |
| 1179 |
| 1180 // Restore the window's placement from the controller. |
| 1181 if (widget_delegate_->GetSavedWindowPlacement(bounds, show_state)) { |
| 1182 if (!widget_delegate_->ShouldRestoreWindowSize()) { |
| 1183 bounds->set_size(non_client_view_->GetPreferredSize()); |
| 1184 } else { |
| 1185 gfx::Size minimum_size = GetMinimumSize(); |
| 1186 // Make sure the bounds are at least the minimum size. |
| 1187 if (bounds->width() < minimum_size.width()) |
| 1188 bounds->set_width(minimum_size.width()); |
| 1189 |
| 1190 if (bounds->height() < minimum_size.height()) |
| 1191 bounds->set_height(minimum_size.height()); |
| 1192 } |
| 1193 return true; |
| 1194 } |
| 1195 return false; |
| 1196 } |
| 1197 |
| 1198 void Widget::ReplaceInputMethod(InputMethod* input_method) { |
| 1199 input_method_.reset(input_method); |
| 1200 // TODO(oshima): Gtk's textfield doesn't need views InputMethod. |
| 1201 // Remove this check once gtk is removed. |
| 1202 if (input_method) { |
| 1203 input_method->set_delegate(native_widget_); |
| 1204 input_method->Init(this); |
| 1205 } |
| 1206 } |
| 1207 |
| 1208 namespace internal { |
| 1209 |
| 1210 //////////////////////////////////////////////////////////////////////////////// |
| 1211 // internal::NativeWidgetPrivate, NativeWidget implementation: |
| 1212 |
| 1213 internal::NativeWidgetPrivate* NativeWidgetPrivate::AsNativeWidgetPrivate() { |
| 1214 return this; |
| 1215 } |
| 1216 |
| 1217 } // namespace internal |
| 1218 } // namespace views |
OLD | NEW |