| 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 |