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