OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/apps/chrome_native_app_window_views.h" | 5 #include "chrome/browser/ui/views/apps/chrome_native_app_window_views.h" |
6 | 6 |
7 #include "apps/ui/views/app_window_frame_view.h" | 7 #include "apps/ui/views/app_window_frame_view.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "chrome/app/chrome_command_ids.h" | 9 #include "chrome/app/chrome_command_ids.h" |
10 #include "chrome/browser/app_mode/app_mode_utils.h" | 10 #include "chrome/browser/app_mode/app_mode_utils.h" |
11 #include "chrome/browser/favicon/favicon_tab_helper.h" | 11 #include "chrome/browser/favicon/favicon_tab_helper.h" |
12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" |
| 14 #include "chrome/browser/ui/exclusive_access/mouse_lock_controller.h" |
13 #include "chrome/browser/ui/host_desktop.h" | 15 #include "chrome/browser/ui/host_desktop.h" |
14 #include "chrome/browser/ui/views/apps/desktop_keyboard_capture.h" | 16 #include "chrome/browser/ui/views/apps/desktop_keyboard_capture.h" |
15 #include "chrome/browser/ui/views/apps/shaped_app_window_targeter.h" | 17 #include "chrome/browser/ui/views/apps/shaped_app_window_targeter.h" |
| 18 #include "chrome/browser/ui/views/exclusive_access_bubble_views.h" |
16 #include "chrome/browser/ui/views/extensions/extension_keybinding_registry_views
.h" | 19 #include "chrome/browser/ui/views/extensions/extension_keybinding_registry_views
.h" |
17 #include "chrome/browser/ui/views/frame/taskbar_decorator.h" | 20 #include "chrome/browser/ui/views/frame/taskbar_decorator.h" |
18 #include "chrome/browser/web_applications/web_app.h" | 21 #include "chrome/browser/web_applications/web_app.h" |
19 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" |
20 #include "components/ui/zoom/page_zoom.h" | 23 #include "components/ui/zoom/page_zoom.h" |
21 #include "components/ui/zoom/zoom_controller.h" | 24 #include "components/ui/zoom/zoom_controller.h" |
| 25 #include "content/public/browser/native_web_keyboard_event.h" |
22 #include "extensions/common/extension.h" | 26 #include "extensions/common/extension.h" |
23 #include "ui/aura/window.h" | 27 #include "ui/aura/window.h" |
24 #include "ui/base/hit_test.h" | 28 #include "ui/base/hit_test.h" |
25 #include "ui/base/models/simple_menu_model.h" | 29 #include "ui/base/models/simple_menu_model.h" |
26 #include "ui/gfx/image/image_skia.h" | 30 #include "ui/gfx/image/image_skia.h" |
27 #include "ui/views/controls/menu/menu_runner.h" | 31 #include "ui/views/controls/menu/menu_runner.h" |
28 #include "ui/views/controls/webview/webview.h" | 32 #include "ui/views/controls/webview/webview.h" |
29 #include "ui/views/widget/widget.h" | 33 #include "ui/views/widget/widget.h" |
30 #include "ui/wm/core/easy_resize_window_targeter.h" | 34 #include "ui/wm/core/easy_resize_window_targeter.h" |
31 #include "ui/wm/core/shadow_types.h" | 35 #include "ui/wm/core/shadow_types.h" |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 DISALLOW_COPY_AND_ASSIGN(NativeAppWindowStateDelegate); | 196 DISALLOW_COPY_AND_ASSIGN(NativeAppWindowStateDelegate); |
193 }; | 197 }; |
194 #endif // USE_ASH | 198 #endif // USE_ASH |
195 | 199 |
196 } // namespace | 200 } // namespace |
197 | 201 |
198 ChromeNativeAppWindowViews::ChromeNativeAppWindowViews() | 202 ChromeNativeAppWindowViews::ChromeNativeAppWindowViews() |
199 : is_fullscreen_(false), | 203 : is_fullscreen_(false), |
200 has_frame_color_(false), | 204 has_frame_color_(false), |
201 active_frame_color_(SK_ColorBLACK), | 205 active_frame_color_(SK_ColorBLACK), |
202 inactive_frame_color_(SK_ColorBLACK) { | 206 inactive_frame_color_(SK_ColorBLACK), |
| 207 key_capture_requested_(false) { |
| 208 exclusive_access_manager_.reset(new ExclusiveAccessManager(this)); |
203 } | 209 } |
204 | 210 |
205 ChromeNativeAppWindowViews::~ChromeNativeAppWindowViews() {} | 211 ChromeNativeAppWindowViews::~ChromeNativeAppWindowViews() {} |
206 | 212 |
207 void ChromeNativeAppWindowViews::OnBeforeWidgetInit( | 213 void ChromeNativeAppWindowViews::OnBeforeWidgetInit( |
208 views::Widget::InitParams* init_params, | 214 views::Widget::InitParams* init_params, |
209 views::Widget* widget) {} | 215 views::Widget* widget) {} |
210 | 216 |
211 void ChromeNativeAppWindowViews::InitializeDefaultWindow( | 217 void ChromeNativeAppWindowViews::InitializeDefaultWindow( |
212 const AppWindow::CreateParams& create_params) { | 218 const AppWindow::CreateParams& create_params) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 #endif | 345 #endif |
340 widget()->Init(params); | 346 widget()->Init(params); |
341 widget()->set_focus_on_creation(create_params.focused); | 347 widget()->set_focus_on_creation(create_params.focused); |
342 } | 348 } |
343 | 349 |
344 views::NonClientFrameView* | 350 views::NonClientFrameView* |
345 ChromeNativeAppWindowViews::CreateStandardDesktopAppFrame() { | 351 ChromeNativeAppWindowViews::CreateStandardDesktopAppFrame() { |
346 return views::WidgetDelegateView::CreateNonClientFrameView(widget()); | 352 return views::WidgetDelegateView::CreateNonClientFrameView(widget()); |
347 } | 353 } |
348 | 354 |
| 355 apps::AppWindowFrameView* |
| 356 ChromeNativeAppWindowViews::CreateNonStandardAppFrame() { |
| 357 apps::AppWindowFrameView* frame = |
| 358 new apps::AppWindowFrameView(widget(), this, has_frame_color_, |
| 359 active_frame_color_, inactive_frame_color_); |
| 360 frame->Init(); |
| 361 #if defined(USE_ASH) |
| 362 // For Aura windows on the Ash desktop the sizes are different and the user |
| 363 // can resize the window from slightly outside the bounds as well. |
| 364 if (chrome::IsNativeWindowInAsh(widget()->GetNativeWindow())) { |
| 365 frame->SetResizeSizes(ash::kResizeInsideBoundsSize, |
| 366 ash::kResizeOutsideBoundsSize, |
| 367 ash::kResizeAreaCornerSize); |
| 368 } |
| 369 #endif |
| 370 |
| 371 #if !defined(OS_CHROMEOS) |
| 372 // For non-Ash windows, install an easy resize window targeter, which ensures |
| 373 // that the root window (not the app) receives mouse events on the edges. |
| 374 if (chrome::GetHostDesktopTypeForNativeWindow(widget()->GetNativeWindow()) != |
| 375 chrome::HOST_DESKTOP_TYPE_ASH) { |
| 376 aura::Window* window = widget()->GetNativeWindow(); |
| 377 int resize_inside = frame->resize_inside_bounds_size(); |
| 378 gfx::Insets inset(resize_inside, resize_inside, resize_inside, |
| 379 resize_inside); |
| 380 // Add the EasyResizeWindowTargeter on the window, not its root window. The |
| 381 // root window does not have a delegate, which is needed to handle the event |
| 382 // in Linux. |
| 383 window->SetEventTargeter(scoped_ptr<ui::EventTargeter>( |
| 384 new wm::EasyResizeWindowTargeter(window, inset, inset))); |
| 385 } |
| 386 #endif |
| 387 |
| 388 return frame; |
| 389 } |
| 390 |
| 391 void ChromeNativeAppWindowViews::Activate() { |
| 392 NativeAppWindowViews::Activate(); |
| 393 exclusive_access_manager_->OnTabDetachedFromView(GetActiveWebContents()); |
| 394 } |
| 395 |
| 396 void ChromeNativeAppWindowViews::Deactivate() { |
| 397 NativeAppWindowViews::Deactivate(); |
| 398 exclusive_access_manager_->OnTabDeactivated(GetActiveWebContents()); |
| 399 } |
| 400 |
| 401 bool ChromeNativeAppWindowViews::PreHandleKeyboardEvent( |
| 402 content::WebContents* source, |
| 403 const content::NativeWebKeyboardEvent& event, |
| 404 bool* is_keyboard_shortcut) { |
| 405 if (event.windowsKeyCode == ui::VKEY_ESCAPE && |
| 406 exclusive_access_manager_->HandleUserPressedEscape()) { |
| 407 return true; |
| 408 } |
| 409 return NativeAppWindowViews::PreHandleKeyboardEvent(source, event, |
| 410 is_keyboard_shortcut); |
| 411 } |
| 412 |
349 // ui::BaseWindow implementation. | 413 // ui::BaseWindow implementation. |
350 | |
351 gfx::Rect ChromeNativeAppWindowViews::GetRestoredBounds() const { | 414 gfx::Rect ChromeNativeAppWindowViews::GetRestoredBounds() const { |
352 #if defined(USE_ASH) | 415 #if defined(USE_ASH) |
353 gfx::Rect* bounds = widget()->GetNativeWindow()->GetProperty( | 416 gfx::Rect* bounds = widget()->GetNativeWindow()->GetProperty( |
354 ash::kRestoreBoundsOverrideKey); | 417 ash::kRestoreBoundsOverrideKey); |
355 if (bounds && !bounds->IsEmpty()) | 418 if (bounds && !bounds->IsEmpty()) |
356 return *bounds; | 419 return *bounds; |
357 #endif | 420 #endif |
358 return widget()->GetRestoredBounds(); | 421 return widget()->GetRestoredBounds(); |
359 } | 422 } |
360 | 423 |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 | 702 |
640 SkColor ChromeNativeAppWindowViews::ActiveFrameColor() const { | 703 SkColor ChromeNativeAppWindowViews::ActiveFrameColor() const { |
641 return active_frame_color_; | 704 return active_frame_color_; |
642 } | 705 } |
643 | 706 |
644 SkColor ChromeNativeAppWindowViews::InactiveFrameColor() const { | 707 SkColor ChromeNativeAppWindowViews::InactiveFrameColor() const { |
645 return inactive_frame_color_; | 708 return inactive_frame_color_; |
646 } | 709 } |
647 | 710 |
648 void ChromeNativeAppWindowViews::SetInterceptAllKeys(bool want_all_keys) { | 711 void ChromeNativeAppWindowViews::SetInterceptAllKeys(bool want_all_keys) { |
649 if (want_all_keys && (desktop_keyboard_capture_.get() == NULL)) { | 712 // Noop if there is no state change. |
650 desktop_keyboard_capture_.reset(new DesktopKeyboardCapture(widget())); | 713 if (want_all_keys == key_capture_requested_) { |
651 } else if (!want_all_keys) { | 714 return; |
652 desktop_keyboard_capture_.reset(NULL); | 715 } |
| 716 |
| 717 key_capture_requested_ = want_all_keys; |
| 718 if (want_all_keys) { |
| 719 exclusive_access_manager_->mouse_lock_controller()->RequestToLockMouse( |
| 720 GetActiveWebContents(), true, true); |
| 721 } else { |
| 722 desktop_keyboard_capture_.reset(nullptr); |
| 723 exclusive_access_manager_->mouse_lock_controller()->LostMouseLock(); |
653 } | 724 } |
654 } | 725 } |
655 | 726 |
656 // NativeAppWindowViews implementation. | 727 // NativeAppWindowViews implementation. |
657 | 728 |
658 void ChromeNativeAppWindowViews::InitializeWindow( | 729 void ChromeNativeAppWindowViews::InitializeWindow( |
659 AppWindow* app_window, | 730 AppWindow* app_window, |
660 const AppWindow::CreateParams& create_params) { | 731 const AppWindow::CreateParams& create_params) { |
661 DCHECK(widget()); | 732 DCHECK(widget()); |
662 has_frame_color_ = create_params.has_frame_color; | 733 has_frame_color_ = create_params.has_frame_color; |
663 active_frame_color_ = create_params.active_frame_color; | 734 active_frame_color_ = create_params.active_frame_color; |
664 inactive_frame_color_ = create_params.inactive_frame_color; | 735 inactive_frame_color_ = create_params.inactive_frame_color; |
665 if (create_params.window_type == AppWindow::WINDOW_TYPE_PANEL || | 736 if (create_params.window_type == AppWindow::WINDOW_TYPE_PANEL || |
666 create_params.window_type == AppWindow::WINDOW_TYPE_V1_PANEL) { | 737 create_params.window_type == AppWindow::WINDOW_TYPE_V1_PANEL) { |
667 InitializePanelWindow(create_params); | 738 InitializePanelWindow(create_params); |
668 } else { | 739 } else { |
669 InitializeDefaultWindow(create_params); | 740 InitializeDefaultWindow(create_params); |
670 } | 741 } |
671 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryViews( | 742 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryViews( |
672 Profile::FromBrowserContext(app_window->browser_context()), | 743 Profile::FromBrowserContext(app_window->browser_context()), |
673 widget()->GetFocusManager(), | 744 widget()->GetFocusManager(), |
674 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, | 745 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, |
675 NULL)); | 746 NULL)); |
676 } | 747 } |
677 | 748 |
678 apps::AppWindowFrameView* | 749 // ExclusiveAccessContext implementation |
679 ChromeNativeAppWindowViews::CreateNonStandardAppFrame() { | 750 Profile* ChromeNativeAppWindowViews::GetProfile() { |
680 apps::AppWindowFrameView* frame = | 751 return Profile::FromBrowserContext(app_window()->browser_context()); |
681 new apps::AppWindowFrameView(widget(), | 752 } |
682 this, | 753 |
683 has_frame_color_, | 754 bool ChromeNativeAppWindowViews::IsFullscreen() const { |
684 active_frame_color_, | 755 return NativeAppWindowViews::IsFullscreen(); |
685 inactive_frame_color_); | 756 } |
686 frame->Init(); | 757 |
687 #if defined(USE_ASH) | 758 bool ChromeNativeAppWindowViews::IsFullscreenWithToolbar() { |
688 // For Aura windows on the Ash desktop the sizes are different and the user | 759 return false; |
689 // can resize the window from slightly outside the bounds as well. | 760 } |
690 if (chrome::IsNativeWindowInAsh(widget()->GetNativeWindow())) { | 761 |
691 frame->SetResizeSizes(ash::kResizeInsideBoundsSize, | 762 bool ChromeNativeAppWindowViews::SupportsFullscreenWithToolbar() { |
692 ash::kResizeOutsideBoundsSize, | 763 return false; |
693 ash::kResizeAreaCornerSize); | 764 } |
| 765 |
| 766 void ChromeNativeAppWindowViews::EnterFullscreen( |
| 767 const GURL& url, |
| 768 ExclusiveAccessBubbleType bubble_type, |
| 769 bool with_toolbar) { |
| 770 app_window()->Fullscreen(); |
| 771 UpdateExclusiveAccessExitBubbleContent(url, bubble_type); |
| 772 } |
| 773 |
| 774 void ChromeNativeAppWindowViews::ExitFullscreen() { |
| 775 app_window()->Restore(); |
| 776 UpdateExclusiveAccessExitBubbleContent(GURL(), |
| 777 EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE); |
| 778 } |
| 779 |
| 780 void ChromeNativeAppWindowViews::UpdateExclusiveAccessExitBubbleContent( |
| 781 GURL url, |
| 782 ExclusiveAccessBubbleType bubble_type) { |
| 783 if (bubble_type == EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE || url.is_empty()) { |
| 784 exclusive_access_bubble_views_.reset(); |
| 785 } else if (exclusive_access_bubble_views_.get()) { |
| 786 exclusive_access_bubble_views_->UpdateContent(url, bubble_type); |
| 787 } else { |
| 788 exclusive_access_bubble_views_.reset( |
| 789 new ExclusiveAccessBubbleViews(this, url, bubble_type)); |
694 } | 790 } |
695 #endif | 791 } |
696 | 792 |
697 #if !defined(OS_CHROMEOS) | 793 content::WebContents* ChromeNativeAppWindowViews::GetActiveWebContents() { |
698 // For non-Ash windows, install an easy resize window targeter, which ensures | 794 return web_view()->GetWebContents(); |
699 // that the root window (not the app) receives mouse events on the edges. | 795 } |
700 if (chrome::GetHostDesktopTypeForNativeWindow(widget()->GetNativeWindow()) != | 796 |
701 chrome::HOST_DESKTOP_TYPE_ASH) { | 797 void ChromeNativeAppWindowViews::UpdateFullscreenWithToolbar( |
702 aura::Window* window = widget()->GetNativeWindow(); | 798 bool with_toolbar) { |
703 int resize_inside = frame->resize_inside_bounds_size(); | 799 // This is currently a Mac only feature. |
704 gfx::Insets inset( | 800 NOTIMPLEMENTED(); |
705 resize_inside, resize_inside, resize_inside, resize_inside); | 801 } |
706 // Add the EasyResizeWindowTargeter on the window, not its root window. The | 802 |
707 // root window does not have a delegate, which is needed to handle the event | 803 void ChromeNativeAppWindowViews::SetMetroSnapMode(bool enable) { |
708 // in Linux. | 804 // Not implemented for chrome app. |
709 window->SetEventTargeter(scoped_ptr<ui::EventTargeter>( | 805 NOTIMPLEMENTED(); |
710 new wm::EasyResizeWindowTargeter(window, inset, inset))); | 806 } |
| 807 |
| 808 bool ChromeNativeAppWindowViews::IsInMetroSnapMode() { |
| 809 return false; |
| 810 } |
| 811 |
| 812 void ChromeNativeAppWindowViews::UpdateDownloadShelf(bool unhide) { |
| 813 // Apps don't have a download shelf and so nothing to do here. |
| 814 } |
| 815 |
| 816 bool ChromeNativeAppWindowViews::UseCallbackForMouseLock() { |
| 817 return true; |
| 818 } |
| 819 |
| 820 bool ChromeNativeAppWindowViews::MouseLockCallback(bool acquired) { |
| 821 if (key_capture_requested_ && acquired) { |
| 822 desktop_keyboard_capture_.reset(new DesktopKeyboardCapture(widget())); |
| 823 } else { |
| 824 desktop_keyboard_capture_.reset(nullptr); |
711 } | 825 } |
712 #endif | |
713 | 826 |
714 return frame; | 827 return key_capture_requested_; |
715 } | 828 } |
| 829 |
| 830 // ExclusiveAccessBubbleViewsContext implementation |
| 831 ExclusiveAccessManager* |
| 832 ChromeNativeAppWindowViews::GetExclusiveAccessManager() { |
| 833 return exclusive_access_manager_.get(); |
| 834 } |
| 835 |
| 836 views::Widget* ChromeNativeAppWindowViews::GetWidget() { |
| 837 return widget(); |
| 838 } |
| 839 |
| 840 bool ChromeNativeAppWindowViews::IsImmersiveModeEnabled() { |
| 841 return false; |
| 842 } |
| 843 |
| 844 gfx::Rect ChromeNativeAppWindowViews::GetTopContainerBoundsInScreen() { |
| 845 return widget()->GetWindowBoundsInScreen(); |
| 846 } |
OLD | NEW |