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