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