native_widget_aura.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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/native_widget_aura.h" 6 7#include "base/bind.h" 8#include "base/strings/string_util.h" 9#include "third_party/skia/include/core/SkRegion.h" 10#include "ui/aura/client/activation_client.h" 11#include "ui/aura/client/aura_constants.h" 12#include "ui/aura/client/cursor_client.h" 13#include "ui/aura/client/drag_drop_client.h" 14#include "ui/aura/client/screen_position_client.h" 15#include "ui/aura/client/stacking_client.h" 16#include "ui/aura/client/window_move_client.h" 17#include "ui/aura/client/window_types.h" 18#include "ui/aura/env.h" 19#include "ui/aura/focus_manager.h" 20#include "ui/aura/root_window.h" 21#include "ui/aura/window.h" 22#include "ui/aura/window_observer.h" 23#include "ui/base/dragdrop/os_exchange_data.h" 24#include "ui/base/events/event.h" 25#include "ui/base/ui_base_types.h" 26#include "ui/compositor/layer.h" 27#include "ui/gfx/canvas.h" 28#include "ui/gfx/font.h" 29#include "ui/gfx/screen.h" 30#include "ui/native_theme/native_theme_aura.h" 31#include "ui/views/drag_utils.h" 32#include "ui/views/ime/input_method_bridge.h" 33#include "ui/views/views_delegate.h" 34#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" 35#include "ui/views/widget/drop_helper.h" 36#include "ui/views/widget/native_widget_aura_window_observer.h" 37#include "ui/views/widget/native_widget_delegate.h" 38#include "ui/views/widget/root_view.h" 39#include "ui/views/widget/tooltip_manager_aura.h" 40#include "ui/views/widget/widget_aura_utils.h" 41#include "ui/views/widget/widget_delegate.h" 42#include "ui/views/widget/window_reorderer.h" 43 44#if defined(OS_WIN) 45#include "base/win/scoped_gdi_object.h" 46#include "base/win/win_util.h" 47#include "ui/base/l10n/l10n_util_win.h" 48#include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h" 49#endif 50 51#if defined(USE_X11) && !defined(OS_CHROMEOS) 52#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h" 53#endif 54 55#if !defined(OS_CHROMEOS) 56#include "ui/views/widget/desktop_aura/desktop_root_window_host.h" 57#endif 58 59namespace views { 60 61namespace { 62 63void SetRestoreBounds(aura::Window* window, const gfx::Rect& bounds) { 64 window->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds)); 65} 66 67} // namespace 68 69//////////////////////////////////////////////////////////////////////////////// 70// NativeWidgetAura, public: 71 72NativeWidgetAura::NativeWidgetAura(internal::NativeWidgetDelegate* delegate) 73 : delegate_(delegate), 74 window_(new aura::Window(this)), 75 ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), 76 close_widget_factory_(this), 77 can_activate_(true), 78 destroying_(false), 79 cursor_(gfx::kNullCursor), 80 saved_window_state_(ui::SHOW_STATE_DEFAULT) { 81 aura::client::SetFocusChangeObserver(window_, this); 82 aura::client::SetActivationChangeObserver(window_, this); 83} 84 85// static 86gfx::Font NativeWidgetAura::GetWindowTitleFont() { 87#if defined(OS_WIN) 88 NONCLIENTMETRICS ncm; 89 base::win::GetNonClientMetrics(&ncm); 90 l10n_util::AdjustUIFont(&(ncm.lfCaptionFont)); 91 base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont))); 92 return gfx::Font(caption_font); 93#else 94 return gfx::Font(); 95#endif 96} 97 98// static 99void NativeWidgetAura::RegisterNativeWidgetForWindow( 100 internal::NativeWidgetPrivate* native_widget, 101 aura::Window* window) { 102 window->set_user_data(native_widget); 103} 104 105//////////////////////////////////////////////////////////////////////////////// 106// NativeWidgetAura, internal::NativeWidgetPrivate implementation: 107 108void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) { 109 // Aura needs to know which desktop (Ash or regular) will manage this widget. 110 // See Widget::InitParams::context for details. 111 DCHECK(params.parent || params.context); 112 113 ownership_ = params.ownership; 114 115 RegisterNativeWidgetForWindow(this, window_); 116 window_->SetType(GetAuraWindowTypeForWidgetType(params.type)); 117 window_->SetProperty(aura::client::kShowStateKey, params.show_state); 118 if (params.type == Widget::InitParams::TYPE_BUBBLE) 119 aura::client::SetHideOnDeactivate(window_, true); 120 window_->SetTransparent( 121 params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW); 122 window_->Init(params.layer_type); 123 if (params.type == Widget::InitParams::TYPE_CONTROL) 124 window_->Show(); 125 126 delegate_->OnNativeWidgetCreated(false); 127 128 gfx::Rect window_bounds = params.bounds; 129 gfx::NativeView parent = params.parent; 130 gfx::NativeView context = params.context; 131 if (!params.child) { 132 // Set up the transient child before the window is added. This way the 133 // LayoutManager knows the window has a transient parent. 134 if (parent && parent->type() != aura::client::WINDOW_TYPE_UNKNOWN) { 135 parent->AddTransientChild(window_); 136 if (!context) 137 context = parent; 138 parent = NULL; 139 } 140 // SetAlwaysOnTop before SetParent so that always-on-top container is used. 141 SetAlwaysOnTop(params.keep_on_top); 142 // Make sure we have a real |window_bounds|. 143 if (parent && window_bounds == gfx::Rect()) { 144 // If a parent is specified but no bounds are given, 145 // use the origin of the parent's display so that the widget 146 // will be added to the same display as the parent. 147 gfx::Rect bounds = gfx::Screen::GetScreenFor(parent)-> 148 GetDisplayNearestWindow(parent).bounds(); 149 window_bounds.set_origin(bounds.origin()); 150 } 151 } 152 153 if (parent) { 154 parent->AddChild(window_); 155 } else { 156 window_->SetDefaultParentByRootWindow(context->GetRootWindow(), 157 window_bounds); 158 } 159 160 // Wait to set the bounds until we have a parent. That way we can know our 161 // true state/bounds (the LayoutManager may enforce a particular 162 // state/bounds). 163 if (IsMaximized()) 164 SetRestoreBounds(window_, window_bounds); 165 else 166 SetBounds(window_bounds); 167 window_->set_ignore_events(!params.accept_events); 168 can_activate_ = params.can_activate && 169 params.type != Widget::InitParams::TYPE_CONTROL && 170 params.type != Widget::InitParams::TYPE_TOOLTIP; 171 DCHECK(GetWidget()->GetRootView()); 172#if !defined(OS_MACOSX) 173 if (params.type != Widget::InitParams::TYPE_TOOLTIP) 174 tooltip_manager_.reset(new views::TooltipManagerAura(window_, GetWidget())); 175#endif // !defined(OS_MACOSX) 176 177 drop_helper_.reset(new DropHelper(GetWidget()->GetRootView())); 178 if (params.type != Widget::InitParams::TYPE_TOOLTIP && 179 params.type != Widget::InitParams::TYPE_POPUP) { 180 aura::client::SetDragDropDelegate(window_, this); 181 } 182 183 aura::client::SetActivationDelegate(window_, this); 184 185 window_->SetProperty(aura::client::kCanMaximizeKey, 186 GetWidget()->widget_delegate()->CanMaximize()); 187 window_->SetProperty(aura::client::kCanResizeKey, 188 GetWidget()->widget_delegate()->CanResize()); 189 190 window_reorderer_.reset(new WindowReorderer(window_, 191 GetWidget()->GetRootView())); 192} 193 194NonClientFrameView* NativeWidgetAura::CreateNonClientFrameView() { 195 return NULL; 196} 197 198bool NativeWidgetAura::ShouldUseNativeFrame() const { 199 // There is only one frame type for aura. 200 return false; 201} 202 203void NativeWidgetAura::FrameTypeChanged() { 204 // This is called when the Theme has changed; forward the event to the root 205 // widget. 206 GetWidget()->ThemeChanged(); 207 GetWidget()->GetRootView()->SchedulePaint(); 208} 209 210Widget* NativeWidgetAura::GetWidget() { 211 return delegate_->AsWidget(); 212} 213 214const Widget* NativeWidgetAura::GetWidget() const { 215 return delegate_->AsWidget(); 216} 217 218gfx::NativeView NativeWidgetAura::GetNativeView() const { 219 return window_; 220} 221 222gfx::NativeWindow NativeWidgetAura::GetNativeWindow() const { 223 return window_; 224} 225 226Widget* NativeWidgetAura::GetTopLevelWidget() { 227 NativeWidgetPrivate* native_widget = GetTopLevelNativeWidget(GetNativeView()); 228 return native_widget ? native_widget->GetWidget() : NULL; 229} 230 231const ui::Compositor* NativeWidgetAura::GetCompositor() const { 232 return window_ ? window_->layer()->GetCompositor() : NULL; 233} 234 235ui::Compositor* NativeWidgetAura::GetCompositor() { 236 return window_ ? window_->layer()->GetCompositor() : NULL; 237} 238 239ui::Layer* NativeWidgetAura::GetLayer() { 240 return window_ ? window_->layer() : NULL; 241} 242 243void NativeWidgetAura::ReorderNativeViews() { 244 window_reorderer_->ReorderChildWindows(); 245} 246 247void NativeWidgetAura::ViewRemoved(View* view) { 248 DCHECK(drop_helper_.get() != NULL); 249 drop_helper_->ResetTargetViewIfEquals(view); 250} 251 252void NativeWidgetAura::SetNativeWindowProperty(const char* name, void* value) { 253 if (window_) 254 window_->SetNativeWindowProperty(name, value); 255} 256 257void* NativeWidgetAura::GetNativeWindowProperty(const char* name) const { 258 return window_ ? window_->GetNativeWindowProperty(name) : NULL; 259} 260 261TooltipManager* NativeWidgetAura::GetTooltipManager() const { 262 return tooltip_manager_.get(); 263} 264 265void NativeWidgetAura::SetCapture() { 266 if (window_) 267 window_->SetCapture(); 268} 269 270void NativeWidgetAura::ReleaseCapture() { 271 if (window_) 272 window_->ReleaseCapture(); 273} 274 275bool NativeWidgetAura::HasCapture() const { 276 return window_ && window_->HasCapture(); 277} 278 279InputMethod* NativeWidgetAura::CreateInputMethod() { 280 if (!window_) 281 return NULL; 282 aura::RootWindow* root_window = window_->GetRootWindow(); 283 ui::InputMethod* host = 284 root_window->GetProperty(aura::client::kRootWindowInputMethodKey); 285 return new InputMethodBridge(this, host, true); 286} 287 288internal::InputMethodDelegate* NativeWidgetAura::GetInputMethodDelegate() { 289 return this; 290} 291 292void NativeWidgetAura::CenterWindow(const gfx::Size& size) { 293 if (!window_) 294 return; 295 296 gfx::Rect parent_bounds(window_->parent()->GetBoundsInRootWindow()); 297 // When centering window, we take the intersection of the host and 298 // the parent. We assume the root window represents the visible 299 // rect of a single screen. 300 gfx::Rect work_area = gfx::Screen::GetScreenFor(window_)-> 301 GetDisplayNearestWindow(window_).work_area(); 302 303 aura::client::ScreenPositionClient* screen_position_client = 304 aura::client::GetScreenPositionClient(window_->GetRootWindow()); 305 if (screen_position_client) { 306 gfx::Point origin = work_area.origin(); 307 screen_position_client->ConvertPointFromScreen(window_->GetRootWindow(), 308 &origin); 309 work_area.set_origin(origin); 310 } 311 312 parent_bounds.Intersect(work_area); 313 314 // If |window_|'s transient parent's bounds are big enough to fit it, then we 315 // center it with respect to the transient parent. 316 if (window_->transient_parent()) { 317 gfx::Rect transient_parent_rect = window_->transient_parent()-> 318 GetBoundsInRootWindow(); 319 transient_parent_rect.Intersect(work_area); 320 if (transient_parent_rect.height() >= size.height() && 321 transient_parent_rect.width() >= size.width()) 322 parent_bounds = transient_parent_rect; 323 } 324 325 gfx::Rect window_bounds( 326 parent_bounds.x() + (parent_bounds.width() - size.width()) / 2, 327 parent_bounds.y() + (parent_bounds.height() - size.height()) / 2, 328 size.width(), 329 size.height()); 330 // Don't size the window bigger than the parent, otherwise the user may not be 331 // able to close or move it. 332 window_bounds.AdjustToFit(parent_bounds); 333 334 // Convert the bounds back relative to the parent. 335 gfx::Point origin = window_bounds.origin(); 336 aura::Window::ConvertPointToTarget(window_->GetRootWindow(), 337 window_->parent(), &origin); 338 window_bounds.set_origin(origin); 339 window_->SetBounds(window_bounds); 340} 341 342void NativeWidgetAura::GetWindowPlacement( 343 gfx::Rect* bounds, 344 ui::WindowShowState* show_state) const { 345 // The interface specifies returning restored bounds, not current bounds. 346 *bounds = GetRestoredBounds(); 347 *show_state = window_ ? window_->GetProperty(aura::client::kShowStateKey) : 348 ui::SHOW_STATE_DEFAULT; 349} 350 351void NativeWidgetAura::SetWindowTitle(const string16& title) { 352 if (window_) 353 window_->set_title(title); 354} 355 356void NativeWidgetAura::SetWindowIcons(const gfx::ImageSkia& window_icon, 357 const gfx::ImageSkia& app_icon) { 358 // Aura doesn't have window icons. 359} 360 361void NativeWidgetAura::InitModalType(ui::ModalType modal_type) { 362 if (modal_type != ui::MODAL_TYPE_NONE) 363 window_->SetProperty(aura::client::kModalKey, modal_type); 364} 365 366gfx::Rect NativeWidgetAura::GetWindowBoundsInScreen() const { 367 return window_ ? window_->GetBoundsInScreen() : gfx::Rect(); 368} 369 370gfx::Rect NativeWidgetAura::GetClientAreaBoundsInScreen() const { 371 // View-to-screen coordinate system transformations depend on this returning 372 // the full window bounds, for example View::ConvertPointToScreen(). 373 return window_ ? window_->GetBoundsInScreen() : gfx::Rect(); 374} 375 376gfx::Rect NativeWidgetAura::GetRestoredBounds() const { 377 if (!window_) 378 return gfx::Rect(); 379 380 // Restored bounds should only be relevant if the window is minimized or 381 // maximized. However, in some places the code expects GetRestoredBounds() 382 // to return the current window bounds if the window is not in either state. 383 if (IsMinimized() || IsMaximized() || IsFullscreen()) { 384 // Restore bounds are in screen coordinates, no need to convert. 385 gfx::Rect* restore_bounds = 386 window_->GetProperty(aura::client::kRestoreBoundsKey); 387 if (restore_bounds) 388 return *restore_bounds; 389 } 390 return window_->GetBoundsInScreen(); 391} 392 393void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) { 394 if (!window_) 395 return; 396 397 aura::RootWindow* root = window_->GetRootWindow(); 398 if (root) { 399 aura::client::ScreenPositionClient* screen_position_client = 400 aura::client::GetScreenPositionClient(root); 401 if (screen_position_client) { 402 gfx::Display dst_display = 403 gfx::Screen::GetScreenFor(window_)->GetDisplayMatching(bounds); 404 screen_position_client->SetBounds(window_, bounds, dst_display); 405 return; 406 } 407 } 408 window_->SetBounds(bounds); 409} 410 411void NativeWidgetAura::SetSize(const gfx::Size& size) { 412 if (window_) 413 window_->SetBounds(gfx::Rect(window_->bounds().origin(), size)); 414} 415 416void NativeWidgetAura::StackAbove(gfx::NativeView native_view) { 417 if (window_ && window_->parent() && 418 window_->parent() == native_view->parent()) 419 window_->parent()->StackChildAbove(window_, native_view); 420} 421 422void NativeWidgetAura::StackAtTop() { 423 if (window_) 424 window_->parent()->StackChildAtTop(window_); 425} 426 427void NativeWidgetAura::StackBelow(gfx::NativeView native_view) { 428 if (window_ && window_->parent() && 429 window_->parent() == native_view->parent()) 430 window_->parent()->StackChildBelow(window_, native_view); 431} 432 433void NativeWidgetAura::SetShape(gfx::NativeRegion region) { 434 // No need for this. Just delete and ignore. 435 delete region; 436} 437 438void NativeWidgetAura::Close() { 439 // |window_| may already be deleted by parent window. This can happen 440 // when this widget is child widget or has transient parent 441 // and ownership is WIDGET_OWNS_NATIVE_WIDGET. 442 DCHECK(window_ || 443 ownership_ == Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET); 444 if (window_) { 445 window_->SuppressPaint(); 446 Hide(); 447 window_->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_NONE); 448 } 449 450 if (!close_widget_factory_.HasWeakPtrs()) { 451 base::MessageLoop::current()->PostTask( 452 FROM_HERE, 453 base::Bind(&NativeWidgetAura::CloseNow, 454 close_widget_factory_.GetWeakPtr())); 455 } 456} 457 458void NativeWidgetAura::CloseNow() { 459 delete window_; 460} 461 462void NativeWidgetAura::Show() { 463 ShowWithWindowState(ui::SHOW_STATE_INACTIVE); 464} 465 466void NativeWidgetAura::Hide() { 467 if (window_) 468 window_->Hide(); 469} 470 471void NativeWidgetAura::ShowMaximizedWithBounds( 472 const gfx::Rect& restored_bounds) { 473 SetRestoreBounds(window_, restored_bounds); 474 ShowWithWindowState(ui::SHOW_STATE_MAXIMIZED); 475} 476 477void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) { 478 if (!window_) 479 return; 480 481 if (state == ui::SHOW_STATE_MAXIMIZED || state == ui::SHOW_STATE_FULLSCREEN) 482 window_->SetProperty(aura::client::kShowStateKey, state); 483 window_->Show(); 484 if (can_activate_) { 485 if (state != ui::SHOW_STATE_INACTIVE) 486 Activate(); 487 // SetInitialFocus() should be always be called, even for 488 // SHOW_STATE_INACTIVE. When a frameless modal dialog is created by 489 // a widget of TYPE_WINDOW_FRAMELESS, Widget::Show() will call into 490 // this function with the window state SHOW_STATE_INACTIVE, 491 // SetInitialFoucs() has to be called so that the dialog can get focus. 492 // This also matches NativeWidgetWin which invokes SetInitialFocus 493 // regardless of show state. 494 SetInitialFocus(); 495 } 496} 497 498bool NativeWidgetAura::IsVisible() const { 499 return window_ && window_->IsVisible(); 500} 501 502void NativeWidgetAura::Activate() { 503 if (!window_) 504 return; 505 506 // We don't necessarily have a root window yet. This can happen with 507 // constrained windows. 508 if (window_->GetRootWindow()) { 509 aura::client::GetActivationClient(window_->GetRootWindow())->ActivateWindow( 510 window_); 511 } 512 if (window_->GetProperty(aura::client::kDrawAttentionKey)) 513 window_->SetProperty(aura::client::kDrawAttentionKey, false); 514} 515 516void NativeWidgetAura::Deactivate() { 517 if (!window_) 518 return; 519 aura::client::GetActivationClient(window_->GetRootWindow())->DeactivateWindow( 520 window_); 521} 522 523bool NativeWidgetAura::IsActive() const { 524 if (!window_) 525 return false; 526 527 // We may up here during destruction of the root, in which case 528 // GetRootWindow() returns NULL (~RootWindow() has run and we're in ~Window). 529 aura::RootWindow* root = window_->GetRootWindow(); 530 return root && 531 aura::client::GetActivationClient(root)->GetActiveWindow() == window_; 532} 533 534void NativeWidgetAura::SetAlwaysOnTop(bool on_top) { 535 if (window_) 536 window_->SetProperty(aura::client::kAlwaysOnTopKey, on_top); 537} 538 539void NativeWidgetAura::Maximize() { 540 if (window_) 541 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); 542} 543 544void NativeWidgetAura::Minimize() { 545 if (window_) 546 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); 547} 548 549bool NativeWidgetAura::IsMaximized() const { 550 return window_ && window_->GetProperty(aura::client::kShowStateKey) == 551 ui::SHOW_STATE_MAXIMIZED; 552} 553 554bool NativeWidgetAura::IsMinimized() const { 555 return window_ && window_->GetProperty(aura::client::kShowStateKey) == 556 ui::SHOW_STATE_MINIMIZED; 557} 558 559void NativeWidgetAura::Restore() { 560 if (window_) 561 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); 562} 563 564void NativeWidgetAura::SetFullscreen(bool fullscreen) { 565 if (!window_ || IsFullscreen() == fullscreen) 566 return; // Nothing to do. 567 568 // Save window state before entering full screen so that it could restored 569 // when exiting full screen. 570 if (fullscreen) 571 saved_window_state_ = window_->GetProperty(aura::client::kShowStateKey); 572 573 window_->SetProperty( 574 aura::client::kShowStateKey, 575 fullscreen ? ui::SHOW_STATE_FULLSCREEN : saved_window_state_); 576} 577 578bool NativeWidgetAura::IsFullscreen() const { 579 return window_ && window_->GetProperty(aura::client::kShowStateKey) == 580 ui::SHOW_STATE_FULLSCREEN; 581} 582 583void NativeWidgetAura::SetOpacity(unsigned char opacity) { 584 if (window_) 585 window_->layer()->SetOpacity(opacity / 255.0); 586} 587 588void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { 589 NOTIMPLEMENTED(); 590} 591 592void NativeWidgetAura::FlashFrame(bool flash) { 593 if (window_) 594 window_->SetProperty(aura::client::kDrawAttentionKey, flash); 595} 596 597void NativeWidgetAura::RunShellDrag(View* view, 598 const ui::OSExchangeData& data, 599 const gfx::Point& location, 600 int operation, 601 ui::DragDropTypes::DragEventSource source) { 602 if (window_) 603 views::RunShellDrag(window_, data, location, operation, source); 604} 605 606void NativeWidgetAura::SchedulePaintInRect(const gfx::Rect& rect) { 607 if (window_) 608 window_->SchedulePaintInRect(rect); 609} 610 611void NativeWidgetAura::SetCursor(gfx::NativeCursor cursor) { 612 cursor_ = cursor; 613 aura::client::CursorClient* cursor_client = 614 aura::client::GetCursorClient(window_->GetRootWindow()); 615 if (cursor_client) 616 cursor_client->SetCursor(cursor); 617} 618 619bool NativeWidgetAura::IsMouseEventsEnabled() const { 620 if (!window_) 621 return false; 622 aura::client::CursorClient* cursor_client = 623 aura::client::GetCursorClient(window_->GetRootWindow()); 624 return cursor_client ? cursor_client->IsMouseEventsEnabled() : true; 625} 626 627void NativeWidgetAura::ClearNativeFocus() { 628 aura::client::FocusClient* client = aura::client::GetFocusClient(window_); 629 if (window_ && client && window_->Contains(client->GetFocusedWindow())) 630 client->ResetFocusWithinActiveWindow(window_); 631} 632 633gfx::Rect NativeWidgetAura::GetWorkAreaBoundsInScreen() const { 634 if (!window_) 635 return gfx::Rect(); 636 return gfx::Screen::GetScreenFor(window_)-> 637 GetDisplayNearestWindow(window_).work_area(); 638} 639 640void NativeWidgetAura::SetInactiveRenderingDisabled(bool value) { 641 if (!window_) 642 return; 643 644 if (!value) { 645 active_window_observer_.reset(); 646 } else { 647 active_window_observer_.reset( 648 new NativeWidgetAuraWindowObserver(window_, delegate_)); 649 } 650} 651 652Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop( 653 const gfx::Vector2d& drag_offset, 654 Widget::MoveLoopSource source) { 655 if (window_ && window_->parent() && 656 aura::client::GetWindowMoveClient(window_->parent())) { 657 SetCapture(); 658 aura::client::WindowMoveSource window_move_source = 659 source == Widget::MOVE_LOOP_SOURCE_MOUSE ? 660 aura::client::WINDOW_MOVE_SOURCE_MOUSE : 661 aura::client::WINDOW_MOVE_SOURCE_TOUCH; 662 if (aura::client::GetWindowMoveClient(window_->parent())->RunMoveLoop( 663 window_, drag_offset, window_move_source) == 664 aura::client::MOVE_SUCCESSFUL) { 665 return Widget::MOVE_LOOP_SUCCESSFUL; 666 } 667 } 668 return Widget::MOVE_LOOP_CANCELED; 669} 670 671void NativeWidgetAura::EndMoveLoop() { 672 if (window_ && window_->parent() && 673 aura::client::GetWindowMoveClient(window_->parent())) { 674 aura::client::GetWindowMoveClient(window_->parent())->EndMoveLoop(); 675 } 676} 677 678void NativeWidgetAura::SetVisibilityChangedAnimationsEnabled(bool value) { 679 if (window_) 680 window_->SetProperty(aura::client::kAnimationsDisabledKey, !value); 681} 682 683ui::NativeTheme* NativeWidgetAura::GetNativeTheme() const { 684#if !defined(OS_CHROMEOS) 685 return DesktopRootWindowHost::GetNativeTheme(window_); 686#else 687 return ui::NativeThemeAura::instance(); 688#endif 689} 690 691void NativeWidgetAura::OnRootViewLayout() const { 692} 693 694//////////////////////////////////////////////////////////////////////////////// 695// NativeWidgetAura, views::InputMethodDelegate implementation: 696 697void NativeWidgetAura::DispatchKeyEventPostIME(const ui::KeyEvent& key) { 698 FocusManager* focus_manager = GetWidget()->GetFocusManager(); 699 delegate_->OnKeyEvent(const_cast<ui::KeyEvent*>(&key)); 700 if (key.handled() || !focus_manager) 701 return; 702 focus_manager->OnKeyEvent(key); 703} 704 705//////////////////////////////////////////////////////////////////////////////// 706// NativeWidgetAura, aura::WindowDelegate implementation: 707 708gfx::Size NativeWidgetAura::GetMinimumSize() const { 709 return delegate_->GetMinimumSize(); 710} 711 712gfx::Size NativeWidgetAura::GetMaximumSize() const { 713 return delegate_->GetMaximumSize(); 714} 715 716void NativeWidgetAura::OnBoundsChanged(const gfx::Rect& old_bounds, 717 const gfx::Rect& new_bounds) { 718 if (old_bounds.origin() != new_bounds.origin()) 719 delegate_->OnNativeWidgetMove(); 720 if (old_bounds.size() != new_bounds.size()) 721 delegate_->OnNativeWidgetSizeChanged(new_bounds.size()); 722} 723 724gfx::NativeCursor NativeWidgetAura::GetCursor(const gfx::Point& point) { 725 return cursor_; 726} 727 728int NativeWidgetAura::GetNonClientComponent(const gfx::Point& point) const { 729 return delegate_->GetNonClientComponent(point); 730} 731 732bool NativeWidgetAura::ShouldDescendIntoChildForEventHandling( 733 aura::Window* child, 734 const gfx::Point& location) { 735 views::WidgetDelegate* widget_delegate = GetWidget()->widget_delegate(); 736 if (widget_delegate && 737 !widget_delegate->ShouldDescendIntoChildForEventHandling(child, location)) 738 return false; 739 740 // Don't descend into |child| if there is a view with a Layer that contains 741 // the point and is stacked above |child|s layer. 742 typedef std::vector<ui::Layer*> Layers; 743 const Layers& root_layers(delegate_->GetRootLayers()); 744 if (root_layers.empty()) 745 return true; 746 747 Layers::const_iterator child_layer_iter( 748 std::find(window_->layer()->children().begin(), 749 window_->layer()->children().end(), child->layer())); 750 if (child_layer_iter == window_->layer()->children().end()) 751 return true; 752 753 for (std::vector<ui::Layer*>::const_reverse_iterator i = root_layers.rbegin(); 754 i != root_layers.rend(); ++i) { 755 ui::Layer* layer = *i; 756 if (layer->visible() && layer->bounds().Contains(location)) { 757 Layers::const_iterator root_layer_iter( 758 std::find(window_->layer()->children().begin(), 759 window_->layer()->children().end(), layer)); 760 if (root_layer_iter > child_layer_iter) 761 return false; 762 } 763 } 764 return true; 765} 766 767bool NativeWidgetAura::CanFocus() { 768 return can_activate_; 769} 770 771void NativeWidgetAura::OnCaptureLost() { 772 delegate_->OnMouseCaptureLost(); 773} 774 775void NativeWidgetAura::OnPaint(gfx::Canvas* canvas) { 776 delegate_->OnNativeWidgetPaint(canvas); 777} 778 779void NativeWidgetAura::OnDeviceScaleFactorChanged(float device_scale_factor) { 780 // Repainting with new scale factor will paint the content at the right scale. 781} 782 783void NativeWidgetAura::OnWindowDestroying() { 784 delegate_->OnNativeWidgetDestroying(); 785 786 // If the aura::Window is destroyed, we can no longer show tooltips. 787 tooltip_manager_.reset(); 788} 789 790void NativeWidgetAura::OnWindowDestroyed() { 791 window_ = NULL; 792 delegate_->OnNativeWidgetDestroyed(); 793 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) 794 delete this; 795} 796 797void NativeWidgetAura::OnWindowTargetVisibilityChanged(bool visible) { 798 delegate_->OnNativeWidgetVisibilityChanged(visible); 799} 800 801bool NativeWidgetAura::HasHitTestMask() const { 802 return delegate_->HasHitTestMask(); 803} 804 805void NativeWidgetAura::GetHitTestMask(gfx::Path* mask) const { 806 DCHECK(mask); 807 delegate_->GetHitTestMask(mask); 808} 809 810void NativeWidgetAura::DidRecreateLayer(ui::Layer *old_layer, 811 ui::Layer *new_layer) { 812} 813 814//////////////////////////////////////////////////////////////////////////////// 815// NativeWidgetAura, ui::EventHandler implementation: 816 817void NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) { 818 DCHECK(window_); 819 if (event->is_char()) { 820 // If a ui::InputMethod object is attached to the root window, character 821 // events are handled inside the object and are not passed to this function. 822 // If such object is not attached, character events might be sent (e.g. on 823 // Windows). In this case, we just skip these. 824 return; 825 } 826 // Renderer may send a key event back to us if the key event wasn't handled, 827 // and the window may be invisible by that time. 828 if (!window_->IsVisible()) 829 return; 830 GetWidget()->GetInputMethod()->DispatchKeyEvent(*event); 831 event->SetHandled(); 832} 833 834void NativeWidgetAura::OnMouseEvent(ui::MouseEvent* event) { 835 DCHECK(window_); 836 DCHECK(window_->IsVisible()); 837 if (event->type() == ui::ET_MOUSEWHEEL) { 838 delegate_->OnMouseEvent(event); 839 if (event->handled()) 840 return; 841 } 842 843 if (tooltip_manager_.get()) 844 tooltip_manager_->UpdateTooltip(); 845 delegate_->OnMouseEvent(event); 846} 847 848void NativeWidgetAura::OnScrollEvent(ui::ScrollEvent* event) { 849 delegate_->OnScrollEvent(event); 850} 851 852void NativeWidgetAura::OnTouchEvent(ui::TouchEvent* event) { 853 DCHECK(window_); 854 DCHECK(window_->IsVisible()); 855 delegate_->OnTouchEvent(event); 856} 857 858void NativeWidgetAura::OnGestureEvent(ui::GestureEvent* event) { 859 DCHECK(window_); 860 DCHECK(window_->IsVisible()); 861 delegate_->OnGestureEvent(event); 862} 863 864//////////////////////////////////////////////////////////////////////////////// 865// NativeWidgetAura, aura::client::ActivationDelegate implementation: 866 867bool NativeWidgetAura::ShouldActivate() const { 868 return can_activate_ && delegate_->CanActivate(); 869} 870 871//////////////////////////////////////////////////////////////////////////////// 872// NativeWidgetAura, aura::client::ActivationChangeObserver implementation: 873 874void NativeWidgetAura::OnWindowActivated(aura::Window* gained_active, 875 aura::Window* lost_active) { 876 DCHECK(window_ == gained_active || window_ == lost_active); 877 if (GetWidget()->GetFocusManager()) { 878 if (window_ == gained_active) 879 GetWidget()->GetFocusManager()->RestoreFocusedView(); 880 else if (window_ == lost_active) 881 GetWidget()->GetFocusManager()->StoreFocusedView(true); 882 } 883 delegate_->OnNativeWidgetActivationChanged(window_ == gained_active); 884 if (IsVisible() && GetWidget()->non_client_view()) 885 GetWidget()->non_client_view()->SchedulePaint(); 886} 887 888//////////////////////////////////////////////////////////////////////////////// 889// NativeWidgetAura, aura::client::FocusChangeObserver: 890 891void NativeWidgetAura::OnWindowFocused(aura::Window* gained_focus, 892 aura::Window* lost_focus) { 893 if (window_ == gained_focus) { 894 // In aura, it is possible for child native widgets to take input and focus, 895 // this differs from the behavior on windows. 896 if (GetWidget()->GetInputMethod()) // Null in tests. 897 GetWidget()->GetInputMethod()->OnFocus(); 898 delegate_->OnNativeFocus(lost_focus); 899 } else if (window_ == lost_focus) { 900 // GetInputMethod() recreates the input method if it's previously been 901 // destroyed. If we get called during destruction, the input method will be 902 // gone, and creating a new one and telling it that we lost the focus will 903 // trigger a DCHECK (the new input method doesn't think that we have the 904 // focus and doesn't expect a blur). OnBlur() shouldn't be called during 905 // destruction unless WIDGET_OWNS_NATIVE_WIDGET is set (which is just the 906 // case in tests). 907 if (!destroying_) { 908 if (GetWidget()->GetInputMethod()) 909 GetWidget()->GetInputMethod()->OnBlur(); 910 } else { 911 DCHECK_EQ(ownership_, Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET); 912 } 913 914 aura::client::FocusClient* client = aura::client::GetFocusClient(window_); 915 if (client) // NULL during destruction of aura::Window. 916 delegate_->OnNativeBlur(client->GetFocusedWindow()); 917 } 918} 919 920//////////////////////////////////////////////////////////////////////////////// 921// NativeWidgetAura, aura::WindowDragDropDelegate implementation: 922 923void NativeWidgetAura::OnDragEntered(const ui::DropTargetEvent& event) { 924 DCHECK(drop_helper_.get() != NULL); 925 last_drop_operation_ = drop_helper_->OnDragOver(event.data(), 926 event.location(), event.source_operations()); 927} 928 929int NativeWidgetAura::OnDragUpdated(const ui::DropTargetEvent& event) { 930 DCHECK(drop_helper_.get() != NULL); 931 last_drop_operation_ = drop_helper_->OnDragOver(event.data(), 932 event.location(), event.source_operations()); 933 return last_drop_operation_; 934} 935 936void NativeWidgetAura::OnDragExited() { 937 DCHECK(drop_helper_.get() != NULL); 938 drop_helper_->OnDragExit(); 939} 940 941int NativeWidgetAura::OnPerformDrop(const ui::DropTargetEvent& event) { 942 DCHECK(drop_helper_.get() != NULL); 943 return drop_helper_->OnDrop(event.data(), event.location(), 944 last_drop_operation_); 945} 946 947//////////////////////////////////////////////////////////////////////////////// 948// NativeWidgetAura, NativeWidget implementation: 949 950ui::EventHandler* NativeWidgetAura::GetEventHandler() { 951 return this; 952} 953 954//////////////////////////////////////////////////////////////////////////////// 955// NativeWidgetAura, protected: 956 957NativeWidgetAura::~NativeWidgetAura() { 958 destroying_ = true; 959 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) 960 delete delegate_; 961 else 962 CloseNow(); 963} 964 965//////////////////////////////////////////////////////////////////////////////// 966// NativeWidgetAura, private: 967 968void NativeWidgetAura::SetInitialFocus() { 969 // The window does not get keyboard messages unless we focus it. 970 if (!GetWidget()->SetInitialFocus()) 971 window_->Focus(); 972} 973 974//////////////////////////////////////////////////////////////////////////////// 975// Widget, public: 976 977// static 978void Widget::NotifyLocaleChanged() { 979 // Deliberately not implemented. 980} 981 982namespace { 983void CloseWindow(aura::Window* window) { 984 if (window) { 985 Widget* widget = Widget::GetWidgetForNativeView(window); 986 if (widget && widget->is_secondary_widget()) 987 // To avoid the delay in shutdown caused by using Close which may wait 988 // for animations, use CloseNow. Because this is only used on secondary 989 // widgets it seems relatively safe to skip the extra processing of 990 // Close. 991 widget->CloseNow(); 992 } 993} 994#if defined(OS_WIN) 995BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) { 996 aura::Window* root_window = 997 DesktopRootWindowHostWin::GetContentWindowForHWND(hwnd); 998 CloseWindow(root_window); 999 return TRUE; 1000} 1001#endif 1002} // namespace 1003 1004// static 1005void Widget::CloseAllSecondaryWidgets() { 1006#if defined(OS_WIN) 1007 EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0); 1008#endif 1009 1010#if defined(USE_X11) && !defined(OS_CHROMEOS) 1011 std::vector<aura::Window*> open_windows = 1012 DesktopRootWindowHostX11::GetAllOpenWindows(); 1013 std::for_each(open_windows.begin(), open_windows.end(), CloseWindow); 1014 DesktopRootWindowHostX11::CleanUpWindowList(); 1015#endif 1016} 1017 1018bool Widget::ConvertRect(const Widget* source, 1019 const Widget* target, 1020 gfx::Rect* rect) { 1021 return false; 1022} 1023 1024namespace internal { 1025 1026//////////////////////////////////////////////////////////////////////////////// 1027// internal::NativeWidgetPrivate, public: 1028 1029// static 1030NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget( 1031 internal::NativeWidgetDelegate* delegate) { 1032 return new NativeWidgetAura(delegate); 1033} 1034 1035// static 1036NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView( 1037 gfx::NativeView native_view) { 1038 // Cast must match type supplied to RegisterNativeWidgetForWindow(). 1039 return reinterpret_cast<NativeWidgetPrivate*>(native_view->user_data()); 1040} 1041 1042// static 1043NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow( 1044 gfx::NativeWindow native_window) { 1045 // Cast must match type supplied to RegisterNativeWidgetForWindow(). 1046 return reinterpret_cast<NativeWidgetPrivate*>(native_window->user_data()); 1047} 1048 1049// static 1050NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget( 1051 gfx::NativeView native_view) { 1052 aura::Window* window = native_view; 1053 NativeWidgetPrivate* top_level_native_widget = NULL; 1054 while (window) { 1055 NativeWidgetPrivate* native_widget = GetNativeWidgetForNativeView(window); 1056 if (native_widget) 1057 top_level_native_widget = native_widget; 1058 window = window->parent(); 1059 } 1060 return top_level_native_widget; 1061} 1062 1063// static 1064void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view, 1065 Widget::Widgets* children) { 1066 { 1067 // Code expects widget for |native_view| to be added to |children|. 1068 NativeWidgetPrivate* native_widget = static_cast<NativeWidgetPrivate*>( 1069 GetNativeWidgetForNativeView(native_view)); 1070 if (native_widget && native_widget->GetWidget()) 1071 children->insert(native_widget->GetWidget()); 1072 } 1073 1074 const aura::Window::Windows& child_windows = native_view->children(); 1075 for (aura::Window::Windows::const_iterator i = child_windows.begin(); 1076 i != child_windows.end(); ++i) { 1077 GetAllChildWidgets((*i), children); 1078 } 1079} 1080 1081// static 1082void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view, 1083 gfx::NativeView new_parent) { 1084 DCHECK(native_view != new_parent); 1085 1086 gfx::NativeView previous_parent = native_view->parent(); 1087 if (previous_parent == new_parent) 1088 return; 1089 1090 Widget::Widgets widgets; 1091 GetAllChildWidgets(native_view, &widgets); 1092 1093 // First notify all the widgets that they are being disassociated 1094 // from their previous parent. 1095 for (Widget::Widgets::iterator it = widgets.begin(); 1096 it != widgets.end(); ++it) { 1097 (*it)->NotifyNativeViewHierarchyWillChange(); 1098 } 1099 1100 if (new_parent) { 1101 new_parent->AddChild(native_view); 1102 } else { 1103 // The following looks weird, but it's the equivalent of what aura has 1104 // always done. (The previous behaviour of aura::Window::SetParent() used 1105 // NULL as a special value that meant ask the StackingClient where things 1106 // should go.) 1107 // 1108 // This probably isn't strictly correct, but its an invariant that a Window 1109 // in use will be attached to a RootWindow, so we can't just call 1110 // RemoveChild here. The only possible thing that could assign a RootWindow 1111 // in this case is the stacking client of the current RootWindow. This 1112 // matches our previous behaviour; the global stacking client would almost 1113 // always reattach the window to the same RootWindow. 1114 aura::RootWindow* root_window = native_view->GetRootWindow(); 1115 native_view->SetDefaultParentByRootWindow( 1116 root_window, root_window->GetBoundsInScreen()); 1117 } 1118 1119 // And now, notify them that they have a brand new parent. 1120 for (Widget::Widgets::iterator it = widgets.begin(); 1121 it != widgets.end(); ++it) { 1122 (*it)->NotifyNativeViewHierarchyChanged(); 1123 } 1124} 1125 1126// static 1127bool NativeWidgetPrivate::IsMouseButtonDown() { 1128 return aura::Env::GetInstance()->is_mouse_button_down(); 1129} 1130 1131// static 1132bool NativeWidgetPrivate::IsTouchDown() { 1133 return aura::Env::GetInstance()->is_touch_down(); 1134} 1135 1136} // namespace internal 1137} // namespace views 1138