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