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