diff options
author | Torne (Richard Coles) <torne@google.com> | 2014-05-14 12:12:37 +0100 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2014-05-14 12:12:37 +0100 |
commit | 010d83a9304c5a91596085d917d248abff47903a (patch) | |
tree | 41ef1a01862f352f9653c7a9cfa817abefe2cce2 /ash | |
parent | 08c107de54178bb0990a09adec724924e8bc9486 (diff) | |
download | chromium_org-010d83a9304c5a91596085d917d248abff47903a.tar.gz |
Merge from Chromium at DEPS revision 269336
This commit was generated by merge_to_master.py.
Change-Id: I8b9c77f10eccd2a8b4c7ce373ffda18568af54ff
Diffstat (limited to 'ash')
113 files changed, 1385 insertions, 3715 deletions
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 93277eafc0..dbdc9e149e 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "ash/accelerators/accelerator_controller.h" + #include "ash/accelerators/accelerator_table.h" #include "ash/accessibility_delegate.h" #include "ash/ash_switches.h" @@ -18,6 +19,7 @@ #include "ash/test/display_manager_test_api.h" #include "ash/test/test_screenshot_delegate.h" #include "ash/test/test_shell_delegate.h" +#include "ash/test/test_volume_control_delegate.h" #include "ash/volume_control_delegate.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" @@ -69,55 +71,6 @@ class ReleaseAccelerator : public ui::Accelerator { } }; -class DummyVolumeControlDelegate : public VolumeControlDelegate { - public: - explicit DummyVolumeControlDelegate(bool consume) - : consume_(consume), - handle_volume_mute_count_(0), - handle_volume_down_count_(0), - handle_volume_up_count_(0) { - } - virtual ~DummyVolumeControlDelegate() {} - - virtual bool HandleVolumeMute(const ui::Accelerator& accelerator) OVERRIDE { - ++handle_volume_mute_count_; - last_accelerator_ = accelerator; - return consume_; - } - virtual bool HandleVolumeDown(const ui::Accelerator& accelerator) OVERRIDE { - ++handle_volume_down_count_; - last_accelerator_ = accelerator; - return consume_; - } - virtual bool HandleVolumeUp(const ui::Accelerator& accelerator) OVERRIDE { - ++handle_volume_up_count_; - last_accelerator_ = accelerator; - return consume_; - } - - int handle_volume_mute_count() const { - return handle_volume_mute_count_; - } - int handle_volume_down_count() const { - return handle_volume_down_count_; - } - int handle_volume_up_count() const { - return handle_volume_up_count_; - } - const ui::Accelerator& last_accelerator() const { - return last_accelerator_; - } - - private: - const bool consume_; - int handle_volume_mute_count_; - int handle_volume_down_count_; - int handle_volume_up_count_; - ui::Accelerator last_accelerator_; - - DISALLOW_COPY_AND_ASSIGN(DummyVolumeControlDelegate); -}; - class DummyBrightnessControlDelegate : public BrightnessControlDelegate { public: explicit DummyBrightnessControlDelegate(bool consume) @@ -714,8 +667,8 @@ TEST_F(AcceleratorControllerTest, GlobalAccelerators) { const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE); const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE); { - DummyVolumeControlDelegate* delegate = - new DummyVolumeControlDelegate(false); + TestVolumeControlDelegate* delegate = + new TestVolumeControlDelegate(false); ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( scoped_ptr<VolumeControlDelegate>(delegate).Pass()); EXPECT_EQ(0, delegate->handle_volume_mute_count()); @@ -732,7 +685,7 @@ TEST_F(AcceleratorControllerTest, GlobalAccelerators) { EXPECT_EQ(volume_up, delegate->last_accelerator()); } { - DummyVolumeControlDelegate* delegate = new DummyVolumeControlDelegate(true); + TestVolumeControlDelegate* delegate = new TestVolumeControlDelegate(true); ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( scoped_ptr<VolumeControlDelegate>(delegate).Pass()); EXPECT_EQ(0, delegate->handle_volume_mute_count()); @@ -1190,8 +1143,8 @@ TEST_F(AcceleratorControllerTest, DisallowedAtModalWindow) { EXPECT_TRUE(ProcessWithContext(volume_mute)); EXPECT_TRUE(ProcessWithContext(volume_down)); EXPECT_TRUE(ProcessWithContext(volume_up)); - DummyVolumeControlDelegate* delegate = - new DummyVolumeControlDelegate(false); + TestVolumeControlDelegate* delegate = + new TestVolumeControlDelegate(false); ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( scoped_ptr<VolumeControlDelegate>(delegate).Pass()); EXPECT_EQ(0, delegate->handle_volume_mute_count()); @@ -1208,7 +1161,7 @@ TEST_F(AcceleratorControllerTest, DisallowedAtModalWindow) { EXPECT_EQ(volume_up, delegate->last_accelerator()); } { - DummyVolumeControlDelegate* delegate = new DummyVolumeControlDelegate(true); + TestVolumeControlDelegate* delegate = new TestVolumeControlDelegate(true); ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( scoped_ptr<VolumeControlDelegate>(delegate).Pass()); EXPECT_EQ(0, delegate->handle_volume_mute_count()); diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc index 10b568c45d..51b63240a5 100644 --- a/ash/accelerators/accelerator_table.cc +++ b/ash/accelerators/accelerator_table.cc @@ -329,6 +329,10 @@ const AcceleratorAction kActionsAllowedAtModalWindow[] = { POWER_RELEASED, PREVIOUS_IME, PRINT_UI_HIERARCHIES, + ROTATE_SCREEN, + SCALE_UI_UP, + SCALE_UI_DOWN, + SCALE_UI_RESET, SHOW_KEYBOARD_OVERLAY, SWITCH_IME, TAKE_PARTIAL_SCREENSHOT, diff --git a/ash/ash.gyp b/ash/ash.gyp index 8c9cfdfbdd..1b8212a6d5 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -161,23 +161,14 @@ 'first_run/first_run_helper_impl.h', 'focus_cycler.cc', 'focus_cycler.h', - 'frame/caption_buttons/alternate_frame_size_button.cc', - 'frame/caption_buttons/alternate_frame_size_button.h', - 'frame/caption_buttons/alternate_frame_size_button_delegate.h', - 'frame/caption_buttons/bubble_contents_button_row.cc', - 'frame/caption_buttons/bubble_contents_button_row.h', 'frame/caption_buttons/caption_button_types.h', 'frame/caption_buttons/frame_caption_button.cc', 'frame/caption_buttons/frame_caption_button.h', 'frame/caption_buttons/frame_caption_button_container_view.cc', 'frame/caption_buttons/frame_caption_button_container_view.h', - 'frame/caption_buttons/frame_maximize_button.cc', - 'frame/caption_buttons/frame_maximize_button.h', - 'frame/caption_buttons/frame_maximize_button_observer.h', - 'frame/caption_buttons/maximize_bubble_controller.cc', - 'frame/caption_buttons/maximize_bubble_controller.h', - 'frame/caption_buttons/maximize_bubble_controller_bubble.cc', - 'frame/caption_buttons/maximize_bubble_controller_bubble.h', + 'frame/caption_buttons/frame_size_button.cc', + 'frame/caption_buttons/frame_size_button.h', + 'frame/caption_buttons/frame_size_button_delegate.h', 'frame/custom_frame_view_ash.cc', 'frame/custom_frame_view_ash.h', 'frame/frame_border_hit_test_controller.cc', @@ -325,21 +316,21 @@ 'system/chromeos/audio/tray_audio_chromeos.h', 'system/chromeos/audio/tray_audio_delegate_chromeos.cc', 'system/chromeos/audio/tray_audio_delegate_chromeos.h', - 'system/chromeos/enterprise/enterprise_domain_observer.h', 'system/chromeos/bluetooth/bluetooth_notification_controller.cc', 'system/chromeos/bluetooth/bluetooth_notification_controller.h', 'system/chromeos/brightness/brightness_controller_chromeos.cc', 'system/chromeos/brightness/brightness_controller_chromeos.h', 'system/chromeos/brightness/tray_brightness.cc', 'system/chromeos/brightness/tray_brightness.h', - 'system/chromeos/enterprise/tray_enterprise.h', + 'system/chromeos/enterprise/enterprise_domain_observer.h', 'system/chromeos/enterprise/tray_enterprise.cc', + 'system/chromeos/enterprise/tray_enterprise.h', 'system/chromeos/keyboard_brightness_controller.cc', 'system/chromeos/keyboard_brightness_controller.h', - 'system/chromeos/label_tray_view.h', 'system/chromeos/label_tray_view.cc', - 'system/chromeos/managed/tray_locally_managed_user.h', + 'system/chromeos/label_tray_view.h', 'system/chromeos/managed/tray_locally_managed_user.cc', + 'system/chromeos/managed/tray_locally_managed_user.h', 'system/chromeos/network/network_connect.cc', 'system/chromeos/network/network_connect.h', 'system/chromeos/network/network_detailed_view.h', @@ -441,6 +432,9 @@ 'system/tray/fixed_sized_scroll_view.h', 'system/tray/hover_highlight_view.cc', 'system/tray/hover_highlight_view.h', + 'system/tray/media_security/media_capture_observer.h', + 'system/tray/media_security/multi_profile_media_tray_item.cc', + 'system/tray/media_security/multi_profile_media_tray_item.h', 'system/tray/special_popup_row.cc', 'system/tray/special_popup_row.h', 'system/tray/system_tray.cc', @@ -677,7 +671,6 @@ 'wm/workspace/multi_window_resize_controller.h', 'wm/workspace/phantom_window_controller.cc', 'wm/workspace/phantom_window_controller.h', - 'wm/workspace/snap_types.h', 'wm/workspace/two_step_edge_cycler.cc', 'wm/workspace/two_step_edge_cycler.h', 'wm/workspace/workspace_event_handler.cc', @@ -729,6 +722,9 @@ ['exclude', 'display/display_configurator_animation.h'], ['exclude', 'display/resolution_notification_controller.cc'], ['exclude', 'display/resolution_notification_controller.h'], + ['exclude', 'system/tray/media_security/media_capture_observer.h'], + ['exclude', 'system/tray/media_security/multi_profile_media_tray_item.cc'], + ['exclude', 'system/tray/media_security/multi_profile_media_tray_item.h'], ], }], ], @@ -836,6 +832,8 @@ 'test/test_system_tray_delegate.h', 'test/test_user_wallpaper_delegate.cc', 'test/test_user_wallpaper_delegate.h', + 'test/test_volume_control_delegate.cc', + 'test/test_volume_control_delegate.h', 'test/ui_controls_factory_ash.cc', 'test/ui_controls_factory_ash.h', ], @@ -878,6 +876,7 @@ '../ui/compositor/compositor.gyp:compositor_test_support', '../ui/events/events.gyp:events', '../ui/events/events.gyp:events_test_support', + '../ui/events/events.gyp:gesture_detection', '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/keyboard/keyboard.gyp:keyboard', @@ -924,9 +923,8 @@ 'drag_drop/drag_drop_tracker_unittest.cc', 'extended_desktop_unittest.cc', 'focus_cycler_unittest.cc', - 'frame/caption_buttons/alternate_frame_size_button_unittest.cc', - 'frame/caption_buttons/frame_caption_button_container_view_unittest.cc', - 'frame/caption_buttons/frame_maximize_button_unittest.cc', + 'frame/caption_buttons/frame_caption_button_container_view_unittest.cc', + 'frame/caption_buttons/frame_size_button_unittest.cc', 'frame/custom_frame_view_ash_unittest.cc', 'frame/default_header_painter_unittest.cc', 'host/ash_window_tree_host_x11_unittest.cc', @@ -966,6 +964,7 @@ 'system/chromeos/tray_display_unittest.cc', 'system/date/date_view_unittest.cc', 'system/overview/overview_button_tray_unittest.cc', + 'system/tray/media_security/multi_profile_media_tray_item_unittest.cc', 'system/tray/system_tray_unittest.cc', 'system/tray/tray_details_view_unittest.cc', 'system/user/tray_user_unittest.cc', @@ -1007,7 +1006,6 @@ 'wm/maximize_mode/workspace_backdrop_delegate.h', 'wm/workspace/magnetism_matcher_unittest.cc', 'wm/workspace/multi_window_resize_controller_unittest.cc', - 'wm/workspace/phantom_window_controller_unittest.cc', 'wm/workspace/workspace_event_handler_test_helper.cc', 'wm/workspace/workspace_event_handler_test_helper.h', 'wm/workspace/workspace_event_handler_unittest.cc', @@ -1031,6 +1029,7 @@ ['exclude', 'wm/workspace/workspace_window_resizer_unittest.cc'], ['exclude', 'sticky_keys/sticky_keys_overlay_unittest.cc'], ['exclude', 'sticky_keys/sticky_keys_unittest.cc'], + ['exclude', 'system/tray/media_security/multi_profile_media_tray_item_unittest.cc'], ['exclude', 'autoclick/autoclick_unittest.cc'], ], 'sources': [ @@ -1067,8 +1066,7 @@ ['exclude', 'display/resolution_notification_controller_unittest.cc'], ], }], - # TODO(dmikurube): Kill linux_use_tcmalloc. http://crbug.com/345554 - ['OS=="linux" and component=="shared_library" and ((use_allocator!="none" and use_allocator!="see_use_tcmalloc") or (use_allocator=="see_use_tcmalloc" and linux_use_tcmalloc==1))', { + ['OS=="linux" and component=="shared_library" and use_allocator!="none"', { 'dependencies': [ '<(DEPTH)/base/allocator/allocator.gyp:allocator', ], @@ -1117,8 +1115,6 @@ 'sources': [ '../content/app/startup_helper_win.cc', '../ui/views/test/test_views_delegate.cc', - 'session/session_state_delegate_stub.cc', - 'session/session_state_delegate_stub.h', 'shell/app_list.cc', 'shell/bubble.cc', 'shell/content_client/shell_browser_main_parts.cc', diff --git a/ash/ash_chromeos_strings.grdp b/ash/ash_chromeos_strings.grdp index b0333ec01c..15a0fb7161 100644 --- a/ash/ash_chromeos_strings.grdp +++ b/ash/ash_chromeos_strings.grdp @@ -305,6 +305,17 @@ Server message: <ph name="server_msg">$3<ex>Incorrect password</ex></ph> Stop </message> + <!-- Status tray media recording state strings. --> + <message name="IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO" desc="label used to indicate that the microphone is used by a background user"> + Micropohne is in use. + </message> + <message name="IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_VIDEO" desc="label used to indicate that the camera is used by a background user"> + Camera is in use. + </message> + <message name="IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO_VIDEO" desc="label used to indicate that the camera and microphone are used by a background user"> + Camera and microphone are in use. + </message> + <!-- Status tray screen share strings. --> <message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_STOP" desc="label used for screen sharing stop button"> Stop diff --git a/ash/ash_resources.gypi b/ash/ash_resources.gypi index 5c2d62ad43..68d93efae7 100644 --- a/ash/ash_resources.gypi +++ b/ash/ash_resources.gypi @@ -8,7 +8,7 @@ 'target_name': 'ash_resources', 'type': 'none', 'variables': { - 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/ash/ash_resources', + 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/ash/resources', }, 'actions': [ { @@ -19,11 +19,7 @@ 'includes': [ '../build/grit_action.gypi' ], }, ], - 'direct_dependent_settings': { - 'include_dirs': [ - '<(SHARED_INTERMEDIATE_DIR)/ash/ash_resources', - ], - }, + 'includes': [ '../build/grit_target.gypi' ], }, ], } diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 6a10965b40..07a6f3ffb4 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd @@ -528,11 +528,11 @@ Press Shift + Alt to switch. </message> <message name="IDS_ASH_STATUS_TRAY_ROTATION_LOCK_AUTO" desc="The text shown in the tray menu when rotation is set to auto."> - Auto rotate + Rotation on (Tap here to change) </message> <message name="IDS_ASH_STATUS_TRAY_ROTATION_LOCK_LOCKED" desc="The text shown in the tray menu when rotation is set to locked."> - Rotation locked + Rotation locked (Tap here to change) </message> <message name="IDS_ASH_VIRTUAL_KEYBOARD_TRAY_ACCESSIBLE_NAME" desc="The accessible text for virtual keyboard icon in status tray."> @@ -542,21 +542,6 @@ Press Shift + Alt to switch. <message name="IDS_ASH_NOTIFICATION_UNREAD_COUNT_NINE_PLUS" desc="The text shown in the notification icon for the unread count when the count is more than 9."> 9+ </message> - <message name="IDS_ASH_MAXIMIZE_WINDOW" desc="A help text to show that when the button gets clicked the window get maximized."> - Maximize - </message> - <message name="IDS_ASH_SNAP_WINDOW_RIGHT" desc="A help text to show that when the button gets clicked the window get snapped to the right side."> - Right - </message> - <message name="IDS_ASH_SNAP_WINDOW_LEFT" desc="A help text to show that when the button gets clicked the window get snapped to the left side."> - Left - </message> - <message name="IDS_ASH_RESTORE_WINDOW" desc="A help text to show that when the button gets clicked the window gets restored to its normal - non maximized - state."> - Restore - </message> - <message name="IDS_ASH_MINIMIZE_WINDOW" desc="A help text to show that when the button gets clicked the window gets minimized."> - Minimize - </message> <message name="IDS_ASH_DISPLAY_FAILURE_ON_MIRRORING" desc="An error message to show that the system failed to enter the mirroring mode."> Could not mirror displays since no supported resolutions found. Entered extended desktop instead. </message> diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc index f6bfeda6f4..acc29b113c 100644 --- a/ash/ash_switches.cc +++ b/ash/ash_switches.cc @@ -38,20 +38,13 @@ const char kAshDefaultWallpaperIsOem[] = "ash-default-wallpaper-is-oem"; const char kAshDefaultWallpaperLarge[] = "ash-default-wallpaper-large"; const char kAshDefaultWallpaperSmall[] = "ash-default-wallpaper-small"; -// Use the normal visual style for the caption buttons (minimize, maximize, -// restore, close). -const char kAshDisableAlternateFrameCaptionButtonStyle[] = - "ash-disable-alternate-caption-button"; - // Disable ability to dock windows at the desktop edge. const char kAshDisableDockedWindows[] = "ash-disable-docked-windows"; -// Use alternate visual style for the caption buttons (minimize, maximize, -// restore, close). The alternate style: -// - Adds a dedicated button for minimize. -// - Removes the maximize button's help bubble. -const char kAshEnableAlternateFrameCaptionButtonStyle[] = - "ash-enable-alternate-caption-button"; +// Enable the Touch Exploration Mode. Touch Exploration Mode will be turned on +// automatically when spoken feedback is enabled when this flag is set. +const char kAshEnableTouchExplorationMode[] = + "ash-enable-touch-exploration-mode"; #if defined(OS_CHROMEOS) // Enables key bindings to scroll magnified screen. @@ -117,11 +110,6 @@ const char kForceAshToDesktop[] = "ash-force-desktop"; #endif -bool UseAlternateFrameCaptionButtonStyle() { - return !CommandLine::ForCurrentProcess()-> - HasSwitch(kAshDisableAlternateFrameCaptionButtonStyle); -} - bool UseDockedWindows() { return !CommandLine::ForCurrentProcess()->HasSwitch(kAshDisableDockedWindows); } diff --git a/ash/ash_switches.h b/ash/ash_switches.h index 1937440399..e1be504d29 100644 --- a/ash/ash_switches.h +++ b/ash/ash_switches.h @@ -24,9 +24,8 @@ ASH_EXPORT extern const char kAshDebugShortcuts[]; ASH_EXPORT extern const char kAshDefaultWallpaperIsOem[]; ASH_EXPORT extern const char kAshDefaultWallpaperLarge[]; ASH_EXPORT extern const char kAshDefaultWallpaperSmall[]; -ASH_EXPORT extern const char kAshDisableAlternateFrameCaptionButtonStyle[]; ASH_EXPORT extern const char kAshDisableDockedWindows[]; -ASH_EXPORT extern const char kAshEnableAlternateFrameCaptionButtonStyle[]; +ASH_EXPORT extern const char kAshEnableTouchExplorationMode[]; #if defined(OS_CHROMEOS) ASH_EXPORT extern const char kAshEnableMagnifierKeyScroller[]; #endif @@ -46,10 +45,6 @@ ASH_EXPORT extern const char kAuraLegacyPowerButton[]; ASH_EXPORT extern const char kForceAshToDesktop[]; #endif -// Returns true if the alternate visual style for the caption buttons (minimize, -// maximize, restore, close) should be used. -ASH_EXPORT bool UseAlternateFrameCaptionButtonStyle(); - // Returns true if items can be dragged off the shelf to unpin. ASH_EXPORT bool UseDragOffShelf(); diff --git a/ash/ash_view_ids.h b/ash/ash_view_ids.h new file mode 100644 index 0000000000..61bf3cfc26 --- /dev/null +++ b/ash/ash_view_ids.h @@ -0,0 +1,18 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_ASH_VIEW_IDS_H_ +#define ASH_ASH_VIEW_IDS_H_ + +namespace ash { + +enum ViewID { + VIEW_ID_NONE = 10000, + VIEW_ID_MEDIA_TRAY_VIEW, + VIEW_ID_USER_VIEW_MEDIA_INDICATOR, +}; + +} // namespace ash + +#endif // ASH_ASH_VIEW_IDS_H_ diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc index 9ef0b9b795..e08d793bd1 100644 --- a/ash/drag_drop/drag_drop_controller_unittest.cc +++ b/ash/drag_drop/drag_drop_controller_unittest.cc @@ -24,6 +24,7 @@ #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/gestures/gesture_types.h" +#include "ui/events/test/events_test_utils.h" #include "ui/gfx/animation/linear_animation.h" #include "ui/gfx/image/image_skia_rep.h" #include "ui/views/test/test_views_delegate.h" @@ -282,8 +283,12 @@ void DispatchGesture(ui::EventType gesture_type, gfx::Point location) { ui::EventTimeForNow(), ui::GestureEventDetails(gesture_type, 0, 0), 1); - Shell::GetPrimaryRootWindow()->GetHost()->dispatcher()->DispatchGestureEvent( - &gesture_event); + ui::EventSource* event_source = + Shell::GetPrimaryRootWindow()->GetHost()->GetEventSource(); + ui::EventSourceTestApi event_source_test(event_source); + ui::EventDispatchDetails details = + event_source_test.SendEventToProcessor(&gesture_event); + CHECK(!details.dispatcher_destroyed); } } // namespace diff --git a/ash/frame/caption_buttons/bubble_contents_button_row.cc b/ash/frame/caption_buttons/bubble_contents_button_row.cc deleted file mode 100644 index 761beec8ed..0000000000 --- a/ash/frame/caption_buttons/bubble_contents_button_row.cc +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/frame/caption_buttons/bubble_contents_button_row.h" - -#include "ash/frame/caption_buttons/maximize_bubble_controller.h" -#include "ash/frame/caption_buttons/maximize_bubble_controller_bubble.h" -#include "grit/ash_resources.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/layout/box_layout.h" - - -namespace ash { - -// BubbleDialogButton --------------------------------------------------------- - -// The image button gets overridden to be able to capture mouse hover events. -// The constructor also assigns all button states and adds |this| as a child of -// |button_row|. -class BubbleDialogButton : public views::ImageButton { - public: - explicit BubbleDialogButton(BubbleContentsButtonRow* button_row, - int normal_image, - int hovered_image, - int pressed_image); - virtual ~BubbleDialogButton(); - - // views::ImageButton: - virtual void OnMouseCaptureLost() OVERRIDE; - virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - - private: - // The creating class which needs to get notified in case of a hover event. - BubbleContentsButtonRow* button_row_; - - DISALLOW_COPY_AND_ASSIGN(BubbleDialogButton); -}; - -BubbleDialogButton::BubbleDialogButton( - BubbleContentsButtonRow* button_row, - int normal_image, - int hovered_image, - int pressed_image) - : views::ImageButton(button_row), - button_row_(button_row) { - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - SetImage(views::CustomButton::STATE_NORMAL, - rb.GetImageSkiaNamed(normal_image)); - SetImage(views::CustomButton::STATE_HOVERED, - rb.GetImageSkiaNamed(hovered_image)); - SetImage(views::CustomButton::STATE_PRESSED, - rb.GetImageSkiaNamed(pressed_image)); - button_row->AddChildView(this); -} - -BubbleDialogButton::~BubbleDialogButton() { -} - -void BubbleDialogButton::OnMouseCaptureLost() { - button_row_->ButtonHovered(NULL); - views::ImageButton::OnMouseCaptureLost(); -} - -void BubbleDialogButton::OnMouseEntered(const ui::MouseEvent& event) { - button_row_->ButtonHovered(this); - views::ImageButton::OnMouseEntered(event); -} - -void BubbleDialogButton::OnMouseExited(const ui::MouseEvent& event) { - button_row_->ButtonHovered(NULL); - views::ImageButton::OnMouseExited(event); -} - -bool BubbleDialogButton::OnMouseDragged(const ui::MouseEvent& event) { - if (!button_row_->bubble()->controller()) - return false; - - // Remove the phantom window when we leave the button. - gfx::Point screen_location(event.location()); - View::ConvertPointToScreen(this, &screen_location); - if (!GetBoundsInScreen().Contains(screen_location)) - button_row_->ButtonHovered(NULL); - else - button_row_->ButtonHovered(this); - - // Pass the event on to the normal handler. - return views::ImageButton::OnMouseDragged(event); -} - - -// BubbleContentsButtonRow ---------------------------------------------------- - -BubbleContentsButtonRow::BubbleContentsButtonRow( - MaximizeBubbleControllerBubble* bubble) - : bubble_(bubble), - left_button_(NULL), - minimize_button_(NULL), - right_button_(NULL) { - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kHorizontal, 0, 0, - MaximizeBubbleControllerBubble::kLayoutSpacing)); - set_background(views::Background::CreateSolidBackground( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor)); - - if (base::i18n::IsRTL()) { - AddMaximizeRightButton(); - AddMinimizeButton(); - AddMaximizeLeftButton(); - } else { - AddMaximizeLeftButton(); - AddMinimizeButton(); - AddMaximizeRightButton(); - } -} - -BubbleContentsButtonRow::~BubbleContentsButtonRow() { -} - -void BubbleContentsButtonRow::ButtonPressed(views::Button* sender, - const ui::Event& event) { - // While shutting down, the connection to the owner might already be broken. - if (!bubble_->controller()) - return; - if (sender == left_button_) { - bubble_->controller()->OnButtonClicked( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) ? - SNAP_RESTORE : SNAP_LEFT); - } else if (sender == minimize_button_) { - bubble_->controller()->OnButtonClicked(SNAP_MINIMIZE); - } else { - DCHECK(sender == right_button_); - bubble_->controller()->OnButtonClicked( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) ? - SNAP_RESTORE : SNAP_RIGHT); - } -} - -void BubbleContentsButtonRow::ButtonHovered(BubbleDialogButton* sender) { - // While shutting down, the connection to the owner might already be broken. - if (!bubble_->controller()) - return; - if (sender == left_button_) { - bubble_->controller()->OnButtonHover( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) ? - SNAP_RESTORE : SNAP_LEFT); - } else if (sender == minimize_button_) { - bubble_->controller()->OnButtonHover(SNAP_MINIMIZE); - } else if (sender == right_button_) { - bubble_->controller()->OnButtonHover( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) ? - SNAP_RESTORE : SNAP_RIGHT); - } else { - bubble_->controller()->OnButtonHover(SNAP_NONE); - } -} - -views::CustomButton* BubbleContentsButtonRow::GetButtonForUnitTest( - SnapType state) { - switch (state) { - case SNAP_LEFT: - return left_button_; - case SNAP_MINIMIZE: - return minimize_button_; - case SNAP_RIGHT: - return right_button_; - default: - NOTREACHED(); - return NULL; - } -} - -void BubbleContentsButtonRow::AddMaximizeLeftButton() { - if (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) { - left_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE_H, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE_P); - } else { - left_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_LEFT, - IDR_AURA_WINDOW_POSITION_LEFT_H, - IDR_AURA_WINDOW_POSITION_LEFT_P); - } -} - -void BubbleContentsButtonRow::AddMaximizeRightButton() { - if (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) { - right_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE_H, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE_P); - } else { - right_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_RIGHT, - IDR_AURA_WINDOW_POSITION_RIGHT_H, - IDR_AURA_WINDOW_POSITION_RIGHT_P); - } -} - -void BubbleContentsButtonRow::AddMinimizeButton() { - minimize_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_MIDDLE, - IDR_AURA_WINDOW_POSITION_MIDDLE_H, - IDR_AURA_WINDOW_POSITION_MIDDLE_P); -} - -} // namespace ash diff --git a/ash/frame/caption_buttons/bubble_contents_button_row.h b/ash/frame/caption_buttons/bubble_contents_button_row.h deleted file mode 100644 index e3bfc6149f..0000000000 --- a/ash/frame/caption_buttons/bubble_contents_button_row.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_FRAME_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ -#define ASH_FRAME_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ - -#include "ash/wm/workspace/snap_types.h" -#include "ui/views/controls/button/button.h" - -namespace views { -class CustomButton; -} - -namespace ash { - -class BubbleDialogButton; -class MaximizeBubbleControllerBubble; - -// A class that creates all buttons and puts them into a view. -class BubbleContentsButtonRow : public views::View, - public views::ButtonListener { - public: - explicit BubbleContentsButtonRow(MaximizeBubbleControllerBubble* bubble); - virtual ~BubbleContentsButtonRow(); - - // views::ButtonListener: - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) OVERRIDE; - - // Called from BubbleDialogButton. - void ButtonHovered(BubbleDialogButton* sender); - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - MaximizeBubbleControllerBubble* bubble() { return bubble_; } - - private: - // Functions to add the left and right maximize / restore buttons. - void AddMaximizeLeftButton(); - void AddMaximizeRightButton(); - void AddMinimizeButton(); - - // The owning object which gets notifications. - MaximizeBubbleControllerBubble* bubble_; - - // The created buttons for our menu. - BubbleDialogButton* left_button_; - BubbleDialogButton* minimize_button_; - BubbleDialogButton* right_button_; - - DISALLOW_COPY_AND_ASSIGN(BubbleContentsButtonRow); -}; - -} // namespace ash - -#endif // ASH_FRAME_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ diff --git a/ash/frame/caption_buttons/caption_button_types.h b/ash/frame/caption_buttons/caption_button_types.h index b481a02f6f..7cf625aa18 100644 --- a/ash/frame/caption_buttons/caption_button_types.h +++ b/ash/frame/caption_buttons/caption_button_types.h @@ -7,14 +7,6 @@ namespace ash { -// These are the types of maximization we know. -enum MaximizeBubbleFrameState { - FRAME_STATE_NONE = 0, - FRAME_STATE_FULL = 1, // This is the full maximized state. - FRAME_STATE_SNAP_LEFT = 2, - FRAME_STATE_SNAP_RIGHT = 3 -}; - // These are the icon types that a caption button can have. The size button's // action (SnapType) can be different from its icon. enum CaptionButtonIcon { diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view.cc b/ash/frame/caption_buttons/frame_caption_button_container_view.cc index f533f14a81..06103f46bd 100644 --- a/ash/frame/caption_buttons/frame_caption_button_container_view.cc +++ b/ash/frame/caption_buttons/frame_caption_button_container_view.cc @@ -7,9 +7,8 @@ #include <cmath> #include "ash/ash_switches.h" -#include "ash/frame/caption_buttons/alternate_frame_size_button.h" #include "ash/frame/caption_buttons/frame_caption_button.h" -#include "ash/frame/caption_buttons/frame_maximize_button.h" +#include "ash/frame/caption_buttons/frame_size_button.h" #include "ash/metrics/user_metrics_recorder.h" #include "ash/shell.h" #include "grit/ui_strings.h" // Accessibility names @@ -48,23 +47,14 @@ FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( minimize_button_(NULL), size_button_(NULL), close_button_(NULL) { - bool alternate_style = switches::UseAlternateFrameCaptionButtonStyle(); - // Insert the buttons left to right. minimize_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_MINIMIZE); minimize_button_->SetAccessibleName( l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE)); - // Hide |minimize_button_| when using the non-alternate button style because - // |size_button_| is capable of minimizing in this case. - minimize_button_->SetVisible( - minimize_allowed == MINIMIZE_ALLOWED && - (alternate_style || !frame_->widget_delegate()->CanMaximize())); + minimize_button_->SetVisible(minimize_allowed == MINIMIZE_ALLOWED); AddChildView(minimize_button_); - if (alternate_style) - size_button_ = new AlternateFrameSizeButton(this, frame, this); - else - size_button_ = new FrameMaximizeButton(this, frame); + size_button_ = new FrameSizeButton(this, frame, this); size_button_->SetAccessibleName( l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE)); UpdateSizeButtonVisibility(false); @@ -79,12 +69,6 @@ FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() { } -FrameMaximizeButton* -FrameCaptionButtonContainerView::GetOldStyleSizeButton() { - return switches::UseAlternateFrameCaptionButtonStyle() ? - NULL : static_cast<FrameMaximizeButton*>(size_button_); -} - void FrameCaptionButtonContainerView::SetButtonImages( CaptionButtonIcon icon, int icon_image_id, diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view.h b/ash/frame/caption_buttons/frame_caption_button_container_view.h index d50350e038..d57695a7e6 100644 --- a/ash/frame/caption_buttons/frame_caption_button_container_view.h +++ b/ash/frame/caption_buttons/frame_caption_button_container_view.h @@ -6,7 +6,7 @@ #define ASH_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ #include "ash/ash_export.h" -#include "ash/frame/caption_buttons/alternate_frame_size_button_delegate.h" +#include "ash/frame/caption_buttons/frame_size_button_delegate.h" #include "ui/views/controls/button/button.h" #include "ui/views/view.h" @@ -15,15 +15,13 @@ class Widget; } namespace ash { -class FrameCaptionButton; -class FrameMaximizeButton; // Container view for the frame caption buttons. It performs the appropriate // action when a caption button is clicked. class ASH_EXPORT FrameCaptionButtonContainerView : public views::View, public views::ButtonListener, - public AlternateFrameSizeButtonDelegate { + public FrameSizeButtonDelegate { public: static const char kViewClassName[]; @@ -66,10 +64,6 @@ class ASH_EXPORT FrameCaptionButtonContainerView DISALLOW_COPY_AND_ASSIGN(TestApi); }; - // Returns the size button if using the old caption button style, returns NULL - // otherwise. - FrameMaximizeButton* GetOldStyleSizeButton(); - // Sets the resource ids of the images to paint the button for |icon|. The // FrameCaptionButtonContainerView will keep track of the images to use for // |icon| even if none of the buttons currently use |icon|. @@ -130,7 +124,7 @@ class ASH_EXPORT FrameCaptionButtonContainerView virtual void ButtonPressed(views::Button* sender, const ui::Event& event) OVERRIDE; - // AlternateFrameSizeButtonDelegate: + // FrameSizeButtonDelegate: virtual bool IsMinimizeButtonVisible() const OVERRIDE; virtual void SetButtonsToNormal(Animate animate) OVERRIDE; virtual void SetButtonIcons(CaptionButtonIcon minimize_button_icon, diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc index c0317bf85b..acd72c8e16 100644 --- a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc +++ b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc @@ -4,12 +4,9 @@ #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" -#include "ash/ash_switches.h" #include "ash/frame/caption_buttons/frame_caption_button.h" #include "ash/test/ash_test_base.h" -#include "base/command_line.h" #include "grit/ash_resources.h" -#include "ui/aura/window_event_dispatcher.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -102,29 +99,10 @@ class FrameCaptionButtonContainerViewTest : public ash::test::AshTestBase { DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTest); }; -class FrameCaptionButtonContainerViewTestOldStyle - : public FrameCaptionButtonContainerViewTest { - public: - FrameCaptionButtonContainerViewTestOldStyle() { - } - - virtual ~FrameCaptionButtonContainerViewTestOldStyle() { - } - - virtual void SetUp() OVERRIDE { - FrameCaptionButtonContainerViewTest::SetUp(); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshDisableAlternateFrameCaptionButtonStyle); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTestOldStyle); -}; - // Test how the allowed actions affect which caption buttons are visible. -TEST_F(FrameCaptionButtonContainerViewTestOldStyle, ButtonVisibility) { - // The minimize button should be hidden when both minimizing and maximizing - // are allowed because the size button can do both. +TEST_F(FrameCaptionButtonContainerViewTest, ButtonVisibility) { + // All the buttons should be visible when minimizing and maximizing are + // allowed. scoped_ptr<views::Widget> widget_can_maximize( CreateTestWidget(MAXIMIZE_ALLOWED)); FrameCaptionButtonContainerView container1(widget_can_maximize.get(), @@ -132,11 +110,11 @@ TEST_F(FrameCaptionButtonContainerViewTestOldStyle, ButtonVisibility) { SetMockImages(&container1); container1.Layout(); FrameCaptionButtonContainerView::TestApi t1(&container1); - EXPECT_FALSE(t1.minimize_button()->visible()); + EXPECT_TRUE(t1.minimize_button()->visible()); EXPECT_TRUE(t1.size_button()->visible()); EXPECT_TRUE(t1.close_button()->visible()); EXPECT_TRUE(CheckButtonsAtEdges( - &container1, *t1.size_button(), *t1.close_button())); + &container1, *t1.minimize_button(), *t1.close_button())); // The minimize button should be visible when minimizing is allowed but // maximizing is disallowed. @@ -167,43 +145,4 @@ TEST_F(FrameCaptionButtonContainerViewTestOldStyle, ButtonVisibility) { &container3, *t3.close_button(), *t3.close_button())); } -class FrameCaptionButtonContainerViewTestAlternateStyle - : public FrameCaptionButtonContainerViewTest { - public: - FrameCaptionButtonContainerViewTestAlternateStyle() { - } - - virtual ~FrameCaptionButtonContainerViewTestAlternateStyle() { - } - - virtual void SetUp() OVERRIDE { - FrameCaptionButtonContainerViewTest::SetUp(); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshEnableAlternateFrameCaptionButtonStyle); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTestAlternateStyle); -}; - -// Test how the alternate button style affects which buttons are visible in the -// default case. -TEST_F(FrameCaptionButtonContainerViewTestAlternateStyle, ButtonVisibility) { - // Both the minimize button and the maximize button should be visible when - // both minimizing and maximizing are allowed when using the alternate - // button style. - scoped_ptr<views::Widget> widget_can_maximize( - CreateTestWidget(MAXIMIZE_ALLOWED)); - FrameCaptionButtonContainerView container(widget_can_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - SetMockImages(&container); - container.Layout(); - FrameCaptionButtonContainerView::TestApi t(&container); - EXPECT_TRUE(t.minimize_button()->visible()); - EXPECT_TRUE(t.size_button()->visible()); - EXPECT_TRUE(t.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container, *t.minimize_button(), *t.close_button())); -} - } // namespace ash diff --git a/ash/frame/caption_buttons/frame_maximize_button.cc b/ash/frame/caption_buttons/frame_maximize_button.cc deleted file mode 100644 index dc28c7ab46..0000000000 --- a/ash/frame/caption_buttons/frame_maximize_button.cc +++ /dev/null @@ -1,547 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/frame/caption_buttons/frame_maximize_button.h" - -#include "ash/frame/caption_buttons/frame_maximize_button_observer.h" -#include "ash/frame/caption_buttons/maximize_bubble_controller.h" -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/screen_util.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/touch/touch_uma.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/wm_event.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "grit/ash_strings.h" -#include "ui/aura/window.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/events/event.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" -#include "ui/views/window/non_client_view.h" - -namespace ash { - -namespace { - -// Delay before forcing an update of the snap location. -const int kUpdateDelayMS = 400; - -// The delay of the bubble appearance. -const int kBubbleAppearanceDelayMS = 500; - -// The minimum sanp size in percent of the screen width. -const int kMinSnapSizePercent = 50; -} - -// EscapeEventFilter is installed on the RootWindow to track when the escape key -// is pressed. We use an EventFilter for this as the FrameMaximizeButton -// normally does not get focus. -class FrameMaximizeButton::EscapeEventFilter : public ui::EventHandler { - public: - explicit EscapeEventFilter(FrameMaximizeButton* button); - virtual ~EscapeEventFilter(); - - // EventFilter overrides: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - - private: - FrameMaximizeButton* button_; - - DISALLOW_COPY_AND_ASSIGN(EscapeEventFilter); -}; - -FrameMaximizeButton::EscapeEventFilter::EscapeEventFilter( - FrameMaximizeButton* button) - : button_(button) { - Shell::GetInstance()->AddPreTargetHandler(this); -} - -FrameMaximizeButton::EscapeEventFilter::~EscapeEventFilter() { - Shell::GetInstance()->RemovePreTargetHandler(this); -} - -void FrameMaximizeButton::EscapeEventFilter::OnKeyEvent( - ui::KeyEvent* event) { - if (event->type() == ui::ET_KEY_PRESSED && - event->key_code() == ui::VKEY_ESCAPE) { - button_->Cancel(false); - } -} - -// FrameMaximizeButton --------------------------------------------------------- - -FrameMaximizeButton::FrameMaximizeButton(views::ButtonListener* listener, - views::Widget* frame) - : FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE), - frame_(frame), - observing_frame_(false), - is_snap_enabled_(false), - exceeded_drag_threshold_(false), - snap_type_(SNAP_NONE), - bubble_appearance_delay_ms_(kBubbleAppearanceDelayMS) { -} - -FrameMaximizeButton::~FrameMaximizeButton() { - // Before the window gets destroyed, the maximizer dialog needs to be shut - // down since it would otherwise call into a deleted object. - maximizer_.reset(); - if (observing_frame_) - OnWindowDestroying(frame_->GetNativeWindow()); -} - -void FrameMaximizeButton::AddObserver(FrameMaximizeButtonObserver* observer) { - observer_list_.AddObserver(observer); -} - -void FrameMaximizeButton::RemoveObserver( - FrameMaximizeButtonObserver* observer) { - observer_list_.RemoveObserver(observer); -} - -void FrameMaximizeButton::SnapButtonHovered(SnapType type) { - // Make sure to only show hover operations when no button is pressed and - // a similar snap operation in progress does not get re-applied. - if (is_snap_enabled_ || type == snap_type_) - return; - // Prime the mouse location with the center of the (local) button. - press_location_ = gfx::Point(width() / 2, height() / 2); - // Then get an adjusted mouse position to initiate the effect. - gfx::Point location = press_location_; - switch (type) { - case SNAP_LEFT: - location.set_x(location.x() - width()); - break; - case SNAP_RIGHT: - location.set_x(location.x() + width()); - break; - case SNAP_MINIMIZE: - location.set_y(location.y() + height()); - break; - case SNAP_RESTORE: - // Simulate a mouse button move over the according button. - if (GetMaximizeBubbleFrameState() == FRAME_STATE_SNAP_LEFT) - location.set_x(location.x() - width()); - else if (GetMaximizeBubbleFrameState() == FRAME_STATE_SNAP_RIGHT) - location.set_x(location.x() + width()); - break; - case SNAP_MAXIMIZE: - break; - case SNAP_NONE: - Cancel(true); - return; - default: - // We should not come here. - NOTREACHED(); - } - UpdateSnap(location); -} - -void FrameMaximizeButton::ExecuteSnapAndCloseMenu(SnapType snap_type) { - Cancel(true); - // Tell our menu to close. - maximizer_.reset(); - snap_type_ = snap_type; - Snap(); -} - -void FrameMaximizeButton::OnMaximizeBubbleShown(views::Widget* bubble) { - FOR_EACH_OBSERVER(FrameMaximizeButtonObserver, - observer_list_, - OnMaximizeBubbleShown(bubble)); -} - -void FrameMaximizeButton::DestroyMaximizeMenu() { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowBoundsChanged( - aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowDestroying(aura::Window* window) { - maximizer_.reset(); - if (observing_frame_) { - CHECK_EQ(frame_->GetNativeWindow(), window); - frame_->GetNativeWindow()->RemoveObserver(this); - frame_->RemoveObserver(this); - observing_frame_ = false; - } -} - -void FrameMaximizeButton::OnWidgetActivationChanged(views::Widget* widget, - bool active) { - // Upon losing focus, the bubble menu and the phantom window should hide. - if (!active) - Cancel(false); -} - -bool FrameMaximizeButton::OnMousePressed(const ui::MouseEvent& event) { - // If we are already in a mouse click / drag operation, a second button down - // call will cancel (this addresses crbug.com/143755). - if (is_snap_enabled_) { - Cancel(false); - } else { - is_snap_enabled_ = event.IsOnlyLeftMouseButton(); - if (is_snap_enabled_) - ProcessStartEvent(event); - } - FrameCaptionButton::OnMousePressed(event); - return true; -} - -void FrameMaximizeButton::OnMouseEntered(const ui::MouseEvent& event) { - FrameCaptionButton::OnMouseEntered(event); - if (!maximizer_) { - DCHECK(GetWidget()); - if (!observing_frame_) { - observing_frame_ = true; - frame_->GetNativeWindow()->AddObserver(this); - frame_->AddObserver(this); - } - maximizer_.reset(new MaximizeBubbleController( - this, - GetMaximizeBubbleFrameState(), - bubble_appearance_delay_ms_)); - } -} - -void FrameMaximizeButton::OnMouseExited(const ui::MouseEvent& event) { - FrameCaptionButton::OnMouseExited(event); - // Remove the bubble menu when the button is not pressed and the mouse is not - // within the bubble. - if (!is_snap_enabled_ && maximizer_) { - if (maximizer_->GetBubbleWindow()) { - gfx::Point screen_location = Shell::GetScreen()->GetCursorScreenPoint(); - if (!maximizer_->GetBubbleWindow()->GetBoundsInScreen().Contains( - screen_location)) { - maximizer_.reset(); - // Make sure that all remaining snap hover states get removed. - SnapButtonHovered(SNAP_NONE); - } - } else { - // The maximize dialog does not show up immediately after creating the - // |maximizer_|. Destroy the dialog therefore before it shows up. - maximizer_.reset(); - } - } -} - -bool FrameMaximizeButton::OnMouseDragged(const ui::MouseEvent& event) { - if (is_snap_enabled_) - ProcessUpdateEvent(event); - return FrameCaptionButton::OnMouseDragged(event); -} - -void FrameMaximizeButton::OnMouseReleased(const ui::MouseEvent& event) { - maximizer_.reset(); - bool snap_was_enabled = is_snap_enabled_; - if (!ProcessEndEvent(event) && snap_was_enabled) - FrameCaptionButton::OnMouseReleased(event); - // At this point |this| might be already destroyed. -} - -void FrameMaximizeButton::OnMouseCaptureLost() { - Cancel(false); - FrameCaptionButton::OnMouseCaptureLost(); -} - -void FrameMaximizeButton::OnGestureEvent(ui::GestureEvent* event) { - if (event->type() == ui::ET_GESTURE_TAP_DOWN) { - is_snap_enabled_ = true; - ProcessStartEvent(*event); - event->SetHandled(); - return; - } - - if (event->type() == ui::ET_GESTURE_TAP || - (event->type() == ui::ET_GESTURE_SCROLL_END && is_snap_enabled_) || - event->type() == ui::ET_SCROLL_FLING_START) { - // The position of the event may have changed from the previous event (both - // for TAP and SCROLL_END). So it is necessary to update the snap-state for - // the current event. - ProcessUpdateEvent(*event); - if (event->type() == ui::ET_GESTURE_TAP) { - snap_type_ = SnapTypeForLocation(event->location()); - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_FRAMEMAXIMIZE_TAP); - } - ProcessEndEvent(*event); - event->SetHandled(); - return; - } - - if (is_snap_enabled_) { - if (event->type() == ui::ET_GESTURE_END && - event->details().touch_points() == 1) { - // The position of the event may have changed from the previous event. So - // it is necessary to update the snap-state for the current event. - ProcessUpdateEvent(*event); - snap_type_ = SnapTypeForLocation(event->location()); - ProcessEndEvent(*event); - event->SetHandled(); - return; - } - - if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE || - event->type() == ui::ET_GESTURE_SCROLL_BEGIN) { - ProcessUpdateEvent(*event); - event->SetHandled(); - return; - } - } - - FrameCaptionButton::OnGestureEvent(event); -} - -void FrameMaximizeButton::SetVisible(bool visible) { - views::View::SetVisible(visible); -} - -void FrameMaximizeButton::ProcessStartEvent(const ui::LocatedEvent& event) { - DCHECK(is_snap_enabled_); - // Prepare the help menu. - if (!maximizer_) { - maximizer_.reset(new MaximizeBubbleController( - this, - GetMaximizeBubbleFrameState(), - bubble_appearance_delay_ms_)); - } else { - // If the menu did not show up yet, we delay it even a bit more. - maximizer_->DelayCreation(); - } - InstallEventFilter(); - snap_type_ = SNAP_NONE; - press_location_ = event.location(); - exceeded_drag_threshold_ = false; - update_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kUpdateDelayMS), - this, - &FrameMaximizeButton::UpdateSnapFromEventLocation); -} - -void FrameMaximizeButton::ProcessUpdateEvent(const ui::LocatedEvent& event) { - DCHECK(is_snap_enabled_); - if (!exceeded_drag_threshold_) { - exceeded_drag_threshold_ = views::View::ExceededDragThreshold( - event.location() - press_location_); - } - if (exceeded_drag_threshold_) - UpdateSnap(event.location()); -} - -bool FrameMaximizeButton::ProcessEndEvent(const ui::LocatedEvent& event) { - update_timer_.Stop(); - UninstallEventFilter(); - bool should_snap = is_snap_enabled_; - is_snap_enabled_ = false; - - // Remove our help bubble. - maximizer_.reset(); - - if (!should_snap || snap_type_ == SNAP_NONE) - return false; - - SetState(views::CustomButton::STATE_NORMAL); - // SetState will not call SchedulePaint() if state was already set to - // STATE_NORMAL during a drag. - SchedulePaint(); - phantom_window_.reset(); - Snap(); - return true; -} - -void FrameMaximizeButton::Cancel(bool keep_menu_open) { - if (!keep_menu_open) { - maximizer_.reset(); - UninstallEventFilter(); - is_snap_enabled_ = false; - } - phantom_window_.reset(); - snap_type_ = SNAP_NONE; - update_timer_.Stop(); - SchedulePaint(); -} - -void FrameMaximizeButton::InstallEventFilter() { - if (escape_event_filter_) - return; - - escape_event_filter_.reset(new EscapeEventFilter(this)); -} - -void FrameMaximizeButton::UninstallEventFilter() { - escape_event_filter_.reset(NULL); -} - -void FrameMaximizeButton::UpdateSnapFromEventLocation() { - // If the drag threshold has been exceeded the snap location is up to date. - if (exceeded_drag_threshold_) - return; - exceeded_drag_threshold_ = true; - UpdateSnap(press_location_); -} - -void FrameMaximizeButton::UpdateSnap(const gfx::Point& location) { - SnapType type = SnapTypeForLocation(location); - if (type == snap_type_) - return; - - snap_type_ = type; - SchedulePaint(); - - if (snap_type_ == SNAP_NONE) { - phantom_window_.reset(); - return; - } - - if (!phantom_window_) { - phantom_window_.reset( - new PhantomWindowController(frame_->GetNativeWindow())); - } - if (maximizer_) { - phantom_window_->set_phantom_below_window(maximizer_->GetBubbleWindow()); - maximizer_->SetSnapType(snap_type_); - } - phantom_window_->Show(ScreenBoundsForType(snap_type_)); -} - -SnapType FrameMaximizeButton::SnapTypeForLocation( - const gfx::Point& location) const { - MaximizeBubbleFrameState maximize_type = GetMaximizeBubbleFrameState(); - gfx::Vector2d delta(location - press_location_); - if (!views::View::ExceededDragThreshold(delta)) - return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE; - if (delta.x() < 0 && delta.y() > delta.x() && delta.y() < -delta.x()) - return maximize_type == FRAME_STATE_SNAP_LEFT ? SNAP_RESTORE : SNAP_LEFT; - if (delta.x() > 0 && delta.y() > -delta.x() && delta.y() < delta.x()) - return maximize_type == FRAME_STATE_SNAP_RIGHT ? SNAP_RESTORE : SNAP_RIGHT; - if (delta.y() > 0) - return SNAP_MINIMIZE; - return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE; -} - -gfx::Rect FrameMaximizeButton::ScreenBoundsForType(SnapType type) const { - aura::Window* window = frame_->GetNativeWindow(); - switch (type) { - case SNAP_LEFT: - return ScreenUtil::ConvertRectToScreen( - window->parent(), - wm::GetDefaultLeftSnappedWindowBoundsInParent(window)); - case SNAP_RIGHT: - return ScreenUtil::ConvertRectToScreen( - window->parent(), - wm::GetDefaultRightSnappedWindowBoundsInParent(window)); - case SNAP_MAXIMIZE: - return ScreenUtil::ConvertRectToScreen( - window->parent(), - ScreenUtil::GetMaximizedWindowBoundsInParent(window)); - case SNAP_MINIMIZE: { - gfx::Rect rect = GetMinimizeAnimationTargetBoundsInScreen(window); - if (!rect.IsEmpty()) { - // PhantomWindowController insets slightly, outset it so the phantom - // doesn't appear inset. - rect.Inset(-8, -8); - } - return rect; - } - case SNAP_RESTORE: { - wm::WindowState* window_state = wm::GetWindowState(window); - return window_state->HasRestoreBounds() ? - window_state->GetRestoreBoundsInScreen() : - frame_->GetWindowBoundsInScreen(); - } - case SNAP_NONE: - NOTREACHED(); - } - return gfx::Rect(); -} - -void FrameMaximizeButton::Snap() { - Shell* shell = Shell::GetInstance(); - wm::WindowState* window_state = wm::GetWindowState(frame_->GetNativeWindow()); - switch (snap_type_) { - case SNAP_LEFT: { - const wm::WMEvent event(wm::WM_EVENT_SNAP_LEFT); - window_state->OnWMEvent(&event); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT); - break; - } - case SNAP_RIGHT: { - const wm::WMEvent event(wm::WM_EVENT_SNAP_RIGHT); - window_state->OnWMEvent(&event); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT); - break; - } - case SNAP_MAXIMIZE: - frame_->Maximize(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE); - break; - case SNAP_MINIMIZE: - frame_->Minimize(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MINIMIZE); - break; - case SNAP_RESTORE: - frame_->Restore(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_RESTORE); - break; - case SNAP_NONE: - NOTREACHED(); - } -} - -MaximizeBubbleFrameState -FrameMaximizeButton::GetMaximizeBubbleFrameState() const { - wm::WindowState* window_state = - wm::GetWindowState(frame_->GetNativeWindow()); - // When there are no restore bounds, we are in normal mode. - if (!window_state->HasRestoreBounds()) - return FRAME_STATE_NONE; - // The normal maximized test can be used. - if (frame_->IsMaximized()) - return FRAME_STATE_FULL; - // For Left/right maximize we need to check the dimensions. - gfx::Rect bounds = frame_->GetWindowBoundsInScreen(); - gfx::Rect screen = Shell::GetScreen()->GetDisplayNearestWindow( - frame_->GetNativeView()).work_area(); - if (bounds.width() < (screen.width() * kMinSnapSizePercent) / 100) - return FRAME_STATE_NONE; - // We might still have a horizontally filled window at this point which we - // treat as no special state. - if (bounds.y() != screen.y() || bounds.height() != screen.height()) - return FRAME_STATE_NONE; - - // We have to be in a maximize mode at this point. - if (bounds.x() == screen.x()) - return FRAME_STATE_SNAP_LEFT; - if (bounds.right() == screen.right()) - return FRAME_STATE_SNAP_RIGHT; - // If we come here, it is likely caused by the fact that the - // "VerticalResizeDoubleClick" stored a restore rectangle. In that case - // we allow all maximize operations (and keep the restore rectangle). - return FRAME_STATE_NONE; -} - -} // namespace ash diff --git a/ash/frame/caption_buttons/frame_maximize_button.h b/ash/frame/caption_buttons/frame_maximize_button.h deleted file mode 100644 index 29d89e81f4..0000000000 --- a/ash/frame/caption_buttons/frame_maximize_button.h +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_FRAME_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ -#define ASH_FRAME_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ - -#include "ash/ash_export.h" -#include "ash/frame/caption_buttons/caption_button_types.h" -#include "ash/frame/caption_buttons/frame_caption_button.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/timer/timer.h" -#include "ui/aura/window_observer.h" -#include "ui/views/widget/widget_observer.h" - -namespace views { -class Widget; -} - -namespace ash { -class FrameMaximizeButtonObserver; -class MaximizeBubbleController; -class PhantomWindowController; - -// Button used for the maximize control on the frame. Handles snapping logic. -class ASH_EXPORT FrameMaximizeButton : public FrameCaptionButton, - public views::WidgetObserver, - public aura::WindowObserver { - public: - FrameMaximizeButton(views::ButtonListener* listener, - views::Widget* frame); - virtual ~FrameMaximizeButton(); - - void AddObserver(FrameMaximizeButtonObserver* observer); - void RemoveObserver(FrameMaximizeButtonObserver* observer); - - // Updates |snap_type_| based on a a given snap type. This is used by - // external hover events from the button menu. - void SnapButtonHovered(SnapType type); - - // The user clicked the |type| button and the action needs to be performed, - // which will at the same time close the window. - void ExecuteSnapAndCloseMenu(SnapType type); - - // Called by the MaximizeBubbleController when the maximize bubble is shown. - void OnMaximizeBubbleShown(views::Widget* bubble); - - // Remove the maximize menu from the screen (and destroy it). - void DestroyMaximizeMenu(); - - // Returns true when the user clicks and drags the button. - bool is_snap_enabled() const { return is_snap_enabled_; } - - // WindowObserver overrides: - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // WidgetObserver overrides: - virtual void OnWidgetActivationChanged(views::Widget* widget, - bool active) OVERRIDE; - - // ImageButton overrides: - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseCaptureLost() OVERRIDE; - - // ui::EventHandler overrides: - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // views::View overwrite: - virtual void SetVisible(bool visible) OVERRIDE; - - // Unit test overwrite: Change the UI delay used for the bubble show up. - void set_bubble_appearance_delay_ms(int bubble_appearance_delay_ms) { - bubble_appearance_delay_ms_ = bubble_appearance_delay_ms; - } - - // Unit test accessor for the maximize bubble. - MaximizeBubbleController* maximizer() { return maximizer_.get(); } - - // Unit test to see if phantom window is open. - bool phantom_window_open() { return phantom_window_.get() != NULL; } - - private: - class EscapeEventFilter; - - // Initializes the snap-gesture based on the event. This should only be called - // when the event is confirmed to have started a snap gesture. - void ProcessStartEvent(const ui::LocatedEvent& event); - - // Updates the snap-state based on the current event. This should only be - // called after the snap gesture has already started. - void ProcessUpdateEvent(const ui::LocatedEvent& event); - - // Returns true if the window was snapped. Returns false otherwise. - bool ProcessEndEvent(const ui::LocatedEvent& event); - - // Cancels snap behavior. If |keep_menu_open| is set, a possibly opened - // bubble help will remain open. - void Cancel(bool keep_menu_open); - - // Installs/uninstalls an EventFilter to track when escape is pressed. - void InstallEventFilter(); - void UninstallEventFilter(); - - // Updates the snap position from the event location. This is invoked by - // |update_timer_|. - void UpdateSnapFromEventLocation(); - - // Updates |snap_type_| based on a mouse drag. - void UpdateSnap(const gfx::Point& location); - - // Returns the type of snap based on the specified location. - SnapType SnapTypeForLocation(const gfx::Point& location) const; - - // Returns the bounds of the resulting window for the specified type. - gfx::Rect ScreenBoundsForType(SnapType type) const; - - // Snaps the window to the current snap position determined by |snap_type_|. - void Snap(); - - // Determine the maximize type of this window. - MaximizeBubbleFrameState GetMaximizeBubbleFrameState() const; - - // Widget that the maximize button acts on. This is different than the widget - // which contains the button in the case of AppNonClientFrameViewAsh. - views::Widget* frame_; - - // True if we have put observers on |frame_|. - bool observing_frame_; - - // Renders the snap position. - scoped_ptr<PhantomWindowController> phantom_window_; - - // Is snapping enabled? Set on press so that in drag we know whether we - // should show the snap locations. - bool is_snap_enabled_; - - // Did the user drag far enough to trigger snapping? - bool exceeded_drag_threshold_; - - // Location of the press. - gfx::Point press_location_; - - // Current snap type. - SnapType snap_type_; - - scoped_ptr<EscapeEventFilter> escape_event_filter_; - - base::OneShotTimer<FrameMaximizeButton> update_timer_; - - scoped_ptr<MaximizeBubbleController> maximizer_; - - // The delay of the bubble appearance. - int bubble_appearance_delay_ms_; - - ObserverList<FrameMaximizeButtonObserver> observer_list_; - - DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButton); -}; - -} // namespace ash - -#endif // ASH_FRAME_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ diff --git a/ash/frame/caption_buttons/frame_maximize_button_observer.h b/ash/frame/caption_buttons/frame_maximize_button_observer.h deleted file mode 100644 index 57bdd47a79..0000000000 --- a/ash/frame/caption_buttons/frame_maximize_button_observer.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_FRAME_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ -#define ASH_FRAME_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ - -#include "ash/ash_export.h" - -namespace views { -class Widget; -} - -namespace ash { - -class ASH_EXPORT FrameMaximizeButtonObserver { - public: - virtual ~FrameMaximizeButtonObserver() {} - - // Called when the maximize button's help bubble is shown. - virtual void OnMaximizeBubbleShown(views::Widget* bubble) = 0; -}; - -} // namespace ash - -#endif // ASH_FRAME_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ diff --git a/ash/frame/caption_buttons/frame_maximize_button_unittest.cc b/ash/frame/caption_buttons/frame_maximize_button_unittest.cc deleted file mode 100644 index 06305d14e3..0000000000 --- a/ash/frame/caption_buttons/frame_maximize_button_unittest.cc +++ /dev/null @@ -1,814 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/frame/caption_buttons/frame_maximize_button.h" - -#include "ash/ash_switches.h" -#include "ash/frame/caption_buttons/frame_caption_button_container_view.h" -#include "ash/frame/caption_buttons/maximize_bubble_controller.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "grit/ash_resources.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/aura/window_tree_host.h" -#include "ui/events/event_processor.h" -#include "ui/events/event_utils.h" -#include "ui/events/gestures/gesture_configuration.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace test { - -namespace { - -class CancelCallbackHandler { - public: - CancelCallbackHandler(int update_events_before_cancel, - FrameMaximizeButton* maximize_button) : - update_events_before_cancel_(update_events_before_cancel), - maximize_button_(maximize_button) {} - virtual ~CancelCallbackHandler() {} - - void CountedCancelCallback(ui::EventType event_type, - const gfx::Vector2dF& pos) { - if (event_type == ui::ET_GESTURE_SCROLL_UPDATE && - !(--update_events_before_cancel_)) { - // Make sure that we are in the middle of a resizing operation, cancel it - // and then test that it is exited. - EXPECT_TRUE(maximize_button_->is_snap_enabled()); - maximize_button_->DestroyMaximizeMenu(); - EXPECT_FALSE(maximize_button_->is_snap_enabled()); - } - } - - private: - // When this counter reaches 0, the gesture maximize action gets cancelled. - int update_events_before_cancel_; - - // The maximize button which needs to get informed of the gesture termination. - FrameMaximizeButton* maximize_button_; - - DISALLOW_COPY_AND_ASSIGN(CancelCallbackHandler); -}; - -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate() {} - virtual ~TestWidgetDelegate() {} - - // views::WidgetDelegate overrides: - virtual views::View* GetContentsView() OVERRIDE { - return this; - } - virtual bool CanResize() const OVERRIDE { - return true; - } - virtual bool CanMaximize() const OVERRIDE { - return true; - } - - ash::FrameCaptionButtonContainerView* caption_button_container() { - return caption_button_container_; - } - - private: - // Overridden from views::View: - virtual void Layout() OVERRIDE { - caption_button_container_->Layout(); - - // Right align the caption button container. - gfx::Size preferred_size = caption_button_container_->GetPreferredSize(); - caption_button_container_->SetBounds(width() - preferred_size.width(), 0, - preferred_size.width(), preferred_size.height()); - } - - virtual void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) OVERRIDE { - if (details.is_add && details.child == this) { - caption_button_container_ = new FrameCaptionButtonContainerView( - GetWidget(), FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - - // Set arbitrary images for the container's buttons so that the buttons - // have non-empty sizes. - for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) { - caption_button_container_->SetButtonImages( - static_cast<CaptionButtonIcon>(icon), - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE, - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - } - - AddChildView(caption_button_container_); - } - } - - // Not owned. - ash::FrameCaptionButtonContainerView* caption_button_container_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -} // namespace - -class FrameMaximizeButtonTest : public ash::test::AshTestBase { - public: - FrameMaximizeButtonTest() {} - virtual ~FrameMaximizeButtonTest() {} - - // The returned widget takes ownership of |delegate|. - views::Widget* CreateWidget(views::WidgetDelegate* delegate) { - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - views::Widget* widget = new views::Widget; - params.context = CurrentContext(); - params.delegate = delegate; - params.bounds = gfx::Rect(10, 10, 100, 100); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - widget->Init(params); - widget->Show(); - return widget; - } - - void CloseWidget() { - if (widget_) - widget_->CloseNow(); - widget_ = NULL; - } - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshDisableAlternateFrameCaptionButtonStyle); - - TestWidgetDelegate* delegate = new TestWidgetDelegate(); - widget_ = CreateWidget(delegate); - FrameCaptionButtonContainerView* caption_button_container = - delegate->caption_button_container(); - - FrameCaptionButtonContainerView::TestApi test(caption_button_container); - maximize_button_ = static_cast<FrameMaximizeButton*>( - test.size_button()); - } - - virtual void TearDown() OVERRIDE { - CloseWidget(); - AshTestBase::TearDown(); - } - - views::Widget* widget() { return widget_; } - - FrameMaximizeButton* maximize_button() { return maximize_button_; } - - private: - views::Widget* widget_; - FrameMaximizeButton* maximize_button_; - - DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButtonTest); -}; - -// Tests that clicking on the resize-button toggles between maximize and normal -// state. -TEST_F(FrameMaximizeButtonTest, ResizeButtonToggleMaximize) { - wm::WindowState* window_state = - wm::GetWindowState(widget()->GetNativeWindow()); - views::View* view = maximize_button(); - gfx::Point center = view->GetBoundsInScreen().CenterPoint(); - - aura::test::EventGenerator generator( - window_state->window()->GetRootWindow(), center); - - EXPECT_FALSE(window_state->IsMaximized()); - - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state->IsMaximized()); - - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state->IsMaximized()); - - generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint()); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint()); - EXPECT_FALSE(window_state->IsMaximized()); - - generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint()); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint()); - EXPECT_FALSE(window_state->IsMaximized()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_ResizeButtonDrag DISABLED_ResizeButtonDrag -#else -#define MAYBE_ResizeButtonDrag ResizeButtonDrag -#endif - -// Tests that click+dragging on the resize-button tiles or minimizes the window. -TEST_F(FrameMaximizeButtonTest, MAYBE_ResizeButtonDrag) { - aura::Window* window = widget()->GetNativeWindow(); - views::View* view = maximize_button(); - gfx::Point center = view->GetBoundsInScreen().CenterPoint(); - - aura::test::EventGenerator generator(window->GetRootWindow(), center); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsNormalStateType()); - - // Snap right. - { - generator.PressLeftButton(); - generator.MoveMouseBy(10, 0); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - EXPECT_EQ(wm::GetDefaultRightSnappedWindowBoundsInParent(window).ToString(), - window->bounds().ToString()); - } - - // Snap left. - { - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.PressLeftButton(); - generator.MoveMouseBy(-10, 0); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), - window->bounds().ToString()); - } - - // Minimize. - { - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.PressLeftButton(); - generator.MoveMouseBy(0, 10); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_TRUE(window_state->IsMinimized()); - } - - window_state->Restore(); - - // Now test the same behaviour for gesture events. - - // Snap right. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(80, 0); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - // This is a short resizing distance and different touch behavior - // applies which leads in half of the screen being used. - EXPECT_EQ("400,0 400x553", window->bounds().ToString()); - } - - // Snap left. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(-80, 0); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), - window->bounds().ToString()); - } - - // Minimize. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(0, 40); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_TRUE(window_state->IsMinimized()); - } - - // Test with gesture events. -} - -// Test that closing the (browser) window with an opened balloon does not -// crash the system. In other words: Make sure that shutting down the frame -// destroys the opened balloon in an orderly fashion. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonExternalShutDown) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Even though the widget is closing the bubble menu should not crash upon - // its delayed destruction. - CloseWidget(); -} - -// Test that maximizing the browser after hovering in does not crash the system -// when the observer gets removed in the bubble destruction process. -TEST_F(FrameMaximizeButtonTest, MaximizeOnHoverThenClick) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - generator.ClickLeftButton(); - EXPECT_TRUE(wm::GetWindowState(window)->IsMaximized()); -} - -// Test that hovering over a button in the balloon dialog will show the phantom -// window. Moving then away from the button will hide it again. Then check that -// pressing and dragging the button itself off the button will also release the -// phantom window. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftButtonDragOut) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Move the mouse over the left maximize button. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - - generator.MoveMouseTo(left_max_pos); - // Expect the phantom window to be open. - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Move away to see the window being destroyed. - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move back over the button. - generator.MoveMouseTo(button_pos); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Press button and drag out of dialog. - generator.PressLeftButton(); - generator.MoveMouseTo(off_pos); - generator.ReleaseLeftButton(); - - // Check that the phantom window is also gone. - EXPECT_FALSE(maximize_button->phantom_window_open()); -} - -// Test that clicking a button in the maximizer bubble (in this case the -// maximize left button) will do the requested action. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftByButton) { - aura::Window* window = widget()->GetNativeWindow(); - - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Move the mouse over the left maximize button. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - generator.ClickLeftButton(); - - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), - window->bounds().ToString()); -} - -// Test that the activation focus does not change when the bubble gets shown. -TEST_F(FrameMaximizeButtonTest, MaximizeKeepFocus) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - - aura::Window* active = - aura::client::GetFocusClient(window)->GetFocusedWindow(); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Check that the focused window is still the same. - EXPECT_EQ(active, aura::client::GetFocusClient(window)->GetFocusedWindow()); -} - -TEST_F(FrameMaximizeButtonTest, MaximizeTap) { - aura::Window* window = widget()->GetNativeWindow(); - aura::Window* root_window = window->GetRootWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - - const int touch_default_radius = - ui::GestureConfiguration::default_radius(); - ui::GestureConfiguration::set_default_radius(0); - - ui::EventProcessor* dispatcher = root_window->GetHost()->event_processor(); - const int kTouchId = 2; - ui::TouchEvent press(ui::ET_TOUCH_PRESSED, - button_pos, - kTouchId, - ui::EventTimeForNow()); - ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press); - ASSERT_FALSE(details.dispatcher_destroyed); - - button_pos.Offset(9, 8); - ui::TouchEvent release( - ui::ET_TOUCH_RELEASED, - button_pos, - kTouchId, - press.time_stamp() + base::TimeDelta::FromMilliseconds(50)); - details = dispatcher->OnEventFromSource(&release); - ASSERT_FALSE(details.dispatcher_destroyed); - - ui::GestureConfiguration::set_default_radius(touch_default_radius); -} - -// Test that only the left button will activate the maximize button. -TEST_F(FrameMaximizeButtonTest, OnlyLeftButtonMaximizes) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsNormalStateType()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Move the mouse cursor over the button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // After pressing the left button the button should get triggered. - generator.PressLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(maximize_button->is_snap_enabled()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Pressing the right button then should cancel the operation. - generator.PressRightButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->maximizer()); - - // After releasing the second button the window shouldn't be maximized. - generator.ReleaseRightButton(); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state->IsMaximized()); - - // Second experiment: Starting with right should also not trigger. - generator.MoveMouseTo(off_pos); - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Pressing first the right button should not activate. - generator.PressRightButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->is_snap_enabled()); - - // Pressing then additionally the left button shouldn't activate either. - generator.PressLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->is_snap_enabled()); - generator.ReleaseRightButton(); - generator.ReleaseLeftButton(); - EXPECT_FALSE(window_state->IsMaximized()); -} - -// Click a button of window maximize functionality. -// If |snap_type| is SNAP_NONE the FrameMaximizeButton gets clicked, otherwise -// the associated snap button. -// |Window| is the window which owns the maximize button. -// |maximize_button| is the FrameMaximizeButton which controls the window. -void ClickMaxButton( - ash::FrameMaximizeButton* maximize_button, - aura::Window* window, - SnapType snap_type) { - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - if (snap_type != SNAP_NONE) { - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(snap_type)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - } - // After pressing the left button the button should get triggered. - generator.ClickLeftButton(); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Test that the restore from left/right maximize is properly done. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - wm::WindowState* window_state = wm::GetWindowState(window); - // The window should not be maximized. - EXPECT_FALSE(window_state->IsMaximized()); - // But the bounds should be different. - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(0, new_bounds.x()); - EXPECT_EQ(0, new_bounds.y()); - - // Now click the same button again to see that it restores. - ClickMaxButton(maximize_button, window, SNAP_LEFT); - // But the bounds should be restored. - new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Maximize, left/right maximize and then restore should works. -TEST_F(FrameMaximizeButtonTest, MaximizeMaximizeLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - EXPECT_FALSE(window_state->IsMaximized()); - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(0, new_bounds.x()); - EXPECT_EQ(0, new_bounds.y()); - - // Now click the same button again to see that it restores. - ClickMaxButton(maximize_button, window, SNAP_LEFT); - RunAllPendingInMessageLoop(); - // But the bounds should be restored. - new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Left/right maximize, maximize and then restore should work. -TEST_F(FrameMaximizeButtonTest, MaximizeSnapLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_FALSE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - EXPECT_TRUE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - EXPECT_FALSE(window_state->IsMaximized()); - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Test that minimizing the window per keyboard closes the maximize bubble. -TEST_F(FrameMaximizeButtonTest, MinimizePerKeyClosesBubble) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - - // Move the mouse cursor over the maximize button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // We simulate the keystroke by calling minimizeWindow directly. - wm::WindowState* window_state = wm::GetWindowState(window); - window_state->Minimize(); - - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Tests that dragging down on the maximize button minimizes the window. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragDownMinimizes) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - wm::WindowState* window_state = wm::GetWindowState(window); - // Drag down on a maximized window. - window_state->Maximize(); - EXPECT_TRUE(window_state->IsMaximized()); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x(), button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow()); - generator.GestureScrollSequence(button_pos, off_pos, - base::TimeDelta::FromMilliseconds(0), 1); - - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); - - // Drag down on a restored window. - window_state->Restore(); - - button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - off_pos = gfx::Point(button_pos.x(), button_pos.y() + 200); - generator.GestureScrollSequence(button_pos, off_pos, - base::TimeDelta::FromMilliseconds(10), 1); - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Tests that dragging Left and pressing ESC does properly abort. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragLeftEscapeExits) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() - button_pos.x() / 2, button_pos.y()); - - const int kGestureSteps = 10; - CancelCallbackHandler cancel_handler(kGestureSteps / 2, maximize_button); - aura::test::EventGenerator generator(window->GetRootWindow()); - generator.GestureScrollSequenceWithCallback( - button_pos, - off_pos, - base::TimeDelta::FromMilliseconds(0), - kGestureSteps, - base::Bind(&CancelCallbackHandler::CountedCancelCallback, - base::Unretained(&cancel_handler))); - - // Check that there was no size change. - EXPECT_EQ(widget()->GetWindowBoundsInScreen().size().ToString(), - initial_bounds.size().ToString()); - // Check that there is no phantom window left open. - EXPECT_FALSE(maximize_button->phantom_window_open()); -} - -// Test that hovering over a button in the maximizer bubble and switching -// activation without moving the mouse properly aborts. -TEST_F(FrameMaximizeButtonTest, LossOfActivationWhileMaximizeBubbleOpenAborts) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - EXPECT_TRUE(widget()->IsActive()); - - // Move the mouse over the maximize button in order to bring up the maximizer - // bubble. - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Hover the mouse over the left maximize button in the maximizer bubble to - // show the phantom window. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Change activation by creating a new window. This could be done via an - // accelerator. The root window takes ownership of |just_created|. - views::Widget* just_created = views::Widget::CreateWindowWithContextAndBounds( - NULL, widget()->GetNativeWindow(), gfx::Rect(100, 100)); - just_created->Show(); - just_created->Activate(); - EXPECT_FALSE(widget()->IsActive()); - - // Test that we have properly reset the state of the now inactive window. - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - EXPECT_EQ(initial_bounds.ToString(), window->GetBoundsInScreen().ToString()); -} - -} // namespace test -} // namespace ash diff --git a/ash/frame/caption_buttons/alternate_frame_size_button.cc b/ash/frame/caption_buttons/frame_size_button.cc index 54799cb134..1399453ffd 100644 --- a/ash/frame/caption_buttons/alternate_frame_size_button.cc +++ b/ash/frame/caption_buttons/frame_size_button.cc @@ -1,8 +1,8 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/frame/caption_buttons/alternate_frame_size_button.h" +#include "ash/frame/caption_buttons/frame_size_button.h" #include "ash/metrics/user_metrics_recorder.h" #include "ash/screen_util.h" @@ -44,10 +44,10 @@ bool HitTestButton(const ash::FrameCaptionButton* button, namespace ash { -AlternateFrameSizeButton::AlternateFrameSizeButton( +FrameSizeButton::FrameSizeButton( views::ButtonListener* listener, views::Widget* frame, - AlternateFrameSizeButtonDelegate* delegate) + FrameSizeButtonDelegate* delegate) : FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE), frame_(frame), delegate_(delegate), @@ -56,10 +56,10 @@ AlternateFrameSizeButton::AlternateFrameSizeButton( snap_type_(SNAP_NONE) { } -AlternateFrameSizeButton::~AlternateFrameSizeButton() { +FrameSizeButton::~FrameSizeButton() { } -bool AlternateFrameSizeButton::OnMousePressed(const ui::MouseEvent& event) { +bool FrameSizeButton::OnMousePressed(const ui::MouseEvent& event) { // The minimize and close buttons are set to snap left and right when snapping // is enabled. Do not enable snapping if the minimize button is not visible. // The close button is always visible. @@ -72,7 +72,7 @@ bool AlternateFrameSizeButton::OnMousePressed(const ui::MouseEvent& event) { return true; } -bool AlternateFrameSizeButton::OnMouseDragged(const ui::MouseEvent& event) { +bool FrameSizeButton::OnMouseDragged(const ui::MouseEvent& event) { UpdateSnapType(event); // By default a FrameCaptionButton reverts to STATE_NORMAL once the mouse // leaves its bounds. Skip FrameCaptionButton's handling when @@ -82,25 +82,25 @@ bool AlternateFrameSizeButton::OnMouseDragged(const ui::MouseEvent& event) { return true; } -void AlternateFrameSizeButton::OnMouseReleased(const ui::MouseEvent& event) { +void FrameSizeButton::OnMouseReleased(const ui::MouseEvent& event) { if (!IsTriggerableEvent(event) || !CommitSnap(event)) FrameCaptionButton::OnMouseReleased(event); } -void AlternateFrameSizeButton::OnMouseCaptureLost() { - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); +void FrameSizeButton::OnMouseCaptureLost() { + SetButtonsToNormalMode(FrameSizeButtonDelegate::ANIMATE_YES); FrameCaptionButton::OnMouseCaptureLost(); } -void AlternateFrameSizeButton::OnMouseMoved(const ui::MouseEvent& event) { +void FrameSizeButton::OnMouseMoved(const ui::MouseEvent& event) { // Ignore any synthetic mouse moves during a drag. if (!in_snap_mode_) FrameCaptionButton::OnMouseMoved(event); } -void AlternateFrameSizeButton::OnGestureEvent(ui::GestureEvent* event) { +void FrameSizeButton::OnGestureEvent(ui::GestureEvent* event) { if (event->details().touch_points() > 1) { - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); + SetButtonsToNormalMode(FrameSizeButtonDelegate::ANIMATE_YES); return; } @@ -135,7 +135,7 @@ void AlternateFrameSizeButton::OnGestureEvent(ui::GestureEvent* event) { FrameCaptionButton::OnGestureEvent(event); } -void AlternateFrameSizeButton::StartSetButtonsToSnapModeTimer( +void FrameSizeButton::StartSetButtonsToSnapModeTimer( const ui::LocatedEvent& event) { set_buttons_to_snap_mode_timer_event_location_ = event.location(); if (set_buttons_to_snap_mode_delay_ms_ == 0) { @@ -145,16 +145,16 @@ void AlternateFrameSizeButton::StartSetButtonsToSnapModeTimer( FROM_HERE, base::TimeDelta::FromMilliseconds(set_buttons_to_snap_mode_delay_ms_), this, - &AlternateFrameSizeButton::AnimateButtonsToSnapMode); + &FrameSizeButton::AnimateButtonsToSnapMode); } } -void AlternateFrameSizeButton::AnimateButtonsToSnapMode() { - SetButtonsToSnapMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); +void FrameSizeButton::AnimateButtonsToSnapMode() { + SetButtonsToSnapMode(FrameSizeButtonDelegate::ANIMATE_YES); } -void AlternateFrameSizeButton::SetButtonsToSnapMode( - AlternateFrameSizeButtonDelegate::Animate animate) { +void FrameSizeButton::SetButtonsToSnapMode( + FrameSizeButtonDelegate::Animate animate) { in_snap_mode_ = true; // When using a right-to-left layout the close button is left of the size @@ -170,7 +170,7 @@ void AlternateFrameSizeButton::SetButtonsToSnapMode( } } -void AlternateFrameSizeButton::UpdateSnapType(const ui::LocatedEvent& event) { +void FrameSizeButton::UpdateSnapType(const ui::LocatedEvent& event) { if (!in_snap_mode_) { // Set the buttons adjacent to the size button to snap left and right early // if the user drags past the drag threshold. @@ -196,7 +196,7 @@ void AlternateFrameSizeButton::UpdateSnapType(const ui::LocatedEvent& event) { if (to_hover) { // Progress the minimize and close icon morph animations to the end if they // are in progress. - SetButtonsToSnapMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO); + SetButtonsToSnapMode(FrameSizeButtonDelegate::ANIMATE_NO); } delegate_->SetHoveredAndPressedButtons( @@ -235,7 +235,7 @@ void AlternateFrameSizeButton::UpdateSnapType(const ui::LocatedEvent& event) { } } -const FrameCaptionButton* AlternateFrameSizeButton::GetButtonToHover( +const FrameCaptionButton* FrameSizeButton::GetButtonToHover( const gfx::Point& event_location_in_screen) const { const FrameCaptionButton* closest_button = delegate_->GetButtonClosestTo( event_location_in_screen); @@ -247,7 +247,7 @@ const FrameCaptionButton* AlternateFrameSizeButton::GetButtonToHover( return NULL; } -bool AlternateFrameSizeButton::CommitSnap(const ui::LocatedEvent& event) { +bool FrameSizeButton::CommitSnap(const ui::LocatedEvent& event) { // The position of |event| may be different than the position of the previous // event. UpdateSnapType(event); @@ -265,15 +265,15 @@ bool AlternateFrameSizeButton::CommitSnap(const ui::LocatedEvent& event) { snap_type_ == SNAP_LEFT ? UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT : UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT); - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO); + SetButtonsToNormalMode(FrameSizeButtonDelegate::ANIMATE_NO); return true; } - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); + SetButtonsToNormalMode(FrameSizeButtonDelegate::ANIMATE_YES); return false; } -void AlternateFrameSizeButton::SetButtonsToNormalMode( - AlternateFrameSizeButtonDelegate::Animate animate) { +void FrameSizeButton::SetButtonsToNormalMode( + FrameSizeButtonDelegate::Animate animate) { in_snap_mode_ = false; snap_type_ = SNAP_NONE; set_buttons_to_snap_mode_timer_.Stop(); diff --git a/ash/frame/caption_buttons/alternate_frame_size_button.h b/ash/frame/caption_buttons/frame_size_button.h index e99d32f39c..f1ac605556 100644 --- a/ash/frame/caption_buttons/alternate_frame_size_button.h +++ b/ash/frame/caption_buttons/frame_size_button.h @@ -1,14 +1,13 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_FRAME_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ -#define ASH_FRAME_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ +#ifndef ASH_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_ +#define ASH_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_ #include "ash/ash_export.h" -#include "ash/frame/caption_buttons/alternate_frame_size_button_delegate.h" #include "ash/frame/caption_buttons/frame_caption_button.h" -#include "ash/wm/workspace/snap_types.h" +#include "ash/frame/caption_buttons/frame_size_button_delegate.h" #include "base/timer/timer.h" namespace views { @@ -16,10 +15,10 @@ class Widget; } namespace ash { -class AlternateFrameSizeButtonDelegate; +class FrameSizeButtonDelegate; class PhantomWindowController; -// The maximize/restore button when using the alternate button style. +// The maximize/restore button. // When the mouse is pressed over the size button or the size button is touched: // - The minimize and close buttons are set to snap left and snap right // respectively. @@ -28,13 +27,13 @@ class PhantomWindowController; // When the drag terminates, the action for the button underneath the mouse // is executed. For the sake of simplicity, the size button is the event // handler for a click starting on the size button and the entire drag. -class ASH_EXPORT AlternateFrameSizeButton : public FrameCaptionButton { +class ASH_EXPORT FrameSizeButton : public FrameCaptionButton { public: - AlternateFrameSizeButton(views::ButtonListener* listener, - views::Widget* frame, - AlternateFrameSizeButtonDelegate* delegate); + FrameSizeButton(views::ButtonListener* listener, + views::Widget* frame, + FrameSizeButtonDelegate* delegate); - virtual ~AlternateFrameSizeButton(); + virtual ~FrameSizeButton(); // views::CustomButton overrides: virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; @@ -49,6 +48,12 @@ class ASH_EXPORT AlternateFrameSizeButton : public FrameCaptionButton { } private: + enum SnapType { + SNAP_LEFT, + SNAP_RIGHT, + SNAP_NONE + }; + // Starts |set_buttons_to_snap_mode_timer_|. void StartSetButtonsToSnapModeTimer(const ui::LocatedEvent& event); @@ -57,8 +62,7 @@ class ASH_EXPORT AlternateFrameSizeButton : public FrameCaptionButton { // Sets the buttons adjacent to the size button to snap left and right. // Passing in ANIMATE_NO progresses the animation (if any) to the end. - void SetButtonsToSnapMode( - AlternateFrameSizeButtonDelegate::Animate animate); + void SetButtonsToSnapMode(FrameSizeButtonDelegate::Animate animate); // Updates |snap_type_|, whether the size button is pressed and whether any // other buttons are hovered. @@ -76,14 +80,13 @@ class ASH_EXPORT AlternateFrameSizeButton : public FrameCaptionButton { // Sets the buttons adjacent to the size button to minimize and close again. // Clears any state set while snapping was enabled. |animate| indicates // whether the buttons should animate back to their original icons. - void SetButtonsToNormalMode( - AlternateFrameSizeButtonDelegate::Animate animate); + void SetButtonsToNormalMode(FrameSizeButtonDelegate::Animate animate); // Widget that the size button acts on. views::Widget* frame_; // Not owned. - AlternateFrameSizeButtonDelegate* delegate_; + FrameSizeButtonDelegate* delegate_; // Location of the event which started |set_buttons_to_snap_mode_timer_| in // view coordinates. @@ -94,7 +97,7 @@ class ASH_EXPORT AlternateFrameSizeButton : public FrameCaptionButton { // right. int set_buttons_to_snap_mode_delay_ms_; - base::OneShotTimer<AlternateFrameSizeButton> set_buttons_to_snap_mode_timer_; + base::OneShotTimer<FrameSizeButton> set_buttons_to_snap_mode_timer_; // Whether the buttons adjacent to the size button snap the window left and // right. @@ -110,9 +113,9 @@ class ASH_EXPORT AlternateFrameSizeButton : public FrameCaptionButton { // left or snap right button is pressed. scoped_ptr<PhantomWindowController> phantom_window_controller_; - DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButton); + DISALLOW_COPY_AND_ASSIGN(FrameSizeButton); }; } // namespace ash -#endif // ASH_FRAME_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ +#endif // ASH_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_ diff --git a/ash/frame/caption_buttons/alternate_frame_size_button_delegate.h b/ash/frame/caption_buttons/frame_size_button_delegate.h index 050227bd0d..ddccf16c66 100644 --- a/ash/frame/caption_buttons/alternate_frame_size_button_delegate.h +++ b/ash/frame/caption_buttons/frame_size_button_delegate.h @@ -1,9 +1,9 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_FRAME_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ -#define ASH_FRAME_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ +#ifndef ASH_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_ +#define ASH_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_ #include "ash/ash_export.h" #include "ash/frame/caption_buttons/caption_button_types.h" @@ -17,8 +17,8 @@ class Vector2d; namespace ash { class FrameCaptionButton; -// Delegate interface for AlternateFrameSizeButton. -class ASH_EXPORT AlternateFrameSizeButtonDelegate { +// Delegate interface for FrameSizeButton. +class ASH_EXPORT FrameSizeButtonDelegate { public: enum Animate { ANIMATE_YES, @@ -50,9 +50,9 @@ class ASH_EXPORT AlternateFrameSizeButtonDelegate { const FrameCaptionButton* to_press) = 0; protected: - virtual ~AlternateFrameSizeButtonDelegate() {} + virtual ~FrameSizeButtonDelegate() {} }; } // namespace ash -#endif // ASH_FRAME_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ +#endif // ASH_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_ diff --git a/ash/frame/caption_buttons/alternate_frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc index 92c7bbca95..74c8f141b6 100644 --- a/ash/frame/caption_buttons/alternate_frame_size_button_unittest.cc +++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc @@ -1,16 +1,14 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/frame/caption_buttons/alternate_frame_size_button.h" +#include "ash/frame/caption_buttons/frame_size_button.h" -#include "ash/ash_switches.h" #include "ash/frame/caption_buttons/frame_caption_button.h" #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_state.h" -#include "base/command_line.h" #include "base/i18n/rtl.h" #include "grit/ash_resources.h" #include "ui/aura/test/event_generator.h" @@ -87,10 +85,10 @@ class TestWidgetDelegate : public views::WidgetDelegateView { } // namespace -class AlternateFrameSizeButtonTest : public AshTestBase { +class FrameSizeButtonTest : public AshTestBase { public: - AlternateFrameSizeButtonTest() {} - virtual ~AlternateFrameSizeButtonTest() {} + FrameSizeButtonTest() {} + virtual ~FrameSizeButtonTest() {} // Returns the center point of |view| in screen coordinates. gfx::Point CenterPointInScreen(views::View* view) { @@ -127,10 +125,6 @@ class AlternateFrameSizeButtonTest : public AshTestBase { virtual void SetUp() OVERRIDE { AshTestBase::SetUp(); - CommandLine* command_line = CommandLine::ForCurrentProcess(); - command_line->AppendSwitch( - switches::kAshEnableAlternateFrameCaptionButtonStyle); - TestWidgetDelegate* delegate = new TestWidgetDelegate(); window_state_ = ash::wm::GetWindowState( CreateWidget(delegate)->GetNativeWindow()); @@ -140,7 +134,7 @@ class AlternateFrameSizeButtonTest : public AshTestBase { minimize_button_ = test.minimize_button(); size_button_ = test.size_button(); - static_cast<AlternateFrameSizeButton*>( + static_cast<FrameSizeButton*>( size_button_)->set_delay_to_set_buttons_to_snap_mode(0); close_button_ = test.close_button(); } @@ -159,12 +153,12 @@ class AlternateFrameSizeButtonTest : public AshTestBase { FrameCaptionButton* size_button_; FrameCaptionButton* close_button_; - DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButtonTest); + DISALLOW_COPY_AND_ASSIGN(FrameSizeButtonTest); }; // Tests that pressing the left mouse button or tapping down on the size button // puts the button into the pressed state. -TEST_F(AlternateFrameSizeButtonTest, PressedState) { +TEST_F(FrameSizeButtonTest, PressedState) { aura::test::EventGenerator& generator = GetEventGenerator(); generator.MoveMouseTo(CenterPointInScreen(size_button())); generator.PressLeftButton(); @@ -183,7 +177,7 @@ TEST_F(AlternateFrameSizeButtonTest, PressedState) { // Tests that clicking on the size button toggles between the maximized and // normal state. -TEST_F(AlternateFrameSizeButtonTest, ClickSizeButtonTogglesMaximize) { +TEST_F(FrameSizeButtonTest, ClickSizeButtonTogglesMaximize) { EXPECT_FALSE(window_state()->IsMaximized()); aura::test::EventGenerator& generator = GetEventGenerator(); @@ -208,7 +202,7 @@ TEST_F(AlternateFrameSizeButtonTest, ClickSizeButtonTogglesMaximize) { // Test that clicking + dragging to a button adjacent to the size button snaps // the window left or right. -TEST_F(AlternateFrameSizeButtonTest, ButtonDrag) { +TEST_F(FrameSizeButtonTest, ButtonDrag) { EXPECT_TRUE(window_state()->IsNormalStateType()); // 1) Test by dragging the mouse. @@ -267,7 +261,7 @@ TEST_F(AlternateFrameSizeButtonTest, ButtonDrag) { // Test that clicking, dragging, and overshooting the minimize button a bit // horizontally still snaps the window left. -TEST_F(AlternateFrameSizeButtonTest, SnapLeftOvershootMinimize) { +TEST_F(FrameSizeButtonTest, SnapLeftOvershootMinimize) { EXPECT_TRUE(window_state()->IsNormalStateType()); aura::test::EventGenerator& generator = GetEventGenerator(); @@ -284,7 +278,7 @@ TEST_F(AlternateFrameSizeButtonTest, SnapLeftOvershootMinimize) { } // Test that right clicking the size button has no effect. -TEST_F(AlternateFrameSizeButtonTest, RightMouseButton) { +TEST_F(FrameSizeButtonTest, RightMouseButton) { EXPECT_TRUE(window_state()->IsNormalStateType()); aura::test::EventGenerator& generator = GetEventGenerator(); @@ -299,7 +293,7 @@ TEST_F(AlternateFrameSizeButtonTest, RightMouseButton) { // button // - The state of all the caption buttons is reset. // - The icon displayed by all of the caption buttons is reset. -TEST_F(AlternateFrameSizeButtonTest, ResetButtonsAfterClick) { +TEST_F(FrameSizeButtonTest, ResetButtonsAfterClick) { EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); EXPECT_TRUE(AllButtonsInNormalState()); @@ -370,7 +364,7 @@ TEST_F(AlternateFrameSizeButtonTest, ResetButtonsAfterClick) { // Test that the size button is pressed whenever the snap left/right buttons // are hovered. -TEST_F(AlternateFrameSizeButtonTest, SizeButtonPressedWhenSnapButtonHovered) { +TEST_F(FrameSizeButtonTest, SizeButtonPressedWhenSnapButtonHovered) { EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); EXPECT_TRUE(AllButtonsInNormalState()); @@ -406,32 +400,32 @@ TEST_F(AlternateFrameSizeButtonTest, SizeButtonPressedWhenSnapButtonHovered) { EXPECT_EQ(views::Button::STATE_HOVERED, close_button()->state()); } -class AlternateFrameSizeButtonTestRTL : public AlternateFrameSizeButtonTest { +class FrameSizeButtonTestRTL : public FrameSizeButtonTest { public: - AlternateFrameSizeButtonTestRTL() {} - virtual ~AlternateFrameSizeButtonTestRTL() {} + FrameSizeButtonTestRTL() {} + virtual ~FrameSizeButtonTestRTL() {} virtual void SetUp() OVERRIDE { original_locale_ = l10n_util::GetApplicationLocale(std::string()); base::i18n::SetICUDefaultLocale("he"); - AlternateFrameSizeButtonTest::SetUp(); + FrameSizeButtonTest::SetUp(); } virtual void TearDown() OVERRIDE { - AlternateFrameSizeButtonTest::TearDown(); + FrameSizeButtonTest::TearDown(); base::i18n::SetICUDefaultLocale(original_locale_); } private: std::string original_locale_; - DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButtonTestRTL); + DISALLOW_COPY_AND_ASSIGN(FrameSizeButtonTestRTL); }; // Test that clicking + dragging to a button adjacent to the size button presses // the correct button and snaps the window to the correct side. -TEST_F(AlternateFrameSizeButtonTestRTL, ButtonDrag) { +TEST_F(FrameSizeButtonTestRTL, ButtonDrag) { // In RTL the close button should be left of the size button and the minimize // button should be right of the size button. ASSERT_LT(close_button()->GetBoundsInScreen().x(), diff --git a/ash/frame/caption_buttons/maximize_bubble_controller.cc b/ash/frame/caption_buttons/maximize_bubble_controller.cc deleted file mode 100644 index 9b353ddf2c..0000000000 --- a/ash/frame/caption_buttons/maximize_bubble_controller.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/frame/caption_buttons/maximize_bubble_controller.h" - -#include "ash/frame/caption_buttons/frame_maximize_button.h" -#include "ash/frame/caption_buttons/maximize_bubble_controller_bubble.h" -#include "base/timer/timer.h" - - -namespace ash { - -MaximizeBubbleController::MaximizeBubbleController( - FrameMaximizeButton* frame_maximize_button, - MaximizeBubbleFrameState maximize_type, - int appearance_delay_ms) - : frame_maximize_button_(frame_maximize_button), - bubble_(NULL), - maximize_type_(maximize_type), - snap_type_for_creation_(SNAP_NONE), - appearance_delay_ms_(appearance_delay_ms) { - // Create the task which will create the bubble delayed. - base::OneShotTimer<MaximizeBubbleController>* new_timer = - new base::OneShotTimer<MaximizeBubbleController>(); - // Note: Even if there was no delay time given, we need to have a timer. - new_timer->Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds( - appearance_delay_ms_ ? appearance_delay_ms_ : 10), - this, - &MaximizeBubbleController::CreateBubble); - timer_.reset(new_timer); - if (!appearance_delay_ms_) - CreateBubble(); -} - -MaximizeBubbleController::~MaximizeBubbleController() { - // Note: The destructor only gets initiated through the owner. - timer_.reset(); - if (bubble_) { - bubble_->ControllerRequestsCloseAndDelete(); - bubble_ = NULL; - } -} - -void MaximizeBubbleController::SetSnapType(SnapType snap_type) { - if (bubble_) { - bubble_->SetSnapType(snap_type); - } else { - // The bubble has not been created yet. This can occur if bubble creation is - // delayed. - snap_type_for_creation_ = snap_type; - } -} - -aura::Window* MaximizeBubbleController::GetBubbleWindow() { - return bubble_ ? bubble_->GetBubbleWindow() : NULL; -} - -void MaximizeBubbleController::DelayCreation() { - if (timer_.get() && timer_->IsRunning()) - timer_->Reset(); -} - -void MaximizeBubbleController::OnButtonClicked(SnapType snap_type) { - frame_maximize_button_->ExecuteSnapAndCloseMenu(snap_type); -} - -void MaximizeBubbleController::OnButtonHover(SnapType snap_type) { - frame_maximize_button_->SnapButtonHovered(snap_type); -} - -views::CustomButton* MaximizeBubbleController::GetButtonForUnitTest( - SnapType state) { - return bubble_ ? bubble_->GetButtonForUnitTest(state) : NULL; -} - -void MaximizeBubbleController::RequestDestructionThroughOwner() { - // Tell the parent to destroy us (if this didn't happen yet). - if (timer_) { - timer_.reset(NULL); - // Informs the owner that the menu is gone and requests |this| destruction. - frame_maximize_button_->DestroyMaximizeMenu(); - // Note: After this call |this| is destroyed. - } -} - -void MaximizeBubbleController::CreateBubble() { - if (!bubble_) { - bubble_ = new MaximizeBubbleControllerBubble(this, appearance_delay_ms_, - snap_type_for_creation_); - frame_maximize_button_->OnMaximizeBubbleShown(bubble_->GetWidget()); - } - - timer_->Stop(); -} - -} // namespace ash diff --git a/ash/frame/caption_buttons/maximize_bubble_controller.h b/ash/frame/caption_buttons/maximize_bubble_controller.h deleted file mode 100644 index 4ed03b8be3..0000000000 --- a/ash/frame/caption_buttons/maximize_bubble_controller.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_FRAME_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ -#define ASH_FRAME_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "ash/frame/caption_buttons/caption_button_types.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/memory/scoped_ptr.h" - -namespace aura { -class Window; -} - -namespace base { -class Timer; -} - -namespace views { -class CustomButton; -} - -namespace ash { - -class FrameMaximizeButton; -class MaximizeBubbleControllerBubble; - -// A class which shows a helper UI for the maximize button after a delay. -class ASH_EXPORT MaximizeBubbleController { - public: - MaximizeBubbleController(FrameMaximizeButton* frame_maximize_button, - MaximizeBubbleFrameState maximize_type, - int appearance_delay_ms); - // Called from the outside to destroy the interface to the UI visuals. - // The visuals will then delete when possible (maybe asynchronously). - virtual ~MaximizeBubbleController(); - - // Update the UI visuals to reflect the previewed |snap_type| snapping state. - void SetSnapType(SnapType snap_type); - - // To achieve proper Z-sorting with the snap animation, this window will be - // presented above the phantom window. - aura::Window* GetBubbleWindow(); - - // Reset the delay of the menu creation (if it was not created yet). - void DelayCreation(); - - // Called to tell the owning FrameMaximizeButton that a button was clicked. - void OnButtonClicked(SnapType snap_type); - - // Called to tell the the owning FrameMaximizeButton that the hover status - // for a button has changed. |snap_type| can be either SNAP_LEFT, SNAP_RIGHT, - // SNAP_MINIMIZE or SNAP_NONE. - void OnButtonHover(SnapType snap_type); - - // Get the owning FrameMaximizeButton. - FrameMaximizeButton* frame_maximize_button() { - return frame_maximize_button_; - } - - // The status of the associated window: Maximized or normal. - MaximizeBubbleFrameState maximize_type() const { return maximize_type_; } - - // A unit test function to return buttons of the sub menu. |state| can be - // either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - // Called from the the Bubble class to destroy itself: It tells the owning - // object that it will destroy itself asynchronously. The owner will then - // destroy |this|. - void RequestDestructionThroughOwner(); - - private: - // The function which creates the bubble once the delay is elapsed. - void CreateBubble(); - - // The owning button which is also the anchor for the menu. - FrameMaximizeButton* frame_maximize_button_; - - // The bubble menu. - MaximizeBubbleControllerBubble* bubble_; - - // The current maximize state of the owning window. - const MaximizeBubbleFrameState maximize_type_; - - // The snap type with which the bubble is created. This is needed because the - // creation of the bubble can be delayed and SetSnapType() may be called - // before the bubble is created. - SnapType snap_type_for_creation_; - - // The timer for the delayed creation of the menu. - scoped_ptr<base::Timer> timer_; - - // The appearance delay in ms (delay and fade in & fade out delay). - const int appearance_delay_ms_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleController); -}; - -} // namespace ash - -#endif // ASH_FRAME_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ diff --git a/ash/frame/caption_buttons/maximize_bubble_controller_bubble.cc b/ash/frame/caption_buttons/maximize_bubble_controller_bubble.cc deleted file mode 100644 index e8188cd840..0000000000 --- a/ash/frame/caption_buttons/maximize_bubble_controller_bubble.cc +++ /dev/null @@ -1,510 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/frame/caption_buttons/maximize_bubble_controller_bubble.h" - -#include "ash/frame/caption_buttons/bubble_contents_button_row.h" -#include "ash/frame/caption_buttons/frame_maximize_button.h" -#include "ash/frame/caption_buttons/maximize_bubble_controller.h" -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "grit/ash_strings.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/path.h" -#include "ui/views/bubble/bubble_frame_view.h" -#include "ui/views/controls/label.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/mouse_watcher.h" -#include "ui/wm/core/masked_window_targeter.h" - -namespace ash { - -// BubbleContentsView --------------------------------------------------------- - -// A class which creates the content of the bubble: The buttons, and the label. -class BubbleContentsView : public views::View { - public: - BubbleContentsView(MaximizeBubbleControllerBubble* bubble, - SnapType initial_snap_type); - virtual ~BubbleContentsView(); - - // Set the label content to reflect the currently selected |snap_type|. - // This function can be executed through the frame maximize button as well as - // through hover operations. - void SetSnapType(SnapType snap_type); - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - private: - // The owning class. - MaximizeBubbleControllerBubble* bubble_; - - // The object which owns all the buttons. - BubbleContentsButtonRow* buttons_view_; - - // The label object which shows the user the selected action. - views::Label* label_view_; - - DISALLOW_COPY_AND_ASSIGN(BubbleContentsView); -}; - -BubbleContentsView::BubbleContentsView( - MaximizeBubbleControllerBubble* bubble, - SnapType initial_snap_type) - : bubble_(bubble), - buttons_view_(NULL), - label_view_(NULL) { - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kVertical, 0, 0, - MaximizeBubbleControllerBubble::kLayoutSpacing)); - set_background(views::Background::CreateSolidBackground( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor)); - - buttons_view_ = new BubbleContentsButtonRow(bubble); - AddChildView(buttons_view_); - - label_view_ = new views::Label(); - SetSnapType(initial_snap_type); - label_view_->SetBackgroundColor( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - const SkColor kBubbleTextColor = SK_ColorWHITE; - label_view_->SetEnabledColor(kBubbleTextColor); - const int kLabelSpacing = 4; - label_view_->SetBorder( - views::Border::CreateEmptyBorder(kLabelSpacing, 0, kLabelSpacing, 0)); - AddChildView(label_view_); -} - -BubbleContentsView::~BubbleContentsView() { -} - -// Set the label content to reflect the currently selected |snap_type|. -// This function can be executed through the frame maximize button as well as -// through hover operations. -void BubbleContentsView::SetSnapType(SnapType snap_type) { - if (!bubble_->controller()) - return; - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - int id = 0; - switch (snap_type) { - case SNAP_LEFT: - id = IDS_ASH_SNAP_WINDOW_LEFT; - break; - case SNAP_RIGHT: - id = IDS_ASH_SNAP_WINDOW_RIGHT; - break; - case SNAP_MAXIMIZE: - DCHECK_NE(FRAME_STATE_FULL, bubble_->controller()->maximize_type()); - id = IDS_ASH_MAXIMIZE_WINDOW; - break; - case SNAP_MINIMIZE: - id = IDS_ASH_MINIMIZE_WINDOW; - break; - case SNAP_RESTORE: - DCHECK_NE(FRAME_STATE_NONE, bubble_->controller()->maximize_type()); - id = IDS_ASH_RESTORE_WINDOW; - break; - default: - // If nothing is selected, we automatically select the click operation. - id = bubble_->controller()->maximize_type() == FRAME_STATE_FULL ? - IDS_ASH_RESTORE_WINDOW : IDS_ASH_MAXIMIZE_WINDOW; - break; - } - label_view_->SetText(rb.GetLocalizedString(id)); -} - -views::CustomButton* BubbleContentsView::GetButtonForUnitTest(SnapType state) { - return buttons_view_->GetButtonForUnitTest(state); -} - - -// MaximizeBubbleBorder ------------------------------------------------------- - -namespace { - -const int kLineWidth = 1; -const int kArrowHeight = 10; -const int kArrowWidth = 20; - -} // namespace - -class MaximizeBubbleBorder : public views::BubbleBorder { - public: - MaximizeBubbleBorder(views::View* content_view, views::View* anchor); - - virtual ~MaximizeBubbleBorder() {} - - // Get the mouse active area of the window. - void GetMask(gfx::Path* mask); - - // views::BubbleBorder: - virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const OVERRIDE; - virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE; - virtual gfx::Size GetMinimumSize() const OVERRIDE; - - private: - // Note: Animations can continue after then main window frame was destroyed. - // To avoid this problem, the owning screen metrics get extracted upon - // creation. - gfx::Size anchor_size_; - gfx::Point anchor_screen_origin_; - views::View* content_view_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleBorder); -}; - -MaximizeBubbleBorder::MaximizeBubbleBorder(views::View* content_view, - views::View* anchor) - : views::BubbleBorder( - views::BubbleBorder::TOP_RIGHT, views::BubbleBorder::NO_SHADOW, - MaximizeBubbleControllerBubble::kBubbleBackgroundColor), - anchor_size_(anchor->size()), - anchor_screen_origin_(0, 0), - content_view_(content_view) { - views::View::ConvertPointToScreen(anchor, &anchor_screen_origin_); - set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); -} - -void MaximizeBubbleBorder::GetMask(gfx::Path* mask) { - gfx::Insets inset = GetInsets(); - // Note: Even though the tip could be added as activatable, it is left out - // since it would not change the action behavior in any way plus it makes - // more sense to keep the focus on the underlying button for clicks. - int left = inset.left() - kLineWidth; - int right = inset.left() + content_view_->width() + kLineWidth; - int top = inset.top() - kLineWidth; - int bottom = inset.top() + content_view_->height() + kLineWidth; - mask->moveTo(left, top); - mask->lineTo(right, top); - mask->lineTo(right, bottom); - mask->lineTo(left, bottom); - mask->lineTo(left, top); - mask->close(); -} - -gfx::Rect MaximizeBubbleBorder::GetBounds( - const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const { - gfx::Size border_size(contents_size); - gfx::Insets insets = GetInsets(); - border_size.Enlarge(insets.width(), insets.height()); - - // Position the bubble to center the box on the anchor. - int x = (anchor_size_.width() - border_size.width()) / 2; - // Position the bubble under the anchor, overlapping the arrow with it. - int y = anchor_size_.height() - insets.top(); - - gfx::Point view_origin(x + anchor_screen_origin_.x(), - y + anchor_screen_origin_.y()); - - return gfx::Rect(view_origin, border_size); -} - -void MaximizeBubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) { - gfx::Insets inset = GetInsets(); - - // Draw the border line around everything. - int y = inset.top(); - // Top - canvas->FillRect(gfx::Rect(inset.left(), - y - kLineWidth, - content_view_->width(), - kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Bottom - canvas->FillRect(gfx::Rect(inset.left(), - y + content_view_->height(), - content_view_->width(), - kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Left - canvas->FillRect(gfx::Rect(inset.left() - kLineWidth, - y - kLineWidth, - kLineWidth, - content_view_->height() + 2 * kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Right - canvas->FillRect(gfx::Rect(inset.left() + content_view_->width(), - y - kLineWidth, - kLineWidth, - content_view_->height() + 2 * kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - - // Draw the arrow afterwards covering the border. - SkPath path; - path.incReserve(4); - // The center of the tip should be in the middle of the button. - int tip_x = inset.left() + content_view_->width() / 2; - int left_base_x = tip_x - kArrowWidth / 2; - int left_base_y = y; - int tip_y = left_base_y - kArrowHeight; - path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); - path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); - path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), - SkIntToScalar(left_base_y)); - - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - canvas->DrawPath(path, paint); -} - -gfx::Size MaximizeBubbleBorder::GetMinimumSize() const { - return gfx::Size(kLineWidth * 2 + kArrowWidth, - std::max(kLineWidth, kArrowHeight) + kLineWidth); -} - -namespace { - -// MaximizebubbleTargeter ----------------------------------------------------- - -// Window targeter used for the bubble. -class MaximizeBubbleTargeter : public ::wm::MaskedWindowTargeter { - public: - MaximizeBubbleTargeter(aura::Window* window, - MaximizeBubbleBorder* border) - : ::wm::MaskedWindowTargeter(window), - border_(border) { - } - - virtual ~MaximizeBubbleTargeter() {} - - private: - // ::wm::MaskedWindowTargeter: - virtual bool GetHitTestMask(aura::Window* window, - gfx::Path* mask) const OVERRIDE { - border_->GetMask(mask); - return true; - } - - MaximizeBubbleBorder* border_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleTargeter); -}; - -} // namespace - - -// BubbleMouseWatcherHost ----------------------------------------------------- - -// The mouse watcher host which makes sure that the bubble does not get closed -// while the mouse cursor is over the maximize button or the balloon content. -// Note: This object gets destroyed when the MouseWatcher gets destroyed. -class BubbleMouseWatcherHost: public views::MouseWatcherHost { - public: - explicit BubbleMouseWatcherHost(MaximizeBubbleControllerBubble* bubble); - virtual ~BubbleMouseWatcherHost(); - - // views::MouseWatcherHost: - virtual bool Contains(const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) OVERRIDE; - private: - MaximizeBubbleControllerBubble* bubble_; - - DISALLOW_COPY_AND_ASSIGN(BubbleMouseWatcherHost); -}; - -BubbleMouseWatcherHost::BubbleMouseWatcherHost( - MaximizeBubbleControllerBubble* bubble) - : bubble_(bubble) { -} - -BubbleMouseWatcherHost::~BubbleMouseWatcherHost() { -} - -bool BubbleMouseWatcherHost::Contains( - const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) { - return bubble_->Contains(screen_point, type); -} - - -// MaximizeBubbleControllerBubble --------------------------------------------- - -// static -const SkColor MaximizeBubbleControllerBubble::kBubbleBackgroundColor = - 0xFF141414; -const int MaximizeBubbleControllerBubble::kLayoutSpacing = -1; - -MaximizeBubbleControllerBubble::MaximizeBubbleControllerBubble( - MaximizeBubbleController* owner, - int appearance_delay_ms, - SnapType initial_snap_type) - : views::BubbleDelegateView(owner->frame_maximize_button(), - views::BubbleBorder::TOP_RIGHT), - shutting_down_(false), - owner_(owner), - contents_view_(NULL), - bubble_border_(NULL), - appearance_delay_ms_(appearance_delay_ms) { - set_margins(gfx::Insets()); - - // The window needs to be owned by the root so that the phantom window does - // not cover it upon animation. - aura::Window* parent = Shell::GetContainer(Shell::GetTargetRootWindow(), - kShellWindowId_ShelfContainer); - set_parent_window(parent); - - set_notify_enter_exit_on_child(true); - set_adjust_if_offscreen(false); - SetPaintToLayer(true); - set_color(kBubbleBackgroundColor); - set_close_on_deactivate(false); - set_background( - views::Background::CreateSolidBackground(kBubbleBackgroundColor)); - - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kVertical, 0, 0, kLayoutSpacing)); - - contents_view_ = new BubbleContentsView(this, initial_snap_type); - AddChildView(contents_view_); - - // Note that the returned widget has an observer which points to our - // functions. - views::Widget* bubble_widget = views::BubbleDelegateView::CreateBubble(this); - bubble_widget->set_focus_on_creation(false); - - SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); - bubble_widget->non_client_view()->frame_view()->set_background(NULL); - - bubble_border_ = new MaximizeBubbleBorder(this, GetAnchorView()); - GetBubbleFrameView()->SetBubbleBorder( - scoped_ptr<views::BubbleBorder>(bubble_border_)); - GetBubbleFrameView()->set_background(NULL); - - // Recalculate size with new border. - SizeToContents(); - - GetWidget()->Show(); - - aura::Window* window = bubble_widget->GetNativeWindow(); - window->SetEventTargeter(scoped_ptr<ui::EventTargeter>( - new MaximizeBubbleTargeter(window, bubble_border_))); - - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( - ash::UMA_WINDOW_MAXIMIZE_BUTTON_SHOW_BUBBLE); - - mouse_watcher_.reset(new views::MouseWatcher( - new BubbleMouseWatcherHost(this), - this)); - mouse_watcher_->Start(); -} - -MaximizeBubbleControllerBubble::~MaximizeBubbleControllerBubble() { -} - -aura::Window* MaximizeBubbleControllerBubble::GetBubbleWindow() { - return GetWidget()->GetNativeWindow(); -} - -gfx::Rect MaximizeBubbleControllerBubble::GetAnchorRect() { - if (!owner_) - return gfx::Rect(); - - gfx::Rect anchor_rect = - owner_->frame_maximize_button()->GetBoundsInScreen(); - return anchor_rect; -} - -bool MaximizeBubbleControllerBubble::CanActivate() const { - return false; -} - -bool MaximizeBubbleControllerBubble::WidgetHasHitTestMask() const { - return bubble_border_ != NULL; -} - -void MaximizeBubbleControllerBubble::GetWidgetHitTestMask( - gfx::Path* mask) const { - DCHECK(mask); - DCHECK(bubble_border_); - bubble_border_->GetMask(mask); -} - -void MaximizeBubbleControllerBubble::MouseMovedOutOfHost() { - if (!owner_ || shutting_down_) - return; - // When we leave the bubble, we might be still be in gesture mode or over - // the maximize button. So only close if none of the other cases apply. - if (!owner_->frame_maximize_button()->is_snap_enabled()) { - gfx::Point screen_location = Shell::GetScreen()->GetCursorScreenPoint(); - if (!owner_->frame_maximize_button()->GetBoundsInScreen().Contains( - screen_location)) { - owner_->RequestDestructionThroughOwner(); - } - } -} - -bool MaximizeBubbleControllerBubble::Contains( - const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) { - if (!owner_ || shutting_down_) - return false; - bool inside_button = - owner_->frame_maximize_button()->GetBoundsInScreen().Contains( - screen_point); - if (!owner_->frame_maximize_button()->is_snap_enabled() && inside_button) { - SetSnapType(controller()->maximize_type() == FRAME_STATE_FULL ? - SNAP_RESTORE : SNAP_MAXIMIZE); - return true; - } - // Check if either a gesture is taking place (=> bubble stays no matter what - // the mouse does) or the mouse is over the maximize button or the bubble - // content. - return (owner_->frame_maximize_button()->is_snap_enabled() || - inside_button || - contents_view_->GetBoundsInScreen().Contains(screen_point)); -} - -gfx::Size MaximizeBubbleControllerBubble::GetPreferredSize() { - return contents_view_->GetPreferredSize(); -} - -void MaximizeBubbleControllerBubble::OnWidgetDestroying(views::Widget* widget) { - if (GetWidget() == widget) { - mouse_watcher_->Stop(); - - if (owner_) { - // If the bubble destruction was triggered by some other external - // influence then ourselves, the owner needs to be informed that the menu - // is gone. - shutting_down_ = true; - owner_->RequestDestructionThroughOwner(); - owner_ = NULL; - } - } - BubbleDelegateView::OnWidgetDestroying(widget); -} - -void MaximizeBubbleControllerBubble::ControllerRequestsCloseAndDelete() { - // This only gets called from the owning base class once it is deleted. - if (shutting_down_) - return; - shutting_down_ = true; - owner_ = NULL; - - // Close the widget asynchronously after the hide animation is finished. - if (!appearance_delay_ms_) - GetWidget()->CloseNow(); - else - GetWidget()->Close(); -} - -void MaximizeBubbleControllerBubble::SetSnapType(SnapType snap_type) { - if (contents_view_) - contents_view_->SetSnapType(snap_type); -} - -views::CustomButton* MaximizeBubbleControllerBubble::GetButtonForUnitTest( - SnapType state) { - return contents_view_->GetButtonForUnitTest(state); -} - -} // namespace ash diff --git a/ash/frame/caption_buttons/maximize_bubble_controller_bubble.h b/ash/frame/caption_buttons/maximize_bubble_controller_bubble.h deleted file mode 100644 index f2e25d6fdc..0000000000 --- a/ash/frame/caption_buttons/maximize_bubble_controller_bubble.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_FRAME_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ -#define ASH_FRAME_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ - -#include "ash/wm/workspace/snap_types.h" -#include "ui/views/bubble/bubble_delegate.h" -#include "ui/views/mouse_watcher.h" - -namespace views { -class CustomButton; -} - -namespace ash { - -class BubbleContentsView; -class MaximizeBubbleBorder; -class MaximizeBubbleController; - -// The class which creates and manages the bubble menu element. -// It creates a 'bubble border' and the content accordingly. -// Note: Since the phantom window will show animations on top of the maximize -// button this menu gets created as a separate window and the phantom window -// will be created underneath this window. -class MaximizeBubbleControllerBubble : public views::BubbleDelegateView, - public views::MouseWatcherListener { - public: - static const SkColor kBubbleBackgroundColor; - static const int kLayoutSpacing; // The spacing between two buttons. - - MaximizeBubbleControllerBubble(MaximizeBubbleController* owner, - int appearance_delay_ms, - SnapType initial_snap_type); - virtual ~MaximizeBubbleControllerBubble(); - - // The window of the menu under which the phantom window will get created. - aura::Window* GetBubbleWindow(); - - // Overridden from views::BubbleDelegateView. - virtual gfx::Rect GetAnchorRect() OVERRIDE; - virtual bool CanActivate() const OVERRIDE; - - // Overridden from views::WidgetDelegateView. - virtual bool WidgetHasHitTestMask() const OVERRIDE; - virtual void GetWidgetHitTestMask(gfx::Path* mask) const OVERRIDE; - - // Implementation of MouseWatcherListener. - virtual void MouseMovedOutOfHost() OVERRIDE; - - // Implementation of MouseWatcherHost. - virtual bool Contains(const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type); - - // Overridden from views::View. - virtual gfx::Size GetPreferredSize() OVERRIDE; - - // Overridden from views::Widget::Observer. - virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; - - // Called from the controller class to indicate that the menu should get - // destroyed. - virtual void ControllerRequestsCloseAndDelete(); - - // Called from the owning class to change the menu content to the given - // |snap_type| so that the user knows what is selected. - void SetSnapType(SnapType snap_type); - - // Get the owning MaximizeBubbleController. This might return NULL in case - // of an asynchronous shutdown. - MaximizeBubbleController* controller() const { return owner_; } - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - private: - // True if the shut down has been initiated. - bool shutting_down_; - - // Our owning class. - MaximizeBubbleController* owner_; - - // The content accessor of the menu. - BubbleContentsView* contents_view_; - - // The bubble border (weak reference). - MaximizeBubbleBorder* bubble_border_; - - // The mouse watcher which takes care of out of window hover events. - scoped_ptr<views::MouseWatcher> mouse_watcher_; - - // The fade delay - if 0 it will show / hide immediately. - const int appearance_delay_ms_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleControllerBubble); -}; - -} // namespace ash - -#endif // ASH_FRAME_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ diff --git a/ash/frame/custom_frame_view_ash.cc b/ash/frame/custom_frame_view_ash.cc index 8ab7e23be8..68bc36a85c 100644 --- a/ash/frame/custom_frame_view_ash.cc +++ b/ash/frame/custom_frame_view_ash.cc @@ -6,8 +6,6 @@ #include "ash/ash_switches.h" #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" -#include "ash/frame/caption_buttons/frame_maximize_button.h" -#include "ash/frame/caption_buttons/frame_maximize_button_observer.h" #include "ash/frame/default_header_painter.h" #include "ash/frame/frame_border_hit_test_controller.h" #include "ash/frame/frame_util.h" @@ -32,7 +30,6 @@ #include "ui/views/view.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" -#include "ui/views/widget/widget_deletion_observer.h" namespace { @@ -127,7 +124,6 @@ namespace ash { class CustomFrameViewAsh::HeaderView : public views::View, public ImmersiveFullscreenController::Delegate, - public FrameMaximizeButtonObserver, public ShellObserver { public: // |frame| is the widget that the caption buttons act on. @@ -175,9 +171,6 @@ class CustomFrameViewAsh::HeaderView virtual void SetVisibleFraction(double visible_fraction) OVERRIDE; virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const OVERRIDE; - // FrameMaximizeButtonObserver: - virtual void OnMaximizeBubbleShown(views::Widget* bubble) OVERRIDE; - // The widget that the caption buttons act on. views::Widget* frame_; @@ -189,13 +182,6 @@ class CustomFrameViewAsh::HeaderView // View which contains the window caption buttons. FrameCaptionButtonContainerView* caption_button_container_; - // The maximize bubble widget. |maximize_bubble_| may be non-NULL but have - // been already destroyed. - views::Widget* maximize_bubble_; - - // Keeps track of whether |maximize_bubble_| is still alive. - scoped_ptr<views::WidgetDeletionObserver> maximize_bubble_lifetime_observer_; - // The fraction of the header's height which is visible while in fullscreen. // This value is meaningless when not in fullscreen. double fullscreen_visible_fraction_; @@ -208,7 +194,6 @@ CustomFrameViewAsh::HeaderView::HeaderView(views::Widget* frame) header_painter_(new ash::DefaultHeaderPainter), avatar_icon_(NULL), caption_button_container_(NULL), - maximize_bubble_(NULL), fullscreen_visible_fraction_(0) { // Unfortunately, there is no views::WidgetDelegate::CanMinimize(). Assume // that the window frame can be minimized if it can be maximized. @@ -221,10 +206,6 @@ CustomFrameViewAsh::HeaderView::HeaderView(views::Widget* frame) caption_button_container_->UpdateSizeButtonVisibility(Shell::GetInstance()-> IsMaximizeModeWindowManagerEnabled()); AddChildView(caption_button_container_); - FrameMaximizeButton* frame_maximize_button = - caption_button_container_->GetOldStyleSizeButton(); - if (frame_maximize_button) - frame_maximize_button->AddObserver(this); header_painter_->Init(frame_, this, NULL, caption_button_container_); UpdateAvatarIcon(); @@ -233,10 +214,6 @@ CustomFrameViewAsh::HeaderView::HeaderView(views::Widget* frame) } CustomFrameViewAsh::HeaderView::~HeaderView() { - FrameMaximizeButton* frame_maximize_button = - caption_button_container_->GetOldStyleSizeButton(); - if (frame_maximize_button) - frame_maximize_button->RemoveObserver(this); Shell::GetInstance()->RemoveShellObserver(this); } @@ -361,24 +338,10 @@ CustomFrameViewAsh::HeaderView::GetVisibleBoundsInScreen() const { std::vector<gfx::Rect> bounds_in_screen; bounds_in_screen.push_back( gfx::Rect(visible_origin_in_screen, visible_bounds.size())); - if (maximize_bubble_lifetime_observer_.get() && - maximize_bubble_lifetime_observer_->IsWidgetAlive()) { - bounds_in_screen.push_back(maximize_bubble_->GetWindowBoundsInScreen()); - } return bounds_in_screen; } /////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh::HeaderView, FrameMaximizeButtonObserver overrides: - -void CustomFrameViewAsh::HeaderView::OnMaximizeBubbleShown( - views::Widget* bubble) { - maximize_bubble_ = bubble; - maximize_bubble_lifetime_observer_.reset( - new views::WidgetDeletionObserver(bubble)); -} - -/////////////////////////////////////////////////////////////////////////////// // CustomFrameViewAsh::OverlayView // View which takes up the entire widget and contains the HeaderView. HeaderView diff --git a/ash/ime/infolist_window.cc b/ash/ime/infolist_window.cc index e48e88e2e6..c29d623b07 100644 --- a/ash/ime/infolist_window.cc +++ b/ash/ime/infolist_window.cc @@ -172,7 +172,6 @@ InfolistWindow::InfolistWindow(views::View* candidate_window, title_font_list_(gfx::Font(kJapaneseFontName, kFontSizeDelta + 15)), description_font_list_(gfx::Font(kJapaneseFontName, kFontSizeDelta + 11)) { - set_move_with_anchor(true); set_margins(gfx::Insets()); set_background( diff --git a/ash/media_delegate.h b/ash/media_delegate.h index 1dac059254..4ea9a17a04 100644 --- a/ash/media_delegate.h +++ b/ash/media_delegate.h @@ -5,8 +5,19 @@ #ifndef ASH_MEDIA_DELEGATE_H_ #define ASH_MEDIA_DELEGATE_H_ +namespace content { +class BrowserContext; +} + namespace ash { +enum MediaCaptureState { + MEDIA_CAPTURE_NONE = 0, + MEDIA_CAPTURE_AUDIO = 1 << 0, + MEDIA_CAPTURE_VIDEO = 1 << 1, + MEDIA_CAPTURE_AUDIO_VIDEO = MEDIA_CAPTURE_AUDIO | MEDIA_CAPTURE_VIDEO, +}; + // A delegate class to control media playback. class MediaDelegate { public: @@ -20,6 +31,11 @@ class MediaDelegate { // Handles the Previous Track Media shortcut key. virtual void HandleMediaPrevTrack() = 0; + + // Returns the current media recording state of web contents + // that belongs to the |context|. + virtual MediaCaptureState GetMediaCaptureState( + content::BrowserContext* context) = 0; }; } // namespace ash diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc index a71271bec0..a44cc78850 100644 --- a/ash/metrics/user_metrics_recorder.cc +++ b/ash/metrics/user_metrics_recorder.cc @@ -357,24 +357,12 @@ void UserMetricsRecorder::RecordUserMetricsAction(UserMetricsAction action) { case ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE: base::RecordAction(base::UserMetricsAction("MinButton_Clk")); break; - case ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE: - base::RecordAction(base::UserMetricsAction("MaxButton_Maximize")); - break; case ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT: base::RecordAction(base::UserMetricsAction("MaxButton_MaxLeft")); break; case ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT: base::RecordAction(base::UserMetricsAction("MaxButton_MaxRight")); break; - case ash::UMA_WINDOW_MAXIMIZE_BUTTON_MINIMIZE: - base::RecordAction(base::UserMetricsAction("MaxButton_Minimize")); - break; - case ash::UMA_WINDOW_MAXIMIZE_BUTTON_RESTORE: - base::RecordAction(base::UserMetricsAction("MaxButton_Restore")); - break; - case ash::UMA_WINDOW_MAXIMIZE_BUTTON_SHOW_BUBBLE: - base::RecordAction(base::UserMetricsAction("MaxButton_ShowBubble")); - break; case ash::UMA_WINDOW_OVERVIEW: base::RecordAction( base::UserMetricsAction("WindowSelector_Overview")); diff --git a/ash/metrics/user_metrics_recorder.h b/ash/metrics/user_metrics_recorder.h index 618b70f4a0..98eb6524bc 100644 --- a/ash/metrics/user_metrics_recorder.h +++ b/ash/metrics/user_metrics_recorder.h @@ -97,12 +97,8 @@ enum UserMetricsAction { UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE, UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE, UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE, - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE, UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT, UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT, - UMA_WINDOW_MAXIMIZE_BUTTON_MINIMIZE, - UMA_WINDOW_MAXIMIZE_BUTTON_RESTORE, - UMA_WINDOW_MAXIMIZE_BUTTON_SHOW_BUBBLE, // Thumbnail sized overview of windows triggered. This is a subset of // UMA_WINDOW_SELECTION triggered by lingering during alt+tab cycles or diff --git a/ash/resources/ash_resources.grd b/ash/resources/ash_resources.grd index 12017454b6..825cadedc1 100644 --- a/ash/resources/ash_resources.grd +++ b/ash/resources/ash_resources.grd @@ -77,6 +77,7 @@ <structure type="chrome_scaled_image" name="IDR_AURA_WARNING_ICON" file="common/alert_small.png" /> + <!-- TODO(oshima): Make following resources cros only --> <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_ACCESSIBILITY" file="cros/status/status_accessibility_mode.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_ACCESSIBILITY_DARK" file="cros/status/status_accessibility_dark.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_BLUETOOTH" file="cros/status/status_bluetooth.png" /> @@ -187,6 +188,8 @@ <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_VPN" file="cros/network/statusbar_vpn_dark.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE" file="cros/network/statusbar_network_vpn_badge.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_WIRED" file="cros/network/statusbar_wired.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_RECORDING" file="cros/status/status_recording.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_RECORDING_RED" file="cros/status/status_recording_red.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_VIRTUAL_KEYBOARD" file="cros/status/status_virtual_keyboard.png" /> </if> @@ -238,21 +241,6 @@ <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_OVERVIEW_CLOSE_H" file="common/window_overview_close_hover.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_OVERVIEW_CLOSE_P" file="common/window_overview_close_pressed.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_LEFT" file="common/window_position_left_normal.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_LEFT_H" file="common/window_position_left_hover.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_LEFT_P" file="common/window_position_left_pressed.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_MIDDLE" file="common/window_position_middle_normal.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_MIDDLE_H" file="common/window_position_middle_hover.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_MIDDLE_P" file="common/window_position_middle_pressed.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_RIGHT" file="common/window_position_right_normal.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_RIGHT_H" file="common/window_position_right_hover.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_RIGHT_P" file="common/window_position_right_pressed.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_LEFT_RESTORE" file="common/window_position_left_normal_restore.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_LEFT_RESTORE_H" file="common/window_position_left_hover_restore.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_LEFT_RESTORE_P" file="common/window_position_left_pressed_restore.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE" file="common/window_position_right_normal_restore.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE_H" file="common/window_position_right_hover_restore.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE_P" file="common/window_position_right_pressed_restore.png" /> <structure type="chrome_scaled_image" name="IDR_AVATAR_HOLDER" file="cros/avatar_holder.png" /> <structure type="chrome_scaled_image" name="IDR_AVATAR_HOLDER_MASK" file="cros/avatar_holder_mask.png" /> </structures> diff --git a/ash/resources/default_100_percent/common/window_position_left_hover.png b/ash/resources/default_100_percent/common/window_position_left_hover.png Binary files differdeleted file mode 100644 index 420d392031..0000000000 --- a/ash/resources/default_100_percent/common/window_position_left_hover.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_left_hover_restore.png b/ash/resources/default_100_percent/common/window_position_left_hover_restore.png Binary files differdeleted file mode 100644 index f94002b846..0000000000 --- a/ash/resources/default_100_percent/common/window_position_left_hover_restore.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_left_normal.png b/ash/resources/default_100_percent/common/window_position_left_normal.png Binary files differdeleted file mode 100644 index c082951044..0000000000 --- a/ash/resources/default_100_percent/common/window_position_left_normal.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_left_normal_restore.png b/ash/resources/default_100_percent/common/window_position_left_normal_restore.png Binary files differdeleted file mode 100644 index 67312ab160..0000000000 --- a/ash/resources/default_100_percent/common/window_position_left_normal_restore.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_left_pressed.png b/ash/resources/default_100_percent/common/window_position_left_pressed.png Binary files differdeleted file mode 100644 index 4201d2a904..0000000000 --- a/ash/resources/default_100_percent/common/window_position_left_pressed.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_left_pressed_restore.png b/ash/resources/default_100_percent/common/window_position_left_pressed_restore.png Binary files differdeleted file mode 100644 index 88415533c1..0000000000 --- a/ash/resources/default_100_percent/common/window_position_left_pressed_restore.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_middle_hover.png b/ash/resources/default_100_percent/common/window_position_middle_hover.png Binary files differdeleted file mode 100644 index aaff1c59c8..0000000000 --- a/ash/resources/default_100_percent/common/window_position_middle_hover.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_middle_normal.png b/ash/resources/default_100_percent/common/window_position_middle_normal.png Binary files differdeleted file mode 100644 index 090b6699fe..0000000000 --- a/ash/resources/default_100_percent/common/window_position_middle_normal.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_middle_pressed.png b/ash/resources/default_100_percent/common/window_position_middle_pressed.png Binary files differdeleted file mode 100644 index 66d29b0d95..0000000000 --- a/ash/resources/default_100_percent/common/window_position_middle_pressed.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_right_hover.png b/ash/resources/default_100_percent/common/window_position_right_hover.png Binary files differdeleted file mode 100644 index e424d95012..0000000000 --- a/ash/resources/default_100_percent/common/window_position_right_hover.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_right_hover_restore.png b/ash/resources/default_100_percent/common/window_position_right_hover_restore.png Binary files differdeleted file mode 100644 index 7583d26b72..0000000000 --- a/ash/resources/default_100_percent/common/window_position_right_hover_restore.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_right_normal.png b/ash/resources/default_100_percent/common/window_position_right_normal.png Binary files differdeleted file mode 100644 index d2c4479136..0000000000 --- a/ash/resources/default_100_percent/common/window_position_right_normal.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_right_normal_restore.png b/ash/resources/default_100_percent/common/window_position_right_normal_restore.png Binary files differdeleted file mode 100644 index 9da076101c..0000000000 --- a/ash/resources/default_100_percent/common/window_position_right_normal_restore.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_right_pressed.png b/ash/resources/default_100_percent/common/window_position_right_pressed.png Binary files differdeleted file mode 100644 index 7fa9303bfb..0000000000 --- a/ash/resources/default_100_percent/common/window_position_right_pressed.png +++ /dev/null diff --git a/ash/resources/default_100_percent/common/window_position_right_pressed_restore.png b/ash/resources/default_100_percent/common/window_position_right_pressed_restore.png Binary files differdeleted file mode 100644 index 790ee0e572..0000000000 --- a/ash/resources/default_100_percent/common/window_position_right_pressed_restore.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_left_hover.png b/ash/resources/default_200_percent/common/window_position_left_hover.png Binary files differdeleted file mode 100644 index 4d79bb222f..0000000000 --- a/ash/resources/default_200_percent/common/window_position_left_hover.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_left_hover_restore.png b/ash/resources/default_200_percent/common/window_position_left_hover_restore.png Binary files differdeleted file mode 100644 index 61c5387687..0000000000 --- a/ash/resources/default_200_percent/common/window_position_left_hover_restore.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_left_normal.png b/ash/resources/default_200_percent/common/window_position_left_normal.png Binary files differdeleted file mode 100644 index 58e21b9967..0000000000 --- a/ash/resources/default_200_percent/common/window_position_left_normal.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_left_normal_restore.png b/ash/resources/default_200_percent/common/window_position_left_normal_restore.png Binary files differdeleted file mode 100644 index bba0ff421a..0000000000 --- a/ash/resources/default_200_percent/common/window_position_left_normal_restore.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_left_pressed.png b/ash/resources/default_200_percent/common/window_position_left_pressed.png Binary files differdeleted file mode 100644 index b7fae08964..0000000000 --- a/ash/resources/default_200_percent/common/window_position_left_pressed.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png b/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png Binary files differdeleted file mode 100644 index 0f9e0c92ac..0000000000 --- a/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_middle_hover.png b/ash/resources/default_200_percent/common/window_position_middle_hover.png Binary files differdeleted file mode 100644 index fe65289b18..0000000000 --- a/ash/resources/default_200_percent/common/window_position_middle_hover.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_middle_normal.png b/ash/resources/default_200_percent/common/window_position_middle_normal.png Binary files differdeleted file mode 100644 index 0cda265b27..0000000000 --- a/ash/resources/default_200_percent/common/window_position_middle_normal.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_middle_pressed.png b/ash/resources/default_200_percent/common/window_position_middle_pressed.png Binary files differdeleted file mode 100644 index f664867493..0000000000 --- a/ash/resources/default_200_percent/common/window_position_middle_pressed.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_right_hover.png b/ash/resources/default_200_percent/common/window_position_right_hover.png Binary files differdeleted file mode 100644 index e31c7294ab..0000000000 --- a/ash/resources/default_200_percent/common/window_position_right_hover.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_right_hover_restore.png b/ash/resources/default_200_percent/common/window_position_right_hover_restore.png Binary files differdeleted file mode 100644 index e5a5be33ca..0000000000 --- a/ash/resources/default_200_percent/common/window_position_right_hover_restore.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_right_normal.png b/ash/resources/default_200_percent/common/window_position_right_normal.png Binary files differdeleted file mode 100644 index 1a8e7a24b9..0000000000 --- a/ash/resources/default_200_percent/common/window_position_right_normal.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_right_normal_restore.png b/ash/resources/default_200_percent/common/window_position_right_normal_restore.png Binary files differdeleted file mode 100644 index 3cf2d4b783..0000000000 --- a/ash/resources/default_200_percent/common/window_position_right_normal_restore.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_right_pressed.png b/ash/resources/default_200_percent/common/window_position_right_pressed.png Binary files differdeleted file mode 100644 index b5e533657e..0000000000 --- a/ash/resources/default_200_percent/common/window_position_right_pressed.png +++ /dev/null diff --git a/ash/resources/default_200_percent/common/window_position_right_pressed_restore.png b/ash/resources/default_200_percent/common/window_position_right_pressed_restore.png Binary files differdeleted file mode 100644 index 62bb151bdd..0000000000 --- a/ash/resources/default_200_percent/common/window_position_right_pressed_restore.png +++ /dev/null diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index 368dd92fe9..2bcec0cd32 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc @@ -28,6 +28,7 @@ #include "ash/switchable_windows.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/system_tray_delegate.h" +#include "ash/system/tray/system_tray_notifier.h" #include "ash/touch/touch_hud_debug.h" #include "ash/touch/touch_hud_projection.h" #include "ash/touch/touch_observer_hud.h" @@ -74,7 +75,9 @@ #include "ui/wm/public/window_types.h" #if defined(OS_CHROMEOS) +#include "ash/system/tray_accessibility.h" #include "ash/wm/boot_splash_screen_chromeos.h" +#include "ui/chromeos/touch_exploration_controller.h" #endif namespace ash { @@ -257,6 +260,54 @@ class EmptyWindowDelegate : public aura::WindowDelegate { DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate); }; +#if defined(OS_CHROMEOS) +// Responsible for initializing TouchExplorationController when spoken +// feedback is on. +class CrosAccessibilityObserver : public AccessibilityObserver { + public: + explicit CrosAccessibilityObserver( + RootWindowController* root_window_controller) + : root_window_controller_(root_window_controller) { + Shell::GetInstance()->system_tray_notifier()-> + AddAccessibilityObserver(this); + UpdateTouchExplorationState(); + } + + virtual ~CrosAccessibilityObserver() { + SystemTrayNotifier* system_tray_notifier = + Shell::GetInstance()->system_tray_notifier(); + if (system_tray_notifier) + system_tray_notifier->RemoveAccessibilityObserver(this); + } + + private: + void UpdateTouchExplorationState() { + AccessibilityDelegate* delegate = + Shell::GetInstance()->accessibility_delegate(); + bool enabled = delegate->IsSpokenFeedbackEnabled(); + + if (enabled && !touch_exploration_controller_.get()) { + touch_exploration_controller_.reset( + new ui::TouchExplorationController( + root_window_controller_->GetRootWindow())); + } else if (!enabled) { + touch_exploration_controller_.reset(); + } + } + + // Overridden from AccessibilityObserver. + virtual void OnAccessibilityModeChanged( + AccessibilityNotificationVisibility notify) OVERRIDE { + UpdateTouchExplorationState(); + } + + scoped_ptr<ui::TouchExplorationController> touch_exploration_controller_; + RootWindowController* root_window_controller_; + + DISALLOW_COPY_AND_ASSIGN(CrosAccessibilityObserver); +}; +#endif // OS_CHROMEOS + } // namespace void RootWindowController::CreateForPrimaryDisplay(AshWindowTreeHost* host) { @@ -339,7 +390,14 @@ void RootWindowController::SetAnimatingWallpaperController( } void RootWindowController::Shutdown() { - Shell::GetInstance()->RemoveShellObserver(this); + Shell* shell = Shell::GetInstance(); + shell->RemoveShellObserver(this); + +#if defined(OS_CHROMEOS) + if (cros_accessibility_observer_) { + cros_accessibility_observer_.reset(); + } +#endif if (animating_wallpaper_controller_.get()) animating_wallpaper_controller_->StopAnimating(); @@ -351,7 +409,7 @@ void RootWindowController::Shutdown() { // window list adding windows from the target root window's containers which // may have already gone away. if (Shell::GetTargetRootWindow() == root_window) { - Shell::GetInstance()->set_target_root_window( + shell->set_target_root_window( Shell::GetPrimaryRootWindow() == root_window ? NULL : Shell::GetPrimaryRootWindow()); @@ -738,6 +796,13 @@ void RootWindowController::Init(RootWindowType root_window_type, // Notify shell observers about new root window. shell->OnRootWindowAdded(root_window); } + +#if defined(OS_CHROMEOS) + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAshEnableTouchExplorationMode)) { + cros_accessibility_observer_.reset(new CrosAccessibilityObserver(this)); + } +#endif } void RootWindowController::InitLayoutManagers() { diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h index 6199a5cee1..b7a059f0b7 100644 --- a/ash/root_window_controller.h +++ b/ash/root_window_controller.h @@ -68,6 +68,7 @@ class WorkspaceController; #if defined(OS_CHROMEOS) class BootSplashScreen; +class AccessibilityObserver; #endif // This class maintains the per root window state for ash. This class @@ -293,8 +294,12 @@ class ASH_EXPORT RootWindowController : public ShellObserver { PanelLayoutManager* panel_layout_manager_; scoped_ptr<SystemBackgroundController> system_background_; + #if defined(OS_CHROMEOS) scoped_ptr<BootSplashScreen> boot_splash_screen_; + // Responsible for initializing TouchExplorationController when spoken + // feedback is on. + scoped_ptr<AccessibilityObserver> cros_accessibility_observer_; #endif scoped_ptr<ScreenDimmer> screen_dimmer_; diff --git a/ash/session/session_state_delegate_stub.cc b/ash/session/session_state_delegate_stub.cc deleted file mode 100644 index 05bca1389f..0000000000 --- a/ash/session/session_state_delegate_stub.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/session/session_state_delegate_stub.h" - -#include "ash/session/user_info.h" -#include "ash/shell.h" -#include "ash/shell/example_factory.h" -#include "ash/shell_delegate.h" -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "ui/gfx/image/image_skia.h" - -namespace ash { -namespace { - -class UserInfoStub : public UserInfo { - public: - UserInfoStub() {} - virtual ~UserInfoStub() {} - - // UserInfo: - virtual base::string16 GetDisplayName() const OVERRIDE { - return base::UTF8ToUTF16("stub-user"); - } - virtual base::string16 GetGivenName() const OVERRIDE { - return base::UTF8ToUTF16("Stub"); - } - virtual std::string GetEmail() const OVERRIDE { - return "stub-user@domain.com"; - } - virtual std::string GetUserID() const OVERRIDE { return GetEmail(); } - virtual const gfx::ImageSkia& GetImage() const OVERRIDE { - return user_image_; - } - - private: - gfx::ImageSkia user_image_; - - DISALLOW_COPY_AND_ASSIGN(UserInfoStub); -}; - -} // namespace - -SessionStateDelegateStub::SessionStateDelegateStub() - : screen_locked_(false), user_info_(new UserInfoStub()) { -} - -SessionStateDelegateStub::~SessionStateDelegateStub() { -} - -content::BrowserContext* SessionStateDelegateStub::GetBrowserContextByIndex( - MultiProfileIndex index) { - return Shell::GetInstance()->delegate()->GetActiveBrowserContext(); -} - -content::BrowserContext* SessionStateDelegateStub::GetBrowserContextForWindow( - aura::Window* window) { - return Shell::GetInstance()->delegate()->GetActiveBrowserContext(); -} - -int SessionStateDelegateStub::GetMaximumNumberOfLoggedInUsers() const { - return 3; -} - -int SessionStateDelegateStub::NumberOfLoggedInUsers() const { - return 1; -} - -bool SessionStateDelegateStub::IsActiveUserSessionStarted() const { - return true; -} - -bool SessionStateDelegateStub::CanLockScreen() const { - return true; -} - -bool SessionStateDelegateStub::IsScreenLocked() const { - return screen_locked_; -} - -bool SessionStateDelegateStub::ShouldLockScreenBeforeSuspending() const { - return false; -} - -void SessionStateDelegateStub::LockScreen() { - shell::CreateLockScreen(); - screen_locked_ = true; - Shell::GetInstance()->UpdateShelfVisibility(); -} - -void SessionStateDelegateStub::UnlockScreen() { - screen_locked_ = false; - Shell::GetInstance()->UpdateShelfVisibility(); -} - -bool SessionStateDelegateStub::IsUserSessionBlocked() const { - return !IsActiveUserSessionStarted() || IsScreenLocked(); -} - -SessionStateDelegate::SessionState SessionStateDelegateStub::GetSessionState() - const { - // Assume that if session is not active we're at login. - return IsActiveUserSessionStarted() ? SESSION_STATE_ACTIVE - : SESSION_STATE_LOGIN_PRIMARY; -} - -const UserInfo* SessionStateDelegateStub::GetUserInfo( - MultiProfileIndex index) const { - return user_info_.get(); -} - -const UserInfo* SessionStateDelegateStub::GetUserInfo( - content::BrowserContext* context) const { - return user_info_.get(); -} - -bool SessionStateDelegateStub::ShouldShowAvatar(aura::Window* window) const { - return !user_info_->GetImage().isNull(); -} - -void SessionStateDelegateStub::SwitchActiveUser(const std::string& user_id) { -} - -void SessionStateDelegateStub::CycleActiveUser(CycleUser cycle_user) { -} - -void SessionStateDelegateStub::AddSessionStateObserver( - ash::SessionStateObserver* observer) { -} - -void SessionStateDelegateStub::RemoveSessionStateObserver( - ash::SessionStateObserver* observer) { -} - -} // namespace ash diff --git a/ash/session/session_state_delegate_stub.h b/ash/session/session_state_delegate_stub.h deleted file mode 100644 index 5ce9cf3c48..0000000000 --- a/ash/session/session_state_delegate_stub.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SESSION_SESSION_STATE_DELEGATE_STUB_H_ -#define ASH_SESSION_SESSION_STATE_DELEGATE_STUB_H_ - -#include "ash/session/session_state_delegate.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" - -namespace ash { - -// Stub implementation of SessionStateDelegate for testing. -class SessionStateDelegateStub : public SessionStateDelegate { - public: - SessionStateDelegateStub(); - virtual ~SessionStateDelegateStub(); - - // SessionStateDelegate: - virtual content::BrowserContext* GetBrowserContextByIndex( - MultiProfileIndex index) OVERRIDE; - virtual content::BrowserContext* GetBrowserContextForWindow( - aura::Window* window) OVERRIDE; - virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE; - virtual int NumberOfLoggedInUsers() const OVERRIDE; - virtual bool IsActiveUserSessionStarted() const OVERRIDE; - virtual bool CanLockScreen() const OVERRIDE; - virtual bool IsScreenLocked() const OVERRIDE; - virtual bool ShouldLockScreenBeforeSuspending() const OVERRIDE; - virtual void LockScreen() OVERRIDE; - virtual void UnlockScreen() OVERRIDE; - virtual bool IsUserSessionBlocked() const OVERRIDE; - virtual SessionState GetSessionState() const OVERRIDE; - virtual const UserInfo* GetUserInfo(MultiProfileIndex index) const OVERRIDE; - virtual const UserInfo* GetUserInfo( - content::BrowserContext* context) const OVERRIDE; - virtual bool ShouldShowAvatar(aura::Window* window) const OVERRIDE; - virtual void SwitchActiveUser(const std::string& user_id) OVERRIDE; - virtual void CycleActiveUser(CycleUser cycle_user) OVERRIDE; - virtual void AddSessionStateObserver( - ash::SessionStateObserver* observer) OVERRIDE; - virtual void RemoveSessionStateObserver( - ash::SessionStateObserver* observer) OVERRIDE; - - private: - bool screen_locked_; - - // A pseudo user info. - scoped_ptr<UserInfo> user_info_; - - DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateStub); -}; - -} // namespace ash - -#endif // ASH_SESSION_SESSION_STATE_DELEGATE_STUB_H_ diff --git a/ash/shelf/overflow_bubble_view.cc b/ash/shelf/overflow_bubble_view.cc index 1aa025b69c..b165b2d5f6 100644 --- a/ash/shelf/overflow_bubble_view.cc +++ b/ash/shelf/overflow_bubble_view.cc @@ -48,7 +48,6 @@ void OverflowBubbleView::InitOverflowBubble(views::View* anchor, set_background(NULL); set_color(SkColorSetARGB(kShelfBackgroundAlpha, 0, 0, 0)); set_margins(gfx::Insets(kPadding, kPadding, kPadding, kPadding)); - set_move_with_anchor(true); // Overflow bubble should not get focus. If it get focus when it is shown, // active state item is changed to running state. set_use_focusless(true); diff --git a/ash/shelf/shelf_tooltip_manager.cc b/ash/shelf/shelf_tooltip_manager.cc index ecfcaa3c3a..cc80bdba79 100644 --- a/ash/shelf/shelf_tooltip_manager.cc +++ b/ash/shelf/shelf_tooltip_manager.cc @@ -73,8 +73,6 @@ ShelfTooltipManager::ShelfTooltipBubble::ShelfTooltipBubble( views::BubbleBorder::Arrow arrow, ShelfTooltipManager* host) : views::BubbleDelegateView(anchor, arrow), host_(host) { - // Make sure that the bubble follows the animation of the shelf. - set_move_with_anchor(true); gfx::Insets insets = gfx::Insets(kArrowOffsetTopBottom, kArrowOffsetLeftRight, kArrowOffsetTopBottom, diff --git a/ash/shell.cc b/ash/shell.cc index 9f19b1487e..8bd4460802 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -828,7 +828,7 @@ void Shell::Init() { // Env creates the compositor. Historically it seems to have been implicitly // initialized first by the ActivationController, but now that FocusController // no longer does this we need to do it explicitly. - aura::Env::CreateInstance(); + aura::Env::CreateInstance(true); // The WindowModalityController needs to be at the front of the input event // pretarget handler list to ensure that it processes input events when modal diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc index c487ba149b..87d46e807e 100644 --- a/ash/shell/app_list.cc +++ b/ash/shell/app_list.cc @@ -248,6 +248,10 @@ class ExampleAppListViewDelegate : public app_list::AppListViewDelegate { return users_; } + virtual bool ShouldCenterWindow() const OVERRIDE { + return false; + } + virtual app_list::AppListModel* GetModel() OVERRIDE { return model_.get(); } virtual app_list::SigninDelegate* GetSigninDelegate() OVERRIDE { diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc index 2bf14e8d26..289d769c9c 100644 --- a/ash/shell/shell_delegate_impl.cc +++ b/ash/shell/shell_delegate_impl.cc @@ -11,7 +11,7 @@ #include "ash/media_delegate.h" #include "ash/new_window_delegate.h" #include "ash/session/session_state_delegate.h" -#include "ash/session/session_state_delegate_stub.h" +#include "ash/session/user_info.h" #include "ash/shell/context_menu.h" #include "ash/shell/example_factory.h" #include "ash/shell/keyboard_controller_proxy_stub.h" @@ -21,6 +21,7 @@ #include "ash/system/tray/default_system_tray_delegate.h" #include "ash/wm/window_state.h" #include "base/message_loop/message_loop.h" +#include "base/strings/utf_string_conversions.h" #include "ui/aura/window.h" #include "ui/wm/core/input_method_event_filter.h" @@ -33,6 +34,7 @@ class NewWindowDelegateImpl : public NewWindowDelegate { NewWindowDelegateImpl() {} virtual ~NewWindowDelegateImpl() {} + // NewWindowDelegate: virtual void NewTab() OVERRIDE {} virtual void NewWindow(bool incognito) OVERRIDE { ash::shell::ToplevelWindow::CreateParams create_params; @@ -56,14 +58,115 @@ class MediaDelegateImpl : public MediaDelegate { MediaDelegateImpl() {} virtual ~MediaDelegateImpl() {} + // MediaDelegate: virtual void HandleMediaNextTrack() OVERRIDE {} virtual void HandleMediaPlayPause() OVERRIDE {} virtual void HandleMediaPrevTrack() OVERRIDE {} + virtual MediaCaptureState GetMediaCaptureState( + content::BrowserContext* context) OVERRIDE { + return MEDIA_CAPTURE_VIDEO; + } private: DISALLOW_COPY_AND_ASSIGN(MediaDelegateImpl); }; +class UserInfoImpl : public UserInfo { + public: + UserInfoImpl() {} + virtual ~UserInfoImpl() {} + + // UserInfo: + virtual base::string16 GetDisplayName() const OVERRIDE { + return base::UTF8ToUTF16("stub-user"); + } + virtual base::string16 GetGivenName() const OVERRIDE { + return base::UTF8ToUTF16("Stub"); + } + virtual std::string GetEmail() const OVERRIDE { + return "stub-user@domain.com"; + } + virtual std::string GetUserID() const OVERRIDE { return GetEmail(); } + virtual const gfx::ImageSkia& GetImage() const OVERRIDE { + return user_image_; + } + + private: + gfx::ImageSkia user_image_; + + DISALLOW_COPY_AND_ASSIGN(UserInfoImpl); +}; + +class SessionStateDelegateImpl : public SessionStateDelegate { + public: + SessionStateDelegateImpl() + : screen_locked_(false), user_info_(new UserInfoImpl()) {} + + virtual ~SessionStateDelegateImpl() {} + + // SessionStateDelegate: + virtual content::BrowserContext* GetBrowserContextByIndex( + MultiProfileIndex index) OVERRIDE { + return Shell::GetInstance()->delegate()->GetActiveBrowserContext(); + } + virtual content::BrowserContext* GetBrowserContextForWindow( + aura::Window* window) OVERRIDE { + return Shell::GetInstance()->delegate()->GetActiveBrowserContext(); + } + virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE { return 3; } + virtual int NumberOfLoggedInUsers() const OVERRIDE { + // ash_shell has 2 users. + return 2; + } + virtual bool IsActiveUserSessionStarted() const OVERRIDE { return true; } + virtual bool CanLockScreen() const OVERRIDE { return true; } + virtual bool IsScreenLocked() const OVERRIDE { return screen_locked_; } + virtual bool ShouldLockScreenBeforeSuspending() const OVERRIDE { + return false; + } + virtual void LockScreen() OVERRIDE { + shell::CreateLockScreen(); + screen_locked_ = true; + Shell::GetInstance()->UpdateShelfVisibility(); + } + virtual void UnlockScreen() OVERRIDE { + screen_locked_ = false; + Shell::GetInstance()->UpdateShelfVisibility(); + } + virtual bool IsUserSessionBlocked() const OVERRIDE { + return !IsActiveUserSessionStarted() || IsScreenLocked(); + } + virtual SessionState GetSessionState() const OVERRIDE { + // Assume that if session is not active we're at login. + return IsActiveUserSessionStarted() ? SESSION_STATE_ACTIVE + : SESSION_STATE_LOGIN_PRIMARY; + } + virtual const UserInfo* GetUserInfo(MultiProfileIndex index) const OVERRIDE { + return user_info_.get(); + } + virtual const UserInfo* GetUserInfo( + content::BrowserContext* context) const OVERRIDE { + return user_info_.get(); + } + virtual bool ShouldShowAvatar(aura::Window* window) const OVERRIDE { + return !user_info_->GetImage().isNull(); + } + virtual void SwitchActiveUser(const std::string& user_id) OVERRIDE {} + virtual void CycleActiveUser(CycleUser cycle_user) OVERRIDE {} + virtual void AddSessionStateObserver( + ash::SessionStateObserver* observer) OVERRIDE {} + virtual void RemoveSessionStateObserver( + ash::SessionStateObserver* observer) OVERRIDE {} + + private: + bool screen_locked_; + + // A pseudo user info. + scoped_ptr<UserInfo> user_info_; + + DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateImpl); +}; + } // namespace ShellDelegateImpl::ShellDelegateImpl() @@ -149,7 +252,7 @@ ash::UserWallpaperDelegate* ShellDelegateImpl::CreateUserWallpaperDelegate() { } ash::SessionStateDelegate* ShellDelegateImpl::CreateSessionStateDelegate() { - return new SessionStateDelegateStub; + return new SessionStateDelegateImpl; } ash::AccessibilityDelegate* ShellDelegateImpl::CreateAccessibilityDelegate() { diff --git a/ash/system/ime/tray_ime.cc b/ash/system/ime/tray_ime.cc index dd73065a2f..3bd0296d06 100644 --- a/ash/system/ime/tray_ime.cc +++ b/ash/system/ime/tray_ime.cc @@ -23,6 +23,8 @@ #include "base/strings/utf_string_conversions.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" +#include "ui/accessibility/ax_enums.h" +#include "ui/accessibility/ax_view_state.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/font.h" @@ -34,6 +36,36 @@ namespace ash { namespace tray { +// A |HoverHighlightView| that uses bold or normal font depending on whetehr +// it is selected. This view exposes itself as a checkbox to the accessibility +// framework. +class SelectableHoverHighlightView : public HoverHighlightView { + public: + SelectableHoverHighlightView(ViewClickListener* listener, + const base::string16& label, + bool selected) + : HoverHighlightView(listener), selected_(selected) { + AddLabel( + label, gfx::ALIGN_LEFT, selected ? gfx::Font::BOLD : gfx::Font::NORMAL); + } + + virtual ~SelectableHoverHighlightView() {} + + protected: + // Overridden from views::View. + virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE { + HoverHighlightView::GetAccessibleState(state); + state->role = ui::AX_ROLE_CHECK_BOX; + if (selected_) + state->AddStateFlag(ui::AX_STATE_CHECKED); + } + + private: + bool selected_; + + DISALLOW_COPY_AND_ASSIGN(SelectableHoverHighlightView); +}; + class IMEDefaultView : public TrayItemMore { public: explicit IMEDefaultView(SystemTrayItem* owner) @@ -99,11 +131,8 @@ class IMEDetailedView : public TrayDetailsView, ime_map_.clear(); CreateScrollableList(); for (size_t i = 0; i < list.size(); i++) { - HoverHighlightView* container = new HoverHighlightView(this); - container->AddLabel( - list[i].name, - gfx::ALIGN_LEFT, - list[i].selected ? gfx::Font::BOLD : gfx::Font::NORMAL); + HoverHighlightView* container = new SelectableHoverHighlightView( + this, list[i].name, list[i].selected); scroll_content()->AddChildView(container); ime_map_[container] = list[i].id; } @@ -112,11 +141,8 @@ class IMEDetailedView : public TrayDetailsView, void AppendIMEProperties(const IMEPropertyInfoList& property_list) { property_map_.clear(); for (size_t i = 0; i < property_list.size(); i++) { - HoverHighlightView* container = new HoverHighlightView(this); - container->AddLabel( - property_list[i].name, - gfx::ALIGN_LEFT, - property_list[i].selected ? gfx::Font::BOLD : gfx::Font::NORMAL); + HoverHighlightView* container = new SelectableHoverHighlightView( + this, property_list[i].name, property_list[i].selected); if (i == 0) container->SetBorder(views::Border::CreateSolidSidedBorder( 1, 0, 0, 0, kBorderLightColor)); diff --git a/ash/system/tray/hover_highlight_view.h b/ash/system/tray/hover_highlight_view.h index ee1bdd8fb5..0797de6a3c 100644 --- a/ash/system/tray/hover_highlight_view.h +++ b/ash/system/tray/hover_highlight_view.h @@ -59,12 +59,15 @@ class HoverHighlightView : public ActionableView { bool hover() const { return hover_; } + protected: + // Overridden from views::View. + virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; + private: // Overridden from ActionableView: virtual bool PerformAction(const ui::Event& event) OVERRIDE; // Overridden from views::View. - virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; virtual gfx::Size GetPreferredSize() OVERRIDE; virtual int GetHeightForWidth(int width) OVERRIDE; virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; diff --git a/ash/system/tray/media_security/media_capture_observer.h b/ash/system/tray/media_security/media_capture_observer.h new file mode 100644 index 0000000000..9a217b2a6e --- /dev/null +++ b/ash/system/tray/media_security/media_capture_observer.h @@ -0,0 +1,23 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_ +#define ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_ + +#include "ash/ash_export.h" + +namespace ash { + +class ASH_EXPORT MediaCaptureObserver { + public: + // Called when media capture state has changed. + virtual void OnMediaCaptureChanged() = 0; + + protected: + virtual ~MediaCaptureObserver() {} +}; + +} // namespace ash + +#endif // ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_ diff --git a/ash/system/tray/media_security/multi_profile_media_tray_item.cc b/ash/system/tray/media_security/multi_profile_media_tray_item.cc new file mode 100644 index 0000000000..7826fb7ec7 --- /dev/null +++ b/ash/system/tray/media_security/multi_profile_media_tray_item.cc @@ -0,0 +1,85 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/tray/media_security/multi_profile_media_tray_item.h" + +#include "ash/ash_view_ids.h" +#include "ash/media_delegate.h" +#include "ash/session/session_state_delegate.h" +#include "ash/shell.h" +#include "ash/system/tray/media_security/media_capture_observer.h" +#include "ash/system/tray/system_tray_notifier.h" +#include "ash/system/tray/tray_item_view.h" +#include "grit/ash_resources.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/layout/fill_layout.h" + +namespace ash { +namespace tray { + +class MultiProfileMediaTrayView : public TrayItemView, + public MediaCaptureObserver { + public: + explicit MultiProfileMediaTrayView(SystemTrayItem* system_tray_item) + : TrayItemView(system_tray_item) { + SetLayoutManager(new views::FillLayout); + views::ImageView* icon = new views::ImageView; + ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); + icon->SetImage( + bundle.GetImageNamed(IDR_AURA_UBER_TRAY_RECORDING).ToImageSkia()); + AddChildView(icon); + OnMediaCaptureChanged(); + Shell::GetInstance()->system_tray_notifier()->AddMediaCaptureObserver(this); + set_id(VIEW_ID_MEDIA_TRAY_VIEW); + } + + virtual ~MultiProfileMediaTrayView() { + Shell::GetInstance()->system_tray_notifier()->RemoveMediaCaptureObserver( + this); + } + + // MediaCaptureObserver: + virtual void OnMediaCaptureChanged() OVERRIDE { + MediaDelegate* media_delegate = Shell::GetInstance()->media_delegate(); + SessionStateDelegate* session_state_delegate = + Shell::GetInstance()->session_state_delegate(); + // The user at 0 is the current desktop user. + for (MultiProfileIndex index = 1; + index < session_state_delegate->NumberOfLoggedInUsers(); + ++index) { + content::BrowserContext* context = + session_state_delegate->GetBrowserContextByIndex(index); + if (media_delegate->GetMediaCaptureState(context) != MEDIA_CAPTURE_NONE) { + SetVisible(true); + return; + } + } + SetVisible(false); + } + + private: + DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayView); +}; + +} // namespace tray + +MultiProfileMediaTrayItem::MultiProfileMediaTrayItem(SystemTray* system_tray) + : SystemTrayItem(system_tray), tray_view_(NULL) { +} + +MultiProfileMediaTrayItem::~MultiProfileMediaTrayItem() { +} + +views::View* MultiProfileMediaTrayItem::CreateTrayView( + user::LoginStatus status) { + tray_view_ = new tray::MultiProfileMediaTrayView(this); + return tray_view_; +} + +void MultiProfileMediaTrayItem::DestroyTrayView() { + tray_view_ = NULL; +} + +} // namespace ash diff --git a/ash/system/tray/media_security/multi_profile_media_tray_item.h b/ash/system/tray/media_security/multi_profile_media_tray_item.h new file mode 100644 index 0000000000..038bf8d6b1 --- /dev/null +++ b/ash/system/tray/media_security/multi_profile_media_tray_item.h @@ -0,0 +1,35 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_CHROMEOS_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_ +#define ASH_SYSTEM_CHROMEOS_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_ + +#include "ash/system/tray/system_tray_item.h" +#include "ui/message_center/notification_delegate.h" +#include "ui/views/view.h" + +namespace ash { +namespace tray { +class MultiProfileMediaTrayView; +} + +// The tray item for media recording. +class ASH_EXPORT MultiProfileMediaTrayItem : public SystemTrayItem { + public: + explicit MultiProfileMediaTrayItem(SystemTray* system_tray); + virtual ~MultiProfileMediaTrayItem(); + + // SystemTrayItem: + virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE; + virtual void DestroyTrayView() OVERRIDE; + + private: + tray::MultiProfileMediaTrayView* tray_view_; + + DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayItem); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_CHROMEOS_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_ diff --git a/ash/system/tray/media_security/multi_profile_media_tray_item_unittest.cc b/ash/system/tray/media_security/multi_profile_media_tray_item_unittest.cc new file mode 100644 index 0000000000..1dcfeaa512 --- /dev/null +++ b/ash/system/tray/media_security/multi_profile_media_tray_item_unittest.cc @@ -0,0 +1,58 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/tray/media_security/multi_profile_media_tray_item.h" + +#include "ash/ash_view_ids.h" +#include "ash/shell.h" +#include "ash/system/status_area_widget.h" +#include "ash/system/tray/system_tray.h" +#include "ash/system/tray/system_tray_bubble.h" +#include "ash/system/tray/tray_item_view.h" +#include "ash/test/ash_test_base.h" +#include "ash/test/test_session_state_delegate.h" +#include "ash/test/test_shell_delegate.h" +#include "ui/views/bubble/tray_bubble_view.h" + +namespace ash { + +typedef test::AshTestBase MultiProfileMediaTrayItemTest; + +TEST_F(MultiProfileMediaTrayItemTest, NotifyMediaCaptureChange) { + TrayItemView::DisableAnimationsForTest(); + test::TestShellDelegate* shell_delegate = + static_cast<test::TestShellDelegate*>(Shell::GetInstance()->delegate()); + test::TestSessionStateDelegate* session_state_delegate = + static_cast<test::TestSessionStateDelegate*>( + Shell::GetInstance()->session_state_delegate()); + session_state_delegate->set_logged_in_users(2); + + SystemTray* system_tray = Shell::GetInstance()->GetPrimarySystemTray(); + system_tray->ShowDefaultView(BUBBLE_CREATE_NEW); + views::View* in_user_view = + system_tray->GetSystemBubble()->bubble_view()->GetViewByID( + VIEW_ID_USER_VIEW_MEDIA_INDICATOR); + + StatusAreaWidget* widget = system_tray->status_area_widget(); + EXPECT_TRUE(widget->GetRootView()->visible()); + views::View* tray_view = + widget->GetRootView()->GetViewByID(VIEW_ID_MEDIA_TRAY_VIEW); + + EXPECT_FALSE(tray_view->visible()); + EXPECT_FALSE(in_user_view->visible()); + + shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_AUDIO); + EXPECT_TRUE(tray_view->visible()); + EXPECT_TRUE(in_user_view->visible()); + + shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_AUDIO_VIDEO); + EXPECT_TRUE(tray_view->visible()); + EXPECT_TRUE(in_user_view->visible()); + + shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_NONE); + EXPECT_FALSE(tray_view->visible()); + EXPECT_FALSE(in_user_view->visible()); +} + +} // namespace ash diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc index 726bbf3698..d8ac9a539b 100644 --- a/ash/system/tray/system_tray.cc +++ b/ash/system/tray/system_tray.cc @@ -61,6 +61,7 @@ #include "ash/system/chromeos/tray_caps_lock.h" #include "ash/system/chromeos/tray_display.h" #include "ash/system/chromeos/tray_tracing.h" +#include "ash/system/tray/media_security/multi_profile_media_tray_item.h" #include "ui/message_center/message_center.h" #elif defined(OS_WIN) #include "ash/system/win/audio/tray_audio_win.h" @@ -188,6 +189,7 @@ void SystemTray::CreateItems(SystemTrayDelegate* delegate) { AddTrayItem(new TrayDisplay(this)); AddTrayItem(new ScreenCaptureTrayItem(this)); AddTrayItem(new ScreenShareTrayItem(this)); + AddTrayItem(new MultiProfileMediaTrayItem(this)); AddTrayItem(new TrayAudioChromeOs(this)); AddTrayItem(new TrayBrightness(this)); AddTrayItem(new TrayCapsLock(this)); diff --git a/ash/system/tray/system_tray_notifier.cc b/ash/system/tray/system_tray_notifier.cc index ed858c3f9f..5801ce6b5b 100644 --- a/ash/system/tray/system_tray_notifier.cc +++ b/ash/system/tray/system_tray_notifier.cc @@ -151,6 +151,16 @@ void SystemTrayNotifier::RemoveEnterpriseDomainObserver( enterprise_domain_observers_.RemoveObserver(observer); } +void SystemTrayNotifier::AddMediaCaptureObserver( + MediaCaptureObserver* observer) { + media_capture_observers_.AddObserver(observer); +} + +void SystemTrayNotifier::RemoveMediaCaptureObserver( + MediaCaptureObserver* observer) { + media_capture_observers_.RemoveObserver(observer); +} + void SystemTrayNotifier::AddScreenCaptureObserver( ScreenCaptureObserver* observer) { screen_capture_observers_.AddObserver(observer); @@ -354,6 +364,11 @@ void SystemTrayNotifier::NotifyEnterpriseDomainChanged() { OnEnterpriseDomainChanged()); } +void SystemTrayNotifier::NotifyMediaCaptureChanged() { + FOR_EACH_OBSERVER( + MediaCaptureObserver, media_capture_observers_, OnMediaCaptureChanged()); +} + void SystemTrayNotifier::NotifyScreenCaptureStart( const base::Closure& stop_callback, const base::string16& sharing_app_name) { diff --git a/ash/system/tray/system_tray_notifier.h b/ash/system/tray/system_tray_notifier.h index 29cd9d2bb3..6e6b03fc97 100644 --- a/ash/system/tray/system_tray_notifier.h +++ b/ash/system/tray/system_tray_notifier.h @@ -30,6 +30,7 @@ #include "ash/system/chromeos/session/last_window_closed_observer.h" #include "ash/system/chromeos/session/logout_button_observer.h" #include "ash/system/chromeos/session/session_length_limit_observer.h" +#include "ash/system/tray/media_security/media_capture_observer.h" #include "base/time/time.h" #endif @@ -92,6 +93,9 @@ class ASH_EXPORT SystemTrayNotifier { void AddEnterpriseDomainObserver(EnterpriseDomainObserver* observer); void RemoveEnterpriseDomainObserver(EnterpriseDomainObserver* observer); + void AddMediaCaptureObserver(MediaCaptureObserver* observer); + void RemoveMediaCaptureObserver(MediaCaptureObserver* observer); + void AddScreenCaptureObserver(ScreenCaptureObserver* observer); void RemoveScreenCaptureObserver(ScreenCaptureObserver* observer); @@ -133,6 +137,7 @@ class ASH_EXPORT SystemTrayNotifier { void NotifyRequestToggleWifi(); void NotifyOnCaptivePortalDetected(const std::string& service_path); void NotifyEnterpriseDomainChanged(); + void NotifyMediaCaptureChanged(); void NotifyScreenCaptureStart(const base::Closure& stop_callback, const base::string16& sharing_app_name); void NotifyScreenCaptureStop(); @@ -164,6 +169,7 @@ class ASH_EXPORT SystemTrayNotifier { ObserverList<NetworkPortalDetectorObserver> network_portal_detector_observers_; ObserverList<EnterpriseDomainObserver> enterprise_domain_observers_; + ObserverList<MediaCaptureObserver> media_capture_observers_; ObserverList<ScreenCaptureObserver> screen_capture_observers_; ObserverList<ScreenShareObserver> screen_share_observers_; ObserverList<LastWindowClosedObserver> last_window_closed_observers_; diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc index 1a2d3555e8..fbf285925e 100644 --- a/ash/system/tray/system_tray_unittest.cc +++ b/ash/system/tray/system_tray_unittest.cc @@ -312,7 +312,7 @@ TEST_F(SystemTrayTest, SystemTrayNotifications) { RunAllPendingInMessageLoop(); ASSERT_TRUE(test_item->notification_view() != NULL); - // Show the detailed view, ensure the notificaiton view remains. + // Show the detailed view, ensure the notification view remains. tray->ShowDetailedView(detailed_item, 0, false, BUBBLE_CREATE_NEW); RunAllPendingInMessageLoop(); ASSERT_TRUE(detailed_item->detailed_view() != NULL); diff --git a/ash/system/user/user_card_view.cc b/ash/system/user/user_card_view.cc index af568aea42..c1bdd15e5f 100644 --- a/ash/system/user/user_card_view.cc +++ b/ash/system/user/user_card_view.cc @@ -11,6 +11,7 @@ #include "ash/session/user_info.h" #include "ash/shell.h" #include "ash/system/tray/system_tray_delegate.h" +#include "ash/system/tray/system_tray_notifier.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/user/config.h" #include "ash/system/user/rounded_image_view.h" @@ -35,6 +36,14 @@ #include "ui/views/controls/link_listener.h" #include "ui/views/layout/box_layout.h" +#if defined(OS_CHROMEOS) +#include "ash/ash_view_ids.h" +#include "ash/media_delegate.h" +#include "ash/system/tray/media_security/media_capture_observer.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/layout/fill_layout.h" +#endif + namespace ash { namespace tray { @@ -46,6 +55,70 @@ const int kUserDetailsVerticalPadding = 5; // and end of the user's display name in the public account user card's text. const base::char16 kDisplayNameMark[] = {0x2060, 0}; +#if defined(OS_CHROMEOS) +class MediaIndicator : public views::View, public MediaCaptureObserver { + public: + explicit MediaIndicator(MultiProfileIndex index) + : index_(index), label_(new views::Label) { + SetLayoutManager(new views::FillLayout); + views::ImageView* icon = new views::ImageView; + icon->SetImage(ui::ResourceBundle::GetSharedInstance() + .GetImageNamed(IDR_AURA_UBER_TRAY_RECORDING_RED) + .ToImageSkia()); + AddChildView(icon); + label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + label_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( + ui::ResourceBundle::SmallFont)); + OnMediaCaptureChanged(); + Shell::GetInstance()->system_tray_notifier()->AddMediaCaptureObserver(this); + set_id(VIEW_ID_USER_VIEW_MEDIA_INDICATOR); + } + + virtual ~MediaIndicator() { + Shell::GetInstance()->system_tray_notifier()->RemoveMediaCaptureObserver( + this); + } + + // MediaCaptureObserver: + virtual void OnMediaCaptureChanged() OVERRIDE { + Shell* shell = Shell::GetInstance(); + content::BrowserContext* context = + shell->session_state_delegate()->GetBrowserContextByIndex(index_); + MediaCaptureState state = + Shell::GetInstance()->media_delegate()->GetMediaCaptureState(context); + int res_id = 0; + switch (state) { + case MEDIA_CAPTURE_AUDIO_VIDEO: + res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO_VIDEO; + break; + case MEDIA_CAPTURE_AUDIO: + res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO; + break; + case MEDIA_CAPTURE_VIDEO: + res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_VIDEO; + break; + case MEDIA_CAPTURE_NONE: + break; + } + SetMessage(res_id ? l10n_util::GetStringUTF16(res_id) : base::string16()); + } + + views::View* GetMessageView() { return label_; } + + void SetMessage(const base::string16& message) { + SetVisible(!message.empty()); + label_->SetText(message); + label_->SetVisible(!message.empty()); + } + + private: + MultiProfileIndex index_; + views::Label* label_; + + DISALLOW_COPY_AND_ASSIGN(MediaIndicator); +}; +#endif + // The user details shown in public account mode. This is essentially a label // but with custom painting code as the text is styled with multiple colors and // contains a link. @@ -301,7 +374,7 @@ void UserCardView::AddUserContent(user::LoginStatus login_status, int multiprofile_index) { views::View* icon = CreateIcon(login_status, multiprofile_index); AddChildView(icon); - views::Label* username = NULL; + views::Label* user_name = NULL; SessionStateDelegate* delegate = Shell::GetInstance()->session_state_delegate(); if (!multiprofile_index) { @@ -313,12 +386,12 @@ void UserCardView::AddUserContent(user::LoginStatus login_status, user_name_string = base::ASCIIToUTF16( delegate->GetUserInfo(multiprofile_index)->GetEmail()); if (!user_name_string.empty()) { - username = new views::Label(user_name_string); - username->SetHorizontalAlignment(gfx::ALIGN_LEFT); + user_name = new views::Label(user_name_string); + user_name->SetHorizontalAlignment(gfx::ALIGN_LEFT); } } - views::Label* additional = NULL; + views::Label* user_email = NULL; if (login_status != user::LOGGED_IN_GUEST && (multiprofile_index || !IsMultiAccountSupportedAndUserActive())) { base::string16 user_email_string = @@ -328,37 +401,55 @@ void UserCardView::AddUserContent(user::LoginStatus login_status, : base::UTF8ToUTF16( delegate->GetUserInfo(multiprofile_index)->GetEmail()); if (!user_email_string.empty()) { - additional = new views::Label(user_email_string); - additional->SetFontList( + user_email = new views::Label(user_email_string); + user_email->SetFontList( ui::ResourceBundle::GetSharedInstance().GetFontList( ui::ResourceBundle::SmallFont)); - additional->SetHorizontalAlignment(gfx::ALIGN_LEFT); + user_email->SetHorizontalAlignment(gfx::ALIGN_LEFT); } } // Adjust text properties dependent on if it is an active or inactive user. if (multiprofile_index) { // Fade the text of non active users to 50%. - SkColor text_color = additional->enabled_color(); + SkColor text_color = user_email->enabled_color(); text_color = SkColorSetA(text_color, SkColorGetA(text_color) / 2); - if (additional) - additional->SetDisabledColor(text_color); - if (username) - username->SetDisabledColor(text_color); + if (user_email) + user_email->SetDisabledColor(text_color); + if (user_name) + user_name->SetDisabledColor(text_color); } - if (additional && username) { + if (user_email && user_name) { views::View* details = new views::View; details->SetLayoutManager(new views::BoxLayout( views::BoxLayout::kVertical, 0, kUserDetailsVerticalPadding, 0)); - details->AddChildView(username); - details->AddChildView(additional); + details->AddChildView(user_name); + details->AddChildView(user_email); AddChildView(details); } else { - if (username) - AddChildView(username); - if (additional) - AddChildView(additional); + if (user_name) + AddChildView(user_name); + if (user_email) { +#if defined(OS_CHROMEOS) + // Only non active user can have a media indicator. + MediaIndicator* media_indicator = new MediaIndicator(multiprofile_index); + views::View* email_indicator_view = new views::View; + email_indicator_view->SetLayoutManager(new views::BoxLayout( + views::BoxLayout::kHorizontal, 0, 0, kTrayPopupPaddingBetweenItems)); + email_indicator_view->AddChildView(user_email); + email_indicator_view->AddChildView(media_indicator); + + views::View* details = new views::View; + details->SetLayoutManager(new views::BoxLayout( + views::BoxLayout::kVertical, 0, kUserDetailsVerticalPadding, 0)); + details->AddChildView(email_indicator_view); + details->AddChildView(media_indicator->GetMessageView()); + AddChildView(details); +#else + AddChildView(user_email); +#endif + } } } diff --git a/ash/system/user/user_view.cc b/ash/system/user/user_view.cc index f5eb6833f1..6707686419 100644 --- a/ash/system/user/user_view.cc +++ b/ash/system/user/user_view.cc @@ -283,8 +283,8 @@ void UserView::Layout() { int remaining_width = contents_area.width() - logout_area.width(); if (IsMultiProfileSupportedAndUserActive() || IsMultiAccountSupportedAndUserActive()) { - // In multiprofile case |user_card_view_| and |logout_button_| have to - // have the same height. + // In multiprofile/multiaccount case |user_card_view_| and + // |logout_button_| have to have the same height. int y = std::min(user_card_area.y(), logout_area.y()); int height = std::max(user_card_area.height(), logout_area.height()); logout_area.set_y(y); diff --git a/ash/system/web_notification/web_notification_tray_unittest.cc b/ash/system/web_notification/web_notification_tray_unittest.cc index d39d3c962c..eaf9d06a1d 100644 --- a/ash/system/web_notification/web_notification_tray_unittest.cc +++ b/ash/system/web_notification/web_notification_tray_unittest.cc @@ -332,11 +332,11 @@ TEST_F(WebNotificationTrayTest, MAYBE_PopupAndSystemTray) { // even more, but still visible. GetSystemTray()->ShowNotificationView(test_item); EXPECT_TRUE(GetTray()->IsPopupVisible()); - gfx::Rect work_area_with_tray_notificaiton = GetPopupWorkArea(); + gfx::Rect work_area_with_tray_notification = GetPopupWorkArea(); EXPECT_GT(work_area.size().GetArea(), - work_area_with_tray_notificaiton.size().GetArea()); + work_area_with_tray_notification.size().GetArea()); EXPECT_GT(work_area_with_tray.size().GetArea(), - work_area_with_tray_notificaiton.size().GetArea()); + work_area_with_tray_notification.size().GetArea()); // Close system tray, only system tray notifications. GetSystemTray()->ClickedOutsideBubble(); @@ -344,7 +344,7 @@ TEST_F(WebNotificationTrayTest, MAYBE_PopupAndSystemTray) { gfx::Rect work_area_with_notification = GetPopupWorkArea(); EXPECT_GT(work_area.size().GetArea(), work_area_with_notification.size().GetArea()); - EXPECT_LT(work_area_with_tray_notificaiton.size().GetArea(), + EXPECT_LT(work_area_with_tray_notification.size().GetArea(), work_area_with_notification.size().GetArea()); // Close the system tray notifications. diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index 5787568caa..9cf3488500 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc @@ -138,7 +138,7 @@ void AshTestHelper::TearDown() { void AshTestHelper::RunAllPendingInMessageLoop() { DCHECK(base::MessageLoopForUI::current() == message_loop_); - aura::Env::CreateInstance(); + aura::Env::CreateInstance(true); base::RunLoop run_loop; run_loop.RunUntilIdle(); } diff --git a/ash/test/display_manager_test_api.h b/ash/test/display_manager_test_api.h index a3c506b142..be5dbb9532 100644 --- a/ash/test/display_manager_test_api.h +++ b/ash/test/display_manager_test_api.h @@ -23,8 +23,8 @@ class DisplayManagerTestApi { // Update the display configuration as given in |display_specs|. The format of // |display_spec| is a list of comma separated spec for each displays. Please - // refer to the comment in |aura::DisplayManager::CreateDisplayFromSpec| for - // the format of the display spec. + // refer to the comment in |ash::DisplayInfo::CreateFromSpec| for the format + // of the display spec. void UpdateDisplay(const std::string& display_specs); // Set the 1st display as an internal display and returns the display Id for diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc index 52962eeb47..2a6597d130 100644 --- a/ash/test/test_shell_delegate.cc +++ b/ash/test/test_shell_delegate.cc @@ -27,11 +27,21 @@ #include "ui/app_list/test/app_list_test_view_delegate.h" #include "ui/aura/window.h" +#if defined(OS_CHROMEOS) +#include "ash/system/tray/system_tray_notifier.h" +#endif + namespace ash { namespace test { namespace { class NewWindowDelegateImpl : public NewWindowDelegate { + public: + NewWindowDelegateImpl() {} + virtual ~NewWindowDelegateImpl() {} + + private: + // NewWindowDelegate: virtual void NewTab() OVERRIDE {} virtual void NewWindow(bool incognito) OVERRIDE {} virtual void OpenFileManager() OVERRIDE {} @@ -40,13 +50,30 @@ class NewWindowDelegateImpl : public NewWindowDelegate { virtual void ShowKeyboardOverlay() OVERRIDE {} virtual void ShowTaskManager() OVERRIDE {} virtual void OpenFeedbackPage() OVERRIDE {} + + DISALLOW_COPY_AND_ASSIGN(NewWindowDelegateImpl); }; class MediaDelegateImpl : public MediaDelegate { public: + MediaDelegateImpl() : state_(MEDIA_CAPTURE_NONE) {} + virtual ~MediaDelegateImpl() {} + + void set_media_capture_state(MediaCaptureState state) { state_ = state; } + + private: + // MediaDelegate: virtual void HandleMediaNextTrack() OVERRIDE {} virtual void HandleMediaPlayPause() OVERRIDE {} virtual void HandleMediaPrevTrack() OVERRIDE {} + virtual MediaCaptureState GetMediaCaptureState( + content::BrowserContext* context) OVERRIDE { + return state_; + } + + MediaCaptureState state_; + + DISALLOW_COPY_AND_ASSIGN(MediaDelegateImpl); }; } // namespace @@ -161,8 +188,13 @@ base::string16 TestShellDelegate::GetProductName() const { return base::string16(); } -TestSessionStateDelegate* TestShellDelegate::test_session_state_delegate() { - return test_session_state_delegate_; +void TestShellDelegate::SetMediaCaptureState(MediaCaptureState state) { +#if defined(OS_CHROMEOS) + Shell* shell = Shell::GetInstance(); + static_cast<MediaDelegateImpl*>(shell->media_delegate()) + ->set_media_capture_state(state); + shell->system_tray_notifier()->NotifyMediaCaptureChanged(); +#endif } } // namespace test diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h index 1d8da2f91a..d92f80dc9e 100644 --- a/ash/test/test_shell_delegate.h +++ b/ash/test/test_shell_delegate.h @@ -7,6 +7,7 @@ #include <string> +#include "ash/media_delegate.h" #include "ash/shell_delegate.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" @@ -63,7 +64,11 @@ class TestShellDelegate : public ShellDelegate { int num_exit_requests() const { return num_exit_requests_; } - TestSessionStateDelegate* test_session_state_delegate(); + TestSessionStateDelegate* test_session_state_delegate() { + return test_session_state_delegate_; + } + + void SetMediaCaptureState(MediaCaptureState state); private: int num_exit_requests_; diff --git a/ash/test/test_volume_control_delegate.cc b/ash/test/test_volume_control_delegate.cc new file mode 100644 index 0000000000..7c5cad0b1c --- /dev/null +++ b/ash/test/test_volume_control_delegate.cc @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/test/test_volume_control_delegate.h" + +namespace ash { + +TestVolumeControlDelegate::TestVolumeControlDelegate(bool consume) + : consume_(consume), + handle_volume_mute_count_(0), + handle_volume_down_count_(0), + handle_volume_up_count_(0) { +} + +TestVolumeControlDelegate::~TestVolumeControlDelegate() { +} + +bool TestVolumeControlDelegate::HandleVolumeMute( + const ui::Accelerator& accelerator) { + ++handle_volume_mute_count_; + last_accelerator_ = accelerator; + return consume_; +} + +bool TestVolumeControlDelegate::HandleVolumeDown( + const ui::Accelerator& accelerator) { + ++handle_volume_down_count_; + last_accelerator_ = accelerator; + return consume_; +} + +bool TestVolumeControlDelegate::HandleVolumeUp( + const ui::Accelerator& accelerator) { + ++handle_volume_up_count_; + last_accelerator_ = accelerator; + return consume_; +} + +} // namespace ash diff --git a/ash/test/test_volume_control_delegate.h b/ash/test/test_volume_control_delegate.h new file mode 100644 index 0000000000..85b3e5dec4 --- /dev/null +++ b/ash/test/test_volume_control_delegate.h @@ -0,0 +1,56 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_TEST_TEST_VOLUME_CONTROL_DELEGATE_H_ +#define ASH_TEST_TEST_VOLUME_CONTROL_DELEGATE_H_ + +#include "ash/volume_control_delegate.h" +#include "ui/base/accelerators/accelerator.h" + +namespace ash { + +// A simple test double for a VolumeControlDelegate +// Will count the number of times the HandleVolumeMute, HandleVolumeDown and +// HandleVolumeUp methods are invoked. +class TestVolumeControlDelegate : public ash::VolumeControlDelegate { + public: + explicit TestVolumeControlDelegate(bool consume); + virtual ~TestVolumeControlDelegate(); + + int handle_volume_mute_count() const { + return handle_volume_mute_count_; + } + + int handle_volume_down_count() const { + return handle_volume_down_count_; + } + + int handle_volume_up_count() const { + return handle_volume_up_count_; + } + + const ui::Accelerator& last_accelerator() const { + return last_accelerator_; + } + + // ash::VolumeControlDelegate: + virtual bool HandleVolumeMute(const ui::Accelerator& accelerator) OVERRIDE; + virtual bool HandleVolumeDown(const ui::Accelerator& accelerator) OVERRIDE; + virtual bool HandleVolumeUp(const ui::Accelerator& accelerator) OVERRIDE; + + private: + // Keeps track of the return value that should be used for the methods + // inherited from VolumeControlDelegate + bool consume_; + int handle_volume_mute_count_; + int handle_volume_down_count_; + int handle_volume_up_count_; + ui::Accelerator last_accelerator_; + + DISALLOW_COPY_AND_ASSIGN(TestVolumeControlDelegate); +}; + +} // namespace ash + +#endif // ASH_TEST_TEST_VOLUME_CONTROL_DELEGATE_H_ diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc index bf631e79a2..45915c49ae 100644 --- a/ash/wm/app_list_controller.cc +++ b/ash/wm/app_list_controller.cc @@ -24,6 +24,7 @@ #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/events/event.h" #include "ui/gfx/transform_util.h" +#include "ui/keyboard/keyboard_controller.h" #include "ui/views/widget/widget.h" namespace ash { @@ -113,6 +114,24 @@ gfx::Vector2d GetAnchorPositionOffsetToShelf( } } +// Gets the point at the center of the display that a particular view is on. +// This calculation excludes the virtual keyboard area. +gfx::Point GetCenterOfDisplayForView(const views::View* view) { + gfx::Rect bounds = Shell::GetScreen()->GetDisplayNearestWindow( + view->GetWidget()->GetNativeView()).bounds(); + + // If the virtual keyboard is active, subtract it from the display bounds, so + // that the app list is centered in the non-keyboard area of the display. + // (Note that work_area excludes the keyboard, but it doesn't get updated + // until after this function is called.) + keyboard::KeyboardController* keyboard_controller = + keyboard::KeyboardController::GetInstance(); + if (keyboard_controller && keyboard_controller->keyboard_visible()) + bounds.Subtract(keyboard_controller->current_keyboard_bounds()); + + return bounds.CenterPoint(); +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -121,6 +140,7 @@ gfx::Vector2d GetAnchorPositionOffsetToShelf( AppListController::AppListController() : pagination_model_(new app_list::PaginationModel), is_visible_(false), + is_centered_(false), view_(NULL), should_snap_back_(false) { Shell::GetInstance()->AddShellObserver(this); @@ -165,17 +185,21 @@ void AppListController::SetVisible(bool visible, aura::Window* window) { aura::Window* root_window = window->GetRootWindow(); aura::Window* container = GetRootWindowController(root_window)-> GetContainer(kShellWindowId_AppListContainer); - if (app_list::switches::IsExperimentalAppListPositionEnabled()) { - // The experimental app list is centered over the primary display. - view->InitAsBubbleCenteredOnPrimaryDisplay( - NULL, + views::View* applist_button = + Shelf::ForWindow(container)->GetAppListButtonView(); + is_centered_ = view->ShouldCenterWindow(); + if (is_centered_) { + // The experimental app list is centered over the display of the app list + // button that was pressed (if triggered via keyboard, this is the display + // with the currently focused window). + view->InitAsBubbleAtFixedLocation( + container, pagination_model_.get(), - Shell::GetScreen(), + GetCenterOfDisplayForView(applist_button), views::BubbleBorder::FLOAT, true /* border_accepts_events */); } else { - gfx::Rect applist_button_bounds = Shelf::ForWindow(container)-> - GetAppListButtonView()->GetBoundsInScreen(); + gfx::Rect applist_button_bounds = applist_button->GetBoundsInScreen(); // We need the location of the button within the local screen. applist_button_bounds = ScreenUtil::ConvertRectFromScreen( root_window, @@ -225,6 +249,10 @@ void AppListController::SetView(app_list::AppListView* view) { view_ = view; views::Widget* widget = view_->GetWidget(); widget->AddObserver(this); + keyboard::KeyboardController* keyboard_controller = + keyboard::KeyboardController::GetInstance(); + if (keyboard_controller) + keyboard_controller->AddObserver(this); Shell::GetInstance()->AddPreTargetHandler(this); Shelf::ForWindow(widget->GetNativeWindow())->AddIconObserver(this); widget->GetNativeView()->GetRootWindow()->AddObserver(this); @@ -240,6 +268,10 @@ void AppListController::ResetView() { views::Widget* widget = view_->GetWidget(); widget->RemoveObserver(this); GetLayer(widget)->GetAnimator()->RemoveObserver(this); + keyboard::KeyboardController* keyboard_controller = + keyboard::KeyboardController::GetInstance(); + if (keyboard_controller) + keyboard_controller->RemoveObserver(this); Shell::GetInstance()->RemovePreTargetHandler(this); Shelf::ForWindow(widget->GetNativeWindow())->RemoveIconObserver(this); widget->GetNativeView()->GetRootWindow()->RemoveObserver(this); @@ -302,8 +334,13 @@ void AppListController::ProcessLocatedEvent(ui::LocatedEvent* event) { } void AppListController::UpdateBounds() { - if (view_ && is_visible_) - view_->UpdateBounds(); + if (!view_ || !is_visible_) + return; + + view_->UpdateBounds(); + + if (is_centered_) + view_->SetAnchorPoint(GetCenterOfDisplayForView(view_)); } //////////////////////////////////////////////////////////////////////////////// @@ -364,6 +401,13 @@ void AppListController::OnWidgetDestroying(views::Widget* widget) { } //////////////////////////////////////////////////////////////////////////////// +// AppListController, keyboard::KeyboardControllerObserver implementation: + +void AppListController::OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) { + UpdateBounds(); +} + +//////////////////////////////////////////////////////////////////////////////// // AppListController, ShellObserver implementation: void AppListController::OnShelfAlignmentChanged(aura::Window* root_window) { if (view_) diff --git a/ash/wm/app_list_controller.h b/ash/wm/app_list_controller.h index c2eb0ad358..437cbb4a75 100644 --- a/ash/wm/app_list_controller.h +++ b/ash/wm/app_list_controller.h @@ -16,6 +16,7 @@ #include "ui/compositor/layer_animation_observer.h" #include "ui/events/event_handler.h" #include "ui/gfx/rect.h" +#include "ui/keyboard/keyboard_controller_observer.h" #include "ui/views/widget/widget_observer.h" namespace app_list { @@ -42,6 +43,7 @@ class AppListController : public ui::EventHandler, public aura::WindowObserver, public ui::ImplicitAnimationObserver, public views::WidgetObserver, + public keyboard::KeyboardControllerObserver, public ShellObserver, public ShelfIconObserver, public app_list::PaginationModelObserver { @@ -108,6 +110,9 @@ class AppListController : public ui::EventHandler, // views::WidgetObserver overrides: virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; + // KeyboardControllerObserver overrides: + virtual void OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) OVERRIDE; + // ShellObserver overrides: virtual void OnShelfAlignmentChanged(aura::Window* root_window) OVERRIDE; @@ -125,6 +130,9 @@ class AppListController : public ui::EventHandler, // Whether we should show or hide app list widget. bool is_visible_; + // Whether the app list should remain centered. + bool is_centered_; + // The AppListView this class manages, owned by its widget. app_list::AppListView* view_; diff --git a/ash/wm/app_list_controller_unittest.cc b/ash/wm/app_list_controller_unittest.cc index 9808d8b27b..7b467dfabf 100644 --- a/ash/wm/app_list_controller_unittest.cc +++ b/ash/wm/app_list_controller_unittest.cc @@ -7,17 +7,41 @@ #include "ash/test/ash_test_base.h" #include "ash/test/test_shell_delegate.h" #include "ash/wm/window_util.h" +#include "base/command_line.h" #include "base/memory/scoped_ptr.h" +#include "ui/app_list/app_list_switches.h" #include "ui/aura/test/event_generator.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" namespace ash { -typedef test::AshTestBase AppListControllerTest; +// The parameter is true to test the centered app list, false for normal. +// (The test name ends in "/0" for normal, "/1" for centered.) +class AppListControllerTest : public test::AshTestBase, + public ::testing::WithParamInterface<bool> { + public: + AppListControllerTest(); + virtual ~AppListControllerTest(); + virtual void SetUp() OVERRIDE; +}; + +AppListControllerTest::AppListControllerTest() { +} + +AppListControllerTest::~AppListControllerTest() { +} + +void AppListControllerTest::SetUp() { + AshTestBase::SetUp(); + if (GetParam()) { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + command_line->AppendSwitch(app_list::switches::kEnableCenteredAppList); + } +} // Tests that app launcher hides when focus moves to a normal window. -TEST_F(AppListControllerTest, HideOnFocusOut) { +TEST_P(AppListControllerTest, HideOnFocusOut) { Shell::GetInstance()->ToggleAppList(NULL); EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); @@ -29,7 +53,7 @@ TEST_F(AppListControllerTest, HideOnFocusOut) { // Tests that app launcher remains visible when focus is moved to a different // window in kShellWindowId_AppListContainer. -TEST_F(AppListControllerTest, RemainVisibleWhenFocusingToApplistContainer) { +TEST_P(AppListControllerTest, RemainVisibleWhenFocusingToApplistContainer) { Shell::GetInstance()->ToggleAppList(NULL); EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); @@ -43,7 +67,7 @@ TEST_F(AppListControllerTest, RemainVisibleWhenFocusingToApplistContainer) { } // Tests that clicking outside the app-list bubble closes it. -TEST_F(AppListControllerTest, ClickOutsideBubbleClosesBubble) { +TEST_P(AppListControllerTest, ClickOutsideBubbleClosesBubble) { Shell* shell = Shell::GetInstance(); shell->ToggleAppList(NULL); @@ -67,7 +91,7 @@ TEST_F(AppListControllerTest, ClickOutsideBubbleClosesBubble) { } // Tests that clicking outside the app-list bubble closes it. -TEST_F(AppListControllerTest, TapOutsideBubbleClosesBubble) { +TEST_P(AppListControllerTest, TapOutsideBubbleClosesBubble) { Shell* shell = Shell::GetInstance(); shell->ToggleAppList(NULL); @@ -89,4 +113,32 @@ TEST_F(AppListControllerTest, TapOutsideBubbleClosesBubble) { EXPECT_FALSE(shell->GetAppListTargetVisibility()); } +// Tests opening the app launcher on a non-primary display, then deleting the +// display. +TEST_P(AppListControllerTest, NonPrimaryDisplay) { + if (!SupportsMultipleDisplays()) + return; + + // Set up a screen with two displays (horizontally adjacent). + UpdateDisplay("800x600,800x600"); + + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + ASSERT_EQ(2u, root_windows.size()); + aura::Window* secondary_window = root_windows[1]; + EXPECT_EQ("800,0 800x600", secondary_window->GetBoundsInScreen().ToString()); + + Shell::GetInstance()->ToggleAppList(secondary_window); + EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); + + // Remove the secondary display. Shouldn't crash (http://crbug.com/368990). + UpdateDisplay("800x600"); + + // Updating the displays should close the app list. + EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility()); +} + +INSTANTIATE_TEST_CASE_P(AppListControllerTestInstance, + AppListControllerTest, + ::testing::Bool()); + } // namespace ash diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc index a26e78c166..ada7e36ebd 100644 --- a/ash/wm/default_state.cc +++ b/ash/wm/default_state.cc @@ -459,6 +459,12 @@ void DefaultState::ReenterToCurrentState( WindowState* window_state, WindowState::State* state_in_previous_mode) { WindowStateType previous_state_type = state_in_previous_mode->GetType(); + if (previous_state_type == wm::WINDOW_STATE_TYPE_FULLSCREEN) { + // A state change should not move a window out of full screen since full + // screen is a "special mode" the user wanted to be in and should be + // respected as such. + state_type_ = wm::WINDOW_STATE_TYPE_FULLSCREEN; + } window_state->UpdateWindowShowStateFromStateType(); window_state->NotifyPreStateTypeChange(previous_state_type); diff --git a/ash/wm/dock/docked_window_layout_manager.cc b/ash/wm/dock/docked_window_layout_manager.cc index daddd1f419..ab738eab79 100644 --- a/ash/wm/dock/docked_window_layout_manager.cc +++ b/ash/wm/dock/docked_window_layout_manager.cc @@ -590,8 +590,9 @@ DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const { return DOCKED_ALIGNMENT_NONE; } -bool DockedWindowLayoutManager::CanDockWindow(aura::Window* window, - SnapType edge) { +bool DockedWindowLayoutManager::CanDockWindow( + aura::Window* window, + DockedAlignment desired_alignment) { if (!switches::UseDockedWindows()) return false; // Don't allow interactive docking of windows with transient parents such as @@ -622,16 +623,19 @@ bool DockedWindowLayoutManager::CanDockWindow(aura::Window* window, return false; // Cannot dock on the other size from an existing dock. const DockedAlignment alignment = CalculateAlignment(); - if ((edge == SNAP_LEFT && alignment == DOCKED_ALIGNMENT_RIGHT) || - (edge == SNAP_RIGHT && alignment == DOCKED_ALIGNMENT_LEFT)) { + if (desired_alignment != DOCKED_ALIGNMENT_NONE && + alignment != DOCKED_ALIGNMENT_NONE && + alignment != desired_alignment) { return false; } // Do not allow docking on the same side as shelf. ShelfAlignment shelf_alignment = SHELF_ALIGNMENT_BOTTOM; if (shelf_) shelf_alignment = shelf_->alignment(); - if ((edge == SNAP_LEFT && shelf_alignment == SHELF_ALIGNMENT_LEFT) || - (edge == SNAP_RIGHT && shelf_alignment == SHELF_ALIGNMENT_RIGHT)) { + if ((desired_alignment == DOCKED_ALIGNMENT_LEFT && + shelf_alignment == SHELF_ALIGNMENT_LEFT) || + (desired_alignment == DOCKED_ALIGNMENT_RIGHT && + shelf_alignment == SHELF_ALIGNMENT_RIGHT)) { return false; } return true; @@ -943,7 +947,7 @@ void DockedWindowLayoutManager::RestoreDockedWindow( const gfx::Rect work_area = display.work_area(); // Evict the window if it can no longer be docked because of its height. - if (!CanDockWindow(window, SNAP_NONE)) { + if (!CanDockWindow(window, DOCKED_ALIGNMENT_NONE)) { UndockWindow(window); RecordUmaAction(DOCKED_ACTION_EVICT, DOCKED_ACTION_SOURCE_UNKNOWN); return; diff --git a/ash/wm/dock/docked_window_layout_manager.h b/ash/wm/dock/docked_window_layout_manager.h index 030d888194..9a362a48b4 100644 --- a/ash/wm/dock/docked_window_layout_manager.h +++ b/ash/wm/dock/docked_window_layout_manager.h @@ -11,7 +11,6 @@ #include "ash/wm/dock/dock_types.h" #include "ash/wm/dock/docked_window_layout_manager_observer.h" #include "ash/wm/window_state_observer.h" -#include "ash/wm/workspace/snap_types.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" @@ -119,7 +118,7 @@ class ASH_EXPORT DockedWindowLayoutManager // Returns true when a window can be docked. Windows cannot be docked at the // edge used by the shelf or the edge opposite from existing dock. - bool CanDockWindow(aura::Window* window, SnapType edge); + bool CanDockWindow(aura::Window* window, DockedAlignment desired_alignment); aura::Window* dock_container() const { return dock_container_; } diff --git a/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc b/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc index d619fd5239..33b898866a 100644 --- a/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc +++ b/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc @@ -7,8 +7,10 @@ #include "ash/accelerometer/accelerometer_controller.h" #include "ash/display/display_manager.h" #include "ash/shell.h" +#include "ash/system/tray/system_tray_delegate.h" #include "ash/test/ash_test_base.h" #include "ash/test/display_manager_test_api.h" +#include "ash/test/test_volume_control_delegate.h" #include "ui/aura/test/event_generator.h" #include "ui/events/event_handler.h" #include "ui/gfx/vector3d_f.h" @@ -327,6 +329,34 @@ TEST_F(MaximizeModeControllerTest, BlocksKeyboard) { counter.reset(); } +// Tests that maximize mode does not block Volume Up & Down events. +TEST_F(MaximizeModeControllerTest, AllowsVolumeControl) { + aura::Window* root = Shell::GetPrimaryRootWindow(); + aura::test::EventGenerator event_generator(root, root); + + TestVolumeControlDelegate* volume_delegate = + new TestVolumeControlDelegate(true); + ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( + scoped_ptr<VolumeControlDelegate>(volume_delegate).Pass()); + + // Trigger maximize mode by opening to 270 to begin the test in maximize mode. + TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, -1.0f), + gfx::Vector3dF(-1.0f, 0.0f, 0.0f)); + ASSERT_TRUE(IsMaximizeModeStarted()); + + // Verify volume down button event is not blocked + ASSERT_EQ(0, volume_delegate->handle_volume_down_count()); + event_generator.PressKey(ui::VKEY_VOLUME_DOWN, 0); + event_generator.ReleaseKey(ui::VKEY_VOLUME_DOWN, 0); + EXPECT_EQ(1, volume_delegate->handle_volume_down_count()); + + // Verify volume up event is not blocked + ASSERT_EQ(0, volume_delegate->handle_volume_up_count()); + event_generator.PressKey(ui::VKEY_VOLUME_UP, 0); + event_generator.ReleaseKey(ui::VKEY_VOLUME_UP, 0); + EXPECT_EQ(1, volume_delegate->handle_volume_up_count()); +} + TEST_F(MaximizeModeControllerTest, LaptopTest) { // Feeds in sample accelerometer data and verifies that there are no // transitions into touchview / maximize mode while shaking the device around diff --git a/ash/wm/maximize_mode/maximize_mode_event_blocker.cc b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc index e283149b6f..dd9fcde68d 100644 --- a/ash/wm/maximize_mode/maximize_mode_event_blocker.cc +++ b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc @@ -8,6 +8,7 @@ #include "base/memory/scoped_ptr.h" #include "ui/aura/client/cursor_client.h" #include "ui/events/event_targeter.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace ash { @@ -54,8 +55,19 @@ void BlockKeyboardAndTouchpadTargeter::SetDefaultTargeter( ui::EventTarget* BlockKeyboardAndTouchpadTargeter::FindTargetForEvent( ui::EventTarget* root, ui::Event* event) { - if (event->HasNativeEvent() && (event->IsMouseEvent() || event->IsKeyEvent())) - return NULL; + if (event->HasNativeEvent()) { + if (event->IsMouseEvent()) + return NULL; + if (event->IsKeyEvent()) { + // TODO(bruthig): Fix this to block rewritten volume keys + // (i.e. F9 and F10) from the device's keyboard. https://crbug.com/368669 + ui::KeyEvent* key_event = static_cast<ui::KeyEvent*>(event); + if (key_event->key_code() != ui::VKEY_VOLUME_DOWN && + key_event->key_code() != ui::VKEY_VOLUME_UP) { + return NULL; + } + } + } return default_targeter_->FindTargetForEvent(root, event); } diff --git a/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc b/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc index 56c6c53c95..6b1c244575 100644 --- a/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc +++ b/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc @@ -13,8 +13,10 @@ #include "ash/test/shell_test_api.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/window_selector_controller.h" +#include "ash/wm/window_properties.h" #include "ash/wm/window_state.h" #include "ash/wm/wm_event.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "ui/aura/client/aura_constants.h" @@ -58,6 +60,21 @@ class MaximizeModeWindowManagerTest : public test::AshTestBase { type, bounds, gfx::Size(), true, true); } + // Creates a window which also has a widget. + aura::Window* CreateWindowWithWidget(const gfx::Rect& bounds) { + views::Widget* widget = new views::Widget(); + views::Widget::InitParams params; + params.context = CurrentContext(); + // Note: The widget will get deleted with the window. + widget->Init(params); + widget->Show(); + aura::Window* window = widget->GetNativeWindow(); + window->SetBounds(bounds); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + + return window; + } + // Create the Maximized mode window manager. ash::MaximizeModeWindowManager* CreateMaximizeModeWindowManager() { EXPECT_FALSE(maximize_mode_window_manager()); @@ -392,6 +409,68 @@ TEST_F(MaximizeModeWindowManagerTest, EXPECT_EQ(rect.ToString(), fixed_window->bounds().ToString()); } +// Create a string which consists of the bounds and the state for comparison. +std::string GetPlacementString(const gfx::Rect& bounds, + ui::WindowShowState state) { + return bounds.ToString() + base::StringPrintf(" %d", state); +} + +// Retrieves the window's restore state override - if any - and returns it as a +// string. +std::string GetPlacementOverride(aura::Window* window) { + gfx::Rect* bounds = window->GetProperty(ash::kRestoreBoundsOverrideKey); + if (bounds) { + gfx::Rect restore_bounds = *bounds; + ui::WindowShowState restore_state = + window->GetProperty(ash::kRestoreShowStateOverrideKey); + return GetPlacementString(restore_bounds, restore_state); + } + return std::string(); +} + +// Test that the restore state will be kept at its original value for +// session restauration purposes. +TEST_F(MaximizeModeWindowManagerTest, TestRestoreIntegrety) { + gfx::Rect bounds(10, 10, 200, 50); + gfx::Size empty_size; + gfx::Rect empty_bounds; + scoped_ptr<aura::Window> normal_window( + CreateWindowWithWidget(bounds)); + scoped_ptr<aura::Window> maximized_window( + CreateWindowWithWidget(bounds)); + wm::GetWindowState(maximized_window.get())->Maximize(); + + EXPECT_EQ(std::string(), GetPlacementOverride(normal_window.get())); + EXPECT_EQ(std::string(), GetPlacementOverride(maximized_window.get())); + + ash::MaximizeModeWindowManager* manager = CreateMaximizeModeWindowManager(); + ASSERT_TRUE(manager); + + // With the maximization the override states should be returned in its + // pre-maximized state. + EXPECT_EQ(GetPlacementString(bounds, ui::SHOW_STATE_NORMAL), + GetPlacementOverride(normal_window.get())); + EXPECT_EQ(GetPlacementString(bounds, ui::SHOW_STATE_MAXIMIZED), + GetPlacementOverride(maximized_window.get())); + + // Changing a window's state now does not change the returned result. + wm::GetWindowState(maximized_window.get())->Minimize(); + EXPECT_EQ(GetPlacementString(bounds, ui::SHOW_STATE_MAXIMIZED), + GetPlacementOverride(maximized_window.get())); + + // Destroy the manager again and check that the overrides get reset. + DestroyMaximizeModeWindowManager(); + EXPECT_EQ(std::string(), GetPlacementOverride(normal_window.get())); + EXPECT_EQ(std::string(), GetPlacementOverride(maximized_window.get())); + + // Changing a window's state now does not bring the overrides back. + wm::GetWindowState(maximized_window.get())->Restore(); + gfx::Rect new_bounds(10, 10, 200, 50); + maximized_window->SetBounds(new_bounds); + + EXPECT_EQ(std::string(), GetPlacementOverride(maximized_window.get())); +} + // Test that windows which got created before the maximizer was created can be // destroyed while the maximizer is still running. TEST_F(MaximizeModeWindowManagerTest, PreCreateWindowsDeleteWhileActive) { @@ -719,7 +798,8 @@ TEST_F(MaximizeModeWindowManagerTest, KeepFullScreenModeOn) { EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); } -// Check that full screen mode can be turned on in maximized mode. +// Check that full screen mode can be turned on in maximized mode and remains +// upon coming back. TEST_F(MaximizeModeWindowManagerTest, AllowFullScreenMode) { gfx::Rect rect(20, 140, 100, 100); scoped_ptr<aura::Window> w1(CreateWindow(ui::wm::WINDOW_TYPE_NORMAL, rect)); @@ -749,11 +829,76 @@ TEST_F(MaximizeModeWindowManagerTest, AllowFullScreenMode) { EXPECT_FALSE(window_state->IsMaximized()); EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); - // With the destruction of the manager we should fall back to the old state. + // With the destruction of the manager we should remain in full screen. DestroyMaximizeModeWindowManager(); - EXPECT_FALSE(window_state->IsFullscreen()); + EXPECT_TRUE(window_state->IsFullscreen()); EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); + EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); +} + +// Check that the full screen mode will stay active when the maximize mode is +// ended. +TEST_F(MaximizeModeWindowManagerTest, + FullScreenModeRemainsWhenCreatedInMaximizedMode) { + CreateMaximizeModeWindowManager(); + + gfx::Rect rect(20, 140, 100, 100); + scoped_ptr<aura::Window> w1(CreateWindow(ui::wm::WINDOW_TYPE_NORMAL, rect)); + wm::WindowState* window_state = wm::GetWindowState(w1.get()); + wm::WMEvent event_full_screen(wm::WM_EVENT_TOGGLE_FULLSCREEN); + window_state->OnWMEvent(&event_full_screen); + EXPECT_TRUE(window_state->IsFullscreen()); + + // After the maximize mode manager is ended, full screen will remain. + DestroyMaximizeModeWindowManager(); + EXPECT_TRUE(window_state->IsFullscreen()); +} + +// Check that the full screen mode will stay active throughout a maximzied mode +// session. +TEST_F(MaximizeModeWindowManagerTest, + FullScreenModeRemainsThroughMaximizeModeSwitch) { + gfx::Rect rect(20, 140, 100, 100); + scoped_ptr<aura::Window> w1(CreateWindow(ui::wm::WINDOW_TYPE_NORMAL, rect)); + wm::WindowState* window_state = wm::GetWindowState(w1.get()); + wm::WMEvent event_full_screen(wm::WM_EVENT_TOGGLE_FULLSCREEN); + window_state->OnWMEvent(&event_full_screen); + EXPECT_TRUE(window_state->IsFullscreen()); + + CreateMaximizeModeWindowManager(); + EXPECT_TRUE(window_state->IsFullscreen()); + DestroyMaximizeModeWindowManager(); + EXPECT_TRUE(window_state->IsFullscreen()); +} + +// Check that an empty window does not get restored to a tiny size. +TEST_F(MaximizeModeWindowManagerTest, + CreateAndMaximizeInMaximizeModeShouldRetoreToGoodSizeGoingToDefault) { + CreateMaximizeModeWindowManager(); + gfx::Rect rect; + scoped_ptr<aura::Window> w1(CreateWindow(ui::wm::WINDOW_TYPE_NORMAL, rect)); + w1->Show(); + wm::WindowState* window_state = wm::GetWindowState(w1.get()); + EXPECT_TRUE(window_state->IsMaximized()); + + // There is a calling order in which the restore bounds can get set to an + // empty rectangle. We simulate this here. + window_state->SetRestoreBoundsInScreen(rect); + EXPECT_TRUE(window_state->GetRestoreBoundsInScreen().IsEmpty()); + + // Setting the window to a new size will physically not change the window, + // but the restore size should get updated so that a restore later on will + // return to this size. + gfx::Rect requested_bounds(10, 20, 50, 70); + w1->SetBounds(requested_bounds); + EXPECT_TRUE(window_state->IsMaximized()); + EXPECT_EQ(requested_bounds.ToString(), + window_state->GetRestoreBoundsInScreen().ToString()); + + DestroyMaximizeModeWindowManager(); + + EXPECT_FALSE(window_state->IsMaximized()); + EXPECT_EQ(w1->bounds().ToString(), requested_bounds.ToString()); } // Check that snapping operations get ignored. diff --git a/ash/wm/maximize_mode/maximize_mode_window_state.cc b/ash/wm/maximize_mode/maximize_mode_window_state.cc index df98796411..5c6623b771 100644 --- a/ash/wm/maximize_mode/maximize_mode_window_state.cc +++ b/ash/wm/maximize_mode/maximize_mode_window_state.cc @@ -11,7 +11,7 @@ #include "ash/wm/coordinate_conversion.h" #include "ash/wm/maximize_mode/maximize_mode_window_manager.h" #include "ash/wm/window_animations.h" -#include "ash/wm/window_state.h" +#include "ash/wm/window_properties.h" #include "ash/wm/window_state_delegate.h" #include "ash/wm/window_state_util.h" #include "ash/wm/window_util.h" @@ -22,6 +22,8 @@ #include "ui/aura/window_delegate.h" #include "ui/gfx/display.h" #include "ui/gfx/rect.h" +#include "ui/views/view_constants_aura.h" +#include "ui/views/widget/widget.h" namespace ash { namespace { @@ -140,13 +142,17 @@ void MaximizeModeWindowState::OnWMEvent(wm::WindowState* window_state, case wm::WM_EVENT_SHOW_INACTIVE: return; case wm::WM_EVENT_SET_BOUNDS: - if (window_state->CanResize()) { - // In case the window is resizable and / or maximized we ignore the - // requested bounds change and resize to the biggest possible size. - UpdateBounds(window_state, true); - } else - if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED && - current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED) { + if (current_state_type_ == wm::WINDOW_STATE_TYPE_MAXIMIZED) { + // Having a maximized window, it could have been created with an empty + // size and the caller should get his size upon leaving the maximized + // mode. As such we set the restore bounds to the requested bounds. + gfx::Rect bounds_in_parent = + (static_cast<const wm::SetBoundsEvent*>(event))->requested_bounds(); + if (!bounds_in_parent.IsEmpty()) + window_state->SetRestoreBoundsInParent(bounds_in_parent); + } else if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED && + current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED && + current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) { // In all other cases (except for minimized windows) we respect the // requested bounds and center it to a fully visible area on the screen. gfx::Rect bounds_in_parent = @@ -186,6 +192,20 @@ void MaximizeModeWindowState::AttachState( wm::WindowState::State* previous_state) { current_state_type_ = previous_state->GetType(); + views::Widget* widget = + views::Widget::GetWidgetForNativeWindow(window_state->window()); + if (widget) { + gfx::Rect bounds = widget->GetRestoredBounds(); + if (!bounds.IsEmpty()) { + // We do not want to do a session restore to our window states. Therefore + // we tell the window to use the current default states instead. + window_state->window()->SetProperty(ash::kRestoreShowStateOverrideKey, + window_state->GetShowState()); + window_state->window()->SetProperty(ash::kRestoreBoundsOverrideKey, + new gfx::Rect(widget->GetRestoredBounds())); + } + } + // Initialize the state to a good preset. if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED && current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED && @@ -199,6 +219,8 @@ void MaximizeModeWindowState::AttachState( } void MaximizeModeWindowState::DetachState(wm::WindowState* window_state) { + // From now on, we can use the default session restore mechanism again. + window_state->window()->ClearProperty(ash::kRestoreBoundsOverrideKey); window_state->set_can_be_dragged(true); } @@ -264,7 +286,12 @@ void MaximizeModeWindowState::UpdateBounds(wm::WindowState* window_state, !animated) { window_state->SetBoundsDirect(bounds_in_parent); } else { - window_state->SetBoundsDirectAnimated(bounds_in_parent); + // If we animate (to) maximized mode, we want to use the cross fade to + // avoid flashing. + if (window_state->IsMaximized()) + window_state->SetBoundsDirectCrossFade(bounds_in_parent); + else + window_state->SetBoundsDirectAnimated(bounds_in_parent); } } } diff --git a/ash/wm/system_modal_container_layout_manager.cc b/ash/wm/system_modal_container_layout_manager.cc index 7ee1ef4f11..81ea8bb708 100644 --- a/ash/wm/system_modal_container_layout_manager.cc +++ b/ash/wm/system_modal_container_layout_manager.cc @@ -4,6 +4,8 @@ #include "ash/wm/system_modal_container_layout_manager.h" +#include <cmath> + #include "ash/session/session_state_delegate.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" @@ -15,6 +17,7 @@ #include "ui/aura/client/capture_client.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_property.h" #include "ui/base/ui_base_switches_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" @@ -27,8 +30,17 @@ #include "ui/views/widget/widget.h" #include "ui/wm/core/compound_event_filter.h" +DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(ASH_EXPORT, bool); + namespace ash { +// If this is set to true, the window will get centered. +DEFINE_WINDOW_PROPERTY_KEY(bool, kCenteredKey, false); + +// The center point of the window can diverge this much from the center point +// of the container to be kept centered upon resizing operations. +const int kCenterPixelDelta = 32; + //////////////////////////////////////////////////////////////////////////////// // SystemModalContainerLayoutManager, public: @@ -87,6 +99,7 @@ void SystemModalContainerLayoutManager::SetChildBounds( aura::Window* child, const gfx::Rect& requested_bounds) { SetChildBoundsDirect(child, requested_bounds); + child->SetProperty(kCenteredKey, DialogIsCentered(requested_bounds)); } //////////////////////////////////////////////////////////////////////////////// @@ -232,14 +245,10 @@ void SystemModalContainerLayoutManager::RemoveModalWindow( } void SystemModalContainerLayoutManager::PositionDialogsAfterWorkAreaResize() { - gfx::Rect valid_bounds = GetUsableDialogArea(); - if (!modal_windows_.empty()) { for (aura::Window::Windows::iterator it = modal_windows_.begin(); it != modal_windows_.end(); ++it) { - gfx::Rect bounds = (*it)->bounds(); - bounds.AdjustToFit(valid_bounds); - (*it)->SetBounds(bounds); + (*it)->SetBounds(GetCenteredAndOrFittedBounds(*it)); } } } @@ -263,4 +272,26 @@ gfx::Rect SystemModalContainerLayoutManager::GetUsableDialogArea() { return valid_bounds; } +gfx::Rect SystemModalContainerLayoutManager::GetCenteredAndOrFittedBounds( + const aura::Window* window) { + if (window->GetProperty(kCenteredKey)) { + // Keep the dialog centered if it was centered before. + gfx::Rect target_bounds = GetUsableDialogArea(); + target_bounds.ClampToCenteredSize(window->bounds().size()); + return target_bounds; + } + gfx::Rect target_bounds = window->bounds(); + target_bounds.AdjustToFit(GetUsableDialogArea()); + return target_bounds; +} + +bool SystemModalContainerLayoutManager::DialogIsCentered( + const gfx::Rect& window_bounds) { + gfx::Point window_center = window_bounds.CenterPoint(); + gfx::Point container_center = GetUsableDialogArea().CenterPoint(); + return + std::abs(window_center.x() - container_center.x()) < kCenterPixelDelta && + std::abs(window_center.y() - container_center.y()) < kCenterPixelDelta; +} + } // namespace ash diff --git a/ash/wm/system_modal_container_layout_manager.h b/ash/wm/system_modal_container_layout_manager.h index 0f47b710f7..6350337dce 100644 --- a/ash/wm/system_modal_container_layout_manager.h +++ b/ash/wm/system_modal_container_layout_manager.h @@ -29,6 +29,8 @@ class Widget; namespace ash { // LayoutManager for the modal window container. +// System modal windows which are centered on the screen will be kept centered +// when the container size changes. class ASH_EXPORT SystemModalContainerLayoutManager : public aura::LayoutManager, public aura::WindowObserver, @@ -85,6 +87,13 @@ class ASH_EXPORT SystemModalContainerLayoutManager // Get the usable bounds rectangle for enclosed dialogs. gfx::Rect GetUsableDialogArea(); + // Gets the new bounds for a |window| to use which are either centered (if the + // window was previously centered) or fitted to the screen. + gfx::Rect GetCenteredAndOrFittedBounds(const aura::Window* window); + + // Returns true if |window_bounds| is centered. + bool DialogIsCentered(const gfx::Rect& window_bounds); + aura::Window* modal_window() { return !modal_windows_.empty() ? modal_windows_.back() : NULL; } diff --git a/ash/wm/system_modal_container_layout_manager_unittest.cc b/ash/wm/system_modal_container_layout_manager_unittest.cc index ca79cef34f..9e6dbd00e5 100644 --- a/ash/wm/system_modal_container_layout_manager_unittest.cc +++ b/ash/wm/system_modal_container_layout_manager_unittest.cc @@ -431,6 +431,24 @@ TEST_F(SystemModalContainerLayoutManagerTest, KeepVisible) { EXPECT_EQ(bounds, gfx::Rect(700, 500, 100, 100)); } +// Verifies that centered windows will remain centered after the visible screen +// area changed. +TEST_F(SystemModalContainerLayoutManagerTest, KeepCentered) { + GetModalContainer()->SetBounds(gfx::Rect(0, 0, 800, 600)); + scoped_ptr<aura::Window> main(OpenTestWindowWithParent(GetModalContainer(), + true)); + // Center the window. + main->SetBounds(gfx::Rect((800 - 512) / 2, (600 - 256) / 2, 512, 256)); + + // We set now the bounds of the root window to something new which will + // Then trigger the reposition operation. + GetModalContainer()->SetBounds(gfx::Rect(0, 0, 1024, 768)); + + // The window should still be centered. + gfx::Rect bounds = main->bounds(); + EXPECT_EQ(bounds.ToString(), gfx::Rect(256, 256, 512, 256).ToString()); +} + TEST_F(SystemModalContainerLayoutManagerTest, ShowNormalBackgroundOrLocked) { scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false)); scoped_ptr<aura::Window> modal_window( diff --git a/ash/wm/window_properties.cc b/ash/wm/window_properties.cc index 1689c90846..2657e3aa85 100644 --- a/ash/wm/window_properties.cc +++ b/ash/wm/window_properties.cc @@ -8,9 +8,19 @@ #include "ui/aura/window_property.h" DECLARE_WINDOW_PROPERTY_TYPE(ash::wm::WindowState*); +DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(ASH_EXPORT, gfx::Rect*) +DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(ASH_EXPORT, ui::WindowShowState) namespace ash { +DEFINE_OWNED_WINDOW_PROPERTY_KEY(gfx::Rect, + kRestoreBoundsOverrideKey, + NULL); + +DEFINE_WINDOW_PROPERTY_KEY(ui::WindowShowState, + kRestoreShowStateOverrideKey, + ui::SHOW_STATE_DEFAULT); + DEFINE_WINDOW_PROPERTY_KEY(bool, kStayInSameRootWindowKey, false); DEFINE_WINDOW_PROPERTY_KEY(bool, kUsesScreenCoordinatesKey, false); DEFINE_OWNED_WINDOW_PROPERTY_KEY(wm::WindowState, diff --git a/ash/wm/window_properties.h b/ash/wm/window_properties.h index c99d21d9ff..c79b694db2 100644 --- a/ash/wm/window_properties.h +++ b/ash/wm/window_properties.h @@ -7,6 +7,7 @@ #include "ash/ash_export.h" #include "ui/base/ui_base_types.h" +#include "ui/gfx/rect.h" namespace aura { class Window; @@ -24,6 +25,18 @@ class WindowState; // Alphabetical sort. +// A property key which stores the bounds to restore a window to. These take +// preference over the current bounds/state. This is used by e.g. the always +// maximized mode window manager. +ASH_EXPORT extern const aura::WindowProperty<gfx::Rect*>* const + kRestoreBoundsOverrideKey; + +// A property key which stores the bounds to restore a window to. These take +// preference over the current bounds/state if |kRestoreBoundsOverrideKey| is +// set. This is used by e.g. the always maximized mode window manager. +ASH_EXPORT extern const aura::WindowProperty<ui::WindowShowState>* const + kRestoreShowStateOverrideKey; + // If this is set to true, the window stays in the same root window // even if the bounds outside of its root window is set. // This is exported as it's used in the tests. diff --git a/ash/wm/workspace/phantom_window_controller.cc b/ash/wm/workspace/phantom_window_controller.cc index ba954231c7..23121c0c0e 100644 --- a/ash/wm/workspace/phantom_window_controller.cc +++ b/ash/wm/workspace/phantom_window_controller.cc @@ -6,18 +6,13 @@ #include <math.h> -#include "ash/ash_switches.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/wm/coordinate_conversion.h" #include "grit/ash_resources.h" -#include "third_party/skia/include/core/SkCanvas.h" #include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/skia_util.h" #include "ui/views/background.h" #include "ui/views/painter.h" #include "ui/views/view.h" @@ -30,32 +25,27 @@ namespace { const int kAnimationDurationMs = 200; // The size of the phantom window at the beginning of the show animation in -// relation to the size of the phantom window at the end of the animation when -// using the alternate caption button style. -const float kAlternateStyleStartBoundsRatio = 0.85f; +// relation to the size of the phantom window at the end of the animation. +const float kStartBoundsRatio = 0.85f; // The amount of pixels that the phantom window's shadow should extend past -// the bounds passed into Show(). There is no shadow when not using the -// alternate caption button style. -const int kAlternateStyleShadowThickness = 15; +// the bounds passed into Show(). +const int kShadowThickness = 15; -// The minimum size of a phantom window including the shadow when using the -// alternate caption button style. The minimum size is derived from the size of -// the IDR_AURA_PHANTOM_WINDOW image assets. -const int kAlternateStyleMinSizeWithShadow = 100; +// The minimum size of a phantom window including the shadow. The minimum size +// is derived from the size of the IDR_AURA_PHANTOM_WINDOW image assets. +const int kMinSizeWithShadow = 100; // Adjusts the phantom window's bounds so that the bounds: // - Include the size of the shadow. -// - Have a size equal to or larger than the minimize phantom window size. -gfx::Rect GetAdjustedBoundsForAlternateStyle(const gfx::Rect& bounds) { +// - Have a size equal to or larger than the minimum phantom window size. +gfx::Rect GetAdjustedBounds(const gfx::Rect& bounds) { int x_inset = std::max( - static_cast<int>( - ceil((kAlternateStyleMinSizeWithShadow - bounds.width()) / 2.0f)), - kAlternateStyleShadowThickness); + static_cast<int>(ceil((kMinSizeWithShadow - bounds.width()) / 2.0f)), + kShadowThickness); int y_inset = std::max( - static_cast<int>( - ceil((kAlternateStyleMinSizeWithShadow - bounds.height()) / 2.0f)), - kAlternateStyleShadowThickness); + static_cast<int>(ceil((kMinSizeWithShadow - bounds.height()) / 2.0f)), + kShadowThickness); gfx::Rect adjusted_bounds(bounds); adjusted_bounds.Inset(-x_inset, -y_inset); @@ -79,161 +69,38 @@ void AnimateToBounds(views::Widget* widget, widget->SetBounds(new_bounds_in_screen); } -// EdgePainter ---------------------------------------------------------------- - -// Paints the background of the phantom window for window snapping. -class EdgePainter : public views::Painter { - public: - EdgePainter(); - virtual ~EdgePainter(); - - // views::Painter: - virtual gfx::Size GetMinimumSize() const OVERRIDE; - virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(EdgePainter); -}; - -EdgePainter::EdgePainter() { -} - -EdgePainter::~EdgePainter() { -} - -gfx::Size EdgePainter::GetMinimumSize() const { - return gfx::Size(); -} - -void EdgePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) { - const int kInsetSize = 4; - int x = kInsetSize; - int y = kInsetSize; - int w = size.width() - kInsetSize * 2; - int h = size.height() - kInsetSize * 2; - bool inset = (w > 0 && h > 0); - if (!inset) { - x = 0; - y = 0; - w = size.width(); - h = size.height(); - } - SkPaint paint; - paint.setColor(SkColorSetARGB(100, 0, 0, 0)); - paint.setStyle(SkPaint::kFill_Style); - paint.setAntiAlias(true); - const int kRoundRectSize = 4; - canvas->sk_canvas()->drawRoundRect( - gfx::RectToSkRect(gfx::Rect(x, y, w, h)), - SkIntToScalar(kRoundRectSize), SkIntToScalar(kRoundRectSize), paint); - if (!inset) - return; - - paint.setColor(SkColorSetARGB(200, 255, 255, 255)); - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(SkIntToScalar(2)); - canvas->sk_canvas()->drawRoundRect( - gfx::RectToSkRect(gfx::Rect(x, y, w, h)), SkIntToScalar(kRoundRectSize), - SkIntToScalar(kRoundRectSize), paint); -} - } // namespace // PhantomWindowController ---------------------------------------------------- PhantomWindowController::PhantomWindowController(aura::Window* window) - : window_(window), - phantom_below_window_(NULL) { + : window_(window) { } PhantomWindowController::~PhantomWindowController() { } void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) { - if (switches::UseAlternateFrameCaptionButtonStyle()) - ShowAlternate(bounds_in_screen); - else - ShowLegacy(bounds_in_screen); -} - -void PhantomWindowController::ShowAlternate(const gfx::Rect& bounds_in_screen) { - gfx::Rect adjusted_bounds_in_screen = - GetAdjustedBoundsForAlternateStyle(bounds_in_screen); + gfx::Rect adjusted_bounds_in_screen = GetAdjustedBounds(bounds_in_screen); if (adjusted_bounds_in_screen == target_bounds_in_screen_) return; target_bounds_in_screen_ = adjusted_bounds_in_screen; gfx::Rect start_bounds_in_screen = target_bounds_in_screen_; int start_width = std::max( - kAlternateStyleMinSizeWithShadow, - static_cast<int>( - start_bounds_in_screen.width() * kAlternateStyleStartBoundsRatio)); + kMinSizeWithShadow, + static_cast<int>(start_bounds_in_screen.width() * kStartBoundsRatio)); int start_height = std::max( - kAlternateStyleMinSizeWithShadow, - static_cast<int>( - start_bounds_in_screen.height() * kAlternateStyleStartBoundsRatio)); + kMinSizeWithShadow, + static_cast<int>(start_bounds_in_screen.height() * kStartBoundsRatio)); start_bounds_in_screen.Inset( floor((start_bounds_in_screen.width() - start_width) / 2.0f), floor((start_bounds_in_screen.height() - start_height) / 2.0f)); - phantom_widget_in_target_root_ = CreatePhantomWidget( + phantom_widget_ = CreatePhantomWidget( wm::GetRootWindowMatching(target_bounds_in_screen_), start_bounds_in_screen); - AnimateToBounds(phantom_widget_in_target_root_.get(), - target_bounds_in_screen_); -} - -void PhantomWindowController::ShowLegacy(const gfx::Rect& bounds_in_screen) { - if (bounds_in_screen == target_bounds_in_screen_) - return; - target_bounds_in_screen_ = bounds_in_screen; - - gfx::Rect start_bounds_in_screen; - if (!phantom_widget_in_target_root_) { - start_bounds_in_screen = window_->GetBoundsInScreen(); - } else { - start_bounds_in_screen = - phantom_widget_in_target_root_->GetWindowBoundsInScreen(); - } - - aura::Window* target_root = - wm::GetRootWindowMatching(target_bounds_in_screen_); - if (!phantom_widget_in_target_root_ || - phantom_widget_in_target_root_->GetNativeWindow()->GetRootWindow() != - target_root) { - phantom_widget_in_target_root_ = - CreatePhantomWidget(target_root, start_bounds_in_screen); - } - AnimateToBounds(phantom_widget_in_target_root_.get(), - target_bounds_in_screen_); - - // Create a secondary widget in a second screen if |start_bounds_in_screen| - // lies at least partially in another screen. This allows animations to start - // or restart in one root window and progress to another root. - aura::Window* start_root = wm::GetRootWindowMatching(start_bounds_in_screen); - if (start_root == target_root) { - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - for (size_t i = 0; i < root_windows.size(); ++i) { - if (root_windows[i] != target_root && - root_windows[i]->GetBoundsInScreen().Intersects( - start_bounds_in_screen)) { - start_root = root_windows[i]; - break; - } - } - } - if (start_root == target_root) { - phantom_widget_in_start_root_.reset(); - } else { - if (!phantom_widget_in_start_root_ || - phantom_widget_in_start_root_->GetNativeWindow()->GetRootWindow() != - start_root) { - phantom_widget_in_start_root_ = - CreatePhantomWidget(start_root, start_bounds_in_screen); - } - AnimateToBounds(phantom_widget_in_start_root_.get(), - target_bounds_in_screen_); - } + AnimateToBounds(phantom_widget_.get(), target_bounds_in_screen_); } scoped_ptr<views::Widget> PhantomWindowController::CreatePhantomWidget( @@ -256,18 +123,11 @@ scoped_ptr<views::Widget> PhantomWindowController::CreatePhantomWidget( phantom_widget->GetNativeWindow()->SetName("PhantomWindow"); phantom_widget->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow); phantom_widget->SetBounds(bounds_in_screen); - if (phantom_below_window_) - phantom_widget->StackBelow(phantom_below_window_); - else - phantom_widget->StackAbove(window_); + phantom_widget->StackAbove(window_); - views::Painter* background_painter = NULL; - if (switches::UseAlternateFrameCaptionButtonStyle()) { - const int kImages[] = IMAGE_GRID(IDR_AURA_PHANTOM_WINDOW); - background_painter = views::Painter::CreateImageGridPainter(kImages); - } else { - background_painter = new EdgePainter; - } + const int kImages[] = IMAGE_GRID(IDR_AURA_PHANTOM_WINDOW); + views::Painter* background_painter = + views::Painter::CreateImageGridPainter(kImages); views::View* content_view = new views::View; content_view->set_background( views::Background::CreateBackgroundPainter(true, background_painter)); diff --git a/ash/wm/workspace/phantom_window_controller.h b/ash/wm/workspace/phantom_window_controller.h index d62b135805..11d6f952e3 100644 --- a/ash/wm/workspace/phantom_window_controller.h +++ b/ash/wm/workspace/phantom_window_controller.h @@ -30,52 +30,27 @@ class ASH_EXPORT PhantomWindowController { // Hides the phantom window without any animation. virtual ~PhantomWindowController(); - // Animates the phantom window towards |bounds_in_screen|. The animation used - // depends on whether the alternate caption button style is used. + // Shows the phantom window and animates shrinking it to |bounds_in_screen|. void Show(const gfx::Rect& bounds_in_screen); - // If set, the phantom window is stacked below this window, otherwise it - // is stacked above the window passed to the constructor. - void set_phantom_below_window(aura::Window* phantom_below_window) { - phantom_below_window_ = phantom_below_window; - } - private: friend class PhantomWindowControllerTest; - // Animates the phantom window towards |bounds_in_screen| when the alternate - // caption button style is used. - void ShowAlternate(const gfx::Rect& bounds_in_screen); - - // Animates the phantom window towards |bounds_in_screen| when the legacy - // caption button style is used. - void ShowLegacy(const gfx::Rect& bounds_in_screen); - // Creates, shows and returns a phantom widget at |bounds| // with kShellWindowId_ShelfContainer in |root_window| as a parent. scoped_ptr<views::Widget> CreatePhantomWidget( aura::Window* root_window, const gfx::Rect& bounds_in_screen); - // Window the phantom is placed beneath. + // Window that the phantom window is stacked above. aura::Window* window_; - // If set, the phantom window should get stacked below this window. - aura::Window* phantom_below_window_; - // Target bounds (including the shadows if any) of the animation in screen // coordinates. gfx::Rect target_bounds_in_screen_; - // Phantom representation of the window which is in the root window matching - // |target_bounds_in_screen_|. - scoped_ptr<views::Widget> phantom_widget_in_target_root_; - - // Phantom representation of the window which is in the root window matching - // the window's initial bounds. This allows animations to progress from one - // display to the other. NULL if the phantom window starts and ends in the - // same root window. Not used when using the alternate caption button style. - scoped_ptr<views::Widget> phantom_widget_in_start_root_; + // Phantom representation of the window. + scoped_ptr<views::Widget> phantom_widget_; DISALLOW_COPY_AND_ASSIGN(PhantomWindowController); }; diff --git a/ash/wm/workspace/phantom_window_controller_unittest.cc b/ash/wm/workspace/phantom_window_controller_unittest.cc deleted file mode 100644 index fa637d8041..0000000000 --- a/ash/wm/workspace/phantom_window_controller_unittest.cc +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/wm/workspace/phantom_window_controller.h" - -#include "ash/ash_switches.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "base/command_line.h" -#include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" -#include "ui/aura/window_observer.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace { - -// Returns true if |window| is non-NULL and is visible. -bool IsVisible(aura::Window* window) { - return window && window->IsVisible(); -} - -// Observes |window|'s deletion. -class WindowDeletionObserver : public aura::WindowObserver { - public: - WindowDeletionObserver(aura::Window* window) : window_(window) { - window_->AddObserver(this); - } - - virtual ~WindowDeletionObserver() { - if (window_) - window_->RemoveObserver(this); - } - - // Returns true if the window has not been deleted yet. - bool IsWindowAlive() { - return !!window_; - } - - // aura::WindowObserver: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { - window_->RemoveObserver(this); - window_ = NULL; - } - - private: - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(WindowDeletionObserver); -}; - -} // namespace - -class PhantomWindowControllerTest : public ash::test::AshTestBase { - public: - PhantomWindowControllerTest() { - } - virtual ~PhantomWindowControllerTest() { - } - - // ash::test::AshTestBase: - virtual void SetUp() OVERRIDE { - ash::test::AshTestBase::SetUp(); - - window_ = CreateTestWindowInShellWithBounds(gfx::Rect(0, 0, 50, 60)); - controller_.reset(new PhantomWindowController(window_)); - } - - void DeleteController() { - controller_.reset(); - } - - PhantomWindowController* controller() { - return controller_.get(); - } - - aura::Window* window() { return window_; } - - aura::Window* phantom_window_in_target_root() { - return controller_->phantom_widget_in_target_root_ ? - controller_->phantom_widget_in_target_root_->GetNativeView() : - NULL; - } - - aura::Window* phantom_window_in_start_root() { - return controller_->phantom_widget_in_start_root_ ? - controller_->phantom_widget_in_start_root_->GetNativeView() : - NULL; - } - - private: - aura::Window* window_; - scoped_ptr<PhantomWindowController> controller_; - - DISALLOW_COPY_AND_ASSIGN(PhantomWindowControllerTest); -}; - -// Test that two phantom windows are used when animating to bounds at least -// partially in another display when using the old caption button style. -TEST_F(PhantomWindowControllerTest, OldCaptionButtonStyle) { - if (!SupportsMultipleDisplays()) - return; - - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshDisableAlternateFrameCaptionButtonStyle); - ASSERT_FALSE(switches::UseAlternateFrameCaptionButtonStyle()); - - UpdateDisplay("500x400,500x400"); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(root_windows[0], window()->GetRootWindow()); - - // Phantom preview only in the left screen. - controller()->Show(gfx::Rect(100, 100, 50, 60)); - EXPECT_TRUE(IsVisible(phantom_window_in_target_root())); - EXPECT_FALSE(IsVisible(phantom_window_in_start_root())); - EXPECT_EQ(root_windows[0], phantom_window_in_target_root()->GetRootWindow()); - - // Move phantom preview into the right screen. Test that 2 windows got - // created. - controller()->Show(gfx::Rect(600, 100, 50, 60)); - EXPECT_TRUE(IsVisible(phantom_window_in_target_root())); - EXPECT_TRUE(IsVisible(phantom_window_in_start_root())); - EXPECT_EQ(root_windows[1], phantom_window_in_target_root()->GetRootWindow()); - EXPECT_EQ(root_windows[0], phantom_window_in_start_root()->GetRootWindow()); - - // Move phantom preview only in the right screen. Start window should close. - controller()->Show(gfx::Rect(700, 100, 50, 60)); - EXPECT_TRUE(IsVisible(phantom_window_in_target_root())); - EXPECT_FALSE(IsVisible(phantom_window_in_start_root())); - EXPECT_EQ(root_windows[1], phantom_window_in_target_root()->GetRootWindow()); - - // Move phantom preview into the left screen. Start window should open. - controller()->Show(gfx::Rect(100, 100, 50, 60)); - EXPECT_TRUE(IsVisible(phantom_window_in_target_root())); - EXPECT_TRUE(IsVisible(phantom_window_in_start_root())); - EXPECT_EQ(root_windows[0], phantom_window_in_target_root()->GetRootWindow()); - EXPECT_EQ(root_windows[1], phantom_window_in_start_root()->GetRootWindow()); - - // Move phantom preview while in the left screen. Start window should close. - controller()->Show(gfx::Rect(200, 100, 50, 60)); - EXPECT_TRUE(IsVisible(phantom_window_in_target_root())); - EXPECT_FALSE(IsVisible(phantom_window_in_start_root())); - EXPECT_EQ(root_windows[0], phantom_window_in_target_root()->GetRootWindow()); - - // Move phantom preview spanning both screens with most of the preview in the - // right screen. Two windows are created. - controller()->Show(gfx::Rect(495, 100, 50, 60)); - EXPECT_TRUE(IsVisible(phantom_window_in_target_root())); - EXPECT_TRUE(IsVisible(phantom_window_in_start_root())); - EXPECT_EQ(root_windows[1], phantom_window_in_target_root()->GetRootWindow()); - EXPECT_EQ(root_windows[0], phantom_window_in_start_root()->GetRootWindow()); - - // Move phantom preview back into the left screen. Phantom windows should - // swap. - controller()->Show(gfx::Rect(200, 100, 50, 60)); - EXPECT_TRUE(IsVisible(phantom_window_in_target_root())); - EXPECT_TRUE(IsVisible(phantom_window_in_start_root())); - EXPECT_EQ(root_windows[0], phantom_window_in_target_root()->GetRootWindow()); - EXPECT_EQ(root_windows[1], phantom_window_in_start_root()->GetRootWindow()); - - // Destroy phantom controller. Both windows should close. - WindowDeletionObserver target_deletion_observer( - phantom_window_in_target_root()); - WindowDeletionObserver start_deletion_observer( - phantom_window_in_start_root()); - DeleteController(); - EXPECT_FALSE(target_deletion_observer.IsWindowAlive()); - EXPECT_FALSE(start_deletion_observer.IsWindowAlive()); -} - -} // namespace ash diff --git a/ash/wm/workspace/snap_types.h b/ash/wm/workspace/snap_types.h deleted file mode 100644 index 482a7dd583..0000000000 --- a/ash/wm/workspace/snap_types.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_WORKSPACE_SNAP_TYPES_H_ -#define ASH_WM_WORKSPACE_SNAP_TYPES_H_ - -namespace ash { - -// These are the window snap types which can be used for window resizing. -// Their main use case is the class FrameMaximizeButton. -enum SnapType { - SNAP_LEFT, - SNAP_RIGHT, - SNAP_MAXIMIZE, - SNAP_MINIMIZE, - SNAP_RESTORE, - SNAP_NONE -}; - -} // namespace ash - -#endif // ASH_WM_WORKSPACE_SNAP_TYPES_H_ diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc index 75fedaa35a..def6ee8741 100644 --- a/ash/wm/workspace/workspace_window_resizer.cc +++ b/ash/wm/workspace/workspace_window_resizer.cc @@ -911,7 +911,11 @@ void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, } } - const bool can_dock = dock_layout_->CanDockWindow(GetTarget(), snap_type_) && + DCHECK(snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT); + DockedAlignment desired_alignment = (snap_type_ == SNAP_LEFT) ? + DOCKED_ALIGNMENT_LEFT : DOCKED_ALIGNMENT_RIGHT; + const bool can_dock = + dock_layout_->CanDockWindow(GetTarget(), desired_alignment) && dock_layout_->GetAlignmentOfWindow(GetTarget()) != DOCKED_ALIGNMENT_NONE; if (!can_dock) { // If the window cannot be docked, undock the window. This may change the @@ -990,7 +994,7 @@ void WorkspaceWindowResizer::RestackWindows() { } } -SnapType WorkspaceWindowResizer::GetSnapType( +WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( const gfx::Point& location) const { // TODO: this likely only wants total display area, not the area of a single // display. diff --git a/ash/wm/workspace/workspace_window_resizer.h b/ash/wm/workspace/workspace_window_resizer.h index d7d57d0870..99a2df51cd 100644 --- a/ash/wm/workspace/workspace_window_resizer.h +++ b/ash/wm/workspace/workspace_window_resizer.h @@ -9,7 +9,6 @@ #include "ash/wm/window_resizer.h" #include "ash/wm/workspace/magnetism_matcher.h" -#include "ash/wm/workspace/snap_types.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" @@ -69,6 +68,13 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { private: friend class WorkspaceWindowResizerTest; + // The edge to which the window should be snapped at the end of the drag. + enum SnapType { + SNAP_LEFT, + SNAP_RIGHT, + SNAP_NONE + }; + // Lays out the attached windows. |bounds| is the bounds of the main window. void LayoutAttachedWindows(gfx::Rect* bounds); @@ -144,8 +150,9 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { // top of the z-order, and the rest directly underneath it. void RestackWindows(); - // Returns the SnapType for the specified point. SNAP_NONE is used if no - // snapping should be used. + // Returns the edge to which the window should be snapped to if the user does + // no more dragging. SNAP_NONE is returned if the window should not be + // snapped. SnapType GetSnapType(const gfx::Point& location) const; // Returns true if |bounds_in_parent| are valid bounds for snapped state type @@ -186,7 +193,7 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { // the user drags a window to the edge of the screen. scoped_ptr<TwoStepEdgeCycler> edge_cycler_; - // Last SnapType. + // The edge to which the window should be snapped to at the end of the drag. SnapType snap_type_; // Number of mouse moves since the last bounds change. Only used for phantom |