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