Merge from Chromium at DEPS revision r210036
This commit was generated by merge_to_master.py.
Change-Id: Ib0e33a83ad5dfa541481e83d7acfc6970e68f471
diff --git a/ash/OWNERS b/ash/OWNERS
index ab22b20..55bce5e 100644
--- a/ash/OWNERS
+++ b/ash/OWNERS
@@ -4,6 +4,7 @@
per-file ash_strings.grd=*
per-file ash_chromeos_strings.grdp=*
+per-file ash_switches.*=*
per-file ash_root_window_transformer.*=oshima@chromium.org
per-file extended_desktop_unittest.*=oshima@chromium.org
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index f30ce5d..b96c201 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -39,7 +39,7 @@
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/web_notification/web_notification_tray.h"
-#include "ash/touch/touch_observer_hud.h"
+#include "ash/touch/touch_hud_debug.h"
#include "ash/volume_control_delegate.h"
#include "ash/wm/partial_screenshot_view.h"
#include "ash/wm/power_button_controller.h"
@@ -561,8 +561,8 @@
case TOUCH_HUD_CLEAR: {
internal::RootWindowController* controller =
internal::RootWindowController::ForActiveRootWindow();
- if (controller->touch_observer_hud()) {
- controller->touch_observer_hud()->Clear();
+ if (controller->touch_hud_debug()) {
+ controller->touch_hud_debug()->Clear();
return true;
}
return false;
@@ -570,12 +570,17 @@
case TOUCH_HUD_MODE_CHANGE: {
internal::RootWindowController* controller =
internal::RootWindowController::ForActiveRootWindow();
- if (controller->touch_observer_hud()) {
- controller->touch_observer_hud()->ChangeToNextMode();
+ if (controller->touch_hud_debug()) {
+ controller->touch_hud_debug()->ChangeToNextMode();
return true;
}
return false;
}
+ case TOUCH_HUD_PROJECTION_TOGGLE: {
+ bool enabled = Shell::GetInstance()->is_touch_hud_projection_enabled();
+ Shell::GetInstance()->SetTouchHudProjectionEnabled(!enabled);
+ return true;
+ }
case DISABLE_GPU_WATCHDOG:
content::GpuDataManager::GetInstance()->DisableGpuWatchdog();
return true;
@@ -762,32 +767,32 @@
if (ime_control_delegate_)
return ime_control_delegate_->HandleSwitchIme(accelerator);
break;
- case SELECT_WIN_0:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(0);
+ case LAUNCH_APP_0:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(0);
return true;
- case SELECT_WIN_1:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(1);
+ case LAUNCH_APP_1:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(1);
return true;
- case SELECT_WIN_2:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(2);
+ case LAUNCH_APP_2:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(2);
return true;
- case SELECT_WIN_3:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(3);
+ case LAUNCH_APP_3:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(3);
return true;
- case SELECT_WIN_4:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(4);
+ case LAUNCH_APP_4:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(4);
return true;
- case SELECT_WIN_5:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(5);
+ case LAUNCH_APP_5:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(5);
return true;
- case SELECT_WIN_6:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(6);
+ case LAUNCH_APP_6:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(6);
return true;
- case SELECT_WIN_7:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(7);
+ case LAUNCH_APP_7:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(7);
return true;
- case SELECT_LAST_WIN:
- Launcher::ForPrimaryDisplay()->SwitchToWindow(-1);
+ case LAUNCH_LAST_APP:
+ Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(-1);
return true;
case WINDOW_SNAP_LEFT:
case WINDOW_SNAP_RIGHT: {
@@ -831,10 +836,6 @@
return true;
}
case TOGGLE_MAXIMIZED: {
- if (key_code == ui::VKEY_MEDIA_LAUNCH_APP2) {
- shell->delegate()->RecordUserMetricsAction(
- UMA_ACCEL_MAXIMIZE_RESTORE_F4);
- }
shell->delegate()->ToggleMaximized();
return true;
}
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc
index 874e807..5bfc38a 100644
--- a/ash/accelerators/accelerator_table.cc
+++ b/ash/accelerators/accelerator_table.cc
@@ -74,6 +74,8 @@
TOUCH_HUD_MODE_CHANGE },
{ true, ui::VKEY_I, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN,
TOUCH_HUD_CLEAR },
+ { true, ui::VKEY_9, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+ TOUCH_HUD_PROJECTION_TOGGLE },
// Accessibility: Spoken feedback shortcuts. The first one is to toggle
// spoken feedback on or off. The others are only valid when
// spoken feedback is enabled.
@@ -109,7 +111,7 @@
// extended keyboard shortcuts.
{ false, ui::VKEY_LWIN, ui::EF_NONE, TOGGLE_APP_LIST },
{ false, ui::VKEY_LWIN, ui::EF_ALT_DOWN, TOGGLE_CAPS_LOCK },
- { true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_NONE, TOGGLE_MAXIMIZED },
+ { true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_NONE, TOGGLE_FULLSCREEN },
{ true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_SHIFT_DOWN, TOGGLE_FULLSCREEN },
{ true, ui::VKEY_VOLUME_MUTE, ui::EF_NONE, VOLUME_MUTE },
{ true, ui::VKEY_VOLUME_DOWN, ui::EF_NONE, VOLUME_DOWN },
@@ -130,15 +132,15 @@
{ true, ui::VKEY_S, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
SHOW_SYSTEM_TRAY_BUBBLE },
{ true, ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, SHOW_TASK_MANAGER },
- { true, ui::VKEY_1, ui::EF_ALT_DOWN, SELECT_WIN_0 },
- { true, ui::VKEY_2, ui::EF_ALT_DOWN, SELECT_WIN_1 },
- { true, ui::VKEY_3, ui::EF_ALT_DOWN, SELECT_WIN_2 },
- { true, ui::VKEY_4, ui::EF_ALT_DOWN, SELECT_WIN_3 },
- { true, ui::VKEY_5, ui::EF_ALT_DOWN, SELECT_WIN_4 },
- { true, ui::VKEY_6, ui::EF_ALT_DOWN, SELECT_WIN_5 },
- { true, ui::VKEY_7, ui::EF_ALT_DOWN, SELECT_WIN_6 },
- { true, ui::VKEY_8, ui::EF_ALT_DOWN, SELECT_WIN_7 },
- { true, ui::VKEY_9, ui::EF_ALT_DOWN, SELECT_LAST_WIN },
+ { true, ui::VKEY_1, ui::EF_ALT_DOWN, LAUNCH_APP_0 },
+ { true, ui::VKEY_2, ui::EF_ALT_DOWN, LAUNCH_APP_1 },
+ { true, ui::VKEY_3, ui::EF_ALT_DOWN, LAUNCH_APP_2 },
+ { true, ui::VKEY_4, ui::EF_ALT_DOWN, LAUNCH_APP_3 },
+ { true, ui::VKEY_5, ui::EF_ALT_DOWN, LAUNCH_APP_4 },
+ { true, ui::VKEY_6, ui::EF_ALT_DOWN, LAUNCH_APP_5 },
+ { true, ui::VKEY_7, ui::EF_ALT_DOWN, LAUNCH_APP_6 },
+ { true, ui::VKEY_8, ui::EF_ALT_DOWN, LAUNCH_APP_7 },
+ { true, ui::VKEY_9, ui::EF_ALT_DOWN, LAUNCH_LAST_APP },
// Window management shortcuts.
{ true, ui::VKEY_OEM_4, ui::EF_ALT_DOWN, WINDOW_SNAP_LEFT },
diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h
index 563a7c5..8c400ce 100644
--- a/ash/accelerators/accelerator_table.h
+++ b/ash/accelerators/accelerator_table.h
@@ -34,6 +34,15 @@
FOCUS_PREVIOUS_PANE,
KEYBOARD_BRIGHTNESS_DOWN,
KEYBOARD_BRIGHTNESS_UP,
+ LAUNCH_APP_0,
+ LAUNCH_APP_1,
+ LAUNCH_APP_2,
+ LAUNCH_APP_3,
+ LAUNCH_APP_4,
+ LAUNCH_APP_5,
+ LAUNCH_APP_6,
+ LAUNCH_APP_7,
+ LAUNCH_LAST_APP,
LOCK_PRESSED,
LOCK_RELEASED,
MAGNIFY_SCREEN_ZOOM_IN,
@@ -59,15 +68,6 @@
SCALE_UI_DOWN,
SCALE_UI_RESET,
SCALE_UI_UP,
- SELECT_LAST_WIN,
- SELECT_WIN_0,
- SELECT_WIN_1,
- SELECT_WIN_2,
- SELECT_WIN_3,
- SELECT_WIN_4,
- SELECT_WIN_5,
- SELECT_WIN_6,
- SELECT_WIN_7,
SHOW_KEYBOARD_OVERLAY,
SHOW_MESSAGE_CENTER_BUBBLE,
SHOW_OAK,
@@ -89,6 +89,7 @@
TOGGLE_WIFI,
TOUCH_HUD_CLEAR,
TOUCH_HUD_MODE_CHANGE,
+ TOUCH_HUD_PROJECTION_TOGGLE,
VOLUME_DOWN,
VOLUME_MUTE,
VOLUME_UP,
diff --git a/ash/accelerators/exit_warning_handler.cc b/ash/accelerators/exit_warning_handler.cc
index 36b5b21..767b266 100644
--- a/ash/accelerators/exit_warning_handler.cc
+++ b/ash/accelerators/exit_warning_handler.cc
@@ -8,8 +8,8 @@
#include "ash/shell_delegate.h"
#include "ash/shell_window_ids.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "grit/ash_strings.h"
#include "ui/aura/root_window.h"
#include "ui/base/accessibility/accessible_view_state.h"
@@ -26,7 +26,7 @@
namespace ash {
namespace {
-const int64 kTimeOutMilliseconds = 1000;
+const int64 kTimeOutMilliseconds = 2000;
const SkColor kForegroundColor = 0xFFFFFFFF;
const SkColor kBackgroundColor = 0xE0808080;
const int kHorizontalMarginAroundText = 100;
@@ -168,8 +168,7 @@
ps.width(), ps.height());
views::Widget::InitParams params;
params.type = views::Widget::InitParams::TYPE_POPUP;
- params.transient = true;
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.accept_events = false;
params.can_activate = false;
params.keep_on_top = true;
diff --git a/ash/accelerators/exit_warning_handler.h b/ash/accelerators/exit_warning_handler.h
index 832a3ed..b303d84 100644
--- a/ash/accelerators/exit_warning_handler.h
+++ b/ash/accelerators/exit_warning_handler.h
@@ -6,7 +6,7 @@
#define ASH_ACCELERATORS_EXIT_WARNING_HANDLER_H_
#include "ash/ash_export.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/base/accelerators/accelerator.h"
namespace views {
diff --git a/ash/accelerators/nested_dispatcher_controller_unittest.cc b/ash/accelerators/nested_dispatcher_controller_unittest.cc
index 8febefa..7c06542 100644
--- a/ash/accelerators/nested_dispatcher_controller_unittest.cc
+++ b/ash/accelerators/nested_dispatcher_controller_unittest.cc
@@ -35,7 +35,7 @@
int num_key_events_dispatched() { return num_key_events_dispatched_; }
-#if defined(OS_WIN) || defined(USE_X11) || defined(USE_MESSAGEPUMP_LINUX)
+#if defined(OS_WIN) || defined(USE_X11) || defined(USE_OZONE)
virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE {
if (ui::EventTypeFromNative(event) == ui::ET_KEY_RELEASED)
num_key_events_dispatched_++;
diff --git a/ash/ash.gyp b/ash/ash.gyp
index abbda38..3c7531c 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -92,6 +92,8 @@
'display/display_error_dialog.h',
'display/display_info.h',
'display/display_info.cc',
+ 'display/display_layout.h',
+ 'display/display_layout.cc',
'display/display_manager.cc',
'display/display_manager.h',
'display/display_pref_util.h',
@@ -127,6 +129,8 @@
'keyboard_overlay/keyboard_overlay_delegate.h',
'keyboard_overlay/keyboard_overlay_view.cc',
'keyboard_overlay/keyboard_overlay_view.h',
+ 'launcher/alternate_app_list_button.cc',
+ 'launcher/alternate_app_list_button.h',
'launcher/app_list_button.cc',
'launcher/app_list_button.h',
'launcher/launcher.cc',
@@ -231,6 +235,8 @@
'system/chromeos/network/tray_sms.h',
'system/chromeos/network/tray_vpn.cc',
'system/chromeos/network/tray_vpn.h',
+ 'system/chromeos/power/power_status.cc',
+ 'system/chromeos/power/power_status.h',
'system/chromeos/power/power_status_view.cc',
'system/chromeos/power/power_status_view.h',
'system/chromeos/power/tray_power.cc',
@@ -343,6 +349,10 @@
'system/user/user_observer.h',
'system/web_notification/web_notification_tray.cc',
'system/web_notification/web_notification_tray.h',
+ 'touch/touch_hud_debug.cc',
+ 'touch/touch_hud_debug.h',
+ 'touch/touch_hud_projection.cc',
+ 'touch/touch_hud_projection.h',
'touch/touch_observer_hud.cc',
'touch/touch_observer_hud.h',
'touch/touch_uma.cc',
@@ -412,6 +422,8 @@
'wm/panels/panel_frame_view.h',
'wm/panels/panel_layout_manager.cc',
'wm/panels/panel_layout_manager.h',
+ 'wm/panels/panel_window_event_handler.cc',
+ 'wm/panels/panel_window_event_handler.h',
'wm/panels/panel_window_resizer.cc',
'wm/panels/panel_window_resizer.h',
'wm/partial_screenshot_view.cc',
@@ -539,6 +551,8 @@
['chromeos==1', {
'dependencies': [
'../chromeos/chromeos.gyp:chromeos',
+ # Ash #includes power_supply_properties.pb.h directly.
+ '../chromeos/chromeos.gyp:power_manager_proto',
],
}, { # else: chromeos!=1
'sources/': [
@@ -625,6 +639,7 @@
'../ui/compositor/compositor.gyp:compositor',
'../ui/keyboard/keyboard.gyp:keyboard',
'../ui/message_center/message_center.gyp:message_center',
+ '../ui/message_center/message_center.gyp:message_center_test_support',
'../ui/ui.gyp:ui',
'../ui/ui.gyp:ui_resources',
'../ui/ui.gyp:ui_test_support',
@@ -694,6 +709,10 @@
'shell/window_watcher.cc',
'shell/window_watcher_unittest.cc',
'system/chromeos/network/network_state_notifier_unittest.cc',
+ 'system/chromeos/power/power_status_unittest.cc',
+ 'system/chromeos/power/tray_power_unittest.cc',
+ 'system/chromeos/screen_security/screen_tray_item_unittest.cc',
+ 'system/chromeos/tray_display_unittest.cc',
'system/tray/system_tray_unittest.cc',
'system/user/tray_user_unittest.cc',
'system/web_notification/web_notification_tray_unittest.cc',
@@ -780,6 +799,10 @@
'sources/': [
['exclude', 'display/display_error_dialog_unittest.cc'],
],
+ }, { # chromeos==1
+ 'dependencies': [
+ '../chromeos/chromeos.gyp:power_manager_proto',
+ ],
}],
],
},
diff --git a/ash/ash_chromeos_strings.grdp b/ash/ash_chromeos_strings.grdp
index 1e99643..76b906b 100644
--- a/ash/ash_chromeos_strings.grdp
+++ b/ash/ash_chromeos_strings.grdp
@@ -3,6 +3,14 @@
Everything in this file is wrapped in <if expr="pp_ifdef('chromeos')">. -->
<grit-part>
+ <!-- Status tray charging strings. -->
+ <message name="IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_TITLE" desc="The title of a notification indicating that a low-current USB charger has been connected.">
+ Low-power charger connected
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_MESSAGE" desc="The message body of a notification indicating that a low-current USB charger has been connected.">
+ Your Chromebook may not charge while it is turned on. Consider using the official charger.
+ </message>
+
<!-- Status Tray Network strings -->
<message name="IDS_ASH_STATUS_TRAY_NETWORK" desc="The label used in the network dialog header.">
Network
@@ -250,10 +258,10 @@
Stop
</message>
<message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED" desc="label for screen sharing notification">
- You are being helped
+ Sharing control of your screen via Hangouts.
</message>
<message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED_NAME" desc="label for screen sharing notification with name">
- You are being helped by <ph name="HELPER_NAME">$1<ex>Walder Frey</ex></ph>
+ Sharing control of your screen with <ph name="HELPER_NAME">$1<ex>Walder Frey</ex></ph> via Hangouts.
</message>
</grit-part>
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 53b2547..a49e9bc 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -289,6 +289,9 @@
<message name="IDS_ASH_STATUS_TRAY_UPDATE" desc="The label used in the tray popup to notify that the user should restart to get system updates.">
Restart to update
</message>
+ <message name="IDS_ASH_STATUS_TRAY_RESTART_AND_POWERWASH_UPDATE" desc="The label used in the tray popup to notify that the user should restart and powerwash to get system updates.">
+ Restart and Powerwash to update
+ </message>
<message name="IDS_ASH_STATUS_TRAY_BRIGHTNESS" desc="The accessible text for the brightness slider.">
Brightness
@@ -307,22 +310,37 @@
</message>
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING" desc="The label used in the tray to show that the current status is mirroring.">
- Mirroring to <ph name="DISPLAY_NAME">$1</ph>
+ Mirroring to <ph name="DISPLAY_NAME">$1</ph>
</message>
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED" desc="The label used in the tray to show that the current status is extended.">
- Extending screen to <ph name="DISPLAY_NAME">$1</ph>
+ Extending screen to <ph name="DISPLAY_NAME">$1</ph>
</message>
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL" desc="The label used in the tray to show that the current status is mirroring and the device doesn't have the internal display.">
- Mirroring
+ Mirroring
</message>
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL" desc="The label used in the tray to show that the current status is extended and the device doesn't have the internal display.">
- Extending screen
+ Extending screen
</message>
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED" desc="The label used in the tray to show that the current status is docked mode.">
- Dock mode
+ Dock mode
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED" desc="The label used in the tray to notify that the display resolution settings has changed.">
+ <ph name="DISPLAY_NAME">$1</ph> has been resized to <ph name="RESOLUTION">$2</ph>
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED" desc="The label used in the tray to notify that the display rotation settings has changed.">
+ <ph name="DISPLAY_NAME">$1</ph> has been rotated
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY" desc="The label used in the tray to show a single display's configuration">
+ <ph name="DISPLAY_NAME">$1</ph>: <ph name="ANNOTATION">$2</ph>
</message>
<message name="IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME" desc="Label shown in tray for a display whose name is unknown.">
- Unknown Display
+ Unknown Display
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION" desc="Label used to annotate the display's status like resolution or overscan flag.">
+ <ph name="RESOLUTION">$1</ph>, <ph name="OVERSCAN">$2</ph>
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN" desc="Label used to describe that the system notice that this display device may have overscan area.">
+ overscan
</message>
<message name="IDS_ASH_STATUS_TRAY_DRIVE_SYNCING" desc="The label in the tray to indicate onoing file sync operations.">
Syncing <ph name="count">$1<ex>3</ex></ph> file(s)
@@ -392,13 +410,13 @@
Spoken feedback
</message>
<message name="IDS_ASH_STATUS_TRAY_ACCESSIBILITY_HIGH_CONTRAST_MODE" desc="The label used in the accessibility menu of the system tray to toggle on/off high contrast feature.">
- High contrast
+ High contrast mode
</message>
<message name="IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SCREEN_MAGNIFIER" desc="The label used in the accessibility menu of the system tray to toggle on/off magnifier feature.">
Screen magnifier
</message>
- <message name="IDS_ASH_STATUS_TRAY_ACCESSIBILITY_LARGE_CURSOR" desc="The label used in the accessibility menu of the system tray to toggle on/off large cursor feature.">
- Large cursor
+ <message name="IDS_ASH_STATUS_TRAY_ACCESSIBILITY_LARGE_CURSOR" desc="The label used in the accessibility menu of the system tray to toggle on/off large mouse cursor feature.">
+ Large mouse cursor
</message>
<message name="IDS_ASH_STATUS_TRAY_ACCESSIBILITY_LEARN_MORE" desc="The label used in the accessibility menu of the system tray
to open a webpage (article on help center) containing explanation about accessibility feature.">
@@ -498,13 +516,13 @@
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.
+ Could not mirror displays since no supported resolutions found. Entered extended desktop instead.
</message>
<message name="IDS_ASH_DISPLAY_FAILURE_ON_NON_MIRRORING" desc="An error message to show that the system failed to enter the extended desktop mode or unknown status. Please translate the parentized text.">
- Dear Monitor, it's not working out between us. (That monitor is not supported)
+ Dear Monitor, it's not working out between us. (That monitor is not supported)
</message>
<message name="IDS_ASH_INTERNAL_DISPLAY_NAME" desc="The name of the internal display which is shown in the display settings.">
- Internal Display
+ Internal Display
</message>
<message name="IDS_ASH_LOW_PERIPHERAL_BATTERY_NOTIFICATION_TEXT" desc="The text of the notification when a peripheral device is in low battery condition.">
Battery low (<ph name="percentage">$1<ex>56</ex></ph>%)
@@ -530,7 +548,7 @@
<!-- ChromeOS-specific strings -->
<if expr="pp_ifdef('chromeos')">
- <part file="ash_chromeos_strings.grdp" />
+ <part file="ash_chromeos_strings.grdp" />
</if>
</messages>
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc
index cc64455..2e67ee5 100644
--- a/ash/ash_switches.cc
+++ b/ash/ash_switches.cc
@@ -29,6 +29,17 @@
// Enable keyboard shortcuts useful for debugging.
const char kAshDebugShortcuts[] = "ash-debug-shortcuts";
+// Default wallpaper to use in guest mode (as paths to trusted,
+// non-user-writable JPEG files).
+const char kAshDefaultGuestWallpaperLarge[] =
+ "ash-default-guest-wallpaper-large";
+const char kAshDefaultGuestWallpaperSmall[] =
+ "ash-default-guest-wallpaper-small";
+
+// Default wallpaper to use (as paths to trusted, non-user-writable JPEG files).
+const char kAshDefaultWallpaperLarge[] = "ash-default-wallpaper-large";
+const char kAshDefaultWallpaperSmall[] = "ash-default-wallpaper-small";
+
// Disable auto window maximization logic.
const char kAshDisableAutoMaximizing[] = "ash-disable-auto-maximizing";
@@ -63,6 +74,10 @@
#if defined(OS_CHROMEOS)
// Disable compositor based mirroring.
const char kAshDisableSoftwareMirroring[] = "ash-disable-software-mirroring";
+
+// Disable the notification when a low-power USB charger is connected.
+const char kAshDisableUsbChargerNotification[] =
+ "ash-disable-usb-charger-notification";
#endif
// Extend the status tray volume item to allow the user to choose an audio
@@ -178,5 +193,12 @@
HasSwitch(ash::switches::kAshUseAlternateShelfLayout);
}
+#if defined(OS_CHROMEOS)
+bool UseUsbChargerNotification() {
+ return !CommandLine::ForCurrentProcess()->
+ HasSwitch(ash::switches::kAshDisableUsbChargerNotification);
+}
+#endif
+
} // namespace switches
} // namespace ash
diff --git a/ash/ash_switches.h b/ash/ash_switches.h
index 6414bd9..23eacfc 100644
--- a/ash/ash_switches.h
+++ b/ash/ash_switches.h
@@ -21,6 +21,10 @@
ASH_EXPORT extern const char kAshConstrainPointerToRoot[];
ASH_EXPORT extern const char kAshCopyHostBackgroundAtBoot[];
ASH_EXPORT extern const char kAshDebugShortcuts[];
+ASH_EXPORT extern const char kAshDefaultGuestWallpaperLarge[];
+ASH_EXPORT extern const char kAshDefaultGuestWallpaperSmall[];
+ASH_EXPORT extern const char kAshDefaultWallpaperLarge[];
+ASH_EXPORT extern const char kAshDefaultWallpaperSmall[];
ASH_EXPORT extern const char kAshDisableAutoMaximizing[];
ASH_EXPORT extern const char kAshDisableAutoWindowPlacement[];
ASH_EXPORT extern const char kAshDisableDisplayChangeLimiter[];
@@ -33,6 +37,7 @@
ASH_EXPORT extern const char kAshDisableDragAndDropAppListToLauncher[];
#if defined(OS_CHROMEOS)
ASH_EXPORT extern const char kAshDisableSoftwareMirroring[];
+ASH_EXPORT extern const char kAshDisableUsbChargerNotification[];
#endif
ASH_EXPORT extern const char kAshEnableAudioDeviceMenu[];
ASH_EXPORT extern const char kAshEnableAdvancedGestures[];
@@ -69,6 +74,12 @@
// Returns true if the alternate shelf layout should be used.
ASH_EXPORT bool UseAlternateShelfLayout();
+#if defined(OS_CHROMEOS)
+// Returns true if a notification should appear when a low-power USB charger
+// is connected.
+ASH_EXPORT bool UseUsbChargerNotification();
+#endif
+
} // namespace switches
} // namespace ash
diff --git a/ash/desktop_background/desktop_background_controller.cc b/ash/desktop_background/desktop_background_controller.cc
index 83ffe46..25b63c3 100644
--- a/ash/desktop_background/desktop_background_controller.cc
+++ b/ash/desktop_background/desktop_background_controller.cc
@@ -4,6 +4,7 @@
#include "ash/desktop_background/desktop_background_controller.h"
+#include "ash/ash_switches.h"
#include "ash/desktop_background/desktop_background_controller_observer.h"
#include "ash/desktop_background/desktop_background_view.h"
#include "ash/desktop_background/desktop_background_widget_controller.h"
@@ -13,8 +14,11 @@
#include "ash/shell.h"
#include "ash/shell_factory.h"
#include "ash/shell_window_ids.h"
+#include "ash/wm/property_util.h"
#include "ash/wm/root_window_layout_manager.h"
#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/logging.h"
#include "base/synchronization/cancellation_flag.h"
#include "base/threading/worker_pool.h"
@@ -23,13 +27,12 @@
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
+#include "ui/gfx/codec/jpeg_codec.h"
+#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/rect.h"
-#include "ui/gfx/image/image.h"
#include "ui/views/widget/widget.h"
using ash::internal::DesktopBackgroundWidgetController;
-using ash::internal::kAnimatingDesktopController;
-using ash::internal::kDesktopController;
using content::BrowserThread;
namespace ash {
@@ -61,24 +64,6 @@
} // namespace
-#if defined(GOOGLE_CHROME_BUILD)
-const WallpaperInfo kDefaultLargeWallpaper =
- { IDR_AURA_WALLPAPERS_2_LANDSCAPE8_LARGE, WALLPAPER_LAYOUT_CENTER_CROPPED };
-const WallpaperInfo kDefaultSmallWallpaper =
- { IDR_AURA_WALLPAPERS_2_LANDSCAPE8_SMALL, WALLPAPER_LAYOUT_CENTER };
-const WallpaperInfo kGuestLargeWallpaper =
- { IDR_AURA_WALLPAPERS_2_LANDSCAPE7_LARGE, WALLPAPER_LAYOUT_CENTER_CROPPED };
-const WallpaperInfo kGuestSmallWallpaper =
- { IDR_AURA_WALLPAPERS_2_LANDSCAPE7_SMALL, WALLPAPER_LAYOUT_CENTER };
-#else
-const WallpaperInfo kDefaultLargeWallpaper =
- { IDR_AURA_WALLPAPERS_5_GRADIENT5_LARGE, WALLPAPER_LAYOUT_TILE };
-const WallpaperInfo kDefaultSmallWallpaper =
- { IDR_AURA_WALLPAPERS_5_GRADIENT5_SMALL, WALLPAPER_LAYOUT_TILE };
-const WallpaperInfo kGuestLargeWallpaper = kDefaultLargeWallpaper;
-const WallpaperInfo kGuestSmallWallpaper = kDefaultSmallWallpaper;
-#endif
-
const int kSmallWallpaperMaxWidth = 1366;
const int kSmallWallpaperMaxHeight = 800;
const int kLargeWallpaperMaxWidth = 2560;
@@ -92,23 +77,30 @@
: public base::RefCountedThreadSafe<
DesktopBackgroundController::WallpaperLoader> {
public:
- explicit WallpaperLoader(const WallpaperInfo& info)
- : info_(info) {
+ // If set, |file_path| must be a trusted (i.e. read-only,
+ // non-user-controlled) file containing a JPEG image.
+ WallpaperLoader(const base::FilePath& file_path,
+ WallpaperLayout file_layout,
+ int resource_id,
+ WallpaperLayout resource_layout)
+ : file_path_(file_path),
+ file_layout_(file_layout),
+ resource_id_(resource_id),
+ resource_layout_(resource_layout) {
}
- static void LoadOnWorkerPoolThread(scoped_refptr<WallpaperLoader> wl) {
+ static void LoadOnWorkerPoolThread(scoped_refptr<WallpaperLoader> loader) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- wl->LoadingWallpaper();
+ loader->LoadWallpaper();
}
+ const base::FilePath& file_path() const { return file_path_; }
+ int resource_id() const { return resource_id_; }
+
void Cancel() {
cancel_flag_.Set();
}
- int idr() const {
- return info_.idr;
- }
-
WallpaperResizer* ReleaseWallpaperResizer() {
return wallpaper_resizer_.release();
}
@@ -117,27 +109,74 @@
friend class base::RefCountedThreadSafe<
DesktopBackgroundController::WallpaperLoader>;
- void LoadingWallpaper() {
+ // Loads a JPEG image from |path|, a trusted file -- note that the image
+ // is not loaded in a sandboxed process. Returns an empty pointer on
+ // error.
+ static scoped_ptr<SkBitmap> LoadSkBitmapFromJPEGFile(
+ const base::FilePath& path) {
+ std::string data;
+ if (!file_util::ReadFileToString(path, &data)) {
+ LOG(ERROR) << "Unable to read data from " << path.value();
+ return scoped_ptr<SkBitmap>();
+ }
+
+ scoped_ptr<SkBitmap> bitmap(gfx::JPEGCodec::Decode(
+ reinterpret_cast<const unsigned char*>(data.data()), data.size()));
+ if (!bitmap)
+ LOG(ERROR) << "Unable to decode JPEG data from " << path.value();
+ return bitmap.Pass();
+ }
+
+ void LoadWallpaper() {
if (cancel_flag_.IsSet())
return;
- wallpaper_resizer_.reset(new WallpaperResizer(info_, GetRootWindowsSize()));
+
+ if (!file_path_.empty())
+ file_bitmap_ = LoadSkBitmapFromJPEGFile(file_path_);
+
+ if (cancel_flag_.IsSet())
+ return;
+
+ if (file_bitmap_) {
+ gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(*file_bitmap_);
+ wallpaper_resizer_.reset(new WallpaperResizer(
+ image, GetRootWindowsSize(), file_layout_));
+ } else {
+ wallpaper_resizer_.reset(new WallpaperResizer(
+ resource_id_, GetRootWindowsSize(), resource_layout_));
+ }
}
~WallpaperLoader() {}
base::CancellationFlag cancel_flag_;
+ // Bitmap loaded from |file_path_|.
+ scoped_ptr<SkBitmap> file_bitmap_;
+
scoped_ptr<WallpaperResizer> wallpaper_resizer_;
- const WallpaperInfo info_;
+ // Path to a trusted JPEG file.
+ base::FilePath file_path_;
+
+ // Layout to be used when displaying the image from |file_path_|.
+ WallpaperLayout file_layout_;
+
+ // ID of an image resource to use if |file_path_| is empty or unloadable.
+ int resource_id_;
+
+ // Layout to be used when displaying |resource_id_|.
+ WallpaperLayout resource_layout_;
DISALLOW_COPY_AND_ASSIGN(WallpaperLoader);
};
DesktopBackgroundController::DesktopBackgroundController()
- : locked_(false),
+ : command_line_for_testing_(NULL),
+ locked_(false),
desktop_background_mode_(BACKGROUND_NONE),
background_color_(kTransparentColor),
+ current_default_wallpaper_resource_id_(-1),
weak_ptr_factory_(this) {
}
@@ -163,25 +202,10 @@
WallpaperLayout DesktopBackgroundController::GetWallpaperLayout() const {
if (current_wallpaper_)
- return current_wallpaper_->wallpaper_info().layout;
+ return current_wallpaper_->layout();
return WALLPAPER_LAYOUT_CENTER_CROPPED;
}
-gfx::ImageSkia DesktopBackgroundController::GetCurrentWallpaperImage() {
- if (desktop_background_mode_ != BACKGROUND_IMAGE)
- return gfx::ImageSkia();
- return GetWallpaper();
-}
-
-int DesktopBackgroundController::GetWallpaperIDR() const {
- if (wallpaper_loader_.get())
- return wallpaper_loader_->idr();
- else if (current_wallpaper_)
- return current_wallpaper_->wallpaper_info().idr;
- else
- return -1;
-}
-
void DesktopBackgroundController::OnRootWindowAdded(
aura::RootWindow* root_window) {
// The background hasn't been set yet.
@@ -199,6 +223,8 @@
if (width < root_window_size.width() ||
height < root_window_size.height()) {
current_wallpaper_.reset(NULL);
+ current_default_wallpaper_path_ = base::FilePath();
+ current_default_wallpaper_resource_id_ = -1;
ash::Shell::GetInstance()->user_wallpaper_delegate()->
UpdateWallpaper();
}
@@ -207,34 +233,71 @@
InstallDesktopController(root_window);
}
-void DesktopBackgroundController::SetDefaultWallpaper(
- const WallpaperInfo& info) {
- DCHECK_NE(GetWallpaperIDR(), info.idr);
+bool DesktopBackgroundController::SetDefaultWallpaper(bool is_guest) {
+ const bool use_large =
+ GetAppropriateResolution() == WALLPAPER_RESOLUTION_LARGE;
+
+ base::FilePath file_path;
+ WallpaperLayout file_layout = use_large ? WALLPAPER_LAYOUT_CENTER_CROPPED :
+ WALLPAPER_LAYOUT_CENTER;
+ int resource_id = -1;
+ WallpaperLayout resource_layout = WALLPAPER_LAYOUT_TILE;
+
+#if defined(GOOGLE_CHROME_BUILD)
+ if (use_large) {
+ resource_id = is_guest ? IDR_AURA_WALLPAPERS_2_LANDSCAPE7_LARGE :
+ IDR_AURA_WALLPAPERS_2_LANDSCAPE8_LARGE;
+ resource_layout = WALLPAPER_LAYOUT_CENTER_CROPPED;
+ } else {
+ resource_id = is_guest ? IDR_AURA_WALLPAPERS_2_LANDSCAPE7_SMALL :
+ IDR_AURA_WALLPAPERS_2_LANDSCAPE8_SMALL;
+ resource_layout = WALLPAPER_LAYOUT_CENTER;
+ }
+#else
+ resource_id = use_large ? IDR_AURA_WALLPAPERS_5_GRADIENT5_LARGE :
+ IDR_AURA_WALLPAPERS_5_GRADIENT5_SMALL;
+ resource_layout = WALLPAPER_LAYOUT_TILE;
+#endif
+
+ const char* switch_name = is_guest ?
+ (use_large ? switches::kAshDefaultGuestWallpaperLarge :
+ switches::kAshDefaultGuestWallpaperSmall) :
+ (use_large ? switches::kAshDefaultWallpaperLarge :
+ switches::kAshDefaultWallpaperSmall);
+ CommandLine* command_line = command_line_for_testing_ ?
+ command_line_for_testing_ : CommandLine::ForCurrentProcess();
+ file_path = command_line->GetSwitchValuePath(switch_name);
+
+ if (DefaultWallpaperIsAlreadyLoadingOrLoaded(file_path, resource_id))
+ return false;
CancelPendingWallpaperOperation();
- wallpaper_loader_ = new WallpaperLoader(info);
+ wallpaper_loader_ = new WallpaperLoader(
+ file_path, file_layout, resource_id, resource_layout);
base::WorkerPool::PostTaskAndReply(
FROM_HERE,
base::Bind(&WallpaperLoader::LoadOnWorkerPoolThread, wallpaper_loader_),
- base::Bind(&DesktopBackgroundController::OnWallpaperLoadCompleted,
+ base::Bind(&DesktopBackgroundController::OnDefaultWallpaperLoadCompleted,
weak_ptr_factory_.GetWeakPtr(),
wallpaper_loader_),
true /* task_is_slow */);
+ return true;
}
void DesktopBackgroundController::SetCustomWallpaper(
- const gfx::ImageSkia& wallpaper,
+ const gfx::ImageSkia& image,
WallpaperLayout layout) {
CancelPendingWallpaperOperation();
- if (current_wallpaper_.get() &&
- current_wallpaper_->wallpaper_image().BackedBySameObjectAs(wallpaper)) {
+ if (CustomWallpaperIsAlreadyLoaded(image))
return;
- }
- WallpaperInfo info = { -1, layout };
- current_wallpaper_.reset(new WallpaperResizer(info, GetRootWindowsSize(),
- wallpaper));
+ current_wallpaper_.reset(new WallpaperResizer(
+ image, GetRootWindowsSize(), layout));
current_wallpaper_->StartResize();
+
+ current_default_wallpaper_path_ = base::FilePath();
+ current_default_wallpaper_resource_id_ = -1;
+
FOR_EACH_OBSERVER(DesktopBackgroundControllerObserver, observers_,
OnWallpaperDataChanged());
SetDesktopBackgroundImageMode();
@@ -264,7 +327,6 @@
WallpaperResolution DesktopBackgroundController::GetAppropriateResolution() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- WallpaperResolution resolution = WALLPAPER_RESOLUTION_SMALL;
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
for (Shell::RootWindowList::iterator iter = root_windows.begin();
iter != root_windows.end(); ++iter) {
@@ -274,11 +336,10 @@
// scenario. Revisit and fix if necessary.
gfx::Size host_window_size = (*iter)->GetHostSize();
if (host_window_size.width() > kSmallWallpaperMaxWidth ||
- host_window_size.height() > kSmallWallpaperMaxHeight) {
- resolution = WALLPAPER_RESOLUTION_LARGE;
- }
+ host_window_size.height() > kSmallWallpaperMaxHeight)
+ return WALLPAPER_RESOLUTION_LARGE;
}
- return resolution;
+ return WALLPAPER_RESOLUTION_SMALL;
}
bool DesktopBackgroundController::MoveDesktopToLockedContainer() {
@@ -297,11 +358,20 @@
GetBackgroundContainerId(false));
}
-void DesktopBackgroundController::OnWindowDestroying(aura::Window* window) {
- window->SetProperty(kDesktopController,
- static_cast<internal::DesktopBackgroundWidgetController*>(NULL));
- window->SetProperty(kAnimatingDesktopController,
- static_cast<internal::AnimatingDesktopController*>(NULL));
+bool DesktopBackgroundController::DefaultWallpaperIsAlreadyLoadingOrLoaded(
+ const base::FilePath& image_file, int image_resource_id) const {
+ return (wallpaper_loader_ &&
+ wallpaper_loader_->file_path() == image_file &&
+ wallpaper_loader_->resource_id() == image_resource_id) ||
+ (current_wallpaper_.get() &&
+ current_default_wallpaper_path_ == image_file &&
+ current_default_wallpaper_resource_id_ == image_resource_id);
+}
+
+bool DesktopBackgroundController::CustomWallpaperIsAlreadyLoaded(
+ const gfx::ImageSkia& image) const {
+ return current_wallpaper_.get() &&
+ current_wallpaper_->wallpaper_image().BackedBySameObjectAs(image);
}
void DesktopBackgroundController::SetDesktopBackgroundImageMode() {
@@ -309,24 +379,21 @@
InstallDesktopControllerForAllWindows();
}
-void DesktopBackgroundController::OnWallpaperLoadCompleted(
- scoped_refptr<WallpaperLoader> wl) {
- current_wallpaper_.reset(wl->ReleaseWallpaperResizer());
+void DesktopBackgroundController::OnDefaultWallpaperLoadCompleted(
+ scoped_refptr<WallpaperLoader> loader) {
+ current_wallpaper_.reset(loader->ReleaseWallpaperResizer());
+ current_wallpaper_->StartResize();
+ current_default_wallpaper_path_ = loader->file_path();
+ current_default_wallpaper_resource_id_ = loader->resource_id();
FOR_EACH_OBSERVER(DesktopBackgroundControllerObserver, observers_,
OnWallpaperDataChanged());
SetDesktopBackgroundImageMode();
- DCHECK(wl.get() == wallpaper_loader_.get());
+ DCHECK(loader.get() == wallpaper_loader_.get());
wallpaper_loader_ = NULL;
}
-void DesktopBackgroundController::NotifyAnimationFinished() {
- Shell* shell = Shell::GetInstance();
- shell->GetPrimaryRootWindowController()->HandleDesktopBackgroundVisible();
- shell->user_wallpaper_delegate()->OnWallpaperAnimationFinished();
-}
-
ui::Layer* DesktopBackgroundController::SetColorLayerForContainer(
SkColor color,
aura::RootWindow* root_window,
@@ -336,12 +403,6 @@
Shell::GetContainer(root_window,container_id)->
layer()->Add(background_layer);
-
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&DesktopBackgroundController::NotifyAnimationFinished,
- weak_ptr_factory_.GetWeakPtr()));
-
return background_layer;
}
@@ -368,17 +429,10 @@
NOTREACHED();
return;
}
- // Ensure we're only observing the root window once. Don't rely on a window
- // property check as those can be cleared by tests resetting the background.
- if (!root_window->HasObserver(this))
- root_window->AddObserver(this);
+ GetRootWindowController(root_window)->SetAnimatingWallpaperController(
+ new internal::AnimatingDesktopController(component));
- internal::AnimatingDesktopController* animating_controller =
- root_window->GetProperty(kAnimatingDesktopController);
- if (animating_controller)
- animating_controller->StopAnimating();
- root_window->SetProperty(kAnimatingDesktopController,
- new internal::AnimatingDesktopController(component));
+ component->StartAnimating(GetRootWindowController(root_window));
}
void DesktopBackgroundController::InstallDesktopControllerForAllWindows() {
@@ -392,33 +446,36 @@
bool DesktopBackgroundController::ReparentBackgroundWidgets(int src_container,
int dst_container) {
bool moved = false;
- Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
- for (Shell::RootWindowList::iterator iter = root_windows.begin();
- iter != root_windows.end(); ++iter) {
- aura::RootWindow* root_window = *iter;
+ Shell::RootWindowControllerList controllers =
+ Shell::GetAllRootWindowControllers();
+ for (Shell::RootWindowControllerList::iterator iter = controllers.begin();
+ iter != controllers.end(); ++iter) {
+ internal::RootWindowController* root_window_controller = *iter;
// In the steady state (no animation playing) the background widget
- // controller exists in the kDesktopController property.
- DesktopBackgroundWidgetController* desktop_controller = root_window->
- GetProperty(kDesktopController);
+ // controller exists in the RootWindowController.
+ DesktopBackgroundWidgetController* desktop_controller =
+ root_window_controller->wallpaper_controller();
if (desktop_controller) {
- moved |= desktop_controller->Reparent(root_window,
- src_container,
- dst_container);
+ moved |= desktop_controller->Reparent(
+ root_window_controller->root_window(),
+ src_container,
+ dst_container);
}
// During desktop show animations the controller lives in
- // kAnimatingDesktopController.
+ // AnimatingDesktopController owned by RootWindowController.
// NOTE: If a wallpaper load happens during a desktop show animation there
// can temporarily be two desktop background widgets. We must reparent
// both of them - one above and one here.
DesktopBackgroundWidgetController* animating_controller =
- root_window->GetProperty(kAnimatingDesktopController) ?
- root_window->GetProperty(kAnimatingDesktopController)->
+ root_window_controller->animating_wallpaper_controller() ?
+ root_window_controller->animating_wallpaper_controller()->
GetController(false) :
NULL;
if (animating_controller) {
- moved |= animating_controller->Reparent(root_window,
- src_container,
- dst_container);
+ moved |= animating_controller->Reparent(
+ root_window_controller->root_window(),
+ src_container,
+ dst_container);
}
}
return moved;
diff --git a/ash/desktop_background/desktop_background_controller.h b/ash/desktop_background/desktop_background_controller.h
index b877898..afdc2dc 100644
--- a/ash/desktop_background/desktop_background_controller.h
+++ b/ash/desktop_background/desktop_background_controller.h
@@ -7,16 +7,18 @@
#include "ash/ash_export.h"
#include "base/basictypes.h"
+#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/image/image_skia.h"
typedef unsigned int SkColor;
+class CommandLine;
+
namespace aura {
class RootWindow;
}
@@ -27,9 +29,16 @@
} // namespace internal
enum WallpaperLayout {
+ // Center the wallpaper on the desktop without scaling it. The wallpaper
+ // may be cropped.
WALLPAPER_LAYOUT_CENTER,
+ // Scale the wallpaper (while preserving its aspect ratio) to cover the
+ // desktop; the wallpaper may be cropped.
WALLPAPER_LAYOUT_CENTER_CROPPED,
+ // Scale the wallpaper (without preserving its aspect ratio) to match the
+ // desktop's size.
WALLPAPER_LAYOUT_STRETCH,
+ // Tile the wallpaper over the background without scaling it.
WALLPAPER_LAYOUT_TILE,
};
@@ -40,17 +49,6 @@
const SkColor kLoginWallpaperColor = 0xFEFEFE;
-// Encapsulates wallpaper infomation needed by desktop background controller.
-struct ASH_EXPORT WallpaperInfo {
- int idr;
- WallpaperLayout layout;
-};
-
-ASH_EXPORT extern const WallpaperInfo kDefaultLargeWallpaper;
-ASH_EXPORT extern const WallpaperInfo kDefaultSmallWallpaper;
-ASH_EXPORT extern const WallpaperInfo kGuestLargeWallpaper;
-ASH_EXPORT extern const WallpaperInfo kGuestSmallWallpaper;
-
// The width and height of small/large resolution wallpaper. When screen size is
// smaller than |kSmallWallpaperMaxWidth| and |kSmallWallpaperMaxHeight|, the
// small resolution wallpaper should be used. Otherwise, uses the large
@@ -69,7 +67,7 @@
// Loads selected desktop wallpaper from file system asynchronously and updates
// background layer if loaded successfully.
-class ASH_EXPORT DesktopBackgroundController : public aura::WindowObserver {
+class ASH_EXPORT DesktopBackgroundController {
public:
enum BackgroundMode {
BACKGROUND_NONE,
@@ -80,38 +78,36 @@
DesktopBackgroundController();
virtual ~DesktopBackgroundController();
- // Gets the desktop background mode.
BackgroundMode desktop_background_mode() const {
return desktop_background_mode_;
}
+ void set_command_line_for_testing(CommandLine* command_line) {
+ command_line_for_testing_ = command_line;
+ }
+
// Add/Remove observers.
void AddObserver(DesktopBackgroundControllerObserver* observer);
void RemoveObserver(DesktopBackgroundControllerObserver* observer);
+ // Provides current image on the background, or empty gfx::ImageSkia if there
+ // is no image, e.g. background is solid color.
gfx::ImageSkia GetWallpaper() const;
WallpaperLayout GetWallpaperLayout() const;
- // Provides current image on the background, or empty gfx::ImageSkia if there
- // is no image, e.g. background is solid color.
- gfx::ImageSkia GetCurrentWallpaperImage();
-
- // Gets the IDR of current wallpaper. Returns -1 if current wallpaper is not
- // a builtin wallpaper.
- int GetWallpaperIDR() const;
-
// Initialize root window's background.
void OnRootWindowAdded(aura::RootWindow* root_window);
- // Loads builtin wallpaper asynchronously and sets to current wallpaper after
- // loaded.
- void SetDefaultWallpaper(const WallpaperInfo& info);
+ // Loads builtin wallpaper asynchronously and sets to current wallpaper
+ // after loaded. Returns true if the controller started loading the
+ // wallpaper and false otherwise (i.e. the appropriate wallpaper was
+ // already loading or loaded).
+ bool SetDefaultWallpaper(bool is_guest);
// Sets the user selected custom wallpaper. Called when user selected a file
// from file system or changed the layout of wallpaper.
- void SetCustomWallpaper(const gfx::ImageSkia& wallpaper,
- WallpaperLayout layout);
+ void SetCustomWallpaper(const gfx::ImageSkia& image, WallpaperLayout layout);
// Cancels the current wallpaper loading operation.
void CancelPendingWallpaperOperation();
@@ -139,22 +135,28 @@
// Returns true if the desktop moved.
bool MoveDesktopToUnlockedContainer();
- // WindowObserver implementation.
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
-
private:
friend class internal::DesktopBackgroundControllerTest;
// An operation to asynchronously loads wallpaper.
class WallpaperLoader;
+ // Returns true if the specified default wallpaper is already being
+ // loaded by |wallpaper_loader_| or stored in |current_wallpaper_|.
+ bool DefaultWallpaperIsAlreadyLoadingOrLoaded(
+ const base::FilePath& image_file, int image_resource_id) const;
+
+ // Returns true if the specified custom wallpaper is already stored
+ // in |current_wallpaper_|.
+ bool CustomWallpaperIsAlreadyLoaded(const gfx::ImageSkia& image) const;
+
// Creates view for all root windows, or notifies them to repaint if they
// already exist.
void SetDesktopBackgroundImageMode();
// Creates a new background widget and sets the background mode to image mode.
- // Called after wallpaper loaded successfully.
- void OnWallpaperLoadCompleted(scoped_refptr<WallpaperLoader> wl);
+ // Called after a default wallpaper has been loaded successfully.
+ void OnDefaultWallpaperLoadCompleted(scoped_refptr<WallpaperLoader> loader);
// Adds layer with solid |color| to container |container_id| in |root_window|.
ui::Layer* SetColorLayerForContainer(SkColor color,
@@ -179,6 +181,9 @@
// Send notification that background animation finished.
void NotifyAnimationFinished();
+ // If non-NULL, used in place of the real command line.
+ CommandLine* command_line_for_testing_;
+
// Can change at runtime.
bool locked_;
@@ -191,6 +196,12 @@
// The current wallpaper.
scoped_ptr<WallpaperResizer> current_wallpaper_;
+ // If a default wallpaper is stored in |current_wallpaper_|, the path and
+ // resource ID that were passed to WallpaperLoader when loading it.
+ // Otherwise, empty and -1, respectively.
+ base::FilePath current_default_wallpaper_path_;
+ int current_default_wallpaper_resource_id_;
+
scoped_refptr<WallpaperLoader> wallpaper_loader_;
base::WeakPtrFactory<DesktopBackgroundController> weak_ptr_factory_;
diff --git a/ash/desktop_background/desktop_background_controller_unittest.cc b/ash/desktop_background/desktop_background_controller_unittest.cc
index d513a9c..4eb9b57 100644
--- a/ash/desktop_background/desktop_background_controller_unittest.cc
+++ b/ash/desktop_background/desktop_background_controller_unittest.cc
@@ -4,17 +4,38 @@
#include "ash/desktop_background/desktop_background_controller.h"
+#include <cmath>
+#include <cstdlib>
+
+#include "ash/ash_switches.h"
+#include "ash/desktop_background/desktop_background_controller_observer.h"
#include "ash/desktop_background/desktop_background_widget_controller.h"
+#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
+#include "ash/test/display_manager_test_api.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "content/public/test/test_browser_thread.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/root_window.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/compositor/test/layer_animator_test_controller.h"
+#include "ui/gfx/codec/jpeg_codec.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
using aura::RootWindow;
using aura::Window;
+namespace ash {
+namespace internal {
+
namespace {
// Containers IDs used for tests.
@@ -30,6 +51,31 @@
return static_cast<int>(container->children().size());
}
+class TestObserver : public DesktopBackgroundControllerObserver {
+ public:
+ explicit TestObserver(DesktopBackgroundController* controller)
+ : controller_(controller) {
+ DCHECK(controller_);
+ controller_->AddObserver(this);
+ }
+
+ virtual ~TestObserver() {
+ controller_->RemoveObserver(this);
+ }
+
+ void WaitForWallpaperDataChanged() {
+ base::MessageLoop::current()->Run();
+ }
+
+ // DesktopBackgroundControllerObserver overrides:
+ virtual void OnWallpaperDataChanged() OVERRIDE {
+ base::MessageLoop::current()->Quit();
+ }
+
+ private:
+ DesktopBackgroundController* controller_;
+};
+
// Steps a widget's layer animation until it is completed. Animations must be
// enabled.
void RunAnimationForWidget(views::Widget* widget) {
@@ -51,25 +97,168 @@
} // namespace
-namespace ash {
-namespace internal {
-
class DesktopBackgroundControllerTest : public test::AshTestBase {
public:
- DesktopBackgroundControllerTest() {}
+ DesktopBackgroundControllerTest()
+ : ui_thread_(content::BrowserThread::UI, base::MessageLoop::current()),
+ command_line_(CommandLine::NO_PROGRAM),
+ controller_(NULL) {
+ }
virtual ~DesktopBackgroundControllerTest() {}
virtual void SetUp() OVERRIDE {
test::AshTestBase::SetUp();
// Ash shell initialization creates wallpaper. Reset it so we can manually
// control wallpaper creation and animation in our tests.
- RootWindow* root = Shell::GetPrimaryRootWindow();
- root->SetProperty(kDesktopController,
- static_cast<DesktopBackgroundWidgetController*>(NULL));
- root->SetProperty(kAnimatingDesktopController,
- static_cast<AnimatingDesktopController*>(NULL));
+ RootWindowController* root_window_controller =
+ Shell::GetPrimaryRootWindowController();
+ root_window_controller->SetWallpaperController(NULL);
+ root_window_controller->SetAnimatingWallpaperController(NULL);
+ controller_ = Shell::GetInstance()->desktop_background_controller();
}
+ protected:
+ // Colors used for different default wallpapers by
+ // WriteWallpapersAndSetFlags().
+ static const SkColor kLargeWallpaperColor = SK_ColorRED;
+ static const SkColor kSmallWallpaperColor = SK_ColorGREEN;
+ static const SkColor kLargeGuestWallpaperColor = SK_ColorBLUE;
+ static const SkColor kSmallGuestWallpaperColor = SK_ColorYELLOW;
+
+ // Dimension used for width and height of default wallpaper images. A
+ // small value is used to minimize the amount of time spent compressing
+ // and writing images.
+ static const int kWallpaperSize = 2;
+
+ // Runs kAnimatingDesktopController's animation to completion.
+ // TODO(bshe): Don't require tests to run animations; it's slow.
+ void RunDesktopControllerAnimation() {
+ DesktopBackgroundWidgetController* controller =
+ Shell::GetPrimaryRootWindowController()->
+ animating_wallpaper_controller()->GetController(false);
+ ASSERT_NO_FATAL_FAILURE(RunAnimationForWidget(controller->widget()));
+ }
+
+ // Returns true if the color at the center of |image| is close to
+ // |expected_color|. (The center is used so small wallpaper images can be
+ // used.)
+ bool ImageIsNearColor(gfx::ImageSkia image, SkColor expected_color) {
+ if (image.size().IsEmpty()) {
+ LOG(ERROR) << "Image is empty";
+ return false;
+ }
+
+ const SkBitmap* bitmap = image.bitmap();
+ if (!bitmap) {
+ LOG(ERROR) << "Unable to get bitmap from image";
+ return false;
+ }
+
+ bitmap->lockPixels();
+ gfx::Point center = gfx::Rect(image.size()).CenterPoint();
+ SkColor image_color = bitmap->getColor(center.x(), center.y());
+ bitmap->unlockPixels();
+
+ const int kDiff = 3;
+ if (std::abs(static_cast<int>(SkColorGetA(image_color)) -
+ static_cast<int>(SkColorGetA(expected_color))) > kDiff ||
+ std::abs(static_cast<int>(SkColorGetR(image_color)) -
+ static_cast<int>(SkColorGetR(expected_color))) > kDiff ||
+ std::abs(static_cast<int>(SkColorGetG(image_color)) -
+ static_cast<int>(SkColorGetG(expected_color))) > kDiff ||
+ std::abs(static_cast<int>(SkColorGetB(image_color)) -
+ static_cast<int>(SkColorGetB(expected_color))) > kDiff) {
+ LOG(ERROR) << "Expected color near 0x" << std::hex << expected_color
+ << " but got 0x" << image_color;
+ return false;
+ }
+
+ return true;
+ }
+
+ // Writes a JPEG image of the specified size and color to |path|. Returns
+ // true on success.
+ bool WriteJPEGFile(const base::FilePath& path,
+ int width,
+ int height,
+ SkColor color) {
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
+ bitmap.allocPixels();
+ bitmap.eraseColor(color);
+
+ const int kQuality = 80;
+ std::vector<unsigned char> output;
+ if (!gfx::JPEGCodec::Encode(
+ static_cast<const unsigned char*>(bitmap.getPixels()),
+ gfx::JPEGCodec::FORMAT_SkBitmap, width, height, bitmap.rowBytes(),
+ kQuality, &output)) {
+ LOG(ERROR) << "Unable to encode " << width << "x" << height << " bitmap";
+ return false;
+ }
+
+ size_t bytes_written = file_util::WriteFile(
+ path, reinterpret_cast<const char*>(&output[0]), output.size());
+ if (bytes_written != output.size()) {
+ LOG(ERROR) << "Wrote " << bytes_written << " byte(s) instead of "
+ << output.size() << " to " << path.value();
+ return false;
+ }
+
+ return true;
+ }
+
+ // Initializes |wallpaper_dir_|, writes JPEG wallpaper images to it, and
+ // passes |controller_| a command line instructing it to use the images.
+ // Only needs to be called (once) by tests that want to test loading of
+ // default wallpapers.
+ void WriteWallpapersAndSetFlags() {
+ wallpaper_dir_.reset(new base::ScopedTempDir);
+ ASSERT_TRUE(wallpaper_dir_->CreateUniqueTempDir());
+
+ const base::FilePath kLargePath =
+ wallpaper_dir_->path().Append(FILE_PATH_LITERAL("large.jpg"));
+ ASSERT_TRUE(WriteJPEGFile(kLargePath, kWallpaperSize, kWallpaperSize,
+ kLargeWallpaperColor));
+ command_line_.AppendSwitchPath(
+ switches::kAshDefaultWallpaperLarge, kLargePath);
+
+ const base::FilePath kSmallPath =
+ wallpaper_dir_->path().Append(FILE_PATH_LITERAL("small.jpg"));
+ ASSERT_TRUE(WriteJPEGFile(kSmallPath, kWallpaperSize, kWallpaperSize,
+ kSmallWallpaperColor));
+ command_line_.AppendSwitchPath(
+ switches::kAshDefaultWallpaperSmall, kSmallPath);
+
+ const base::FilePath kLargeGuestPath =
+ wallpaper_dir_->path().Append(FILE_PATH_LITERAL("guest_large.jpg"));
+ ASSERT_TRUE(WriteJPEGFile(kLargeGuestPath, kWallpaperSize, kWallpaperSize,
+ kLargeGuestWallpaperColor));
+ command_line_.AppendSwitchPath(
+ switches::kAshDefaultGuestWallpaperLarge, kLargeGuestPath);
+
+ const base::FilePath kSmallGuestPath =
+ wallpaper_dir_->path().Append(FILE_PATH_LITERAL("guest_small.jpg"));
+ ASSERT_TRUE(WriteJPEGFile(kSmallGuestPath, kWallpaperSize, kWallpaperSize,
+ kSmallGuestWallpaperColor));
+ command_line_.AppendSwitchPath(
+ switches::kAshDefaultGuestWallpaperSmall, kSmallGuestPath);
+
+ controller_->set_command_line_for_testing(&command_line_);
+ }
+
+ content::TestBrowserThread ui_thread_;
+
+ // Custom command line passed to DesktopBackgroundController by
+ // WriteWallpapersAndSetFlags().
+ CommandLine command_line_;
+
+ // Directory created by WriteWallpapersAndSetFlags() to store default
+ // wallpaper images.
+ scoped_ptr<base::ScopedTempDir> wallpaper_dir_;
+
+ DesktopBackgroundController* controller_; // Not owned.
+
private:
DISALLOW_COPY_AND_ASSIGN(DesktopBackgroundControllerTest);
};
@@ -114,24 +303,22 @@
// The new wallpaper is ready to start animating. kAnimatingDesktopController
// holds the widget controller instance. kDesktopController will get it later.
- RootWindow* root = Shell::GetPrimaryRootWindow();
- EXPECT_TRUE(
- root->GetProperty(kAnimatingDesktopController)->GetController(false));
+ RootWindowController* root_window_controller =
+ Shell::GetPrimaryRootWindowController();
+ EXPECT_TRUE(root_window_controller->animating_wallpaper_controller()->
+ GetController(false));
// kDesktopController will receive the widget controller when the animation
// is done.
- EXPECT_FALSE(root->GetProperty(kDesktopController));
+ EXPECT_FALSE(root_window_controller->wallpaper_controller());
// Force the widget's layer animation to play to completion.
- ASSERT_NO_FATAL_FAILURE(
- RunAnimationForWidget(
- root->GetProperty(kAnimatingDesktopController)->GetController(false)->
- widget()));
+ RunDesktopControllerAnimation();
// Ownership has moved from kAnimatingDesktopController to kDesktopController.
- EXPECT_FALSE(
- root->GetProperty(kAnimatingDesktopController)->GetController(false));
- EXPECT_TRUE(root->GetProperty(kDesktopController));
+ EXPECT_FALSE(root_window_controller->animating_wallpaper_controller()->
+ GetController(false));
+ EXPECT_TRUE(root_window_controller->wallpaper_controller());
}
// Test for crbug.com/149043 "Unlock screen, no launcher appears". Ensure we
@@ -147,11 +334,7 @@
controller->CreateEmptyWallpaper();
// Run wallpaper show animation to completion.
- RootWindow* root = Shell::GetPrimaryRootWindow();
- ASSERT_NO_FATAL_FAILURE(
- RunAnimationForWidget(
- root->GetProperty(kAnimatingDesktopController)->GetController(false)->
- widget()));
+ RunDesktopControllerAnimation();
// User locks the screen, which moves the background forward.
controller->MoveDesktopToLockedContainer();
@@ -162,9 +345,11 @@
// In this state we have two desktop background views stored in different
// properties. Both are in the lock screen background container.
- EXPECT_TRUE(
- root->GetProperty(kAnimatingDesktopController)->GetController(false));
- EXPECT_TRUE(root->GetProperty(kDesktopController));
+ RootWindowController* root_window_controller =
+ Shell::GetPrimaryRootWindowController();
+ EXPECT_TRUE(root_window_controller->animating_wallpaper_controller()->
+ GetController(false));
+ EXPECT_TRUE(root_window_controller->wallpaper_controller());
EXPECT_EQ(0, ChildCountForContainer(kDesktopBackgroundId));
EXPECT_EQ(2, ChildCountForContainer(kLockScreenBackgroundId));
@@ -177,10 +362,7 @@
EXPECT_EQ(0, ChildCountForContainer(kLockScreenBackgroundId));
// Finish the new desktop background animation.
- ASSERT_NO_FATAL_FAILURE(
- RunAnimationForWidget(
- root->GetProperty(kAnimatingDesktopController)->GetController(false)->
- widget()));
+ RunDesktopControllerAnimation();
// Now there is one desktop background, in the back.
EXPECT_EQ(1, ChildCountForContainer(kDesktopBackgroundId));
@@ -200,41 +382,149 @@
controller->CreateEmptyWallpaper();
// Run wallpaper show animation to completion.
- RootWindow* root = Shell::GetPrimaryRootWindow();
- ASSERT_NO_FATAL_FAILURE(
- RunAnimationForWidget(
- root->GetProperty(kAnimatingDesktopController)->GetController(false)->
- widget()));
+ RunDesktopControllerAnimation();
// Change to a new wallpaper.
controller->CreateEmptyWallpaper();
- DesktopBackgroundWidgetController* animatingController =
- root->GetProperty(kAnimatingDesktopController)->GetController(false);
- EXPECT_TRUE(animatingController);
- EXPECT_TRUE(root->GetProperty(kDesktopController));
+ RootWindowController* root_window_controller =
+ Shell::GetPrimaryRootWindowController();
+ DesktopBackgroundWidgetController* animating_controller =
+ root_window_controller->animating_wallpaper_controller()->
+ GetController(false);
+ EXPECT_TRUE(animating_controller);
+ EXPECT_TRUE(root_window_controller->wallpaper_controller());
// Change to another wallpaper before animation finished.
controller->CreateEmptyWallpaper();
// The animating controller should immediately move to desktop controller.
- EXPECT_EQ(animatingController, root->GetProperty(kDesktopController));
+ EXPECT_EQ(animating_controller,
+ root_window_controller->wallpaper_controller());
// Cache the new animating controller.
- animatingController =
- root->GetProperty(kAnimatingDesktopController)->GetController(false);
+ animating_controller = root_window_controller->
+ animating_wallpaper_controller()->GetController(false);
// Run wallpaper show animation to completion.
ASSERT_NO_FATAL_FAILURE(
RunAnimationForWidget(
- root->GetProperty(kAnimatingDesktopController)->GetController(false)->
- widget()));
+ root_window_controller->animating_wallpaper_controller()->
+ GetController(false)->widget()));
- EXPECT_TRUE(root->GetProperty(kDesktopController));
- EXPECT_FALSE(
- root->GetProperty(kAnimatingDesktopController)->GetController(false));
+ EXPECT_TRUE(root_window_controller->wallpaper_controller());
+ EXPECT_FALSE(root_window_controller->animating_wallpaper_controller()->
+ GetController(false));
// The desktop controller should be the last created animating controller.
- EXPECT_EQ(animatingController, root->GetProperty(kDesktopController));
+ EXPECT_EQ(animating_controller,
+ root_window_controller->wallpaper_controller());
+}
+
+TEST_F(DesktopBackgroundControllerTest, GetAppropriateResolution) {
+ // TODO(derat|oshima|bshe): Configuring desktops seems busted on Win8,
+ // even when just a single display is being used -- the small wallpaper
+ // is used instead of the large one. Track down the cause of the problem
+ // and only use a SupportsMultipleDisplays() clause for the dual-display
+ // code below.
+ if (!SupportsMultipleDisplays())
+ return;
+
+ test::DisplayManagerTestApi display_manager_test_api(
+ Shell::GetInstance()->display_manager());
+
+ // Small wallpaper images should be used for configurations less than or
+ // equal to kSmallWallpaperMaxWidth by kSmallWallpaperMaxHeight, even if
+ // multiple displays are connected.
+ display_manager_test_api.UpdateDisplay("800x600");
+ EXPECT_EQ(WALLPAPER_RESOLUTION_SMALL,
+ controller_->GetAppropriateResolution());
+ display_manager_test_api.UpdateDisplay("800x600,800x600");
+ EXPECT_EQ(WALLPAPER_RESOLUTION_SMALL,
+ controller_->GetAppropriateResolution());
+ display_manager_test_api.UpdateDisplay("1366x800");
+ EXPECT_EQ(WALLPAPER_RESOLUTION_SMALL,
+ controller_->GetAppropriateResolution());
+
+ // At larger sizes, large wallpapers should be used.
+ display_manager_test_api.UpdateDisplay("1367x800");
+ EXPECT_EQ(WALLPAPER_RESOLUTION_LARGE,
+ controller_->GetAppropriateResolution());
+ display_manager_test_api.UpdateDisplay("1367x801");
+ EXPECT_EQ(WALLPAPER_RESOLUTION_LARGE,
+ controller_->GetAppropriateResolution());
+ display_manager_test_api.UpdateDisplay("2560x1700");
+ EXPECT_EQ(WALLPAPER_RESOLUTION_LARGE,
+ controller_->GetAppropriateResolution());
+}
+
+// Test that DesktopBackgroundController loads the appropriate wallpaper
+// images as specified via command-line flags in various situations.
+// Splitting these into separate tests avoids needing to run animations.
+// TODO(derat): Combine these into a single test -- see
+// RunDesktopControllerAnimation()'s TODO.
+TEST_F(DesktopBackgroundControllerTest, SmallDefaultWallpaper) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ WriteWallpapersAndSetFlags();
+ TestObserver observer(controller_);
+
+ // At 800x600, the small wallpaper should be loaded.
+ test::DisplayManagerTestApi display_manager_test_api(
+ Shell::GetInstance()->display_manager());
+ display_manager_test_api.UpdateDisplay("800x600");
+ ASSERT_TRUE(controller_->SetDefaultWallpaper(false));
+ observer.WaitForWallpaperDataChanged();
+ EXPECT_TRUE(ImageIsNearColor(controller_->GetWallpaper(),
+ kSmallWallpaperColor));
+
+ // Requesting the same wallpaper again should be a no-op.
+ ASSERT_FALSE(controller_->SetDefaultWallpaper(false));
+}
+
+TEST_F(DesktopBackgroundControllerTest, LargeDefaultWallpaper) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ WriteWallpapersAndSetFlags();
+ TestObserver observer(controller_);
+ test::DisplayManagerTestApi display_manager_test_api(
+ Shell::GetInstance()->display_manager());
+ display_manager_test_api.UpdateDisplay("1600x1200");
+ ASSERT_TRUE(controller_->SetDefaultWallpaper(false));
+ observer.WaitForWallpaperDataChanged();
+ EXPECT_TRUE(ImageIsNearColor(controller_->GetWallpaper(),
+ kLargeWallpaperColor));
+}
+
+TEST_F(DesktopBackgroundControllerTest, SmallGuestWallpaper) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ WriteWallpapersAndSetFlags();
+ TestObserver observer(controller_);
+ test::DisplayManagerTestApi display_manager_test_api(
+ Shell::GetInstance()->display_manager());
+ display_manager_test_api.UpdateDisplay("800x600");
+ ASSERT_TRUE(controller_->SetDefaultWallpaper(true));
+ observer.WaitForWallpaperDataChanged();
+ EXPECT_TRUE(ImageIsNearColor(controller_->GetWallpaper(),
+ kSmallGuestWallpaperColor));
+}
+
+TEST_F(DesktopBackgroundControllerTest, LargeGuestWallpaper) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ WriteWallpapersAndSetFlags();
+ TestObserver observer(controller_);
+ test::DisplayManagerTestApi display_manager_test_api(
+ Shell::GetInstance()->display_manager());
+ display_manager_test_api.UpdateDisplay("1600x1200");
+ ASSERT_TRUE(controller_->SetDefaultWallpaper(true));
+ observer.WaitForWallpaperDataChanged();
+ EXPECT_TRUE(ImageIsNearColor(controller_->GetWallpaper(),
+ kLargeGuestWallpaperColor));
}
} // namespace internal
diff --git a/ash/desktop_background/desktop_background_view.cc b/ash/desktop_background/desktop_background_view.cc
index e27a183..daaa6b4 100644
--- a/ash/desktop_background/desktop_background_view.cc
+++ b/ash/desktop_background/desktop_background_view.cc
@@ -21,80 +21,14 @@
#include "ui/aura/root_window.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animation_observer.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_observer.h"
namespace ash {
namespace internal {
namespace {
-class ShowWallpaperAnimationObserver : public ui::ImplicitAnimationObserver,
- public views::WidgetObserver {
- public:
- ShowWallpaperAnimationObserver(aura::RootWindow* root_window,
- views::Widget* desktop_widget,
- bool is_initial_animation)
- : root_window_(root_window),
- desktop_widget_(desktop_widget),
- is_initial_animation_(is_initial_animation) {
- DCHECK(desktop_widget_);
- desktop_widget_->AddObserver(this);
- }
-
- virtual ~ShowWallpaperAnimationObserver() {
- StopObservingImplicitAnimations();
- if (desktop_widget_)
- desktop_widget_->RemoveObserver(this);
- }
-
- private:
- // Overridden from ui::ImplicitAnimationObserver:
- virtual void OnImplicitAnimationsScheduled() OVERRIDE {
- if (is_initial_animation_) {
- GetRootWindowController(root_window_)->
- HandleInitialDesktopBackgroundAnimationStarted();
- }
- }
-
- virtual void OnImplicitAnimationsCompleted() OVERRIDE {
- GetRootWindowController(root_window_)->HandleDesktopBackgroundVisible();
- ash::Shell::GetInstance()->user_wallpaper_delegate()->
- OnWallpaperAnimationFinished();
- // Only removes old component when wallpaper animation finished. If we
- // remove the old one before the new wallpaper is done fading in there will
- // be a white flash during the animation.
- if (root_window_->GetProperty(kAnimatingDesktopController)) {
- DesktopBackgroundWidgetController* controller =
- root_window_->GetProperty(kAnimatingDesktopController)->
- GetController(true);
- // |desktop_widget_| should be the same animating widget we try to move
- // to |kDesktopController|. Otherwise, we may close |desktop_widget_|
- // before move it to |kDesktopController|.
- DCHECK_EQ(controller->widget(), desktop_widget_);
- // Release the old controller and close its background widget.
- root_window_->SetProperty(kDesktopController, controller);
- }
- delete this;
- }
-
- // Overridden from views::WidgetObserver.
- virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
- delete this;
- }
-
- aura::RootWindow* root_window_;
- views::Widget* desktop_widget_;
-
- // Is this object observing the initial brightness/grayscale animation?
- const bool is_initial_animation_;
-
- DISALLOW_COPY_AND_ASSIGN(ShowWallpaperAnimationObserver);
-};
-
// For our scaling ratios we need to round positive numbers.
int RoundPositive(double x) {
return static_cast<int>(floor(x + 0.5));
@@ -188,7 +122,7 @@
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
if (controller->GetWallpaper().isNull())
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.parent = root_window->GetChildById(container_id);
desktop_widget->Init(params);
desktop_widget->SetContentsView(new DesktopBackgroundView());
@@ -196,13 +130,16 @@
views::corewm::SetWindowVisibilityAnimationType(
desktop_widget->GetNativeView(), animation_type);
+ RootWindowController* root_window_controller =
+ GetRootWindowController(root_window);
+
// Enable wallpaper transition for the following cases:
// 1. Initial(OOBE) wallpaper animation.
// 2. Wallpaper fades in from a non empty background.
// 3. From an empty background, chrome transit to a logged in user session.
// 4. From an empty background, guest user logged in.
if (wallpaper_delegate->ShouldShowInitialAnimation() ||
- root_window->GetProperty(kAnimatingDesktopController) ||
+ root_window_controller->animating_wallpaper_controller() ||
Shell::GetInstance()->session_state_delegate()->NumberOfLoggedInUsers()) {
views::corewm::SetWindowVisibilityAnimationTransition(
desktop_widget->GetNativeView(), views::corewm::ANIMATE_SHOW);
@@ -213,14 +150,6 @@
}
desktop_widget->SetBounds(params.parent->bounds());
- ui::ScopedLayerAnimationSettings settings(
- desktop_widget->GetNativeView()->layer()->GetAnimator());
- settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
- settings.AddObserver(new ShowWallpaperAnimationObserver(
- root_window, desktop_widget,
- wallpaper_delegate->ShouldShowInitialAnimation()));
- desktop_widget->Show();
- desktop_widget->GetNativeView()->SetName("DesktopBackgroundView");
return desktop_widget;
}
diff --git a/ash/desktop_background/desktop_background_widget_controller.cc b/ash/desktop_background/desktop_background_widget_controller.cc
index 98d1ba4..cbd7727 100644
--- a/ash/desktop_background/desktop_background_widget_controller.cc
+++ b/ash/desktop_background/desktop_background_widget_controller.cc
@@ -5,23 +5,67 @@
#include "ash/desktop_background/desktop_background_widget_controller.h"
#include "ash/ash_export.h"
+#include "ash/desktop_background/user_wallpaper_delegate.h"
+#include "ash/root_window_controller.h"
+#include "ash/shell.h"
#include "ui/aura/root_window.h"
-#include "ui/aura/window_property.h"
+#include "ui/compositor/layer_animation_observer.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/views/widget/widget.h"
-
-// Exported for tests.
-DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(
- ASH_EXPORT, ash::internal::DesktopBackgroundWidgetController*);
-DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(
- ASH_EXPORT, ash::internal::AnimatingDesktopController*);
+#include "ui/views/widget/widget_observer.h"
namespace ash {
namespace internal {
+namespace {
-DEFINE_OWNED_WINDOW_PROPERTY_KEY(DesktopBackgroundWidgetController,
- kDesktopController, NULL);
-DEFINE_OWNED_WINDOW_PROPERTY_KEY(AnimatingDesktopController,
- kAnimatingDesktopController, NULL);
+class ShowWallpaperAnimationObserver : public ui::ImplicitAnimationObserver,
+ public views::WidgetObserver {
+ public:
+ ShowWallpaperAnimationObserver(RootWindowController* root_window_controller,
+ views::Widget* desktop_widget,
+ bool is_initial_animation)
+ : root_window_controller_(root_window_controller),
+ desktop_widget_(desktop_widget),
+ is_initial_animation_(is_initial_animation) {
+ DCHECK(desktop_widget_);
+ desktop_widget_->AddObserver(this);
+ }
+
+ virtual ~ShowWallpaperAnimationObserver() {
+ StopObservingImplicitAnimations();
+ if (desktop_widget_)
+ desktop_widget_->RemoveObserver(this);
+ }
+
+ private:
+ // Overridden from ui::ImplicitAnimationObserver:
+ virtual void OnImplicitAnimationsScheduled() OVERRIDE {
+ if (is_initial_animation_) {
+ root_window_controller_->
+ HandleInitialDesktopBackgroundAnimationStarted();
+ }
+ }
+
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE {
+ root_window_controller_->OnWallpaperAnimationFinished(desktop_widget_);
+ delete this;
+ }
+
+ // Overridden from views::WidgetObserver.
+ virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
+ delete this;
+ }
+
+ RootWindowController* root_window_controller_;
+ views::Widget* desktop_widget_;
+
+ // Is this object observing the initial brightness/grayscale animation?
+ const bool is_initial_animation_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShowWallpaperAnimationObserver);
+};
+
+} // namespace
DesktopBackgroundWidgetController::DesktopBackgroundWidgetController(
views::Widget* widget) : widget_(widget) {
@@ -63,8 +107,7 @@
views::Widget::ReparentNativeView(widget_->GetNativeView(),
root_window->GetChildById(dest_container));
return true;
- }
- if (layer_) {
+ } else if (layer_) {
ui::Layer* layer = layer_.get();
root_window->GetChildById(src_container)->layer()->Remove(layer);
root_window->GetChildById(dest_container)->layer()->Add(layer);
@@ -74,6 +117,22 @@
return false;
}
+void DesktopBackgroundWidgetController::StartAnimating(
+ RootWindowController* root_window_controller) {
+ if (widget_) {
+ ui::ScopedLayerAnimationSettings settings(
+ widget_->GetNativeView()->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
+ settings.AddObserver(new ShowWallpaperAnimationObserver(
+ root_window_controller, widget_,
+ Shell::GetInstance()->user_wallpaper_delegate()->
+ ShouldShowInitialAnimation()));
+ widget_->Show();
+ widget_->GetNativeView()->SetName("DesktopBackgroundView");
+ } else if (layer_)
+ root_window_controller->OnWallpaperAnimationFinished(NULL);
+}
+
AnimatingDesktopController::AnimatingDesktopController(
DesktopBackgroundWidgetController* component) {
controller_.reset(component);
diff --git a/ash/desktop_background/desktop_background_widget_controller.h b/ash/desktop_background/desktop_background_widget_controller.h
index bf94619..8aa3449 100644
--- a/ash/desktop_background/desktop_background_widget_controller.h
+++ b/ash/desktop_background/desktop_background_widget_controller.h
@@ -14,14 +14,13 @@
namespace ash {
namespace internal {
+class RootWindowController;
// This class hides difference between two possible background implementations:
// effective Layer-based for solid color, and Widget-based for images.
-// DesktopBackgroundWidgetController is installed as an owned property on the
-// RootWindow. To avoid a white flash during wallpaper changes the old
-// DesktopBackgroundWidgetController is moved to a secondary property
-// (kComponentWrapper). When the animation completes the old
-// DesktopBackgroundWidgetController is destroyed. Exported for tests.
+// DesktopBackgroundWidgetController is owned by RootWindowController.
+// When the animation completes the old DesktopBackgroundWidgetController is
+// destroyed. Exported for tests.
class ASH_EXPORT DesktopBackgroundWidgetController
: public views::WidgetObserver {
public:
@@ -44,6 +43,11 @@
int src_container,
int dest_container);
+ // Starts wallpaper fade in animation. |root_window_controller| is
+ // the root window where the animation will happen. (This is
+ // necessary this as |layer_| doesn't have access to the root window).
+ void StartAnimating(RootWindowController* root_window_controller);
+
views::Widget* widget() { return widget_; }
ui::Layer* layer() { return layer_.get(); }
@@ -54,11 +58,10 @@
DISALLOW_COPY_AND_ASSIGN(DesktopBackgroundWidgetController);
};
-// This class wraps a DesktopBackgroundWidgetController pointer. It is installed
-// as an owned property on the RootWindow. DesktopBackgroundWidgetController is
-// moved to this property before animation completes. After animation completes,
-// the kDesktopController property on RootWindow is set to the
-// DesktopBackgroundWidgetController in this class. Exported for tests.
+// This class wraps a DesktopBackgroundWidgetController pointer. It is owned
+// by RootWindowController. The instance of DesktopBackgroundWidgetController is
+// moved to this RootWindowController when the animation completes.
+// Exported for tests.
class ASH_EXPORT AnimatingDesktopController {
public:
explicit AnimatingDesktopController(
@@ -90,17 +93,6 @@
DISALLOW_COPY_AND_ASSIGN(AnimatingDesktopController);
};
-// Window property key, that binds instance of DesktopBackgroundWidgetController
-// to root windows. Owned property.
-ASH_EXPORT extern
- const aura::WindowProperty<DesktopBackgroundWidgetController*>* const
- kDesktopController;
-
-// Wrapper for the DesktopBackgroundWidgetController for a desktop background
-// that is animating in. Owned property.
-ASH_EXPORT extern const aura::WindowProperty<AnimatingDesktopController*>* const
- kAnimatingDesktopController;
-
} // namespace internal
} // namespace ash
diff --git a/ash/desktop_background/wallpaper_resizer.cc b/ash/desktop_background/wallpaper_resizer.cc
index c7e1dda..b75e262 100644
--- a/ash/desktop_background/wallpaper_resizer.cc
+++ b/ash/desktop_background/wallpaper_resizer.cc
@@ -18,91 +18,95 @@
namespace ash {
namespace {
-// Callback used to indicate that wallpaper has been resized.
-typedef base::Callback<void(const SkBitmap&)> ResizedCallback;
-
// For our scaling ratios we need to round positive numbers.
int RoundPositive(double x) {
return static_cast<int>(floor(x + 0.5));
}
-// Resizes |wallpaper| to |target_size| and calls the callback.
-void Resize(const SkBitmap& wallpaper,
- WallpaperLayout layout,
+// Resizes |orig_bitmap| to |target_size| using |layout| and stores the
+// resulting bitmap at |resized_bitmap_out|.
+void Resize(SkBitmap orig_bitmap,
const gfx::Size& target_size,
- base::MessageLoop* origin_loop,
- const ResizedCallback& callback) {
- SkBitmap resized_wallpaper = wallpaper;
- int width = target_size.width();
- int height = target_size.height();
- if (wallpaper.width() > width || wallpaper.height() > height) {
- gfx::Rect wallpaper_rect(0, 0, wallpaper.width(), wallpaper.height());
- gfx::Size cropped_size = gfx::Size(std::min(width, wallpaper.width()),
- std::min(height, wallpaper.height()));
+ WallpaperLayout layout,
+ SkBitmap* resized_bitmap_out) {
+ DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+ SkBitmap new_bitmap = orig_bitmap;
+
+ const int orig_width = orig_bitmap.width();
+ const int orig_height = orig_bitmap.height();
+ const int new_width = target_size.width();
+ const int new_height = target_size.height();
+
+ if (orig_width > new_width || orig_height > new_height) {
+ gfx::Rect wallpaper_rect(0, 0, orig_width, orig_height);
+ gfx::Size cropped_size = gfx::Size(std::min(new_width, orig_width),
+ std::min(new_height, orig_height));
switch (layout) {
case WALLPAPER_LAYOUT_CENTER:
wallpaper_rect.ClampToCenteredSize(cropped_size);
- wallpaper.extractSubset(&resized_wallpaper,
- gfx::RectToSkIRect(wallpaper_rect));
+ orig_bitmap.extractSubset(&new_bitmap,
+ gfx::RectToSkIRect(wallpaper_rect));
break;
case WALLPAPER_LAYOUT_TILE:
wallpaper_rect.set_size(cropped_size);
- wallpaper.extractSubset(&resized_wallpaper,
- gfx::RectToSkIRect(wallpaper_rect));
+ orig_bitmap.extractSubset(&new_bitmap,
+ gfx::RectToSkIRect(wallpaper_rect));
break;
case WALLPAPER_LAYOUT_STRETCH:
- resized_wallpaper = skia::ImageOperations::Resize(
- wallpaper, skia::ImageOperations::RESIZE_LANCZOS3,
- width, height);
+ new_bitmap = skia::ImageOperations::Resize(
+ orig_bitmap, skia::ImageOperations::RESIZE_LANCZOS3,
+ new_width, new_height);
break;
case WALLPAPER_LAYOUT_CENTER_CROPPED:
- if (wallpaper.width() > width && wallpaper.height() > height) {
+ if (orig_width > new_width && orig_height > new_height) {
// The dimension with the smallest ratio must be cropped, the other
// one is preserved. Both are set in gfx::Size cropped_size.
- double horizontal_ratio = static_cast<double>(width) /
- static_cast<double>(wallpaper.width());
- double vertical_ratio = static_cast<double>(height) /
- static_cast<double>(wallpaper.height());
+ double horizontal_ratio = static_cast<double>(new_width) /
+ static_cast<double>(orig_width);
+ double vertical_ratio = static_cast<double>(new_height) /
+ static_cast<double>(orig_height);
if (vertical_ratio > horizontal_ratio) {
cropped_size = gfx::Size(
- RoundPositive(static_cast<double>(width) / vertical_ratio),
- wallpaper.height());
+ RoundPositive(static_cast<double>(new_width) / vertical_ratio),
+ orig_height);
} else {
- cropped_size = gfx::Size(wallpaper.width(),
- RoundPositive(static_cast<double>(height) / horizontal_ratio));
+ cropped_size = gfx::Size(orig_width, RoundPositive(
+ static_cast<double>(new_height) / horizontal_ratio));
}
wallpaper_rect.ClampToCenteredSize(cropped_size);
SkBitmap sub_image;
- wallpaper.extractSubset(&sub_image,
- gfx::RectToSkIRect(wallpaper_rect));
- resized_wallpaper = skia::ImageOperations::Resize(
+ orig_bitmap.extractSubset(&sub_image,
+ gfx::RectToSkIRect(wallpaper_rect));
+ new_bitmap = skia::ImageOperations::Resize(
sub_image, skia::ImageOperations::RESIZE_LANCZOS3,
- width, height);
+ new_width, new_height);
}
}
}
- resized_wallpaper.setImmutable();
- origin_loop->PostTask(FROM_HERE, base::Bind(callback, resized_wallpaper));
+
+ *resized_bitmap_out = new_bitmap;
+ resized_bitmap_out->setImmutable();
}
} // namespace
-WallpaperResizer::WallpaperResizer(const WallpaperInfo& info,
- const gfx::Size& target_size)
- : wallpaper_info_(info),
+WallpaperResizer::WallpaperResizer(int image_resource_id,
+ const gfx::Size& target_size,
+ WallpaperLayout layout)
+ : wallpaper_image_(*(ui::ResourceBundle::GetSharedInstance().
+ GetImageNamed(image_resource_id).ToImageSkia())),
target_size_(target_size),
- wallpaper_image_(*(ui::ResourceBundle::GetSharedInstance().
- GetImageNamed(info.idr).ToImageSkia())),
+ layout_(layout),
weak_ptr_factory_(this) {
}
-WallpaperResizer::WallpaperResizer(const WallpaperInfo& info,
+WallpaperResizer::WallpaperResizer(const gfx::ImageSkia& image,
const gfx::Size& target_size,
- const gfx::ImageSkia& image)
- : wallpaper_info_(info),
+ WallpaperLayout layout)
+ : wallpaper_image_(image),
target_size_(target_size),
- wallpaper_image_(image),
+ layout_(layout),
weak_ptr_factory_(this) {
}
@@ -110,18 +114,17 @@
}
void WallpaperResizer::StartResize() {
- if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ SkBitmap* resized_bitmap = new SkBitmap;
+ if (!content::BrowserThread::PostBlockingPoolTaskAndReply(
FROM_HERE,
- base::Bind(&Resize,
- *wallpaper_image_.bitmap(),
- wallpaper_info_.layout,
- target_size_,
- base::MessageLoop::current(),
- base::Bind(&WallpaperResizer::OnResizeFinished,
- weak_ptr_factory_.GetWeakPtr())),
- base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {
- LOG(WARNING) << "PostSequencedWorkerTask failed. " <<
- "Wallpaper may not be resized.";
+ base::Bind(&Resize, *wallpaper_image_.bitmap(), target_size_,
+ layout_, resized_bitmap),
+ base::Bind(&WallpaperResizer::OnResizeFinished,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(resized_bitmap)))) {
+ LOG(WARNING) << "PostSequencedWorkerTask failed. "
+ << "Wallpaper may not be resized.";
}
}
@@ -133,8 +136,9 @@
observers_.RemoveObserver(observer);
}
-void WallpaperResizer::OnResizeFinished(const SkBitmap& resized_wallpaper) {
- wallpaper_image_ = gfx::ImageSkia::CreateFrom1xBitmap(resized_wallpaper);
+void WallpaperResizer::OnResizeFinished(SkBitmap* resized_bitmap) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ wallpaper_image_ = gfx::ImageSkia::CreateFrom1xBitmap(*resized_bitmap);
FOR_EACH_OBSERVER(WallpaperResizerObserver, observers_,
OnWallpaperResized());
}
diff --git a/ash/desktop_background/wallpaper_resizer.h b/ash/desktop_background/wallpaper_resizer.h
index 9b47b7c..e39dcd5 100644
--- a/ash/desktop_background/wallpaper_resizer.h
+++ b/ash/desktop_background/wallpaper_resizer.h
@@ -10,6 +10,7 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/size.h"
@@ -20,18 +21,21 @@
// Stores the current wallpaper data and resize it to |target_size| if needed.
class ASH_EXPORT WallpaperResizer {
public:
- WallpaperResizer(const WallpaperInfo& info, const gfx::Size& target_size);
+ WallpaperResizer(int image_resource_id,
+ const gfx::Size& target_size,
+ WallpaperLayout layout);
- WallpaperResizer(const WallpaperInfo& info, const gfx::Size& target_size,
- const gfx::ImageSkia& image);
+ WallpaperResizer(const gfx::ImageSkia& image,
+ const gfx::Size& target_size,
+ WallpaperLayout layout);
- virtual ~WallpaperResizer();
-
- const WallpaperInfo& wallpaper_info() const { return wallpaper_info_; }
+ ~WallpaperResizer();
const gfx::ImageSkia& wallpaper_image() const { return wallpaper_image_; }
+ const WallpaperLayout layout() const { return layout_; }
- // Starts resize task on UI thread. It posts task to worker pool.
+ // Called on the UI thread to run Resize() on the worker pool and post an
+ // OnResizeFinished() task back to the UI thread on completion.
void StartResize();
// Add/Remove observers.
@@ -39,16 +43,20 @@
void RemoveObserver(WallpaperResizerObserver* observer);
private:
- // Replaces the orginal uncompressed wallpaper to |resized_wallpaper|.
- void OnResizeFinished(const SkBitmap& resized_wallpaper);
+ // Copies |resized_bitmap| to |wallpaper_image_| and notifies observers
+ // after Resize() has finished running.
+ void OnResizeFinished(SkBitmap* resized_bitmap);
ObserverList<WallpaperResizerObserver> observers_;
- const WallpaperInfo wallpaper_info_;
+ // Image that should currently be used for wallpaper. It initially
+ // contains the original image and is updated to contain the resized
+ // image by OnResizeFinished().
+ gfx::ImageSkia wallpaper_image_;
gfx::Size target_size_;
- gfx::ImageSkia wallpaper_image_;
+ WallpaperLayout layout_;
base::WeakPtrFactory<WallpaperResizer> weak_ptr_factory_;
diff --git a/ash/desktop_background/wallpaper_resizer_unittest.cc b/ash/desktop_background/wallpaper_resizer_unittest.cc
index 0093ade..5761b67 100644
--- a/ash/desktop_background/wallpaper_resizer_unittest.cc
+++ b/ash/desktop_background/wallpaper_resizer_unittest.cc
@@ -5,7 +5,9 @@
#include "ash/desktop_background/wallpaper_resizer.h"
#include "ash/desktop_background/wallpaper_resizer_observer.h"
-#include "ash/test/ash_test_base.h"
+#include "base/message_loop/message_loop.h"
+#include "content/public/test/test_browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/image/image_skia_rep.h"
using aura::RootWindow;
@@ -55,17 +57,19 @@
namespace ash {
namespace internal {
-class WallpaperResizerTest : public test::AshTestBase,
+class WallpaperResizerTest : public testing::Test,
public WallpaperResizerObserver {
public:
- WallpaperResizerTest() {}
+ WallpaperResizerTest()
+ : ui_thread_(content::BrowserThread::UI, &message_loop_) {
+ }
virtual ~WallpaperResizerTest() {}
- gfx::ImageSkia Resize(const WallpaperInfo& info,
+ gfx::ImageSkia Resize(const gfx::ImageSkia& image,
const gfx::Size& target_size,
- const gfx::ImageSkia& image) {
+ WallpaperLayout layout) {
scoped_ptr<WallpaperResizer> resizer;
- resizer.reset(new WallpaperResizer(info, target_size, image));
+ resizer.reset(new WallpaperResizer(image, target_size, layout));
resizer->AddObserver(this);
resizer->StartResize();
WaitForResize();
@@ -74,14 +78,17 @@
}
void WaitForResize() {
- base::MessageLoop::current()->Run();
+ message_loop_.Run();
}
virtual void OnWallpaperResized() OVERRIDE {
- base::MessageLoop::current()->Quit();
+ message_loop_.Quit();
}
private:
+ base::MessageLoop message_loop_;
+ content::TestBrowserThread ui_thread_;
+
DISALLOW_COPY_AND_ASSIGN(WallpaperResizerTest);
};
@@ -97,19 +104,18 @@
for (int i = 0; i < length; i++) {
WallpaperLayout layout = layouts[i];
- WallpaperInfo info = { 0, layout };
gfx::ImageSkia small_image(gfx::ImageSkiaRep(gfx::Size(10, 20),
ui::SCALE_FACTOR_100P));
- gfx::ImageSkia resized_small = Resize(info, gfx::Size(800, 600),
- small_image);
+ gfx::ImageSkia resized_small = Resize(small_image, gfx::Size(800, 600),
+ layout);
EXPECT_EQ(10, resized_small.width());
EXPECT_EQ(20, resized_small.height());
gfx::ImageSkia large_image(gfx::ImageSkiaRep(gfx::Size(1000, 1000),
ui::SCALE_FACTOR_100P));
- gfx::ImageSkia resized_large = Resize(info, gfx::Size(800, 600),
- large_image);
+ gfx::ImageSkia resized_large = Resize(large_image, gfx::Size(800, 600),
+ layout);
EXPECT_EQ(800, resized_large.width());
EXPECT_EQ(600, resized_large.height());
}
@@ -122,18 +128,14 @@
gfx::Size(kTestImageWidth, kTestImageHeight));
gfx::Size target_size = gfx::Size(kTargetWidth, kTargetHeight);
- WallpaperInfo info_center = { 0, WALLPAPER_LAYOUT_CENTER };
- gfx::ImageSkia center = Resize(info_center, target_size, image);
+ gfx::ImageSkia center = Resize(image, target_size, WALLPAPER_LAYOUT_CENTER);
- WallpaperInfo info_center_cropped = { 0, WALLPAPER_LAYOUT_CENTER_CROPPED };
- gfx::ImageSkia center_cropped = Resize(info_center_cropped, target_size,
- image);
+ gfx::ImageSkia center_cropped = Resize(image, target_size,
+ WALLPAPER_LAYOUT_CENTER_CROPPED);
- WallpaperInfo info_stretch = { 0, WALLPAPER_LAYOUT_STRETCH };
- gfx::ImageSkia stretch = Resize(info_stretch, target_size, image);
+ gfx::ImageSkia stretch = Resize(image, target_size, WALLPAPER_LAYOUT_STRETCH);
- WallpaperInfo info_tile = { 0, WALLPAPER_LAYOUT_TILE };
- gfx::ImageSkia tile = Resize(info_tile, target_size, image);
+ gfx::ImageSkia tile = Resize(image, target_size, WALLPAPER_LAYOUT_TILE);
EXPECT_TRUE(IsColor(center, kExpectedCenter));
EXPECT_TRUE(IsColor(center_cropped, kExpectedCenterCropped));
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index bc1aeff..e8186db 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -10,7 +10,6 @@
#include "ash/ash_switches.h"
#include "ash/display/display_manager.h"
-#include "ash/display/display_pref_util.h"
#include "ash/display/root_window_transformers.h"
#include "ash/host/root_window_host_factory.h"
#include "ash/root_window_controller.h"
@@ -20,18 +19,13 @@
#include "ash/wm/property_util.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
-#include "base/json/json_value_converter.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
-#include "base/values.h"
#include "third_party/skia/include/utils/SkMatrix44.h"
#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/aura/root_window_transformer.h"
#include "ui/aura/window.h"
@@ -44,7 +38,7 @@
#if defined(OS_CHROMEOS)
#include "base/chromeos/chromeos_version.h"
-#include "base/time.h"
+#include "base/time/time.h"
#if defined(USE_X11)
#include "ash/display/output_configurator_animation.h"
#include "chromeos/display/output_configurator.h"
@@ -70,14 +64,6 @@
// ash::Shell:: is deleted.
int num_displays_for_shutdown = -1;
-// The maximum value for 'offset' in DisplayLayout in case of outliers. Need
-// to change this value in case to support even larger displays.
-const int kMaxValidOffset = 10000;
-
-// The number of pixels to overlap between the primary and secondary displays,
-// in case that the offset value is too large.
-const int kMinimumOverlapForInvalidOffset = 100;
-
// Specifies how long the display change should have been disabled
// after each display change operations.
// |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
@@ -88,41 +74,6 @@
const int64 kCycleDisplayThrottleTimeoutMs = 4000;
const int64 kSwapDisplayThrottleTimeoutMs = 500;
-// Persistent key names
-const char kPositionKey[] = "position";
-const char kOffsetKey[] = "offset";
-const char kMirroredKey[] = "mirrored";
-const char kPrimaryIdKey[] = "primary-id";
-
-typedef std::map<DisplayLayout::Position, std::string> PositionToStringMap;
-
-const PositionToStringMap* GetPositionToStringMap() {
- static const PositionToStringMap* map = CreateToStringMap(
- DisplayLayout::TOP, "top",
- DisplayLayout::BOTTOM, "bottom",
- DisplayLayout::RIGHT, "right",
- DisplayLayout::LEFT, "left");
- return map;
-}
-
-bool GetPositionFromString(const base::StringPiece& position,
- DisplayLayout::Position* field) {
- if (ReverseFind(GetPositionToStringMap(), position, field))
- return true;
- LOG(ERROR) << "Invalid position value:" << position;
- return false;
-}
-
-std::string GetStringFromPosition(DisplayLayout::Position position) {
- const PositionToStringMap* map = GetPositionToStringMap();
- PositionToStringMap::const_iterator iter = map->find(position);
- return iter != map->end() ? iter->second : std::string("unknown");
-}
-
-bool GetDisplayIdFromString(const base::StringPiece& position, int64* field) {
- return base::StringToInt64(position, field);
-}
-
internal::DisplayManager* GetDisplayManager() {
return Shell::GetInstance()->display_manager();
}
@@ -243,98 +194,6 @@
} // namespace internal
////////////////////////////////////////////////////////////////////////////////
-// DisplayLayout
-
-// static
-DisplayLayout DisplayLayout::FromInts(int position, int offsets) {
- return DisplayLayout(static_cast<Position>(position), offsets);
-}
-
-DisplayLayout::DisplayLayout()
- : position(RIGHT),
- offset(0),
- mirrored(false),
- primary_id(gfx::Display::kInvalidDisplayID) {
-}
-
-DisplayLayout::DisplayLayout(DisplayLayout::Position position, int offset)
- : position(position),
- offset(offset),
- mirrored(false),
- primary_id(gfx::Display::kInvalidDisplayID) {
- DCHECK_LE(TOP, position);
- DCHECK_GE(LEFT, position);
-
- // Set the default value to |position| in case position is invalid. DCHECKs
- // above doesn't stop in Release builds.
- if (TOP > position || LEFT < position)
- this->position = RIGHT;
-
- DCHECK_GE(kMaxValidOffset, abs(offset));
-}
-
-DisplayLayout DisplayLayout::Invert() const {
- Position inverted_position = RIGHT;
- switch (position) {
- case TOP:
- inverted_position = BOTTOM;
- break;
- case BOTTOM:
- inverted_position = TOP;
- break;
- case RIGHT:
- inverted_position = LEFT;
- break;
- case LEFT:
- inverted_position = RIGHT;
- break;
- }
- DisplayLayout ret = DisplayLayout(inverted_position, -offset);
- ret.primary_id = primary_id;
- return ret;
-}
-
-// static
-bool DisplayLayout::ConvertFromValue(const base::Value& value,
- DisplayLayout* layout) {
- base::JSONValueConverter<DisplayLayout> converter;
- return converter.Convert(value, layout);
-}
-
-// static
-bool DisplayLayout::ConvertToValue(const DisplayLayout& layout,
- base::Value* value) {
- base::DictionaryValue* dict_value = NULL;
- if (!value->GetAsDictionary(&dict_value) || dict_value == NULL)
- return false;
-
- const std::string position_str = GetStringFromPosition(layout.position);
- dict_value->SetString(kPositionKey, position_str);
- dict_value->SetInteger(kOffsetKey, layout.offset);
- dict_value->SetBoolean(kMirroredKey, layout.mirrored);
- dict_value->SetString(kPrimaryIdKey, base::Int64ToString(layout.primary_id));
- return true;
-}
-
-std::string DisplayLayout::ToString() const {
- const std::string position_str = GetStringFromPosition(position);
- return base::StringPrintf(
- "%s, %d%s",
- position_str.c_str(), offset, mirrored ? ", mirrored" : "");
-}
-
-// static
-void DisplayLayout::RegisterJSONConverter(
- base::JSONValueConverter<DisplayLayout>* converter) {
- converter->RegisterCustomField<Position>(
- kPositionKey, &DisplayLayout::position, &GetPositionFromString);
- converter->RegisterIntField(kOffsetKey, &DisplayLayout::offset);
- converter->RegisterBoolField(kMirroredKey, &DisplayLayout::mirrored);
- converter->RegisterCustomField<int64>(
- kPrimaryIdKey, &DisplayLayout::primary_id, &GetDisplayIdFromString);
-}
-
-////////////////////////////////////////////////////////////////////////////////
// DisplayChangeLimiter
DisplayController::DisplayChangeLimiter::DisplayChangeLimiter()
@@ -441,11 +300,11 @@
GetDisplayManager()->GetPrimaryDisplayCandidate();
primary_display_id = primary_candidate->id();
AddRootWindowForDisplay(*primary_candidate);
- UpdateDisplayBoundsForLayout();
}
void DisplayController::InitSecondaryDisplays() {
internal::DisplayManager* display_manager = GetDisplayManager();
+ UpdateDisplayBoundsForLayout();
for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
const gfx::Display* display = display_manager->GetDisplayAt(i);
if (primary_display_id != display->id()) {
@@ -454,13 +313,13 @@
}
}
if (display_manager->GetNumDisplays() > 1) {
- UpdateDisplayBoundsForLayout();
DisplayIdPair pair = GetCurrentDisplayIdPair();
DisplayLayout layout = GetCurrentDisplayLayout();
SetPrimaryDisplayId(
layout.primary_id == gfx::Display::kInvalidDisplayID ?
pair.first : layout.primary_id);
}
+ UpdateHostWindowNames();
}
void DisplayController::AddObserver(Observer* observer) {
@@ -517,10 +376,6 @@
GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
}
-void DisplayController::ClearCustomOverscanInsets(int64 display_id) {
- GetDisplayManager()->ClearCustomOverscanInsets(display_id);
-}
-
std::vector<internal::RootWindowController*>
DisplayController::GetAllRootWindowControllers() {
std::vector<internal::RootWindowController*> controllers;
@@ -547,20 +402,6 @@
RegisterLayoutForDisplayIdPairInternal(id1, id2, layout, true);
}
-void DisplayController::RegisterLayoutForDisplayId(
- int64 id,
- const DisplayLayout& layout) {
- int64 first_id = gfx::Display::InternalDisplayId();
- if (first_id == gfx::Display::kInvalidDisplayID)
- first_id = GetDisplayManager()->first_display_id();
- // Caveat: This doesn't work if the machine booted with
- // no display.
- // Ignore if the layout was registered for the internal or
- // 1st display.
- if (first_id != id)
- RegisterLayoutForDisplayIdPairInternal(first_id, id, layout, false);
-}
-
void DisplayController::SetLayoutForCurrentDisplays(
const DisplayLayout& layout_relative_to_primary) {
DCHECK_EQ(2U, GetDisplayManager()->GetNumDisplays());
@@ -578,24 +419,23 @@
to_set.primary_id = primary.id();
paired_layouts_[pair] = to_set;
NotifyDisplayConfigurationChanging();
+ // TODO(oshima): Call UpdateDisplays instead.
UpdateDisplayBoundsForLayout();
NotifyDisplayConfigurationChanged();
}
}
-DisplayLayout DisplayController::GetCurrentDisplayLayout() const {
+DisplayLayout DisplayController::GetCurrentDisplayLayout() {
DCHECK_EQ(2U, GetDisplayManager()->num_connected_displays());
// Invert if the primary was swapped.
if (GetDisplayManager()->num_connected_displays() > 1) {
DisplayIdPair pair = GetCurrentDisplayIdPair();
- DisplayLayout layout = GetRegisteredDisplayLayout(pair);
- const gfx::Display& primary = GetPrimaryDisplay();
- // Invert if the primary was swapped. If mirrored, first is always
- // primary.
- return pair.first == primary.id() ? layout : layout.Invert();
+ return ComputeDisplayLayoutForDisplayIdPair(pair);
}
// On release build, just fallback to default instead of blowing up.
- return default_display_layout_;
+ DisplayLayout layout = default_display_layout_;
+ layout.primary_id = primary_display_id;
+ return layout;
}
DisplayIdPair DisplayController::GetCurrentDisplayIdPair() const {
@@ -617,10 +457,11 @@
}
DisplayLayout DisplayController::GetRegisteredDisplayLayout(
- const DisplayIdPair& pair) const {
+ const DisplayIdPair& pair) {
std::map<DisplayIdPair, DisplayLayout>::const_iterator iter =
paired_layouts_.find(pair);
- return iter != paired_layouts_.end() ? iter->second : default_display_layout_;
+ return
+ iter != paired_layouts_.end() ? iter->second : CreateDisplayLayout(pair);
}
void DisplayController::ToggleMirrorMode() {
@@ -820,22 +661,15 @@
}
void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
- if (limiter_)
- limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
const internal::DisplayInfo& display_info =
GetDisplayManager()->GetDisplayInfo(display.id());
DCHECK(!display_info.bounds_in_pixel().IsEmpty());
-
- UpdateDisplayBoundsForLayout();
aura::RootWindow* root = root_windows_[display.id()];
- SetDisplayPropertiesOnHostWindow(root, display);
root->SetHostBounds(display_info.bounds_in_pixel());
+ SetDisplayPropertiesOnHostWindow(root, display);
}
void DisplayController::OnDisplayAdded(const gfx::Display& display) {
- if (limiter_)
- limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
-
if (primary_root_window_for_replace_) {
DCHECK(root_windows_.empty());
primary_display_id = display.id();
@@ -843,7 +677,6 @@
primary_root_window_for_replace_->SetProperty(
internal::kDisplayIdKey, display.id());
primary_root_window_for_replace_ = NULL;
- UpdateDisplayBoundsForLayout();
const internal::DisplayInfo& display_info =
GetDisplayManager()->GetDisplayInfo(display.id());
root_windows_[display.id()]->SetHostBounds(
@@ -853,15 +686,11 @@
primary_display_id = display.id();
DCHECK(!root_windows_.empty());
aura::RootWindow* root = AddRootWindowForDisplay(display);
- UpdateDisplayBoundsForLayout();
Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
}
}
void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
- if (limiter_)
- limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
-
aura::RootWindow* root_to_delete = root_windows_[display.id()];
DCHECK(root_to_delete) << display.ToString();
@@ -941,49 +770,11 @@
GetDisplayManager()->num_connected_displays() < 2) {
return;
}
-
DCHECK_EQ(2, Shell::GetScreen()->GetNumDisplays());
- const gfx::Rect& primary_bounds = GetPrimaryDisplay().bounds();
-
- gfx::Display* secondary_display = GetSecondaryDisplay();
- const gfx::Rect& secondary_bounds = secondary_display->bounds();
- gfx::Point new_secondary_origin = primary_bounds.origin();
const DisplayLayout layout = GetCurrentDisplayLayout();
- DisplayLayout::Position position = layout.position;
-
- // Ignore the offset in case the secondary display doesn't share edges with
- // the primary display.
- int offset = layout.offset;
- if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) {
- offset = std::min(
- offset, primary_bounds.width() - kMinimumOverlapForInvalidOffset);
- offset = std::max(
- offset, -secondary_bounds.width() + kMinimumOverlapForInvalidOffset);
- } else {
- offset = std::min(
- offset, primary_bounds.height() - kMinimumOverlapForInvalidOffset);
- offset = std::max(
- offset, -secondary_bounds.height() + kMinimumOverlapForInvalidOffset);
- }
- switch (position) {
- case DisplayLayout::TOP:
- new_secondary_origin.Offset(offset, -secondary_bounds.height());
- break;
- case DisplayLayout::RIGHT:
- new_secondary_origin.Offset(primary_bounds.width(), offset);
- break;
- case DisplayLayout::BOTTOM:
- new_secondary_origin.Offset(offset, primary_bounds.height());
- break;
- case DisplayLayout::LEFT:
- new_secondary_origin.Offset(-secondary_bounds.width(), offset);
- break;
- }
- gfx::Insets insets = secondary_display->GetWorkAreaInsets();
- secondary_display->set_bounds(
- gfx::Rect(new_secondary_origin, secondary_bounds.size()));
- secondary_display->UpdateWorkAreaFromInsets(insets);
+ Shell::GetInstance()->display_manager()->UpdateDisplayBoundsForLayout(
+ layout, GetPrimaryDisplay(), GetSecondaryDisplay());
}
void DisplayController::NotifyDisplayConfigurationChanging() {
@@ -996,13 +787,17 @@
void DisplayController::NotifyDisplayConfigurationChanged() {
if (in_bootstrap())
return;
+
+ if (limiter_)
+ limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
+
focus_activation_store_->Restore();
internal::DisplayManager* display_manager = GetDisplayManager();
if (display_manager->num_connected_displays() > 1) {
DisplayIdPair pair = GetCurrentDisplayIdPair();
if (paired_layouts_.find(pair) == paired_layouts_.end())
- paired_layouts_[pair] = default_display_layout_;
+ CreateDisplayLayout(pair);
paired_layouts_[pair].mirrored = display_manager->IsMirrored();
if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
int64 primary_id = paired_layouts_[pair].primary_id;
@@ -1017,6 +812,7 @@
}
}
FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
+ UpdateHostWindowNames();
}
void DisplayController::RegisterLayoutForDisplayIdPairInternal(
@@ -1036,4 +832,40 @@
#endif
}
+DisplayLayout DisplayController::ComputeDisplayLayoutForDisplayIdPair(
+ const DisplayIdPair& pair) {
+ DisplayLayout layout = GetRegisteredDisplayLayout(pair);
+ int64 primary_id = layout.primary_id;
+ // TODO(oshima): replace this with DCHECK.
+ if (primary_id == gfx::Display::kInvalidDisplayID)
+ primary_id = GetPrimaryDisplay().id();
+ // Invert if the primary was swapped. If mirrored, first is always
+ // primary.
+ return pair.first == primary_id ? layout : layout.Invert();
+}
+
+void DisplayController::UpdateHostWindowNames() {
+#if defined(USE_X11)
+ // crbug.com/120229 - set the window title for the primary dislpay
+ // to "aura_root_0" so gtalk can find the primary root window to broadcast.
+ // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
+ aura::RootWindow* primary = Shell::GetPrimaryRootWindow();
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ for (size_t i = 0; i < root_windows.size(); ++i) {
+ std::string name =
+ root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
+ gfx::AcceleratedWidget xwindow = root_windows[i]->GetAcceleratedWidget();
+ XStoreName(ui::GetXDisplay(), xwindow, name.c_str());
+ }
+#endif
+}
+
+DisplayLayout DisplayController::CreateDisplayLayout(
+ const DisplayIdPair& pair) {
+ DisplayLayout layout = default_display_layout_;
+ layout.primary_id = pair.first;
+ paired_layouts_[pair] = layout;
+ return layout;
+}
+
} // namespace ash
diff --git a/ash/display/display_controller.h b/ash/display/display_controller.h
index ca441cb..299be14 100644
--- a/ash/display/display_controller.h
+++ b/ash/display/display_controller.h
@@ -9,14 +9,14 @@
#include <vector>
#include "ash/ash_export.h"
+#include "ash/display/display_layout.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/gfx/display_observer.h"
-#include "ui/gfx/display.h"
namespace aura {
class Display;
@@ -28,61 +28,23 @@
template <typename T> class JSONValueConverter;
}
+namespace gfx {
+class Display;
+class Insets;
+class Point;
+}
+
namespace ash {
namespace internal {
class DisplayManager;
class FocusActivationStore;
+class MirrorWindowController;
class RootWindowController;
}
-typedef std::pair<int64, int64> DisplayIdPair;
-
-struct ASH_EXPORT DisplayLayout {
- // Layout options where the secondary display should be positioned.
- enum Position {
- TOP,
- RIGHT,
- BOTTOM,
- LEFT
- };
- // Factory method to create DisplayLayout from ints. The |mirrored| is
- // set to false and |primary_id| is set to gfx::Display::kInvalidDisplayId.
- // Used for persistence and webui.
- static DisplayLayout FromInts(int position, int offsets);
-
- DisplayLayout();
- DisplayLayout(Position position, int offset);
-
- // Returns an inverted display layout.
- DisplayLayout Invert() const WARN_UNUSED_RESULT;
-
- // Converter functions to/from base::Value.
- static bool ConvertFromValue(const base::Value& value, DisplayLayout* layout);
- static bool ConvertToValue(const DisplayLayout& layout, base::Value* value);
-
- // This method is used by base::JSONValueConverter, you don't need to call
- // this directly. Instead consider using converter functions above.
- static void RegisterJSONConverter(
- base::JSONValueConverter<DisplayLayout>* converter);
-
- Position position;
-
- // The offset of the position of the secondary display. The offset is
- // based on the top/left edge of the primary display.
- int offset;
-
- // True if displays are mirrored.
- bool mirrored;
-
- // The id of the display used as a primary display.
- int64 primary_id;
-
- // Returns string representation of the layout for debugging/testing.
- std::string ToString() const;
-};
-
// DisplayController owns and maintains RootWindows for each attached
// display, keeping them in sync with display configuration changes.
+// TODO(oshima): Factor out the layout registration class.
class ASH_EXPORT DisplayController : public gfx::DisplayObserver {
public:
class ASH_EXPORT Observer {
@@ -164,7 +126,6 @@
// display_manager.h for the details.
gfx::Insets GetOverscanInsets(int64 display_id) const;
void SetOverscanInsets(int64 display_id, const gfx::Insets& insets_in_dip);
- void ClearCustomOverscanInsets(int64 display_id);
const DisplayLayout& default_display_layout() const {
return default_display_layout_;
@@ -175,22 +136,20 @@
void RegisterLayoutForDisplayIdPair(int64 id1,
int64 id2,
const DisplayLayout& layout);
- // OBSOLETE
- // TODO(oshima): Remove this in m28.
- void RegisterLayoutForDisplayId(int64 id, const DisplayLayout& layout);
-
// Sets the layout for the current display pair. The |layout| specifies
// the locaion of the secondary display relative to the primary.
void SetLayoutForCurrentDisplays(const DisplayLayout& layout);
// Returns the display layout used for current displays.
- DisplayLayout GetCurrentDisplayLayout() const;
+ DisplayLayout GetCurrentDisplayLayout();
// Returns the current display pair.
DisplayIdPair GetCurrentDisplayIdPair() const;
// Returns the display layout registered for the given display id |pair|.
- DisplayLayout GetRegisteredDisplayLayout(const DisplayIdPair& pair) const;
+ // If no layout is registered, it creatas new layout using
+ // |default_display_layout_|.
+ DisplayLayout GetRegisteredDisplayLayout(const DisplayIdPair& pair);
// Checks if the mouse pointer is on one of displays, and moves to
// the center of the nearest display if it's outside of all displays.
@@ -210,6 +169,7 @@
private:
friend class internal::DisplayManager;
+ friend class internal::MirrorWindowController;
// Creates a root window for |display| and stores it in the |root_windows_|
// map.
@@ -231,6 +191,17 @@
void OnFadeOutForSwapDisplayFinished();
+ // Returns the display layout for the display id pair
+ // with display swapping applied. That is, this returns
+ // flipped layout if the displays are swapped.
+ DisplayLayout ComputeDisplayLayoutForDisplayIdPair(
+ const DisplayIdPair& display_pair);
+
+ void UpdateHostWindowNames();
+
+ // Creates new layout for display pair from |default_display_layout_|.
+ DisplayLayout CreateDisplayLayout(const DisplayIdPair& display_pair);
+
bool in_bootstrap() const { return in_bootstrap_; }
class DisplayChangeLimiter {
diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc
index 7b41a51..d126c98 100644
--- a/ash/display/display_controller_unittest.cc
+++ b/ash/display/display_controller_unittest.cc
@@ -21,6 +21,12 @@
#include "ui/gfx/screen.h"
#include "ui/views/widget/widget.h"
+#if defined(USE_X11)
+#include "ui/base/x/x11_util.h"
+#include <X11/Xlib.h>
+#undef RootWindow
+#endif
+
namespace ash {
namespace test {
namespace {
@@ -113,8 +119,11 @@
virtual ~TestEventHandler() {}
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- if (event->flags() & ui::EF_IS_SYNTHESIZED)
+ if (event->flags() & ui::EF_IS_SYNTHESIZED &&
+ event->type() != ui::ET_MOUSE_EXITED &&
+ event->type() != ui::ET_MOUSE_ENTERED) {
return;
+ }
aura::Window* target = static_cast<aura::Window*>(event->target());
mouse_location_ = event->root_location();
target_root_ = target->GetRootWindow();
@@ -184,6 +193,21 @@
return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).ui_scale();
}
+#if defined(USE_X11)
+void GetPrimaryAndSeconary(aura::RootWindow** primary,
+ aura::RootWindow** secondary) {
+ *primary = Shell::GetPrimaryRootWindow();
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ *secondary = root_windows[0] == *primary ? root_windows[1] : root_windows[0];
+}
+
+std::string GetXWindowName(aura::RootWindow* window) {
+ char* name = NULL;
+ XFetchName(ui::GetXDisplay(), window->GetAcceleratedWidget(), &name);
+ return std::string(name);
+}
+#endif
+
} // namespace
typedef test::AshTestBase DisplayControllerTest;
@@ -721,7 +745,7 @@
generator.MoveMouseToInHost(20, 25);
EXPECT_EQ("5,15", event_handler.GetLocationAndReset());
- display_controller->ClearCustomOverscanInsets(display1.id());
+ display_controller->SetOverscanInsets(display1.id(), gfx::Insets());
EXPECT_EQ("0,0 120x200", root_windows[0]->bounds().ToString());
EXPECT_EQ("120,0 150x200",
ScreenAsh::GetSecondaryDisplay().bounds().ToString());
@@ -729,6 +753,19 @@
generator.MoveMouseToInHost(30, 20);
EXPECT_EQ("30,20", event_handler.GetLocationAndReset());
+ // Make sure the root window transformer uses correct scale
+ // factor when swapping display. Test crbug.com/253690.
+ UpdateDisplay("400x300*2,600x400/o");
+ root_windows = Shell::GetAllRootWindows();
+ gfx::Point point;
+ Shell::GetAllRootWindows()[1]->GetRootTransform().TransformPoint(point);
+ EXPECT_EQ("15,10", point.ToString());
+
+ display_controller->SwapPrimaryDisplay();
+ point.SetPoint(0, 0);
+ Shell::GetAllRootWindows()[1]->GetRootTransform().TransformPoint(point);
+ EXPECT_EQ("15,10", point.ToString());
+
Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
}
@@ -783,6 +820,7 @@
EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
+#if !defined(OS_WIN)
aura::test::EventGenerator generator2(root_windows[1]);
generator2.MoveMouseToInHost(50, 40);
EXPECT_EQ("179,25", event_handler.GetLocationAndReset());
@@ -799,6 +837,7 @@
generator1.MoveMouseToInHost(50, 40);
EXPECT_EQ("69,159", event_handler.GetLocationAndReset());
+#endif
Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
}
@@ -933,5 +972,29 @@
Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
}
+#if defined(USE_X11)
+TEST_F(DisplayControllerTest, XWidowNameForRootWindow) {
+ EXPECT_EQ("aura_root_0", GetXWindowName(Shell::GetPrimaryRootWindow()));
+
+ // Multiple display.
+ UpdateDisplay("200x200,300x300");
+ aura::RootWindow* primary, *secondary;
+ GetPrimaryAndSeconary(&primary, &secondary);
+ EXPECT_EQ("aura_root_0", GetXWindowName(primary));
+ EXPECT_EQ("aura_root_x", GetXWindowName(secondary));
+
+ // Swap primary.
+ primary = secondary = NULL;
+ Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
+ GetPrimaryAndSeconary(&primary, &secondary);
+ EXPECT_EQ("aura_root_0", GetXWindowName(primary));
+ EXPECT_EQ("aura_root_x", GetXWindowName(secondary));
+
+ // Switching back to single display.
+ UpdateDisplay("300x400");
+ EXPECT_EQ("aura_root_0", GetXWindowName(Shell::GetPrimaryRootWindow()));
+}
+#endif
+
} // namespace test
} // namespace ash
diff --git a/ash/display/display_info.cc b/ash/display/display_info.cc
index 446a0ca..a177000 100644
--- a/ash/display/display_info.cc
+++ b/ash/display/display_info.cc
@@ -40,10 +40,10 @@
static int64 synthesized_display_id = 2200000000LL;
#if defined(OS_WIN)
- gfx::Rect bounds(aura::RootWindowHost::GetNativeScreenSize());
+ gfx::Rect bounds_in_pixel(aura::RootWindowHost::GetNativeScreenSize());
#else
- gfx::Rect bounds(kDefaultHostWindowX, kDefaultHostWindowY,
- kDefaultHostWindowWidth, kDefaultHostWindowHeight);
+ gfx::Rect bounds_in_pixel(kDefaultHostWindowX, kDefaultHostWindowY,
+ kDefaultHostWindowWidth, kDefaultHostWindowHeight);
#endif
std::string main_spec = spec;
@@ -89,7 +89,7 @@
&width, &height, &device_scale_factor) >= 2 ||
sscanf(main_spec.c_str(), "%d+%d-%dx%d*%f", &x, &y, &width, &height,
&device_scale_factor) >= 4) {
- bounds.SetRect(x, y, width, height);
+ bounds_in_pixel.SetRect(x, y, width, height);
}
if (id == gfx::Display::kInvalidDisplayID)
id = synthesized_display_id++;
@@ -98,7 +98,16 @@
display_info.set_device_scale_factor(device_scale_factor);
display_info.set_rotation(rotation);
display_info.set_ui_scale(ui_scale);
- display_info.SetBounds(bounds);
+ display_info.SetBounds(bounds_in_pixel);
+
+ // To test the overscan, it creates the default 5% overscan.
+ if (has_overscan) {
+ int width = bounds_in_pixel.width() / device_scale_factor / 40;
+ int height = bounds_in_pixel.height() / device_scale_factor / 40;
+ display_info.SetOverscanInsets(gfx::Insets(height, width, height, width));
+ display_info.UpdateDisplaySize();
+ }
+
DVLOG(1) << "DisplayInfoFromSpec info=" << display_info.ToString()
<< ", spec=" << spec;
return display_info;
@@ -110,7 +119,6 @@
rotation_(gfx::Display::ROTATE_0),
device_scale_factor_(1.0f),
overscan_insets_in_dip_(0, 0, 0, 0),
- has_custom_overscan_insets_(false),
ui_scale_(1.0f),
native_(false) {
}
@@ -124,7 +132,6 @@
rotation_(gfx::Display::ROTATE_0),
device_scale_factor_(1.0f),
overscan_insets_in_dip_(0, 0, 0, 0),
- has_custom_overscan_insets_(false),
ui_scale_(1.0f),
native_(false) {
}
@@ -142,6 +149,13 @@
size_in_pixel_ = native_info.size_in_pixel_;
device_scale_factor_ = native_info.device_scale_factor_;
+ // Copy overscan_insets_in_dip_ if it's not empty. This is for test
+ // cases which use "/o" annotation which sets the overscan inset
+ // to native, and that overscan has to be propagated. This does not
+ // happen on the real environment.
+ if (!native_info.overscan_insets_in_dip_.empty())
+ overscan_insets_in_dip_ = native_info.overscan_insets_in_dip_;
+
// Rotation_ and ui_scale_ are given by preference, or unit
// tests. Don't copy if this native_info came from
// DisplayChangeObserverX11.
@@ -162,21 +176,10 @@
void DisplayInfo::UpdateDisplaySize() {
size_in_pixel_ = bounds_in_pixel_.size();
- if (has_custom_overscan_insets_) {
+ if (!overscan_insets_in_dip_.empty()) {
gfx::Insets insets_in_pixel =
overscan_insets_in_dip_.Scale(device_scale_factor_);
size_in_pixel_.Enlarge(-insets_in_pixel.width(), -insets_in_pixel.height());
- } else if (has_overscan_) {
- // Currently we assume 5% overscan and hope for the best if TV claims it
- // overscan, but doesn't expose how much.
- // TODO(oshima): The insets has to be applied after rotation.
- // Fix this.
- int width = bounds_in_pixel_.width() / 40;
- int height = bounds_in_pixel_.height() / 40;
- gfx::Insets insets_in_pixel(height, width, height, width);
- overscan_insets_in_dip_ =
- insets_in_pixel.Scale(1.0 / device_scale_factor_);
- size_in_pixel_.Enlarge(-insets_in_pixel.width(), -insets_in_pixel.height());
} else {
overscan_insets_in_dip_.Set(0, 0, 0, 0);
}
@@ -189,9 +192,7 @@
size_in_pixel_ = gfx::ToFlooredSize(size_f);
}
-void DisplayInfo::SetOverscanInsets(bool custom,
- const gfx::Insets& insets_in_dip) {
- has_custom_overscan_insets_ = custom;
+void DisplayInfo::SetOverscanInsets(const gfx::Insets& insets_in_dip) {
overscan_insets_in_dip_ = insets_in_dip;
}
diff --git a/ash/display/display_info.h b/ash/display/display_info.h
index e89c7c4..a679a73 100644
--- a/ash/display/display_info.h
+++ b/ash/display/display_info.h
@@ -66,7 +66,8 @@
// The name of the display.
const std::string& name() const { return name_; }
- // True if the display has overscan.
+ // True if the display EDID has the overscan flag. This does not create the
+ // actual overscan automatically, but used in the message.
bool has_overscan() const { return has_overscan_; }
void set_rotation(gfx::Display::Rotation rotation) { rotation_ = rotation; }
@@ -94,8 +95,7 @@
void set_ui_scale(float scale) { ui_scale_ = scale; }
// Copy the display info except for fields that can be modified by a user
- // (|has_custom_overscan_insets_| and |custom_overscan_insets_in_dip_|,
- // |rotation_| and |ui_scale_|). |rotation_| and |ui_scale_| are copied
+ // (|rotation_| and |ui_scale_|). |rotation_| and |ui_scale_| are copied
// when the |another_info| isn't native one.
void Copy(const DisplayInfo& another_info);
@@ -105,28 +105,12 @@
// Update the |bounds_in_pixel| according to the current overscan
// and rotation settings.
- // 1) If this has custom overscan insets
- // (i.e. |has_custom_overscan_insets_| is true), it simply applies
- // the existing |overscan_insets_in_dip_|.
- // 2) If this doesn't have custom overscan insets but the display claims
- // that it has overscan (|has_overscan_| is true), then updates
- // |overscan_insets_in_dip_| to default value (5% of the display size)
- // and apply the insets.
- // 3) Otherwise, clear the overscan insets.
void UpdateDisplaySize();
// Sets/Clears the overscan insets.
- void SetOverscanInsets(bool custom,
- const gfx::Insets& insets_in_dip);
+ void SetOverscanInsets(const gfx::Insets& insets_in_dip);
gfx::Insets GetOverscanInsetsInPixel() const;
- void clear_has_custom_overscan_insets() {
- has_custom_overscan_insets_ = false;
- }
- bool has_custom_overscan_insets() const {
- return has_custom_overscan_insets_;
- }
-
void set_native(bool native) { native_ = native; }
bool native() const { return native_; }
@@ -134,12 +118,6 @@
std::string ToString() const;
private:
- FRIEND_TEST_ALL_PREFIXES(DisplayManagerTest, AutomaticOverscanInsets);
- // Set the overscan flag. Used for test.
- void set_has_overscan_for_test(bool has_overscan) {
- has_overscan_ = has_overscan;
- }
-
int64 id_;
std::string name_;
bool has_overscan_;
@@ -151,10 +129,6 @@
gfx::Size size_in_pixel_;
gfx::Insets overscan_insets_in_dip_;
- // True if the |overscan_insets_in_dip| is specified by a user. This
- // is used not to override the insets by native insets.
- bool has_custom_overscan_insets_;
-
// UI scale of the display.
float ui_scale_;
diff --git a/ash/display/display_info_unittest.cc b/ash/display/display_info_unittest.cc
index 6806915..d425046 100644
--- a/ash/display/display_info_unittest.cc
+++ b/ash/display/display_info_unittest.cc
@@ -22,19 +22,19 @@
info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/o", 10);
EXPECT_EQ("10,20 300x400", info.bounds_in_pixel().ToString());
- EXPECT_EQ("286x380", info.size_in_pixel().ToString());
+ EXPECT_EQ("288x380", info.size_in_pixel().ToString());
EXPECT_EQ(gfx::Display::ROTATE_0, info.rotation());
EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString());
info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/ob", 10);
EXPECT_EQ("10,20 300x400", info.bounds_in_pixel().ToString());
- EXPECT_EQ("286x380", info.size_in_pixel().ToString());
+ EXPECT_EQ("288x380", info.size_in_pixel().ToString());
EXPECT_EQ(gfx::Display::ROTATE_0, info.rotation());
EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString());
info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/or", 10);
EXPECT_EQ("10,20 300x400", info.bounds_in_pixel().ToString());
- EXPECT_EQ("380x286", info.size_in_pixel().ToString());
+ EXPECT_EQ("380x288", info.size_in_pixel().ToString());
EXPECT_EQ(gfx::Display::ROTATE_90, info.rotation());
// TODO(oshima): This should be rotated too. Fix this.
EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString());
diff --git a/ash/display/display_layout.cc b/ash/display/display_layout.cc
new file mode 100644
index 0000000..a733e76
--- /dev/null
+++ b/ash/display/display_layout.cc
@@ -0,0 +1,152 @@
+// 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/display/display_layout.h"
+
+#include "ash/display/display_pref_util.h"
+#include "base/json/json_value_converter.h"
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "ui/gfx/display.h"
+
+namespace ash {
+namespace {
+
+// The maximum value for 'offset' in DisplayLayout in case of outliers. Need
+// to change this value in case to support even larger displays.
+const int kMaxValidOffset = 10000;
+
+// Persistent key names
+const char kPositionKey[] = "position";
+const char kOffsetKey[] = "offset";
+const char kMirroredKey[] = "mirrored";
+const char kPrimaryIdKey[] = "primary-id";
+
+typedef std::map<DisplayLayout::Position, std::string> PositionToStringMap;
+
+const PositionToStringMap* GetPositionToStringMap() {
+ static const PositionToStringMap* map = CreateToStringMap(
+ DisplayLayout::TOP, "top",
+ DisplayLayout::BOTTOM, "bottom",
+ DisplayLayout::RIGHT, "right",
+ DisplayLayout::LEFT, "left");
+ return map;
+}
+
+bool GetPositionFromString(const base::StringPiece& position,
+ DisplayLayout::Position* field) {
+ if (ReverseFind(GetPositionToStringMap(), position, field))
+ return true;
+ LOG(ERROR) << "Invalid position value:" << position;
+ return false;
+}
+
+std::string GetStringFromPosition(DisplayLayout::Position position) {
+ const PositionToStringMap* map = GetPositionToStringMap();
+ PositionToStringMap::const_iterator iter = map->find(position);
+ return iter != map->end() ? iter->second : std::string("unknown");
+}
+
+bool GetDisplayIdFromString(const base::StringPiece& position, int64* field) {
+ return base::StringToInt64(position, field);
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// DisplayLayout
+
+// static
+DisplayLayout DisplayLayout::FromInts(int position, int offsets) {
+ return DisplayLayout(static_cast<Position>(position), offsets);
+}
+
+DisplayLayout::DisplayLayout()
+ : position(RIGHT),
+ offset(0),
+ mirrored(false),
+ primary_id(gfx::Display::kInvalidDisplayID) {
+}
+
+DisplayLayout::DisplayLayout(DisplayLayout::Position position, int offset)
+ : position(position),
+ offset(offset),
+ mirrored(false),
+ primary_id(gfx::Display::kInvalidDisplayID) {
+ DCHECK_LE(TOP, position);
+ DCHECK_GE(LEFT, position);
+
+ // Set the default value to |position| in case position is invalid. DCHECKs
+ // above doesn't stop in Release builds.
+ if (TOP > position || LEFT < position)
+ this->position = RIGHT;
+
+ DCHECK_GE(kMaxValidOffset, abs(offset));
+}
+
+DisplayLayout DisplayLayout::Invert() const {
+ Position inverted_position = RIGHT;
+ switch (position) {
+ case TOP:
+ inverted_position = BOTTOM;
+ break;
+ case BOTTOM:
+ inverted_position = TOP;
+ break;
+ case RIGHT:
+ inverted_position = LEFT;
+ break;
+ case LEFT:
+ inverted_position = RIGHT;
+ break;
+ }
+ DisplayLayout ret = DisplayLayout(inverted_position, -offset);
+ ret.primary_id = primary_id;
+ return ret;
+}
+
+// static
+bool DisplayLayout::ConvertFromValue(const base::Value& value,
+ DisplayLayout* layout) {
+ base::JSONValueConverter<DisplayLayout> converter;
+ return converter.Convert(value, layout);
+}
+
+// static
+bool DisplayLayout::ConvertToValue(const DisplayLayout& layout,
+ base::Value* value) {
+ base::DictionaryValue* dict_value = NULL;
+ if (!value->GetAsDictionary(&dict_value) || dict_value == NULL)
+ return false;
+
+ const std::string position_str = GetStringFromPosition(layout.position);
+ dict_value->SetString(kPositionKey, position_str);
+ dict_value->SetInteger(kOffsetKey, layout.offset);
+ dict_value->SetBoolean(kMirroredKey, layout.mirrored);
+ dict_value->SetString(kPrimaryIdKey, base::Int64ToString(layout.primary_id));
+ return true;
+}
+
+std::string DisplayLayout::ToString() const {
+ const std::string position_str = GetStringFromPosition(position);
+ return base::StringPrintf(
+ "%s, %d%s",
+ position_str.c_str(), offset, mirrored ? ", mirrored" : "");
+}
+
+// static
+void DisplayLayout::RegisterJSONConverter(
+ base::JSONValueConverter<DisplayLayout>* converter) {
+ converter->RegisterCustomField<Position>(
+ kPositionKey, &DisplayLayout::position, &GetPositionFromString);
+ converter->RegisterIntField(kOffsetKey, &DisplayLayout::offset);
+ converter->RegisterBoolField(kMirroredKey, &DisplayLayout::mirrored);
+ converter->RegisterCustomField<int64>(
+ kPrimaryIdKey, &DisplayLayout::primary_id, &GetDisplayIdFromString);
+}
+
+} // namespace ash
diff --git a/ash/display/display_layout.h b/ash/display/display_layout.h
new file mode 100644
index 0000000..dc32208
--- /dev/null
+++ b/ash/display/display_layout.h
@@ -0,0 +1,71 @@
+// 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_DISPLAY_DISPLAY_LAYOUT_H_
+#define ASH_DISPLAY_DISPLAY_LAYOUT_H_
+
+#include <map>
+#include <string>
+
+#include "ash/ash_export.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+
+namespace base {
+class Value;
+template <typename T> class JSONValueConverter;
+}
+
+namespace ash {
+
+typedef std::pair<int64, int64> DisplayIdPair;
+
+struct ASH_EXPORT DisplayLayout {
+ // Layout options where the secondary display should be positioned.
+ enum Position {
+ TOP,
+ RIGHT,
+ BOTTOM,
+ LEFT
+ };
+
+ // Factory method to create DisplayLayout from ints. The |mirrored| is
+ // set to false and |primary_id| is set to gfx::Display::kInvalidDisplayId.
+ // Used for persistence and webui.
+ static DisplayLayout FromInts(int position, int offsets);
+
+ DisplayLayout();
+ DisplayLayout(Position position, int offset);
+
+ // Returns an inverted display layout.
+ DisplayLayout Invert() const WARN_UNUSED_RESULT;
+
+ // Converter functions to/from base::Value.
+ static bool ConvertFromValue(const base::Value& value, DisplayLayout* layout);
+ static bool ConvertToValue(const DisplayLayout& layout, base::Value* value);
+
+ // This method is used by base::JSONValueConverter, you don't need to call
+ // this directly. Instead consider using converter functions above.
+ static void RegisterJSONConverter(
+ base::JSONValueConverter<DisplayLayout>* converter);
+
+ Position position;
+
+ // The offset of the position of the secondary display. The offset is
+ // based on the top/left edge of the primary display.
+ int offset;
+
+ // True if displays are mirrored.
+ bool mirrored;
+
+ // The id of the display used as a primary display.
+ int64 primary_id;
+
+ // Returns string representation of the layout for debugging/testing.
+ std::string ToString() const;
+};
+
+} // namespace ash
+
+#endif
diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc
index eceb643..11fb650 100644
--- a/ash/display/display_manager.cc
+++ b/ash/display/display_manager.cc
@@ -58,6 +58,10 @@
namespace {
+// The number of pixels to overlap between the primary and secondary displays,
+// in case that the offset value is too large.
+const int kMinimumOverlapForInvalidOffset = 100;
+
// List of value UI Scale values. Scales for 2x are equivalent to 640,
// 800, 1024, 1280, 1440, 1600 and 1920 pixel width respectively on
// 2560 pixel width 2x density display. Please see crbug.com/233375
@@ -192,6 +196,54 @@
return 1.0f;
}
+void DisplayManager::UpdateDisplayBoundsForLayout(
+ const DisplayLayout& layout,
+ const gfx::Display& primary_display,
+ gfx::Display* secondary_display) {
+ DCHECK_EQ("0,0", primary_display.bounds().origin().ToString());
+
+ const gfx::Rect& primary_bounds = primary_display.bounds();
+ DisplayController::GetPrimaryDisplay().bounds();
+
+ const gfx::Rect& secondary_bounds = secondary_display->bounds();
+ gfx::Point new_secondary_origin = primary_bounds.origin();
+
+ DisplayLayout::Position position = layout.position;
+
+ // Ignore the offset in case the secondary display doesn't share edges with
+ // the primary display.
+ int offset = layout.offset;
+ if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) {
+ offset = std::min(
+ offset, primary_bounds.width() - kMinimumOverlapForInvalidOffset);
+ offset = std::max(
+ offset, -secondary_bounds.width() + kMinimumOverlapForInvalidOffset);
+ } else {
+ offset = std::min(
+ offset, primary_bounds.height() - kMinimumOverlapForInvalidOffset);
+ offset = std::max(
+ offset, -secondary_bounds.height() + kMinimumOverlapForInvalidOffset);
+ }
+ switch (position) {
+ case DisplayLayout::TOP:
+ new_secondary_origin.Offset(offset, -secondary_bounds.height());
+ break;
+ case DisplayLayout::RIGHT:
+ new_secondary_origin.Offset(primary_bounds.width(), offset);
+ break;
+ case DisplayLayout::BOTTOM:
+ new_secondary_origin.Offset(offset, primary_bounds.height());
+ break;
+ case DisplayLayout::LEFT:
+ new_secondary_origin.Offset(-secondary_bounds.width(), offset);
+ break;
+ }
+ gfx::Insets insets = secondary_display->GetWorkAreaInsets();
+ secondary_display->set_bounds(
+ gfx::Rect(new_secondary_origin, secondary_bounds.size()));
+ secondary_display->UpdateWorkAreaFromInsets(insets);
+}
+
bool DisplayManager::IsActiveDisplay(const gfx::Display& display) const {
for (DisplayList::const_iterator iter = displays_.begin();
iter != displays_.end(); ++iter) {
@@ -236,20 +288,7 @@
void DisplayManager::SetOverscanInsets(int64 display_id,
const gfx::Insets& insets_in_dip) {
- // TODO(oshima): insets has to be rotated according to the
- // the current display rotation.
- display_info_[display_id].SetOverscanInsets(true, insets_in_dip);
- DisplayInfoList display_info_list;
- for (DisplayList::const_iterator iter = displays_.begin();
- iter != displays_.end(); ++iter) {
- display_info_list.push_back(GetDisplayInfo(iter->id()));
- }
- AddMirrorDisplayInfoIfAny(&display_info_list);
- UpdateDisplays(display_info_list);
-}
-
-void DisplayManager::ClearCustomOverscanInsets(int64 display_id) {
- display_info_[display_id].clear_has_custom_overscan_insets();
+ display_info_[display_id].SetOverscanInsets(insets_in_dip);
DisplayInfoList display_info_list;
for (DisplayList::const_iterator iter = displays_.begin();
iter != displays_.end(); ++iter) {
@@ -321,7 +360,7 @@
if (0.5f <= ui_scale && ui_scale <= 2.0f)
display_info_[display_id].set_ui_scale(ui_scale);
if (overscan_insets)
- display_info_[display_id].SetOverscanInsets(true, *overscan_insets);
+ display_info_[display_id].SetOverscanInsets(*overscan_insets);
}
bool DisplayManager::IsDisplayRotationEnabled() const {
@@ -419,7 +458,7 @@
if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
DCHECK_EQ(1u, updated_display_info_list.size()) <<
"Multiple display test does not work on Win8 bots. Please "
- "skip (don't disable) the test using |SupportMultipleDisplay()|";
+ "skip (don't disable) the test using SupportsMultipleDisplays()";
}
#endif
@@ -453,7 +492,7 @@
if (new_info_iter != new_display_info_list.end() &&
mirrored_display_id == new_info_iter->id()) {
DisplayInfo info = *new_info_iter;
- info.SetOverscanInsets(true, gfx::Insets());
+ info.SetOverscanInsets(gfx::Insets());
InsertAndUpdateDisplayInfo(info);
mirrored_display_ = CreateDisplayFromDisplayInfoById(new_info_iter->id());
@@ -550,6 +589,17 @@
display_controller->NotifyDisplayConfigurationChanging();
mouse_location_in_native = display_controller->GetNativeMouseCursorLocation();
+ size_t updated_index;
+ if (UpdateSecondaryDisplayBoundsForLayout(&new_displays, &updated_index) &&
+ std::find(added_display_indices.begin(),
+ added_display_indices.end(),
+ updated_index) == added_display_indices.end() &&
+ std::find(changed_display_indices.begin(),
+ changed_display_indices.end(),
+ updated_index) == changed_display_indices.end()) {
+ changed_display_indices.push_back(updated_index);
+ }
+
displays_ = new_displays;
base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false);
@@ -685,6 +735,15 @@
return base::StringPrintf("Display %d", static_cast<int>(id));
}
+int64 DisplayManager::GetDisplayIdForUIScaling() const {
+ // UI Scaling is effective only on internal display.
+ int64 display_id = gfx::Display::InternalDisplayId();
+#if defined(OS_WIN)
+ display_id = first_display_id();
+#endif
+ return display_id;
+}
+
void DisplayManager::SetMirrorMode(bool mirrored) {
if (num_connected_displays() <= 1)
return;
@@ -768,15 +827,6 @@
mirrored_display_ = gfx::Display();
}
-int64 DisplayManager::GetDisplayIdForUIScaling() const {
- // UI Scaling is effective only on internal display.
- int64 display_id = gfx::Display::InternalDisplayId();
-#if defined(OS_WIN)
- display_id = first_display_id();
-#endif
- return display_id;
-}
-
void DisplayManager::Init() {
// TODO(oshima): Move this logic to DisplayChangeObserver.
const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
@@ -856,12 +906,49 @@
// Simply set the origin to (0,0). The primary display's origin is
// always (0,0) and the secondary display's bounds will be updated
- // by |DisplayController::UpdateDisplayBoundsForLayout|.
+ // in |UpdateSecondaryDisplayBoundsForLayout| called in |UpdateDisplay|.
new_display.SetScaleAndBounds(
display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size()));
new_display.set_rotation(display_info.rotation());
return new_display;
}
+bool DisplayManager::UpdateSecondaryDisplayBoundsForLayout(
+ DisplayList* displays,
+ size_t* updated_index) const {
+ if (displays->size() != 2U)
+ return false;
+
+ DisplayController* controller = Shell::GetInstance()->display_controller();
+ int64 id_at_zero = displays->at(0).id();
+ DisplayIdPair pair =
+ (id_at_zero == first_display_id_ ||
+ id_at_zero == gfx::Display::InternalDisplayId()) ?
+ std::make_pair(id_at_zero, displays->at(1).id()) :
+ std::make_pair(displays->at(1).id(), id_at_zero) ;
+ DisplayLayout layout =
+ controller->ComputeDisplayLayoutForDisplayIdPair(pair);
+
+ // Ignore if a user has a old format (should be extremely rare)
+ // and this will be replaced with DCHECK.
+ if (layout.primary_id != gfx::Display::kInvalidDisplayID) {
+ size_t primary_index, secondary_index;
+ if (displays->at(0).id() == layout.primary_id) {
+ primary_index = 0;
+ secondary_index = 1;
+ } else {
+ primary_index = 1;
+ secondary_index = 0;
+ }
+ gfx::Rect bounds =
+ GetDisplayForId(displays->at(secondary_index).id()).bounds();
+ UpdateDisplayBoundsForLayout(
+ layout, displays->at(primary_index), &displays->at(secondary_index));
+ *updated_index = secondary_index;
+ return bounds != displays->at(secondary_index).bounds();
+ }
+ return false;
+}
+
} // namespace internal
} // namespace ash
diff --git a/ash/display/display_manager.h b/ash/display/display_manager.h
index f1e52f9..3d75616 100644
--- a/ash/display/display_manager.h
+++ b/ash/display/display_manager.h
@@ -10,6 +10,7 @@
#include "ash/ash_export.h"
#include "ash/display/display_info.h"
+#include "ash/display/display_layout.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "ui/aura/root_window_observer.h"
@@ -54,6 +55,12 @@
// Returns next valid UI scale.
static float GetNextUIScale(const DisplayInfo& info, bool up);
+ // Updates the bounds of |secondary_display| according to |layout|.
+ static void UpdateDisplayBoundsForLayout(
+ const DisplayLayout& layout,
+ const gfx::Display& primary_display,
+ gfx::Display* secondary_display);
+
// When set to true, the MonitorManager calls OnDisplayBoundsChanged
// even if the display's bounds didn't change. Used to swap primary
// display.
@@ -89,9 +96,6 @@
// display's bounds change.
void SetOverscanInsets(int64 display_id, const gfx::Insets& insets_in_dip);
- // Clears the overscan insets
- void ClearCustomOverscanInsets(int64 display_id);
-
// Sets the display's rotation.
void SetDisplayRotation(int64 display_id, gfx::Display::Rotation rotation);
@@ -187,7 +191,7 @@
void SetSoftwareMirroring(bool enabled);
#endif
- private:
+private:
FRIEND_TEST_ALL_PREFIXES(ExtendedDesktopTest, ConvertPoint);
FRIEND_TEST_ALL_PREFIXES(DisplayManagerTest, TestNativeDisplaysChanged);
FRIEND_TEST_ALL_PREFIXES(DisplayManagerTest,
@@ -226,6 +230,14 @@
// Creates a display object from the DisplayInfo for |display_id|.
gfx::Display CreateDisplayFromDisplayInfoById(int64 display_id);
+ // Updates the bounds of the secondary display in |display_list|
+ // using the layout registered for the display pair and set the
+ // index of display updated to |updated_index|. Returns true
+ // if the secondary display's bounds has been changed from current
+ // value, or false otherwise.
+ bool UpdateSecondaryDisplayBoundsForLayout(DisplayList* display_list,
+ size_t* updated_index) const;
+
int64 first_display_id_;
gfx::Display mirrored_display_;
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc
index 062a0e7..f06aa78 100644
--- a/ash/display/display_manager_unittest.cc
+++ b/ash/display/display_manager_unittest.cc
@@ -11,6 +11,7 @@
#include "ash/test/display_manager_test_api.h"
#include "ash/test/mirror_window_test_api.h"
#include "base/format_macros.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
@@ -27,6 +28,14 @@
using base::StringPrintf;
+namespace {
+
+std::string ToDisplayName(int64 id) {
+ return "x-" + base::Int64ToString(id);
+}
+
+} // namespace
+
class DisplayManagerTest : public test::AshTestBase,
public gfx::DisplayObserver,
public aura::WindowObserver {
@@ -118,7 +127,7 @@
DISALLOW_COPY_AND_ASSIGN(DisplayManagerTest);
};
-TEST_F(DisplayManagerTest, NativeDisplayTest) {
+TEST_F(DisplayManagerTest, UpdateDisplayTest) {
if (!SupportsMultipleDisplays())
return;
@@ -209,6 +218,15 @@
EXPECT_EQ("1000,1000 600x400",
GetDisplayInfoAt(1).bounds_in_pixel().ToString());
reset();
+
+ // Changing primary will update secondary as well.
+ UpdateDisplay("0+0-800x600,1000+1000-600x400");
+ EXPECT_EQ("2 0 0", GetCountSummary());
+ reset();
+ EXPECT_EQ("0,0 800x600",
+ display_manager()->GetDisplayAt(0)->bounds().ToString());
+ EXPECT_EQ("800,0 600x400",
+ display_manager()->GetDisplayAt(1)->bounds().ToString());
}
// Test in emulation mode (use_fullscreen_host_window=false)
@@ -365,6 +383,9 @@
}
TEST_F(DisplayManagerTest, TestDeviceScaleOnlyChange) {
+ if (!SupportsHostWindowResize())
+ return;
+
UpdateDisplay("1000x600");
EXPECT_EQ(1,
Shell::GetPrimaryRootWindow()->compositor()->device_scale_factor());
@@ -378,13 +399,13 @@
}
DisplayInfo CreateDisplayInfo(int64 id, const gfx::Rect& bounds) {
- DisplayInfo info(id, StringPrintf("x-%d", static_cast<int>(id)), false);
+ DisplayInfo info(id, ToDisplayName(id), false);
info.SetBounds(bounds);
return info;
}
TEST_F(DisplayManagerTest, TestNativeDisplaysChanged) {
- const int internal_display_id =
+ const int64 internal_display_id =
test::DisplayManagerTestApi(display_manager()).
SetFirstDisplayAsInternalDisplay();
const int external_id = 10;
@@ -426,20 +447,24 @@
EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
EXPECT_EQ(external_id, Shell::GetScreen()->GetPrimaryDisplay().id());
+ EXPECT_EQ(internal_display_id, gfx::Display::InternalDisplayId());
+
// Primary connected, with different bounds.
display_info_list.clear();
display_info_list.push_back(internal_display_info);
display_info_list.push_back(external_display_info);
display_manager()->OnNativeDisplaysChanged(display_info_list);
EXPECT_EQ(2U, display_manager()->GetNumDisplays());
- // need to remember which is primary
+ EXPECT_EQ(internal_display_id, Shell::GetScreen()->GetPrimaryDisplay().id());
+
+ // This combinatino is new, so internal display becomes primary.
EXPECT_EQ("0,0 500x500",
FindDisplayForId(internal_display_id).bounds().ToString());
EXPECT_EQ("1,1 100x100",
FindDisplayInfoForId(10).bounds_in_pixel().ToString());
EXPECT_EQ(2U, display_manager()->num_connected_displays());
EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
- EXPECT_EQ(StringPrintf("x-%d", internal_display_id),
+ EXPECT_EQ(ToDisplayName(internal_display_id),
display_manager()->GetDisplayNameForId(internal_display_id));
// Emulate suspend.
@@ -452,7 +477,7 @@
FindDisplayInfoForId(10).bounds_in_pixel().ToString());
EXPECT_EQ(2U, display_manager()->num_connected_displays());
EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
- EXPECT_EQ(StringPrintf("x-%d", internal_display_id),
+ EXPECT_EQ(ToDisplayName(internal_display_id),
display_manager()->GetDisplayNameForId(internal_display_id));
// External display has disconnected then resumed.
@@ -500,7 +525,7 @@
EXPECT_TRUE(display_manager()->IsMirrored());
// Test display name.
- EXPECT_EQ(StringPrintf("x-%d", internal_display_id),
+ EXPECT_EQ(ToDisplayName(internal_display_id),
display_manager()->GetDisplayNameForId(internal_display_id));
EXPECT_EQ("x-10", display_manager()->GetDisplayNameForId(10));
EXPECT_EQ("x-11", display_manager()->GetDisplayNameForId(11));
@@ -690,43 +715,6 @@
EXPECT_EQ("0,0 100x100", FindDisplayForId(10).bounds().ToString());
}
-TEST_F(DisplayManagerTest, AutomaticOverscanInsets) {
- if (!SupportsMultipleDisplays())
- return;
-
- UpdateDisplay("200x200,400x400");
-
- std::vector<DisplayInfo> display_info_list;
- display_info_list.push_back(GetDisplayInfoAt(0));
- display_info_list.push_back(GetDisplayInfoAt(1));
- display_info_list[1].set_has_overscan_for_test(true);
- int64 id = display_info_list[1].id();
- // SetDefaultOverscanInsets(&display_info_list[1]);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- // It has overscan insets, although SetOverscanInsets() isn't called.
- EXPECT_EQ("380x380",
- GetDisplayInfoAt(1).size_in_pixel().ToString());
-
- // If custom overscan insets is specified, the specified value is used.
- display_manager()->SetOverscanInsets(id, gfx::Insets(5, 6, 7, 8));
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ("386x388",
- GetDisplayInfoAt(1).size_in_pixel().ToString());
-
- // Do not overscan even though it has 'has_overscan' flag, if the custom
- // insets is empty.
- display_manager()->SetOverscanInsets(id, gfx::Insets());
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ("400x400",
- GetDisplayInfoAt(1).size_in_pixel().ToString());
-
- // Clearing the custom overscan should set the bounds to
- // original.
- display_manager()->ClearCustomOverscanInsets(id);
- EXPECT_EQ("380x380",
- GetDisplayInfoAt(1).size_in_pixel().ToString());
-}
-
TEST_F(DisplayManagerTest, Rotate) {
if (!SupportsMultipleDisplays())
return;
@@ -756,6 +744,20 @@
EXPECT_EQ("300x400",
GetDisplayInfoAt(1).size_in_pixel().ToString());
+ // Just Rotating display will change the bounds on both display.
+ UpdateDisplay("100x200/l,300x400");
+ EXPECT_EQ("2 0 0", GetCountSummary());
+ reset();
+
+ // Updating tothe same configuration should report no changes.
+ UpdateDisplay("100x200/l,300x400");
+ EXPECT_EQ("0 0 0", GetCountSummary());
+ reset();
+
+ UpdateDisplay("100x200/l,300x400");
+ EXPECT_EQ("0 0 0", GetCountSummary());
+ reset();
+
UpdateDisplay("200x200");
EXPECT_EQ("1 0 1", GetCountSummary());
reset();
diff --git a/ash/display/mirror_window_controller.cc b/ash/display/mirror_window_controller.cc
index 4f750fe..a2b9d09 100644
--- a/ash/display/mirror_window_controller.cc
+++ b/ash/display/mirror_window_controller.cc
@@ -11,6 +11,7 @@
#undef RootWindow
#endif
+#include "ash/display/display_controller.h"
#include "ash/display/display_info.h"
#include "ash/display/display_manager.h"
#include "ash/display/root_window_transformers.h"
@@ -155,6 +156,9 @@
}
void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) {
+ if (Shell::GetInstance()->display_controller()->in_bootstrap())
+ return;
+
static int mirror_root_window_count = 0;
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
diff --git a/ash/display/output_configurator_animation.cc b/ash/display/output_configurator_animation.cc
index 0b57aca..d58d9a5 100644
--- a/ash/display/output_configurator_animation.cc
+++ b/ash/display/output_configurator_animation.cc
@@ -9,7 +9,7 @@
#include "ash/shell_window_ids.h"
#include "base/bind.h"
#include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
diff --git a/ash/display/output_configurator_animation.h b/ash/display/output_configurator_animation.h
index dc70264..3fefe92 100644
--- a/ash/display/output_configurator_animation.h
+++ b/ash/display/output_configurator_animation.h
@@ -9,7 +9,7 @@
#include "ash/ash_export.h"
#include "base/callback.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "chromeos/display/output_configurator.h"
namespace aura {
diff --git a/ash/display/root_window_transformers.cc b/ash/display/root_window_transformers.cc
index 6142839..a698fa4 100644
--- a/ash/display/root_window_transformers.cc
+++ b/ash/display/root_window_transformers.cc
@@ -44,6 +44,10 @@
}
}
+// TODO(oshima): Transformers should be able to adjust itself
+// when the device scale factor is changed, instead of
+// precalculating the transform using fixed value.
+
gfx::Transform CreateRotationTransform(aura::RootWindow* root_window,
const gfx::Display& display) {
DisplayInfo info =
diff --git a/ash/display/shared_display_edge_indicator.cc b/ash/display/shared_display_edge_indicator.cc
index 5370c3b..cfcf4ba 100644
--- a/ash/display/shared_display_edge_indicator.cc
+++ b/ash/display/shared_display_edge_indicator.cc
@@ -49,7 +49,7 @@
views::View* contents_view) {
views::Widget* widget = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.can_activate = false;
params.keep_on_top = true;
// We set the context to the primary root window; this is OK because the ash
diff --git a/ash/drag_drop/drag_image_view.cc b/ash/drag_drop/drag_image_view.cc
index 066b99c..242488b 100644
--- a/ash/drag_drop/drag_image_view.cc
+++ b/ash/drag_drop/drag_image_view.cc
@@ -26,7 +26,7 @@
params.context = context;
params.accept_events = false;
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.transparent = true;
+ params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW;
drag_widget->Init(params);
drag_widget->SetOpacity(0xFF);
drag_widget->GetNativeWindow()->set_owned_by_parent(false);
diff --git a/ash/launcher/alternate_app_list_button.cc b/ash/launcher/alternate_app_list_button.cc
new file mode 100644
index 0000000..77f1184
--- /dev/null
+++ b/ash/launcher/alternate_app_list_button.cc
@@ -0,0 +1,137 @@
+// 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/launcher/alternate_app_list_button.h"
+
+#include "ash/ash_switches.h"
+#include "ash/launcher/launcher_button_host.h"
+#include "ash/launcher/launcher_types.h"
+#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_widget.h"
+#include "ash/shell.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_element.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/image/image_skia_operations.h"
+
+namespace ash {
+namespace internal {
+
+// static
+const int AlternateAppListButton::kImageBoundsSize = 7;
+
+
+AlternateAppListButton::AlternateAppListButton(views::ButtonListener* listener,
+ LauncherButtonHost* host,
+ ShelfWidget* shelf_widget)
+ : views::ImageButton(listener),
+ host_(host),
+ shelf_widget_(shelf_widget) {
+ SetAccessibleName(l10n_util::GetStringUTF16(IDS_AURA_APP_LIST_TITLE));
+ SetSize(gfx::Size(ShelfLayoutManager::kShelfSize,
+ ShelfLayoutManager::kShelfSize));
+}
+
+AlternateAppListButton::~AlternateAppListButton() {
+}
+
+bool AlternateAppListButton::OnMousePressed(const ui::MouseEvent& event) {
+ ImageButton::OnMousePressed(event);
+ host_->PointerPressedOnButton(this, LauncherButtonHost::MOUSE, event);
+ return true;
+}
+
+void AlternateAppListButton::OnMouseReleased(const ui::MouseEvent& event) {
+ ImageButton::OnMouseReleased(event);
+ host_->PointerReleasedOnButton(this, LauncherButtonHost::MOUSE, false);
+}
+
+void AlternateAppListButton::OnMouseCaptureLost() {
+ host_->PointerReleasedOnButton(this, LauncherButtonHost::MOUSE, true);
+ ImageButton::OnMouseCaptureLost();
+}
+
+bool AlternateAppListButton::OnMouseDragged(const ui::MouseEvent& event) {
+ ImageButton::OnMouseDragged(event);
+ host_->PointerDraggedOnButton(this, LauncherButtonHost::MOUSE, event);
+ return true;
+}
+
+void AlternateAppListButton::OnMouseMoved(const ui::MouseEvent& event) {
+ ImageButton::OnMouseMoved(event);
+ host_->MouseMovedOverButton(this);
+}
+
+void AlternateAppListButton::OnMouseEntered(const ui::MouseEvent& event) {
+ ImageButton::OnMouseEntered(event);
+ host_->MouseEnteredButton(this);
+}
+
+void AlternateAppListButton::OnMouseExited(const ui::MouseEvent& event) {
+ ImageButton::OnMouseExited(event);
+ host_->MouseExitedButton(this);
+}
+
+void AlternateAppListButton::OnPaint(gfx::Canvas* canvas) {
+ // Call the base class first to paint any background/borders.
+ View::OnPaint(canvas);
+
+ int background_image_id = 0;
+ if (Shell::GetInstance()->GetAppListTargetVisibility()) {
+ background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED;
+ } else {
+ if (shelf_widget_->GetDimsShelf())
+ background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK;
+ else
+ background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL;
+ }
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ const gfx::ImageSkia* background_image =
+ rb.GetImageNamed(background_image_id).ToImageSkia();
+ const gfx::ImageSkia* forground_image =
+ rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST_ALTERNATE).ToImageSkia();
+
+ gfx::Rect contents_bounds = GetContentsBounds();
+ gfx::Rect background_bounds, forground_bounds;
+
+ background_bounds.set_x(contents_bounds.x() +
+ std::max(0,
+ (contents_bounds.width() - background_image->width()) / 2));
+ background_bounds.set_y(contents_bounds.y() +
+ std::max(kImageBoundsSize,
+ (contents_bounds.height() - background_image->height()) / 2));
+ background_bounds.set_size(background_image->size());
+
+ forground_bounds.set_size(forground_image->size());
+ forground_bounds.set_x(background_bounds.x() +
+ std::max(0,
+ (background_bounds.width() - forground_bounds.width()) / 2));
+ forground_bounds.set_y(background_bounds.y() +
+ std::max(0,
+ (background_bounds.height() - forground_bounds.height()) / 2));
+
+ canvas->DrawImageInt(*background_image,
+ background_bounds.x(),
+ background_bounds.y());
+ canvas->DrawImageInt(*forground_image,
+ forground_bounds.x(),
+ forground_bounds.y());
+
+ OnPaintFocusBorder(canvas);
+}
+
+void AlternateAppListButton::GetAccessibleState(
+ ui::AccessibleViewState* state) {
+ state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
+ state->name = host_->GetAccessibleName(this);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/launcher/alternate_app_list_button.h b/ash/launcher/alternate_app_list_button.h
new file mode 100644
index 0000000..f68207c
--- /dev/null
+++ b/ash/launcher/alternate_app_list_button.h
@@ -0,0 +1,58 @@
+// 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_LAUNCHER_ALTERNATE_APP_LIST_BUTTON_H_
+#define ASH_LAUNCHER_ALTERNATE_APP_LIST_BUTTON_H_
+
+#include "ui/views/controls/button/image_button.h"
+
+namespace ash {
+
+class ShelfWidget;
+
+namespace internal {
+
+class LauncherButtonHost;
+
+
+
+// Button used for the AppList icon on the launcher.
+// This class is an alternate implementation to
+// ash::internal::AppListButton for the purposes of testing an
+// alternate shelf layout (see ash_switches: UseAlternateShelfLayout).
+class AlternateAppListButton : public views::ImageButton {
+ public:
+ // Bounds size (inset) required for the app icon image (in pixels).
+ static const int kImageBoundsSize;
+
+ AlternateAppListButton(views::ButtonListener* listener,
+ LauncherButtonHost* host,
+ ShelfWidget* shelf_widget);
+ virtual ~AlternateAppListButton();
+
+ protected:
+ // View overrides:
+ virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnMouseCaptureLost() OVERRIDE;
+ virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
+ virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+
+ private:
+ LauncherButtonHost* host_;
+ // Reference to the shelf widget containing this button, owned by the
+ // root window controller.
+ ShelfWidget* shelf_widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(AlternateAppListButton);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_LAUNCHER_ALTERNATE_APP_LIST_BUTTON_H_
diff --git a/ash/launcher/launcher.cc b/ash/launcher/launcher.cc
index 8991c35..03e7ff8 100644
--- a/ash/launcher/launcher.cc
+++ b/ash/launcher/launcher.cc
@@ -146,11 +146,11 @@
return launcher_view_->GetAppListButtonView();
}
-void Launcher::SwitchToWindow(int window_index) {
+void Launcher::LaunchAppIndexAt(int item_index) {
LauncherModel* launcher_model = launcher_view_->model();
const LauncherItems& items = launcher_model->items();
int item_count = launcher_model->item_count();
- int indexes_left = window_index >= 0 ? window_index : item_count;
+ int indexes_left = item_index >= 0 ? item_index : item_count;
int found_index = -1;
// Iterating until we have hit the index we are interested in which
@@ -165,7 +165,7 @@
// There are two ways how found_index can be valid: a.) the nth item was
// found (which is true when indexes_left is -1) or b.) the last item was
// requested (which is true when index was passed in as a negative number).
- if (found_index >= 0 && (indexes_left == -1 || window_index < 0) &&
+ if (found_index >= 0 && (indexes_left == -1 || item_index < 0) &&
(delegate_->IsPerAppLauncher() ||
(items[found_index].status == ash::STATUS_RUNNING ||
items[found_index].status == ash::STATUS_CLOSED))) {
diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h
index caeb63f..f9bdcc0 100644
--- a/ash/launcher/launcher.h
+++ b/ash/launcher/launcher.h
@@ -87,9 +87,9 @@
views::View* GetAppListButtonView() const;
- // Switches to a 0-indexed (in order of creation) window.
- // A negative index switches to the last window in the list.
- void SwitchToWindow(int window_index);
+ // Launch a 0-indexed launcher item in the Launcher.
+ // A negative index launches the last launcher item in the launcher.
+ void LaunchAppIndexAt(int item_index);
// Only to be called for testing. Retrieves the LauncherView.
// TODO(sky): remove this!
diff --git a/ash/launcher/launcher_model.cc b/ash/launcher/launcher_model.cc
index 68e57e0..8daf561 100644
--- a/ash/launcher/launcher_model.cc
+++ b/ash/launcher/launcher_model.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "ash/ash_switches.h"
#include "ash/launcher/launcher_model_observer.h"
namespace ash {
@@ -22,7 +23,7 @@
case TYPE_PLATFORM_APP:
return 1;
case TYPE_APP_LIST:
- return 2;
+ return ash::switches::UseAlternateShelfLayout() ? 0 : 2;
case TYPE_APP_PANEL:
return 3;
}
@@ -148,7 +149,8 @@
int LauncherModel::ValidateInsertionIndex(LauncherItemType type,
int index) const {
- DCHECK(index >= 0 && index <= item_count());
+ DCHECK(index >= 0 && index <= item_count() +
+ (ash::switches::UseAlternateShelfLayout() ? 1 : 0));
// Clamp |index| to the allowed range for the type as determined by |weight|.
LauncherItem weight_dummy;
diff --git a/ash/launcher/launcher_tooltip_manager.cc b/ash/launcher/launcher_tooltip_manager.cc
index 1ed63d5..8fbcc6a 100644
--- a/ash/launcher/launcher_tooltip_manager.cc
+++ b/ash/launcher/launcher_tooltip_manager.cc
@@ -11,8 +11,8 @@
#include "ash/wm/window_animations.h"
#include "base/bind.h"
#include "base/message_loop.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/base/events/event.h"
diff --git a/ash/launcher/launcher_tooltip_manager_unittest.cc b/ash/launcher/launcher_tooltip_manager_unittest.cc
index 6a38d09..5df58a6 100644
--- a/ash/launcher/launcher_tooltip_manager_unittest.cc
+++ b/ash/launcher/launcher_tooltip_manager_unittest.cc
@@ -12,7 +12,7 @@
#include "ash/test/ash_test_base.h"
#include "ash/wm/window_util.h"
#include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/root_window.h"
#include "ui/base/events/event.h"
#include "ui/base/events/event_constants.h"
@@ -90,7 +90,7 @@
widget_.reset(new views::Widget);
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.parent = Shell::GetContainer(
Shell::GetPrimaryRootWindow(),
diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc
index 70292f2..ede55d4 100644
--- a/ash/launcher/launcher_view.cc
+++ b/ash/launcher/launcher_view.cc
@@ -9,6 +9,7 @@
#include "ash/ash_constants.h"
#include "ash/ash_switches.h"
#include "ash/drag_drop/drag_image_view.h"
+#include "ash/launcher/alternate_app_list_button.h"
#include "ash/launcher/app_list_button.h"
#include "ash/launcher/launcher_button.h"
#include "ash/launcher/launcher_delegate.h"
@@ -441,7 +442,8 @@
LayoutToIdealBounds();
for (int i=0; i < view_model_->view_size(); ++i) {
// TODO: remove when AppIcon is a Launcher Button.
- if (TYPE_APP_LIST == model_->items()[i].type) {
+ if (TYPE_APP_LIST == model_->items()[i].type &&
+ !ash::switches::UseAlternateShelfLayout()) {
ShelfLayoutManager* shelf = tooltip_->shelf_layout_manager();
static_cast<AppListButton*>(view_model_->view_at(i))->SetImageAlignment(
shelf->SelectValueForShelfAlignment(
@@ -683,6 +685,7 @@
return;
int first_panel_index = model_->FirstPanelIndex();
+ // TODO(harrym): if alternate shelf layout stays, rename app_list_index.
int app_list_index = first_panel_index - 1;
// Initial x,y values account both leading_inset in primary
@@ -698,8 +701,12 @@
leading_inset(),
leading_inset(),
0);
- int w = shelf->PrimaryAxisValue(kLauncherPreferredSize, width());
- int h = shelf->PrimaryAxisValue(height(), kLauncherPreferredSize);
+
+ int shelf_size = ash::switches::UseAlternateShelfLayout() ?
+ ShelfLayoutManager::kShelfSize : kLauncherPreferredSize;
+
+ int w = shelf->PrimaryAxisValue(shelf_size, width());
+ int h = shelf->PrimaryAxisValue(height(), shelf_size);
for (int i = 0; i < view_model_->view_size(); ++i) {
if (i < first_visible_index_) {
view_model_->set_ideal_bounds(i, gfx::Rect(x, y, 0, 0));
@@ -901,21 +908,26 @@
}
case TYPE_APP_LIST: {
- // TODO(dave): turn this into a LauncherButton too.
- AppListButton* button = new AppListButton(this, this);
- ShelfLayoutManager* shelf = tooltip_->shelf_layout_manager();
- button->SetImageAlignment(
- shelf->SelectValueForShelfAlignment(
- views::ImageButton::ALIGN_CENTER,
- views::ImageButton::ALIGN_LEFT,
- views::ImageButton::ALIGN_RIGHT,
- views::ImageButton::ALIGN_CENTER),
- shelf->SelectValueForShelfAlignment(
- views::ImageButton::ALIGN_TOP,
- views::ImageButton::ALIGN_MIDDLE,
- views::ImageButton::ALIGN_MIDDLE,
- views::ImageButton::ALIGN_BOTTOM));
- view = button;
+ if (ash::switches::UseAlternateShelfLayout()) {
+ view = new AlternateAppListButton(this, this,
+ tooltip_->shelf_layout_manager()->shelf_widget());
+ } else {
+ // TODO(dave): turn this into a LauncherButton too.
+ AppListButton* button = new AppListButton(this, this);
+ ShelfLayoutManager* shelf = tooltip_->shelf_layout_manager();
+ button->SetImageAlignment(
+ shelf->SelectValueForShelfAlignment(
+ views::ImageButton::ALIGN_CENTER,
+ views::ImageButton::ALIGN_LEFT,
+ views::ImageButton::ALIGN_RIGHT,
+ views::ImageButton::ALIGN_CENTER),
+ shelf->SelectValueForShelfAlignment(
+ views::ImageButton::ALIGN_TOP,
+ views::ImageButton::ALIGN_MIDDLE,
+ views::ImageButton::ALIGN_MIDDLE,
+ views::ImageButton::ALIGN_BOTTOM));
+ view = button;
+ }
break;
}
@@ -1023,17 +1035,36 @@
bool LauncherView::SameDragType(LauncherItemType typea,
LauncherItemType typeb) const {
- switch (typea) {
- case TYPE_TABBED:
- case TYPE_PLATFORM_APP:
+ if (ash::switches::UseAlternateShelfLayout()) {
+ // TODO(harrym): Allow app list to be repositionable, if this goes live
+ // (no flag) the pref file has to be updated so the changes persist.
+ switch (typea) {
+ case TYPE_TABBED:
+ case TYPE_PLATFORM_APP:
return (typeb == TYPE_TABBED || typeb == TYPE_PLATFORM_APP);
- case TYPE_APP_SHORTCUT:
- case TYPE_BROWSER_SHORTCUT:
- return (typeb == TYPE_APP_SHORTCUT || typeb == TYPE_BROWSER_SHORTCUT);
- case TYPE_WINDOWED_APP:
- case TYPE_APP_LIST:
- case TYPE_APP_PANEL:
- return typeb == typea;
+ case TYPE_APP_SHORTCUT:
+ case TYPE_APP_LIST:
+ case TYPE_BROWSER_SHORTCUT:
+ return (typeb == TYPE_APP_SHORTCUT ||
+ typeb == TYPE_APP_LIST ||
+ typeb == TYPE_BROWSER_SHORTCUT);
+ case TYPE_WINDOWED_APP:
+ case TYPE_APP_PANEL:
+ return typeb == typea;
+ }
+ } else {
+ switch (typea) {
+ case TYPE_TABBED:
+ case TYPE_PLATFORM_APP:
+ return (typeb == TYPE_TABBED || typeb == TYPE_PLATFORM_APP);
+ case TYPE_APP_SHORTCUT:
+ case TYPE_BROWSER_SHORTCUT:
+ return (typeb == TYPE_APP_SHORTCUT || typeb == TYPE_BROWSER_SHORTCUT);
+ case TYPE_WINDOWED_APP:
+ case TYPE_APP_LIST:
+ case TYPE_APP_PANEL:
+ return typeb == typea;
+ }
}
NOTREACHED();
return false;
@@ -1339,6 +1370,8 @@
}
void LauncherView::LauncherStatusChanged() {
+ if (ash::switches::UseAlternateShelfLayout())
+ return;
AppListButton* app_list_button =
static_cast<AppListButton*>(GetAppListButtonView());
if (model_->status() == LauncherModel::STATUS_LOADING)
diff --git a/ash/launcher/tabbed_launcher_button.h b/ash/launcher/tabbed_launcher_button.h
index 6eb0b9e..0ac2c3b 100644
--- a/ash/launcher/tabbed_launcher_button.h
+++ b/ash/launcher/tabbed_launcher_button.h
@@ -7,7 +7,7 @@
#include "ash/launcher/launcher_button.h"
#include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/base/animation/animation_delegate.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/glow_hover_controller.h"
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc
index bb50285..c8becce 100644
--- a/ash/magnifier/magnification_controller.cc
+++ b/ash/magnifier/magnification_controller.cc
@@ -4,8 +4,6 @@
#include "ash/magnifier/magnification_controller.h"
-#include "ash/display/display_controller.h"
-#include "ash/display/display_manager.h"
#include "ash/display/root_window_transformers.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
diff --git a/ash/magnifier/magnification_controller_unittest.cc b/ash/magnifier/magnification_controller_unittest.cc
index 701c1f4..f369586 100644
--- a/ash/magnifier/magnification_controller_unittest.cc
+++ b/ash/magnifier/magnification_controller_unittest.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ash/display/display_controller.h"
#include "ash/magnifier/magnification_controller.h"
#include "ash/magnifier/magnifier_constants.h"
#include "ash/shell.h"
diff --git a/ash/magnifier/partial_magnification_controller.cc b/ash/magnifier/partial_magnification_controller.cc
index 1f46d51..d913856 100644
--- a/ash/magnifier/partial_magnification_controller.cc
+++ b/ash/magnifier/partial_magnification_controller.cc
@@ -144,7 +144,7 @@
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.can_activate = false;
params.accept_events = false;
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.parent = root_window;
zoom_widget_->Init(params);
zoom_widget_->SetBounds(gfx::Rect(mouse.x() - kMagnifierWidth / 2,
diff --git a/ash/resources/ash_resources.grd b/ash/resources/ash_resources.grd
index c858b32..b9e20ac 100644
--- a/ash/resources/ash_resources.grd
+++ b/ash/resources/ash_resources.grd
@@ -20,6 +20,7 @@
<structure type="chrome_scaled_image" name="IDR_AURA_LAUNCHER_BROWSER_SHORTCUT" file="common/chromium-32.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_LAUNCHER_DIMMING" file="common/launcher/launcher_dimming.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_LAUNCHER_ICON_APPLIST" file="common/launcher/launcher_appmenu.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_LAUNCHER_ICON_APPLIST_ALTERNATE" file="common/alt_launcher/status_app_menu_icon.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_LAUNCHER_ICON_APPLIST_HOT" file="common/launcher/launcher_appmenu_hover.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_LAUNCHER_ICON_APPLIST_PUSHED" file="common/launcher/launcher_appmenu_pressed.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_LAUNCHER_INCOGNITO_BROWSER" file="common/launcher/launcher_incognito_browser.png" />
@@ -33,6 +34,9 @@
<structure type="chrome_scaled_image" name="IDR_AURA_LAUNCHER_ICON_TASK_MANAGER" file="common/launcher/task_manager.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_MULTI_WINDOW_RESIZE_H" file="common/multi_window_resize_horizontal.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_MULTI_WINDOW_RESIZE_V" file="common/multi_window_resize_vertical.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL" file="common/alt_launcher/status_icon_background_normal.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK" file="common/alt_launcher/status_icon_background_onblack_normal.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED" file="common/alt_launcher/status_icon_background_pressed.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_RESIZE_SHADOW_BOTTOM" file="common/resize_shadow_bottom.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_RESIZE_SHADOW_BOTTOM_LEFT" file="common/resize_shadow_bottom_left.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_RESIZE_SHADOW_BOTTOM_RIGHT" file="common/resize_shadow_bottom_right.png" />
@@ -132,6 +136,7 @@
<!-- ChromeOS specific icons -->
<if expr="pp_ifdef('chromeos')">
+ <structure type="chrome_scaled_image" name="IDR_AURA_NOTIFICATION_LOW_POWER_CHARGER" file="cros/notification/notification_low_power_charger.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_ENTERPRISE_DARK" file="cros/status/status_managed.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_MANAGED_USER" file="cros/status/status_managed_mode_user.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_1X" file="cros/network/statusbar_network_1x.png" />
diff --git a/ash/resources/default_100_percent/common/alt_launcher/launcher_background.png b/ash/resources/default_100_percent/common/alt_launcher/launcher_background.png
index 38951a4..45b06ed 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/launcher_background.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/launcher_background.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/launcher_underline_active.png b/ash/resources/default_100_percent/common/alt_launcher/launcher_underline_active.png
index 7812473..6a69d17 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/launcher_underline_active.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/launcher_underline_active.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/launcher_underline_running.png b/ash/resources/default_100_percent/common/alt_launcher/launcher_underline_running.png
index 2360bb7..9bcff86 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/launcher_underline_running.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/launcher_underline_running.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_app_menu_icon.png b/ash/resources/default_100_percent/common/alt_launcher/status_app_menu_icon.png
index 40c5082..5e5f18b 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_app_menu_icon.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_app_menu_icon.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_normal.png b/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_normal.png
index 4c0299a..565c501 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_normal.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_onblack_normal.png b/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_onblack_normal.png
index f1c8389..41ba35c 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_onblack_normal.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_onblack_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_pressed.png b/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_pressed.png
index 1325562..d8cdd77 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_pressed.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_icon_background_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png b/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
index e941a3f..388c1e0 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_center.png
index 2616bc3..7f895ba 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_left.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_left.png
index 0252ad7..8b00443 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_left.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_left.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_center.png
index ffc9223..0d26eb2 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_left.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_left.png
index d0affb9..3484127 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_left.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_left.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_right.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_right.png
index cd1d9ee..5787128 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_right.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_onblack_right.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_right.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_right.png
index 7608c85..850e80f 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_right.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_normal_right.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_center.png
index 2eb9556..3eb461d 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
index 686332c..969c86b 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_right.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_right.png
index 36347a0..8ec7227 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_right.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_right.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/chromium-32.png b/ash/resources/default_100_percent/common/chromium-32.png
index 4266218..e708447 100644
--- a/ash/resources/default_100_percent/common/chromium-32.png
+++ b/ash/resources/default_100_percent/common/chromium-32.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_appmenu.png b/ash/resources/default_100_percent/common/launcher/launcher_appmenu.png
index 13118c8..719d772 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_appmenu.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_appmenu.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_appmenu_hover.png b/ash/resources/default_100_percent/common/launcher/launcher_appmenu_hover.png
index bafb356..a41d0e4 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_appmenu_hover.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_appmenu_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_appmenu_pressed.png b/ash/resources/default_100_percent/common/launcher/launcher_appmenu_pressed.png
index c6f0ce0..98750f8 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_appmenu_pressed.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_appmenu_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_browser.png b/ash/resources/default_100_percent/common/launcher/launcher_browser.png
index 9a5ee09..669a3a9 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_browser.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_browser.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_browser_panel.png b/ash/resources/default_100_percent/common/launcher/launcher_browser_panel.png
index ba32624..b974cb3 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_browser_panel.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_browser_panel.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png b/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
index 870bd9c..690de02 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_overflow.png b/ash/resources/default_100_percent/common/launcher/launcher_overflow.png
index d9c555d..05cc71d 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_overflow.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_overflow.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_underline_left_running.png b/ash/resources/default_100_percent/common/launcher/launcher_underline_left_running.png
index d70f0eb..6a4294f 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_underline_left_running.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_underline_left_running.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_underline_right_active.png b/ash/resources/default_100_percent/common/launcher/launcher_underline_right_active.png
index 01e392e..82572f2 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_underline_right_active.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_underline_right_active.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_underline_right_running.png b/ash/resources/default_100_percent/common/launcher/launcher_underline_right_running.png
index 7e96267..24de3c0 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_underline_right_running.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_underline_right_running.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/task_manager.png b/ash/resources/default_100_percent/common/launcher/task_manager.png
index 3b4e561..293bc76 100644
--- a/ash/resources/default_100_percent/common/launcher/task_manager.png
+++ b/ash/resources/default_100_percent/common/launcher/task_manager.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/multi_window_resize_horizontal.png b/ash/resources/default_100_percent/common/multi_window_resize_horizontal.png
index 0f9f63d..0f17aa9 100644
--- a/ash/resources/default_100_percent/common/multi_window_resize_horizontal.png
+++ b/ash/resources/default_100_percent/common/multi_window_resize_horizontal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/multi_window_resize_vertical.png b/ash/resources/default_100_percent/common/multi_window_resize_vertical.png
index c3e0750..7dceda4 100644
--- a/ash/resources/default_100_percent/common/multi_window_resize_vertical.png
+++ b/ash/resources/default_100_percent/common/multi_window_resize_vertical.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/notification/notification_button_active_hover.png b/ash/resources/default_100_percent/common/notification/notification_button_active_hover.png
index cd0c8dc..7a39af0 100644
--- a/ash/resources/default_100_percent/common/notification/notification_button_active_hover.png
+++ b/ash/resources/default_100_percent/common/notification/notification_button_active_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/notification/notification_button_active_normal.png b/ash/resources/default_100_percent/common/notification/notification_button_active_normal.png
index cd0c8dc..391b130 100644
--- a/ash/resources/default_100_percent/common/notification/notification_button_active_normal.png
+++ b/ash/resources/default_100_percent/common/notification/notification_button_active_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/notification/notification_button_active_pressed.png b/ash/resources/default_100_percent/common/notification/notification_button_active_pressed.png
index 6551999..309b888 100644
--- a/ash/resources/default_100_percent/common/notification/notification_button_active_pressed.png
+++ b/ash/resources/default_100_percent/common/notification/notification_button_active_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/notification/notification_button_inactive_hover.png b/ash/resources/default_100_percent/common/notification/notification_button_inactive_hover.png
index 99dd7ae..eb6788a 100644
--- a/ash/resources/default_100_percent/common/notification/notification_button_inactive_hover.png
+++ b/ash/resources/default_100_percent/common/notification/notification_button_inactive_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/notification/notification_button_inactive_normal.png b/ash/resources/default_100_percent/common/notification/notification_button_inactive_normal.png
index b81c965..659decf 100644
--- a/ash/resources/default_100_percent/common/notification/notification_button_inactive_normal.png
+++ b/ash/resources/default_100_percent/common/notification/notification_button_inactive_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/notification/notification_button_inactive_pressed.png b/ash/resources/default_100_percent/common/notification/notification_button_inactive_pressed.png
index fe56d69..44b62ee 100644
--- a/ash/resources/default_100_percent/common/notification/notification_button_inactive_pressed.png
+++ b/ash/resources/default_100_percent/common/notification/notification_button_inactive_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_fullscreen_hover.png b/ash/resources/default_100_percent/common/window_close_fullscreen_hover.png
index 3729d47..bd6cffa 100644
--- a/ash/resources/default_100_percent/common/window_close_fullscreen_hover.png
+++ b/ash/resources/default_100_percent/common/window_close_fullscreen_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_fullscreen_normal.png b/ash/resources/default_100_percent/common/window_close_fullscreen_normal.png
index 44a19c1..d9b19f1 100644
--- a/ash/resources/default_100_percent/common/window_close_fullscreen_normal.png
+++ b/ash/resources/default_100_percent/common/window_close_fullscreen_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png b/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
index 16b7da6..a0a0cc3 100644
--- a/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
+++ b/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_short_black_hover.png b/ash/resources/default_100_percent/common/window_close_short_black_hover.png
index 414d999..3d46487 100644
--- a/ash/resources/default_100_percent/common/window_close_short_black_hover.png
+++ b/ash/resources/default_100_percent/common/window_close_short_black_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_short_black_normal.png b/ash/resources/default_100_percent/common/window_close_short_black_normal.png
index 0735ffa..23010ea 100644
--- a/ash/resources/default_100_percent/common/window_close_short_black_normal.png
+++ b/ash/resources/default_100_percent/common/window_close_short_black_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_short_black_pressed.png b/ash/resources/default_100_percent/common/window_close_short_black_pressed.png
index c991375..703fce2 100644
--- a/ash/resources/default_100_percent/common/window_close_short_black_pressed.png
+++ b/ash/resources/default_100_percent/common/window_close_short_black_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_short_hover.png b/ash/resources/default_100_percent/common/window_close_short_hover.png
index d94256a..2e27e58 100644
--- a/ash/resources/default_100_percent/common/window_close_short_hover.png
+++ b/ash/resources/default_100_percent/common/window_close_short_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_short_normal.png b/ash/resources/default_100_percent/common/window_close_short_normal.png
index 44a19c1..a49779a 100644
--- a/ash/resources/default_100_percent/common/window_close_short_normal.png
+++ b/ash/resources/default_100_percent/common/window_close_short_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_short_pressed.png b/ash/resources/default_100_percent/common/window_close_short_pressed.png
index e191da2..31f9b6e 100644
--- a/ash/resources/default_100_percent/common/window_close_short_pressed.png
+++ b/ash/resources/default_100_percent/common/window_close_short_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_tall_hover.png b/ash/resources/default_100_percent/common/window_close_tall_hover.png
index 5cef0ab..400a398 100644
--- a/ash/resources/default_100_percent/common/window_close_tall_hover.png
+++ b/ash/resources/default_100_percent/common/window_close_tall_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_tall_normal.png b/ash/resources/default_100_percent/common/window_close_tall_normal.png
index 0c6e564..a3384f8 100644
--- a/ash/resources/default_100_percent/common/window_close_tall_normal.png
+++ b/ash/resources/default_100_percent/common/window_close_tall_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_tall_pressed.png b/ash/resources/default_100_percent/common/window_close_tall_pressed.png
index 034d592..323135d 100644
--- a/ash/resources/default_100_percent/common/window_close_tall_pressed.png
+++ b/ash/resources/default_100_percent/common/window_close_tall_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_fullscreen_shadow.png b/ash/resources/default_100_percent/common/window_fullscreen_shadow.png
index 391ac3f..8a6e37f 100644
--- a/ash/resources/default_100_percent/common/window_fullscreen_shadow.png
+++ b/ash/resources/default_100_percent/common/window_fullscreen_shadow.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_fullscreen_shadow_rtl.png b/ash/resources/default_100_percent/common/window_fullscreen_shadow_rtl.png
index 8214fc2..6439bdc 100644
--- a/ash/resources/default_100_percent/common/window_fullscreen_shadow_rtl.png
+++ b/ash/resources/default_100_percent/common/window_fullscreen_shadow_rtl.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_immersive_enter_normal.png b/ash/resources/default_100_percent/common/window_immersive_enter_normal.png
index d6e1203..bdb7c2a 100644
--- a/ash/resources/default_100_percent/common/window_immersive_enter_normal.png
+++ b/ash/resources/default_100_percent/common/window_immersive_enter_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_immersive_enter_pressed.png b/ash/resources/default_100_percent/common/window_immersive_enter_pressed.png
index fc99c86..095a17f 100644
--- a/ash/resources/default_100_percent/common/window_immersive_enter_pressed.png
+++ b/ash/resources/default_100_percent/common/window_immersive_enter_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_immersive_exit_hover.png b/ash/resources/default_100_percent/common/window_immersive_exit_hover.png
index bc8f52b..a0d6e04 100644
--- a/ash/resources/default_100_percent/common/window_immersive_exit_hover.png
+++ b/ash/resources/default_100_percent/common/window_immersive_exit_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_immersive_exit_normal.png b/ash/resources/default_100_percent/common/window_immersive_exit_normal.png
index b728735..4b6fd37 100644
--- a/ash/resources/default_100_percent/common/window_immersive_exit_normal.png
+++ b/ash/resources/default_100_percent/common/window_immersive_exit_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_immersive_exit_pressed.png b/ash/resources/default_100_percent/common/window_immersive_exit_pressed.png
index f115f8f..cc903e9 100644
--- a/ash/resources/default_100_percent/common/window_immersive_exit_pressed.png
+++ b/ash/resources/default_100_percent/common/window_immersive_exit_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_minimize_short_hover.png b/ash/resources/default_100_percent/common/window_minimize_short_hover.png
index 379e729..ad54e15 100644
--- a/ash/resources/default_100_percent/common/window_minimize_short_hover.png
+++ b/ash/resources/default_100_percent/common/window_minimize_short_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_minimize_short_normal.png b/ash/resources/default_100_percent/common/window_minimize_short_normal.png
index 2275079..e4eb416 100644
--- a/ash/resources/default_100_percent/common/window_minimize_short_normal.png
+++ b/ash/resources/default_100_percent/common/window_minimize_short_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_minimize_short_pressed.png b/ash/resources/default_100_percent/common/window_minimize_short_pressed.png
index d2fef09..32bccbe 100644
--- a/ash/resources/default_100_percent/common/window_minimize_short_pressed.png
+++ b/ash/resources/default_100_percent/common/window_minimize_short_pressed.png
Binary files differ
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
index 694116e..420d392 100644
--- 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 differ
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
index 9400be0..f94002b 100644
--- 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 differ
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
index c716194..4201d2a 100644
--- 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 differ
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
index 6f6e5b5..8841553 100644
--- 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 differ
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
index e4d5b63..aaff1c5 100644
--- 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 differ
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
index 248d1a4..e424d95 100644
--- 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 differ
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
index 0081c21..7583d26 100644
--- 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 differ
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
index 3abc648..9da0761 100644
--- 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 differ
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
index 5c68cc5..f002fd4 100644
--- 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 differ
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
index 62cae5f..790ee0e 100644
--- 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 differ
diff --git a/ash/resources/default_100_percent/common/window_size_fullscreen_hover.png b/ash/resources/default_100_percent/common/window_size_fullscreen_hover.png
index fc18aa3..a85c2b7 100644
--- a/ash/resources/default_100_percent/common/window_size_fullscreen_hover.png
+++ b/ash/resources/default_100_percent/common/window_size_fullscreen_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_size_fullscreen_normal.png b/ash/resources/default_100_percent/common/window_size_fullscreen_normal.png
index 2fca36c..500e8a4 100644
--- a/ash/resources/default_100_percent/common/window_size_fullscreen_normal.png
+++ b/ash/resources/default_100_percent/common/window_size_fullscreen_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_size_fullscreen_pressed.png b/ash/resources/default_100_percent/common/window_size_fullscreen_pressed.png
index fea4748..6afc601 100644
--- a/ash/resources/default_100_percent/common/window_size_fullscreen_pressed.png
+++ b/ash/resources/default_100_percent/common/window_size_fullscreen_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_size_short_hover.png b/ash/resources/default_100_percent/common/window_size_short_hover.png
index e3346e2..c52c4aa 100644
--- a/ash/resources/default_100_percent/common/window_size_short_hover.png
+++ b/ash/resources/default_100_percent/common/window_size_short_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_size_short_normal.png b/ash/resources/default_100_percent/common/window_size_short_normal.png
index 2ce5efb..ebe911f 100644
--- a/ash/resources/default_100_percent/common/window_size_short_normal.png
+++ b/ash/resources/default_100_percent/common/window_size_short_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_size_short_pressed.png b/ash/resources/default_100_percent/common/window_size_short_pressed.png
index f1f3bdc..cf7cde8 100644
--- a/ash/resources/default_100_percent/common/window_size_short_pressed.png
+++ b/ash/resources/default_100_percent/common/window_size_short_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_size_tall_hover.png b/ash/resources/default_100_percent/common/window_size_tall_hover.png
index 02a5adf..393beaf 100644
--- a/ash/resources/default_100_percent/common/window_size_tall_hover.png
+++ b/ash/resources/default_100_percent/common/window_size_tall_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_size_tall_normal.png b/ash/resources/default_100_percent/common/window_size_tall_normal.png
index 5bff897..bba5130 100644
--- a/ash/resources/default_100_percent/common/window_size_tall_normal.png
+++ b/ash/resources/default_100_percent/common/window_size_tall_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_size_tall_pressed.png b/ash/resources/default_100_percent/common/window_size_tall_pressed.png
index a3bf843..9047b4a 100644
--- a/ash/resources/default_100_percent/common/window_size_tall_pressed.png
+++ b/ash/resources/default_100_percent/common/window_size_tall_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/common/default_throbber.png b/ash/resources/default_100_percent/cros/common/default_throbber.png
index c8bdf37..47eeb2c 100644
--- a/ash/resources/default_100_percent/cros/common/default_throbber.png
+++ b/ash/resources/default_100_percent/cros/common/default_throbber.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/notification_3g.png b/ash/resources/default_100_percent/cros/network/notification_3g.png
index cfc2a15..ced1c67 100644
--- a/ash/resources/default_100_percent/cros/network/notification_3g.png
+++ b/ash/resources/default_100_percent/cros/network/notification_3g.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/notification_lte.png b/ash/resources/default_100_percent/cros/network/notification_lte.png
index f707a1c..6139623 100644
--- a/ash/resources/default_100_percent/cros/network/notification_lte.png
+++ b/ash/resources/default_100_percent/cros/network/notification_lte.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_cellular_disabled.png b/ash/resources/default_100_percent/cros/network/status_cellular_disabled.png
index 5d68e87..a00aecc 100644
--- a/ash/resources/default_100_percent/cros/network/status_cellular_disabled.png
+++ b/ash/resources/default_100_percent/cros/network/status_cellular_disabled.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_cellular_disabled_hover.png b/ash/resources/default_100_percent/cros/network/status_cellular_disabled_hover.png
index 9e599c7..348682b 100644
--- a/ash/resources/default_100_percent/cros/network/status_cellular_disabled_hover.png
+++ b/ash/resources/default_100_percent/cros/network/status_cellular_disabled_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_cellular_enabled.png b/ash/resources/default_100_percent/cros/network/status_cellular_enabled.png
index 0ce9dc4..cc5b733 100644
--- a/ash/resources/default_100_percent/cros/network/status_cellular_enabled.png
+++ b/ash/resources/default_100_percent/cros/network/status_cellular_enabled.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_cellular_enabled_hover.png b/ash/resources/default_100_percent/cros/network/status_cellular_enabled_hover.png
index d8326b1..77879ed 100644
--- a/ash/resources/default_100_percent/cros/network/status_cellular_enabled_hover.png
+++ b/ash/resources/default_100_percent/cros/network/status_cellular_enabled_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_cellular_failed.png b/ash/resources/default_100_percent/cros/network/status_cellular_failed.png
index c70d10e..412d9d4 100644
--- a/ash/resources/default_100_percent/cros/network/status_cellular_failed.png
+++ b/ash/resources/default_100_percent/cros/network/status_cellular_failed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_data_low.png b/ash/resources/default_100_percent/cros/network/status_data_low.png
index 7df1f9d..b757e5f 100644
--- a/ash/resources/default_100_percent/cros/network/status_data_low.png
+++ b/ash/resources/default_100_percent/cros/network/status_data_low.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_data_none.png b/ash/resources/default_100_percent/cros/network/status_data_none.png
index 1548778..07aee20 100644
--- a/ash/resources/default_100_percent/cros/network/status_data_none.png
+++ b/ash/resources/default_100_percent/cros/network/status_data_none.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_arcs_dark.png b/ash/resources/default_100_percent/cros/network/statusbar_network_arcs_dark.png
index 1ae409f..29b6c72 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_arcs_dark.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_arcs_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_arcs_light.png b/ash/resources/default_100_percent/cros/network/statusbar_network_arcs_light.png
index 512f976..2d783f6 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_arcs_light.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_arcs_light.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_bars_dark.png b/ash/resources/default_100_percent/cros/network/statusbar_network_bars_dark.png
index d0fa516..9facf9f 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_bars_dark.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_bars_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_bars_light.png b/ash/resources/default_100_percent/cros/network/statusbar_network_bars_light.png
index 15dc018..4f77026 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_bars_light.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_bars_light.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_hspa_plus_dark.png b/ash/resources/default_100_percent/cros/network/statusbar_network_hspa_plus_dark.png
index 3c74a7f..2b34e39 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_hspa_plus_dark.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_hspa_plus_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_lte_advanced_dark.png b/ash/resources/default_100_percent/cros/network/statusbar_network_lte_advanced_dark.png
index 2d37ee0..db3ab77 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_lte_advanced_dark.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_lte_advanced_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_lte_dark.png b/ash/resources/default_100_percent/cros/network/statusbar_network_lte_dark.png
index e93bf61..84b7c7c 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_lte_dark.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_lte_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_wired.png b/ash/resources/default_100_percent/cros/network/statusbar_wired.png
index 22a8061..14335f7 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_wired.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_wired.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/notification/notification_low_power_charger.png b/ash/resources/default_100_percent/cros/notification/notification_low_power_charger.png
new file mode 100644
index 0000000..d410c4b
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/notification/notification_low_power_charger.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/multiprofiles_add.png b/ash/resources/default_100_percent/cros/status/multiprofiles_add.png
index e464320..0e8a7a1 100644
--- a/ash/resources/default_100_percent/cros/status/multiprofiles_add.png
+++ b/ash/resources/default_100_percent/cros/status/multiprofiles_add.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_audio_device_bluetooth.png b/ash/resources/default_100_percent/cros/status/status_audio_device_bluetooth.png
index 6c8a44a..073b821 100644
--- a/ash/resources/default_100_percent/cros/status/status_audio_device_bluetooth.png
+++ b/ash/resources/default_100_percent/cros/status/status_audio_device_bluetooth.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_audio_device_usb.png b/ash/resources/default_100_percent/cros/status/status_audio_device_usb.png
index d3f9ddd..b093268 100644
--- a/ash/resources/default_100_percent/cros/status/status_audio_device_usb.png
+++ b/ash/resources/default_100_percent/cros/status/status_audio_device_usb.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_bluetooth_disabled.png b/ash/resources/default_100_percent/cros/status/status_bluetooth_disabled.png
index 508866a..4f8cae0 100644
--- a/ash/resources/default_100_percent/cros/status/status_bluetooth_disabled.png
+++ b/ash/resources/default_100_percent/cros/status/status_bluetooth_disabled.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_bluetooth_disabled_hover.png b/ash/resources/default_100_percent/cros/status/status_bluetooth_disabled_hover.png
index de3977c..66b1dd2 100644
--- a/ash/resources/default_100_percent/cros/status/status_bluetooth_disabled_hover.png
+++ b/ash/resources/default_100_percent/cros/status/status_bluetooth_disabled_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_bluetooth_enabled.png b/ash/resources/default_100_percent/cros/status/status_bluetooth_enabled.png
index 85298b2..c06841b 100644
--- a/ash/resources/default_100_percent/cros/status/status_bluetooth_enabled.png
+++ b/ash/resources/default_100_percent/cros/status/status_bluetooth_enabled.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_bluetooth_enabled_hover.png b/ash/resources/default_100_percent/cros/status/status_bluetooth_enabled_hover.png
index 4171c0d..0bf56fb 100644
--- a/ash/resources/default_100_percent/cros/status/status_bluetooth_enabled_hover.png
+++ b/ash/resources/default_100_percent/cros/status/status_bluetooth_enabled_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_brightness.png b/ash/resources/default_100_percent/cros/status/status_brightness.png
index 5c2f161..08ce57a 100644
--- a/ash/resources/default_100_percent/cros/status/status_brightness.png
+++ b/ash/resources/default_100_percent/cros/status/status_brightness.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_capslock.png b/ash/resources/default_100_percent/cros/status/status_capslock.png
index 55191f1..8b0e095 100644
--- a/ash/resources/default_100_percent/cros/status/status_capslock.png
+++ b/ash/resources/default_100_percent/cros/status/status_capslock.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_display.png b/ash/resources/default_100_percent/cros/status/status_display.png
index 4c82782..df3f63d 100644
--- a/ash/resources/default_100_percent/cros/status/status_display.png
+++ b/ash/resources/default_100_percent/cros/status/status_display.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_display_dark.png b/ash/resources/default_100_percent/cros/status/status_display_dark.png
index cf8cda9..6bb251b 100644
--- a/ash/resources/default_100_percent/cros/status/status_display_dark.png
+++ b/ash/resources/default_100_percent/cros/status/status_display_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_drive_item_failed.png b/ash/resources/default_100_percent/cros/status/status_drive_item_failed.png
index 99ebc18..09e0c81 100644
--- a/ash/resources/default_100_percent/cros/status/status_drive_item_failed.png
+++ b/ash/resources/default_100_percent/cros/status/status_drive_item_failed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_managed.png b/ash/resources/default_100_percent/cros/status/status_managed.png
index c0cf96f..88155e7 100644
--- a/ash/resources/default_100_percent/cros/status/status_managed.png
+++ b/ash/resources/default_100_percent/cros/status/status_managed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_managed_mode_user.png b/ash/resources/default_100_percent/cros/status/status_managed_mode_user.png
index 02066e5..5110417 100644
--- a/ash/resources/default_100_percent/cros/status/status_managed_mode_user.png
+++ b/ash/resources/default_100_percent/cros/status/status_managed_mode_user.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_managed_tray.png b/ash/resources/default_100_percent/cros/status/status_managed_tray.png
index 398b2cc..709546e 100644
--- a/ash/resources/default_100_percent/cros/status/status_managed_tray.png
+++ b/ash/resources/default_100_percent/cros/status/status_managed_tray.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_more.png b/ash/resources/default_100_percent/cros/status/status_more.png
index 23be76e..6c27f4e 100644
--- a/ash/resources/default_100_percent/cros/status/status_more.png
+++ b/ash/resources/default_100_percent/cros/status/status_more.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_power_small_all.png b/ash/resources/default_100_percent/cros/status/status_power_small_all.png
index 58747de..f09e1fc 100644
--- a/ash/resources/default_100_percent/cros/status/status_power_small_all.png
+++ b/ash/resources/default_100_percent/cros/status/status_power_small_all.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_power_small_all_dark.png b/ash/resources/default_100_percent/cros/status/status_power_small_all_dark.png
index e827389..c5f4a86 100644
--- a/ash/resources/default_100_percent/cros/status/status_power_small_all_dark.png
+++ b/ash/resources/default_100_percent/cros/status/status_power_small_all_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_power_small_all_dark_discharging.png b/ash/resources/default_100_percent/cros/status/status_power_small_all_dark_discharging.png
index 4088573..19bcaa1 100644
--- a/ash/resources/default_100_percent/cros/status/status_power_small_all_dark_discharging.png
+++ b/ash/resources/default_100_percent/cros/status/status_power_small_all_dark_discharging.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_power_small_all_dark_fluctuating.png b/ash/resources/default_100_percent/cros/status/status_power_small_all_dark_fluctuating.png
index eaf7982..d8a10e8 100644
--- a/ash/resources/default_100_percent/cros/status/status_power_small_all_dark_fluctuating.png
+++ b/ash/resources/default_100_percent/cros/status/status_power_small_all_dark_fluctuating.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_power_small_all_discharging.png b/ash/resources/default_100_percent/cros/status/status_power_small_all_discharging.png
index 52f127d..108d98b 100644
--- a/ash/resources/default_100_percent/cros/status/status_power_small_all_discharging.png
+++ b/ash/resources/default_100_percent/cros/status/status_power_small_all_discharging.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_power_small_all_fluctuating.png b/ash/resources/default_100_percent/cros/status/status_power_small_all_fluctuating.png
index 0ca74f2..3c37c59 100644
--- a/ash/resources/default_100_percent/cros/status/status_power_small_all_fluctuating.png
+++ b/ash/resources/default_100_percent/cros/status/status_power_small_all_fluctuating.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_session_length_limit_timer.png b/ash/resources/default_100_percent/cros/status/status_session_length_limit_timer.png
index c8016c1..2e0fd04 100644
--- a/ash/resources/default_100_percent/cros/status/status_session_length_limit_timer.png
+++ b/ash/resources/default_100_percent/cros/status/status_session_length_limit_timer.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_shutdown.png b/ash/resources/default_100_percent/cros/status/status_shutdown.png
index abd2a97..00328f9 100644
--- a/ash/resources/default_100_percent/cros/status/status_shutdown.png
+++ b/ash/resources/default_100_percent/cros/status/status_shutdown.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_shutdown_hover.png b/ash/resources/default_100_percent/cros/status/status_shutdown_hover.png
index 22cc83c..0658652 100644
--- a/ash/resources/default_100_percent/cros/status/status_shutdown_hover.png
+++ b/ash/resources/default_100_percent/cros/status/status_shutdown_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_sms.png b/ash/resources/default_100_percent/cros/status/status_sms.png
index 6074d43..093ce58 100644
--- a/ash/resources/default_100_percent/cros/status/status_sms.png
+++ b/ash/resources/default_100_percent/cros/status/status_sms.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_update.png b/ash/resources/default_100_percent/cros/status/status_update.png
index 591a827..2489bbb 100644
--- a/ash/resources/default_100_percent/cros/status/status_update.png
+++ b/ash/resources/default_100_percent/cros/status/status_update.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_update_orange.png b/ash/resources/default_100_percent/cros/status/status_update_orange.png
index 7442d50..43d61c7 100644
--- a/ash/resources/default_100_percent/cros/status/status_update_orange.png
+++ b/ash/resources/default_100_percent/cros/status/status_update_orange.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_update_red.png b/ash/resources/default_100_percent/cros/status/status_update_red.png
index f6ef96ac..a73b85a 100644
--- a/ash/resources/default_100_percent/cros/status/status_update_red.png
+++ b/ash/resources/default_100_percent/cros/status/status_update_red.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_volume_dark.png b/ash/resources/default_100_percent/cros/status/status_volume_dark.png
index ecd5962..76dc185 100644
--- a/ash/resources/default_100_percent/cros/status/status_volume_dark.png
+++ b/ash/resources/default_100_percent/cros/status/status_volume_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_volume_mute.png b/ash/resources/default_100_percent/cros/status/status_volume_mute.png
index dca2cb4..04aded3 100644
--- a/ash/resources/default_100_percent/cros/status/status_volume_mute.png
+++ b/ash/resources/default_100_percent/cros/status/status_volume_mute.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alert_small.png b/ash/resources/default_200_percent/common/alert_small.png
index bf1b90a..544f98a 100644
--- a/ash/resources/default_200_percent/common/alert_small.png
+++ b/ash/resources/default_200_percent/common/alert_small.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/launcher_background.png b/ash/resources/default_200_percent/common/alt_launcher/launcher_background.png
index b68ef01..5a62204 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/launcher_background.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/launcher_background.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/launcher_underline_active.png b/ash/resources/default_200_percent/common/alt_launcher/launcher_underline_active.png
index d057bf3..f89d8f5 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/launcher_underline_active.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/launcher_underline_active.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/launcher_underline_running.png b/ash/resources/default_200_percent/common/alt_launcher/launcher_underline_running.png
index 06d9f68..ede3d2d 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/launcher_underline_running.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/launcher_underline_running.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_app_menu_icon.png b/ash/resources/default_200_percent/common/alt_launcher/status_app_menu_icon.png
index 1ac214f..2e1a70f 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_app_menu_icon.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_app_menu_icon.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_normal.png b/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_normal.png
index 3cf8a42..cc2d1b7 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_normal.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_onblack_normal.png b/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_onblack_normal.png
index b286103..55bac58 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_onblack_normal.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_onblack_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_pressed.png b/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_pressed.png
index 082a876..498b80b 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_pressed.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_icon_background_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_notification_icon.png b/ash/resources/default_200_percent/common/alt_launcher/status_notification_icon.png
index b8f252d..19322c5 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_notification_icon.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_notification_icon.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_center.png
index 6de16b0..9b07237 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_left.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_left.png
index e50e4e3..dba3b69 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_left.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_center.png
index 6a5a985..ea17751 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_left.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_left.png
index 38ea70b..ff4e1ef 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_left.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_right.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_right.png
index ab08fd1..9284fa8 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_right.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_onblack_right.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_right.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_right.png
index 0a855c1..bb129f5 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_right.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_normal_right.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_center.png
index e397005..953e1ed 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
index 619dd69..0ad8bd1 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_right.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_right.png
index a574cab..27207a1 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_right.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_right.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_appmenu_hover.png b/ash/resources/default_200_percent/common/launcher/launcher_appmenu_hover.png
index 5758ec9..7762f27 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_appmenu_hover.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_appmenu_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_appmenu_pressed.png b/ash/resources/default_200_percent/common/launcher/launcher_appmenu_pressed.png
index dd40409..82ca4b2 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_appmenu_pressed.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_appmenu_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_background_right.png b/ash/resources/default_200_percent/common/launcher/launcher_background_right.png
index bbab21c..593780b 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_background_right.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_background_right.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_browser.png b/ash/resources/default_200_percent/common/launcher/launcher_browser.png
index 5fc5e5b..0f02221 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_browser.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_browser.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_browser_panel.png b/ash/resources/default_200_percent/common/launcher/launcher_browser_panel.png
index d5a3609..457026e 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_browser_panel.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_browser_panel.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser.png b/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser.png
index 45f0cfa..f6d4821 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png b/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
index 87e923a..d0e2c63 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_overflow.png b/ash/resources/default_200_percent/common/launcher/launcher_overflow.png
index 895d8f7..bddc06c 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_overflow.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_overflow.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_bottom_active.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_bottom_active.png
index 2246c96..2118115 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_bottom_active.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_bottom_active.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_bottom_running.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_bottom_running.png
index 58d1343..7b7e3e2 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_bottom_running.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_bottom_running.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_active.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_active.png
index f4522fe..c2937e7 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_active.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_active.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
index f4522fe..fc1ee96 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_running.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_running.png
index c281866..d7ac049 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_running.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_running.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_right_active.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_right_active.png
index 9757703..2f9ac00 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_right_active.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_right_active.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_right_hover.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_right_hover.png
index 9757703..2f9ac00 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_right_hover.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_right_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_right_running.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_right_running.png
index 974c8c5..8fade19 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_right_running.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_right_running.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/task_manager.png b/ash/resources/default_200_percent/common/launcher/task_manager.png
index ecd9176..63b1821 100644
--- a/ash/resources/default_200_percent/common/launcher/task_manager.png
+++ b/ash/resources/default_200_percent/common/launcher/task_manager.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/window_switcher_icon_normal.png b/ash/resources/default_200_percent/common/launcher/window_switcher_icon_normal.png
index accf7d4..a718a45 100644
--- a/ash/resources/default_200_percent/common/launcher/window_switcher_icon_normal.png
+++ b/ash/resources/default_200_percent/common/launcher/window_switcher_icon_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/multi_window_resize_vertical.png b/ash/resources/default_200_percent/common/multi_window_resize_vertical.png
index 2f56fa5..80f7d62 100644
--- a/ash/resources/default_200_percent/common/multi_window_resize_vertical.png
+++ b/ash/resources/default_200_percent/common/multi_window_resize_vertical.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/notification/notification_button_active_hover.png b/ash/resources/default_200_percent/common/notification/notification_button_active_hover.png
index 4327172..be2ea52 100644
--- a/ash/resources/default_200_percent/common/notification/notification_button_active_hover.png
+++ b/ash/resources/default_200_percent/common/notification/notification_button_active_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/notification/notification_button_active_normal.png b/ash/resources/default_200_percent/common/notification/notification_button_active_normal.png
index 4327172..328e3b1 100644
--- a/ash/resources/default_200_percent/common/notification/notification_button_active_normal.png
+++ b/ash/resources/default_200_percent/common/notification/notification_button_active_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/notification/notification_button_active_pressed.png b/ash/resources/default_200_percent/common/notification/notification_button_active_pressed.png
index e0643d5..54cb9a0 100644
--- a/ash/resources/default_200_percent/common/notification/notification_button_active_pressed.png
+++ b/ash/resources/default_200_percent/common/notification/notification_button_active_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/notification/notification_button_inactive_hover.png b/ash/resources/default_200_percent/common/notification/notification_button_inactive_hover.png
index aa5b511..fde7fe1 100644
--- a/ash/resources/default_200_percent/common/notification/notification_button_inactive_hover.png
+++ b/ash/resources/default_200_percent/common/notification/notification_button_inactive_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/notification/notification_button_inactive_normal.png b/ash/resources/default_200_percent/common/notification/notification_button_inactive_normal.png
index 75e80fd..c2284c2 100644
--- a/ash/resources/default_200_percent/common/notification/notification_button_inactive_normal.png
+++ b/ash/resources/default_200_percent/common/notification/notification_button_inactive_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/notification/notification_button_inactive_pressed.png b/ash/resources/default_200_percent/common/notification/notification_button_inactive_pressed.png
index 41fdc1f..ac515e7 100644
--- a/ash/resources/default_200_percent/common/notification/notification_button_inactive_pressed.png
+++ b/ash/resources/default_200_percent/common/notification/notification_button_inactive_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/notification/notification_icon.png b/ash/resources/default_200_percent/common/notification/notification_icon.png
index d851cdd..8a44727 100644
--- a/ash/resources/default_200_percent/common/notification/notification_icon.png
+++ b/ash/resources/default_200_percent/common/notification/notification_icon.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_fullscreen_hover.png b/ash/resources/default_200_percent/common/window_close_fullscreen_hover.png
index 2523d2c..450c886 100644
--- a/ash/resources/default_200_percent/common/window_close_fullscreen_hover.png
+++ b/ash/resources/default_200_percent/common/window_close_fullscreen_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_fullscreen_normal.png b/ash/resources/default_200_percent/common/window_close_fullscreen_normal.png
index 843af1f..c077c43 100644
--- a/ash/resources/default_200_percent/common/window_close_fullscreen_normal.png
+++ b/ash/resources/default_200_percent/common/window_close_fullscreen_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_fullscreen_pressed.png b/ash/resources/default_200_percent/common/window_close_fullscreen_pressed.png
index c5ccb7f..5c2ad3f 100644
--- a/ash/resources/default_200_percent/common/window_close_fullscreen_pressed.png
+++ b/ash/resources/default_200_percent/common/window_close_fullscreen_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_hover.png b/ash/resources/default_200_percent/common/window_close_short_black_hover.png
index 12c0979..f237da7 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_hover.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_normal.png b/ash/resources/default_200_percent/common/window_close_short_black_normal.png
index a30ebd2..174bee2 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_normal.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_pressed.png b/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
index fc3bd0c..c452fca 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_hover.png b/ash/resources/default_200_percent/common/window_close_short_hover.png
index 1b9e6fa..ad35cc7 100644
--- a/ash/resources/default_200_percent/common/window_close_short_hover.png
+++ b/ash/resources/default_200_percent/common/window_close_short_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_normal.png b/ash/resources/default_200_percent/common/window_close_short_normal.png
index c8afdec..d75809f 100644
--- a/ash/resources/default_200_percent/common/window_close_short_normal.png
+++ b/ash/resources/default_200_percent/common/window_close_short_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_pressed.png b/ash/resources/default_200_percent/common/window_close_short_pressed.png
index b11bd8f..e136ec5 100644
--- a/ash/resources/default_200_percent/common/window_close_short_pressed.png
+++ b/ash/resources/default_200_percent/common/window_close_short_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_tall_hover.png b/ash/resources/default_200_percent/common/window_close_tall_hover.png
index 8d22dae..011e670 100644
--- a/ash/resources/default_200_percent/common/window_close_tall_hover.png
+++ b/ash/resources/default_200_percent/common/window_close_tall_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_tall_normal.png b/ash/resources/default_200_percent/common/window_close_tall_normal.png
index 9c68fac..dd86f4a 100644
--- a/ash/resources/default_200_percent/common/window_close_tall_normal.png
+++ b/ash/resources/default_200_percent/common/window_close_tall_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_tall_pressed.png b/ash/resources/default_200_percent/common/window_close_tall_pressed.png
index 482ae01..b6cfd64 100644
--- a/ash/resources/default_200_percent/common/window_close_tall_pressed.png
+++ b/ash/resources/default_200_percent/common/window_close_tall_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_fullscreen_shadow.png b/ash/resources/default_200_percent/common/window_fullscreen_shadow.png
index 4c987c4..9c41fc0 100644
--- a/ash/resources/default_200_percent/common/window_fullscreen_shadow.png
+++ b/ash/resources/default_200_percent/common/window_fullscreen_shadow.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_header_shade_left.png b/ash/resources/default_200_percent/common/window_header_shade_left.png
index da6e234..46f341e 100644
--- a/ash/resources/default_200_percent/common/window_header_shade_left.png
+++ b/ash/resources/default_200_percent/common/window_header_shade_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_immersive_enter_hover.png b/ash/resources/default_200_percent/common/window_immersive_enter_hover.png
index 697cd5f..fb796a0 100644
--- a/ash/resources/default_200_percent/common/window_immersive_enter_hover.png
+++ b/ash/resources/default_200_percent/common/window_immersive_enter_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_immersive_exit_normal.png b/ash/resources/default_200_percent/common/window_immersive_exit_normal.png
index d972dda..bcf3050 100644
--- a/ash/resources/default_200_percent/common/window_immersive_exit_normal.png
+++ b/ash/resources/default_200_percent/common/window_immersive_exit_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_immersive_exit_pressed.png b/ash/resources/default_200_percent/common/window_immersive_exit_pressed.png
index 199b91d..724f7f2 100644
--- a/ash/resources/default_200_percent/common/window_immersive_exit_pressed.png
+++ b/ash/resources/default_200_percent/common/window_immersive_exit_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_minimize_short_hover.png b/ash/resources/default_200_percent/common/window_minimize_short_hover.png
index 79288b7..452ebc8 100644
--- a/ash/resources/default_200_percent/common/window_minimize_short_hover.png
+++ b/ash/resources/default_200_percent/common/window_minimize_short_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_minimize_short_normal.png b/ash/resources/default_200_percent/common/window_minimize_short_normal.png
index c62b876..29f8470 100644
--- a/ash/resources/default_200_percent/common/window_minimize_short_normal.png
+++ b/ash/resources/default_200_percent/common/window_minimize_short_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_minimize_short_pressed.png b/ash/resources/default_200_percent/common/window_minimize_short_pressed.png
index 3c0a40c..7511d7d 100644
--- a/ash/resources/default_200_percent/common/window_minimize_short_pressed.png
+++ b/ash/resources/default_200_percent/common/window_minimize_short_pressed.png
Binary files differ
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
index 7e69a2a..4d79bb2 100644
--- 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 differ
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
index 1a6d54e..61c5387 100644
--- 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 differ
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
index f299844..bba0ff4 100644
--- 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 differ
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
index 73bcc2d..b7fae08 100644
--- 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 differ
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
index 3507542..6b319db 100644
--- 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 differ
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
index 035fc6b..fe65289 100644
--- 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 differ
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
index 9d0b8d1..f664867 100644
--- 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 differ
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
index 47fad5c..e31c729 100644
--- 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 differ
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
index 7d75941..e5a5be3 100644
--- 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 differ
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
index 8aec6e6..1a8e7a2 100644
--- 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 differ
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
index 62b4b5f..3cf2d4b 100644
--- 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 differ
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
index c8af642..b5e5336 100644
--- 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 differ
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
index f3ba8cd..62bb151 100644
--- 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 differ
diff --git a/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png b/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
index c2711ef..2855067 100644
--- a/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
+++ b/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png b/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
index 0e9ecd2..688028d 100644
--- a/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
+++ b/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_fullscreen_pressed.png b/ash/resources/default_200_percent/common/window_size_fullscreen_pressed.png
index fc7d290..ca09716 100644
--- a/ash/resources/default_200_percent/common/window_size_fullscreen_pressed.png
+++ b/ash/resources/default_200_percent/common/window_size_fullscreen_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_short_black_normal.png b/ash/resources/default_200_percent/common/window_size_short_black_normal.png
index ce21dcd..d7cd09e 100644
--- a/ash/resources/default_200_percent/common/window_size_short_black_normal.png
+++ b/ash/resources/default_200_percent/common/window_size_short_black_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_short_black_pressed.png b/ash/resources/default_200_percent/common/window_size_short_black_pressed.png
index a6d0a8d..24d36b2 100644
--- a/ash/resources/default_200_percent/common/window_size_short_black_pressed.png
+++ b/ash/resources/default_200_percent/common/window_size_short_black_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_short_hover.png b/ash/resources/default_200_percent/common/window_size_short_hover.png
index aa624e5..39c3179 100644
--- a/ash/resources/default_200_percent/common/window_size_short_hover.png
+++ b/ash/resources/default_200_percent/common/window_size_short_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_short_normal.png b/ash/resources/default_200_percent/common/window_size_short_normal.png
index 0afbf2f..a318359 100644
--- a/ash/resources/default_200_percent/common/window_size_short_normal.png
+++ b/ash/resources/default_200_percent/common/window_size_short_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_short_pressed.png b/ash/resources/default_200_percent/common/window_size_short_pressed.png
index 2ae9f1b..1aca3db 100644
--- a/ash/resources/default_200_percent/common/window_size_short_pressed.png
+++ b/ash/resources/default_200_percent/common/window_size_short_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_tall_hover.png b/ash/resources/default_200_percent/common/window_size_tall_hover.png
index 1f8ba07..8d33073 100644
--- a/ash/resources/default_200_percent/common/window_size_tall_hover.png
+++ b/ash/resources/default_200_percent/common/window_size_tall_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_tall_normal.png b/ash/resources/default_200_percent/common/window_size_tall_normal.png
index c8e5115..928eb01 100644
--- a/ash/resources/default_200_percent/common/window_size_tall_normal.png
+++ b/ash/resources/default_200_percent/common/window_size_tall_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_tall_pressed.png b/ash/resources/default_200_percent/common/window_size_tall_pressed.png
index bcc2f8b..3e988f3 100644
--- a/ash/resources/default_200_percent/common/window_size_tall_pressed.png
+++ b/ash/resources/default_200_percent/common/window_size_tall_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/common/default_throbber.png b/ash/resources/default_200_percent/cros/common/default_throbber.png
index ad8247e..1538e41 100644
--- a/ash/resources/default_200_percent/cros/common/default_throbber.png
+++ b/ash/resources/default_200_percent/cros/common/default_throbber.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/notification_3g.png b/ash/resources/default_200_percent/cros/network/notification_3g.png
index bacd42d..6c04076 100644
--- a/ash/resources/default_200_percent/cros/network/notification_3g.png
+++ b/ash/resources/default_200_percent/cros/network/notification_3g.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/notification_lte.png b/ash/resources/default_200_percent/cros/network/notification_lte.png
index a569889..0ca53f7 100644
--- a/ash/resources/default_200_percent/cros/network/notification_lte.png
+++ b/ash/resources/default_200_percent/cros/network/notification_lte.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_cellular_disabled.png b/ash/resources/default_200_percent/cros/network/status_cellular_disabled.png
index 7f75d5f..cd10247 100644
--- a/ash/resources/default_200_percent/cros/network/status_cellular_disabled.png
+++ b/ash/resources/default_200_percent/cros/network/status_cellular_disabled.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_cellular_disabled_hover.png b/ash/resources/default_200_percent/cros/network/status_cellular_disabled_hover.png
index 8e9991b..18ffd31 100644
--- a/ash/resources/default_200_percent/cros/network/status_cellular_disabled_hover.png
+++ b/ash/resources/default_200_percent/cros/network/status_cellular_disabled_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_cellular_enabled.png b/ash/resources/default_200_percent/cros/network/status_cellular_enabled.png
index 7cc460a..5817ab5 100644
--- a/ash/resources/default_200_percent/cros/network/status_cellular_enabled.png
+++ b/ash/resources/default_200_percent/cros/network/status_cellular_enabled.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_cellular_enabled_hover.png b/ash/resources/default_200_percent/cros/network/status_cellular_enabled_hover.png
index 0a27f99..f9c0c60 100644
--- a/ash/resources/default_200_percent/cros/network/status_cellular_enabled_hover.png
+++ b/ash/resources/default_200_percent/cros/network/status_cellular_enabled_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_cellular_failed.png b/ash/resources/default_200_percent/cros/network/status_cellular_failed.png
index a4f254f..282cc07 100644
--- a/ash/resources/default_200_percent/cros/network/status_cellular_failed.png
+++ b/ash/resources/default_200_percent/cros/network/status_cellular_failed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_data_low.png b/ash/resources/default_200_percent/cros/network/status_data_low.png
index 480e25c..e32346c 100644
--- a/ash/resources/default_200_percent/cros/network/status_data_low.png
+++ b/ash/resources/default_200_percent/cros/network/status_data_low.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_data_none.png b/ash/resources/default_200_percent/cros/network/status_data_none.png
index 9c22d8e..3f20d4a 100644
--- a/ash/resources/default_200_percent/cros/network/status_data_none.png
+++ b/ash/resources/default_200_percent/cros/network/status_data_none.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_network_failed.png b/ash/resources/default_200_percent/cros/network/status_network_failed.png
index 1776332..803a48e 100644
--- a/ash/resources/default_200_percent/cros/network/status_network_failed.png
+++ b/ash/resources/default_200_percent/cros/network/status_network_failed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_network_info.png b/ash/resources/default_200_percent/cros/network/status_network_info.png
index 2a42c36..98a9209 100644
--- a/ash/resources/default_200_percent/cros/network/status_network_info.png
+++ b/ash/resources/default_200_percent/cros/network/status_network_info.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_network_info_hover.png b/ash/resources/default_200_percent/cros/network/status_network_info_hover.png
index 3a9c90c..db3e266 100644
--- a/ash/resources/default_200_percent/cros/network/status_network_info_hover.png
+++ b/ash/resources/default_200_percent/cros/network/status_network_info_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_wifi_disabled.png b/ash/resources/default_200_percent/cros/network/status_wifi_disabled.png
index f9e2427..a9d54c7 100644
--- a/ash/resources/default_200_percent/cros/network/status_wifi_disabled.png
+++ b/ash/resources/default_200_percent/cros/network/status_wifi_disabled.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_wifi_disabled_hover.png b/ash/resources/default_200_percent/cros/network/status_wifi_disabled_hover.png
index d1ec838..b485bae 100644
--- a/ash/resources/default_200_percent/cros/network/status_wifi_disabled_hover.png
+++ b/ash/resources/default_200_percent/cros/network/status_wifi_disabled_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png b/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
index c140f7c..4fae330 100644
--- a/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
+++ b/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png b/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
index 1f91e30..bfb35bd 100644
--- a/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
+++ b/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_3g_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_3g_light.png
index e493160..095a889 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_3g_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_3g_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_4g_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_4g_light.png
index 3f190f5..e783596 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_4g_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_4g_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_arcs_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_arcs_dark.png
index b87ecdc..f3c281f 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_arcs_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_arcs_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_arcs_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_arcs_light.png
index 4886542..108249c 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_arcs_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_arcs_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_bars_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_bars_dark.png
index e7d82aa..548ef5f 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_bars_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_bars_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_bars_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_bars_light.png
index f5c2661..90f2232 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_bars_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_bars_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_gprs_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_gprs_dark.png
index 12aa268..c45081d 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_gprs_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_gprs_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_hspa_plus_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_hspa_plus_dark.png
index a4d9b21..a352289 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_hspa_plus_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_hspa_plus_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_lte_advanced_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_lte_advanced_dark.png
index ca86c91..50c496a 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_lte_advanced_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_lte_advanced_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_lte_advanced_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_lte_advanced_light.png
index 72b5cc3..ef9f7ce 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_lte_advanced_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_lte_advanced_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_lte_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_lte_dark.png
index d6bc7fb..1c72085 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_lte_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_lte_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_lte_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_lte_light.png
index e1b5bab..53f9ab1 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_lte_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_lte_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_roaming_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_roaming_dark.png
index 72a8057..f59974f 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_roaming_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_roaming_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_roaming_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_roaming_light.png
index 0196152..ae7fade 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_roaming_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_roaming_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_secure_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_secure_dark.png
index 2708a23..1089307 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_secure_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_secure_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_secure_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_secure_light.png
index d2190ea..022dd66 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_secure_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_secure_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_vpn_badge.png b/ash/resources/default_200_percent/cros/network/statusbar_network_vpn_badge.png
index 7f60574..07a0756 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_vpn_badge.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_vpn_badge.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_vpn_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_vpn_dark.png
index 237e189..5503851 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_vpn_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_vpn_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/notification/notification_low_power_charger.png b/ash/resources/default_200_percent/cros/notification/notification_low_power_charger.png
new file mode 100644
index 0000000..78a6b88
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/notification/notification_low_power_charger.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/multiprofiles_add.png b/ash/resources/default_200_percent/cros/status/multiprofiles_add.png
index e62b626..2fb62cd 100644
--- a/ash/resources/default_200_percent/cros/status/multiprofiles_add.png
+++ b/ash/resources/default_200_percent/cros/status/multiprofiles_add.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_audio_device_bluetooth.png b/ash/resources/default_200_percent/cros/status/status_audio_device_bluetooth.png
index 203f2ae..28d36d0 100644
--- a/ash/resources/default_200_percent/cros/status/status_audio_device_bluetooth.png
+++ b/ash/resources/default_200_percent/cros/status/status_audio_device_bluetooth.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_audio_device_hdmi.png b/ash/resources/default_200_percent/cros/status/status_audio_device_hdmi.png
index 69d263f..d6ddc09 100644
--- a/ash/resources/default_200_percent/cros/status/status_audio_device_hdmi.png
+++ b/ash/resources/default_200_percent/cros/status/status_audio_device_hdmi.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_audio_device_headphones.png b/ash/resources/default_200_percent/cros/status/status_audio_device_headphones.png
index 4266d86..4c0e648 100644
--- a/ash/resources/default_200_percent/cros/status/status_audio_device_headphones.png
+++ b/ash/resources/default_200_percent/cros/status/status_audio_device_headphones.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_audio_device_usb.png b/ash/resources/default_200_percent/cros/status/status_audio_device_usb.png
index a418ecd..f17edcf 100644
--- a/ash/resources/default_200_percent/cros/status/status_audio_device_usb.png
+++ b/ash/resources/default_200_percent/cros/status/status_audio_device_usb.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_bluetooth.png b/ash/resources/default_200_percent/cros/status/status_bluetooth.png
index 4c6b397..d4cf7c7 100644
--- a/ash/resources/default_200_percent/cros/status/status_bluetooth.png
+++ b/ash/resources/default_200_percent/cros/status/status_bluetooth.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_bluetooth_disabled.png b/ash/resources/default_200_percent/cros/status/status_bluetooth_disabled.png
index 4ec7293..6676cf9 100644
--- a/ash/resources/default_200_percent/cros/status/status_bluetooth_disabled.png
+++ b/ash/resources/default_200_percent/cros/status/status_bluetooth_disabled.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_bluetooth_disabled_hover.png b/ash/resources/default_200_percent/cros/status/status_bluetooth_disabled_hover.png
index 793ad0c..66f368d 100644
--- a/ash/resources/default_200_percent/cros/status/status_bluetooth_disabled_hover.png
+++ b/ash/resources/default_200_percent/cros/status/status_bluetooth_disabled_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_bluetooth_enabled.png b/ash/resources/default_200_percent/cros/status/status_bluetooth_enabled.png
index e478713..d9ee935 100644
--- a/ash/resources/default_200_percent/cros/status/status_bluetooth_enabled.png
+++ b/ash/resources/default_200_percent/cros/status/status_bluetooth_enabled.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_bluetooth_enabled_hover.png b/ash/resources/default_200_percent/cros/status/status_bluetooth_enabled_hover.png
index 40223f3..a4fa7eb 100644
--- a/ash/resources/default_200_percent/cros/status/status_bluetooth_enabled_hover.png
+++ b/ash/resources/default_200_percent/cros/status/status_bluetooth_enabled_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_brightness.png b/ash/resources/default_200_percent/cros/status/status_brightness.png
index 86880a6..547982e 100644
--- a/ash/resources/default_200_percent/cros/status/status_brightness.png
+++ b/ash/resources/default_200_percent/cros/status/status_brightness.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_capslock.png b/ash/resources/default_200_percent/cros/status/status_capslock.png
index 6e118a6..7ceed83 100644
--- a/ash/resources/default_200_percent/cros/status/status_capslock.png
+++ b/ash/resources/default_200_percent/cros/status/status_capslock.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_capslock_dark.png b/ash/resources/default_200_percent/cros/status/status_capslock_dark.png
index cbb24b6..1d78d5d 100644
--- a/ash/resources/default_200_percent/cros/status/status_capslock_dark.png
+++ b/ash/resources/default_200_percent/cros/status/status_capslock_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_display.png b/ash/resources/default_200_percent/cros/status/status_display.png
index d511b29..b89a120 100644
--- a/ash/resources/default_200_percent/cros/status/status_display.png
+++ b/ash/resources/default_200_percent/cros/status/status_display.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_display_dark.png b/ash/resources/default_200_percent/cros/status/status_display_dark.png
index 6fce73c..9d28ca2 100644
--- a/ash/resources/default_200_percent/cros/status/status_display_dark.png
+++ b/ash/resources/default_200_percent/cros/status/status_display_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_drive.png b/ash/resources/default_200_percent/cros/status/status_drive.png
index 84490ce..43e6877 100644
--- a/ash/resources/default_200_percent/cros/status/status_drive.png
+++ b/ash/resources/default_200_percent/cros/status/status_drive.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_drive_item_cancel_hover.png b/ash/resources/default_200_percent/cros/status/status_drive_item_cancel_hover.png
index dc9f9e0..9b02e58 100644
--- a/ash/resources/default_200_percent/cros/status/status_drive_item_cancel_hover.png
+++ b/ash/resources/default_200_percent/cros/status/status_drive_item_cancel_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_drive_item_failed.png b/ash/resources/default_200_percent/cros/status/status_drive_item_failed.png
index c455e5a..3ed87e1 100644
--- a/ash/resources/default_200_percent/cros/status/status_drive_item_failed.png
+++ b/ash/resources/default_200_percent/cros/status/status_drive_item_failed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_drive_light.png b/ash/resources/default_200_percent/cros/status/status_drive_light.png
index 34f9ba8..bfea7bd 100644
--- a/ash/resources/default_200_percent/cros/status/status_drive_light.png
+++ b/ash/resources/default_200_percent/cros/status/status_drive_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_ime.png b/ash/resources/default_200_percent/cros/status/status_ime.png
index 30df35c..f0104f0 100644
--- a/ash/resources/default_200_percent/cros/status/status_ime.png
+++ b/ash/resources/default_200_percent/cros/status/status_ime.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_less.png b/ash/resources/default_200_percent/cros/status/status_less.png
index 2c756c2..8c5e81f 100644
--- a/ash/resources/default_200_percent/cros/status/status_less.png
+++ b/ash/resources/default_200_percent/cros/status/status_less.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_locale.png b/ash/resources/default_200_percent/cros/status/status_locale.png
index 8339309..dab0994 100644
--- a/ash/resources/default_200_percent/cros/status/status_locale.png
+++ b/ash/resources/default_200_percent/cros/status/status_locale.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_lockscreen.png b/ash/resources/default_200_percent/cros/status/status_lockscreen.png
index 60166ce..9d7fdcd 100644
--- a/ash/resources/default_200_percent/cros/status/status_lockscreen.png
+++ b/ash/resources/default_200_percent/cros/status/status_lockscreen.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_lockscreen_hover.png b/ash/resources/default_200_percent/cros/status/status_lockscreen_hover.png
index df585f2..e4aa68a 100644
--- a/ash/resources/default_200_percent/cros/status/status_lockscreen_hover.png
+++ b/ash/resources/default_200_percent/cros/status/status_lockscreen_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_logout_button_hover_bottom_right.png b/ash/resources/default_200_percent/cros/status/status_logout_button_hover_bottom_right.png
index c42cfb9..216bffd 100644
--- a/ash/resources/default_200_percent/cros/status/status_logout_button_hover_bottom_right.png
+++ b/ash/resources/default_200_percent/cros/status/status_logout_button_hover_bottom_right.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_managed.png b/ash/resources/default_200_percent/cros/status/status_managed.png
index c9937a3..19161c1 100644
--- a/ash/resources/default_200_percent/cros/status/status_managed.png
+++ b/ash/resources/default_200_percent/cros/status/status_managed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_managed_mode_user.png b/ash/resources/default_200_percent/cros/status/status_managed_mode_user.png
index 023a55e..b0b522d 100644
--- a/ash/resources/default_200_percent/cros/status/status_managed_mode_user.png
+++ b/ash/resources/default_200_percent/cros/status/status_managed_mode_user.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_managed_tray.png b/ash/resources/default_200_percent/cros/status/status_managed_tray.png
index 8f1c9f5..5019650 100644
--- a/ash/resources/default_200_percent/cros/status/status_managed_tray.png
+++ b/ash/resources/default_200_percent/cros/status/status_managed_tray.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_more.png b/ash/resources/default_200_percent/cros/status/status_more.png
index dbf5ebc..a33620b 100644
--- a/ash/resources/default_200_percent/cros/status/status_more.png
+++ b/ash/resources/default_200_percent/cros/status/status_more.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_power_small_all.png b/ash/resources/default_200_percent/cros/status/status_power_small_all.png
index ce25997..42b706d 100644
--- a/ash/resources/default_200_percent/cros/status/status_power_small_all.png
+++ b/ash/resources/default_200_percent/cros/status/status_power_small_all.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_power_small_all_dark.png b/ash/resources/default_200_percent/cros/status/status_power_small_all_dark.png
index 2c06574..d0ea331 100644
--- a/ash/resources/default_200_percent/cros/status/status_power_small_all_dark.png
+++ b/ash/resources/default_200_percent/cros/status/status_power_small_all_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_power_small_all_dark_discharging.png b/ash/resources/default_200_percent/cros/status/status_power_small_all_dark_discharging.png
index d31c677..3c5557e 100644
--- a/ash/resources/default_200_percent/cros/status/status_power_small_all_dark_discharging.png
+++ b/ash/resources/default_200_percent/cros/status/status_power_small_all_dark_discharging.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_power_small_all_dark_fluctuating.png b/ash/resources/default_200_percent/cros/status/status_power_small_all_dark_fluctuating.png
index e7f5a4e..8be069f 100644
--- a/ash/resources/default_200_percent/cros/status/status_power_small_all_dark_fluctuating.png
+++ b/ash/resources/default_200_percent/cros/status/status_power_small_all_dark_fluctuating.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_power_small_all_discharging.png b/ash/resources/default_200_percent/cros/status/status_power_small_all_discharging.png
index b1f8725..8c8490f 100644
--- a/ash/resources/default_200_percent/cros/status/status_power_small_all_discharging.png
+++ b/ash/resources/default_200_percent/cros/status/status_power_small_all_discharging.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png b/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
index 555c229..d46f7ca 100644
--- a/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
+++ b/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_screen_share_dark.png b/ash/resources/default_200_percent/cros/status/status_screen_share_dark.png
index 84490ce..392b99d 100644
--- a/ash/resources/default_200_percent/cros/status/status_screen_share_dark.png
+++ b/ash/resources/default_200_percent/cros/status/status_screen_share_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_screen_share_light.png b/ash/resources/default_200_percent/cros/status/status_screen_share_light.png
index 34f9ba8..4845e0a 100644
--- a/ash/resources/default_200_percent/cros/status/status_screen_share_light.png
+++ b/ash/resources/default_200_percent/cros/status/status_screen_share_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_session_length_limit_timer.png b/ash/resources/default_200_percent/cros/status/status_session_length_limit_timer.png
index 85becc0..0dbae98 100644
--- a/ash/resources/default_200_percent/cros/status/status_session_length_limit_timer.png
+++ b/ash/resources/default_200_percent/cros/status/status_session_length_limit_timer.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_settings.png b/ash/resources/default_200_percent/cros/status/status_settings.png
index 0ecd530..a5655d6 100644
--- a/ash/resources/default_200_percent/cros/status/status_settings.png
+++ b/ash/resources/default_200_percent/cros/status/status_settings.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_shutdown.png b/ash/resources/default_200_percent/cros/status/status_shutdown.png
index dc3a8f5..15ce5e1 100644
--- a/ash/resources/default_200_percent/cros/status/status_shutdown.png
+++ b/ash/resources/default_200_percent/cros/status/status_shutdown.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_shutdown_hover.png b/ash/resources/default_200_percent/cros/status/status_shutdown_hover.png
index c428613..f19ca3c 100644
--- a/ash/resources/default_200_percent/cros/status/status_shutdown_hover.png
+++ b/ash/resources/default_200_percent/cros/status/status_shutdown_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_sms.png b/ash/resources/default_200_percent/cros/status/status_sms.png
index f737f84..101156b 100644
--- a/ash/resources/default_200_percent/cros/status/status_sms.png
+++ b/ash/resources/default_200_percent/cros/status/status_sms.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_update_dark.png b/ash/resources/default_200_percent/cros/status/status_update_dark.png
index 48bbd44..4cba931 100644
--- a/ash/resources/default_200_percent/cros/status/status_update_dark.png
+++ b/ash/resources/default_200_percent/cros/status/status_update_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_update_dark_green.png b/ash/resources/default_200_percent/cros/status/status_update_dark_green.png
index 3a38219..c9ca473 100644
--- a/ash/resources/default_200_percent/cros/status/status_update_dark_green.png
+++ b/ash/resources/default_200_percent/cros/status/status_update_dark_green.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_update_dark_orange.png b/ash/resources/default_200_percent/cros/status/status_update_dark_orange.png
index 068fc4d..467b3f1 100644
--- a/ash/resources/default_200_percent/cros/status/status_update_dark_orange.png
+++ b/ash/resources/default_200_percent/cros/status/status_update_dark_orange.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_update_dark_red.png b/ash/resources/default_200_percent/cros/status/status_update_dark_red.png
index b52893f..e861ab6 100644
--- a/ash/resources/default_200_percent/cros/status/status_update_dark_red.png
+++ b/ash/resources/default_200_percent/cros/status/status_update_dark_red.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_update_orange.png b/ash/resources/default_200_percent/cros/status/status_update_orange.png
index 2283a4b..02e0469 100644
--- a/ash/resources/default_200_percent/cros/status/status_update_orange.png
+++ b/ash/resources/default_200_percent/cros/status/status_update_orange.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_update_red.png b/ash/resources/default_200_percent/cros/status/status_update_red.png
index 4ed4318..ef49b2d 100644
--- a/ash/resources/default_200_percent/cros/status/status_update_red.png
+++ b/ash/resources/default_200_percent/cros/status/status_update_red.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_volume_dark.png b/ash/resources/default_200_percent/cros/status/status_volume_dark.png
index d518f65..b8593a6 100644
--- a/ash/resources/default_200_percent/cros/status/status_volume_dark.png
+++ b/ash/resources/default_200_percent/cros/status/status_volume_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_volume_mute.png b/ash/resources/default_200_percent/cros/status/status_volume_mute.png
index ea8e9a3..7a6abc8 100644
--- a/ash/resources/default_200_percent/cros/status/status_volume_mute.png
+++ b/ash/resources/default_200_percent/cros/status/status_volume_mute.png
Binary files differ
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index af6e946..ba20f58 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -9,7 +9,7 @@
#include "ash/ash_constants.h"
#include "ash/ash_switches.h"
#include "ash/desktop_background/desktop_background_widget_controller.h"
-#include "ash/display/display_controller.h"
+#include "ash/desktop_background/user_wallpaper_delegate.h"
#include "ash/display/display_manager.h"
#include "ash/focus_cycler.h"
#include "ash/session_state_delegate.h"
@@ -22,11 +22,15 @@
#include "ash/shell_window_ids.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/tray/system_tray_delegate.h"
+#include "ash/touch/touch_hud_debug.h"
+#include "ash/touch/touch_hud_projection.h"
#include "ash/touch/touch_observer_hud.h"
+#include "ash/wm/always_on_top_controller.h"
#include "ash/wm/base_layout_manager.h"
#include "ash/wm/boot_splash_screen.h"
#include "ash/wm/dock/docked_window_layout_manager.h"
#include "ash/wm/panels/panel_layout_manager.h"
+#include "ash/wm/panels/panel_window_event_handler.h"
#include "ash/wm/property_util.h"
#include "ash/wm/root_window_layout_manager.h"
#include "ash/wm/screen_dimmer.h"
@@ -39,14 +43,13 @@
#include "ash/wm/window_util.h"
#include "ash/wm/workspace_controller.h"
#include "base/command_line.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/tooltip_client.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/base/models/menu_model.h"
-#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_util.h"
@@ -170,11 +173,12 @@
root_window_layout_(NULL),
docked_layout_manager_(NULL),
panel_layout_manager_(NULL),
- touch_observer_hud_(NULL) {
+ touch_hud_debug_(NULL),
+ touch_hud_projection_(NULL) {
SetRootWindowController(root_window, this);
screen_dimmer_.reset(new ScreenDimmer(root_window));
- stacking_controller_.reset(new ash::StackingController);
+ stacking_controller_.reset(new StackingController);
aura::client::SetStackingClient(root_window, stacking_controller_.get());
}
@@ -199,7 +203,36 @@
return GetRootWindowController(Shell::GetActiveRootWindow());
}
+void RootWindowController::EnableTouchHudProjection() {
+ if (touch_hud_projection_)
+ return;
+ set_touch_hud_projection(new TouchHudProjection(root_window_.get()));
+}
+
+void RootWindowController::DisableTouchHudProjection() {
+ if (!touch_hud_projection_)
+ return;
+ touch_hud_projection_->Remove();
+}
+
+void RootWindowController::SetWallpaperController(
+ DesktopBackgroundWidgetController* controller) {
+ wallpaper_controller_.reset(controller);
+}
+
+void RootWindowController::SetAnimatingWallpaperController(
+ AnimatingDesktopController* controller) {
+ if (animating_wallpaper_controller_.get())
+ animating_wallpaper_controller_->StopAnimating();
+ animating_wallpaper_controller_.reset(controller);
+}
+
void RootWindowController::Shutdown() {
+ if (animating_wallpaper_controller_.get())
+ animating_wallpaper_controller_->StopAnimating();
+ wallpaper_controller_.reset();
+ animating_wallpaper_controller_.reset();
+
CloseChildWindows();
if (Shell::GetActiveRootWindow() == root_window_) {
Shell::GetInstance()->set_active_root_window(
@@ -246,92 +279,26 @@
return root_window_->GetChildById(container_id);
}
-void RootWindowController::InitLayoutManagers() {
- root_window_layout_ =
- new RootWindowLayoutManager(root_window_.get());
- root_window_->SetLayoutManager(root_window_layout_);
-
- aura::Window* default_container =
- GetContainer(kShellWindowId_DefaultContainer);
- // Workspace manager has its own layout managers.
- workspace_controller_.reset(
- new WorkspaceController(default_container));
-
- aura::Window* always_on_top_container =
- GetContainer(kShellWindowId_AlwaysOnTopContainer);
- always_on_top_container->SetLayoutManager(
- new BaseLayoutManager(
- always_on_top_container->GetRootWindow()));
-}
-
-void RootWindowController::InitForPrimaryDisplay() {
- DCHECK(!shelf_.get());
- aura::Window* shelf_container =
- GetContainer(ash::internal::kShellWindowId_ShelfContainer);
- // TODO(harrym): Remove when status area is view.
- aura::Window* status_container =
- GetContainer(ash::internal::kShellWindowId_StatusContainer);
- shelf_.reset(new ash::ShelfWidget(
- shelf_container, status_container, workspace_controller()));
-
- // Create Docked windows layout manager
- aura::Window* docked_container = GetContainer(
- internal::kShellWindowId_DockedContainer);
- docked_layout_manager_ =
- new internal::DockedWindowLayoutManager(docked_container);
- docked_container_handler_.reset(
- new ToplevelWindowEventHandler(docked_container));
- docked_container->SetLayoutManager(docked_layout_manager_);
-
- // Create Panel layout manager
- aura::Window* panel_container = GetContainer(
- internal::kShellWindowId_PanelContainer);
- panel_layout_manager_ =
- new internal::PanelLayoutManager(panel_container);
- panel_container_handler_.reset(
- new ToplevelWindowEventHandler(panel_container));
- panel_container->SetLayoutManager(panel_layout_manager_);
-
- // TODO(stevenjb/oshima): Remove this call to CreateLauncher() and call
- // ash::Shell::CreateLauncher() explicitly in ash_shell and ash_unittests
- // so that the behavior and construction order is consistent betwheen Ash
- // and Chrome.
- if (Shell::GetInstance()->session_state_delegate()->NumberOfLoggedInUsers())
- shelf_->CreateLauncher();
-
- InitKeyboard();
-}
-
-void RootWindowController::CreateContainers() {
+void RootWindowController::Init(bool first_run_after_boot) {
+ root_window_->SetCursor(ui::kCursorPointer);
CreateContainersInRootWindow(root_window_.get());
+ CreateSystemBackground(first_run_after_boot);
- // Create touch observer HUD if needed. HUD should be created after the
- // containers have been created, so that its widget can be added to them.
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kAshTouchHud))
- touch_observer_hud_ = new TouchObserverHUD(root_window_.get());
+ InitLayoutManagers();
+ InitKeyboard();
+ InitTouchHuds();
+
+ if (Shell::GetPrimaryRootWindowController()->
+ GetSystemModalLayoutManager(NULL)->has_modal_background()) {
+ GetSystemModalLayoutManager(NULL)->CreateModalBackground();
+ }
}
-void RootWindowController::CreateSystemBackground(
- bool is_first_run_after_boot) {
- SkColor color = SK_ColorBLACK;
-#if defined(OS_CHROMEOS)
- if (is_first_run_after_boot)
- color = kChromeOsBootColor;
-#endif
- system_background_.reset(
- new SystemBackgroundController(root_window_.get(), color));
-
-#if defined(OS_CHROMEOS)
- // Make a copy of the system's boot splash screen so we can composite it
- // onscreen until the desktop background is ready.
- if (is_first_run_after_boot &&
- (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAshCopyHostBackgroundAtBoot) ||
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAshAnimateFromBootSplashScreen)))
- boot_splash_screen_.reset(new BootSplashScreen(root_window_.get()));
-#endif
+void RootWindowController::ShowLauncher() {
+ if (!shelf_->launcher())
+ return;
+ shelf_->launcher()->SetVisible(true);
+ shelf_->status_area_widget()->Show();
}
void RootWindowController::OnLauncherCreated() {
@@ -341,23 +308,13 @@
docked_layout_manager_->SetLauncher(shelf_->launcher());
}
-void RootWindowController::ShowLauncher() {
- if (!shelf_.get() || !shelf_->launcher())
- return;
- shelf_->launcher()->SetVisible(true);
- shelf_->status_area_widget()->Show();
-}
-
void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
- // TODO(oshima): remove if when launcher per display is enabled by
- // default.
- if (shelf_)
- shelf_->shelf_layout_manager()->UpdateVisibilityState();
+ shelf_->shelf_layout_manager()->UpdateVisibilityState();
}
void RootWindowController::UpdateAfterLoginStatusChange(
user::LoginStatus status) {
- if (shelf_.get() && shelf_->status_area_widget())
+ if (shelf_->status_area_widget())
shelf_->status_area_widget()->UpdateAfterLoginStatusChange(status);
}
@@ -372,12 +329,31 @@
}
}
-void RootWindowController::HandleDesktopBackgroundVisible() {
+void RootWindowController::OnWallpaperAnimationFinished(views::Widget* widget) {
+ // Make sure the wallpaper is visible.
system_background_->SetColor(SK_ColorBLACK);
boot_splash_screen_.reset();
+
+ Shell::GetInstance()->user_wallpaper_delegate()->
+ OnWallpaperAnimationFinished();
+ // Only removes old component when wallpaper animation finished. If we
+ // remove the old one before the new wallpaper is done fading in there will
+ // be a white flash during the animation.
+ if (animating_wallpaper_controller()) {
+ DesktopBackgroundWidgetController* controller =
+ animating_wallpaper_controller()->GetController(true);
+ // |desktop_widget_| should be the same animating widget we try to move
+ // to |kDesktopController|. Otherwise, we may close |desktop_widget_|
+ // before move it to |kDesktopController|.
+ DCHECK_EQ(controller->widget(), widget);
+ // Release the old controller and close its background widget.
+ SetWallpaperController(controller);
+ }
}
void RootWindowController::CloseChildWindows() {
+ if (!shelf_.get())
+ return;
// panel_layout_manager_ needs to be shut down before windows are destroyed.
if (panel_layout_manager_) {
panel_layout_manager_->Shutdown();
@@ -385,17 +361,14 @@
}
// TODO(harrym): Remove when Status Area Widget is a child view.
- if (shelf_)
- shelf_->ShutdownStatusAreaWidget();
+ shelf_->ShutdownStatusAreaWidget();
- if (shelf_.get() && shelf_->shelf_layout_manager())
+ if (shelf_->shelf_layout_manager())
shelf_->shelf_layout_manager()->set_workspace_controller(NULL);
// Close background widget first as it depends on tooltip.
- root_window_->SetProperty(kDesktopController,
- static_cast<DesktopBackgroundWidgetController*>(NULL));
- root_window_->SetProperty(kAnimatingDesktopController,
- static_cast<AnimatingDesktopController*>(NULL));
+ wallpaper_controller_.reset();
+ animating_wallpaper_controller_.reset();
workspace_controller_.reset();
aura::client::SetTooltipClient(root_window_.get(), NULL);
@@ -416,13 +389,13 @@
}
ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
- return shelf_.get() ? shelf_->shelf_layout_manager() : NULL;
+ return shelf_->shelf_layout_manager();
}
SystemTray* RootWindowController::GetSystemTray() {
// We assume in throughout the code that this will not return NULL. If code
// triggers this for valid reasons, it should test status_area_widget first.
- CHECK(shelf_.get() && shelf_->status_area_widget());
+ CHECK(shelf_->status_area_widget());
return shelf_->status_area_widget()->system_tray();
}
@@ -434,15 +407,13 @@
if (!menu_model)
return;
- internal::DesktopBackgroundWidgetController* background =
- root_window_->GetProperty(kDesktopController);
// Background controller may not be set yet if user clicked on status are
// before initial animation completion. See crbug.com/222218
- if (!background)
+ if (!wallpaper_controller_.get())
return;
views::MenuRunner menu_runner(menu_model.get());
- if (menu_runner.RunMenuAt(background->widget(),
+ if (menu_runner.RunMenuAt(wallpaper_controller_->widget(),
NULL, gfx::Rect(location_in_screen, gfx::Size()),
views::MenuItemView::TOPLEFT, source_type,
views::MenuRunner::CONTEXT_MENU) ==
@@ -461,7 +432,7 @@
aura::Window* container = workspace_controller_->GetActiveWorkspaceWindow();
for (size_t i = 0; i < container->children().size(); ++i) {
aura::Window* child = container->children()[i];
- if (ash::wm::IsWindowFullscreen(child))
+ if (wm::IsWindowFullscreen(child))
return child;
}
return NULL;
@@ -490,6 +461,83 @@
////////////////////////////////////////////////////////////////////////////////
// RootWindowController, private:
+void RootWindowController::InitLayoutManagers() {
+ root_window_layout_ =
+ new RootWindowLayoutManager(root_window_.get());
+ root_window_->SetLayoutManager(root_window_layout_);
+
+ aura::Window* default_container =
+ GetContainer(kShellWindowId_DefaultContainer);
+ // Workspace manager has its own layout managers.
+ workspace_controller_.reset(
+ new WorkspaceController(default_container));
+
+ aura::Window* always_on_top_container =
+ GetContainer(kShellWindowId_AlwaysOnTopContainer);
+ always_on_top_container->SetLayoutManager(
+ new BaseLayoutManager(
+ always_on_top_container->GetRootWindow()));
+ always_on_top_controller_.reset(new internal::AlwaysOnTopController);
+ always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
+
+ DCHECK(!shelf_.get());
+ aura::Window* shelf_container =
+ GetContainer(internal::kShellWindowId_ShelfContainer);
+ // TODO(harrym): Remove when status area is view.
+ aura::Window* status_container =
+ GetContainer(internal::kShellWindowId_StatusContainer);
+ shelf_.reset(new ShelfWidget(
+ shelf_container, status_container, workspace_controller()));
+
+ // Create Docked windows layout manager
+ aura::Window* docked_container = GetContainer(
+ internal::kShellWindowId_DockedContainer);
+ docked_layout_manager_ =
+ new internal::DockedWindowLayoutManager(docked_container);
+ docked_container_handler_.reset(
+ new ToplevelWindowEventHandler(docked_container));
+ docked_container->SetLayoutManager(docked_layout_manager_);
+
+ // Create Panel layout manager
+ aura::Window* panel_container = GetContainer(
+ internal::kShellWindowId_PanelContainer);
+ panel_layout_manager_ =
+ new internal::PanelLayoutManager(panel_container);
+ panel_container_handler_.reset(
+ new PanelWindowEventHandler(panel_container));
+ panel_container->SetLayoutManager(panel_layout_manager_);
+}
+
+void RootWindowController::InitTouchHuds() {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kAshTouchHud))
+ set_touch_hud_debug(new TouchHudDebug(root_window_.get()));
+ if (Shell::GetInstance()->is_touch_hud_projection_enabled())
+ EnableTouchHudProjection();
+}
+
+void RootWindowController::CreateSystemBackground(
+ bool is_first_run_after_boot) {
+ SkColor color = SK_ColorBLACK;
+#if defined(OS_CHROMEOS)
+ if (is_first_run_after_boot)
+ color = kChromeOsBootColor;
+#endif
+ system_background_.reset(
+ new SystemBackgroundController(root_window_.get(), color));
+
+#if defined(OS_CHROMEOS)
+ // Make a copy of the system's boot splash screen so we can composite it
+ // onscreen until the desktop background is ready.
+ if (is_first_run_after_boot &&
+ (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshCopyHostBackgroundAtBoot) ||
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshAnimateFromBootSplashScreen)))
+ boot_splash_screen_.reset(new BootSplashScreen(root_window_.get()));
+#endif
+}
+
void RootWindowController::CreateContainersInRootWindow(
aura::RootWindow* root_window) {
// These containers are just used by PowerButtonController to animate groups
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index 2c02b20..393dcb3 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -5,6 +5,8 @@
#ifndef ASH_ROOT_WINDOW_CONTROLLER_H_
#define ASH_ROOT_WINDOW_CONTROLLER_H_
+#include <map>
+
#include "ash/ash_export.h"
#include "ash/shelf/shelf_types.h"
#include "ash/system/user/login_status.h"
@@ -25,6 +27,8 @@
}
namespace views {
+class Widget;
+
namespace corewm {
class InputMethodEventFilter;
class RootWindowEventFilter;
@@ -43,7 +47,10 @@
namespace internal {
+class AlwaysOnTopController;
+class AnimatingDesktopController;
class BootSplashScreen;
+class DesktopBackgroundWidgetController;
class DockedWindowLayoutManager;
class PanelLayoutManager;
class RootWindowLayoutManager;
@@ -52,7 +59,8 @@
class StatusAreaWidget;
class SystemBackgroundController;
class SystemModalContainerLayoutManager;
-class TouchObserverHUD;
+class TouchHudDebug;
+class TouchHudProjection;
class WorkspaceController;
// This class maintains the per root window state for ash. This class
@@ -85,19 +93,50 @@
return workspace_controller_.get();
}
+ AlwaysOnTopController* always_on_top_controller() {
+ return always_on_top_controller_.get();
+ }
+
ScreenDimmer* screen_dimmer() { return screen_dimmer_.get(); }
// Access the shelf associated with this root window controller,
// NULL if no such shelf exists.
ShelfWidget* shelf() { return shelf_.get(); }
- TouchObserverHUD* touch_observer_hud() { return touch_observer_hud_; }
-
- // Sets the touch HUD. The RootWindowController will not own this HUD; its
- // lifetime is managed by itself.
- void set_touch_observer_hud(TouchObserverHUD* hud) {
- touch_observer_hud_ = hud;
+ // Get touch HUDs associated with this root window controller.
+ TouchHudDebug* touch_hud_debug() const {
+ return touch_hud_debug_;
}
+ TouchHudProjection* touch_hud_projection() const {
+ return touch_hud_projection_;
+ }
+
+ // Set touch HUDs for this root window controller. The root window controller
+ // will not own the HUDs; their lifetimes are managed by themselves. Whenever
+ // the widget showing a HUD is being destroyed (e.g. because of detaching a
+ // display), the HUD deletes itself.
+ void set_touch_hud_debug(TouchHudDebug* hud) {
+ touch_hud_debug_ = hud;
+ }
+ void set_touch_hud_projection(TouchHudProjection* hud) {
+ touch_hud_projection_ = hud;
+ }
+
+ // Enables projection touch HUD.
+ void EnableTouchHudProjection();
+
+ // Disables projection touch HUD.
+ void DisableTouchHudProjection();
+
+ DesktopBackgroundWidgetController* wallpaper_controller() {
+ return wallpaper_controller_.get();
+ }
+ void SetWallpaperController(DesktopBackgroundWidgetController* controller);
+ AnimatingDesktopController* animating_wallpaper_controller() {
+ return animating_wallpaper_controller_.get();
+ }
+ void SetAnimatingWallpaperController(AnimatingDesktopController* controller);
+
// Access the shelf layout manager associated with this root
// window controller, NULL if no such shelf exists.
ShelfLayoutManager* GetShelfLayoutManager();
@@ -124,16 +163,9 @@
aura::Window* GetContainer(int container_id);
- void InitLayoutManagers();
- void CreateContainers();
-
- // Initializs the RootWindowController for primary display. This
- // creates
- void InitForPrimaryDisplay();
-
- // Initializes |system_background_| and possibly also |boot_splash_screen_|.
- // |is_first_run_after_boot| determines the background's initial color.
- void CreateSystemBackground(bool is_first_run_after_boot);
+ // Initializes the RootWindowController. |first_run_after_boot| is
+ // set to true only for primary root window after boot.
+ void Init(bool first_run_after_boot);
// Show launcher view if it was created hidden (before session has started).
void ShowLauncher();
@@ -153,9 +185,11 @@
// hiding animation (if the screen is non-NULL).
void HandleInitialDesktopBackgroundAnimationStarted();
- // Called when the login background is fully visible. Updates |background_|
- // to be black and drops |boot_splash_screen_|.
- void HandleDesktopBackgroundVisible();
+ // Called when the wallpaper ainmation is finished. Updates |background_|
+ // to be black and drops |boot_splash_screen_| and moves the wallpaper
+ // controller into the root window controller. |widget| holds the wallpaper
+ // image, or NULL if the background is a solid color.
+ void OnWallpaperAnimationFinished(views::Widget* widget);
// Deletes associated objects and clears the state, but doesn't delete
// the root window yet. This is used to delete a secondary displays'
@@ -172,12 +206,21 @@
// Force the shelf to query for it's current visibility state.
void UpdateShelfVisibility();
+ // Initialize touch HUDs if necessary.
+ void InitTouchHuds();
+
// Returns the window, if any, which is in fullscreen mode in the active
// workspace. Exposed here so clients of Ash don't need to know the details
// of workspace management.
aura::Window* GetFullscreenWindow() const;
private:
+ void InitLayoutManagers();
+
+ // Initializes |system_background_| and possibly also |boot_splash_screen_|.
+ // |is_first_run_after_boot| determines the background's initial color.
+ void CreateSystemBackground(bool is_first_run_after_boot);
+
// Creates each of the special window containers that holds windows of various
// types in the shell UI.
void CreateContainersInRootWindow(aura::RootWindow* root_window);
@@ -206,10 +249,12 @@
scoped_ptr<ScreenDimmer> screen_dimmer_;
scoped_ptr<WorkspaceController> workspace_controller_;
+ scoped_ptr<AlwaysOnTopController> always_on_top_controller_;
- // Heads-up display for touch events. The RootWindowController does not own
- // this HUD; its lifetime is managed by itself.
- TouchObserverHUD* touch_observer_hud_;
+ // Heads-up displays for touch events. These HUDs are not owned by the root
+ // window controller and manage their own lifetimes.
+ TouchHudDebug* touch_hud_debug_;
+ TouchHudProjection* touch_hud_projection_;
// We need to own event handlers for various containers.
scoped_ptr<ToplevelWindowEventHandler> default_container_handler_;
@@ -219,6 +264,9 @@
scoped_ptr<ToplevelWindowEventHandler> panel_container_handler_;
scoped_ptr<ToplevelWindowEventHandler> docked_container_handler_;
+ scoped_ptr<DesktopBackgroundWidgetController> wallpaper_controller_;
+ scoped_ptr<AnimatingDesktopController> animating_wallpaper_controller_;
+
DISALLOW_COPY_AND_ASSIGN(RootWindowController);
};
diff --git a/ash/root_window_controller_unittest.cc b/ash/root_window_controller_unittest.cc
index 81a3e62..9896f95 100644
--- a/ash/root_window_controller_unittest.cc
+++ b/ash/root_window_controller_unittest.cc
@@ -4,7 +4,6 @@
#include "ash/root_window_controller.h"
-#include "ash/display/display_controller.h"
#include "ash/session_state_delegate.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h"
diff --git a/ash/rotator/screen_rotation.cc b/ash/rotator/screen_rotation.cc
index 2f0dc85..248394a 100644
--- a/ash/rotator/screen_rotation.cc
+++ b/ash/rotator/screen_rotation.cc
@@ -4,7 +4,7 @@
#include "ash/rotator/screen_rotation.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/interpolated_transform.h"
#include "ui/gfx/rect.h"
diff --git a/ash/screen_ash_unittest.cc b/ash/screen_ash_unittest.cc
index f5faf3b..2243742 100644
--- a/ash/screen_ash_unittest.cc
+++ b/ash/screen_ash_unittest.cc
@@ -4,7 +4,6 @@
#include "ash/screen_ash.h"
-#include "ash/display/display_controller.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_widget.h"
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index d592a8c..c53da27 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -581,7 +581,6 @@
state_.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN &&
state.visibility_state == SHELF_VISIBLE) ?
BackgroundAnimator::CHANGE_IMMEDIATE : BackgroundAnimator::CHANGE_ANIMATE;
- StopAnimating();
State old_state = state_;
state_ = state;
@@ -593,6 +592,8 @@
launcher_animation_setter.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS));
launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
+ launcher_animation_setter.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
GetLayer(shelf_)->SetBounds(
target_bounds.shelf_bounds_in_root);
GetLayer(shelf_)->SetOpacity(target_bounds.opacity);
@@ -601,6 +602,8 @@
status_animation_setter.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS));
status_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
+ status_animation_setter.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
// Delay updating the background when going from SHELF_AUTO_HIDE_SHOWN to
// SHELF_AUTO_HIDE_HIDDEN until the shelf animates out. Otherwise during the
@@ -632,7 +635,7 @@
status_bounds.set_y(status_bounds.y() +
target_bounds.shelf_bounds_in_root.y());
layer->SetBounds(status_bounds);
- layer->SetOpacity(target_bounds.opacity);
+ layer->SetOpacity(target_bounds.status_opacity);
Shell::GetInstance()->SetDisplayWorkAreaInsets(
root_window_, target_bounds.work_area_insets);
UpdateHitTestBounds();
@@ -738,6 +741,10 @@
(gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS ||
state.visibility_state == SHELF_VISIBLE ||
state.visibility_state == SHELF_AUTO_HIDE) ? 1.0f : 0.0f;
+ target_bounds->status_opacity =
+ (state.visibility_state == SHELF_AUTO_HIDE &&
+ state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) ?
+ 0.0f : target_bounds->opacity;
if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS)
UpdateTargetBoundsForGesture(target_bounds);
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h
index e731cf1..d49f42a 100644
--- a/ash/shelf/shelf_layout_manager.h
+++ b/ash/shelf/shelf_layout_manager.h
@@ -17,7 +17,7 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/observer_list.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/aura/client/activation_change_observer.h"
#include "ui/aura/layout_manager.h"
#include "ui/gfx/insets.h"
@@ -207,6 +207,7 @@
~TargetBounds();
float opacity;
+ float status_opacity;
gfx::Rect shelf_bounds_in_root;
gfx::Rect launcher_bounds_in_shelf;
gfx::Rect status_bounds_in_shelf;
@@ -237,7 +238,7 @@
// Sets the visibility of the shelf to |state|.
void SetState(ShelfVisibilityState visibility_state);
- // Stops any animations.
+ // Stops any animations and progresses them to the end.
void StopAnimating();
// Returns the width (if aligned to the side) or height (if aligned to the
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index a0db945..20b5be0 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -33,6 +33,7 @@
#include "ui/base/animation/animation_container_element.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/views/controls/label.h"
@@ -659,6 +660,33 @@
Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
}
+// Test that switching to a different visibility state does not restart the
+// shelf show / hide animation if it is already running. (crbug.com/250918)
+TEST_F(ShelfLayoutManagerTest, SetStateWhileAnimating) {
+ ShelfWidget* shelf = GetShelfWidget();
+ SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
+ gfx::Rect initial_shelf_bounds = shelf->GetWindowBoundsInScreen();
+ gfx::Rect initial_status_bounds =
+ shelf->status_area_widget()->GetWindowBoundsInScreen();
+
+ ui::ScopedAnimationDurationScaleMode normal_animation_duration(
+ ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
+ SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
+ SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
+
+ gfx::Rect current_shelf_bounds = shelf->GetWindowBoundsInScreen();
+ gfx::Rect current_status_bounds =
+ shelf->status_area_widget()->GetWindowBoundsInScreen();
+
+ const int small_change = initial_shelf_bounds.height() / 2;
+ EXPECT_LE(
+ std::abs(initial_shelf_bounds.height() - current_shelf_bounds.height()),
+ small_change);
+ EXPECT_LE(
+ std::abs(initial_status_bounds.height() - current_status_bounds.height()),
+ small_change);
+}
+
// Makes sure the launcher is sized when the status area changes size.
TEST_F(ShelfLayoutManagerTest, LauncherUpdatedWhenStatusAreaChangesSize) {
Launcher* launcher = Launcher::ForPrimaryDisplay();
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 9f95946..223d034 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -322,7 +322,7 @@
dimmer_.reset(new views::Widget);
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.can_activate = false;
params.accept_events = false;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
@@ -436,7 +436,7 @@
window_container_(shelf_container) {
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.parent = shelf_container;
params.delegate = delegate_view_;
@@ -489,6 +489,8 @@
void ShelfWidget::SetDimsShelf(bool dimming) {
delegate_view_->SetDimmed(dimming);
+ if (launcher_)
+ launcher_->GetAppListButtonView()->SchedulePaint();
}
bool ShelfWidget::GetDimsShelf() const {
@@ -516,7 +518,7 @@
launcher_->SetVisible(
shell->session_state_delegate()->IsActiveUserSessionStarted());
-
+ shelf_layout_manager_->LayoutShelf();
Show();
}
diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc
index 3379e29..f043f34 100644
--- a/ash/shelf/shelf_widget_unittest.cc
+++ b/ash/shelf/shelf_widget_unittest.cc
@@ -8,6 +8,7 @@
#include "ash/launcher/launcher_button.h"
#include "ash/launcher/launcher_model.h"
#include "ash/launcher/launcher_view.h"
+#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
@@ -23,6 +24,7 @@
namespace ash {
namespace {
+
ShelfWidget* GetShelfWidget() {
return Launcher::ForPrimaryDisplay()->shelf_widget();
}
@@ -154,4 +156,40 @@
widget->SetFullscreen(true);
}
+#if defined(OS_CHROMEOS)
+// Verifies launcher is created with correct size after user login and when its
+// container and status widget has finished sizing.
+// See http://crbug.com/252533
+TEST_F(ShelfWidgetTest, LauncherInitiallySizedAfterLogin) {
+ SetUserLoggedIn(false);
+ UpdateDisplay("300x200,400x300");
+
+ ShelfWidget* shelf = NULL;
+ Shell::RootWindowControllerList controllers(
+ Shell::GetAllRootWindowControllers());
+ for (Shell::RootWindowControllerList::const_iterator i = controllers.begin();
+ i != controllers.end();
+ ++i) {
+ if (!(*i)->shelf()->launcher()) {
+ shelf = (*i)->shelf();
+ break;
+ }
+ }
+ ASSERT_TRUE(shelf != NULL);
+
+ SetUserLoggedIn(true);
+ Shell::GetInstance()->CreateLauncher();
+
+ Launcher* launcher = shelf->launcher();
+ ASSERT_TRUE(launcher != NULL);
+
+ const int status_width =
+ shelf->status_area_widget()->GetWindowBoundsInScreen().width();
+ EXPECT_GT(status_width, 0);
+ EXPECT_EQ(status_width,
+ shelf->GetContentsView()->width() -
+ launcher->GetLauncherViewForTest()->width());
+}
+#endif
+
} // namespace ash
diff --git a/ash/shell.cc b/ash/shell.cc
index 84fe09f..1610ae3 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -39,7 +39,6 @@
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/wm/activation_controller.h"
-#include "ash/wm/always_on_top_controller.h"
#include "ash/wm/app_list_controller.h"
#include "ash/wm/ash_activation_controller.h"
#include "ash/wm/ash_focus_rules.h"
@@ -107,7 +106,8 @@
#include "ash/accelerators/nested_dispatcher_controller.h"
#endif
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
+#if defined(USE_X11)
#include "ash/ash_constants.h"
#include "ash/display/display_change_observer_x11.h"
#include "ash/display/display_error_dialog.h"
@@ -118,6 +118,8 @@
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_switches.h"
#include "gpu/config/gpu_feature_type.h"
+#endif // defined(USE_X11)
+#include "ash/system/chromeos/power/power_status.h"
#endif // defined(OS_CHROMEOS)
namespace ash {
@@ -208,7 +210,8 @@
cursor_manager_(scoped_ptr<views::corewm::NativeCursorManager>(
native_cursor_manager_)),
browser_context_(NULL),
- simulate_modal_window_open_for_testing_(false) {
+ simulate_modal_window_open_for_testing_(false),
+ is_touch_hud_projection_enabled_(false) {
DCHECK(delegate_.get());
display_manager_.reset(new internal::DisplayManager);
mirror_window_controller_.reset(new internal::MirrorWindowController);
@@ -233,6 +236,10 @@
output_configurator());
#endif // defined(OS_CHROMEOS)
AddPreTargetHandler(this);
+
+#if defined(OS_CHROMEOS)
+ internal::PowerStatus::Initialize();
+#endif
}
Shell::~Shell() {
@@ -325,6 +332,10 @@
display_change_observer_.reset();
#endif // defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS)
+ internal::PowerStatus::Shutdown();
+#endif
+
DCHECK(instance_ == this);
instance_ = NULL;
}
@@ -523,12 +534,6 @@
if (keyboard::IsKeyboardEnabled())
keyboard::InitializeKeyboard();
- internal::RootWindowController* root_window_controller =
- new internal::RootWindowController(root_window);
- root_window_controller->CreateContainers();
- root_window_controller->CreateSystemBackground(
- delegate_->IsFirstRunAfterBoot());
-
if (command_line->HasSwitch(ash::switches::kAshDisableNewLockAnimations))
lock_state_controller_.reset(new SessionStateControllerImpl);
else
@@ -566,8 +571,6 @@
event_client_.reset(new internal::EventClientImpl);
- InitRootWindowController(root_window_controller);
-
// This controller needs to be set before SetupManagedWindowMode.
desktop_background_controller_.reset(new DesktopBackgroundController());
user_wallpaper_delegate_.reset(delegate_->CreateUserWallpaperDelegate());
@@ -593,8 +596,10 @@
if (!system_tray_delegate_)
system_tray_delegate_.reset(SystemTrayDelegate::CreateDummyDelegate());
- // Creates StatusAreaWidget.
- root_window_controller->InitForPrimaryDisplay();
+ internal::RootWindowController* root_window_controller =
+ new internal::RootWindowController(root_window);
+ InitRootWindowController(root_window_controller,
+ delegate_->IsFirstRunAfterBoot());
// Initialize system_tray_delegate_ after StatusAreaWidget is created.
system_tray_delegate_->Initialize();
@@ -838,34 +843,47 @@
LauncherDelegate* Shell::GetLauncherDelegate() {
if (!launcher_delegate_) {
- if (!launcher_model_)
- launcher_model_.reset(new LauncherModel);
- // Attempt to create the Launcher. This may fail if the application is not
- // ready to create it yet, in which case the app is responsible for calling
- // ash::Shell::CreateLauncher() when ready.
+ launcher_model_.reset(new LauncherModel);
launcher_delegate_.reset(
delegate_->CreateLauncherDelegate(launcher_model_.get()));
}
return launcher_delegate_.get();
}
+void Shell::SetTouchHudProjectionEnabled(bool enabled) {
+ if (is_touch_hud_projection_enabled_ == enabled)
+ return;
+
+ RootWindowList roots = GetInstance()->GetAllRootWindows();
+ for (RootWindowList::iterator iter = roots.begin(); iter != roots.end();
+ ++iter) {
+ internal::RootWindowController* controller = GetRootWindowController(*iter);
+ if (enabled)
+ controller->EnableTouchHudProjection();
+ else
+ controller->DisableTouchHudProjection();
+ }
+ is_touch_hud_projection_enabled_ = enabled;
+}
+
void Shell::InitRootWindowForSecondaryDisplay(aura::RootWindow* root) {
- aura::client::SetFocusClient(root, focus_client_.get());
internal::RootWindowController* controller =
new internal::RootWindowController(root);
- controller->CreateContainers();
// Pass false for the |is_first_run_after_boot| parameter so we'll show a
// black background on this display instead of trying to mimic the boot splash
// screen.
- controller->CreateSystemBackground(false);
- InitRootWindowController(controller);
- controller->InitForPrimaryDisplay();
+ InitRootWindowController(controller, false);
+
controller->root_window_layout()->OnWindowResized();
desktop_background_controller_->OnRootWindowAdded(root);
high_contrast_controller_->OnRootWindowAdded(root);
root->ShowRootWindow();
// Activate new root for testing.
active_root_window_ = root;
+
+ // Create a launcher if a user is already logged.
+ if (Shell::GetInstance()->session_state_delegate()->NumberOfLoggedInUsers())
+ controller->shelf()->CreateLauncher();
}
void Shell::DoInitialWorkspaceAnimation() {
@@ -874,7 +892,9 @@
}
void Shell::InitRootWindowController(
- internal::RootWindowController* controller) {
+ internal::RootWindowController* controller,
+ bool first_run_after_boot) {
+
aura::RootWindow* root_window = controller->root_window();
DCHECK(activation_client_);
DCHECK(visibility_controller_.get());
@@ -906,21 +926,7 @@
if (user_action_client_)
aura::client::SetUserActionClient(root_window, user_action_client_.get());
- root_window->SetCursor(ui::kCursorPointer);
- controller->InitLayoutManagers();
-
- // TODO(oshima): Move the instance to RootWindowController when
- // the extended desktop is enabled by default.
- internal::AlwaysOnTopController* always_on_top_controller =
- new internal::AlwaysOnTopController;
- always_on_top_controller->SetAlwaysOnTopContainer(
- root_window->GetChildById(internal::kShellWindowId_AlwaysOnTopContainer));
- root_window->SetProperty(internal::kAlwaysOnTopControllerKey,
- always_on_top_controller);
- if (GetPrimaryRootWindowController()->GetSystemModalLayoutManager(NULL)->
- has_modal_background()) {
- controller->GetSystemModalLayoutManager(NULL)->CreateModalBackground();
- }
+ controller->Init(first_run_after_boot);
window_cycle_controller_->OnRootWindowAdded(root_window);
}
diff --git a/ash/shell.h b/ash/shell.h
index f8649dc..a602cdf 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -462,6 +462,12 @@
// Returns the launcher delegate, creating if necesary.
LauncherDelegate* GetLauncherDelegate();
+ void SetTouchHudProjectionEnabled(bool enabled);
+
+ bool is_touch_hud_projection_enabled() const {
+ return is_touch_hud_projection_enabled_;
+ }
+
private:
FRIEND_TEST_ALL_PREFIXES(ExtendedDesktopTest, TestCursor);
FRIEND_TEST_ALL_PREFIXES(WindowManagerTest, MouseEventCursors);
@@ -479,8 +485,10 @@
void Init();
// Initializes the root window and root window controller so that it
- // can host browser windows.
- void InitRootWindowController(internal::RootWindowController* root);
+ // can host browser windows. |first_run_after_boot| is true for the
+ // primary display only first time after boot.
+ void InitRootWindowController(internal::RootWindowController* root,
+ bool first_run_after_boot);
// ash::internal::SystemModalContainerEventFilterDelegate overrides:
virtual bool CanWindowReceiveEvents(aura::Window* window) OVERRIDE;
@@ -604,6 +612,8 @@
// For testing only: simulate that a modal window is open
bool simulate_modal_window_open_for_testing_;
+ bool is_touch_hud_projection_enabled_;
+
DISALLOW_COPY_AND_ASSIGN(Shell);
};
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc
index 1f6fc49..dd7adc5 100644
--- a/ash/shell/app_list.cc
+++ b/ash/shell/app_list.cc
@@ -9,6 +9,8 @@
#include "ash/shell/example_factory.h"
#include "ash/shell/toplevel_window.h"
#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
#include "base/i18n/case_conversion.h"
#include "base/i18n/string_search.h"
#include "base/strings/string_util.h"
@@ -231,6 +233,11 @@
return NULL;
}
+ virtual void GetShortcutPathForApp(
+ const std::string& app_id,
+ const base::Callback<void(const base::FilePath&)>& callback) OVERRIDE {
+ }
+
virtual void ActivateAppListItem(app_list::AppListItemModel* item,
int event_flags) OVERRIDE {
static_cast<WindowTypeLauncherItem*>(item)->Activate(event_flags);
diff --git a/ash/shell/content_client/shell_browser_main_parts.cc b/ash/shell/content_client/shell_browser_main_parts.cc
index 03a401c..08efd79 100644
--- a/ash/shell/content_client/shell_browser_main_parts.cc
+++ b/ash/shell/content_client/shell_browser_main_parts.cc
@@ -9,6 +9,7 @@
#include "ash/shell.h"
#include "ash/shell/shell_delegate_impl.h"
#include "ash/shell/window_watcher.h"
+#include "ash/system/user/login_status.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/i18n/icu_util.h"
@@ -18,7 +19,7 @@
#include "base/threading/thread_restrictions.h"
#include "content/public/common/content_switches.h"
#include "content/shell/shell_browser_context.h"
-#include "googleurl/src/gurl.h"
+#include "content/shell/shell_net_log.h"
#include "net/base/net_module.h"
#include "ui/aura/client/stacking_client.h"
#include "ui/aura/env.h"
@@ -39,7 +40,6 @@
#if defined(OS_CHROMEOS)
#include "chromeos/audio/cras_audio_handler.h"
#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/power/power_manager_handler.h"
#endif
namespace ash {
@@ -102,7 +102,9 @@
}
void ShellBrowserMainParts::PreMainMessageLoopRun() {
- browser_context_.reset(new content::ShellBrowserContext(false));
+ net_log_.reset(new content::ShellNetLog());
+ browser_context_.reset(new content::ShellBrowserContext(
+ false, net_log_.get()));
// A ViewsDelegate is required.
if (!views::ViewsDelegate::views_delegate)
@@ -119,11 +121,13 @@
// is absent.
chromeos::CrasAudioHandler::InitializeForTesting();
}
- chromeos::PowerManagerHandler::Initialize();
#endif
ash::Shell::CreateInstance(delegate_);
ash::Shell::GetInstance()->set_browser_context(browser_context_.get());
+ ash::Shell::GetInstance()->CreateLauncher();
+ ash::Shell::GetInstance()->UpdateAfterLoginStatusChange(
+ user::LOGGED_IN_USER);
window_watcher_.reset(new ash::shell::WindowWatcher);
gfx::Screen* screen = Shell::GetInstance()->GetScreen();
@@ -132,12 +136,8 @@
ash::shell::InitWindowTypeLauncher();
- DesktopBackgroundController* controller =
- Shell::GetInstance()->desktop_background_controller();
- if (controller->GetAppropriateResolution() == WALLPAPER_RESOLUTION_LARGE)
- controller->SetDefaultWallpaper(kDefaultLargeWallpaper);
- else
- controller->SetDefaultWallpaper(kDefaultSmallWallpaper);
+ Shell::GetInstance()->desktop_background_controller()->SetDefaultWallpaper(
+ false /* is_guest */);
ash::Shell::GetPrimaryRootWindow()->ShowRootWindow();
}
@@ -155,7 +155,6 @@
message_center::MessageCenter::Shutdown();
#if defined(OS_CHROMEOS)
- chromeos::PowerManagerHandler::Shutdown();
if (ash::switches::UseNewAudioHandler())
chromeos::CrasAudioHandler::Shutdown();
#endif
diff --git a/ash/shell/content_client/shell_browser_main_parts.h b/ash/shell/content_client/shell_browser_main_parts.h
index 8c51306..768ee5e 100644
--- a/ash/shell/content_client/shell_browser_main_parts.h
+++ b/ash/shell/content_client/shell_browser_main_parts.h
@@ -18,6 +18,10 @@
struct MainFunctionParams;
}
+namespace net {
+class NetLog;
+}
+
namespace ash {
namespace shell {
@@ -42,6 +46,7 @@
}
private:
+ scoped_ptr<net::NetLog> net_log_;
scoped_ptr<content::ShellBrowserContext> browser_context_;
scoped_ptr<ash::shell::WindowWatcher> window_watcher_;
ShellDelegateImpl* delegate_; // owned by Shell
diff --git a/ash/shell/shell_main_parts_mac.mm b/ash/shell/shell_main_parts_mac.mm
index d5c726e..292e1d5 100644
--- a/ash/shell/shell_main_parts_mac.mm
+++ b/ash/shell/shell_main_parts_mac.mm
@@ -8,7 +8,7 @@
#include "base/i18n/icu_util.h"
#include "base/mac/bundle_locations.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
@@ -20,9 +20,9 @@
icu_util::Initialize();
ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL);
- scoped_nsobject<NSNib>
- nib([[NSNib alloc] initWithNibNamed:@"MainMenu"
- bundle:base::mac::FrameworkBundle()]);
+ base::scoped_nsobject<NSNib> nib(
+ [[NSNib alloc] initWithNibNamed:@"MainMenu"
+ bundle:base::mac::FrameworkBundle()]);
[nib instantiateNibWithOwner:NSApp topLevelObjects:nil];
}
diff --git a/ash/shell/window_type_launcher.cc b/ash/shell/window_type_launcher.cc
index 4bfe453..5a260a5 100644
--- a/ash/shell/window_type_launcher.cc
+++ b/ash/shell/window_type_launcher.cc
@@ -17,7 +17,7 @@
#include "ash/system/web_notification/web_notification_tray.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
diff --git a/ash/shell/window_watcher_unittest.cc b/ash/shell/window_watcher_unittest.cc
index e35ba62..dfc7e6b 100644
--- a/ash/shell/window_watcher_unittest.cc
+++ b/ash/shell/window_watcher_unittest.cc
@@ -7,6 +7,7 @@
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/shell/shell_delegate_impl.h"
+#include "ash/system/user/login_status.h"
#include "ash/test/ash_test_base.h"
#include "ui/aura/root_window.h"
@@ -22,8 +23,11 @@
shell::ShellDelegateImpl* delegate = new ash::shell::ShellDelegateImpl;
Shell::CreateInstance(delegate);
-
Shell::GetPrimaryRootWindow()->ShowRootWindow();
+ Shell::GetInstance()->CreateLauncher();
+ Shell::GetInstance()->UpdateAfterLoginStatusChange(
+ user::LOGGED_IN_USER);
+
window_watcher.reset(new ash::shell::WindowWatcher);
delegate->SetWatcher(window_watcher.get());
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index 8660c2f..0e7fcb4 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -12,7 +12,7 @@
#include "ash/shell.h"
#include "base/callback.h"
#include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
namespace app_list {
class AppListViewDelegate;
diff --git a/ash/system/chromeos/audio/tray_audio.cc b/ash/system/chromeos/audio/tray_audio.cc
index 742a6e5..1360161 100644
--- a/ash/system/chromeos/audio/tray_audio.cc
+++ b/ash/system/chromeos/audio/tray_audio.cc
@@ -189,6 +189,7 @@
device_type_(NULL),
more_(NULL),
is_default_view_(is_default_view) {
+ set_focusable(false);
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
kTrayPopupPaddingHorizontal, 0, kTrayPopupPaddingBetweenItems));
@@ -444,7 +445,7 @@
false); /* no checkmark */
for (size_t i = 0; i < output_devices_.size(); ++i) {
HoverHighlightView* container = AddScrollListItem(
- output_devices_[i].display_name,
+ UTF8ToUTF16(output_devices_[i].display_name),
gfx::Font::NORMAL,
output_devices_[i].active); /* checkmark if active */
device_map_[container] = output_devices_[i];
@@ -459,7 +460,7 @@
false); /* no checkmark */
for (size_t i = 0; i < input_devices_.size(); ++i) {
HoverHighlightView* container = AddScrollListItem(
- input_devices_[i].display_name,
+ UTF8ToUTF16(input_devices_[i].display_name),
gfx::Font::NORMAL,
input_devices_[i].active); /* checkmark if active */
device_map_[container] = input_devices_[i];
@@ -586,10 +587,12 @@
if (tray_view())
tray_view()->SetVisible(GetInitialVisibility());
- if (volume_view_)
+ if (volume_view_) {
volume_view_->Update();
- else
+ SetDetailedViewCloseDelay(kTrayPopupAutoCloseDelayInSeconds);
+ } else {
PopupDetailedView(kTrayPopupAutoCloseDelayInSeconds, false);
+ }
}
@@ -613,9 +616,10 @@
if (tray_view())
tray_view()->SetVisible(GetInitialVisibility());
- if (volume_view_)
+ if (volume_view_) {
volume_view_->Update();
- else {
+ SetDetailedViewCloseDelay(kTrayPopupAutoCloseDelayInSeconds);
+ } else {
pop_up_volume_view_ = true;
PopupDetailedView(kTrayPopupAutoCloseDelayInSeconds, false);
}
diff --git a/ash/system/chromeos/label_tray_view.cc b/ash/system/chromeos/label_tray_view.cc
index 8398421..5af294e 100644
--- a/ash/system/chromeos/label_tray_view.cc
+++ b/ash/system/chromeos/label_tray_view.cc
@@ -50,13 +50,14 @@
child->set_border(
views::Border::CreateEmptyBorder(0, kTrayPopupPaddingHorizontal,
0, kTrayPopupPaddingHorizontal));
+ child->text_label()->SetMultiLine(true);
child->text_label()->SizeToFit(kTrayNotificationContentsWidth);
} else {
child->AddLabel(message, gfx::Font::NORMAL);
+ child->text_label()->SetMultiLine(true);
child->text_label()->SizeToFit(kTrayNotificationContentsWidth +
kNotificationIconWidth);
}
- child->text_label()->SetMultiLine(true);
child->text_label()->SetAllowCharacterBreak(true);
child->SetExpandable(true);
child->SetVisible(true);
diff --git a/ash/system/chromeos/managed/tray_locally_managed_user.cc b/ash/system/chromeos/managed/tray_locally_managed_user.cc
index 1803bea..61e422d 100644
--- a/ash/system/chromeos/managed/tray_locally_managed_user.cc
+++ b/ash/system/chromeos/managed/tray_locally_managed_user.cc
@@ -49,7 +49,8 @@
TrayLocallyManagedUser::TrayLocallyManagedUser(SystemTray* system_tray)
: SystemTrayItem(system_tray),
tray_view_(NULL),
- notification_view_(NULL) {
+ notification_view_(NULL),
+ status_(ash::user::LOGGED_IN_NONE) {
}
TrayLocallyManagedUser::~TrayLocallyManagedUser() {
@@ -98,8 +99,13 @@
void TrayLocallyManagedUser::UpdateAfterLoginStatusChange(
user::LoginStatus status) {
- if (status == ash::user::LOGGED_IN_LOCALLY_MANAGED)
+ if (status == status_)
+ return;
+ if (status == ash::user::LOGGED_IN_LOCALLY_MANAGED &&
+ status_ != ash::user::LOGGED_IN_LOCKED) {
ShowNotificationView();
+ }
+ status_ = status;
}
} // namespace internal
diff --git a/ash/system/chromeos/managed/tray_locally_managed_user.h b/ash/system/chromeos/managed/tray_locally_managed_user.h
index fb85c31..eda2be0 100644
--- a/ash/system/chromeos/managed/tray_locally_managed_user.h
+++ b/ash/system/chromeos/managed/tray_locally_managed_user.h
@@ -41,6 +41,8 @@
private:
LabelTrayView* tray_view_;
views::View* notification_view_;
+ // Previous login status to avoid showing notification upon unlock.
+ user::LoginStatus status_;
DISALLOW_COPY_AND_ASSIGN(TrayLocallyManagedUser);
};
diff --git a/ash/system/chromeos/network/network_state_list_detailed_view.cc b/ash/system/chromeos/network/network_state_list_detailed_view.cc
index 5d2e553..8063b1e 100644
--- a/ash/system/chromeos/network/network_state_list_detailed_view.cc
+++ b/ash/system/chromeos/network/network_state_list_detailed_view.cc
@@ -22,7 +22,7 @@
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_state.h"
diff --git a/ash/system/chromeos/network/network_state_notifier.h b/ash/system/chromeos/network/network_state_notifier.h
index 89d46c3..cfcc4b7 100644
--- a/ash/system/chromeos/network/network_state_notifier.h
+++ b/ash/system/chromeos/network/network_state_notifier.h
@@ -11,7 +11,7 @@
#include "ash/system/chromeos/network/network_tray_delegate.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "chromeos/network/network_state_handler_observer.h"
namespace chromeos {
diff --git a/ash/system/chromeos/network/network_state_notifier_unittest.cc b/ash/system/chromeos/network/network_state_notifier_unittest.cc
index 009274c..2f681bc 100644
--- a/ash/system/chromeos/network/network_state_notifier_unittest.cc
+++ b/ash/system/chromeos/network/network_state_notifier_unittest.cc
@@ -68,10 +68,11 @@
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
service_test->ClearServices();
const bool add_to_watchlist = true;
+ const bool add_to_visible = true;
// Create wifi and cellular networks and set to online.
service_test->AddService("wifi1", "wifi1",
flimflam::kTypeWifi, flimflam::kStateOnline,
- add_to_watchlist);
+ add_to_visible, add_to_watchlist);
RunAllPendingInMessageLoop();
}
diff --git a/ash/system/chromeos/network/tray_network.h b/ash/system/chromeos/network/tray_network.h
index 3ba88c4..332db1d 100644
--- a/ash/system/chromeos/network/tray_network.h
+++ b/ash/system/chromeos/network/tray_network.h
@@ -12,7 +12,7 @@
#include "ash/system/chromeos/network/tray_network_state_observer.h"
#include "ash/system/tray/system_tray_item.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
namespace chromeos {
class NetworkState;
diff --git a/ash/system/chromeos/power/power_status.cc b/ash/system/chromeos/power/power_status.cc
new file mode 100644
index 0000000..7982aa0
--- /dev/null
+++ b/ash/system/chromeos/power/power_status.cc
@@ -0,0 +1,267 @@
+// 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/system/chromeos/power/power_status.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include "ash/shell.h"
+#include "ash/shell_delegate.h"
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager_client.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/rect.h"
+
+namespace ash {
+namespace internal {
+
+namespace {
+
+// Updates |proto| to ensure that its fields are consistent.
+void SanitizeProto(power_manager::PowerSupplyProperties* proto) {
+ DCHECK(proto);
+
+ if (proto->battery_state() ==
+ power_manager::PowerSupplyProperties_BatteryState_FULL)
+ proto->set_battery_percent(100.0);
+
+ if (!proto->is_calculating_battery_time()) {
+ const bool on_line_power = proto->external_power() !=
+ power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
+ if ((on_line_power && proto->battery_time_to_full_sec() < 0) ||
+ (!on_line_power && proto->battery_time_to_empty_sec() < 0))
+ proto->set_is_calculating_battery_time(true);
+ }
+}
+
+base::string16 GetBatteryTimeAccessibilityString(int hour, int min) {
+ DCHECK(hour || min);
+ if (hour && !min) {
+ return Shell::GetInstance()->delegate()->GetTimeDurationLongString(
+ base::TimeDelta::FromHours(hour));
+ }
+ if (min && !hour) {
+ return Shell::GetInstance()->delegate()->GetTimeDurationLongString(
+ base::TimeDelta::FromMinutes(min));
+ }
+ return l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_BATTERY_TIME_ACCESSIBLE,
+ Shell::GetInstance()->delegate()->GetTimeDurationLongString(
+ base::TimeDelta::FromHours(hour)),
+ Shell::GetInstance()->delegate()->GetTimeDurationLongString(
+ base::TimeDelta::FromMinutes(min)));
+}
+
+static PowerStatus* g_power_status = NULL;
+
+// Minimum battery percentage rendered in UI.
+const int kMinBatteryPercent = 1;
+
+// Width and height of battery images.
+const int kBatteryImageHeight = 25;
+const int kBatteryImageWidth = 25;
+
+// Number of different power states.
+const int kNumPowerImages = 15;
+
+} // namespace
+
+// static
+void PowerStatus::Initialize() {
+ CHECK(!g_power_status);
+ g_power_status = new PowerStatus();
+}
+
+// static
+void PowerStatus::Shutdown() {
+ CHECK(g_power_status);
+ delete g_power_status;
+ g_power_status = NULL;
+}
+
+// static
+bool PowerStatus::IsInitialized() {
+ return g_power_status != NULL;
+}
+
+// static
+PowerStatus* PowerStatus::Get() {
+ CHECK(g_power_status) << "PowerStatus::Get() called before Initialize().";
+ return g_power_status;
+}
+
+void PowerStatus::AddObserver(Observer* observer) {
+ DCHECK(observer);
+ observers_.AddObserver(observer);
+}
+
+void PowerStatus::RemoveObserver(Observer* observer) {
+ DCHECK(observer);
+ observers_.RemoveObserver(observer);
+}
+
+void PowerStatus::RequestStatusUpdate() {
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
+ RequestStatusUpdate();
+}
+
+bool PowerStatus::IsBatteryPresent() const {
+ return proto_.battery_state() !=
+ power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT;
+}
+
+bool PowerStatus::IsBatteryFull() const {
+ return proto_.battery_state() ==
+ power_manager::PowerSupplyProperties_BatteryState_FULL;
+}
+
+double PowerStatus::GetBatteryPercent() const {
+ return proto_.battery_percent();
+}
+
+int PowerStatus::GetRoundedBatteryPercent() const {
+ return std::max(kMinBatteryPercent,
+ static_cast<int>(GetBatteryPercent() + 0.5));
+}
+
+bool PowerStatus::IsBatteryTimeBeingCalculated() const {
+ return proto_.is_calculating_battery_time();
+}
+
+base::TimeDelta PowerStatus::GetBatteryTimeToEmpty() const {
+ return base::TimeDelta::FromSeconds(proto_.battery_time_to_empty_sec());
+}
+
+base::TimeDelta PowerStatus::GetBatteryTimeToFull() const {
+ return base::TimeDelta::FromSeconds(proto_.battery_time_to_full_sec());
+}
+
+bool PowerStatus::IsLinePowerConnected() const {
+ return proto_.external_power() !=
+ power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
+}
+
+bool PowerStatus::IsMainsChargerConnected() const {
+ return proto_.external_power() ==
+ power_manager::PowerSupplyProperties_ExternalPower_AC;
+}
+
+bool PowerStatus::IsUsbChargerConnected() const {
+ return proto_.external_power() ==
+ power_manager::PowerSupplyProperties_ExternalPower_USB;
+}
+
+gfx::ImageSkia PowerStatus::GetBatteryImage(IconSet icon_set) const {
+ gfx::Image all;
+ if (IsUsbChargerConnected()) {
+ all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+ icon_set == ICON_DARK ?
+ IDR_AURA_UBER_TRAY_POWER_SMALL_CHARGING_UNRELIABLE_DARK :
+ IDR_AURA_UBER_TRAY_POWER_SMALL_CHARGING_UNRELIABLE);
+ } else {
+ all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+ icon_set == ICON_DARK ?
+ IDR_AURA_UBER_TRAY_POWER_SMALL_DARK : IDR_AURA_UBER_TRAY_POWER_SMALL);
+ }
+
+ // Get the horizontal offset in the battery icon array image.
+ int offset = (IsUsbChargerConnected() || !IsLinePowerConnected()) ? 0 : 1;
+
+ // Get the icon index in the battery icon array image.
+ int index = -1;
+ if (GetBatteryPercent() >= 100.0) {
+ index = kNumPowerImages - 1;
+ } else if (!IsBatteryPresent()) {
+ index = kNumPowerImages;
+ } else {
+ index = static_cast<int>(
+ GetBatteryPercent() / 100.0 * (kNumPowerImages - 1));
+ index = std::max(std::min(index, kNumPowerImages - 2), 0);
+ }
+
+ gfx::Rect region(
+ offset * kBatteryImageWidth, index * kBatteryImageHeight,
+ kBatteryImageWidth, kBatteryImageHeight);
+ return gfx::ImageSkiaOperations::ExtractSubset(*all.ToImageSkia(), region);
+}
+
+base::string16 PowerStatus::GetAccessibleNameString() const {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ if (IsLinePowerConnected() && IsBatteryFull()) {
+ return rb.GetLocalizedString(
+ IDS_ASH_STATUS_TRAY_BATTERY_FULL_CHARGE_ACCESSIBLE);
+ }
+ base::string16 battery_percentage_accessible = l10n_util::GetStringFUTF16(
+ IsLinePowerConnected() ?
+ IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ACCESSIBLE :
+ IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ACCESSIBLE,
+ base::IntToString16(GetRoundedBatteryPercent()));
+ base::string16 battery_time_accessible = base::string16();
+ if (IsUsbChargerConnected()) {
+ battery_time_accessible = rb.GetLocalizedString(
+ IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE_ACCESSIBLE);
+ } else {
+ if (IsBatteryTimeBeingCalculated()) {
+ battery_time_accessible = rb.GetLocalizedString(
+ IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING_ACCESSIBLE);
+ } else {
+ base::TimeDelta time = IsLinePowerConnected() ? GetBatteryTimeToFull() :
+ GetBatteryTimeToEmpty();
+ int hour = time.InHours();
+ int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
+ if (hour || min) {
+ base::string16 minute = min < 10 ?
+ ASCIIToUTF16("0") + base::IntToString16(min) :
+ base::IntToString16(min);
+ battery_time_accessible =
+ l10n_util::GetStringFUTF16(
+ IsLinePowerConnected() ?
+ IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_ACCESSIBLE :
+ IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_ACCESSIBLE,
+ GetBatteryTimeAccessibilityString(hour, min));
+ }
+ }
+ }
+ return battery_time_accessible.empty() ?
+ battery_percentage_accessible :
+ battery_percentage_accessible + ASCIIToUTF16(". ") +
+ battery_time_accessible;
+}
+
+PowerStatus::PowerStatus() {
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
+ AddObserver(this);
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
+ RequestStatusUpdate();
+}
+
+PowerStatus::~PowerStatus() {
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
+ RemoveObserver(this);
+}
+
+void PowerStatus::SetProtoForTesting(
+ const power_manager::PowerSupplyProperties& proto) {
+ proto_ = proto;
+ SanitizeProto(&proto_);
+}
+
+void PowerStatus::PowerChanged(
+ const power_manager::PowerSupplyProperties& proto) {
+ proto_ = proto;
+ SanitizeProto(&proto_);
+ FOR_EACH_OBSERVER(Observer, observers_, OnPowerStatusChanged());
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/system/chromeos/power/power_status.h b/ash/system/chromeos/power/power_status.h
new file mode 100644
index 0000000..4eba247
--- /dev/null
+++ b/ash/system/chromeos/power/power_status.h
@@ -0,0 +1,126 @@
+// 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_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_
+#define ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_
+
+#include "ash/ash_export.h"
+#include "base/basictypes.h"
+#include "base/observer_list.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
+#include "chromeos/dbus/power_manager_client.h"
+#include "ui/gfx/image/image_skia.h"
+
+namespace ash {
+namespace internal {
+
+// PowerStatus is a singleton that receives updates about the system's
+// power status from chromeos::PowerManagerClient and makes the information
+// available to interested classes within Ash.
+class ASH_EXPORT PowerStatus : public chromeos::PowerManagerClient::Observer {
+ public:
+ // Different styles of battery icons.
+ enum IconSet {
+ ICON_LIGHT,
+ ICON_DARK
+ };
+
+ // Interface for classes that wish to be notified when the power status
+ // has changed.
+ class Observer {
+ public:
+ // Called when the power status changes.
+ virtual void OnPowerStatusChanged() = 0;
+
+ protected:
+ virtual ~Observer() {}
+ };
+
+ virtual ~PowerStatus();
+
+ // Sets the global instance. Must be called before any calls to Get().
+ static void Initialize();
+
+ // Destroys the global instance.
+ static void Shutdown();
+
+ // Returns true if the global instance is initialized.
+ static bool IsInitialized();
+
+ // Gets the global instance. Initialize must be called first.
+ static PowerStatus* Get();
+
+ // Adds or removes an observer.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ // Requests updated status from the power manager.
+ void RequestStatusUpdate();
+
+ // Returns true if a battery is present.
+ bool IsBatteryPresent() const;
+
+ // Returns true if the battery is full.
+ bool IsBatteryFull() const;
+
+ // Returns the battery's remaining charge as a value in the range [0.0,
+ // 100.0].
+ double GetBatteryPercent() const;
+
+ // Returns the battery's remaining charge, rounded to an integer with a
+ // maximum value of 100.
+ int GetRoundedBatteryPercent() const;
+
+ // Returns true if the battery's time-to-full and time-to-empty estimates
+ // should not be displayed because the power manager is still calculating
+ // them.
+ bool IsBatteryTimeBeingCalculated() const;
+
+ // Returns the estimated time until the battery is empty (if line power
+ // is disconnected) or full (if line power is connected). These estimates
+ // should only be used if IsBatteryTimeBeingCalculated() returns false.
+ base::TimeDelta GetBatteryTimeToEmpty() const;
+ base::TimeDelta GetBatteryTimeToFull() const;
+
+ // Returns true if line power (including a charger of any type) is connected.
+ bool IsLinePowerConnected() const;
+
+ // Returns true if an official, non-USB charger is connected.
+ bool IsMainsChargerConnected() const;
+
+ // Returns true if a USB charger (which is likely to only support a low
+ // charging rate) is connected.
+ bool IsUsbChargerConnected() const;
+
+ // Returns the image that should be shown for the battery's current state.
+ gfx::ImageSkia GetBatteryImage(IconSet icon_set) const;
+
+ // Returns an string describing the current state for accessibility.
+ base::string16 GetAccessibleNameString() const;
+
+ // Updates |proto_|. Does not notify observers.
+ void SetProtoForTesting(const power_manager::PowerSupplyProperties& proto);
+
+ protected:
+ PowerStatus();
+
+ private:
+ // Overriden from PowerManagerClient::Observer.
+ virtual void PowerChanged(
+ const power_manager::PowerSupplyProperties& proto) OVERRIDE;
+
+ ObserverList<Observer> observers_;
+
+ // Current state.
+ power_manager::PowerSupplyProperties proto_;
+
+ DISALLOW_COPY_AND_ASSIGN(PowerStatus);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_
diff --git a/ash/system/chromeos/power/power_status_unittest.cc b/ash/system/chromeos/power/power_status_unittest.cc
new file mode 100644
index 0000000..831dd3d
--- /dev/null
+++ b/ash/system/chromeos/power/power_status_unittest.cc
@@ -0,0 +1,86 @@
+// 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/system/chromeos/power/power_status.h"
+
+#include <set>
+#include <string>
+
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace ash {
+namespace internal {
+
+namespace {
+
+class TestObserver : public PowerStatus::Observer {
+ public:
+ TestObserver() : power_changed_count_(0) {}
+ virtual ~TestObserver() {}
+
+ int power_changed_count() const { return power_changed_count_; }
+
+ // PowerStatus::Observer overrides:
+ virtual void OnPowerStatusChanged() OVERRIDE { ++power_changed_count_; }
+
+ private:
+ int power_changed_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestObserver);
+};
+
+} // namespace
+
+class PowerStatusTest : public testing::Test {
+ public:
+ PowerStatusTest() : power_status_(NULL) {}
+ virtual ~PowerStatusTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ chromeos::DBusThreadManager::InitializeWithStub();
+ PowerStatus::Initialize();
+ power_status_ = PowerStatus::Get();
+ test_observer_.reset(new TestObserver);
+ power_status_->AddObserver(test_observer_.get());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ power_status_->RemoveObserver(test_observer_.get());
+ test_observer_.reset();
+ PowerStatus::Shutdown();
+ chromeos::DBusThreadManager::Shutdown();
+ }
+
+ protected:
+ base::MessageLoopForUI message_loop_;
+ PowerStatus* power_status_; // Not owned.
+ scoped_ptr<TestObserver> test_observer_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PowerStatusTest);
+};
+
+TEST_F(PowerStatusTest, PowerStatusInitializeAndUpdate) {
+ // Test that the initial power supply state should be acquired after
+ // PowerStatus is instantiated. This depends on
+ // PowerManagerClientStubImpl, which responds to power status update
+ // requests, pretends there is a battery present, and generates some valid
+ // power supply status data.
+ message_loop_.RunUntilIdle();
+ EXPECT_EQ(1, test_observer_->power_changed_count());
+
+ // Test RequestUpdate, test_obsever_ should be notified for power suuply
+ // status change.
+ power_status_->RequestStatusUpdate();
+ message_loop_.RunUntilIdle();
+ EXPECT_EQ(2, test_observer_->power_changed_count());
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/system/chromeos/power/power_status_view.cc b/ash/system/chromeos/power/power_status_view.cc
index 4267010..4c88784 100644
--- a/ash/system/chromeos/power/power_status_view.cc
+++ b/ash/system/chromeos/power/power_status_view.cc
@@ -6,6 +6,7 @@
#include "ash/shell.h"
#include "ash/shell_delegate.h"
+#include "ash/system/chromeos/power/power_status.h"
#include "ash/system/chromeos/power/tray_power.h"
#include "ash/system/tray/fixed_sized_image_view.h"
#include "ash/system/tray/tray_constants.h"
@@ -30,8 +31,6 @@
const int kLabelMinWidth = 120;
// Padding between battery status text and battery icon on default view.
const int kPaddingBetweenBatteryStatusAndIcon = 3;
-// Minimum battery percentage rendered in UI.
-const int kMinBatteryPercent = 1;
} // namespace
PowerStatusView::PowerStatusView(ViewType view_type,
@@ -42,10 +41,8 @@
time_status_label_(NULL),
percentage_label_(NULL),
icon_(NULL),
- icon_image_index_(-1),
- icon_image_offset_(0),
- battery_charging_unreliable_(false),
view_type_(view_type) {
+ PowerStatus::Get()->AddObserver(this);
if (view_type == VIEW_DEFAULT) {
time_status_label_ = new views::Label;
percentage_label_ = new views::Label;
@@ -56,17 +53,22 @@
time_label_ = new views::Label;
LayoutNotificationView();
}
- Update();
+ OnPowerStatusChanged();
}
-void PowerStatusView::UpdatePowerStatus(
- const chromeos::PowerSupplyStatus& status) {
- supply_status_ = status;
- // Sanitize.
- if (supply_status_.battery_is_full)
- supply_status_.battery_percentage = 100.0;
+PowerStatusView::~PowerStatusView() {
+ PowerStatus::Get()->RemoveObserver(this);
+}
- Update();
+void PowerStatusView::OnPowerStatusChanged() {
+ view_type_ == VIEW_DEFAULT ?
+ UpdateTextForDefaultView() : UpdateTextForNotificationView();
+
+ if (icon_) {
+ icon_->SetImage(
+ PowerStatus::Get()->GetBatteryImage(PowerStatus::ICON_DARK));
+ icon_->SetVisible(true);
+ }
}
void PowerStatusView::LayoutDefaultView() {
@@ -107,43 +109,29 @@
AddChildView(time_label_);
}
-void PowerStatusView::UpdateText() {
- view_type_ == VIEW_DEFAULT ?
- UpdateTextForDefaultView() : UpdateTextForNotificationView();
- accessible_name_ = TrayPower::GetAccessibleNameString(supply_status_);
-}
-
void PowerStatusView::UpdateTextForDefaultView() {
+ const PowerStatus& status = *PowerStatus::Get();
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
base::string16 battery_percentage;
base::string16 battery_time_status;
- bool is_charging_unreliable =
- TrayPower::IsBatteryChargingUnreliable(supply_status_);
- if (supply_status_.line_power_on && supply_status_.battery_is_full) {
+
+ if (status.IsLinePowerConnected() && status.IsBatteryFull()) {
battery_time_status =
rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_FULL);
- } else if (supply_status_.battery_percentage < 0.0f) {
- battery_time_status =
- is_charging_unreliable ?
- rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE) :
- rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING);
} else {
battery_percentage = l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ONLY,
- base::IntToString16(TrayPower::GetRoundedBatteryPercentage(
- supply_status_.battery_percentage)));
- if (is_charging_unreliable) {
+ base::IntToString16(status.GetRoundedBatteryPercent()));
+ if (status.IsUsbChargerConnected()) {
battery_time_status = rb.GetLocalizedString(
IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE);
} else {
- if (supply_status_.is_calculating_battery_time) {
+ if (status.IsBatteryTimeBeingCalculated()) {
battery_time_status =
rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING);
} else {
- base::TimeDelta time = base::TimeDelta::FromSeconds(
- supply_status_.line_power_on ?
- supply_status_.battery_seconds_to_full :
- supply_status_.battery_seconds_to_empty);
+ base::TimeDelta time = status.IsLinePowerConnected() ?
+ status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty();
int hour = time.InHours();
int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
if (hour || min) {
@@ -152,7 +140,7 @@
base::IntToString16(min);
battery_time_status =
l10n_util::GetStringFUTF16(
- supply_status_.line_power_on ?
+ status.IsLinePowerConnected() ?
IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_SHORT :
IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_SHORT,
base::IntToString16(hour),
@@ -170,60 +158,44 @@
}
void PowerStatusView::UpdateTextForNotificationView() {
- int hour = 0;
- int min = 0;
- if (!supply_status_.is_calculating_battery_time) {
- base::TimeDelta time = base::TimeDelta::FromSeconds(
- supply_status_.line_power_on ?
- supply_status_.battery_seconds_to_full :
- supply_status_.battery_seconds_to_empty);
- hour = time.InHours();
- min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
- }
- bool is_charging_unreliable =
- TrayPower::IsBatteryChargingUnreliable(supply_status_);
- if (supply_status_.line_power_on && supply_status_.battery_is_full) {
+ const PowerStatus& status = *PowerStatus::Get();
+ if (status.IsLinePowerConnected() && status.IsBatteryFull()) {
status_label_->SetText(
ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
IDS_ASH_STATUS_TRAY_BATTERY_FULL));
} else {
- if (supply_status_.battery_percentage < 0.0f) {
- // If charging is unreliable and no percentage available, we
- // leave the top field, |staus_label|, blank. We do not want to
- // show "Calculating". The user is informed in the bottom field,
- // |time_label|, that "Charging not reliable".
- status_label_->SetText(
- is_charging_unreliable ?
- base::string16() :
- ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
- IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING));
- } else {
- status_label_->SetText(
- l10n_util::GetStringFUTF16(
- IDS_ASH_STATUS_TRAY_BATTERY_PERCENT,
- base::IntToString16(TrayPower::GetRoundedBatteryPercentage(
- supply_status_.battery_percentage))));
- }
+ status_label_->SetText(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_BATTERY_PERCENT,
+ base::IntToString16(status.GetRoundedBatteryPercent())));
}
- if (is_charging_unreliable) {
+ int hour = 0;
+ int min = 0;
+ if (!status.IsBatteryTimeBeingCalculated()) {
+ base::TimeDelta time = status.IsLinePowerConnected() ?
+ status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty();
+ hour = time.InHours();
+ min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
+ }
+
+ if (status.IsUsbChargerConnected()) {
time_label_->SetText(
ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE));
- } else if (supply_status_.is_calculating_battery_time) {
+ } else if (status.IsBatteryTimeBeingCalculated()) {
time_label_->SetText(
ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING));
} else if (hour || min) {
- if (supply_status_.line_power_on) {
+ if (status.IsLinePowerConnected()) {
time_label_->SetText(
l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL,
base::IntToString16(hour),
base::IntToString16(min)));
} else {
- // This is a low battery warning, which prompts user when battery
- // time left is not much (ie in minutes).
+ // This is a low battery warning prompting the user in minutes.
min = hour * 60 + min;
ShellDelegate* delegate = Shell::GetInstance()->delegate();
if (delegate) {
@@ -238,54 +210,6 @@
}
}
-base::string16 PowerStatusView::GetBatteryTimeAccessibilityString(
- int hour, int min) {
- DCHECK(hour || min);
- if (hour && !min) {
- return Shell::GetInstance()->delegate()->GetTimeDurationLongString(
- base::TimeDelta::FromHours(hour));
- } else if (min && !hour) {
- return Shell::GetInstance()->delegate()->GetTimeDurationLongString(
- base::TimeDelta::FromMinutes(min));
- } else {
- return l10n_util::GetStringFUTF16(
- IDS_ASH_STATUS_TRAY_BATTERY_TIME_ACCESSIBLE,
- Shell::GetInstance()->delegate()->GetTimeDurationLongString(
- base::TimeDelta::FromHours(hour)),
- Shell::GetInstance()->delegate()->GetTimeDurationLongString(
- base::TimeDelta::FromMinutes(min)));
- }
-}
-
-void PowerStatusView::UpdateIcon() {
- if (icon_) {
- int index = TrayPower::GetBatteryImageIndex(supply_status_);
- int offset = TrayPower::GetBatteryImageOffset(supply_status_);
- bool charging_unreliable =
- TrayPower::IsBatteryChargingUnreliable(supply_status_);
- if (icon_image_index_ != index ||
- icon_image_offset_ != offset ||
- battery_charging_unreliable_ != charging_unreliable) {
- icon_image_index_ = index;
- icon_image_offset_ = offset;
- battery_charging_unreliable_ = charging_unreliable;
- if (icon_image_index_ != -1) {
- icon_->SetImage(
- TrayPower::GetBatteryImage(icon_image_index_,
- icon_image_offset_,
- battery_charging_unreliable_,
- ICON_DARK));
- }
- }
- icon_->SetVisible(true);
- }
-}
-
-void PowerStatusView::Update() {
- UpdateText();
- UpdateIcon();
-}
-
void PowerStatusView::ChildPreferredSizeChanged(views::View* child) {
PreferredSizeChanged();
}
diff --git a/ash/system/chromeos/power/power_status_view.h b/ash/system/chromeos/power/power_status_view.h
index 421ce40..465da02 100644
--- a/ash/system/chromeos/power/power_status_view.h
+++ b/ash/system/chromeos/power/power_status_view.h
@@ -5,7 +5,7 @@
#ifndef ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_VIEW_H_
#define ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_VIEW_H_
-#include "chromeos/dbus/power_supply_status.h"
+#include "ash/system/chromeos/power/power_status.h"
#include "ui/views/view.h"
namespace views {
@@ -16,7 +16,7 @@
namespace ash {
namespace internal {
-class PowerStatusView : public views::View {
+class PowerStatusView : public views::View, public PowerStatus::Observer {
public:
enum ViewType {
VIEW_DEFAULT,
@@ -24,25 +24,21 @@
};
PowerStatusView(ViewType view_type, bool default_view_right_align);
- virtual ~PowerStatusView() {}
-
- void UpdatePowerStatus(const chromeos::PowerSupplyStatus& status);
- const base::string16& accessible_name() const { return accessible_name_; }
+ virtual ~PowerStatusView();
// Overridden from views::View.
virtual gfx::Size GetPreferredSize() OVERRIDE;
virtual int GetHeightForWidth(int width) OVERRIDE;
virtual void Layout() OVERRIDE;
+ // Overridden from PowerStatus::Observer.
+ virtual void OnPowerStatusChanged() OVERRIDE;
+
private:
void LayoutDefaultView();
void LayoutNotificationView();
- void UpdateText();
- void UpdateIcon();
- void Update();
void UpdateTextForDefaultView();
void UpdateTextForNotificationView();
- base::string16 GetBatteryTimeAccessibilityString(int hour, int min);
// Overridden from views::View.
virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE;
@@ -62,24 +58,8 @@
// Battery status indicator icon.
views::ImageView* icon_;
- // Index of the current icon in the icon array image, or -1 if unknown.
- int icon_image_index_;
-
- // Horizontal offset of the current icon in the icon array image.
- int icon_image_offset_;
-
- // Battery charging may be unreliable for non-standard power supplies.
- // It may change from charging to discharging frequently depending on
- // charger power and current power consumption. We show different UIs
- // when in this state. See TrayPower::IsBatteryChargingUnreliable.
- bool battery_charging_unreliable_;
-
ViewType view_type_;
- chromeos::PowerSupplyStatus supply_status_;
-
- base::string16 accessible_name_;
-
DISALLOW_COPY_AND_ASSIGN(PowerStatusView);
};
diff --git a/ash/system/chromeos/power/tray_power.cc b/ash/system/chromeos/power/tray_power.cc
index 9dc87cc..4fe4e68 100644
--- a/ash/system/chromeos/power/tray_power.cc
+++ b/ash/system/chromeos/power/tray_power.cc
@@ -5,30 +5,20 @@
#include "ash/system/chromeos/power/tray_power.h"
#include "ash/ash_switches.h"
-#include "ash/shell.h"
-#include "ash/shell_delegate.h"
#include "ash/system/chromeos/power/power_status_view.h"
#include "ash/system/date/date_view.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_notification_view.h"
#include "ash/system/tray/tray_utils.h"
#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chromeos/dbus/power_supply_status.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "third_party/icu/public/i18n/unicode/fieldpos.h"
#include "third_party/icu/public/i18n/unicode/fmtable.h"
-#include "third_party/skia/include/core/SkRect.h"
#include "ui/base/accessibility/accessible_view_state.h"
-#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/gfx/size.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
@@ -38,18 +28,13 @@
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
-using chromeos::PowerManagerHandler;
-using chromeos::PowerSupplyStatus;
+using message_center::MessageCenter;
+using message_center::Notification;
namespace ash {
namespace internal {
namespace {
-// Width and height of battery images.
-const int kBatteryImageHeight = 25;
-const int kBatteryImageWidth = 25;
-// Number of different power states.
-const int kNumPowerImages = 15;
// Top/bottom padding of the text items.
const int kPaddingVertical = 10;
// Specify min width of status label for layout.
@@ -58,31 +43,11 @@
const int kCriticalSeconds = 5 * 60;
const int kLowPowerSeconds = 15 * 60;
const int kNoWarningSeconds = 30 * 60;
-// Minimum battery percentage rendered in UI.
-const int kMinBatteryPercent = 1;
// Notification in battery percentage.
const double kCriticalPercentage = 5.0;
const double kLowPowerPercentage = 10.0;
const double kNoWarningPercentage = 15.0;
-base::string16 GetBatteryTimeAccessibilityString(int hour, int min) {
- DCHECK(hour || min);
- if (hour && !min) {
- return Shell::GetInstance()->delegate()->GetTimeDurationLongString(
- base::TimeDelta::FromHours(hour));
- }
- if (min && !hour) {
- return Shell::GetInstance()->delegate()->GetTimeDurationLongString(
- base::TimeDelta::FromMinutes(min));
- }
- return l10n_util::GetStringFUTF16(
- IDS_ASH_STATUS_TRAY_BATTERY_TIME_ACCESSIBLE,
- Shell::GetInstance()->delegate()->GetTimeDurationLongString(
- base::TimeDelta::FromHours(hour)),
- Shell::GetInstance()->delegate()->GetTimeDurationLongString(
- base::TimeDelta::FromMinutes(min)));
-}
-
} // namespace
namespace tray {
@@ -90,10 +55,7 @@
// This view is used only for the tray.
class PowerTrayView : public views::ImageView {
public:
- PowerTrayView()
- : battery_icon_index_(-1),
- battery_icon_offset_(0),
- battery_charging_unreliable_(false) {
+ PowerTrayView() {
UpdateImage();
}
@@ -106,94 +68,42 @@
state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
}
- void UpdatePowerStatus(const PowerSupplyStatus& status,
- bool battery_alert) {
- supply_status_ = status;
- // Sanitize.
- if (supply_status_.battery_is_full)
- supply_status_.battery_percentage = 100.0;
-
+ void UpdateStatus(bool battery_alert) {
UpdateImage();
- SetVisible(status.battery_is_present);
+ SetVisible(PowerStatus::Get()->IsBatteryPresent());
if (battery_alert) {
- accessible_name_ = TrayPower::GetAccessibleNameString(status);
+ accessible_name_ = PowerStatus::Get()->GetAccessibleNameString();
NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_ALERT, true);
}
}
private:
void UpdateImage() {
- int index = TrayPower::GetBatteryImageIndex(supply_status_);
- int offset = TrayPower::GetBatteryImageOffset(supply_status_);
- bool charging_unreliable =
- TrayPower::IsBatteryChargingUnreliable(supply_status_);
- if (battery_icon_index_ != index ||
- battery_icon_offset_ != offset ||
- battery_charging_unreliable_ != charging_unreliable) {
- battery_icon_index_ = index;
- battery_icon_offset_ = offset;
- battery_charging_unreliable_ = charging_unreliable;
- if (battery_icon_index_ != -1)
- SetImage(TrayPower::GetBatteryImage(battery_icon_index_,
- battery_icon_offset_,
- battery_charging_unreliable_,
- ICON_LIGHT));
- }
+ SetImage(PowerStatus::Get()->GetBatteryImage(PowerStatus::ICON_LIGHT));
}
- PowerSupplyStatus supply_status_;
base::string16 accessible_name_;
- // Index of the current icon in the icon array image, or -1 if unknown.
- int battery_icon_index_;
- int battery_icon_offset_;
- bool battery_charging_unreliable_;
-
DISALLOW_COPY_AND_ASSIGN(PowerTrayView);
};
class PowerNotificationView : public TrayNotificationView {
public:
explicit PowerNotificationView(TrayPower* owner)
- : TrayNotificationView(owner, 0),
- battery_icon_index_(-1),
- battery_icon_offset_(0),
- battery_charging_unreliable_(false) {
+ : TrayNotificationView(owner, 0) {
power_status_view_ =
new PowerStatusView(PowerStatusView::VIEW_NOTIFICATION, true);
InitView(power_status_view_);
}
- void UpdatePowerStatus(const PowerSupplyStatus& status) {
- int index = TrayPower::GetBatteryImageIndex(status);
- int offset = TrayPower::GetBatteryImageOffset(status);
- bool charging_unreliable = TrayPower::IsBatteryChargingUnreliable(status);
- if (battery_icon_index_ != index ||
- battery_icon_offset_ != offset ||
- battery_charging_unreliable_ != charging_unreliable) {
- battery_icon_index_ = index;
- battery_icon_offset_ = offset;
- battery_charging_unreliable_ = charging_unreliable;
- if (battery_icon_index_ != -1) {
- SetIconImage(TrayPower::GetBatteryImage(
- battery_icon_index_,
- battery_icon_offset_,
- battery_charging_unreliable_,
- ICON_DARK));
- }
- }
- power_status_view_->UpdatePowerStatus(status);
+ void UpdateStatus() {
+ SetIconImage(PowerStatus::Get()->GetBatteryImage(PowerStatus::ICON_DARK));
}
private:
PowerStatusView* power_status_view_;
- // Index of the current icon in the icon array image, or -1 if unknown.
- int battery_icon_index_;
- int battery_icon_offset_;
- bool battery_charging_unreliable_;
-
DISALLOW_COPY_AND_ASSIGN(PowerNotificationView);
};
@@ -201,170 +111,43 @@
using tray::PowerNotificationView;
-TrayPower::TrayPower(SystemTray* system_tray)
+TrayPower::TrayPower(SystemTray* system_tray, MessageCenter* message_center)
: SystemTrayItem(system_tray),
+ message_center_(message_center),
power_tray_(NULL),
notification_view_(NULL),
- notification_state_(NOTIFICATION_NONE) {
- PowerManagerHandler::Get()->AddObserver(this);
+ notification_state_(NOTIFICATION_NONE),
+ usb_charger_was_connected_(false) {
+ PowerStatus::Get()->AddObserver(this);
}
TrayPower::~TrayPower() {
- if (PowerManagerHandler::IsInitialized())
- PowerManagerHandler::Get()->RemoveObserver(this);
-}
-
-// static
-bool TrayPower::IsBatteryChargingUnreliable(
- const chromeos::PowerSupplyStatus& supply_status) {
- // Sometimes devices can get into a state where the battery is almost fully
- // charged and the power subsystem reports "neither charging nor discharging"
- // despite the battery not at 100%. For now, only report unreliable charging
- // on USB.
- // TODO(derat): Update this when the power manager code is refactored for M29.
- return supply_status.battery_state == PowerSupplyStatus::CONNECTED_TO_USB;
-}
-
-// static
-int TrayPower::GetBatteryImageIndex(
- const chromeos::PowerSupplyStatus& supply_status) {
- int image_index = 0;
- if (supply_status.battery_percentage >= 100) {
- image_index = kNumPowerImages - 1;
- } else if (!supply_status.battery_is_present) {
- image_index = kNumPowerImages;
- } else {
- image_index = static_cast<int>(supply_status.battery_percentage /
- 100.0 * (kNumPowerImages - 1));
- image_index = std::max(std::min(image_index, kNumPowerImages - 2), 0);
- }
- return image_index;
-}
-
-// static
-int TrayPower::GetBatteryImageOffset(
- const chromeos::PowerSupplyStatus& supply_status) {
- if (IsBatteryChargingUnreliable(supply_status) ||
- !supply_status.line_power_on)
- return 0;
- return 1;
-}
-
-// static
-gfx::ImageSkia TrayPower::GetBatteryImage(int image_index,
- int image_offset,
- bool charging_unreliable,
- IconSet icon_set) {
- gfx::Image all;
- if (charging_unreliable) {
- all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- icon_set == ICON_DARK ?
- IDR_AURA_UBER_TRAY_POWER_SMALL_CHARGING_UNRELIABLE_DARK :
- IDR_AURA_UBER_TRAY_POWER_SMALL_CHARGING_UNRELIABLE);
- } else {
- all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- icon_set == ICON_DARK ?
- IDR_AURA_UBER_TRAY_POWER_SMALL_DARK : IDR_AURA_UBER_TRAY_POWER_SMALL);
- }
- gfx::Rect region(
- image_offset * kBatteryImageWidth,
- image_index * kBatteryImageHeight,
- kBatteryImageWidth, kBatteryImageHeight);
- return gfx::ImageSkiaOperations::ExtractSubset(*all.ToImageSkia(), region);
-}
-
-// static
-base::string16 TrayPower::GetAccessibleNameString(
- const chromeos::PowerSupplyStatus& supply_status) {
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- if (supply_status.line_power_on && supply_status.battery_is_full) {
- return rb.GetLocalizedString(
- IDS_ASH_STATUS_TRAY_BATTERY_FULL_CHARGE_ACCESSIBLE);
- }
- bool charging_unreliable =
- IsBatteryChargingUnreliable(supply_status);
- if (supply_status.battery_percentage < 0.0f) {
- if (charging_unreliable) {
- return rb.GetLocalizedString(
- IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE_ACCESSIBLE);
- }
- return rb.GetLocalizedString(
- IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING_ACCESSIBLE);
- }
- base::string16 battery_percentage_accessbile = l10n_util::GetStringFUTF16(
- supply_status.line_power_on ?
- IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ACCESSIBLE:
- IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ACCESSIBLE ,
- base::IntToString16(GetRoundedBatteryPercentage(
- supply_status.battery_percentage)));
- base::string16 battery_time_accessible = base::string16();
- if (charging_unreliable) {
- battery_time_accessible = rb.GetLocalizedString(
- IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE_ACCESSIBLE);
- } else {
- if (supply_status.is_calculating_battery_time) {
- battery_time_accessible = rb.GetLocalizedString(
- IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING_ACCESSIBLE);
- } else {
- base::TimeDelta time = base::TimeDelta::FromSeconds(
- supply_status.line_power_on ?
- supply_status.battery_seconds_to_full :
- supply_status.battery_seconds_to_empty);
- int hour = time.InHours();
- int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
- if (hour || min) {
- base::string16 minute = min < 10 ?
- ASCIIToUTF16("0") + base::IntToString16(min) :
- base::IntToString16(min);
- battery_time_accessible =
- l10n_util::GetStringFUTF16(
- supply_status.line_power_on ?
- IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_ACCESSIBLE :
- IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_ACCESSIBLE,
- GetBatteryTimeAccessibilityString(hour, min));
- }
- }
- }
- return battery_time_accessible.empty() ?
- battery_percentage_accessbile :
- battery_percentage_accessbile + ASCIIToUTF16(". ")
- + battery_time_accessible;
-}
-
-// static
-int TrayPower::GetRoundedBatteryPercentage(double battery_percentage) {
- DCHECK(battery_percentage >= 0.0);
- return std::max(kMinBatteryPercent,
- static_cast<int>(battery_percentage + 0.5));
+ PowerStatus::Get()->RemoveObserver(this);
}
views::View* TrayPower::CreateTrayView(user::LoginStatus status) {
// There may not be enough information when this is created about whether
// there is a battery or not. So always create this, and adjust visibility as
// necessary.
- PowerSupplyStatus power_status =
- PowerManagerHandler::Get()->GetPowerSupplyStatus();
CHECK(power_tray_ == NULL);
power_tray_ = new tray::PowerTrayView();
- power_tray_->UpdatePowerStatus(power_status, false);
+ power_tray_->UpdateStatus(false);
return power_tray_;
}
views::View* TrayPower::CreateDefaultView(user::LoginStatus status) {
// Make sure icon status is up-to-date. (Also triggers stub activation).
- RequestStatusUpdate();
+ PowerStatus::Get()->RequestStatusUpdate();
return NULL;
}
views::View* TrayPower::CreateNotificationView(user::LoginStatus status) {
CHECK(notification_view_ == NULL);
- PowerSupplyStatus power_status =
- PowerManagerHandler::Get()->GetPowerSupplyStatus();
- if (!power_status.battery_is_present)
+ if (!PowerStatus::Get()->IsBatteryPresent())
return NULL;
notification_view_ = new PowerNotificationView(this);
- notification_view_->UpdatePowerStatus(power_status);
+ notification_view_->UpdateStatus();
return notification_view_;
}
@@ -387,48 +170,77 @@
SetTrayImageItemBorder(power_tray_, alignment);
}
-void TrayPower::OnPowerStatusChanged(
- const chromeos::PowerSupplyStatus& status) {
- bool battery_alert = UpdateNotificationState(status);
+void TrayPower::OnPowerStatusChanged() {
+ bool battery_alert = UpdateNotificationState();
if (power_tray_)
- power_tray_->UpdatePowerStatus(status, battery_alert);
+ power_tray_->UpdateStatus(battery_alert);
if (notification_view_)
- notification_view_->UpdatePowerStatus(status);
+ notification_view_->UpdateStatus();
// Factory testing may place the battery into unusual states.
if (CommandLine::ForCurrentProcess()->HasSwitch(
ash::switches::kAshHideNotificationsForFactory))
return;
+ if (ash::switches::UseUsbChargerNotification())
+ MaybeShowUsbChargerNotification();
+
if (battery_alert)
ShowNotificationView();
else if (notification_state_ == NOTIFICATION_NONE)
HideNotificationView();
+
+ usb_charger_was_connected_ = PowerStatus::Get()->IsUsbChargerConnected();
}
-void TrayPower::RequestStatusUpdate() const {
- PowerManagerHandler::Get()->RequestStatusUpdate();
+bool TrayPower::MaybeShowUsbChargerNotification() {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ const char kNotificationId[] = "usb-charger";
+ bool usb_charger_is_connected = PowerStatus::Get()->IsUsbChargerConnected();
+
+ // Check for a USB charger being connected.
+ if (usb_charger_is_connected && !usb_charger_was_connected_) {
+ scoped_ptr<Notification> notification(new Notification(
+ message_center::NOTIFICATION_TYPE_SIMPLE,
+ kNotificationId,
+ rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_TITLE),
+ rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_MESSAGE),
+ rb.GetImageNamed(IDR_AURA_NOTIFICATION_LOW_POWER_CHARGER),
+ base::string16(),
+ std::string(),
+ message_center::RichNotificationData(),
+ NULL));
+ message_center_->AddNotification(notification.Pass());
+ return true;
+ }
+
+ // Check for unplug of a USB charger while the USB charger notification is
+ // showing.
+ if (!usb_charger_is_connected && usb_charger_was_connected_) {
+ message_center_->RemoveNotification(kNotificationId, false);
+ return true;
+ }
+ return false;
}
-bool TrayPower::UpdateNotificationState(
- const chromeos::PowerSupplyStatus& status) {
- if (!status.battery_is_present ||
- status.is_calculating_battery_time ||
- status.battery_state == PowerSupplyStatus::CHARGING) {
+bool TrayPower::UpdateNotificationState() {
+ const PowerStatus& status = *PowerStatus::Get();
+ if (!status.IsBatteryPresent() ||
+ status.IsBatteryTimeBeingCalculated() ||
+ status.IsMainsChargerConnected()) {
notification_state_ = NOTIFICATION_NONE;
return false;
}
- if (TrayPower::IsBatteryChargingUnreliable(status)) {
- return UpdateNotificationStateForRemainingPercentage(
- status.battery_percentage);
- } else {
- return UpdateNotificationStateForRemainingTime(
- status.battery_seconds_to_empty);
- }
+ return status.IsUsbChargerConnected() ?
+ UpdateNotificationStateForRemainingPercentage() :
+ UpdateNotificationStateForRemainingTime();
}
-bool TrayPower::UpdateNotificationStateForRemainingTime(int remaining_seconds) {
+bool TrayPower::UpdateNotificationStateForRemainingTime() {
+ const int remaining_seconds =
+ PowerStatus::Get()->GetBatteryTimeToEmpty().InSeconds();
+
if (remaining_seconds >= kNoWarningSeconds) {
notification_state_ = NOTIFICATION_NONE;
return false;
@@ -439,7 +251,8 @@
if (remaining_seconds <= kCriticalSeconds) {
notification_state_ = NOTIFICATION_CRITICAL;
return true;
- } else if (remaining_seconds <= kLowPowerSeconds) {
+ }
+ if (remaining_seconds <= kLowPowerSeconds) {
notification_state_ = NOTIFICATION_LOW_POWER;
return true;
}
@@ -457,8 +270,9 @@
return false;
}
-bool TrayPower::UpdateNotificationStateForRemainingPercentage(
- double remaining_percentage) {
+bool TrayPower::UpdateNotificationStateForRemainingPercentage() {
+ const double remaining_percentage = PowerStatus::Get()->GetBatteryPercent();
+
if (remaining_percentage > kNoWarningPercentage) {
notification_state_ = NOTIFICATION_NONE;
return false;
diff --git a/ash/system/chromeos/power/tray_power.h b/ash/system/chromeos/power/tray_power.h
index db33f35..2a66cd5 100644
--- a/ash/system/chromeos/power/tray_power.h
+++ b/ash/system/chromeos/power/tray_power.h
@@ -5,15 +5,20 @@
#ifndef ASH_SYSTEM_CHROMEOS_POWER_TRAY_POWER_H_
#define ASH_SYSTEM_CHROMEOS_POWER_TRAY_POWER_H_
+#include "ash/system/chromeos/power/power_status.h"
#include "ash/system/tray/system_tray_item.h"
-#include "chromeos/power/power_manager_handler.h"
class SkBitmap;
namespace gfx {
+class Image;
class ImageSkia;
}
+namespace message_center {
+class MessageCenter;
+}
+
namespace ash {
namespace internal {
@@ -22,56 +27,27 @@
class PowerTrayView;
}
-enum IconSet {
- ICON_LIGHT,
- ICON_DARK
-};
-
-class TrayPower : public SystemTrayItem,
- public chromeos::PowerManagerHandler::Observer {
+class ASH_EXPORT TrayPower : public SystemTrayItem,
+ public PowerStatus::Observer {
public:
- explicit TrayPower(SystemTray* system_tray);
- virtual ~TrayPower();
-
- // Gets whether battery charging is unreliable for |supply_status|.
- // When a non-standard power supply is connected, the battery may
- // change from being charged to discharged frequently depending on the
- // charger power and power consumption, i.e usage. In this case we
- // do not want to show either a charging or discharging state.
- static bool IsBatteryChargingUnreliable(
- const chromeos::PowerSupplyStatus& supply_status);
-
- // Gets the icon index in the battery icon array image based on
- // |supply_status|. If |supply_status| is uncertain about the power state,
- // returns -1.
- static int GetBatteryImageIndex(
- const chromeos::PowerSupplyStatus& supply_status);
-
- // Gets the horizontal offset in the battery icon array image based on
- // |supply_status|.
- static int GetBatteryImageOffset(
- const chromeos::PowerSupplyStatus& supply_status);
-
- // Looks up the actual icon in the icon array image for |image_index|.
- static gfx::ImageSkia GetBatteryImage(int image_index,
- int image_offset,
- bool charging_unreliable,
- IconSet icon_set);
-
- // Gets the battery accessible string for |supply_status|.
- static base::string16 GetAccessibleNameString(
- const chromeos::PowerSupplyStatus& supply_status);
-
- // Gets rounded battery percentage for |battery_percentage|.
- static int GetRoundedBatteryPercentage(double battery_percentage);
-
- private:
+ // Visible for testing.
enum NotificationState {
NOTIFICATION_NONE,
+
+ // Low battery charge.
NOTIFICATION_LOW_POWER,
- NOTIFICATION_CRITICAL
+
+ // Critically low battery charge.
+ NOTIFICATION_CRITICAL,
};
+ TrayPower(SystemTray* system_tray,
+ message_center::MessageCenter* message_center);
+ virtual ~TrayPower();
+
+ private:
+ friend class TrayPowerTest;
+
// Overridden from SystemTrayItem.
virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE;
virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE;
@@ -84,23 +60,27 @@
virtual void UpdateAfterShelfAlignmentChange(
ShelfAlignment alignment) OVERRIDE;
- // Overridden from chromeos::PowerManagerHandler::Observer.
- virtual void OnPowerStatusChanged(
- const chromeos::PowerSupplyStatus& status) OVERRIDE;
+ // Overridden from PowerStatus::Observer.
+ virtual void OnPowerStatusChanged() OVERRIDE;
- // Requests a power status update.
- void RequestStatusUpdate() const;
+ // Show a notification that a low-power USB charger has been connected.
+ // Returns true if a notification was shown or explicitly hidden.
+ bool MaybeShowUsbChargerNotification();
// Sets |notification_state_|. Returns true if a notification should be shown.
- bool UpdateNotificationState(const chromeos::PowerSupplyStatus& status);
- bool UpdateNotificationStateForRemainingTime(int remaining_seconds);
- bool UpdateNotificationStateForRemainingPercentage(
- double remaining_percentage);
+ bool UpdateNotificationState();
+ bool UpdateNotificationStateForRemainingTime();
+ bool UpdateNotificationStateForRemainingPercentage();
+ message_center::MessageCenter* message_center_; // Not owned.
tray::PowerTrayView* power_tray_;
tray::PowerNotificationView* notification_view_;
NotificationState notification_state_;
+ // Was a USB charger connected the last time OnPowerStatusChanged() was
+ // called?
+ bool usb_charger_was_connected_;
+
DISALLOW_COPY_AND_ASSIGN(TrayPower);
};
diff --git a/ash/system/chromeos/power/tray_power_unittest.cc b/ash/system/chromeos/power/tray_power_unittest.cc
new file mode 100644
index 0000000..82bac27
--- /dev/null
+++ b/ash/system/chromeos/power/tray_power_unittest.cc
@@ -0,0 +1,173 @@
+// 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/system/chromeos/power/tray_power.h"
+
+#include "ash/ash_switches.h"
+#include "ash/test/ash_test_base.h"
+#include "base/memory/scoped_ptr.h"
+#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
+#include "ui/message_center/fake_message_center.h"
+
+using message_center::Notification;
+using power_manager::PowerSupplyProperties;
+
+namespace {
+
+class MockMessageCenter : public message_center::FakeMessageCenter {
+ public:
+ MockMessageCenter() : add_count_(0), remove_count_(0) {}
+ virtual ~MockMessageCenter() {}
+
+ int add_count() const { return add_count_; }
+ int remove_count() const { return remove_count_; }
+
+ // message_center::FakeMessageCenter overrides:
+ virtual void AddNotification(scoped_ptr<Notification> notification) OVERRIDE {
+ add_count_++;
+ }
+ virtual void RemoveNotification(const std::string& id, bool by_user)
+ OVERRIDE {
+ remove_count_++;
+ }
+
+ private:
+ int add_count_;
+ int remove_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
+};
+
+} // namespace
+
+namespace ash {
+namespace internal {
+
+class TrayPowerTest : public test::AshTestBase {
+ public:
+ TrayPowerTest() {}
+ virtual ~TrayPowerTest() {}
+
+ MockMessageCenter* message_center() { return message_center_.get(); }
+ TrayPower* tray_power() { return tray_power_.get(); }
+
+ // test::AshTestBase::SetUp() overrides:
+ virtual void SetUp() OVERRIDE {
+ test::AshTestBase::SetUp();
+ message_center_.reset(new MockMessageCenter());
+ tray_power_.reset(new TrayPower(NULL, message_center_.get()));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ tray_power_.reset();
+ message_center_.reset();
+ test::AshTestBase::TearDown();
+ }
+
+ TrayPower::NotificationState notification_state() const {
+ return tray_power_->notification_state_;
+ }
+
+ bool MaybeShowUsbChargerNotification(const PowerSupplyProperties& proto) {
+ PowerStatus::Get()->SetProtoForTesting(proto);
+ return tray_power_->MaybeShowUsbChargerNotification();
+ }
+
+ bool UpdateNotificationState(const PowerSupplyProperties& proto) {
+ PowerStatus::Get()->SetProtoForTesting(proto);
+ return tray_power_->UpdateNotificationState();
+ }
+
+ void SetUsbChargerConnected(bool connected) {
+ tray_power_->usb_charger_was_connected_ = connected;
+ }
+
+ // Returns a discharging PowerSupplyProperties more appropriate for testing.
+ static PowerSupplyProperties DefaultPowerSupplyProperties() {
+ PowerSupplyProperties proto;
+ proto.set_external_power(
+ power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
+ proto.set_battery_state(
+ power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
+ proto.set_battery_percent(50.0);
+ proto.set_battery_time_to_empty_sec(3 * 60 * 60);
+ proto.set_battery_time_to_full_sec(2 * 60 * 60);
+ proto.set_is_calculating_battery_time(false);
+ return proto;
+ }
+
+ private:
+ scoped_ptr<MockMessageCenter> message_center_;
+ scoped_ptr<TrayPower> tray_power_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrayPowerTest);
+};
+
+TEST_F(TrayPowerTest, MaybeShowUsbChargerNotification) {
+ PowerSupplyProperties discharging = DefaultPowerSupplyProperties();
+ EXPECT_FALSE(MaybeShowUsbChargerNotification(discharging));
+ EXPECT_EQ(0, message_center()->add_count());
+ EXPECT_EQ(0, message_center()->remove_count());
+
+ // Notification shows when connecting a USB charger.
+ PowerSupplyProperties usb_connected = DefaultPowerSupplyProperties();
+ usb_connected.set_external_power(
+ power_manager::PowerSupplyProperties_ExternalPower_USB);
+ EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
+ EXPECT_EQ(1, message_center()->add_count());
+ EXPECT_EQ(0, message_center()->remove_count());
+
+ // Change in charge does not trigger the notification again.
+ PowerSupplyProperties more_charge = DefaultPowerSupplyProperties();
+ more_charge.set_external_power(
+ power_manager::PowerSupplyProperties_ExternalPower_USB);
+ more_charge.set_battery_time_to_full_sec(60 * 60);
+ more_charge.set_battery_percent(75.0);
+ SetUsbChargerConnected(true);
+ EXPECT_FALSE(MaybeShowUsbChargerNotification(more_charge));
+ EXPECT_EQ(1, message_center()->add_count());
+ EXPECT_EQ(0, message_center()->remove_count());
+
+ // Disconnecting a USB charger with the notification showing should close
+ // the notification.
+ EXPECT_TRUE(MaybeShowUsbChargerNotification(discharging));
+ EXPECT_EQ(1, message_center()->add_count());
+ EXPECT_EQ(1, message_center()->remove_count());
+}
+
+TEST_F(TrayPowerTest, UpdateNotificationState) {
+ // No notifications when no battery present.
+ PowerSupplyProperties no_battery = DefaultPowerSupplyProperties();
+ no_battery.set_external_power(
+ power_manager::PowerSupplyProperties_ExternalPower_AC);
+ no_battery.set_battery_state(
+ power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT);
+ EXPECT_FALSE(UpdateNotificationState(no_battery));
+ EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
+
+ // No notification when calculating remaining battery time.
+ PowerSupplyProperties calculating = DefaultPowerSupplyProperties();
+ calculating.set_is_calculating_battery_time(true);
+ EXPECT_FALSE(UpdateNotificationState(calculating));
+ EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
+
+ // No notification when charging.
+ PowerSupplyProperties charging = DefaultPowerSupplyProperties();
+ charging.set_external_power(
+ power_manager::PowerSupplyProperties_ExternalPower_AC);
+ charging.set_battery_state(
+ power_manager::PowerSupplyProperties_BatteryState_CHARGING);
+ EXPECT_FALSE(UpdateNotificationState(charging));
+ EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
+
+ // Critical low battery notification.
+ PowerSupplyProperties critical = DefaultPowerSupplyProperties();
+ critical.set_battery_time_to_empty_sec(60);
+ critical.set_battery_percent(2.0);
+ EXPECT_TRUE(UpdateNotificationState(critical));
+ EXPECT_EQ(TrayPower::NOTIFICATION_CRITICAL, notification_state());
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/system/chromeos/screen_security/screen_capture_tray_item.h b/ash/system/chromeos/screen_security/screen_capture_tray_item.h
index a756416..f1fb4b5 100644
--- a/ash/system/chromeos/screen_security/screen_capture_tray_item.h
+++ b/ash/system/chromeos/screen_security/screen_capture_tray_item.h
@@ -15,8 +15,8 @@
namespace ash {
namespace internal {
-class ScreenCaptureTrayItem : public ScreenTrayItem,
- public ScreenCaptureObserver {
+class ASH_EXPORT ScreenCaptureTrayItem : public ScreenTrayItem,
+ public ScreenCaptureObserver {
public:
explicit ScreenCaptureTrayItem(SystemTray* system_tray);
virtual ~ScreenCaptureTrayItem();
diff --git a/ash/system/chromeos/screen_security/screen_share_tray_item.cc b/ash/system/chromeos/screen_security/screen_share_tray_item.cc
index c1971e2..3e10763 100644
--- a/ash/system/chromeos/screen_security/screen_share_tray_item.cc
+++ b/ash/system/chromeos/screen_security/screen_share_tray_item.cc
@@ -25,7 +25,7 @@
views::View* ScreenShareTrayItem::CreateTrayView(user::LoginStatus status) {
set_tray_view(
- new tray::ScreenTrayView(this, IDR_AURA_UBER_TRAY_SCREEN_SHARE_LIGHT));
+ new tray::ScreenTrayView(this, IDR_AURA_UBER_TRAY_DISPLAY_LIGHT));
return tray_view();
}
@@ -33,7 +33,7 @@
set_default_view(new tray::ScreenStatusView(
this,
tray::ScreenStatusView::VIEW_DEFAULT,
- IDR_AURA_UBER_TRAY_SCREEN_SHARE_DARK,
+ IDR_AURA_UBER_TRAY_DISPLAY,
l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED),
l10n_util::GetStringUTF16(
@@ -55,7 +55,7 @@
set_notification_view(new tray::ScreenNotificationView(
this,
- IDR_AURA_UBER_TRAY_SCREEN_SHARE_DARK,
+ IDR_AURA_UBER_TRAY_DISPLAY,
help_label_text,
l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_SCREEN_SHARE_STOP)));
diff --git a/ash/system/chromeos/screen_security/screen_share_tray_item.h b/ash/system/chromeos/screen_security/screen_share_tray_item.h
index 84a29d0..4624ac2 100644
--- a/ash/system/chromeos/screen_security/screen_share_tray_item.h
+++ b/ash/system/chromeos/screen_security/screen_share_tray_item.h
@@ -15,8 +15,8 @@
namespace ash {
namespace internal {
-class ScreenShareTrayItem : public ScreenTrayItem,
- public ScreenShareObserver {
+class ASH_EXPORT ScreenShareTrayItem : public ScreenTrayItem,
+ public ScreenShareObserver {
public:
explicit ScreenShareTrayItem(SystemTray* system_tray);
virtual ~ScreenShareTrayItem();
diff --git a/ash/system/chromeos/screen_security/screen_tray_item.h b/ash/system/chromeos/screen_security/screen_tray_item.h
index ff7e1bb..03b8435 100644
--- a/ash/system/chromeos/screen_security/screen_tray_item.h
+++ b/ash/system/chromeos/screen_security/screen_tray_item.h
@@ -99,7 +99,7 @@
// The base tray item for screen capture and screen sharing. The
// Start method brings up a notification and a tray item, and the user
// can stop the screen capture/sharing by pressing the stop button.
-class ScreenTrayItem : public SystemTrayItem {
+class ASH_EXPORT ScreenTrayItem : public SystemTrayItem {
public:
explicit ScreenTrayItem(SystemTray* system_tray);
virtual ~ScreenTrayItem();
diff --git a/ash/system/chromeos/screen_security/screen_tray_item_unittest.cc b/ash/system/chromeos/screen_security/screen_tray_item_unittest.cc
new file mode 100644
index 0000000..d95bed9
--- /dev/null
+++ b/ash/system/chromeos/screen_security/screen_tray_item_unittest.cc
@@ -0,0 +1,227 @@
+// 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/system/chromeos/screen_security/screen_tray_item.h"
+
+#include "ash/system/chromeos/screen_security/screen_capture_tray_item.h"
+#include "ash/system/chromeos/screen_security/screen_share_tray_item.h"
+#include "ash/system/tray/tray_item_view.h"
+#include "ash/test/ash_test_base.h"
+#include "base/callback.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/base/events/event.h"
+#include "ui/gfx/point.h"
+#include "ui/views/view.h"
+
+namespace ash {
+namespace internal {
+
+// Test with unicode strings.
+const char kTestScreenCaptureAppName[] =
+ "\xE0\xB2\xA0\x5F\xE0\xB2\xA0 (Screen Capture Test)";
+const char kTestScreenShareHelperName[] =
+ "\xE5\xAE\x8B\xE8\x85\xBE (Screen Share Test)";
+
+SystemTray* GetSystemTray() {
+ return Shell::GetInstance()->GetPrimarySystemTray();
+}
+
+SystemTrayNotifier* GetSystemTrayNotifier() {
+ return Shell::GetInstance()->system_tray_notifier();
+}
+
+void ClickViewCenter(views::View* view) {
+ gfx::Point click_location_in_local =
+ gfx::Point(view->width() / 2, view->height() / 2);
+ view->OnMousePressed(ui::MouseEvent(ui::ET_MOUSE_PRESSED,
+ click_location_in_local,
+ click_location_in_local,
+ ui::EF_NONE));
+}
+
+class ScreenTrayItemTest : public ash::test::AshTestBase {
+ public:
+ ScreenTrayItemTest()
+ : tray_item_(NULL), stop_callback_hit_count_(0) {}
+ virtual ~ScreenTrayItemTest() {}
+
+ ScreenTrayItem* tray_item() { return tray_item_; }
+ void set_tray_item(ScreenTrayItem* tray_item) { tray_item_ = tray_item; }
+
+ int stop_callback_hit_count() const { return stop_callback_hit_count_; }
+
+ virtual void SetUp() OVERRIDE {
+ test::AshTestBase::SetUp();
+ TrayItemView::DisableAnimationsForTest();
+ }
+
+ void StartSession() {
+ tray_item_->Start(
+ base::Bind(&ScreenTrayItemTest::StopCallback, base::Unretained(this)));
+ }
+
+ void StopSession() {
+ tray_item_->Stop();
+ }
+
+ void StopCallback() {
+ stop_callback_hit_count_++;
+ }
+
+ private:
+ ScreenTrayItem* tray_item_;
+ int stop_callback_hit_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenTrayItemTest);
+};
+
+class ScreenCaptureTest : public ScreenTrayItemTest {
+ public:
+ ScreenCaptureTest() {}
+ virtual ~ScreenCaptureTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ScreenTrayItemTest::SetUp();
+ // This tray item is owned by its parent system tray view and will
+ // be deleted automatically when its parent is destroyed in AshTestBase.
+ ScreenTrayItem* tray_item = new ScreenCaptureTrayItem(GetSystemTray());
+ GetSystemTray()->AddTrayItem(tray_item);
+ set_tray_item(tray_item);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenCaptureTest);
+};
+
+class ScreenShareTest : public ScreenTrayItemTest {
+ public:
+ ScreenShareTest() {}
+ virtual ~ScreenShareTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ScreenTrayItemTest::SetUp();
+ // This tray item is owned by its parent system tray view and will
+ // be deleted automatically when its parent is destroyed in AshTestBase.
+ ScreenTrayItem* tray_item = new ScreenShareTrayItem(GetSystemTray());
+ GetSystemTray()->AddTrayItem(tray_item);
+ set_tray_item(tray_item);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenShareTest);
+};
+
+void TestStartAndStop(ScreenTrayItemTest* test) {
+ ScreenTrayItem* tray_item = test->tray_item();
+
+ EXPECT_FALSE(tray_item->is_started());
+ EXPECT_EQ(0, test->stop_callback_hit_count());
+
+ test->StartSession();
+ EXPECT_TRUE(tray_item->is_started());
+
+ test->StopSession();
+ EXPECT_FALSE(tray_item->is_started());
+ EXPECT_EQ(1, test->stop_callback_hit_count());
+}
+
+TEST_F(ScreenCaptureTest, StartAndStop) { TestStartAndStop(this); }
+TEST_F(ScreenShareTest, StartAndStop) { TestStartAndStop(this); }
+
+void TestNotificationStartAndStop(ScreenTrayItemTest* test,
+ const base::Closure& start_function,
+ const base::Closure& stop_function) {
+ ScreenTrayItem* tray_item = test->tray_item();
+ EXPECT_FALSE(tray_item->is_started());
+
+ start_function.Run();
+ EXPECT_TRUE(tray_item->is_started());
+
+ // The stop callback shouldn't be called because we stopped
+ // through the notification system.
+ stop_function.Run();
+ EXPECT_FALSE(tray_item->is_started());
+ EXPECT_EQ(0, test->stop_callback_hit_count());
+}
+
+TEST_F(ScreenCaptureTest, NotificationStartAndStop) {
+ base::Closure start_function =
+ base::Bind(&SystemTrayNotifier::NotifyScreenCaptureStart,
+ base::Unretained(GetSystemTrayNotifier()),
+ base::Bind(&ScreenTrayItemTest::StopCallback,
+ base::Unretained(this)),
+ base::UTF8ToUTF16(kTestScreenCaptureAppName));
+
+ base::Closure stop_function =
+ base::Bind(&SystemTrayNotifier::NotifyScreenCaptureStop,
+ base::Unretained(GetSystemTrayNotifier()));
+
+ TestNotificationStartAndStop(this, start_function, stop_function);
+}
+
+TEST_F(ScreenShareTest, NotificationStartAndStop) {
+ base::Closure start_func =
+ base::Bind(&SystemTrayNotifier::NotifyScreenShareStart,
+ base::Unretained(GetSystemTrayNotifier()),
+ base::Bind(&ScreenTrayItemTest::StopCallback,
+ base::Unretained(this)),
+ base::UTF8ToUTF16(kTestScreenShareHelperName));
+
+ base::Closure stop_func =
+ base::Bind(&SystemTrayNotifier::NotifyScreenShareStop,
+ base::Unretained(GetSystemTrayNotifier()));
+
+ TestNotificationStartAndStop(this, start_func, stop_func);
+}
+
+void TestNotificationView(ScreenTrayItemTest* test) {
+ ScreenTrayItem* tray_item = test->tray_item();
+
+ test->StartSession();
+ EXPECT_TRUE(tray_item->notification_view()->visible());
+
+ // Clicking on the notification view should dismiss the view
+ ClickViewCenter(tray_item->notification_view());
+ EXPECT_FALSE(tray_item->notification_view());
+
+ test->StopSession();
+}
+
+TEST_F(ScreenCaptureTest, NotificationView) { TestNotificationView(this); }
+TEST_F(ScreenShareTest, NotificationView) { TestNotificationView(this); }
+
+void TestSystemTrayInteraction(ScreenTrayItemTest* test) {
+ ScreenTrayItem* tray_item = test->tray_item();
+ EXPECT_FALSE(tray_item->tray_view()->visible());
+
+ const std::vector<SystemTrayItem*>& tray_items =
+ GetSystemTray()->GetTrayItems();
+ EXPECT_NE(std::find(tray_items.begin(), tray_items.end(), tray_item),
+ tray_items.end());
+
+ test->StartSession();
+ EXPECT_TRUE(tray_item->tray_view()->visible());
+
+ // The default view should be created in a new bubble.
+ GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
+ EXPECT_TRUE(tray_item->default_view());
+ GetSystemTray()->CloseSystemBubble();
+ EXPECT_FALSE(tray_item->default_view());
+
+ test->StopSession();
+ EXPECT_FALSE(tray_item->tray_view()->visible());
+
+ // The default view should not be visible because session is stopped.
+ GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
+ EXPECT_FALSE(tray_item->default_view()->visible());
+}
+
+TEST_F(ScreenCaptureTest, SystemTrayInteraction) {
+ TestSystemTrayInteraction(this);
+}
+
+TEST_F(ScreenShareTest, SystemTrayInteraction) {
+ TestSystemTrayInteraction(this);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/system/chromeos/settings/tray_settings.cc b/ash/system/chromeos/settings/tray_settings.cc
index a721299..8153aea 100644
--- a/ash/system/chromeos/settings/tray_settings.cc
+++ b/ash/system/chromeos/settings/tray_settings.cc
@@ -5,6 +5,7 @@
#include "ash/system/chromeos/settings/tray_settings.h"
#include "ash/shell.h"
+#include "ash/system/chromeos/power/power_status.h"
#include "ash/system/chromeos/power/power_status_view.h"
#include "ash/system/tray/actionable_view.h"
#include "ash/system/tray/fixed_sized_image_view.h"
@@ -12,7 +13,6 @@
#include "ash/system/tray/tray_constants.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
-#include "chromeos/dbus/power_manager_client.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -30,12 +30,14 @@
namespace tray {
-class SettingsDefaultView : public ActionableView {
+class SettingsDefaultView : public ActionableView,
+ public PowerStatus::Observer {
public:
explicit SettingsDefaultView(user::LoginStatus status)
: login_status_(status),
label_(NULL),
power_status_view_(NULL) {
+ PowerStatus::Get()->AddObserver(this);
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
ash::kTrayPopupPaddingHorizontal, 0,
ash::kTrayPopupPaddingBetweenItems));
@@ -58,27 +60,16 @@
power_view_right_align = true;
}
- chromeos::PowerSupplyStatus power_status =
- chromeos::PowerManagerHandler::Get()->GetPowerSupplyStatus();
- if (power_status.battery_is_present) {
+ if (PowerStatus::Get()->IsBatteryPresent()) {
power_status_view_ = new ash::internal::PowerStatusView(
ash::internal::PowerStatusView::VIEW_DEFAULT, power_view_right_align);
AddChildView(power_status_view_);
- UpdatePowerStatus(power_status);
+ OnPowerStatusChanged();
}
}
- virtual ~SettingsDefaultView() {}
-
- void UpdatePowerStatus(const chromeos::PowerSupplyStatus& status) {
- if (!power_status_view_)
- return;
- power_status_view_->UpdatePowerStatus(status);
- base::string16 accessible_name = label_ ?
- label_->text() + ASCIIToUTF16(", ") +
- power_status_view_->accessible_name() :
- power_status_view_->accessible_name();
- SetAccessibleName(accessible_name);
+ virtual ~SettingsDefaultView() {
+ PowerStatus::Get()->RemoveObserver(this);
}
// Overridden from ash::internal::ActionableView.
@@ -112,6 +103,18 @@
Layout();
}
+ // Overridden from PowerStatus::Observer.
+ virtual void OnPowerStatusChanged() OVERRIDE {
+ if (!PowerStatus::Get()->IsBatteryPresent())
+ return;
+
+ base::string16 accessible_name = label_ ?
+ label_->text() + ASCIIToUTF16(", ") +
+ PowerStatus::Get()->GetAccessibleNameString() :
+ PowerStatus::Get()->GetAccessibleNameString();
+ SetAccessibleName(accessible_name);
+ }
+
private:
user::LoginStatus login_status_;
views::Label* label_;
@@ -125,12 +128,9 @@
TraySettings::TraySettings(SystemTray* system_tray)
: SystemTrayItem(system_tray),
default_view_(NULL) {
- chromeos::PowerManagerHandler::Get()->AddObserver(this);
}
TraySettings::~TraySettings() {
- if (chromeos::PowerManagerHandler::IsInitialized())
- chromeos::PowerManagerHandler::Get()->RemoveObserver(this);
}
views::View* TraySettings::CreateTrayView(user::LoginStatus status) {
@@ -139,9 +139,7 @@
views::View* TraySettings::CreateDefaultView(user::LoginStatus status) {
if ((status == user::LOGGED_IN_NONE || status == user::LOGGED_IN_LOCKED) &&
- (chromeos::PowerManagerHandler::IsInitialized() &&
- !chromeos::PowerManagerHandler::Get()->
- GetPowerSupplyStatus().battery_is_present))
+ !PowerStatus::Get()->IsBatteryPresent())
return NULL;
CHECK(default_view_ == NULL);
@@ -167,11 +165,5 @@
void TraySettings::UpdateAfterLoginStatusChange(user::LoginStatus status) {
}
-void TraySettings::OnPowerStatusChanged(
- const chromeos::PowerSupplyStatus& status) {
- if (default_view_)
- default_view_->UpdatePowerStatus(status);
-}
-
} // namespace internal
} // namespace ash
diff --git a/ash/system/chromeos/settings/tray_settings.h b/ash/system/chromeos/settings/tray_settings.h
index c0dc9db..e48aad3 100644
--- a/ash/system/chromeos/settings/tray_settings.h
+++ b/ash/system/chromeos/settings/tray_settings.h
@@ -6,7 +6,6 @@
#define ASH_SYSTEM_CHROMEOS_SETTINGS_TRAY_SETTINGS_H_
#include "ash/system/tray/system_tray_item.h"
-#include "chromeos/power/power_manager_handler.h"
namespace ash {
namespace internal {
@@ -15,8 +14,7 @@
class SettingsDefaultView;
}
-class TraySettings : public SystemTrayItem,
- public chromeos::PowerManagerHandler::Observer {
+class TraySettings : public SystemTrayItem {
public:
explicit TraySettings(SystemTray* system_tray);
virtual ~TraySettings();
@@ -31,10 +29,6 @@
virtual void DestroyDetailedView() OVERRIDE;
virtual void UpdateAfterLoginStatusChange(user::LoginStatus status) OVERRIDE;
- // Overridden from chromeos::PowerManagerHandler::Observer.
- virtual void OnPowerStatusChanged(
- const chromeos::PowerSupplyStatus& status) OVERRIDE;
-
tray::SettingsDefaultView* default_view_;
DISALLOW_COPY_AND_ASSIGN(TraySettings);
diff --git a/ash/system/chromeos/tray_display.cc b/ash/system/chromeos/tray_display.cc
index cf3ca84..29c07aa 100644
--- a/ash/system/chromeos/tray_display.cc
+++ b/ash/system/chromeos/tray_display.cc
@@ -7,43 +7,97 @@
#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
#include "ash/shell.h"
+#include "ash/system/tray/actionable_view.h"
#include "ash/system/tray/fixed_sized_image_view.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_notification_view.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_delegate.h"
+#include "ui/message_center/notification_list.h"
+#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
+using message_center::Notification;
+
namespace ash {
namespace internal {
namespace {
-TrayDisplayMode GetCurrentTrayDisplayMode() {
- DisplayManager* display_manager = Shell::GetInstance()->display_manager();
- if (display_manager->GetNumDisplays() > 1)
- return TRAY_DISPLAY_EXTENDED;
+static const char kDisplayNotificationId[] = "chrome://settings/display";
- if (display_manager->IsMirrored())
- return TRAY_DISPLAY_MIRRORED;
+DisplayManager* GetDisplayManager() {
+ return Shell::GetInstance()->display_manager();
+}
- int64 first_id = display_manager->first_display_id();
- if (display_manager->HasInternalDisplay() &&
- !display_manager->IsInternalDisplayId(first_id)) {
- return TRAY_DISPLAY_DOCKED;
+base::string16 GetDisplayName(int64 display_id) {
+ return UTF8ToUTF16(GetDisplayManager()->GetDisplayNameForId(display_id));
+}
+
+// Returns 1-line information for the specified display, like
+// "InternalDisplay: 1280x750"
+base::string16 GetDisplayInfoLine(int64 display_id) {
+ const DisplayInfo& display_info =
+ GetDisplayManager()->GetDisplayInfo(display_id);
+
+ base::string16 size_text = UTF8ToUTF16(
+ display_info.size_in_pixel().ToString());
+ base::string16 display_data;
+ if (display_info.has_overscan()) {
+ display_data = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION,
+ size_text,
+ l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN));
+ } else {
+ display_data = size_text;
}
- return TRAY_DISPLAY_SINGLE;
+ return l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY,
+ GetDisplayName(display_id),
+ display_data);
+}
+
+base::string16 GetAllDisplayInfo() {
+ DisplayManager* display_manager = GetDisplayManager();
+ std::vector<base::string16> lines;
+ int64 internal_id = gfx::Display::kInvalidDisplayID;
+ // Make sure to show the internal display first.
+ if (display_manager->HasInternalDisplay() &&
+ display_manager->IsInternalDisplayId(
+ display_manager->first_display_id())) {
+ internal_id = display_manager->first_display_id();
+ lines.push_back(GetDisplayInfoLine(internal_id));
+ }
+
+ for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
+ int64 id = display_manager->GetDisplayAt(i)->id();
+ if (id == internal_id)
+ continue;
+ lines.push_back(GetDisplayInfoLine(id));
+ }
+
+ if (display_manager->IsMirrored()) {
+ lines.push_back(GetDisplayInfoLine(
+ display_manager->mirrored_display().id()));
+ }
+
+ return JoinString(lines, '\n');
}
// Returns the name of the currently connected external display.
base::string16 GetExternalDisplayName() {
- DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ DisplayManager* display_manager = GetDisplayManager();
int64 external_id = display_manager->mirrored_display().id();
if (external_id == gfx::Display::kInvalidDisplayID) {
@@ -56,82 +110,120 @@
}
}
}
- if (external_id != gfx::Display::kInvalidDisplayID)
- return UTF8ToUTF16(display_manager->GetDisplayNameForId(external_id));
- return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
+
+ if (external_id == gfx::Display::kInvalidDisplayID)
+ return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
+
+ // The external display name may have an annotation of "(width x height)" in
+ // case that the display is rotated or its resolution is changed.
+ base::string16 name = GetDisplayName(external_id);
+ const DisplayInfo& display_info =
+ display_manager->GetDisplayInfo(external_id);
+ if (display_info.rotation() != gfx::Display::ROTATE_0 ||
+ display_info.ui_scale() != 1.0f ||
+ !display_info.overscan_insets_in_dip().empty()) {
+ name += UTF8ToUTF16(
+ " (" + display_info.size_in_pixel().ToString() + ")");
+ } else if (display_info.overscan_insets_in_dip().empty() &&
+ display_info.has_overscan()) {
+ name += UTF8ToUTF16(" (") + l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN) + UTF8ToUTF16(")");
+ }
+
+ return name;
}
-class DisplayViewBase {
- public:
- DisplayViewBase(user::LoginStatus login_status)
- : login_status_(login_status) {
- label_ = new views::Label();
- label_->SetMultiLine(true);
- label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+base::string16 GetTrayDisplayMessage() {
+ DisplayManager* display_manager = GetDisplayManager();
+ if (display_manager->GetNumDisplays() > 1) {
+ if (GetDisplayManager()->HasInternalDisplay()) {
+ return l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetExternalDisplayName());
+ }
+ return l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL);
}
- virtual ~DisplayViewBase() {
+ if (display_manager->IsMirrored()) {
+ if (GetDisplayManager()->HasInternalDisplay()) {
+ return l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetExternalDisplayName());
+ }
+ return l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL);
}
+ int64 first_id = display_manager->first_display_id();
+ if (display_manager->HasInternalDisplay() &&
+ !display_manager->IsInternalDisplayId(first_id)) {
+ return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED);
+ }
+
+ return base::string16();
+}
+
+void OpenSettings(user::LoginStatus login_status) {
+ if (login_status == ash::user::LOGGED_IN_USER ||
+ login_status == ash::user::LOGGED_IN_OWNER ||
+ login_status == ash::user::LOGGED_IN_GUEST) {
+ ash::Shell::GetInstance()->system_tray_delegate()->ShowDisplaySettings();
+ }
+}
+
+class DisplayNotificationDelegate
+ : public message_center::NotificationDelegate {
+ public:
+ DisplayNotificationDelegate(user::LoginStatus login_status)
+ : login_status_(login_status) {}
+
+ // message_center::NotificationDelegate overrides:
+ virtual void Display() OVERRIDE {}
+ virtual void Error() OVERRIDE {}
+ virtual void Close(bool by_user) OVERRIDE {}
+ virtual bool HasClickedListener() OVERRIDE { return true; }
+ virtual void Click() OVERRIDE { OpenSettings(login_status_); }
+
protected:
- void OpenSettings() {
- if (login_status_ == ash::user::LOGGED_IN_USER ||
- login_status_ == ash::user::LOGGED_IN_OWNER ||
- login_status_ == ash::user::LOGGED_IN_GUEST) {
- ash::Shell::GetInstance()->system_tray_delegate()->ShowDisplaySettings();
- }
- }
-
- bool UpdateLabelText() {
- switch (GetCurrentTrayDisplayMode()) {
- case TRAY_DISPLAY_SINGLE:
- // TODO(oshima|mukai): Support single display mode for overscan
- // alignment.
- return false;
- case TRAY_DISPLAY_EXTENDED:
- if (Shell::GetInstance()->display_manager()->HasInternalDisplay()) {
- label_->SetText(l10n_util::GetStringFUTF16(
- IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetExternalDisplayName()));
- } else {
- label_->SetText(l10n_util::GetStringUTF16(
- IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL));
- }
- break;
- case TRAY_DISPLAY_MIRRORED:
- if (Shell::GetInstance()->display_manager()->HasInternalDisplay()) {
- label_->SetText(l10n_util::GetStringFUTF16(
- IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetExternalDisplayName()));
- } else {
- label_->SetText(l10n_util::GetStringUTF16(
- IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL));
- }
- break;
- case TRAY_DISPLAY_DOCKED:
- label_->SetText(l10n_util::GetStringUTF16(
- IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED));
- break;
- }
- return true;
- }
-
- views::Label* label() { return label_; }
+ virtual ~DisplayNotificationDelegate() {}
private:
user::LoginStatus login_status_;
- views::Label* label_;
- DISALLOW_COPY_AND_ASSIGN(DisplayViewBase);
+ DISALLOW_COPY_AND_ASSIGN(DisplayNotificationDelegate);
};
+void UpdateDisplayNotification(const base::string16& message) {
+ // Always remove the notification to make sure the notification appears
+ // as a popup in any situation.
+ message_center::MessageCenter::Get()->RemoveNotification(
+ kDisplayNotificationId, false /* by_user */);
+
+ if (message.empty())
+ return;
+
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ scoped_ptr<Notification> notification(new Notification(
+ message_center::NOTIFICATION_TYPE_SIMPLE,
+ kDisplayNotificationId,
+ message,
+ GetAllDisplayInfo(),
+ bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY),
+ base::string16(), // display_source
+ "", // extension_id
+ message_center::RichNotificationData(),
+ new DisplayNotificationDelegate(
+ Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus())));
+ message_center::MessageCenter::Get()->AddNotification(notification.Pass());
+}
+
} // namespace
-class DisplayView : public DisplayViewBase,
- public ash::internal::ActionableView {
+class DisplayView : public ash::internal::ActionableView {
public:
explicit DisplayView(user::LoginStatus login_status)
- : DisplayViewBase(login_status) {
- SetLayoutManager(new
- views::BoxLayout(views::BoxLayout::kHorizontal,
+ : login_status_(login_status) {
+ SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kHorizontal,
ash::kTrayPopupPaddingHorizontal, 0,
ash::kTrayPopupPaddingBetweenItems));
@@ -141,70 +233,107 @@
image_->SetImage(
bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY).ToImageSkia());
AddChildView(image_);
- AddChildView(label());
+
+ label_ = new views::Label();
+ label_->SetMultiLine(true);
+ label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ AddChildView(label_);
Update();
}
virtual ~DisplayView() {}
void Update() {
- SetVisible(UpdateLabelText());
+ base::string16 message = GetTrayDisplayMessage();
+ if (message.empty() && ShouldShowFirstDisplayInfo())
+ message = GetDisplayInfoLine(GetDisplayManager()->first_display_id());
+ SetVisible(!message.empty());
+ label_->SetText(message);
+ }
+
+ views::Label* label() { return label_; }
+
+ // Overridden from views::View.
+ virtual bool GetTooltipText(const gfx::Point& p,
+ base::string16* tooltip) const OVERRIDE {
+ base::string16 tray_message = GetTrayDisplayMessage();
+ base::string16 display_message = GetAllDisplayInfo();
+ if (tray_message.empty() && display_message.empty())
+ return false;
+
+ *tooltip = tray_message + ASCIIToUTF16("\n") + display_message;
+ return true;
}
private:
+ bool ShouldShowFirstDisplayInfo() const {
+ const DisplayInfo& display_info = GetDisplayManager()->GetDisplayInfo(
+ GetDisplayManager()->first_display_id());
+ return display_info.rotation() != gfx::Display::ROTATE_0 ||
+ display_info.ui_scale() != 1.0f ||
+ !display_info.overscan_insets_in_dip().empty() ||
+ display_info.has_overscan();
+ }
+
// Overridden from ActionableView.
virtual bool PerformAction(const ui::Event& event) OVERRIDE {
- OpenSettings();
+ OpenSettings(login_status_);
return true;
}
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE {
int label_max_width = bounds().width() - kTrayPopupPaddingHorizontal * 2 -
kTrayPopupPaddingBetweenItems - image_->GetPreferredSize().width();
- label()->SizeToFit(label_max_width);
+ label_->SizeToFit(label_max_width);
PreferredSizeChanged();
}
+ user::LoginStatus login_status_;
views::ImageView* image_;
+ views::Label* label_;
DISALLOW_COPY_AND_ASSIGN(DisplayView);
};
-class DisplayNotificationView : public DisplayViewBase,
- public TrayNotificationView {
+class DisplayNotificationView : public TrayNotificationView {
public:
DisplayNotificationView(user::LoginStatus login_status,
- TrayDisplay* tray_item)
- : DisplayViewBase(login_status),
- TrayNotificationView(tray_item, IDR_AURA_UBER_TRAY_DISPLAY) {
- InitView(label());
+ TrayDisplay* tray_item,
+ const base::string16& message)
+ : TrayNotificationView(tray_item, IDR_AURA_UBER_TRAY_DISPLAY),
+ login_status_(login_status) {
StartAutoCloseTimer(kTrayPopupAutoCloseDelayForTextInSeconds);
- Update();
+ Update(message);
}
virtual ~DisplayNotificationView() {}
- void Update() {
- if (UpdateLabelText())
- RestartAutoCloseTimer();
- else
+ void Update(const base::string16& message) {
+ if (message.empty()) {
owner()->HideNotificationView();
+ } else {
+ views::Label* label = new views::Label(message);
+ label->SetMultiLine(true);
+ label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ UpdateView(label);
+ RestartAutoCloseTimer();
+ }
}
// Overridden from TrayNotificationView:
virtual void OnClickAction() OVERRIDE {
- OpenSettings();
+ OpenSettings(login_status_);
}
private:
+ user::LoginStatus login_status_;
+
DISALLOW_COPY_AND_ASSIGN(DisplayNotificationView);
};
TrayDisplay::TrayDisplay(SystemTray* system_tray)
: SystemTrayItem(system_tray),
- default_(NULL),
- notification_(NULL),
- current_mode_(GetCurrentTrayDisplayMode()) {
+ default_(NULL) {
Shell::GetInstance()->display_controller()->AddObserver(this);
}
@@ -212,39 +341,86 @@
Shell::GetInstance()->display_controller()->RemoveObserver(this);
}
+base::string16 TrayDisplay::GetDisplayMessageForNotification() {
+ DisplayManager* display_manager = GetDisplayManager();
+ DisplayInfoMap old_info;
+ old_info.swap(display_info_);
+ for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
+ int64 id = display_manager->GetDisplayAt(i)->id();
+ display_info_[id] = display_manager->GetDisplayInfo(id);
+ }
+
+ // Display is added or removed. Use the same message as the one in
+ // the system tray.
+ if (display_info_.size() != old_info.size())
+ return GetTrayDisplayMessage();
+
+ for (DisplayInfoMap::const_iterator iter = display_info_.begin();
+ iter != display_info_.end(); ++iter) {
+ DisplayInfoMap::const_iterator old_iter = old_info.find(iter->first);
+ // A display is removed and added at the same time. It won't happen
+ // in the actual environment, but falls back to the system tray's
+ // message just in case.
+ if (old_iter == old_info.end())
+ return GetTrayDisplayMessage();
+
+ if (iter->second.ui_scale() != old_iter->second.ui_scale()) {
+ return l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
+ GetDisplayName(iter->first),
+ UTF8ToUTF16(iter->second.size_in_pixel().ToString()));
+ }
+ if (iter->second.rotation() != old_iter->second.rotation()) {
+ return l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter->first));
+ }
+ }
+
+ // Found nothing special
+ return base::string16();
+}
+
views::View* TrayDisplay::CreateDefaultView(user::LoginStatus status) {
DCHECK(default_ == NULL);
default_ = new DisplayView(status);
return default_;
}
-views::View* TrayDisplay::CreateNotificationView(user::LoginStatus status) {
- DCHECK(notification_ == NULL);
- notification_ = new DisplayNotificationView(status, this);
- return notification_;
-}
-
void TrayDisplay::DestroyDefaultView() {
default_ = NULL;
}
-void TrayDisplay::DestroyNotificationView() {
- notification_ = NULL;
-}
-
-bool TrayDisplay::ShouldShowLauncher() const {
- return false;
-}
-
void TrayDisplay::OnDisplayConfigurationChanged() {
- TrayDisplayMode new_mode = GetCurrentTrayDisplayMode();
- if (current_mode_ != new_mode && new_mode != TRAY_DISPLAY_SINGLE) {
- if (notification_)
- notification_->Update();
- else
- ShowNotificationView();
+ if (!Shell::GetInstance()->system_tray_delegate()->
+ ShouldShowDisplayNotification()) {
+ return;
}
- current_mode_ = new_mode;
+
+ UpdateDisplayNotification(GetDisplayMessageForNotification());
+}
+
+base::string16 TrayDisplay::GetDefaultViewMessage() {
+ if (!default_ || !default_->visible())
+ return base::string16();
+
+ return static_cast<DisplayView*>(default_)->label()->text();
+}
+
+base::string16 TrayDisplay::GetNotificationMessage() {
+ message_center::NotificationList::Notifications notifications =
+ message_center::MessageCenter::Get()->GetNotifications();
+ for (message_center::NotificationList::Notifications::const_iterator iter =
+ notifications.begin(); iter != notifications.end(); ++iter) {
+ if ((*iter)->id() == kDisplayNotificationId)
+ return (*iter)->title();
+ }
+
+ return base::string16();
+}
+
+void TrayDisplay::CloseNotificationForTest() {
+ message_center::MessageCenter::Get()->RemoveNotification(
+ kDisplayNotificationId, false);
}
} // namespace internal
diff --git a/ash/system/chromeos/tray_display.h b/ash/system/chromeos/tray_display.h
index 0265704..7ede247 100644
--- a/ash/system/chromeos/tray_display.h
+++ b/ash/system/chromeos/tray_display.h
@@ -5,47 +5,54 @@
#ifndef ASH_SYSTEM_CHROMEOS_TRAY_DISPLAY_H_
#define ASH_SYSTEM_CHROMEOS_TRAY_DISPLAY_H_
-#include "ash/display/display_controller.h"
-#include "ash/system/tray/system_tray_item.h"
+#include <map>
-namespace views {
-class View;
-}
+#include "ash/ash_export.h"
+#include "ash/display/display_controller.h"
+#include "ash/display/display_info.h"
+#include "ash/system/tray/system_tray_item.h"
+#include "base/strings/string16.h"
+#include "ui/views/view.h"
namespace ash {
+namespace test {
+class AshTestBase;
+}
+
namespace internal {
-enum TrayDisplayMode {
- TRAY_DISPLAY_SINGLE,
- TRAY_DISPLAY_EXTENDED,
- TRAY_DISPLAY_MIRRORED,
- TRAY_DISPLAY_DOCKED,
-};
-
-class DisplayView;
class DisplayNotificationView;
-class TrayDisplay : public SystemTrayItem,
- public DisplayController::Observer {
+class ASH_EXPORT TrayDisplay : public SystemTrayItem,
+ public DisplayController::Observer {
public:
explicit TrayDisplay(SystemTray* system_tray);
virtual ~TrayDisplay();
private:
+ friend class TrayDisplayTest;
+
+ typedef std::map<int64, DisplayInfo> DisplayInfoMap;
+
+ // Checks the current display settings and determine what message should be
+ // shown for notification.
+ base::string16 GetDisplayMessageForNotification();
+
// Overridden from SystemTrayItem.
virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE;
- virtual views::View* CreateNotificationView(
- user::LoginStatus status) OVERRIDE;
virtual void DestroyDefaultView() OVERRIDE;
- virtual void DestroyNotificationView() OVERRIDE;
- virtual bool ShouldShowLauncher() const OVERRIDE;
// Overridden from DisplayControllerObserver:
virtual void OnDisplayConfigurationChanged() OVERRIDE;
- DisplayView* default_;
- DisplayNotificationView* notification_;
- TrayDisplayMode current_mode_;
+ // Test accessors.
+ base::string16 GetDefaultViewMessage();
+ base::string16 GetNotificationMessage();
+ void CloseNotificationForTest();
+ views::View* default_view() { return default_; }
+
+ views::View* default_;
+ DisplayInfoMap display_info_;
DISALLOW_COPY_AND_ASSIGN(TrayDisplay);
};
diff --git a/ash/system/chromeos/tray_display_unittest.cc b/ash/system/chromeos/tray_display_unittest.cc
new file mode 100644
index 0000000..1501a84
--- /dev/null
+++ b/ash/system/chromeos/tray_display_unittest.cc
@@ -0,0 +1,397 @@
+// 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/system/chromeos/tray_display.h"
+
+#include "ash/display/display_manager.h"
+#include "ash/root_window_controller.h"
+#include "ash/screen_ash.h"
+#include "ash/shell.h"
+#include "ash/system/tray/system_tray.h"
+#include "ash/system/tray/test_system_tray_delegate.h"
+#include "ash/test/ash_test_base.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "grit/ash_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/display.h"
+#include "ui/views/controls/label.h"
+
+namespace ash {
+namespace internal {
+
+base::string16 GetTooltipText(const base::string16& headline,
+ const base::string16& name1,
+ const std::string& data1,
+ const base::string16& name2,
+ const std::string& data2) {
+ std::vector<base::string16> lines;
+ lines.push_back(headline);
+ lines.push_back(l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY,
+ name1, UTF8ToUTF16(data1)));
+ if (!name2.empty()) {
+ lines.push_back(l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY,
+ name2, UTF8ToUTF16(data2)));
+ }
+ return JoinString(lines, '\n');
+}
+
+base::string16 GetFirstDisplayName() {
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ return UTF8ToUTF16(display_manager->GetDisplayNameForId(
+ display_manager->first_display_id()));
+}
+
+base::string16 GetSecondDisplayName() {
+ return UTF8ToUTF16(
+ Shell::GetInstance()->display_manager()->GetDisplayNameForId(
+ ScreenAsh::GetSecondaryDisplay().id()));
+}
+
+base::string16 GetMirroredDisplayName() {
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ return UTF8ToUTF16(display_manager->GetDisplayNameForId(
+ display_manager->mirrored_display().id()));
+}
+
+class TrayDisplayTest : public ash::test::AshTestBase {
+ public:
+ TrayDisplayTest();
+ virtual ~TrayDisplayTest();
+
+ virtual void SetUp() OVERRIDE;
+
+ protected:
+ SystemTray* tray() { return tray_; }
+
+ void CloseNotification();
+ bool IsDisplayVisibleInTray();
+ base::string16 GetTrayDisplayText();
+ base::string16 GetTrayDisplayTooltipText();
+ base::string16 GetDisplayNotificationText();
+
+ private:
+ // Weak reference, owned by Shell.
+ SystemTray* tray_;
+
+ // Weak reference, owned by |tray_|.
+ TrayDisplay* tray_display_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrayDisplayTest);
+};
+
+TrayDisplayTest::TrayDisplayTest() : tray_(NULL), tray_display_(NULL) {
+}
+
+TrayDisplayTest::~TrayDisplayTest() {
+}
+
+void TrayDisplayTest::SetUp() {
+ ash::test::AshTestBase::SetUp();
+ tray_ = Shell::GetPrimaryRootWindowController()->GetSystemTray();
+ tray_display_ = new TrayDisplay(tray_);
+ tray_->AddTrayItem(tray_display_);
+}
+
+void TrayDisplayTest::CloseNotification() {
+ tray_display_->CloseNotificationForTest();
+ RunAllPendingInMessageLoop();
+}
+
+bool TrayDisplayTest::IsDisplayVisibleInTray() {
+ return tray_display_->default_view() &&
+ tray_display_->default_view()->visible();
+}
+
+base::string16 TrayDisplayTest::GetTrayDisplayText() {
+ return tray_display_->GetDefaultViewMessage();
+}
+
+base::string16 TrayDisplayTest::GetTrayDisplayTooltipText() {
+ if (!tray_display_->default_view())
+ return base::string16();
+
+ base::string16 tooltip;
+ if (!tray_display_->default_view()->GetTooltipText(gfx::Point(), &tooltip))
+ return base::string16();
+ return tooltip;
+}
+
+base::string16 TrayDisplayTest::GetDisplayNotificationText() {
+ return tray_display_->GetNotificationMessage();
+}
+
+TEST_F(TrayDisplayTest, NoInternalDisplay) {
+ UpdateDisplay("400x400");
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_FALSE(IsDisplayVisibleInTray());
+
+ UpdateDisplay("400x400,200x200");
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+ base::string16 expected = l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL);
+ base::string16 first_name = GetFirstDisplayName();
+ EXPECT_EQ(expected, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(expected, GetFirstDisplayName(), "400x400",
+ GetSecondDisplayName(), "200x200"),
+ GetTrayDisplayTooltipText());
+
+ // mirroring
+ Shell::GetInstance()->display_manager()->SetSoftwareMirroring(true);
+ UpdateDisplay("400x400,200x200");
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+ expected = l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL);
+ EXPECT_EQ(expected, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(expected, GetFirstDisplayName(), "400x400",
+ GetMirroredDisplayName(), "200x200"),
+ GetTrayDisplayTooltipText());
+}
+
+TEST_F(TrayDisplayTest, InternalDisplay) {
+ UpdateDisplay("400x400");
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ gfx::Display::SetInternalDisplayId(display_manager->first_display_id());
+
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_FALSE(IsDisplayVisibleInTray());
+
+ // Extended
+ UpdateDisplay("400x400,200x200");
+ string16 expected = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName());
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+ EXPECT_EQ(expected, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(expected, GetFirstDisplayName(), "400x400",
+ GetSecondDisplayName(), "200x200"),
+ GetTrayDisplayTooltipText());
+
+ // Mirroring
+ display_manager->SetSoftwareMirroring(true);
+ UpdateDisplay("400x400,200x200");
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+
+ expected = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroredDisplayName());
+ EXPECT_EQ(expected, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(expected, GetFirstDisplayName(), "400x400",
+ GetMirroredDisplayName(), "200x200"),
+ GetTrayDisplayTooltipText());
+
+ // TODO(mukai): add test case for docked mode here.
+}
+
+TEST_F(TrayDisplayTest, InternalDisplayResized) {
+ UpdateDisplay("400x400@1.5");
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ gfx::Display::SetInternalDisplayId(display_manager->first_display_id());
+
+ // Shows the tray_display even though there's a single-display.
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+ base::string16 internal_info = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY,
+ GetFirstDisplayName(), UTF8ToUTF16("600x600"));
+ EXPECT_EQ(internal_info, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(base::string16(), GetFirstDisplayName(), "600x600",
+ base::string16(), std::string()),
+ GetTrayDisplayTooltipText());
+
+ // Extended
+ UpdateDisplay("400x400@1.5,200x200");
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+ base::string16 expected = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName());
+ EXPECT_EQ(expected, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(expected, GetFirstDisplayName(), "600x600",
+ GetSecondDisplayName(), "200x200"),
+ GetTrayDisplayTooltipText());
+
+ // Mirroring
+ display_manager->SetSoftwareMirroring(true);
+ UpdateDisplay("400x400@1.5,200x200");
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+ expected = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroredDisplayName());
+ EXPECT_EQ(expected, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(expected, GetFirstDisplayName(), "600x600",
+ GetMirroredDisplayName(), "200x200"),
+ GetTrayDisplayTooltipText());
+}
+
+TEST_F(TrayDisplayTest, ExternalDisplayResized) {
+ UpdateDisplay("400x400");
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ gfx::Display::SetInternalDisplayId(display_manager->first_display_id());
+
+ // Shows the tray_display even though there's a single-display.
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_FALSE(IsDisplayVisibleInTray());
+
+ // Extended
+ UpdateDisplay("400x400,200x200@1.5");
+ const gfx::Display& secondary_display = ScreenAsh::GetSecondaryDisplay();
+ base::string16 secondary_annotation = UTF8ToUTF16(
+ " (" + secondary_display.size().ToString() + ")");
+
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+ base::string16 expected = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED,
+ GetSecondDisplayName() + secondary_annotation);
+ EXPECT_EQ(expected, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(expected, GetFirstDisplayName(), "400x400",
+ GetSecondDisplayName(), "300x300"),
+ GetTrayDisplayTooltipText());
+
+ // Mirroring: in mirroring, it's not possible to lookup the DisplayInfo.
+ display_manager->SetSoftwareMirroring(true);
+ UpdateDisplay("400x400,200x200@1.5");
+ base::string16 mirror_name =
+ GetMirroredDisplayName() + UTF8ToUTF16(" (300x300)");
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+ expected = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, mirror_name);
+ EXPECT_EQ(expected, GetTrayDisplayText());
+ EXPECT_EQ(GetTooltipText(expected, GetFirstDisplayName(), "400x400",
+ GetMirroredDisplayName(), "300x300"),
+ GetTrayDisplayTooltipText());
+}
+
+TEST_F(TrayDisplayTest, OverscanDisplay) {
+ UpdateDisplay("400x400,300x300/o");
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ gfx::Display::SetInternalDisplayId(display_manager->first_display_id());
+
+ tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ EXPECT_TRUE(IsDisplayVisibleInTray());
+
+ // /o creates the default overscan, and if overscan is set, the annotation
+ // should be the size.
+ base::string16 size_annotation = UTF8ToUTF16(" (286x286)");
+ base::string16 overscan = l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN);
+ base::string16 headline = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED,
+ GetSecondDisplayName() + size_annotation);
+ std::string second_data = l10n_util::GetStringFUTF8(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION,
+ UTF8ToUTF16("286x286"), overscan);
+ EXPECT_EQ(GetTooltipText(headline, GetFirstDisplayName(), "400x400",
+ GetSecondDisplayName(), second_data),
+ GetTrayDisplayTooltipText());
+
+ // reset the overscan.
+ display_manager->SetOverscanInsets(
+ ScreenAsh::GetSecondaryDisplay().id(), gfx::Insets());
+ base::string16 overscan_annotation =
+ UTF8ToUTF16(" (") + overscan + UTF8ToUTF16(")");
+ headline = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED,
+ GetSecondDisplayName() + overscan_annotation);
+ second_data = l10n_util::GetStringFUTF8(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION,
+ UTF8ToUTF16("300x300"), overscan);
+ EXPECT_EQ(GetTooltipText(headline, GetFirstDisplayName(), "400x400",
+ GetSecondDisplayName(), second_data),
+ GetTrayDisplayTooltipText());
+}
+
+TEST_F(TrayDisplayTest, DisplayNotifications) {
+ test::TestSystemTrayDelegate* tray_delegate =
+ static_cast<test::TestSystemTrayDelegate*>(
+ Shell::GetInstance()->system_tray_delegate());
+ tray_delegate->set_should_show_display_notification(true);
+
+ UpdateDisplay("400x400");
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ gfx::Display::SetInternalDisplayId(display_manager->first_display_id());
+ EXPECT_TRUE(GetDisplayNotificationText().empty());
+
+ // rotation.
+ UpdateDisplay("400x400/r");
+ base::string16 rotation_message = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName());
+ EXPECT_EQ(rotation_message, GetDisplayNotificationText());
+
+ CloseNotification();
+ UpdateDisplay("400x400");
+ EXPECT_EQ(rotation_message, GetDisplayNotificationText());
+
+ // UI-scale
+ CloseNotification();
+ UpdateDisplay("400x400@1.5");
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
+ GetFirstDisplayName(), UTF8ToUTF16("600x600")),
+ GetDisplayNotificationText());
+
+ // UI-scale to 1.0
+ CloseNotification();
+ UpdateDisplay("400x400");
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
+ GetFirstDisplayName(), UTF8ToUTF16("400x400")),
+ GetDisplayNotificationText());
+
+ // No-update
+ CloseNotification();
+ UpdateDisplay("400x400");
+ EXPECT_TRUE(GetDisplayNotificationText().empty());
+
+ // Extended.
+ CloseNotification();
+ UpdateDisplay("400x400,200x200");
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName()),
+ GetDisplayNotificationText());
+
+ // Mirroring.
+ CloseNotification();
+ display_manager->SetSoftwareMirroring(true);
+ UpdateDisplay("400x400,200x200");
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroredDisplayName()),
+ GetDisplayNotificationText());
+
+ // Back to extended.
+ CloseNotification();
+ display_manager->SetSoftwareMirroring(false);
+ UpdateDisplay("400x400,200x200");
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName()),
+ GetDisplayNotificationText());
+
+ // Resize the first display.
+ UpdateDisplay("400x400@1.5,200x200");
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
+ GetFirstDisplayName(), UTF8ToUTF16("600x600")),
+ GetDisplayNotificationText());
+
+ // rotate the second.
+ UpdateDisplay("400x400@1.5,200x200/r");
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetSecondDisplayName()),
+ GetDisplayNotificationText());
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/system/date/date_view.cc b/ash/system/date/date_view.cc
index b044897..68789fc 100644
--- a/ash/system/date/date_view.cc
+++ b/ash/system/date/date_view.cc
@@ -10,7 +10,7 @@
#include "ash/system/tray/tray_utils.h"
#include "base/i18n/time_formatting.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "grit/ash_strings.h"
#include "third_party/icu/public/i18n/unicode/datefmt.h"
#include "third_party/icu/public/i18n/unicode/dtptngen.h"
diff --git a/ash/system/date/date_view.h b/ash/system/date/date_view.h
index 6809461..98bc45f 100644
--- a/ash/system/date/date_view.h
+++ b/ash/system/date/date_view.h
@@ -8,7 +8,7 @@
#include "ash/system/date/tray_date.h"
#include "ash/system/tray/actionable_view.h"
#include "base/i18n/time_formatting.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/views/view.h"
namespace views {
diff --git a/ash/system/date/tray_date.cc b/ash/system/date/tray_date.cc
index 0386b3b..0e245a8 100644
--- a/ash/system/date/tray_date.cc
+++ b/ash/system/date/tray_date.cc
@@ -17,8 +17,8 @@
#include "base/i18n/time_formatting.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "third_party/icu/public/i18n/unicode/datefmt.h"
diff --git a/ash/system/drive/tray_drive.h b/ash/system/drive/tray_drive.h
index 9680c99..6550fde 100644
--- a/ash/system/drive/tray_drive.h
+++ b/ash/system/drive/tray_drive.h
@@ -7,7 +7,7 @@
#include "ash/system/drive/drive_observer.h"
#include "ash/system/tray/tray_image_item.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
namespace views {
class Label;
diff --git a/ash/system/monitor/tray_monitor.h b/ash/system/monitor/tray_monitor.h
index 4f496c4..cd5734f 100644
--- a/ash/system/monitor/tray_monitor.h
+++ b/ash/system/monitor/tray_monitor.h
@@ -9,7 +9,7 @@
#include "ash/system/tray/system_tray_item.h"
#include "base/process.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
namespace views {
class Label;
diff --git a/ash/system/session_length_limit/tray_session_length_limit.h b/ash/system/session_length_limit/tray_session_length_limit.h
index 88d601d..1df4bb0 100644
--- a/ash/system/session_length_limit/tray_session_length_limit.h
+++ b/ash/system/session_length_limit/tray_session_length_limit.h
@@ -10,8 +10,8 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
namespace ash {
namespace internal {
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc
index 1430bd1..471e885 100644
--- a/ash/system/status_area_widget.cc
+++ b/ash/system/status_area_widget.cc
@@ -35,7 +35,7 @@
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.delegate = status_area_widget_delegate_;
params.parent = status_container;
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
Init(params);
set_focus_on_creation(false);
SetContentsView(status_area_widget_delegate_);
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index eb183ec..a766c2e 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -31,7 +31,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "grit/ash_strings.h"
#include "ui/aura/root_window.h"
#include "ui/base/events/event_constants.h"
@@ -58,6 +58,7 @@
#include "ash/system/chromeos/screen_security/screen_share_tray_item.h"
#include "ash/system/chromeos/settings/tray_settings.h"
#include "ash/system/chromeos/tray_display.h"
+#include "ui/message_center/message_center.h"
#endif
using views::TrayBubbleView;
@@ -120,7 +121,8 @@
: internal::TrayBackgroundView(status_area_widget),
items_(),
default_bubble_height_(0),
- hide_notifications_(false) {
+ hide_notifications_(false),
+ tray_accessibility_(NULL) {
SetContentsBackground();
}
@@ -164,7 +166,8 @@
tray_accessibility_ = new internal::TrayAccessibility(this);
AddTrayItem(tray_accessibility_);
#if defined(OS_CHROMEOS)
- AddTrayItem(new internal::TrayPower(this));
+ AddTrayItem(
+ new internal::TrayPower(this, message_center::MessageCenter::Get()));
#endif
#if defined(OS_CHROMEOS)
AddTrayItem(new internal::TrayNetwork(this));
@@ -221,6 +224,10 @@
NOTIMPLEMENTED();
}
+const std::vector<SystemTrayItem*>& SystemTray::GetTrayItems() const {
+ return items_.get();
+}
+
void SystemTray::ShowDefaultView(BubbleCreationType creation_type) {
ShowDefaultViewWithOffset(creation_type,
TrayBubbleView::InitParams::kArrowDefaultOffset);
diff --git a/ash/system/tray/system_tray.h b/ash/system/tray/system_tray.h
index 1a6b6fa..1dc4d34 100644
--- a/ash/system/tray/system_tray.h
+++ b/ash/system/tray/system_tray.h
@@ -70,6 +70,9 @@
// Removes an existing tray item.
void RemoveTrayItem(SystemTrayItem* item);
+ // Returns all tray items that has been added to system tray.
+ const std::vector<SystemTrayItem*>& GetTrayItems() const;
+
// Shows the default view of all items.
void ShowDefaultView(BubbleCreationType creation_type);
diff --git a/ash/system/tray/system_tray_bubble.h b/ash/system/tray/system_tray_bubble.h
index 73edaac..61b1543 100644
--- a/ash/system/tray/system_tray_bubble.h
+++ b/ash/system/tray/system_tray_bubble.h
@@ -8,7 +8,7 @@
#include "ash/system/user/login_status.h"
#include "base/base_export.h"
#include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/views/bubble/tray_bubble_view.h"
#include <vector>
diff --git a/ash/system/tray/system_tray_delegate.h b/ash/system/tray/system_tray_delegate.h
index 847ff8c..ee60831 100644
--- a/ash/system/tray/system_tray_delegate.h
+++ b/ash/system/tray/system_tray_delegate.h
@@ -139,6 +139,9 @@
// Returns the email of user that manages current locally managed user.
virtual const std::string GetLocallyManagedUserManager() const = 0;
+ // Returns the email of user that manages current locally managed user.
+ virtual const base::string16 GetLocallyManagedUserManagerName() const = 0;
+
// Returns notification for locally managed users.
virtual const base::string16 GetLocallyManagedUserMessage() const = 0;
@@ -164,6 +167,10 @@
// Shows settings related to multiple displays.
virtual void ShowDisplaySettings() = 0;
+ // Returns true if the notification for the display configuration change
+ // should appear.
+ virtual bool ShouldShowDisplayNotification() = 0;
+
// Shows settings related to Google Drive.
virtual void ShowDriveSettings() = 0;
diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc
index 936b29e..6d0b4d9 100644
--- a/ash/system/tray/system_tray_unittest.cc
+++ b/ash/system/tray/system_tray_unittest.cc
@@ -156,6 +156,13 @@
tray->AddTrayItem(test_item);
tray->AddTrayItem(detailed_item);
+ // Check items have been added
+ const std::vector<SystemTrayItem*>& items = tray->GetTrayItems();
+ ASSERT_TRUE(
+ std::find(items.begin(), items.end(), test_item) != items.end());
+ ASSERT_TRUE(
+ std::find(items.begin(), items.end(), detailed_item) != items.end());
+
// Ensure the tray views are created.
ASSERT_TRUE(test_item->tray_view() != NULL);
ASSERT_TRUE(detailed_item->tray_view() != NULL);
diff --git a/ash/system/tray/test_system_tray_delegate.cc b/ash/system/tray/test_system_tray_delegate.cc
index c2eb2df..17742ba 100644
--- a/ash/system/tray/test_system_tray_delegate.cc
+++ b/ash/system/tray/test_system_tray_delegate.cc
@@ -10,7 +10,7 @@
#include "ash/shell.h"
#include "ash/volume_control_delegate.h"
#include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
namespace ash {
namespace test {
@@ -53,6 +53,7 @@
TestSystemTrayDelegate::TestSystemTrayDelegate()
: bluetooth_enabled_(true),
caps_lock_enabled_(false),
+ should_show_display_notification_(false),
volume_control_delegate_(new TestVolumeControlDelegate) {
}
@@ -104,6 +105,11 @@
return std::string();
}
+const base::string16 TestSystemTrayDelegate::GetLocallyManagedUserManagerName()
+ const {
+ return string16();
+}
+
const base::string16 TestSystemTrayDelegate::GetLocallyManagedUserMessage()
const {
return string16();
@@ -133,6 +139,10 @@
void TestSystemTrayDelegate::ShowDisplaySettings() {
}
+bool TestSystemTrayDelegate::ShouldShowDisplayNotification() {
+ return should_show_display_notification_;
+}
+
void TestSystemTrayDelegate::ShowDriveSettings() {
}
diff --git a/ash/system/tray/test_system_tray_delegate.h b/ash/system/tray/test_system_tray_delegate.h
index 27ee734..56cb078 100644
--- a/ash/system/tray/test_system_tray_delegate.h
+++ b/ash/system/tray/test_system_tray_delegate.h
@@ -32,6 +32,8 @@
virtual const std::string GetEnterpriseDomain() const OVERRIDE;
virtual const base::string16 GetEnterpriseMessage() const OVERRIDE;
virtual const std::string GetLocallyManagedUserManager() const OVERRIDE;
+ virtual const base::string16 GetLocallyManagedUserManagerName() const
+ OVERRIDE;
virtual const base::string16 GetLocallyManagedUserMessage() const OVERRIDE;
virtual bool SystemShouldUpgrade() const OVERRIDE;
virtual base::HourClockType GetHourClockType() const OVERRIDE;
@@ -40,6 +42,7 @@
virtual void ShowNetworkSettings(const std::string& service_path) OVERRIDE;
virtual void ShowBluetoothSettings() OVERRIDE;
virtual void ShowDisplaySettings() OVERRIDE;
+ virtual bool ShouldShowDisplayNotification() OVERRIDE;
virtual void ShowDriveSettings() OVERRIDE;
virtual void ShowIMESettings() OVERRIDE;
virtual void ShowHelp() OVERRIDE;
@@ -93,9 +96,14 @@
const base::TimeDelta& delta) const OVERRIDE;
virtual void MaybeSpeak(const std::string& utterance) const OVERRIDE;
+ void set_should_show_display_notification(bool should_show) {
+ should_show_display_notification_ = should_show;
+ }
+
private:
bool bluetooth_enabled_;
bool caps_lock_enabled_;
+ bool should_show_display_notification_;
scoped_ptr<VolumeControlDelegate> volume_control_delegate_;
DISALLOW_COPY_AND_ASSIGN(TestSystemTrayDelegate);
diff --git a/ash/system/tray/tray_item_view.cc b/ash/system/tray/tray_item_view.cc
index 632dcbf..f95ceb9 100644
--- a/ash/system/tray/tray_item_view.cc
+++ b/ash/system/tray/tray_item_view.cc
@@ -18,6 +18,9 @@
const int kTrayIconHeight = 29;
const int kTrayIconWidth = 29;
const int kTrayItemAnimationDurationMS = 200;
+
+// Animations can be disabled for testing.
+bool animations_enabled = true;
}
namespace ash {
@@ -35,6 +38,11 @@
TrayItemView::~TrayItemView() {}
+// static
+void TrayItemView::DisableAnimationsForTest() {
+ animations_enabled = false;
+}
+
void TrayItemView::CreateLabel() {
label_ = new views::Label;
AddChildView(label_);
@@ -46,7 +54,7 @@
}
void TrayItemView::SetVisible(bool set_visible) {
- if (!GetWidget()) {
+ if (!GetWidget() || !animations_enabled) {
views::View::SetVisible(set_visible);
return;
}
diff --git a/ash/system/tray/tray_item_view.h b/ash/system/tray/tray_item_view.h
index ca260cf..e0d8ec4 100644
--- a/ash/system/tray/tray_item_view.h
+++ b/ash/system/tray/tray_item_view.h
@@ -5,6 +5,7 @@
#ifndef ASH_SYSTEM_TRAY_TRAY_ITEM_VIEW_H_
#define ASH_SYSTEM_TRAY_TRAY_ITEM_VIEW_H_
+#include "ash/ash_export.h"
#include "ui/base/animation/animation_delegate.h"
#include "ui/views/view.h"
@@ -26,12 +27,14 @@
// Base-class for items in the tray. It makes sure the widget is updated
// correctly when the visibility/size of the tray item changes. It also adds
// animation when showing/hiding the item in the tray.
-class TrayItemView : public views::View,
- public ui::AnimationDelegate {
+class ASH_EXPORT TrayItemView : public views::View,
+ public ui::AnimationDelegate {
public:
explicit TrayItemView(SystemTrayItem* owner);
virtual ~TrayItemView();
+ static void DisableAnimationsForTest();
+
// Convenience function for creating a child Label or ImageView.
void CreateLabel();
void CreateImageView();
diff --git a/ash/system/tray/tray_notification_view.h b/ash/system/tray/tray_notification_view.h
index 403beca..314b8aa 100644
--- a/ash/system/tray/tray_notification_view.h
+++ b/ash/system/tray/tray_notification_view.h
@@ -3,9 +3,9 @@
// found in the LICENSE file.
#ifndef ASH_SYSTEM_TRAY_TRAY_NOTIFICATION_VIEW_H_
-#define ASH_SYSTEM_TRAY_TRAY_NOTIFICATION_VIEWS_H_
+#define ASH_SYSTEM_TRAY_TRAY_NOTIFICATION_VIEW_H_
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/slide_out_view.h"
@@ -95,4 +95,4 @@
} // namespace internal
} // namespace ash
-#endif // ASH_SYSTEM_TRAY_TRAY_NOTIFICATION_VIEWS_H_
+#endif // ASH_SYSTEM_TRAY_TRAY_NOTIFICATION_VIEW_H_
diff --git a/ash/system/tray_update.cc b/ash/system/tray_update.cc
index e998cc7..e01dd97 100644
--- a/ash/system/tray_update.cc
+++ b/ash/system/tray_update.cc
@@ -14,8 +14,8 @@
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/tray/tray_constants.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "ui/aura/window.h"
diff --git a/ash/system/user/tray_user.cc b/ash/system/user/tray_user.cc
index 1566371..10c07bd 100644
--- a/ash/system/user/tray_user.cc
+++ b/ash/system/user/tray_user.cc
@@ -694,6 +694,7 @@
// between the two.
remaining_width -= kTrayPopupPaddingBetweenItems;
}
+ user_card_area.set_width(remaining_width);
user_card_view_->SetBoundsRect(user_card_area);
logout_button_->SetBoundsRect(logout_area);
} else if (user_card_view_) {
@@ -809,22 +810,28 @@
views::Label* username = NULL;
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
if (!multiprofile_index_) {
- username = new views::Label(
+ base::string16 user_name_string =
login == ash::user::LOGGED_IN_GUEST ?
bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_GUEST_LABEL) :
- delegate->GetUserDisplayName(multiprofile_index_));
- username->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ delegate->GetUserDisplayName(multiprofile_index_);
+ if (!user_name_string.empty()) {
+ username = new views::Label(user_name_string);
+ username->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ }
}
views::Label* additional = NULL;
if (login != ash::user::LOGGED_IN_GUEST) {
- additional = new views::Label();
- additional->SetText(login == ash::user::LOGGED_IN_LOCALLY_MANAGED ?
- bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOCALLY_MANAGED_LABEL) :
- UTF8ToUTF16(delegate->GetUserEmail(multiprofile_index_)));
-
- additional->SetFont(bundle.GetFont(ui::ResourceBundle::SmallFont));
- additional->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ base::string16 user_email_string =
+ login == ash::user::LOGGED_IN_LOCALLY_MANAGED ?
+ bundle.GetLocalizedString(
+ IDS_ASH_STATUS_TRAY_LOCALLY_MANAGED_LABEL) :
+ UTF8ToUTF16(delegate->GetUserEmail(multiprofile_index_));
+ if (!user_email_string.empty()) {
+ additional = new views::Label(user_email_string);
+ additional->SetFont(bundle.GetFont(ui::ResourceBundle::SmallFont));
+ additional->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ }
}
// Adjust text properties dependent on if it is an active or inactive user.
@@ -910,7 +917,7 @@
params.context = this->GetWidget()->GetNativeWindow();
params.accept_events = true;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
add_menu_option_->Init(params);
add_menu_option_->SetOpacity(0xFF);
add_menu_option_->GetNativeWindow()->set_owned_by_parent(false);
diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc
index 9579442..7569509 100644
--- a/ash/system/web_notification/web_notification_tray.cc
+++ b/ash/system/web_notification/web_notification_tray.cc
@@ -198,18 +198,17 @@
// Public methods.
-bool WebNotificationTray::ShowMessageCenter() {
+bool WebNotificationTray::ShowMessageCenterInternal(bool show_settings) {
if (!ShouldShowMessageCenter())
return false;
should_block_shelf_auto_hide_ = true;
message_center::MessageCenterBubble* message_center_bubble =
- new message_center::MessageCenterBubble(message_center());
+ new message_center::MessageCenterBubble(message_center(),
+ message_center_tray_.get());
- // TODO(mukai): move this to WebNotificationBubbleWrapper if it's safe
- // to set the height of the popup.
int max_height = 0;
- aura::Window* status_area_window = status_area_widget()->GetNativeWindow();
+ aura::Window* status_area_window = status_area_widget()->GetNativeView();
switch (GetShelfLayoutManager()->GetAlignment()) {
case SHELF_ALIGNMENT_BOTTOM: {
gfx::Rect shelf_bounds = GetShelfLayoutManager()->GetIdealBounds();
@@ -232,8 +231,10 @@
default:
NOTREACHED();
}
- max_height = std::max(0, max_height - kTraySpacing);
- message_center_bubble->SetMaxHeight(max_height);
+
+ message_center_bubble->SetMaxHeight(std::max(0, max_height - kTraySpacing));
+ if (show_settings)
+ message_center_bubble->SetSettingsVisible();
message_center_bubble_.reset(
new internal::WebNotificationBubbleWrapper(this, message_center_bubble));
@@ -243,6 +244,10 @@
return true;
}
+bool WebNotificationTray::ShowMessageCenter() {
+ return ShowMessageCenterInternal(false /* show_settings */);
+}
+
void WebNotificationTray::HideMessageCenter() {
if (!message_center_bubble())
return;
@@ -274,7 +279,8 @@
ash::Shell::GetContainer(
GetWidget()->GetNativeView()->GetRootWindow(),
internal::kShellWindowId_StatusContainer),
- message_center()));
+ message_center(),
+ message_center_tray_.get()));
} else {
message_center::MessagePopupBubble* popup_bubble =
new message_center::MessagePopupBubble(message_center());
@@ -454,6 +460,15 @@
HideBubbleWithView(bubble_view);
}
+bool WebNotificationTray::ShowNotifierSettings() {
+ if (message_center_bubble()) {
+ static_cast<message_center::MessageCenterBubble*>(
+ message_center_bubble()->bubble())->SetSettingsVisible();
+ return true;
+ }
+ return ShowMessageCenterInternal(true /* show_settings */);
+}
+
void WebNotificationTray::ButtonPressed(views::Button* sender,
const ui::Event& event) {
DCHECK_EQ(button_, sender);
@@ -490,9 +505,10 @@
}
bool WebNotificationTray::ClickedOutsideBubble() {
- // Only hide the message center.
+ // Only hide the message center
if (!message_center_bubble())
return false;
+
message_center_tray_->HideMessageCenterBubble();
return true;
}
diff --git a/ash/system/web_notification/web_notification_tray.h b/ash/system/web_notification/web_notification_tray.h
index df7a663..999657e 100644
--- a/ash/system/web_notification/web_notification_tray.h
+++ b/ash/system/web_notification/web_notification_tray.h
@@ -106,6 +106,7 @@
virtual bool ShowPopups() OVERRIDE;
virtual void UpdatePopups() OVERRIDE;
virtual void HidePopups() OVERRIDE;
+ virtual bool ShowNotifierSettings() OVERRIDE;
message_center::MessageCenter* message_center();
@@ -118,6 +119,11 @@
void UpdateTrayContent();
+ // The actual process to show the message center. Set |show_settings| to true
+ // if the message center should be initialized with the settings visible.
+ // Returns true if the center is successfully created.
+ bool ShowMessageCenterInternal(bool show_settings);
+
// Queries login status and the status area widget to determine visibility of
// the message center.
bool ShouldShowMessageCenter();
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc
index 8e93f27..95b8d99 100644
--- a/ash/test/ash_test_base.cc
+++ b/ash/test/ash_test_base.cc
@@ -30,6 +30,10 @@
#include "ui/gfx/point.h"
#include "ui/gfx/screen.h"
+#if defined(OS_CHROMEOS)
+#include "ash/system/chromeos/tray_display.h"
+#endif
+
#if defined(OS_WIN)
#include "ash/test/test_metro_viewer_process_host.h"
#include "base/test/test_process_killer_win.h"
@@ -124,8 +128,7 @@
ipc_thread_->StartWithOptions(options);
metro_viewer_host_.reset(
- new TestMetroViewerProcessHost("viewer",
- ipc_thread_->message_loop_proxy()));
+ new TestMetroViewerProcessHost(ipc_thread_->message_loop_proxy()));
CHECK(metro_viewer_host_->LaunchViewerAndWaitForConnection(
win8::test::kDefaultTestAppUserModelId));
aura::RemoteRootWindowHostWin* root_window_host =
@@ -189,6 +192,15 @@
#endif
}
+// static
+bool AshTestBase::SupportsHostWindowResize() {
+#if defined(OS_WIN)
+ return base::win::GetVersion() < base::win::VERSION_WIN8;
+#else
+ return true;
+#endif
+}
+
void AshTestBase::UpdateDisplay(const std::string& display_specs) {
DisplayManagerTestApi display_manager_test_api(
Shell::GetInstance()->display_manager());
diff --git a/ash/test/ash_test_base.h b/ash/test/ash_test_base.h
index 53c2e50..69564b0 100644
--- a/ash/test/ash_test_base.h
+++ b/ash/test/ash_test_base.h
@@ -99,6 +99,10 @@
// or false otherwise (e.g. win8 bot).
static bool SupportsMultipleDisplays();
+ // True if the running environment supports host window resize,
+ // or false otherwise (e.g. win8 bot).
+ static bool SupportsHostWindowResize();
+
void RunAllPendingInMessageLoop();
// Utility methods to emulate user logged in or not, session started or not
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 17a3cc7..84d28c5 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -8,6 +8,7 @@
#include "ash/shell.h"
#include "ash/test/display_manager_test_api.h"
#include "ash/test/shell_test_api.h"
+#include "ash/test/test_session_state_delegate.h"
#include "ash/test/test_shell_delegate.h"
#include "base/run_loop.h"
#include "ui/aura/env.h"
@@ -17,7 +18,6 @@
#if defined(OS_CHROMEOS)
#include "chromeos/audio/cras_audio_handler.h"
-#include "chromeos/power/power_manager_handler.h"
#endif
#if defined(USE_X11)
@@ -58,15 +58,17 @@
// created in AshTestBase tests.
chromeos::CrasAudioHandler::InitializeForTesting();
}
- chromeos::PowerManagerHandler::Initialize();
#endif
ash::Shell::CreateInstance(test_shell_delegate_);
Shell* shell = Shell::GetInstance();
+ test_shell_delegate_->test_session_state_delegate()->
+ SetActiveUserSessionStarted(true);
+ test_shell_delegate_->test_session_state_delegate()->SetHasActiveUser(true);
+
test::DisplayManagerTestApi(shell->display_manager()).
DisableChangeDisplayUponHostResize();
ShellTestApi(shell).DisableOutputConfiguratorAnimation();
-
}
void AshTestHelper::TearDown() {
@@ -79,7 +81,6 @@
#if defined(OS_CHROMEOS)
if (ash::switches::UseNewAudioHandler())
chromeos::CrasAudioHandler::Shutdown();
- chromeos::PowerManagerHandler::Shutdown();
#endif
aura::Env::DeleteInstance();
diff --git a/ash/test/test_metro_viewer_process_host.cc b/ash/test/test_metro_viewer_process_host.cc
index 3819d35..a788da9 100644
--- a/ash/test/test_metro_viewer_process_host.cc
+++ b/ash/test/test_metro_viewer_process_host.cc
@@ -4,30 +4,18 @@
#include "ash/test/test_metro_viewer_process_host.h"
-#include <shellapi.h>
-#include <shlobj.h>
+#include <windef.h>
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/strings/string16.h"
-#include "base/time.h"
-#include "base/win/scoped_com_initializer.h"
-#include "base/win/scoped_comptr.h"
-#include "ipc/ipc_channel_proxy.h"
-#include "ipc/ipc_message_macros.h"
+#include "base/logging.h"
#include "ui/aura/remote_root_window_host_win.h"
-#include "ui/metro_viewer/metro_viewer_messages.h"
#include "ui/surface/accelerated_surface_win.h"
namespace ash {
namespace test {
TestMetroViewerProcessHost::TestMetroViewerProcessHost(
- const std::string& ipc_channel_name,
base::SingleThreadTaskRunner* ipc_task_runner)
- : MetroViewerProcessHost(ipc_channel_name, ipc_task_runner),
- closed_unexpectedly_(false) {
+ : MetroViewerProcessHost(ipc_task_runner), closed_unexpectedly_(false) {
}
TestMetroViewerProcessHost::~TestMetroViewerProcessHost() {
@@ -43,7 +31,7 @@
DLOG(INFO) << __FUNCTION__ << ", target_surface = " << target_surface;
HWND hwnd = reinterpret_cast<HWND>(target_surface);
- backing_surface.reset(new AcceleratedSurface(hwnd));
+ backing_surface_.reset(new AcceleratedSurface(hwnd));
scoped_refptr<AcceleratedPresenter> any_window =
AcceleratedPresenter::GetForWindow(NULL);
diff --git a/ash/test/test_metro_viewer_process_host.h b/ash/test/test_metro_viewer_process_host.h
index 63ca815..e6d0a64 100644
--- a/ash/test/test_metro_viewer_process_host.h
+++ b/ash/test/test_metro_viewer_process_host.h
@@ -5,8 +5,7 @@
#ifndef ASH_TEST_TEST_METRO_VIEWER_PROCESS_HOST_H_
#define ASH_TEST_TEST_METRO_VIEWER_PROCESS_HOST_H_
-#include <string>
-
+#include "base/memory/scoped_ptr.h"
#include "win8/viewer/metro_viewer_process_host.h"
class AcceleratedSurface;
@@ -16,8 +15,7 @@
class TestMetroViewerProcessHost : public win8::MetroViewerProcessHost {
public:
- TestMetroViewerProcessHost(const std::string& ipc_channel_name,
- base::SingleThreadTaskRunner* ipc_task_runner);
+ TestMetroViewerProcessHost(base::SingleThreadTaskRunner* ipc_task_runner);
virtual ~TestMetroViewerProcessHost();
bool closed_unexpectedly() { return closed_unexpectedly_; }
@@ -29,7 +27,7 @@
virtual void OnOpenURL(const string16& url) OVERRIDE;
virtual void OnHandleSearchRequest(const string16& search_string) OVERRIDE;
- scoped_ptr<AcceleratedSurface> backing_surface;
+ scoped_ptr<AcceleratedSurface> backing_surface_;
bool closed_unexpectedly_;
diff --git a/ash/test/test_session_state_delegate.cc b/ash/test/test_session_state_delegate.cc
index a8ee01e..7af9e3c 100644
--- a/ash/test/test_session_state_delegate.cc
+++ b/ash/test/test_session_state_delegate.cc
@@ -4,6 +4,8 @@
#include "ash/test/test_session_state_delegate.h"
+#include "ash/shell.h"
+#include "ash/system/user/login_status.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
@@ -11,8 +13,8 @@
namespace test {
TestSessionStateDelegate::TestSessionStateDelegate()
- : has_active_user_(true),
- active_user_session_started_(true),
+ : has_active_user_(false),
+ active_user_session_started_(false),
can_lock_screen_(true),
screen_locked_(false),
logged_in_users_(1) {
@@ -55,13 +57,19 @@
has_active_user_ = has_active_user;
if (!has_active_user)
active_user_session_started_ = false;
+ else
+ Shell::GetInstance()->ShowLauncher();
}
void TestSessionStateDelegate::SetActiveUserSessionStarted(
bool active_user_session_started) {
active_user_session_started_ = active_user_session_started;
- if (active_user_session_started)
+ if (active_user_session_started) {
has_active_user_ = true;
+ Shell::GetInstance()->CreateLauncher();
+ Shell::GetInstance()->UpdateAfterLoginStatusChange(
+ user::LOGGED_IN_USER);
+ }
}
void TestSessionStateDelegate::SetCanLockScreen(bool can_lock_screen) {
@@ -69,12 +77,12 @@
}
const base::string16 TestSessionStateDelegate::GetUserDisplayName(
- ash::MultiProfileIndex index) const {
+ MultiProfileIndex index) const {
return UTF8ToUTF16("Über tray Über tray Über tray Über tray");
}
const std::string TestSessionStateDelegate::GetUserEmail(
- ash::MultiProfileIndex index) const {
+ MultiProfileIndex index) const {
switch (index) {
case 0: return "first@tray";
case 1: return "second@tray";
@@ -84,7 +92,7 @@
}
const gfx::ImageSkia& TestSessionStateDelegate::GetUserImage(
- ash::MultiProfileIndex index) const {
+ MultiProfileIndex index) const {
return null_image_;
}
@@ -96,11 +104,11 @@
}
void TestSessionStateDelegate::AddSessionStateObserver(
- ash::SessionStateObserver* observer) {
+ SessionStateObserver* observer) {
}
void TestSessionStateDelegate::RemoveSessionStateObserver(
- ash::SessionStateObserver* observer) {
+ SessionStateObserver* observer) {
}
} // namespace test
diff --git a/ash/test/test_session_state_delegate.h b/ash/test/test_session_state_delegate.h
index 17062d5..f9466ff 100644
--- a/ash/test/test_session_state_delegate.h
+++ b/ash/test/test_session_state_delegate.h
@@ -42,6 +42,8 @@
virtual void RemoveSessionStateObserver(
ash::SessionStateObserver* observer) OVERRIDE;
+ // TODO(oshima): Use state machine instead of using boolean variables.
+
// Updates the internal state that indicates whether a session is in progress
// and there is an active user. If |has_active_user| is |false|,
// |active_user_session_started_| is reset to |false| as well (see below for
diff --git a/ash/test/test_suite_init.mm b/ash/test/test_suite_init.mm
index 1564c38..c32df2b 100644
--- a/ash/test/test_suite_init.mm
+++ b/ash/test/test_suite_init.mm
@@ -8,7 +8,6 @@
#include "base/files/file_path.h"
#include "base/mac/bundle_locations.h"
-#include "base/memory/scoped_nsobject.h"
#include "base/path_service.h"
namespace ash {
diff --git a/ash/tooltips/tooltip_controller_unittest.cc b/ash/tooltips/tooltip_controller_unittest.cc
index ff894c8..8cf0daf 100644
--- a/ash/tooltips/tooltip_controller_unittest.cc
+++ b/ash/tooltips/tooltip_controller_unittest.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ash/display/display_controller.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/ash/touch/touch_hud_debug.cc b/ash/touch/touch_hud_debug.cc
new file mode 100644
index 0000000..5b7c120
--- /dev/null
+++ b/ash/touch/touch_hud_debug.cc
@@ -0,0 +1,491 @@
+// 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/touch/touch_hud_debug.h"
+
+#include "ash/display/display_manager.h"
+#include "ash/root_window_controller.h"
+#include "ash/shell.h"
+#include "ash/wm/property_util.h"
+#include "base/json/json_string_value_serializer.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "ui/aura/root_window.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/events/event.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/size.h"
+#include "ui/gfx/transform.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/widget/widget.h"
+
+#if defined(USE_X11)
+#include <X11/extensions/XInput2.h>
+#include <X11/Xlib.h>
+
+#include "ui/base/x/device_data_manager.h"
+#endif
+
+namespace ash {
+namespace internal {
+
+const int kPointRadius = 20;
+const SkColor kColors[] = {
+ SK_ColorYELLOW,
+ SK_ColorGREEN,
+ SK_ColorRED,
+ SK_ColorBLUE,
+ SK_ColorGRAY,
+ SK_ColorMAGENTA,
+ SK_ColorCYAN,
+ SK_ColorWHITE,
+ SK_ColorBLACK,
+ SkColorSetRGB(0xFF, 0x8C, 0x00),
+ SkColorSetRGB(0x8B, 0x45, 0x13),
+ SkColorSetRGB(0xFF, 0xDE, 0xAD),
+};
+const int kAlpha = 0x60;
+const int kMaxPaths = arraysize(kColors);
+const int kReducedScale = 10;
+
+const char* GetTouchEventLabel(ui::EventType type) {
+ switch (type) {
+ case ui::ET_UNKNOWN:
+ return " ";
+ case ui::ET_TOUCH_PRESSED:
+ return "P";
+ case ui::ET_TOUCH_MOVED:
+ return "M";
+ case ui::ET_TOUCH_RELEASED:
+ return "R";
+ case ui::ET_TOUCH_CANCELLED:
+ return "C";
+ default:
+ break;
+ }
+ return "?";
+}
+
+int GetTrackingId(const ui::TouchEvent& event) {
+ if (!event.HasNativeEvent())
+ return 0;
+#if defined(USE_XI2_MT)
+ ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
+ double tracking_id;
+ if (manager->GetEventData(*event.native_event(),
+ ui::DeviceDataManager::DT_TOUCH_TRACKING_ID,
+ &tracking_id)) {
+ return static_cast<int>(tracking_id);
+ }
+#endif
+ return 0;
+}
+
+int GetSourceDeviceId(const ui::TouchEvent& event) {
+ if (!event.HasNativeEvent())
+ return 0;
+#if defined(USE_X11)
+ XEvent* xev = event.native_event();
+ return static_cast<XIDeviceEvent*>(xev->xcookie.data)->sourceid;
+#endif
+ return 0;
+}
+
+// A TouchPointLog represents a single touch-event of a touch point.
+struct TouchPointLog {
+ public:
+ explicit TouchPointLog(const ui::TouchEvent& touch)
+ : id(touch.touch_id()),
+ type(touch.type()),
+ location(touch.root_location()),
+ timestamp(touch.time_stamp().InMillisecondsF()),
+ radius_x(touch.radius_x()),
+ radius_y(touch.radius_y()),
+ pressure(touch.force()),
+ tracking_id(GetTrackingId(touch)),
+ source_device(GetSourceDeviceId(touch)) {
+ }
+
+ // Populates a dictionary value with all the information about the touch
+ // point.
+ scoped_ptr<DictionaryValue> GetAsDictionary() const {
+ scoped_ptr<DictionaryValue> value(new DictionaryValue());
+
+ value->SetInteger("id", id);
+ value->SetString("type", std::string(GetTouchEventLabel(type)));
+ value->SetString("location", location.ToString());
+ value->SetDouble("timestamp", timestamp);
+ value->SetDouble("radius_x", radius_x);
+ value->SetDouble("radius_y", radius_y);
+ value->SetDouble("pressure", pressure);
+ value->SetInteger("tracking_id", tracking_id);
+ value->SetInteger("source_device", source_device);
+
+ return value.Pass();
+ }
+
+ int id;
+ ui::EventType type;
+ gfx::Point location;
+ double timestamp;
+ float radius_x;
+ float radius_y;
+ float pressure;
+ int tracking_id;
+ int source_device;
+};
+
+// A TouchTrace keeps track of all the touch events of a single touch point
+// (starting from a touch-press and ending at a touch-release or touch-cancel).
+class TouchTrace {
+ public:
+ typedef std::vector<TouchPointLog>::iterator iterator;
+ typedef std::vector<TouchPointLog>::const_iterator const_iterator;
+ typedef std::vector<TouchPointLog>::reverse_iterator reverse_iterator;
+ typedef std::vector<TouchPointLog>::const_reverse_iterator
+ const_reverse_iterator;
+
+ TouchTrace() {
+ }
+
+ void AddTouchPoint(const ui::TouchEvent& touch) {
+ log_.push_back(TouchPointLog(touch));
+ }
+
+ const std::vector<TouchPointLog>& log() const { return log_; }
+
+ bool active() const {
+ return !log_.empty() && log_.back().type != ui::ET_TOUCH_RELEASED &&
+ log_.back().type != ui::ET_TOUCH_CANCELLED;
+ }
+
+ // Returns a list containing data from all events for the touch point.
+ scoped_ptr<ListValue> GetAsList() const {
+ scoped_ptr<ListValue> list(new ListValue());
+ for (const_iterator i = log_.begin(); i != log_.end(); ++i)
+ list->Append((*i).GetAsDictionary().release());
+ return list.Pass();
+ }
+
+ void Reset() {
+ log_.clear();
+ }
+
+ private:
+ std::vector<TouchPointLog> log_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchTrace);
+};
+
+// A TouchLog keeps track of all touch events of all touch points.
+class TouchLog {
+ public:
+ TouchLog() : next_trace_index_(0) {
+ }
+
+ void AddTouchPoint(const ui::TouchEvent& touch) {
+ if (touch.type() == ui::ET_TOUCH_PRESSED)
+ StartTrace(touch);
+ AddToTrace(touch);
+ }
+
+ void Reset() {
+ next_trace_index_ = 0;
+ for (int i = 0; i < kMaxPaths; ++i)
+ traces_[i].Reset();
+ }
+
+ scoped_ptr<ListValue> GetAsList() const {
+ scoped_ptr<ListValue> list(new ListValue());
+ for (int i = 0; i < kMaxPaths; ++i) {
+ if (!traces_[i].log().empty())
+ list->Append(traces_[i].GetAsList().release());
+ }
+ return list.Pass();
+ }
+
+ int GetTraceIndex(int touch_id) const {
+ return touch_id_to_trace_index_.at(touch_id);
+ }
+
+ const TouchTrace* traces() const {
+ return traces_;
+ }
+
+ private:
+ void StartTrace(const ui::TouchEvent& touch) {
+ // Find the first inactive spot; otherwise, overwrite the one
+ // |next_trace_index_| is pointing to.
+ int old_trace_index = next_trace_index_;
+ do {
+ if (!traces_[next_trace_index_].active())
+ break;
+ next_trace_index_ = (next_trace_index_ + 1) % kMaxPaths;
+ } while (next_trace_index_ != old_trace_index);
+ int touch_id = touch.touch_id();
+ traces_[next_trace_index_].Reset();
+ touch_id_to_trace_index_[touch_id] = next_trace_index_;
+ next_trace_index_ = (next_trace_index_ + 1) % kMaxPaths;
+ }
+
+ void AddToTrace(const ui::TouchEvent& touch) {
+ int touch_id = touch.touch_id();
+ int trace_index = touch_id_to_trace_index_[touch_id];
+ traces_[trace_index].AddTouchPoint(touch);
+ }
+
+ TouchTrace traces_[kMaxPaths];
+ int next_trace_index_;
+
+ std::map<int, int> touch_id_to_trace_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchLog);
+};
+
+// TouchHudCanvas draws touch traces in |FULLSCREEN| and |REDUCED_SCALE| modes.
+class TouchHudCanvas : public views::View {
+ public:
+ explicit TouchHudCanvas(const TouchLog& touch_log)
+ : touch_log_(touch_log),
+ scale_(1) {
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(false);
+
+ paint_.setStyle(SkPaint::kFill_Style);
+ }
+
+ virtual ~TouchHudCanvas() {}
+
+ void SetScale(int scale) {
+ if (scale_ == scale)
+ return;
+ scale_ = scale;
+ gfx::Transform transform;
+ transform.Scale(1. / scale_, 1. / scale_);
+ layer()->SetTransform(transform);
+ }
+
+ int scale() const { return scale_; }
+
+ void TouchPointAdded(int touch_id) {
+ int trace_index = touch_log_.GetTraceIndex(touch_id);
+ const TouchTrace& trace = touch_log_.traces()[trace_index];
+ const TouchPointLog& point = trace.log().back();
+ if (point.type == ui::ET_TOUCH_PRESSED)
+ StartedTrace(trace_index);
+ if (point.type != ui::ET_TOUCH_CANCELLED)
+ AddedPointToTrace(trace_index);
+ }
+
+ void Clear() {
+ for (int i = 0; i < kMaxPaths; ++i)
+ paths_[i].reset();
+
+ SchedulePaint();
+ }
+
+ private:
+ void StartedTrace(int trace_index) {
+ paths_[trace_index].reset();
+ colors_[trace_index] = SkColorSetA(kColors[trace_index], kAlpha);
+ }
+
+ void AddedPointToTrace(int trace_index) {
+ const TouchTrace& trace = touch_log_.traces()[trace_index];
+ const TouchPointLog& point = trace.log().back();
+ const gfx::Point& location = point.location;
+ SkScalar x = SkIntToScalar(location.x());
+ SkScalar y = SkIntToScalar(location.y());
+ SkPoint last;
+ if (!paths_[trace_index].getLastPt(&last) || x != last.x() ||
+ y != last.y()) {
+ paths_[trace_index].addCircle(x, y, SkIntToScalar(kPointRadius));
+ SchedulePaint();
+ }
+ }
+
+ // Overridden from views::View.
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
+ for (int i = 0; i < kMaxPaths; ++i) {
+ if (paths_[i].countPoints() == 0)
+ continue;
+ paint_.setColor(colors_[i]);
+ canvas->DrawPath(paths_[i], paint_);
+ }
+ }
+
+ SkPaint paint_;
+
+ const TouchLog& touch_log_;
+ SkPath paths_[kMaxPaths];
+ SkColor colors_[kMaxPaths];
+
+ int scale_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchHudCanvas);
+};
+
+TouchHudDebug::TouchHudDebug(aura::RootWindow* initial_root)
+ : TouchObserverHUD(initial_root),
+ mode_(FULLSCREEN),
+ touch_log_(new TouchLog()),
+ canvas_(NULL),
+ label_container_(NULL) {
+ const gfx::Display& display =
+ Shell::GetInstance()->display_manager()->GetDisplayForId(display_id());
+
+ views::View* content = widget()->GetContentsView();
+
+ canvas_ = new TouchHudCanvas(*touch_log_);
+ content->AddChildView(canvas_);
+
+ const gfx::Size& display_size = display.size();
+ canvas_->SetSize(display_size);
+
+ label_container_ = new views::View;
+ label_container_->SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kVertical, 0, 0, 0));
+
+ for (int i = 0; i < kMaxTouchPoints; ++i) {
+ touch_labels_[i] = new views::Label;
+ touch_labels_[i]->SetBackgroundColor(SkColorSetARGB(0, 255, 255, 255));
+ touch_labels_[i]->SetShadowColors(SK_ColorWHITE,
+ SK_ColorWHITE);
+ touch_labels_[i]->SetShadowOffset(1, 1);
+ label_container_->AddChildView(touch_labels_[i]);
+ }
+ label_container_->SetX(0);
+ label_container_->SetY(display_size.height() / kReducedScale);
+ label_container_->SetSize(label_container_->GetPreferredSize());
+ label_container_->SetVisible(false);
+ content->AddChildView(label_container_);
+}
+
+TouchHudDebug::~TouchHudDebug() {
+}
+
+// static
+scoped_ptr<DictionaryValue> TouchHudDebug::GetAllAsDictionary() {
+ scoped_ptr<DictionaryValue> value(new DictionaryValue());
+ Shell::RootWindowList roots = Shell::GetInstance()->GetAllRootWindows();
+ for (Shell::RootWindowList::iterator iter = roots.begin();
+ iter != roots.end(); ++iter) {
+ internal::RootWindowController* controller = GetRootWindowController(*iter);
+ internal::TouchHudDebug* hud = controller->touch_hud_debug();
+ if (hud) {
+ scoped_ptr<ListValue> list = hud->GetLogAsList();
+ if (!list->empty())
+ value->Set(base::Int64ToString(hud->display_id()), list.release());
+ }
+ }
+ return value.Pass();
+}
+
+void TouchHudDebug::ChangeToNextMode() {
+ switch (mode_) {
+ case FULLSCREEN:
+ SetMode(REDUCED_SCALE);
+ break;
+ case REDUCED_SCALE:
+ SetMode(INVISIBLE);
+ break;
+ case INVISIBLE:
+ SetMode(FULLSCREEN);
+ break;
+ }
+}
+
+scoped_ptr<ListValue> TouchHudDebug::GetLogAsList() const {
+ return touch_log_->GetAsList();
+}
+
+void TouchHudDebug::Clear() {
+ if (widget()->IsVisible()) {
+ canvas_->Clear();
+ for (int i = 0; i < kMaxTouchPoints; ++i)
+ touch_labels_[i]->SetText(string16());
+ label_container_->SetSize(label_container_->GetPreferredSize());
+ }
+}
+
+void TouchHudDebug::SetMode(Mode mode) {
+ if (mode_ == mode)
+ return;
+ mode_ = mode;
+ switch (mode) {
+ case FULLSCREEN:
+ label_container_->SetVisible(false);
+ canvas_->SetVisible(true);
+ canvas_->SetScale(1);
+ canvas_->SchedulePaint();
+ widget()->Show();
+ break;
+ case REDUCED_SCALE:
+ label_container_->SetVisible(true);
+ canvas_->SetVisible(true);
+ canvas_->SetScale(kReducedScale);
+ canvas_->SchedulePaint();
+ widget()->Show();
+ break;
+ case INVISIBLE:
+ widget()->Hide();
+ break;
+ }
+}
+
+void TouchHudDebug::UpdateTouchPointLabel(int index) {
+ int trace_index = touch_log_->GetTraceIndex(index);
+ const TouchTrace& trace = touch_log_->traces()[trace_index];
+ TouchTrace::const_reverse_iterator point = trace.log().rbegin();
+ ui::EventType touch_status = point->type;
+ float touch_radius = std::max(point->radius_x, point->radius_y);
+ while (point != trace.log().rend() && point->type == ui::ET_TOUCH_CANCELLED)
+ point++;
+ DCHECK(point != trace.log().rend());
+ gfx::Point touch_position = point->location;
+
+ std::string string = base::StringPrintf("%2d: %s %s (%.4f)",
+ index,
+ GetTouchEventLabel(touch_status),
+ touch_position.ToString().c_str(),
+ touch_radius);
+ touch_labels_[index]->SetText(UTF8ToUTF16(string));
+}
+
+void TouchHudDebug::OnTouchEvent(ui::TouchEvent* event) {
+ if (event->touch_id() >= kMaxTouchPoints)
+ return;
+
+ touch_log_->AddTouchPoint(*event);
+ canvas_->TouchPointAdded(event->touch_id());
+ UpdateTouchPointLabel(event->touch_id());
+ label_container_->SetSize(label_container_->GetPreferredSize());
+}
+
+void TouchHudDebug::OnDisplayBoundsChanged(const gfx::Display& display) {
+ TouchObserverHUD::OnDisplayBoundsChanged(display);
+
+ if (display.id() != display_id())
+ return;
+ const gfx::Size& size = display.size();
+ canvas_->SetSize(size);
+ label_container_->SetY(size.height() / kReducedScale);
+}
+
+void TouchHudDebug::SetHudForRootWindowController(
+ RootWindowController* controller) {
+ controller->set_touch_hud_debug(this);
+}
+
+void TouchHudDebug::UnsetHudForRootWindowController(
+ RootWindowController* controller) {
+ controller->set_touch_hud_debug(NULL);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/touch/touch_hud_debug.h b/ash/touch/touch_hud_debug.h
new file mode 100644
index 0000000..a02a888
--- /dev/null
+++ b/ash/touch/touch_hud_debug.h
@@ -0,0 +1,87 @@
+// 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_TOUCH_TOUCH_HUD_DEBUG_H_
+#define ASH_TOUCH_TOUCH_HUD_DEBUG_H_
+
+#include <map>
+
+#include "ash/ash_export.h"
+#include "ash/touch/touch_observer_hud.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+
+namespace views {
+class Label;
+class View;
+}
+
+namespace ash {
+namespace internal {
+
+class TouchHudCanvas;
+class TouchLog;
+
+// A heads-up display to show touch traces on the screen and log touch events.
+// As a derivative of TouchObserverHUD, objects of this class manage their own
+// lifetime.
+class ASH_EXPORT TouchHudDebug : public TouchObserverHUD {
+ public:
+ enum Mode {
+ FULLSCREEN,
+ REDUCED_SCALE,
+ INVISIBLE,
+ };
+
+ explicit TouchHudDebug(aura::RootWindow* initial_root);
+
+ // Returns the log of touch events for all displays as a dictionary mapping id
+ // of each display to its touch log.
+ static scoped_ptr<DictionaryValue> GetAllAsDictionary();
+
+ // Changes the display mode (e.g. scale, visibility). Calling this repeatedly
+ // cycles between a fixed number of display modes.
+ void ChangeToNextMode();
+
+ // Returns log of touch events as a list value. Each item in the list is a
+ // trace of one touch point.
+ scoped_ptr<ListValue> GetLogAsList() const;
+
+ Mode mode() const { return mode_; }
+
+ // Overriden from TouchObserverHUD.
+ virtual void Clear() OVERRIDE;
+
+ private:
+ virtual ~TouchHudDebug();
+
+ void SetMode(Mode mode);
+
+ void UpdateTouchPointLabel(int index);
+
+ // Overriden from TouchObserverHUD.
+ virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
+ virtual void SetHudForRootWindowController(
+ RootWindowController* controller) OVERRIDE;
+ virtual void UnsetHudForRootWindowController(
+ RootWindowController* controller) OVERRIDE;
+
+ static const int kMaxTouchPoints = 32;
+
+ Mode mode_;
+
+ scoped_ptr<TouchLog> touch_log_;
+
+ TouchHudCanvas* canvas_;
+ views::View* label_container_;
+ views::Label* touch_labels_[kMaxTouchPoints];
+
+ DISALLOW_COPY_AND_ASSIGN(TouchHudDebug);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_TOUCH_TOUCH_HUD_DEBUG_H_
diff --git a/ash/touch/touch_hud_projection.cc b/ash/touch/touch_hud_projection.cc
new file mode 100644
index 0000000..3a834a5
--- /dev/null
+++ b/ash/touch/touch_hud_projection.cc
@@ -0,0 +1,186 @@
+// 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/touch/touch_hud_projection.h"
+
+#include "ash/root_window_controller.h"
+#include "ash/shell.h"
+#include "ash/wm/property_util.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/linear_animation.h"
+#include "ui/base/events/event.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/size.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+namespace internal {
+
+const int kPointRadius = 20;
+const SkColor kProjectionFillColor = SkColorSetRGB(0xF5, 0xF5, 0xDC);
+const SkColor kProjectionStrokeColor = SK_ColorGRAY;
+const int kProjectionAlpha = 0xB0;
+const int kFadeoutDurationInMs = 250;
+const int kFadeoutFrameRate = 60;
+
+// TouchPointView draws a single touch point. This object manages its own
+// lifetime and deletes itself upon fade-out completion or whenever |Remove()|
+// is explicitly called.
+class TouchPointView : public views::View,
+ public ui::AnimationDelegate,
+ public views::WidgetObserver {
+ public:
+ explicit TouchPointView(views::Widget* parent_widget)
+ : circle_center_(kPointRadius + 1, kPointRadius + 1),
+ gradient_center_(SkPoint::Make(kPointRadius + 1,
+ kPointRadius + 1)) {
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(false);
+
+ SetSize(gfx::Size(2 * kPointRadius + 2, 2 * kPointRadius + 2));
+
+ stroke_paint_.setStyle(SkPaint::kStroke_Style);
+ stroke_paint_.setColor(kProjectionStrokeColor);
+
+ gradient_colors_[0] = kProjectionFillColor;
+ gradient_colors_[1] = kProjectionStrokeColor;
+
+ gradient_pos_[0] = SkFloatToScalar(0.9f);
+ gradient_pos_[1] = SkFloatToScalar(1.0f);
+
+ parent_widget->GetContentsView()->AddChildView(this);
+
+ parent_widget->AddObserver(this);
+ }
+
+ void UpdateTouch(const ui::TouchEvent& touch) {
+ if (touch.type() == ui::ET_TOUCH_RELEASED ||
+ touch.type() == ui::ET_TOUCH_CANCELLED) {
+ fadeout_.reset(new ui::LinearAnimation(kFadeoutDurationInMs,
+ kFadeoutFrameRate,
+ this));
+ fadeout_->Start();
+ } else {
+ SetX(touch.root_location().x() - kPointRadius - 1);
+ SetY(touch.root_location().y() - kPointRadius - 1);
+ }
+ }
+
+ void Remove() {
+ delete this;
+ }
+
+ private:
+ virtual ~TouchPointView() {
+ GetWidget()->RemoveObserver(this);
+ parent()->RemoveChildView(this);
+ }
+
+ // Overridden from views::View.
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
+ int alpha = kProjectionAlpha;
+ if (fadeout_)
+ alpha = static_cast<int>(fadeout_->CurrentValueBetween(alpha, 0));
+ fill_paint_.setAlpha(alpha);
+ stroke_paint_.setAlpha(alpha);
+ SkShader* shader = SkGradientShader::CreateRadial(
+ gradient_center_,
+ SkIntToScalar(kPointRadius),
+ gradient_colors_,
+ gradient_pos_,
+ arraysize(gradient_colors_),
+ SkShader::kMirror_TileMode,
+ NULL);
+ fill_paint_.setShader(shader);
+ shader->unref();
+ canvas->DrawCircle(circle_center_, SkIntToScalar(kPointRadius),
+ fill_paint_);
+ canvas->DrawCircle(circle_center_, SkIntToScalar(kPointRadius),
+ stroke_paint_);
+ }
+
+ // Overridden from ui::AnimationDelegate.
+ virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE {
+ DCHECK_EQ(fadeout_.get(), animation);
+ delete this;
+ }
+
+ virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE {
+ DCHECK_EQ(fadeout_.get(), animation);
+ SchedulePaint();
+ }
+
+ virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE {
+ AnimationEnded(animation);
+ }
+
+ // Overridden from views::WidgetObserver.
+ virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
+ fadeout_->Stop();
+ }
+
+ const gfx::Point circle_center_;
+ const SkPoint gradient_center_;
+
+ SkPaint fill_paint_;
+ SkPaint stroke_paint_;
+ SkColor gradient_colors_[2];
+ SkScalar gradient_pos_[2];
+
+ scoped_ptr<ui::Animation> fadeout_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchPointView);
+};
+
+TouchHudProjection::TouchHudProjection(aura::RootWindow* initial_root)
+ : TouchObserverHUD(initial_root) {
+}
+
+TouchHudProjection::~TouchHudProjection() {
+}
+
+void TouchHudProjection::Clear() {
+ for (std::map<int, TouchPointView*>::iterator iter = points_.begin();
+ iter != points_.end(); iter++)
+ iter->second->Remove();
+ points_.clear();
+}
+
+void TouchHudProjection::OnTouchEvent(ui::TouchEvent* event) {
+ if (event->type() == ui::ET_TOUCH_PRESSED) {
+ TouchPointView* point = new TouchPointView(widget());
+ point->UpdateTouch(*event);
+ std::pair<std::map<int, TouchPointView*>::iterator, bool> result =
+ points_.insert(std::make_pair(event->touch_id(), point));
+ // If a |TouchPointView| is already mapped to the touch id, remove it and
+ // replace it with the new one.
+ if (!result.second) {
+ result.first->second->Remove();
+ result.first->second = point;
+ }
+ } else {
+ std::map<int, TouchPointView*>::iterator iter =
+ points_.find(event->touch_id());
+ if (iter != points_.end()) {
+ iter->second->UpdateTouch(*event);
+ if (event->type() == ui::ET_TOUCH_RELEASED ||
+ event->type() == ui::ET_TOUCH_CANCELLED)
+ points_.erase(iter);
+ }
+ }
+}
+
+void TouchHudProjection::SetHudForRootWindowController(
+ RootWindowController* controller) {
+ controller->set_touch_hud_projection(this);
+}
+
+void TouchHudProjection::UnsetHudForRootWindowController(
+ RootWindowController* controller) {
+ controller->set_touch_hud_projection(NULL);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/touch/touch_hud_projection.h b/ash/touch/touch_hud_projection.h
new file mode 100644
index 0000000..29fddc3
--- /dev/null
+++ b/ash/touch/touch_hud_projection.h
@@ -0,0 +1,44 @@
+// 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_TOUCH_TOUCH_HUD_PROJECTION_H_
+#define ASH_TOUCH_TOUCH_HUD_PROJECTION_H_
+
+#include <map>
+
+#include "ash/touch/touch_observer_hud.h"
+
+namespace ash {
+namespace internal {
+
+class TouchPointView;
+
+// A heads-up display to show active touch points on the screen. As a derivative
+// of TouchObserverHUD, objects of this class manage their own lifetime.
+class TouchHudProjection : public TouchObserverHUD {
+ public:
+ explicit TouchHudProjection(aura::RootWindow* initial_root);
+
+ // Overriden from TouchObserverHUD.
+ virtual void Clear() OVERRIDE;
+
+ private:
+ virtual ~TouchHudProjection();
+
+ // Overriden from TouchObserverHUD.
+ virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ virtual void SetHudForRootWindowController(
+ RootWindowController* controller) OVERRIDE;
+ virtual void UnsetHudForRootWindowController(
+ RootWindowController* controller) OVERRIDE;
+
+ std::map<int, TouchPointView*> points_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchHudProjection);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_TOUCH_TOUCH_HUD_PROJECTION_H_
diff --git a/ash/touch/touch_observer_hud.cc b/ash/touch/touch_observer_hud.cc
index a9ac307..ceb87fd 100644
--- a/ash/touch/touch_observer_hud.cc
+++ b/ash/touch/touch_observer_hud.cc
@@ -4,496 +4,40 @@
#include "ash/touch/touch_observer_hud.h"
-#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
#include "ash/root_window_controller.h"
+#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/property_util.h"
-#include "base/json/json_string_value_serializer.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "third_party/skia/include/core/SkPath.h"
-#include "third_party/skia/include/core/SkXfermode.h"
-#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/linear_animation.h"
-#include "ui/base/events/event.h"
-#include "ui/gfx/canvas.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size.h"
-#include "ui/gfx/transform.h"
-#include "ui/views/background.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_X11)
-#include <X11/extensions/XInput2.h>
-#include <X11/Xlib.h>
-
-#include "ui/base/x/device_data_manager.h"
-#endif
-
namespace ash {
namespace internal {
-const int kPointRadius = 20;
-const SkColor kColors[] = {
- SK_ColorYELLOW,
- SK_ColorGREEN,
- SK_ColorRED,
- SK_ColorBLUE,
- SK_ColorGRAY,
- SK_ColorMAGENTA,
- SK_ColorCYAN,
- SK_ColorWHITE,
- SK_ColorBLACK,
- SkColorSetRGB(0xFF, 0x8C, 0x00),
- SkColorSetRGB(0x8B, 0x45, 0x13),
- SkColorSetRGB(0xFF, 0xDE, 0xAD),
-};
-const int kAlpha = 0x60;
-const SkColor kProjectionFillColor = SkColorSetRGB(0xF5, 0xF5, 0xDC);
-const SkColor kProjectionStrokeColor = SK_ColorGRAY;
-const int kProjectionAlpha = 0xB0;
-const int kMaxPaths = arraysize(kColors);
-const int kReducedScale = 10;
-const int kFadeoutDurationInMs = 250;
-const int kFadeoutFrameRate = 60;
-
-const char* GetTouchEventLabel(ui::EventType type) {
- switch (type) {
- case ui::ET_UNKNOWN:
- return " ";
- case ui::ET_TOUCH_PRESSED:
- return "P";
- case ui::ET_TOUCH_MOVED:
- return "M";
- case ui::ET_TOUCH_RELEASED:
- return "R";
- case ui::ET_TOUCH_CANCELLED:
- return "C";
- default:
- break;
- }
- return "?";
-}
-
-int GetTrackingId(const ui::TouchEvent& event) {
- if (!event.HasNativeEvent())
- return 0;
-#if defined(USE_XI2_MT)
- ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
- double tracking_id;
- if (manager->GetEventData(*event.native_event(),
- ui::DeviceDataManager::DT_TOUCH_TRACKING_ID,
- &tracking_id)) {
- return static_cast<int>(tracking_id);
- }
-#endif
- return 0;
-}
-
-int GetSourceDeviceId(const ui::TouchEvent& event) {
- if (!event.HasNativeEvent())
- return 0;
-#if defined(USE_X11)
- XEvent* xev = event.native_event();
- return static_cast<XIDeviceEvent*>(xev->xcookie.data)->sourceid;
-#endif
- return 0;
-}
-
-// A TouchPointLog represents a single touch-event of a touch point.
-struct TouchPointLog {
- public:
- explicit TouchPointLog(const ui::TouchEvent& touch)
- : id(touch.touch_id()),
- type(touch.type()),
- location(touch.root_location()),
- timestamp(touch.time_stamp().InMillisecondsF()),
- radius_x(touch.radius_x()),
- radius_y(touch.radius_y()),
- pressure(touch.force()),
- tracking_id(GetTrackingId(touch)),
- source_device(GetSourceDeviceId(touch)) {
- }
-
- // Populates a dictionary value with all the information about the touch
- // point.
- scoped_ptr<DictionaryValue> GetAsDictionary() const {
- scoped_ptr<DictionaryValue> value(new DictionaryValue());
-
- value->SetInteger("id", id);
- value->SetString("type", std::string(GetTouchEventLabel(type)));
- value->SetString("location", location.ToString());
- value->SetDouble("timestamp", timestamp);
- value->SetDouble("radius_x", radius_x);
- value->SetDouble("radius_y", radius_y);
- value->SetDouble("pressure", pressure);
- value->SetInteger("tracking_id", tracking_id);
- value->SetInteger("source_device", source_device);
-
- return value.Pass();
- }
-
- int id;
- ui::EventType type;
- gfx::Point location;
- double timestamp;
- float radius_x;
- float radius_y;
- float pressure;
- int tracking_id;
- int source_device;
-};
-
-// A TouchTrace keeps track of all the touch events of a single touch point
-// (starting from a touch-press and ending at touch-release).
-class TouchTrace {
- public:
- typedef std::vector<TouchPointLog>::iterator iterator;
- typedef std::vector<TouchPointLog>::const_iterator const_iterator;
- typedef std::vector<TouchPointLog>::reverse_iterator reverse_iterator;
- typedef std::vector<TouchPointLog>::const_reverse_iterator
- const_reverse_iterator;
-
- TouchTrace() {
- }
-
- void AddTouchPoint(const ui::TouchEvent& touch) {
- log_.push_back(TouchPointLog(touch));
- }
-
- const std::vector<TouchPointLog>& log() const { return log_; }
-
- bool active() const {
- return !log_.empty() && log_.back().type != ui::ET_TOUCH_RELEASED &&
- log_.back().type != ui::ET_TOUCH_CANCELLED;
- }
-
- // Returns a list containing data from all events for the touch point.
- scoped_ptr<ListValue> GetAsList() const {
- scoped_ptr<ListValue> list(new ListValue());
- for (const_iterator i = log_.begin(); i != log_.end(); ++i)
- list->Append((*i).GetAsDictionary().release());
- return list.Pass();
- }
-
- void Reset() {
- log_.clear();
- }
-
- private:
- std::vector<TouchPointLog> log_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchTrace);
-};
-
-// A TouchLog keeps track of all touch events of all touch points.
-class TouchLog {
- public:
- TouchLog() : next_trace_index_(0) {
- }
-
- void AddTouchPoint(const ui::TouchEvent& touch) {
- if (touch.type() == ui::ET_TOUCH_PRESSED)
- StartTrace(touch);
- AddToTrace(touch);
- }
-
- void Reset() {
- next_trace_index_ = 0;
- for (int i = 0; i < kMaxPaths; ++i)
- traces_[i].Reset();
- }
-
- scoped_ptr<ListValue> GetAsList() const {
- scoped_ptr<ListValue> list(new ListValue());
- for (int i = 0; i < kMaxPaths; ++i) {
- if (!traces_[i].log().empty())
- list->Append(traces_[i].GetAsList().release());
- }
- return list.Pass();
- }
-
- int GetTraceIndex(int touch_id) const {
- return touch_id_to_trace_index_.at(touch_id);
- }
-
- const TouchTrace* traces() const {
- return traces_;
- }
-
- private:
- void StartTrace(const ui::TouchEvent& touch) {
- // Find the first inactive spot; otherwise, overwrite the one
- // |next_trace_index_| is pointing to.
- int old_trace_index = next_trace_index_;
- do {
- if (!traces_[next_trace_index_].active())
- break;
- next_trace_index_ = (next_trace_index_ + 1) % kMaxPaths;
- } while (next_trace_index_ != old_trace_index);
- int touch_id = touch.touch_id();
- traces_[next_trace_index_].Reset();
- touch_id_to_trace_index_[touch_id] = next_trace_index_;
- next_trace_index_ = (next_trace_index_ + 1) % kMaxPaths;
- }
-
- void AddToTrace(const ui::TouchEvent& touch) {
- int touch_id = touch.touch_id();
- int trace_index = touch_id_to_trace_index_[touch_id];
- traces_[trace_index].AddTouchPoint(touch);
- }
-
- TouchTrace traces_[kMaxPaths];
- int next_trace_index_;
-
- std::map<int, int> touch_id_to_trace_index_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchLog);
-};
-
-// TouchHudCanvas draws touch traces in |FULLSCREEN| and |REDUCED_SCALE| modes.
-class TouchHudCanvas : public views::View {
- public:
- explicit TouchHudCanvas(const TouchLog& touch_log)
- : touch_log_(touch_log),
- scale_(1) {
- SetPaintToLayer(true);
- SetFillsBoundsOpaquely(false);
-
- paint_.setStyle(SkPaint::kFill_Style);
- }
-
- virtual ~TouchHudCanvas() {}
-
- void SetScale(int scale) {
- if (scale_ == scale)
- return;
- scale_ = scale;
- gfx::Transform transform;
- transform.Scale(1. / scale_, 1. / scale_);
- layer()->SetTransform(transform);
- }
-
- int scale() const { return scale_; }
-
- void TouchPointAdded(int touch_id) {
- int trace_index = touch_log_.GetTraceIndex(touch_id);
- const TouchTrace& trace = touch_log_.traces()[trace_index];
- const TouchPointLog& point = trace.log().back();
- if (point.type == ui::ET_TOUCH_PRESSED)
- StartedTrace(trace_index);
- if (point.type != ui::ET_TOUCH_CANCELLED)
- AddedPointToTrace(trace_index);
- }
-
- void Clear() {
- for (int i = 0; i < kMaxPaths; ++i)
- paths_[i].reset();
-
- SchedulePaint();
- }
-
- private:
- void StartedTrace(int trace_index) {
- paths_[trace_index].reset();
- colors_[trace_index] = SkColorSetA(kColors[trace_index], kAlpha);
- }
-
- void AddedPointToTrace(int trace_index) {
- const TouchTrace& trace = touch_log_.traces()[trace_index];
- const TouchPointLog& point = trace.log().back();
- const gfx::Point& location = point.location;
- SkScalar x = SkIntToScalar(location.x());
- SkScalar y = SkIntToScalar(location.y());
- SkPoint last;
- if (!paths_[trace_index].getLastPt(&last) || x != last.x() ||
- y != last.y()) {
- paths_[trace_index].addCircle(x, y, SkIntToScalar(kPointRadius));
- SchedulePaint();
- }
- }
-
- // Overridden from views::View.
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
- for (int i = 0; i < kMaxPaths; ++i) {
- if (paths_[i].countPoints() == 0)
- continue;
- paint_.setColor(colors_[i]);
- canvas->DrawPath(paths_[i], paint_);
- }
- }
-
- SkPaint paint_;
-
- const TouchLog& touch_log_;
- SkPath paths_[kMaxPaths];
- SkColor colors_[kMaxPaths];
-
- int scale_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchHudCanvas);
-};
-
-// TouchPointView draws a single touch point in |PROJECTION| mode. This object
-// manages its own lifetime and deletes itself upon fade-out completion or
-// whenever |Remove()| is explicitly called.
-class TouchPointView : public views::View,
- public ui::AnimationDelegate,
- public views::WidgetObserver {
- public:
- explicit TouchPointView(views::Widget* parent_widget)
- : circle_center_(kPointRadius + 1, kPointRadius + 1),
- gradient_center_(SkPoint::Make(kPointRadius + 1,
- kPointRadius + 1)) {
- SetPaintToLayer(true);
- SetFillsBoundsOpaquely(false);
-
- SetSize(gfx::Size(2 * kPointRadius + 2, 2 * kPointRadius + 2));
-
- stroke_paint_.setStyle(SkPaint::kStroke_Style);
- stroke_paint_.setColor(kProjectionStrokeColor);
-
- gradient_colors_[0] = kProjectionFillColor;
- gradient_colors_[1] = kProjectionStrokeColor;
-
- gradient_pos_[0] = SkFloatToScalar(0.9f);
- gradient_pos_[1] = SkFloatToScalar(1.0f);
-
- parent_widget->GetContentsView()->AddChildView(this);
-
- parent_widget->AddObserver(this);
- }
-
- void UpdateTouch(const ui::TouchEvent& touch) {
- if (touch.type() == ui::ET_TOUCH_RELEASED ||
- touch.type() == ui::ET_TOUCH_CANCELLED) {
- fadeout_.reset(new ui::LinearAnimation(kFadeoutDurationInMs,
- kFadeoutFrameRate,
- this));
- fadeout_->Start();
- } else {
- SetX(touch.root_location().x() - kPointRadius - 1);
- SetY(touch.root_location().y() - kPointRadius - 1);
- }
- }
-
- void Remove() {
- delete this;
- }
-
- private:
- virtual ~TouchPointView() {
- GetWidget()->RemoveObserver(this);
- parent()->RemoveChildView(this);
- }
-
- // Overridden from views::View.
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
- int alpha = kProjectionAlpha;
- if (fadeout_)
- alpha = static_cast<int>(fadeout_->CurrentValueBetween(alpha, 0));
- fill_paint_.setAlpha(alpha);
- stroke_paint_.setAlpha(alpha);
- SkShader* shader = SkGradientShader::CreateRadial(
- gradient_center_,
- SkIntToScalar(kPointRadius),
- gradient_colors_,
- gradient_pos_,
- arraysize(gradient_colors_),
- SkShader::kMirror_TileMode,
- NULL);
- fill_paint_.setShader(shader);
- shader->unref();
- canvas->DrawCircle(circle_center_, SkIntToScalar(kPointRadius),
- fill_paint_);
- canvas->DrawCircle(circle_center_, SkIntToScalar(kPointRadius),
- stroke_paint_);
- }
-
- // Overridden from ui::AnimationDelegate.
- virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE {
- DCHECK_EQ(fadeout_.get(), animation);
- delete this;
- }
-
- virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE {
- DCHECK_EQ(fadeout_.get(), animation);
- SchedulePaint();
- }
-
- virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE {
- AnimationEnded(animation);
- }
-
- // Overridden from views::WidgetObserver.
- virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
- fadeout_->Stop();
- }
-
- const gfx::Point circle_center_;
- const SkPoint gradient_center_;
-
- SkPaint fill_paint_;
- SkPaint stroke_paint_;
- SkColor gradient_colors_[2];
- SkScalar gradient_pos_[2];
-
- scoped_ptr<ui::Animation> fadeout_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchPointView);
-};
-
TouchObserverHUD::TouchObserverHUD(aura::RootWindow* initial_root)
: display_id_(initial_root->GetProperty(kDisplayIdKey)),
root_window_(initial_root),
- mode_(FULLSCREEN),
- touch_log_(new TouchLog()) {
+ widget_(NULL) {
const gfx::Display& display =
Shell::GetInstance()->display_manager()->GetDisplayForId(display_id_);
views::View* content = new views::View;
- canvas_ = new TouchHudCanvas(*touch_log_);
- content->AddChildView(canvas_);
-
const gfx::Size& display_size = display.size();
- canvas_->SetSize(display_size);
content->SetSize(display_size);
- label_container_ = new views::View;
- label_container_->SetLayoutManager(new views::BoxLayout(
- views::BoxLayout::kVertical, 0, 0, 0));
-
- for (int i = 0; i < kMaxTouchPoints; ++i) {
- touch_labels_[i] = new views::Label;
- touch_labels_[i]->SetBackgroundColor(SkColorSetARGB(0, 255, 255, 255));
- touch_labels_[i]->SetShadowColors(SK_ColorWHITE,
- SK_ColorWHITE);
- touch_labels_[i]->SetShadowOffset(1, 1);
- label_container_->AddChildView(touch_labels_[i]);
- }
- label_container_->SetX(0);
- label_container_->SetY(display_size.height() / kReducedScale);
- label_container_->SetSize(label_container_->GetPreferredSize());
- label_container_->SetVisible(false);
- content->AddChildView(label_container_);
-
widget_ = new views::Widget();
views::Widget::InitParams
params(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.can_activate = false;
params.accept_events = false;
- params.bounds = gfx::Rect(display_size);
+ params.bounds = display.bounds();
params.parent = Shell::GetContainer(
root_window_,
internal::kShellWindowId_OverlayContainer);
@@ -525,142 +69,19 @@
widget_->RemoveObserver(this);
}
-// static
-scoped_ptr<DictionaryValue> TouchObserverHUD::GetAllAsDictionary() {
- scoped_ptr<DictionaryValue> value(new DictionaryValue());
- Shell::RootWindowList roots = Shell::GetInstance()->GetAllRootWindows();
- for (Shell::RootWindowList::iterator iter = roots.begin();
- iter != roots.end(); ++iter) {
- internal::RootWindowController* controller = GetRootWindowController(*iter);
- if (controller->touch_observer_hud()) {
- int64 display_id = (*iter)->GetProperty(kDisplayIdKey);
- scoped_ptr<ListValue> list =
- controller->touch_observer_hud()->GetLogAsList();
- if (!list->empty())
- value->Set(base::Int64ToString(display_id), list.release());
- }
- }
- return value.Pass();
-}
-
-void TouchObserverHUD::ChangeToNextMode() {
- switch (mode_) {
- case FULLSCREEN:
- SetMode(REDUCED_SCALE);
- break;
- case REDUCED_SCALE:
- SetMode(PROJECTION);
- break;
- case PROJECTION:
- SetMode(INVISIBLE);
- break;
- case INVISIBLE:
- SetMode(FULLSCREEN);
- break;
- }
-}
-
void TouchObserverHUD::Clear() {
- if (widget_->IsVisible())
- canvas_->Clear();
- for (int i = 0; i < kMaxTouchPoints; ++i)
- touch_labels_[i]->SetText(string16());
- label_container_->SetSize(label_container_->GetPreferredSize());
}
-scoped_ptr<ListValue> TouchObserverHUD::GetLogAsList() const {
- return touch_log_->GetAsList();
+void TouchObserverHUD::Remove() {
+ root_window_->RemovePreTargetHandler(this);
+
+ RootWindowController* controller = GetRootWindowController(root_window_);
+ UnsetHudForRootWindowController(controller);
+
+ widget_->CloseNow();
}
-void TouchObserverHUD::SetMode(Mode mode) {
- if (mode_ == mode)
- return;
- // When going out of projection mode, hide all active touch points.
- if (mode_ == PROJECTION) {
- for (std::map<int, TouchPointView*>::iterator iter = points_.begin();
- iter != points_.end(); ++iter)
- iter->second->Remove();
- points_.clear();
- }
- mode_ = mode;
- switch (mode) {
- case FULLSCREEN:
- label_container_->SetVisible(false);
- canvas_->SetVisible(true);
- canvas_->SetScale(1);
- canvas_->SchedulePaint();
- widget_->Show();
- break;
- case REDUCED_SCALE:
- label_container_->SetVisible(true);
- canvas_->SetVisible(true);
- canvas_->SetScale(kReducedScale);
- canvas_->SchedulePaint();
- widget_->Show();
- break;
- case PROJECTION:
- label_container_->SetVisible(false);
- canvas_->SetVisible(false);
- widget_->Show();
- break;
- case INVISIBLE:
- widget_->Hide();
- break;
- }
-}
-
-void TouchObserverHUD::UpdateTouchPointLabel(int index) {
- int trace_index = touch_log_->GetTraceIndex(index);
- const TouchTrace& trace = touch_log_->traces()[trace_index];
- TouchTrace::const_reverse_iterator point = trace.log().rbegin();
- ui::EventType touch_status = point->type;
- float touch_radius = std::max(point->radius_x, point->radius_y);
- while (point != trace.log().rend() && point->type == ui::ET_TOUCH_CANCELLED)
- point++;
- DCHECK(point != trace.log().rend());
- gfx::Point touch_position = point->location;
-
- std::string string = base::StringPrintf("%2d: %s %s (%.4f)",
- index,
- GetTouchEventLabel(touch_status),
- touch_position.ToString().c_str(),
- touch_radius);
- touch_labels_[index]->SetText(UTF8ToUTF16(string));
-}
-
-void TouchObserverHUD::OnTouchEvent(ui::TouchEvent* event) {
- if (event->touch_id() >= kMaxTouchPoints)
- return;
-
- touch_log_->AddTouchPoint(*event);
- canvas_->TouchPointAdded(event->touch_id());
-
- if (mode_ == PROJECTION) {
- if (event->type() == ui::ET_TOUCH_PRESSED) {
- TouchPointView* point = new TouchPointView(widget_);
- point->UpdateTouch(*event);
- std::pair<std::map<int, TouchPointView*>::iterator, bool> result =
- points_.insert(std::make_pair(event->touch_id(), point));
- // If a |TouchPointView| is already mapped to the touch id, remove it and
- // replace it with the new one.
- if (!result.second) {
- result.first->second->Remove();
- result.first->second = point;
- }
- } else {
- std::map<int, TouchPointView*>::iterator iter =
- points_.find(event->touch_id());
- if (iter != points_.end()) {
- iter->second->UpdateTouch(*event);
- if (event->type() == ui::ET_TOUCH_RELEASED ||
- event->type() == ui::ET_TOUCH_CANCELLED)
- points_.erase(iter);
- }
- }
- }
-
- UpdateTouchPointLabel(event->touch_id());
- label_container_->SetSize(label_container_->GetPreferredSize());
+void TouchObserverHUD::OnTouchEvent(ui::TouchEvent* /*event*/) {
}
void TouchObserverHUD::OnWidgetDestroying(views::Widget* widget) {
@@ -671,10 +92,7 @@
void TouchObserverHUD::OnDisplayBoundsChanged(const gfx::Display& display) {
if (display.id() != display_id_)
return;
- const gfx::Size& size = display.size();
- widget_->SetSize(size);
- canvas_->SetSize(size);
- label_container_->SetY(size.height() / kReducedScale);
+ widget_->SetSize(display.size());
}
void TouchObserverHUD::OnDisplayAdded(const gfx::Display& new_display) {}
@@ -700,7 +118,7 @@
root_window_->RemovePreTargetHandler(this);
RootWindowController* controller = GetRootWindowController(root_window_);
- controller->set_touch_observer_hud(NULL);
+ UnsetHudForRootWindowController(controller);
views::Widget::ReparentNativeView(
widget_->GetNativeView(),
@@ -723,7 +141,7 @@
internal::kShellWindowId_OverlayContainer));
RootWindowController* controller = GetRootWindowController(root_window_);
- controller->set_touch_observer_hud(this);
+ SetHudForRootWindowController(controller);
root_window_->AddPreTargetHandler(this);
}
diff --git a/ash/touch/touch_observer_hud.h b/ash/touch/touch_observer_hud.h
index d1c65eb..850bc5e 100644
--- a/ash/touch/touch_observer_hud.h
+++ b/ash/touch/touch_observer_hud.h
@@ -5,43 +5,23 @@
#ifndef ASH_TOUCH_TOUCH_OBSERVER_HUD_H_
#define ASH_TOUCH_TOUCH_OBSERVER_HUD_H_
-#include <map>
-
#include "ash/ash_export.h"
#include "ash/display/display_controller.h"
-#include "ash/shell.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
#include "ui/base/events/event_handler.h"
#include "ui/gfx/display_observer.h"
-#include "ui/gfx/point.h"
#include "ui/views/widget/widget_observer.h"
#if defined(OS_CHROMEOS)
#include "chromeos/display/output_configurator.h"
#endif // defined(OS_CHROMEOS)
-namespace aura {
-class Window;
-}
-
-namespace gfx {
-class Display;
-}
-
namespace views {
-class Label;
-class View;
class Widget;
}
namespace ash {
namespace internal {
-class TouchHudCanvas;
-class TouchLog;
-class TouchPointView;
-
// An event filter which handles system level gesture events. Objects of this
// class manage their own lifetime.
class ASH_EXPORT TouchObserverHUD
@@ -53,76 +33,54 @@
#endif // defined(OS_CHROMEOS)
public DisplayController::Observer {
public:
- enum Mode {
- FULLSCREEN,
- REDUCED_SCALE,
- PROJECTION,
- INVISIBLE,
- };
+ // Called to clear touch points and traces from the screen. Default
+ // implementation does nothing. Sub-classes should implement appropriately.
+ virtual void Clear();
+ // Removes the HUD from the screen.
+ void Remove();
+
+ int64 display_id() const { return display_id_; }
+
+ protected:
explicit TouchObserverHUD(aura::RootWindow* initial_root);
- // Returns the log of touch events as a dictionary mapping id of each display
- // to its touch log.
- static scoped_ptr<DictionaryValue> GetAllAsDictionary();
-
- // Changes the display mode (e.g. scale, visibility). Calling this repeatedly
- // cycles between a fixed number of display modes.
- void ChangeToNextMode();
-
- // Removes all existing touch points from the screen (only if the HUD is
- // visible).
- void Clear();
-
- // Returns log of touch events as a list value. Each item in the list is a
- // trace of one touch point.
- scoped_ptr<ListValue> GetLogAsList() const;
-
- Mode mode() const { return mode_; }
-
- private:
- friend class TouchHudTest;
-
virtual ~TouchObserverHUD();
- void SetMode(Mode mode);
+ virtual void SetHudForRootWindowController(
+ RootWindowController* controller) = 0;
+ virtual void UnsetHudForRootWindowController(
+ RootWindowController* controller) = 0;
- void UpdateTouchPointLabel(int index);
+ views::Widget* widget() { return widget_; }
- // Overriden from ui::EventHandler:
+ // Overriden from ui::EventHandler.
virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
- // Overridden from views::WidgetObserver:
+ // Overridden from views::WidgetObserver.
virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
- // Overridden from gfx::DisplayObserver:
+ // Overridden from gfx::DisplayObserver.
virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE;
#if defined(OS_CHROMEOS)
- // Overriden from chromeos::OutputConfigurator::Observer:
+ // Overriden from chromeos::OutputConfigurator::Observer.
virtual void OnDisplayModeChanged() OVERRIDE;
#endif // defined(OS_CHROMEOS)
- // Overriden form DisplayController::Observer:
+ // Overriden form DisplayController::Observer.
virtual void OnDisplayConfigurationChanging() OVERRIDE;
virtual void OnDisplayConfigurationChanged() OVERRIDE;
- static const int kMaxTouchPoints = 32;
+ private:
+ friend class TouchHudTest;
const int64 display_id_;
aura::RootWindow* root_window_;
- Mode mode_;
-
- scoped_ptr<TouchLog> touch_log_;
-
views::Widget* widget_;
- TouchHudCanvas* canvas_;
- std::map<int, TouchPointView*> points_;
- views::View* label_container_;
- views::Label* touch_labels_[kMaxTouchPoints];
DISALLOW_COPY_AND_ASSIGN(TouchObserverHUD);
};
diff --git a/ash/touch/touch_observer_hud_unittest.cc b/ash/touch/touch_observer_hud_unittest.cc
index 7e8b91b..0399407 100644
--- a/ash/touch/touch_observer_hud_unittest.cc
+++ b/ash/touch/touch_observer_hud_unittest.cc
@@ -7,8 +7,10 @@
#include "ash/ash_switches.h"
#include "ash/display/display_manager.h"
#include "ash/root_window_controller.h"
+#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/display_manager_test_api.h"
+#include "ash/touch/touch_hud_debug.h"
#include "ash/wm/property_util.h"
#include "base/command_line.h"
#include "base/format_macros.h"
@@ -208,19 +210,19 @@
}
internal::TouchObserverHUD* GetInternalTouchHud() {
- return GetInternalRootController()->touch_observer_hud();
+ return GetInternalRootController()->touch_hud_debug();
}
internal::TouchObserverHUD* GetExternalTouchHud() {
- return GetExternalRootController()->touch_observer_hud();
+ return GetExternalRootController()->touch_hud_debug();
}
internal::TouchObserverHUD* GetPrimaryTouchHud() {
- return GetPrimaryRootController()->touch_observer_hud();
+ return GetPrimaryRootController()->touch_hud_debug();
}
internal::TouchObserverHUD* GetSecondaryTouchHud() {
- return GetSecondaryRootController()->touch_observer_hud();
+ return GetSecondaryRootController()->touch_hud_debug();
}
DisplayInfo CreateDisplayInfo(int64 id, const gfx::Rect& bounds) {
diff --git a/ash/touch/touch_uma.cc b/ash/touch/touch_uma.cc
index 663a319..f8ab0f1 100644
--- a/ash/touch/touch_uma.cc
+++ b/ash/touch/touch_uma.cc
@@ -22,26 +22,6 @@
namespace {
-enum GestureActionType {
- GESTURE_UNKNOWN,
- GESTURE_OMNIBOX_PINCH,
- GESTURE_OMNIBOX_SCROLL,
- GESTURE_TABSTRIP_PINCH,
- GESTURE_TABSTRIP_SCROLL,
- GESTURE_BEZEL_SCROLL,
- GESTURE_DESKTOP_SCROLL,
- GESTURE_DESKTOP_PINCH,
- GESTURE_WEBPAGE_PINCH,
- GESTURE_WEBPAGE_SCROLL,
- GESTURE_WEBPAGE_TAP,
- GESTURE_TABSTRIP_TAP,
- GESTURE_BEZEL_DOWN,
-// NOTE: Add new action types only immediately above this line. Also, make sure
-// the enum list in tools/histogram/histograms.xml is updated with any change in
-// here.
- GESTURE_ACTION_COUNT
-};
-
enum UMAEventType {
UMA_ET_UNKNOWN,
UMA_ET_TOUCH_RELEASED,
@@ -102,72 +82,6 @@
kWindowTouchDetails,
NULL);
-GestureActionType FindGestureActionType(aura::Window* window,
- const ui::GestureEvent& event) {
- if (!window || window->GetRootWindow() == window) {
- if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
- return GESTURE_BEZEL_SCROLL;
- if (event.type() == ui::ET_GESTURE_BEGIN)
- return GESTURE_BEZEL_DOWN;
- return GESTURE_UNKNOWN;
- }
-
- std::string name = window ? window->name() : std::string();
-
- const char kDesktopBackgroundView[] = "DesktopBackgroundView";
- if (name == kDesktopBackgroundView) {
- if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
- return GESTURE_DESKTOP_SCROLL;
- if (event.type() == ui::ET_GESTURE_PINCH_BEGIN)
- return GESTURE_DESKTOP_PINCH;
- return GESTURE_UNKNOWN;
- }
-
- const char kWebPage[] = "RenderWidgetHostViewAura";
- if (name == kWebPage) {
- if (event.type() == ui::ET_GESTURE_PINCH_BEGIN)
- return GESTURE_WEBPAGE_PINCH;
- if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
- return GESTURE_WEBPAGE_SCROLL;
- if (event.type() == ui::ET_GESTURE_TAP)
- return GESTURE_WEBPAGE_TAP;
- return GESTURE_UNKNOWN;
- }
-
- views::Widget* widget = views::Widget::GetWidgetForNativeView(window);
- if (!widget)
- return GESTURE_UNKNOWN;
-
- views::View* view = widget->GetRootView()->
- GetEventHandlerForPoint(event.location());
- if (!view)
- return GESTURE_UNKNOWN;
-
- name = view->GetClassName();
-
- const char kTabStrip[] = "TabStrip";
- const char kTab[] = "BrowserTab";
- if (name == kTabStrip || name == kTab) {
- if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
- return GESTURE_TABSTRIP_SCROLL;
- if (event.type() == ui::ET_GESTURE_PINCH_BEGIN)
- return GESTURE_TABSTRIP_PINCH;
- if (event.type() == ui::ET_GESTURE_TAP)
- return GESTURE_TABSTRIP_TAP;
- return GESTURE_UNKNOWN;
- }
-
- const char kOmnibox[] = "BrowserOmniboxViewViews";
- if (name == kOmnibox) {
- if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
- return GESTURE_OMNIBOX_SCROLL;
- if (event.type() == ui::ET_GESTURE_PINCH_BEGIN)
- return GESTURE_OMNIBOX_PINCH;
- return GESTURE_UNKNOWN;
- }
-
- return GESTURE_UNKNOWN;
-}
UMAEventType UMAEventTypeFromEvent(const ui::Event& event) {
switch (event.type()) {
@@ -257,14 +171,10 @@
}
namespace ash {
-namespace internal {
-TouchUMA::TouchUMA()
- : touch_in_progress_(false),
- burst_length_(0) {
-}
-
-TouchUMA::~TouchUMA() {
+// static
+TouchUMA* TouchUMA::GetInstance() {
+ return Singleton<TouchUMA>::get();
}
void TouchUMA::RecordGestureEvent(aura::Window* target,
@@ -274,11 +184,7 @@
UMA_ET_COUNT);
GestureActionType action = FindGestureActionType(target, event);
- if (action != GESTURE_UNKNOWN) {
- UMA_HISTOGRAM_ENUMERATION("Ash.GestureTarget",
- action,
- GESTURE_ACTION_COUNT);
- }
+ RecordGestureAction(action);
if (event.type() == ui::ET_GESTURE_END &&
event.details().touch_points() == 2) {
@@ -292,6 +198,13 @@
}
}
+void TouchUMA::RecordGestureAction(GestureActionType action) {
+ if (action == GESTURE_UNKNOWN || action >= GESTURE_ACTION_COUNT)
+ return;
+ UMA_HISTOGRAM_ENUMERATION("Ash.GestureTarget", action,
+ GESTURE_ACTION_COUNT);
+}
+
void TouchUMA::RecordTouchEvent(aura::Window* target,
const ui::TouchEvent& event) {
UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchRadius",
@@ -423,6 +336,14 @@
}
}
+TouchUMA::TouchUMA()
+ : touch_in_progress_(false),
+ burst_length_(0) {
+}
+
+TouchUMA::~TouchUMA() {
+}
+
void TouchUMA::UpdateBurstData(const ui::TouchEvent& event) {
if (event.type() == ui::ET_TOUCH_PRESSED) {
if (!touch_in_progress_) {
@@ -445,5 +366,72 @@
}
}
-} // namespace internal
+TouchUMA::GestureActionType TouchUMA::FindGestureActionType(
+ aura::Window* window,
+ const ui::GestureEvent& event) {
+ if (!window || window->GetRootWindow() == window) {
+ if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
+ return GESTURE_BEZEL_SCROLL;
+ if (event.type() == ui::ET_GESTURE_BEGIN)
+ return GESTURE_BEZEL_DOWN;
+ return GESTURE_UNKNOWN;
+ }
+
+ std::string name = window ? window->name() : std::string();
+
+ const char kDesktopBackgroundView[] = "DesktopBackgroundView";
+ if (name == kDesktopBackgroundView) {
+ if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
+ return GESTURE_DESKTOP_SCROLL;
+ if (event.type() == ui::ET_GESTURE_PINCH_BEGIN)
+ return GESTURE_DESKTOP_PINCH;
+ return GESTURE_UNKNOWN;
+ }
+
+ const char kWebPage[] = "RenderWidgetHostViewAura";
+ if (name == kWebPage) {
+ if (event.type() == ui::ET_GESTURE_PINCH_BEGIN)
+ return GESTURE_WEBPAGE_PINCH;
+ if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
+ return GESTURE_WEBPAGE_SCROLL;
+ if (event.type() == ui::ET_GESTURE_TAP)
+ return GESTURE_WEBPAGE_TAP;
+ return GESTURE_UNKNOWN;
+ }
+
+ views::Widget* widget = views::Widget::GetWidgetForNativeView(window);
+ if (!widget)
+ return GESTURE_UNKNOWN;
+
+ views::View* view = widget->GetRootView()->
+ GetEventHandlerForPoint(event.location());
+ if (!view)
+ return GESTURE_UNKNOWN;
+
+ name = view->GetClassName();
+
+ const char kTabStrip[] = "TabStrip";
+ const char kTab[] = "BrowserTab";
+ if (name == kTabStrip || name == kTab) {
+ if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
+ return GESTURE_TABSTRIP_SCROLL;
+ if (event.type() == ui::ET_GESTURE_PINCH_BEGIN)
+ return GESTURE_TABSTRIP_PINCH;
+ if (event.type() == ui::ET_GESTURE_TAP)
+ return GESTURE_TABSTRIP_TAP;
+ return GESTURE_UNKNOWN;
+ }
+
+ const char kOmnibox[] = "BrowserOmniboxViewViews";
+ if (name == kOmnibox) {
+ if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
+ return GESTURE_OMNIBOX_SCROLL;
+ if (event.type() == ui::ET_GESTURE_PINCH_BEGIN)
+ return GESTURE_OMNIBOX_PINCH;
+ return GESTURE_UNKNOWN;
+ }
+
+ return GESTURE_UNKNOWN;
+}
+
} // namespace ash
diff --git a/ash/touch/touch_uma.h b/ash/touch/touch_uma.h
index 46805b1..3e2c7fd 100644
--- a/ash/touch/touch_uma.h
+++ b/ash/touch/touch_uma.h
@@ -8,6 +8,7 @@
#include <map>
#include "ash/shell.h"
+#include "base/memory/singleton.h"
#include "ui/gfx/point.h"
#include "ui/views/widget/widget.h"
@@ -16,22 +17,57 @@
}
namespace ash {
-namespace internal {
// Records some touch/gesture event specific details (e.g. what gestures are
// targetted to which components etc.)
-class TouchUMA {
+class ASH_EXPORT TouchUMA {
public:
- TouchUMA();
- ~TouchUMA();
+ enum GestureActionType {
+ GESTURE_UNKNOWN,
+ GESTURE_OMNIBOX_PINCH,
+ GESTURE_OMNIBOX_SCROLL,
+ GESTURE_TABSTRIP_PINCH,
+ GESTURE_TABSTRIP_SCROLL,
+ GESTURE_BEZEL_SCROLL,
+ GESTURE_DESKTOP_SCROLL,
+ GESTURE_DESKTOP_PINCH,
+ GESTURE_WEBPAGE_PINCH,
+ GESTURE_WEBPAGE_SCROLL,
+ GESTURE_WEBPAGE_TAP,
+ GESTURE_TABSTRIP_TAP,
+ GESTURE_BEZEL_DOWN,
+ GESTURE_TABSWITCH_TAP,
+ GESTURE_TABNOSWITCH_TAP,
+ GESTURE_TABCLOSE_TAP,
+ GESTURE_NEWTAB_TAP,
+ GESTURE_ROOTVIEWTOP_TAP,
+ GESTURE_FRAMEMAXIMIZE_TAP,
+ GESTURE_FRAMEVIEW_TAP,
+ GESTURE_MAXIMIZE_DOUBLETAP,
+ // NOTE: Add new action types only immediately above this line. Also,
+ // make sure the enum list in tools/histogram/histograms.xml is
+ // updated with any change in here.
+ GESTURE_ACTION_COUNT
+ };
+
+ // Returns the singleton instance.
+ static TouchUMA* GetInstance();
void RecordGestureEvent(aura::Window* target,
const ui::GestureEvent& event);
+ void RecordGestureAction(GestureActionType action);
void RecordTouchEvent(aura::Window* target,
const ui::TouchEvent& event);
private:
+ friend struct DefaultSingletonTraits<TouchUMA>;
+
+ TouchUMA();
+ ~TouchUMA();
+
void UpdateBurstData(const ui::TouchEvent& event);
+ GestureActionType FindGestureActionType(aura::Window* window,
+ const ui::GestureEvent& event);
// These are used to measure the number of touch-start events we receive in a
// quick succession, regardless of the target window.
@@ -42,7 +78,6 @@
DISALLOW_COPY_AND_ASSIGN(TouchUMA);
};
-} // namespace internal
} // namespace ash
#endif // ASH_TOUCH_TOUCH_OBSERVER_UMA_H_
diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc
index a13ba65..96b90f6 100644
--- a/ash/wm/app_list_controller.cc
+++ b/ash/wm/app_list_controller.cc
@@ -121,13 +121,31 @@
Shell::GetInstance()->delegate()->CreateAppListViewDelegate());
aura::Window* container = GetRootWindowController(window->GetRootWindow())->
GetContainer(kShellWindowId_AppListContainer);
- view->InitAsBubble(
- container,
- pagination_model_.get(),
- Launcher::ForWindow(container)->GetAppListButtonView(),
- gfx::Point(),
- GetBubbleArrow(container),
- true /* border_accepts_events */);
+ // TODO(harrym): find a better solution for this.
+ if (ash::switches::UseAlternateShelfLayout()) {
+ gfx::Rect applist_button_bounds = Launcher::ForWindow(container)->
+ GetAppListButtonView()->GetBoundsInScreen();
+ gfx::Point anchor = applist_button_bounds.origin();
+ if (anchor.x() == 0)
+ anchor.set_x(applist_button_bounds.right());
+ if (anchor.y() == 0)
+ anchor.set_y(applist_button_bounds.bottom());
+ view->InitAsBubble(
+ container,
+ pagination_model_.get(),
+ NULL,
+ anchor,
+ GetBubbleArrow(container),
+ true /* border_accepts_events */);
+ } else {
+ view->InitAsBubble(
+ container,
+ pagination_model_.get(),
+ Launcher::ForWindow(container)->GetAppListButtonView(),
+ gfx::Point(),
+ GetBubbleArrow(container),
+ true /* border_accepts_events */);
+ }
if (ash::switches::UseAlternateShelfLayout())
view->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
SetView(view);
diff --git a/ash/wm/app_list_controller.h b/ash/wm/app_list_controller.h
index ac163aa..922cbcc 100644
--- a/ash/wm/app_list_controller.h
+++ b/ash/wm/app_list_controller.h
@@ -9,7 +9,7 @@
#include "ash/shell_observer.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/app_list/pagination_model_observer.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/window_observer.h"
diff --git a/ash/wm/boot_splash_screen.h b/ash/wm/boot_splash_screen.h
index dc4538b..f56f49f 100644
--- a/ash/wm/boot_splash_screen.h
+++ b/ash/wm/boot_splash_screen.h
@@ -9,7 +9,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
namespace aura {
class RootWindow;
diff --git a/ash/wm/dock/docked_window_layout_manager_unittest.cc b/ash/wm/dock/docked_window_layout_manager_unittest.cc
index 1c8bad9..e52109f 100644
--- a/ash/wm/dock/docked_window_layout_manager_unittest.cc
+++ b/ash/wm/dock/docked_window_layout_manager_unittest.cc
@@ -215,6 +215,9 @@
// Tests that a created window is successfully added to the dock
// layout manager.
TEST_P(DockedWindowLayoutManagerTest, AddOneWindow) {
+ if (!SupportsHostWindowResize())
+ return;
+
gfx::Rect bounds(0, 0, 201, 201);
scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
diff --git a/ash/wm/dock/docked_window_resizer.cc b/ash/wm/dock/docked_window_resizer.cc
index 931ecb0..780e1bf 100644
--- a/ash/wm/dock/docked_window_resizer.cc
+++ b/ash/wm/dock/docked_window_resizer.cc
@@ -5,7 +5,6 @@
#include "ash/wm/dock/docked_window_resizer.h"
#include "ash/ash_switches.h"
-#include "ash/display/display_controller.h"
#include "ash/launcher/launcher.h"
#include "ash/root_window_controller.h"
#include "ash/screen_ash.h"
diff --git a/ash/wm/dock/docked_window_resizer_unittest.cc b/ash/wm/dock/docked_window_resizer_unittest.cc
index bed2833..7f08981 100644
--- a/ash/wm/dock/docked_window_resizer_unittest.cc
+++ b/ash/wm/dock/docked_window_resizer_unittest.cc
@@ -223,6 +223,9 @@
// Verifies a window can be dragged and attached to the dock.
TEST_P(DockedWindowResizerTest, AttachRightPrecise) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
@@ -235,6 +238,9 @@
// Verifies a window can be dragged and attached to the dock
// even if we overshoot the screen edge by a few pixels (sticky edge)
TEST_P(DockedWindowResizerTest, AttachRightOvershoot) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), +4);
@@ -247,6 +253,9 @@
// Verifies a window can be dragged and then if not quite reaching the screen
// edge it does not get docked to a screen edge and stays in the workspace.
TEST_P(DockedWindowResizerTest, AttachRightUndershoot) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), -1);
@@ -259,6 +268,9 @@
// Verifies a window can be dragged and attached to the dock.
TEST_P(DockedWindowResizerTest, AttachLeftPrecise) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 0);
@@ -271,6 +283,9 @@
// Verifies a window can be dragged and attached to the dock
// even if we overshoot the screen edge by a few pixels (sticky edge)
TEST_P(DockedWindowResizerTest, AttachLeftOvershoot) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), -4);
@@ -283,6 +298,9 @@
// Verifies a window can be dragged and then if not quite reaching the screen
// edge it does not get docked to a screen edge and stays in the workspace.
TEST_P(DockedWindowResizerTest, AttachLeftUndershoot) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 1);
@@ -296,6 +314,9 @@
// Dock on the right side, change shelf alignment, check that windows move to
// the opposite side.
TEST_P(DockedWindowResizerTest, AttachRightChangeShelf) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
@@ -332,6 +353,9 @@
// Dock on the right side, try to undock, then drag more to really undock
TEST_P(DockedWindowResizerTest, AttachTryDetach) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
@@ -366,6 +390,9 @@
// Minimize a docked window, then restore it and check that it is still docked.
TEST_P(DockedWindowResizerTest, AttachMinimizeRestore) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
@@ -452,6 +479,9 @@
// Reverting drag
TEST_P(DockedWindowResizerTest, RevertDragRestoresAttachment) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
diff --git a/ash/wm/drag_window_controller.cc b/ash/wm/drag_window_controller.cc
index 85e2cb4..01ae80f 100644
--- a/ash/wm/drag_window_controller.cc
+++ b/ash/wm/drag_window_controller.cc
@@ -67,7 +67,7 @@
DCHECK(!drag_widget_);
drag_widget_ = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.parent = window_->parent();
params.can_activate = false;
params.keep_on_top = true;
diff --git a/ash/wm/event_rewriter_event_filter.cc b/ash/wm/event_rewriter_event_filter.cc
index 2ef4853..840f498 100644
--- a/ash/wm/event_rewriter_event_filter.cc
+++ b/ash/wm/event_rewriter_event_filter.cc
@@ -8,6 +8,9 @@
#include "base/logging.h"
#include "ui/base/events/event.h"
+#if defined(OS_CHROMEOS)
+#include "ash/wm/sticky_keys.h"
+#endif // OS_CHROMEOS
namespace ash {
namespace internal {
@@ -20,6 +23,13 @@
delegate_ = delegate.Pass();
}
+void EventRewriterEventFilter::EnableStickyKeys(bool enabled) {
+#if defined(OS_CHROMEOS)
+ if (enabled)
+ sticky_keys_.reset(new StickyKeys());
+#endif // OS_CHROMEOS
+}
+
void EventRewriterEventFilter::OnKeyEvent(ui::KeyEvent* event) {
if (!delegate_)
return;
@@ -37,6 +47,14 @@
event->StopPropagation();
break;
}
+
+ if (event->stopped_propagation())
+ return;
+
+#if defined(OS_CHROMEOS)
+ if (sticky_keys_.get() && sticky_keys_->HandleKeyEvent(event))
+ event->StopPropagation();
+#endif // OS_CHROMEOS
}
void EventRewriterEventFilter::OnMouseEvent(ui::MouseEvent* event) {
diff --git a/ash/wm/event_rewriter_event_filter.h b/ash/wm/event_rewriter_event_filter.h
index 6c267a0..87cf07f 100644
--- a/ash/wm/event_rewriter_event_filter.h
+++ b/ash/wm/event_rewriter_event_filter.h
@@ -14,6 +14,9 @@
namespace ash {
class EventRewriterDelegate;
+#if defined(OS_CHROMEOS)
+class StickyKeys;
+#endif // OS_CHROMEOS
namespace internal {
@@ -25,12 +28,18 @@
void SetEventRewriterDelegate(scoped_ptr<EventRewriterDelegate> delegate);
+ // Enables or disables sticky keys.
+ void EnableStickyKeys(bool enabled);
+
private:
// Overridden from ui::EventHandler:
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
scoped_ptr<EventRewriterDelegate> delegate_;
+#if defined(OS_CHROMEOS)
+ scoped_ptr<StickyKeys> sticky_keys_;
+#endif // OS_CHROMEOS
DISALLOW_COPY_AND_ASSIGN(EventRewriterEventFilter);
};
diff --git a/ash/wm/frame_painter.cc b/ash/wm/frame_painter.cc
index 712594f..79e7839 100644
--- a/ash/wm/frame_painter.cc
+++ b/ash/wm/frame_painter.cc
@@ -58,8 +58,10 @@
const int kTitleIconOffsetX = 4;
// Space between window edge and title text, when there is no icon.
const int kTitleNoIconOffsetX = 8;
-// Color for the title text.
-const SkColor kTitleTextColor = SkColorSetRGB(40, 40, 40);
+// Color for the non-maximized window title text.
+const SkColor kNonMaximizedWindowTitleTextColor = SkColorSetRGB(40, 40, 40);
+// Color for the maximized window title text.
+const SkColor kMaximizedWindowTitleTextColor = SK_ColorWHITE;
// Size of header/content separator line below the header image.
const int kHeaderContentSeparatorSize = 1;
// Color of header bottom edge line.
@@ -591,9 +593,11 @@
views::WidgetDelegate* delegate = frame_->widget_delegate();
if (delegate && delegate->ShouldShowWindowTitle()) {
gfx::Rect title_bounds = GetTitleBounds(view, title_font);
+ SkColor title_color = frame_->IsMaximized() ?
+ kMaximizedWindowTitleTextColor : kNonMaximizedWindowTitleTextColor;
canvas->DrawStringInt(delegate->GetWindowTitle(),
title_font,
- kTitleTextColor,
+ title_color,
view->GetMirroredXForRect(title_bounds),
title_bounds.y(),
title_bounds.width(),
diff --git a/ash/wm/gestures/long_press_affordance_handler.cc b/ash/wm/gestures/long_press_affordance_handler.cc
index d35c3f0..5450e97 100644
--- a/ash/wm/gestures/long_press_affordance_handler.cc
+++ b/ash/wm/gestures/long_press_affordance_handler.cc
@@ -66,7 +66,7 @@
params.accept_events = false;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.context = root_window;
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
widget->Init(params);
widget->SetOpacity(0xFF);
ash::GetRootWindowController(root_window)->GetContainer(
diff --git a/ash/wm/gestures/long_press_affordance_handler.h b/ash/wm/gestures/long_press_affordance_handler.h
index c21a587..14ff0f3 100644
--- a/ash/wm/gestures/long_press_affordance_handler.h
+++ b/ash/wm/gestures/long_press_affordance_handler.h
@@ -5,7 +5,7 @@
#ifndef ASH_WM_GESTURES_LONG_PRESS_AFFORDANCE_HANDLER_H_
#define ASH_WM_GESTURES_LONG_PRESS_AFFORDANCE_HANDLER_H_
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/base/animation/animation_delegate.h"
#include "ui/base/animation/linear_animation.h"
#include "ui/gfx/point.h"
diff --git a/ash/wm/lock_state_controller.h b/ash/wm/lock_state_controller.h
index a651b5f..10fce26 100644
--- a/ash/wm/lock_state_controller.h
+++ b/ash/wm/lock_state_controller.h
@@ -12,8 +12,8 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "ui/aura/root_window_observer.h"
namespace gfx {
diff --git a/ash/wm/lock_state_controller_impl2.cc b/ash/wm/lock_state_controller_impl2.cc
index fe7152f..c5301b7 100644
--- a/ash/wm/lock_state_controller_impl2.cc
+++ b/ash/wm/lock_state_controller_impl2.cc
@@ -12,7 +12,7 @@
#include "ash/wm/session_state_animator.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/aura/root_window.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
diff --git a/ash/wm/lock_state_controller_impl2.h b/ash/wm/lock_state_controller_impl2.h
index 2ea1616..8908a7e 100644
--- a/ash/wm/lock_state_controller_impl2.h
+++ b/ash/wm/lock_state_controller_impl2.h
@@ -11,8 +11,8 @@
#include "ash/wm/session_state_animator.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "ui/aura/root_window_observer.h"
namespace gfx {
diff --git a/ash/wm/lock_state_controller_impl2_unittest.cc b/ash/wm/lock_state_controller_impl2_unittest.cc
index 8177422..62bed7c 100644
--- a/ash/wm/lock_state_controller_impl2_unittest.cc
+++ b/ash/wm/lock_state_controller_impl2_unittest.cc
@@ -14,7 +14,7 @@
#include "ash/wm/session_state_animator.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/aura/test/event_generator.h"
diff --git a/ash/wm/maximize_bubble_controller.cc b/ash/wm/maximize_bubble_controller.cc
index f2e3acb..ae108ca 100644
--- a/ash/wm/maximize_bubble_controller.cc
+++ b/ash/wm/maximize_bubble_controller.cc
@@ -9,7 +9,7 @@
#include "ash/shell_window_ids.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/workspace/frame_maximize_button.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "third_party/skia/include/core/SkPath.h"
diff --git a/ash/wm/panels/panel_layout_manager.cc b/ash/wm/panels/panel_layout_manager.cc
index c4ccd11..efb1826 100644
--- a/ash/wm/panels/panel_layout_manager.cc
+++ b/ash/wm/panels/panel_layout_manager.cc
@@ -13,9 +13,11 @@
#include "ash/shelf/shelf_types.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
#include "ash/wm/frame_painter.h"
#include "ash/wm/property_util.h"
#include "ash/wm/window_animations.h"
+#include "ash/wm/window_properties.h"
#include "ash/wm/window_util.h"
#include "base/auto_reset.h"
#include "base/bind.h"
@@ -221,7 +223,7 @@
void InitWidget(aura::Window* parent) {
views::Widget::InitParams params;
params.type = views::Widget::InitParams::TYPE_POPUP;
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.can_activate = false;
params.keep_on_top = true;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
@@ -250,6 +252,7 @@
// PanelLayoutManager public implementation:
PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container)
: panel_container_(panel_container),
+ in_add_window_(false),
in_layout_(false),
dragged_panel_(NULL),
launcher_(NULL),
@@ -328,6 +331,22 @@
void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
if (child->type() == aura::client::WINDOW_TYPE_POPUP)
return;
+ if (in_add_window_)
+ return;
+ base::AutoReset<bool> auto_reset_in_add_window(&in_add_window_, true);
+ if (!child->GetProperty(kPanelAttachedKey)) {
+ // This should only happen when a window is added to panel container as a
+ // result of bounds change from within the application during a drag.
+ // If so we have already stopped the drag and should reparent the panel
+ // back to appropriate container and ignore it.
+ // TODO(varkha): Updating bounds during a drag can cause problems and a more
+ // general solution is needed. See http://crbug.com/251813 .
+ child->SetDefaultParentByRootWindow(
+ child->GetRootWindow(),
+ child->GetRootWindow()->GetBoundsInScreen());
+ DCHECK(child->parent()->id() != kShellWindowId_PanelContainer);
+ return;
+ }
PanelInfo panel_info;
panel_info.window = child;
panel_info.callout_widget = new PanelCalloutWidget(panel_container_);
diff --git a/ash/wm/panels/panel_layout_manager.h b/ash/wm/panels/panel_layout_manager.h
index 0a79824..04fa589 100644
--- a/ash/wm/panels/panel_layout_manager.h
+++ b/ash/wm/panels/panel_layout_manager.h
@@ -152,6 +152,8 @@
// Parent window associated with this layout manager.
aura::Window* panel_container_;
+ // Protect against recursive calls to OnWindowAddedToLayout().
+ bool in_add_window_;
// Protect against recursive calls to Relayout().
bool in_layout_;
// Ordered list of unowned pointers to panel windows.
diff --git a/ash/wm/panels/panel_window_event_handler.cc b/ash/wm/panels/panel_window_event_handler.cc
new file mode 100644
index 0000000..2509196
--- /dev/null
+++ b/ash/wm/panels/panel_window_event_handler.cc
@@ -0,0 +1,49 @@
+// 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/wm/panels/panel_window_event_handler.h"
+
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
+#include "ui/base/events/event.h"
+#include "ui/base/hit_test.h"
+
+namespace ash {
+namespace internal {
+
+PanelWindowEventHandler::PanelWindowEventHandler(aura::Window* owner)
+ : ToplevelWindowEventHandler(owner) {
+}
+
+PanelWindowEventHandler::~PanelWindowEventHandler() {
+}
+
+void PanelWindowEventHandler::OnMouseEvent(ui::MouseEvent* event) {
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ if (event->type() == ui::ET_MOUSE_PRESSED &&
+ event->flags() & ui::EF_IS_DOUBLE_CLICK &&
+ target->delegate()->GetNonClientComponent(event->location()) ==
+ HTCAPTION) {
+ target->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
+ return;
+ }
+ ToplevelWindowEventHandler::OnMouseEvent(event);
+}
+
+void PanelWindowEventHandler::OnGestureEvent(ui::GestureEvent* event) {
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ if (event->type() == ui::ET_GESTURE_TAP &&
+ event->details().tap_count() == 2 &&
+ target->delegate()->GetNonClientComponent(event->location()) ==
+ HTCAPTION) {
+ target->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
+ event->StopPropagation();
+ return;
+ }
+ ToplevelWindowEventHandler::OnGestureEvent(event);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/wm/panels/panel_window_event_handler.h b/ash/wm/panels/panel_window_event_handler.h
new file mode 100644
index 0000000..2823b88
--- /dev/null
+++ b/ash/wm/panels/panel_window_event_handler.h
@@ -0,0 +1,35 @@
+// 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_WM_PANELS_PANEL_WINDOW_EVENT_HANDLER_H_
+#define ASH_WM_PANELS_PANEL_WINDOW_EVENT_HANDLER_H_
+
+#include "ash/wm/toplevel_window_event_handler.h"
+
+namespace aura {
+class Window;
+}
+
+namespace ash {
+namespace internal {
+
+// PanelWindowEventHandler minimizes panels when the user double clicks or
+// double taps on the panel header.
+class PanelWindowEventHandler : public ToplevelWindowEventHandler {
+ public:
+ explicit PanelWindowEventHandler(aura::Window* owner);
+ virtual ~PanelWindowEventHandler();
+
+ // TopLevelWindowEventHandler:
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PanelWindowEventHandler);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_WM_PANELS_PANEL_WINDOW_EVENT_HANDLER_H_
diff --git a/ash/wm/panels/panel_window_resizer.cc b/ash/wm/panels/panel_window_resizer.cc
index 1c054b4..7f14280 100644
--- a/ash/wm/panels/panel_window_resizer.cc
+++ b/ash/wm/panels/panel_window_resizer.cc
@@ -64,13 +64,11 @@
did_move_or_resize_ = true;
StartedDragging();
}
- gfx::Point location_in_screen = location;
- wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
// Check if the destination has changed displays.
gfx::Screen* screen = Shell::GetScreen();
const gfx::Display dst_display =
- screen->GetDisplayNearestPoint(location_in_screen);
+ screen->GetDisplayNearestPoint(last_location_);
if (dst_display.id() !=
screen->GetDisplayNearestWindow(panel_container_->GetRootWindow()).id()) {
// The panel is being dragged to a new display. If the previous container is
@@ -198,9 +196,11 @@
// Attach the panel while dragging placing it in front of other panels.
GetTarget()->SetProperty(internal::kContinueDragAfterReparent, true);
GetTarget()->SetProperty(internal::kPanelAttachedKey, true);
+ // We use root window coordinates to ensure that during the drag the panel
+ // is reparented to a container in the root window that has that window.
GetTarget()->SetDefaultParentByRootWindow(
GetTarget()->GetRootWindow(),
- GetTarget()->GetBoundsInScreen());
+ GetTarget()->GetRootWindow()->GetBoundsInScreen());
}
}
@@ -210,9 +210,11 @@
if (GetTarget()->GetProperty(internal::kPanelAttachedKey) !=
should_attach_) {
GetTarget()->SetProperty(internal::kPanelAttachedKey, should_attach_);
- gfx::Rect near_last_location(last_location_, gfx::Size());
- GetTarget()->SetDefaultParentByRootWindow(GetTarget()->GetRootWindow(),
- near_last_location);
+ // We use last known location to ensure that after the drag the panel
+ // is reparented to a container in the root window that has that location.
+ GetTarget()->SetDefaultParentByRootWindow(
+ GetTarget()->GetRootWindow(),
+ gfx::Rect(last_location_, gfx::Size()));
}
if (panel_container_)
GetPanelLayoutManager(panel_container_)->FinishDragging();
diff --git a/ash/wm/panels/panel_window_resizer_unittest.cc b/ash/wm/panels/panel_window_resizer_unittest.cc
index a0d493e..bc7465e 100644
--- a/ash/wm/panels/panel_window_resizer_unittest.cc
+++ b/ash/wm/panels/panel_window_resizer_unittest.cc
@@ -221,12 +221,18 @@
// Verifies a window can be dragged from the panel and detached and then
// reattached.
TEST_F(PanelWindowResizerTest, PanelDetachReattachBottom) {
+ if (!SupportsHostWindowResize())
+ return;
+
scoped_ptr<aura::Window> window(
CreatePanelWindow(gfx::Rect(0, 0, 201, 201)));
DetachReattachTest(window.get(), 0, -1);
}
TEST_F(PanelWindowResizerTest, PanelDetachReattachLeft) {
+ if (!SupportsHostWindowResize())
+ return;
+
ash::Shell* shell = ash::Shell::GetInstance();
shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
scoped_ptr<aura::Window> window(
@@ -252,6 +258,9 @@
}
TEST_F(PanelWindowResizerTest, PanelDetachReattachTop) {
+ if (!SupportsHostWindowResize())
+ return;
+
ash::Shell* shell = ash::Shell::GetInstance();
shell->SetShelfAlignment(SHELF_ALIGNMENT_TOP, shell->GetPrimaryRootWindow());
scoped_ptr<aura::Window> window(
@@ -432,6 +441,9 @@
}
TEST_P(PanelWindowResizerTextDirectionTest, DragReordersPanelsHorizontal) {
+ if (!SupportsHostWindowResize())
+ return;
+
DragAlongShelfReorder(base::i18n::IsRTL() ? 1 : -1, 0);
}
diff --git a/ash/wm/partial_screenshot_view.cc b/ash/wm/partial_screenshot_view.cc
index 032c91b..1b2fa66 100644
--- a/ash/wm/partial_screenshot_view.cc
+++ b/ash/wm/partial_screenshot_view.cc
@@ -112,7 +112,7 @@
views::Widget* widget = new views::Widget;
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.delegate = this;
// The partial screenshot rectangle has to be at the real top of
// the screen.
diff --git a/ash/wm/power_button_controller_unittest.cc b/ash/wm/power_button_controller_unittest.cc
index 5ee1e27..e1ce71b 100644
--- a/ash/wm/power_button_controller_unittest.cc
+++ b/ash/wm/power_button_controller_unittest.cc
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ash/wm/lock_state_controller.h"
-#include "ash/wm/power_button_controller.h"
-#include "ash/wm/session_state_animator.h"
-#include "ash/wm/session_state_controller_impl.h"
#include "ash/ash_switches.h"
#include "ash/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/test_shell_delegate.h"
+#include "ash/wm/lock_state_controller.h"
+#include "ash/wm/power_button_controller.h"
+#include "ash/wm/session_state_animator.h"
+#include "ash/wm/session_state_controller_impl.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/aura/test/event_generator.h"
diff --git a/ash/wm/resize_shadow.cc b/ash/wm/resize_shadow.cc
index 27ed2b7..cdf573d 100644
--- a/ash/wm/resize_shadow.cc
+++ b/ash/wm/resize_shadow.cc
@@ -4,7 +4,7 @@
#include "ash/wm/resize_shadow.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "grit/ash_resources.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
diff --git a/ash/wm/root_window_layout_manager.cc b/ash/wm/root_window_layout_manager.cc
index 481fe3f..584bc06 100644
--- a/ash/wm/root_window_layout_manager.cc
+++ b/ash/wm/root_window_layout_manager.cc
@@ -5,7 +5,9 @@
#include "ash/wm/root_window_layout_manager.h"
#include "ash/desktop_background/desktop_background_widget_controller.h"
-#include "ui/aura/window.h"
+#include "ash/root_window_controller.h"
+#include "ash/wm/property_util.h"
+#include "ui/aura/root_window.h"
#include "ui/compositor/layer.h"
#include "ui/views/widget/widget.h"
@@ -39,10 +41,13 @@
for (j = (*i)->children().begin(); j != (*i)->children().end(); ++j)
(*j)->SetBounds(fullscreen_bounds);
}
- internal::DesktopBackgroundWidgetController* background =
- owner_->GetProperty(kDesktopController);
- if (!background && owner_->GetProperty(kAnimatingDesktopController)) {
- background = owner_->GetProperty(kAnimatingDesktopController)->
+ RootWindowController* root_window_controller = GetRootWindowController(
+ static_cast<aura::RootWindow*>(owner_));
+ DesktopBackgroundWidgetController* background =
+ root_window_controller->wallpaper_controller();
+
+ if (!background && root_window_controller->animating_wallpaper_controller()) {
+ background = root_window_controller->animating_wallpaper_controller()->
GetController(false);
}
if (background)
diff --git a/ash/wm/screen_dimmer.cc b/ash/wm/screen_dimmer.cc
index 814620a..101d69b 100644
--- a/ash/wm/screen_dimmer.cc
+++ b/ash/wm/screen_dimmer.cc
@@ -5,7 +5,7 @@
#include "ash/wm/screen_dimmer.h"
#include "ash/shell.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/root_window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
diff --git a/ash/wm/session_state_animator.h b/ash/wm/session_state_animator.h
index cfd79d5..19ead2f 100644
--- a/ash/wm/session_state_animator.h
+++ b/ash/wm/session_state_animator.h
@@ -9,7 +9,7 @@
#include "ash/wm/workspace/colored_window_controller.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer_animation_observer.h"
diff --git a/ash/wm/session_state_controller_impl.h b/ash/wm/session_state_controller_impl.h
index 79a5c2c..3ffc221 100644
--- a/ash/wm/session_state_controller_impl.h
+++ b/ash/wm/session_state_controller_impl.h
@@ -11,8 +11,8 @@
#include "ash/wm/session_state_animator.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "ui/aura/root_window_observer.h"
namespace gfx {
diff --git a/ash/wm/stacking_controller.cc b/ash/wm/stacking_controller.cc
index 7b3337f..24f38d5 100644
--- a/ash/wm/stacking_controller.cc
+++ b/ash/wm/stacking_controller.cc
@@ -4,12 +4,13 @@
#include "ash/wm/stacking_controller.h"
-#include "ash/display/display_controller.h"
+#include "ash/root_window_controller.h"
#include "ash/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/always_on_top_controller.h"
#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/property_util.h"
#include "ash/wm/window_properties.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/root_window.h"
@@ -53,6 +54,11 @@
return window->GetProperty(internal::kPanelAttachedKey);
}
+internal::AlwaysOnTopController*
+GetAlwaysOnTopController(aura::RootWindow* root_window) {
+ return GetRootWindowController(root_window)->always_on_top_controller();
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -145,20 +151,4 @@
return container;
}
-// TODO(oshima): Remove this once extended desktop is on by default.
-internal::AlwaysOnTopController*
-StackingController::GetAlwaysOnTopController(aura::RootWindow* root_window) {
- internal::AlwaysOnTopController* controller =
- root_window->GetProperty(internal::kAlwaysOnTopControllerKey);
- if (!controller) {
- controller = new internal::AlwaysOnTopController;
- controller->SetAlwaysOnTopContainer(
- root_window->GetChildById(
- internal::kShellWindowId_AlwaysOnTopContainer));
- // RootWindow owns the AlwaysOnTopController object.
- root_window->SetProperty(internal::kAlwaysOnTopControllerKey, controller);
- }
- return controller;
-}
-
} // namespace ash
diff --git a/ash/wm/stacking_controller.h b/ash/wm/stacking_controller.h
index 21611ed..07003cb 100644
--- a/ash/wm/stacking_controller.h
+++ b/ash/wm/stacking_controller.h
@@ -40,10 +40,6 @@
aura::Window* GetSystemModalContainer(aura::RootWindow* root,
aura::Window* window) const;
- // Returns the AlwaysOnTopController of the |root_window|.
- internal::AlwaysOnTopController* GetAlwaysOnTopController(
- aura::RootWindow* root_window);
-
DISALLOW_COPY_AND_ASSIGN(StackingController);
};
diff --git a/ash/wm/system_gesture_event_filter.cc b/ash/wm/system_gesture_event_filter.cc
index 029ab72..b368822 100644
--- a/ash/wm/system_gesture_event_filter.cc
+++ b/ash/wm/system_gesture_event_filter.cc
@@ -52,8 +52,7 @@
}
void SystemGestureEventFilter::OnMouseEvent(ui::MouseEvent* event) {
-// TODO(rjkroege): Remove USE_MESSAGEPUMP_LINUX guard once mice are supported.
-#if defined(OS_CHROMEOS) && !defined(USE_MESSAGEPUMP_LINUX)
+#if defined(OS_CHROMEOS) && !defined(USE_OZONE)
if (event->type() == ui::ET_MOUSE_PRESSED && event->native_event() &&
ui::TouchFactory::GetInstance()->IsTouchDevicePresent() &&
Shell::GetInstance()->delegate()) {
@@ -65,13 +64,13 @@
void SystemGestureEventFilter::OnTouchEvent(ui::TouchEvent* event) {
aura::Window* target = static_cast<aura::Window*>(event->target());
- touch_uma_.RecordTouchEvent(target, *event);
+ ash::TouchUMA::GetInstance()->RecordTouchEvent(target, *event);
long_press_affordance_->ProcessEvent(target, event, event->touch_id());
}
void SystemGestureEventFilter::OnGestureEvent(ui::GestureEvent* event) {
aura::Window* target = static_cast<aura::Window*>(event->target());
- touch_uma_.RecordGestureEvent(target, *event);
+ ash::TouchUMA::GetInstance()->RecordGestureEvent(target, *event);
long_press_affordance_->ProcessEvent(target, event,
event->GetLowestTouchId());
diff --git a/ash/wm/system_gesture_event_filter.h b/ash/wm/system_gesture_event_filter.h
index 182ed5a..a2a5c73 100644
--- a/ash/wm/system_gesture_event_filter.h
+++ b/ash/wm/system_gesture_event_filter.h
@@ -7,7 +7,7 @@
#include "ash/shell.h"
#include "ash/touch/touch_uma.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
#include "ui/base/animation/animation_delegate.h"
#include "ui/base/animation/linear_animation.h"
@@ -69,8 +69,6 @@
scoped_ptr<LongPressAffordanceHandler> long_press_affordance_;
scoped_ptr<TwoFingerDragHandler> two_finger_drag_;
- TouchUMA touch_uma_;
-
DISALLOW_COPY_AND_ASSIGN(SystemGestureEventFilter);
};
diff --git a/ash/wm/system_gesture_event_filter_unittest.cc b/ash/wm/system_gesture_event_filter_unittest.cc
index ce02fad..2238d47 100644
--- a/ash/wm/system_gesture_event_filter_unittest.cc
+++ b/ash/wm/system_gesture_event_filter_unittest.cc
@@ -20,8 +20,8 @@
#include "ash/wm/gestures/long_press_affordance_handler.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "ui/aura/root_window.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_windows.h"
diff --git a/ash/wm/user_activity_detector.h b/ash/wm/user_activity_detector.h
index a15b0d4..0a4ad48 100644
--- a/ash/wm/user_activity_detector.h
+++ b/ash/wm/user_activity_detector.h
@@ -9,7 +9,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/base/events/event_handler.h"
namespace ash {
diff --git a/ash/wm/user_activity_detector_unittest.cc b/ash/wm/user_activity_detector_unittest.cc
index 66306f7..75af6cc 100644
--- a/ash/wm/user_activity_detector_unittest.cc
+++ b/ash/wm/user_activity_detector_unittest.cc
@@ -9,7 +9,7 @@
#include "ash/wm/user_activity_observer.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/base/events/event.h"
diff --git a/ash/wm/video_detector.h b/ash/wm/video_detector.h
index 81fd2da..7a2b112 100644
--- a/ash/wm/video_detector.h
+++ b/ash/wm/video_detector.h
@@ -14,7 +14,7 @@
#include "base/memory/linked_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observer.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/env_observer.h"
#include "ui/aura/window_observer.h"
diff --git a/ash/wm/video_detector_unittest.cc b/ash/wm/video_detector_unittest.cc
index 187742c..96e0787 100644
--- a/ash/wm/video_detector_unittest.cc
+++ b/ash/wm/video_detector_unittest.cc
@@ -9,7 +9,7 @@
#include "ash/wm/window_util.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/window_types.h"
diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc
index f490a67..bd17770 100644
--- a/ash/wm/window_animations.cc
+++ b/ash/wm/window_animations.cc
@@ -13,14 +13,14 @@
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/wm/window_util.h"
-#include "ash/wm/workspace_controller.h"
#include "ash/wm/workspace/workspace_animations.h"
+#include "ash/wm/workspace_controller.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
@@ -396,13 +396,22 @@
}
void CrossFadeToBounds(aura::Window* window, const gfx::Rect& new_bounds) {
- DCHECK(window->TargetVisibility());
+ // Some test results in invoking CrossFadeToBounds when window is not visible.
+ // No animation is necessary in that case, thus just change the bounds and
+ // quit.
+ if (!window->TargetVisibility()) {
+ window->SetBounds(new_bounds);
+ return;
+ }
+
const gfx::Rect old_bounds = window->bounds();
// Create fresh layers for the window and all its children to paint into.
// Takes ownership of the old layer and all its children, which will be
// cleaned up after the animation completes.
- ui::Layer* old_layer = views::corewm::RecreateWindowLayers(window, false);
+ // Specify |set_bounds| to true here to keep the old bounds in the child
+ // windows of |window|.
+ ui::Layer* old_layer = views::corewm::RecreateWindowLayers(window, true);
ui::Layer* new_layer = window->layer();
// Resize the window to the new size, which will force a layout and paint.
diff --git a/ash/wm/window_animations_unittest.cc b/ash/wm/window_animations_unittest.cc
index a8646b6..d5680cc 100644
--- a/ash/wm/window_animations_unittest.cc
+++ b/ash/wm/window_animations_unittest.cc
@@ -7,7 +7,7 @@
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/workspace_controller.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/base/animation/animation_container_element.h"
diff --git a/ash/wm/window_cycle_controller_unittest.cc b/ash/wm/window_cycle_controller_unittest.cc
index e639258..8e74543 100644
--- a/ash/wm/window_cycle_controller_unittest.cc
+++ b/ash/wm/window_cycle_controller_unittest.cc
@@ -6,8 +6,6 @@
#include <algorithm>
-#include "ash/display/display_controller.h"
-#include "ash/display/display_manager.h"
#include "ash/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
diff --git a/ash/wm/window_cycle_list.cc b/ash/wm/window_cycle_list.cc
index 7ea875b..fd39d0f 100644
--- a/ash/wm/window_cycle_list.cc
+++ b/ash/wm/window_cycle_list.cc
@@ -6,6 +6,7 @@
#include "ash/wm/window_util.h"
#include "ui/aura/window.h"
+#include "ui/views/corewm/window_animations.h"
namespace ash {
@@ -41,8 +42,12 @@
// provided window list. Just switch to the first (or last) one.
current_index_ = (direction == FORWARD ? 0 : windows_.size() - 1);
} else {
- if (windows_.size() == 1)
+ // When there is only one window, we should give a feedback to user.
+ if (windows_.size() == 1) {
+ AnimateWindow(windows_[0],
+ views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE);
return;
+ }
// We're in a valid cycle, so step forward or backward.
current_index_ += (direction == FORWARD ? 1 : -1);
}
diff --git a/ash/wm/window_properties.cc b/ash/wm/window_properties.cc
index 64d55a7..9dda017 100644
--- a/ash/wm/window_properties.cc
+++ b/ash/wm/window_properties.cc
@@ -5,21 +5,16 @@
#include "ash/wm/window_properties.h"
#include "ash/root_window_controller.h"
-#include "ash/wm/always_on_top_controller.h"
#include "ash/wm/frame_painter.h"
#include "ui/aura/window_property.h"
#include "ui/gfx/rect.h"
-DECLARE_WINDOW_PROPERTY_TYPE(ash::internal::AlwaysOnTopController*);
DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(ASH_EXPORT, ash::FramePainter*);
DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowPersistsAcrossAllWorkspacesType)
DECLARE_WINDOW_PROPERTY_TYPE(ash::internal::RootWindowController*);
namespace ash {
namespace internal {
-DEFINE_OWNED_WINDOW_PROPERTY_KEY(ash::internal::AlwaysOnTopController,
- kAlwaysOnTopControllerKey,
- NULL);
DEFINE_WINDOW_PROPERTY_KEY(bool, kContinueDragAfterReparent, false);
DEFINE_WINDOW_PROPERTY_KEY(bool, kCyclingThroughWorkspacesKey, false);
DEFINE_WINDOW_PROPERTY_KEY(bool, kFullscreenUsesMinimalChromeKey, false);
diff --git a/ash/wm/window_properties.h b/ash/wm/window_properties.h
index ae30435..c5bba1f 100644
--- a/ash/wm/window_properties.h
+++ b/ash/wm/window_properties.h
@@ -17,18 +17,12 @@
namespace ash {
class FramePainter;
namespace internal {
-class AlwaysOnTopController;
class RootWindowController;
// Shell-specific window property keys.
// Alphabetical sort.
-// A Key to store AlwaysOnTopController per RootWindow. The value is
-// owned by the RootWindow.
-extern const aura::WindowProperty<internal::AlwaysOnTopController*>* const
- kAlwaysOnTopControllerKey;
-
// A property key to indicate that an in progress drag should be continued
// after the window is reparented to another container.
extern const aura::WindowProperty<bool>* const kContinueDragAfterReparent;
diff --git a/ash/wm/workspace/desktop_background_fade_controller.cc b/ash/wm/workspace/desktop_background_fade_controller.cc
index 68628b88..563d07b 100644
--- a/ash/wm/workspace/desktop_background_fade_controller.cc
+++ b/ash/wm/workspace/desktop_background_fade_controller.cc
@@ -6,7 +6,7 @@
#include "ash/wm/window_animations.h"
#include "ash/wm/workspace/colored_window_controller.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/aura/window.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/views/widget/widget.h"
diff --git a/ash/wm/workspace/frame_maximize_button.cc b/ash/wm/workspace/frame_maximize_button.cc
index 0329e3f..23ca750 100644
--- a/ash/wm/workspace/frame_maximize_button.cc
+++ b/ash/wm/workspace/frame_maximize_button.cc
@@ -9,6 +9,7 @@
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
+#include "ash/touch/touch_uma.h"
#include "ash/wm/maximize_bubble_controller.h"
#include "ash/wm/property_util.h"
#include "ash/wm/window_properties.h"
@@ -279,8 +280,11 @@
// 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)
+ if (event->type() == ui::ET_GESTURE_TAP) {
snap_type_ = SnapTypeForLocation(event->location());
+ TouchUMA::GetInstance()->RecordGestureAction(
+ TouchUMA::GESTURE_FRAMEMAXIMIZE_TAP);
+ }
ProcessEndEvent(*event);
event->SetHandled();
return;
diff --git a/ash/wm/workspace/frame_maximize_button.h b/ash/wm/workspace/frame_maximize_button.h
index 6429aed..f01df6c 100644
--- a/ash/wm/workspace/frame_maximize_button.h
+++ b/ash/wm/workspace/frame_maximize_button.h
@@ -9,7 +9,7 @@
#include "ash/wm/workspace/maximize_bubble_frame_state.h"
#include "ash/wm/workspace/snap_types.h"
#include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/widget/widget_observer.h"
diff --git a/ash/wm/workspace/multi_window_resize_controller.cc b/ash/wm/workspace/multi_window_resize_controller.cc
index 8880e33..c447b9c 100644
--- a/ash/wm/workspace/multi_window_resize_controller.cc
+++ b/ash/wm/workspace/multi_window_resize_controller.cc
@@ -384,7 +384,7 @@
show_timer_.Stop();
resize_widget_.reset(new views::Widget);
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.parent = Shell::GetContainer(
Shell::GetActiveRootWindow(),
diff --git a/ash/wm/workspace/multi_window_resize_controller.h b/ash/wm/workspace/multi_window_resize_controller.h
index 85f7c27..02eeb25 100644
--- a/ash/wm/workspace/multi_window_resize_controller.h
+++ b/ash/wm/workspace/multi_window_resize_controller.h
@@ -10,7 +10,7 @@
#include "ash/ash_export.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
#include "ui/gfx/rect.h"
#include "ui/views/mouse_watcher.h"
diff --git a/ash/wm/workspace/phantom_window_controller.cc b/ash/wm/workspace/phantom_window_controller.cc
index 8cdbd0c..4287d5b 100644
--- a/ash/wm/workspace/phantom_window_controller.cc
+++ b/ash/wm/workspace/phantom_window_controller.cc
@@ -137,7 +137,7 @@
DCHECK(!phantom_widget_);
phantom_widget_ = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
- params.transparent = true;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
// PhantomWindowController is used by FrameMaximizeButton to highlight the
// launcher button. Put the phantom in the same window as the launcher so that
// the phantom is visible.
diff --git a/ash/wm/workspace/snap_sizer.h b/ash/wm/workspace/snap_sizer.h
index b283258..bd5f719 100644
--- a/ash/wm/workspace/snap_sizer.h
+++ b/ash/wm/workspace/snap_sizer.h
@@ -9,7 +9,7 @@
#include "ash/ash_export.h"
#include "base/basictypes.h"
-#include "base/time.h"
+#include "base/time/time.h"
#include "ui/gfx/rect.h"
namespace aura {
diff --git a/ash/wm/workspace/workspace_animations.h b/ash/wm/workspace/workspace_animations.h
index 3e60c1b..39d84a2 100644
--- a/ash/wm/workspace/workspace_animations.h
+++ b/ash/wm/workspace/workspace_animations.h
@@ -6,7 +6,7 @@
#define ASH_WM_WORKSPACE_WORKSPACE_ANIMATIONS_H_
#include "ash/ash_export.h"
-#include "base/time.h"
+#include "base/time/time.h"
namespace aura {
class Window;
diff --git a/ash/wm/workspace/workspace_event_handler.cc b/ash/wm/workspace/workspace_event_handler.cc
index 828f024..6bf384c 100644
--- a/ash/wm/workspace/workspace_event_handler.cc
+++ b/ash/wm/workspace/workspace_event_handler.cc
@@ -7,6 +7,7 @@
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
+#include "ash/touch/touch_uma.h"
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/property_util.h"
#include "ash/wm/window_util.h"
@@ -119,14 +120,23 @@
void WorkspaceEventHandler::OnGestureEvent(ui::GestureEvent* event) {
aura::Window* target = static_cast<aura::Window*>(event->target());
if (event->type() == ui::ET_GESTURE_TAP &&
- event->details().tap_count() == 2 &&
target->delegate()->GetNonClientComponent(event->location()) ==
HTCAPTION) {
- ash::Shell::GetInstance()->delegate()->RecordUserMetricsAction(
- ash::UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE);
- ToggleMaximizedState(target); // |this| may be destroyed from here.
- event->StopPropagation();
- return;
+ if (event->details().tap_count() == 2) {
+ ash::Shell::GetInstance()->delegate()->RecordUserMetricsAction(
+ ash::UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE);
+ // Note: TouchUMA::GESTURE_FRAMEVIEW_TAP is counted twice each time
+ // TouchUMA::GESTURE_MAXIMIZE_DOUBLETAP is counted once.
+ TouchUMA::GetInstance()->RecordGestureAction(
+ TouchUMA::GESTURE_MAXIMIZE_DOUBLETAP);
+ ToggleMaximizedState(target); // |this| may be destroyed from here.
+ event->StopPropagation();
+ return;
+ } else {
+ // Note: TouchUMA::GESTURE_FRAMEVIEW_TAP is counted twice for each tap.
+ TouchUMA::GetInstance()->RecordGestureAction(
+ TouchUMA::GESTURE_FRAMEVIEW_TAP);
+ }
}
ToplevelWindowEventHandler::OnGestureEvent(event);
}
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc
index 6e9feca..de32a1d 100644
--- a/ash/wm/workspace/workspace_layout_manager.cc
+++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -5,11 +5,13 @@
#include "ash/wm/workspace/workspace_layout_manager.h"
#include "ash/ash_switches.h"
+#include "ash/root_window_controller.h"
#include "ash/screen_ash.h"
#include "ash/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/wm/always_on_top_controller.h"
#include "ash/wm/base_layout_manager.h"
+#include "ash/wm/property_util.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_properties.h"
#include "ash/wm/window_util.h"
@@ -230,18 +232,15 @@
if (key == internal::kWindowTrackedByWorkspaceKey &&
GetTrackedByWorkspace(window)) {
workspace_manager()->OnTrackedByWorkspaceChanged(workspace_, window);
- if (wm::IsWindowMaximized(window)) {
- SetChildBoundsDirect(
- window, ScreenAsh::GetMaximizedWindowBoundsInParent(
- window->parent()->parent()));
- }
+ if (wm::IsWindowMaximized(window))
+ SetMaximizedOrFullscreenBounds(window);
}
if (key == aura::client::kAlwaysOnTopKey &&
window->GetProperty(aura::client::kAlwaysOnTopKey)) {
internal::AlwaysOnTopController* controller =
- window->GetRootWindow()->GetProperty(
- internal::kAlwaysOnTopControllerKey);
+ GetRootWindowController(window->GetRootWindow())->
+ always_on_top_controller();
controller->GetContainer(window)->AddChild(window);
}
}
@@ -355,7 +354,7 @@
gfx::Rect bounds_in_parent =
ScreenAsh::ConvertRectFromScreen(window->parent()->parent(),
*restore);
- SetChildBoundsDirect(
+ CrossFadeToBounds(
window,
BaseLayoutManager::BoundsWithScreenEdgeVisible(
window->parent()->parent(),
@@ -366,6 +365,9 @@
}
case ui::SHOW_STATE_MAXIMIZED:
+ CrossFadeToBounds(window, ScreenAsh::GetMaximizedWindowBoundsInParent(
+ window->parent()->parent()));
+ break;
case ui::SHOW_STATE_FULLSCREEN:
SetMaximizedOrFullscreenBounds(window);
break;
diff --git a/ash/wm/workspace/workspace_manager.cc b/ash/wm/workspace/workspace_manager.cc
index b23f5c4..a060df2 100644
--- a/ash/wm/workspace/workspace_manager.cc
+++ b/ash/wm/workspace/workspace_manager.cc
@@ -368,12 +368,12 @@
contents_window_->StackChildAtTop(last_active->window());
}
- UpdateShelfVisibility();
-
// NOTE: duration supplied to this method is only used for desktop background.
HideWorkspace(last_active, reason, is_unminimizing_fullscreen_window);
ShowWorkspace(workspace, last_active, reason);
+ UpdateShelfVisibility();
+
RootWindowController* root_controller = GetRootWindowController(
contents_window_->GetRootWindow());
if (root_controller) {
diff --git a/ash/wm/workspace/workspace_manager.h b/ash/wm/workspace/workspace_manager.h
index f070e62..b7ef571 100644
--- a/ash/wm/workspace/workspace_manager.h
+++ b/ash/wm/workspace/workspace_manager.h
@@ -15,8 +15,8 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "ui/base/ui_base_types.h"
namespace aura {
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc
index 4472815..cf2d8b0 100644
--- a/ash/wm/workspace/workspace_window_resizer.cc
+++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -10,7 +10,6 @@
#include <vector>
#include "ash/ash_switches.h"
-#include "ash/display/display_controller.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"