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