diff options
-rw-r--r-- | ash/accelerators/accelerator_controller.cc | 35 | ||||
-rw-r--r-- | ash/accelerators/accelerator_table.cc | 12 | ||||
-rw-r--r-- | ash/accelerators/accelerator_table.h | 2 | ||||
-rw-r--r-- | ash/extended_desktop_unittest.cc | 70 | ||||
-rw-r--r-- | ash/root_window_controller.cc | 4 | ||||
-rw-r--r-- | ash/root_window_controller.h | 3 | ||||
-rw-r--r-- | ash/shell.cc | 10 | ||||
-rw-r--r-- | ash/shell.h | 4 | ||||
-rw-r--r-- | ash/wm/event_client_impl.cc | 22 | ||||
-rw-r--r-- | ash/wm/event_client_impl.h | 4 | ||||
-rw-r--r-- | ash/wm/power_button_controller.cc | 11 | ||||
-rw-r--r-- | ui/aura/event_filter_unittest.cc | 21 | ||||
-rw-r--r-- | ui/aura/test/event_generator.cc | 27 |
13 files changed, 186 insertions, 39 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 6b35e24..8a7b4cf 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc @@ -33,6 +33,7 @@ #include "ash/system/tray/system_tray_delegate.h" #include "ash/volume_control_delegate.h" #include "ash/wm/partial_screenshot_view.h" +#include "ash/wm/power_button_controller.h" #include "ash/wm/property_util.h" #include "ash/wm/window_cycle_controller.h" #include "ash/wm/window_util.h" @@ -57,6 +58,7 @@ #if defined(OS_CHROMEOS) #include "ash/display/output_configurator_animation.h" #include "base/chromeos/chromeos_version.h" +#include "base/time.h" #include "chromeos/display/output_configurator.h" #endif // defined(OS_CHROMEOS) @@ -757,10 +759,35 @@ bool AcceleratorController::PerformAction(int action, return HandleMediaPrevTrack(); case POWER_PRESSED: // fallthrough case POWER_RELEASED: - // We don't do anything with these at present, but we consume them to - // prevent them from getting passed to apps -- see - // http://crbug.com/146609. - return true; +#if defined(OS_CHROMEOS) + if (!base::chromeos::IsRunningOnChromeOS()) { + // There is no powerd in linux desktop, so call the + // PowerButtonController here. + Shell::GetInstance()->power_button_controller()-> + OnPowerButtonEvent(action == POWER_PRESSED, base::TimeTicks()); + } +#endif + // We don't do anything with these at present on the device, + // (power button evets are reported to us from powerm via + // D-BUS), but we consume them to prevent them from getting + // passed to apps -- see http://crbug.com/146609. + return true; + case LOCK_PRESSED: + case LOCK_RELEASED: +#if defined(OS_CHROMEOS) + if (!base::chromeos::IsRunningOnChromeOS()) { + // There is no powerd in linux desktop, so call the + // PowerButtonController here. + Shell::GetInstance()->power_button_controller()-> + OnLockButtonEvent(action == LOCK_PRESSED, base::TimeTicks()); + return true; + } +#endif + // LOCK_PRESSED/RELEASED in debug only action that is meant for + // testing lock behavior on linux desktop. If we ever reached + // here (when you run a debug build on the device), pass it onto + // apps. + return false; #if !defined(NDEBUG) case PRINT_LAYER_HIERARCHY: return HandlePrintLayerHierarchy(); diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc index 45ec793..8a8ee03 100644 --- a/ash/accelerators/accelerator_table.cc +++ b/ash/accelerators/accelerator_table.cc @@ -66,6 +66,12 @@ const AcceleratorData kAcceleratorData[] = { // Extra shortcut for display swaping as alt-f4 is taken on linux desktop. { true, ui::VKEY_F4, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, SWAP_PRIMARY_DISPLAY }, + // Extra shortcut to exit on linux desktop. + { true, ui::VKEY_F11, ui::EF_NONE, POWER_PRESSED }, + { false, ui::VKEY_F11, ui::EF_NONE, POWER_RELEASED }, + // Extra shortcut to lock the screen on linux desktop. + { true, ui::VKEY_F11, ui::EF_SHIFT_DOWN, LOCK_PRESSED }, + { false, ui::VKEY_F11, ui::EF_SHIFT_DOWN, LOCK_RELEASED }, #endif { true, ui::VKEY_O, ui::EF_CONTROL_DOWN, OPEN_FILE_MANAGER_DIALOG }, { true, ui::VKEY_M, ui::EF_CONTROL_DOWN, OPEN_FILE_MANAGER_TAB }, @@ -195,6 +201,8 @@ const AcceleratorAction kReservedActions[] = { CYCLE_FORWARD_MRU_PRESSED, // Alt+Tab CYCLE_FORWARD_MRU_RELEASED, #if defined(OS_CHROMEOS) + LOCK_PRESSED, + LOCK_RELEASED, POWER_PRESSED, POWER_RELEASED, #endif @@ -231,6 +239,10 @@ const AcceleratorAction kActionsAllowedAtLoginOrLockScreen[] = { PRINT_WINDOW_HIERARCHY, ROTATE_SCREEN, #endif +#if defined(OS_CHROMEOS) && !defined(NDEBUG) + POWER_PRESSED, + POWER_RELEASED, +#endif }; const size_t kActionsAllowedAtLoginOrLockScreenLength = diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h index 91442a4..14b4327 100644 --- a/ash/accelerators/accelerator_table.h +++ b/ash/accelerators/accelerator_table.h @@ -32,6 +32,8 @@ enum AcceleratorAction { FOCUS_SYSTEM_TRAY, KEYBOARD_BRIGHTNESS_DOWN, KEYBOARD_BRIGHTNESS_UP, + LOCK_PRESSED, + LOCK_RELEASED, MAGNIFY_SCREEN_ZOOM_IN, MAGNIFY_SCREEN_ZOOM_OUT, MEDIA_NEXT_TRACK, diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc index 5f4dd6c..4cc75fa 100644 --- a/ash/extended_desktop_unittest.cc +++ b/ash/extended_desktop_unittest.cc @@ -4,7 +4,9 @@ #include "ash/display/display_controller.h" #include "ash/display/multi_display_manager.h" +#include "ash/screen_ash.h" #include "ash/shell.h" +#include "ash/shell_window_ids.h" #include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/wm/coordinate_conversion.h" @@ -12,6 +14,7 @@ #include "ash/wm/window_cycle_controller.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_util.h" +#include "base/string_util.h" #include "ui/aura/client/activation_client.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/env.h" @@ -23,6 +26,7 @@ #include "ui/base/cursor/cursor.h" #include "ui/gfx/display.h" #include "ui/gfx/screen.h" +#include "ui/views/controls/textfield/textfield.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -599,5 +603,71 @@ TEST_F(ExtendedDesktopTest, StayInSameRootWindow) { EXPECT_EQ(root_windows[0], w1->GetNativeView()->GetRootWindow()); } +TEST_F(ExtendedDesktopTest, KeyEventsOnLockScreen) { + UpdateDisplay("100x100,200x200"); + Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); + + // Create normal windows on both displays. + views::Widget* widget1 = CreateTestWidget( + gfx::Screen::GetPrimaryDisplay().bounds()); + widget1->Show(); + EXPECT_EQ(root_windows[0], widget1->GetNativeView()->GetRootWindow()); + views::Widget* widget2 = CreateTestWidget( + ScreenAsh::GetSecondaryDisplay().bounds()); + widget2->Show(); + EXPECT_EQ(root_windows[1], widget2->GetNativeView()->GetRootWindow()); + + // Create a LockScreen window. + views::Widget* lock_widget = CreateTestWidget( + gfx::Screen::GetPrimaryDisplay().bounds()); + views::Textfield* textfield = new views::Textfield; + lock_widget->SetContentsView(textfield); + + ash::Shell::GetContainer( + Shell::GetPrimaryRootWindow(), + ash::internal::kShellWindowId_LockScreenContainer)-> + AddChild(lock_widget->GetNativeView()); + lock_widget->Show(); + textfield->RequestFocus(); + + aura::FocusManager* focus_manager = root_windows[0]->GetFocusManager(); + EXPECT_EQ(lock_widget->GetNativeView(), focus_manager->GetFocusedWindow()); + + // The lock window should get events on both root windows. + aura::test::EventGenerator generator1(root_windows[0]); + generator1.PressKey(ui::VKEY_A, 0); + generator1.ReleaseKey(ui::VKEY_A, 0); + EXPECT_EQ(lock_widget->GetNativeView(), focus_manager->GetFocusedWindow()); + EXPECT_EQ("a", UTF16ToASCII(textfield->text())); + + aura::test::EventGenerator generator2(root_windows[1]); + generator2.PressKey(ui::VKEY_B, 0); + generator2.ReleaseKey(ui::VKEY_B, 0); + EXPECT_EQ(lock_widget->GetNativeView(), focus_manager->GetFocusedWindow()); + EXPECT_EQ("ab", UTF16ToASCII(textfield->text())); + + // Deleting 2nd display. The lock window still should get the events. + UpdateDisplay("100x100"); + generator2.PressKey(ui::VKEY_C, 0); + generator2.ReleaseKey(ui::VKEY_C, 0); + EXPECT_EQ(lock_widget->GetNativeView(), focus_manager->GetFocusedWindow()); + EXPECT_EQ("abc", UTF16ToASCII(textfield->text())); + + // Creating 2nd display again, and lock window still should get events + // on both root windows. + UpdateDisplay("100x100,200x200"); + root_windows = Shell::GetAllRootWindows(); + generator1.PressKey(ui::VKEY_D, 0); + generator1.ReleaseKey(ui::VKEY_D, 0); + EXPECT_EQ(lock_widget->GetNativeView(), focus_manager->GetFocusedWindow()); + EXPECT_EQ("abcd", UTF16ToASCII(textfield->text())); + + aura::test::EventGenerator generator22(root_windows[1]); + generator22.PressKey(ui::VKEY_E, 0); + generator22.ReleaseKey(ui::VKEY_E, 0); + EXPECT_EQ(lock_widget->GetNativeView(), focus_manager->GetFocusedWindow()); + EXPECT_EQ("abcde", UTF16ToASCII(textfield->text())); +} + } // namespace internal } // namespace ash diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index 1f08095..b0a5b92bb 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc @@ -13,7 +13,6 @@ #include "ash/shell_factory.h" #include "ash/shell_window_ids.h" #include "ash/wm/base_layout_manager.h" -#include "ash/wm/event_client_impl.h" #include "ash/wm/property_util.h" #include "ash/wm/root_window_layout_manager.h" #include "ash/wm/screen_dimmer.h" @@ -144,8 +143,6 @@ namespace internal { RootWindowController::RootWindowController(aura::RootWindow* root_window) : root_window_(root_window) { SetRootWindowController(root_window, this); - - event_client_.reset(new EventClientImpl(root_window)); screen_dimmer_.reset(new ScreenDimmer(root_window)); } @@ -162,7 +159,6 @@ void RootWindowController::Shutdown() { NULL : Shell::GetPrimaryRootWindow()); } SetRootWindowController(root_window_.get(), NULL); - event_client_.reset(); screen_dimmer_.reset(); workspace_controller_.reset(); // Forget with the display ID so that display lookup diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h index e8f623d..c88795d 100644 --- a/ash/root_window_controller.h +++ b/ash/root_window_controller.h @@ -25,7 +25,6 @@ namespace ash { class ToplevelWindowEventHandler; namespace internal { -class EventClientImpl; class RootWindowLayoutManager; class ScreenDimmer; class SystemBackgroundController; @@ -101,8 +100,6 @@ class ASH_EXPORT RootWindowController { // desktop background image when displaying the login screen. scoped_ptr<SystemBackgroundController> background_; - // An event filter that pre-handles all key events to send them to an IME. - scoped_ptr<EventClientImpl> event_client_; scoped_ptr<ScreenDimmer> screen_dimmer_; scoped_ptr<WorkspaceController> workspace_controller_; diff --git a/ash/shell.cc b/ash/shell.cc index 3627616..9de3e091 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -256,6 +256,7 @@ Shell::~Shell() { resize_shadow_controller_.reset(); shadow_controller_.reset(); tooltip_controller_.reset(); + event_client_.reset(); window_cycle_controller_.reset(); capture_controller_.reset(); nested_dispatcher_controller_.reset(); @@ -348,6 +349,12 @@ aura::Window* Shell::GetContainer(aura::RootWindow* root_window, } // static +const aura::Window* Shell::GetContainer(const aura::RootWindow* root_window, + int container_id) { + return root_window->GetChildById(container_id); +} + +// static std::vector<aura::Window*> Shell::GetAllContainers(int container_id) { std::vector<aura::Window*> containers; aura::Window* container = GetPrimaryRootWindow()->GetChildById(container_id); @@ -448,6 +455,8 @@ void Shell::Init() { drag_drop_controller_.get())); AddEnvEventFilter(tooltip_controller_.get()); + event_client_.reset(new internal::EventClientImpl); + InitRootWindowController(root_window_controller); // This controller needs to be set before SetupManagedWindowMode. @@ -731,6 +740,7 @@ void Shell::InitRootWindowController( screen_position_controller_.get()); aura::client::SetCursorClient(root_window, &cursor_manager_); aura::client::SetTooltipClient(root_window, tooltip_controller_.get()); + aura::client::SetEventClient(root_window, event_client_.get()); if (nested_dispatcher_controller_.get()) { aura::client::SetDispatcherClient(root_window, diff --git a/ash/shell.h b/ash/shell.h index ef869bf..044ba06 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -83,6 +83,7 @@ class ActivationController; class AppListController; class CaptureController; class DragDropController; +class EventClientImpl; class EventRewriterEventFilter; class FocusCycler; class MagnificationController; @@ -175,6 +176,8 @@ class ASH_EXPORT Shell : CursorDelegate, static aura::Window* GetContainer(aura::RootWindow* root_window, int container_id); + static const aura::Window* GetContainer(const aura::RootWindow* root_window, + int container_id); // Returns the list of containers that match |container_id| in // all root windows. @@ -457,6 +460,7 @@ class ASH_EXPORT Shell : CursorDelegate, scoped_ptr<internal::MouseCursorEventFilter> mouse_cursor_filter_; scoped_ptr<internal::ScreenPositionController> screen_position_controller_; scoped_ptr<internal::SystemModalContainerEventFilter> modality_filter_; + scoped_ptr<internal::EventClientImpl> event_client_; // An event filter that rewrites or drops an event. scoped_ptr<internal::EventRewriterEventFilter> event_rewriter_filter_; diff --git a/ash/wm/event_client_impl.cc b/ash/wm/event_client_impl.cc index 4482c11..f7fc8b2 100644 --- a/ash/wm/event_client_impl.cc +++ b/ash/wm/event_client_impl.cc @@ -6,32 +6,30 @@ #include "ash/shell.h" #include "ash/shell_window_ids.h" -#include "ui/aura/root_window.h" #include "ui/aura/window.h" namespace ash { namespace internal { -EventClientImpl::EventClientImpl(aura::RootWindow* root_window) - : root_window_(root_window) { - aura::client::SetEventClient(root_window_, this); +EventClientImpl::EventClientImpl() { } EventClientImpl::~EventClientImpl() { - aura::client::SetEventClient(root_window_, NULL); } bool EventClientImpl::CanProcessEventsWithinSubtree( const aura::Window* window) const { - if (Shell::GetInstance()->IsScreenLocked()) { - aura::Window* lock_screen_containers = Shell::GetContainer( - root_window_, + const aura::RootWindow* root_window = + window ? window->GetRootWindow() : NULL; + if (Shell::GetInstance()->IsScreenLocked() && root_window) { + const aura::Window* lock_screen_containers = Shell::GetContainer( + root_window, kShellWindowId_LockScreenContainersContainer); - aura::Window* lock_background_containers = Shell::GetContainer( - root_window_, + const aura::Window* lock_background_containers = Shell::GetContainer( + root_window, kShellWindowId_LockScreenBackgroundContainer); - aura::Window* lock_screen_related_containers = Shell::GetContainer( - root_window_, + const aura::Window* lock_screen_related_containers = Shell::GetContainer( + root_window, kShellWindowId_LockScreenRelatedContainersContainer); return lock_screen_containers->Contains(window) || lock_background_containers->Contains(window) || diff --git a/ash/wm/event_client_impl.h b/ash/wm/event_client_impl.h index cf689ed..3702709 100644 --- a/ash/wm/event_client_impl.h +++ b/ash/wm/event_client_impl.h @@ -17,7 +17,7 @@ namespace internal { class EventClientImpl : public aura::client::EventClient { public: - explicit EventClientImpl(aura::RootWindow* root_window); + EventClientImpl(); virtual ~EventClientImpl(); private: @@ -25,8 +25,6 @@ class EventClientImpl : public aura::client::EventClient { virtual bool CanProcessEventsWithinSubtree( const aura::Window* window) const OVERRIDE; - aura::RootWindow* root_window_; - DISALLOW_COPY_AND_ASSIGN(EventClientImpl); }; diff --git a/ash/wm/power_button_controller.cc b/ash/wm/power_button_controller.cc index bd9bb91..4f05f1b 100644 --- a/ash/wm/power_button_controller.cc +++ b/ash/wm/power_button_controller.cc @@ -13,6 +13,10 @@ #include "ui/aura/root_window.h" #include "ui/aura/shared/compound_event_filter.h" +#if defined(OS_CHROMEOS) +#include "base/chromeos/chromeos_version.h" +#endif + namespace ash { namespace { @@ -307,6 +311,13 @@ void PowerButtonController::OnShutdownTimeout() { void PowerButtonController::OnRealShutdownTimeout() { DCHECK(shutting_down_); +#if defined(OS_CHROMEOS) + if (!base::chromeos::IsRunningOnChromeOS()) { + ShellDelegate* delegate = Shell::GetInstance()->delegate(); + if (delegate) + delegate->Exit(); + } +#endif delegate_->RequestShutdown(); } diff --git a/ui/aura/event_filter_unittest.cc b/ui/aura/event_filter_unittest.cc index 010fbfb..1827e81 100644 --- a/ui/aura/event_filter_unittest.cc +++ b/ui/aura/event_filter_unittest.cc @@ -200,10 +200,17 @@ TEST_F(EventFilterTest, PostHandle) { generator.PressKey(ui::VKEY_A, 0); generator.PressLeftButton(); - EXPECT_EQ(1, w1_filter->key_event_count()); +#if defined(OS_WIN) + // Windows sends two WM_KEYDOWN/WM_CHAR events for one key press. + const int kExpectedKeyCount = 2; +#else + const int kExpectedKeyCount = 1; +#endif + + EXPECT_EQ(kExpectedKeyCount, w1_filter->key_event_count()); EXPECT_EQ(1, w1_filter->mouse_event_count()); EXPECT_EQ(1, root_window_filter.mouse_event_count()); - EXPECT_EQ(1, d11.key_event_count()); + EXPECT_EQ(kExpectedKeyCount, d11.key_event_count()); EXPECT_EQ(1, d11.mouse_event_count()); root_window_filter.ResetCounts(); @@ -246,12 +253,12 @@ TEST_F(EventFilterTest, PostHandle) { generator.PressKey(ui::VKEY_A, 0); generator.PressLeftButton(); - EXPECT_EQ(1, d11.key_event_count()); + EXPECT_EQ(kExpectedKeyCount, d11.key_event_count()); EXPECT_EQ(1, d11.mouse_event_count()); // The delegate processed the event. But it should still bubble up to the // post-target filters. - EXPECT_EQ(1, w1_filter->key_event_count()); - EXPECT_EQ(1, root_window_filter.key_event_count()); + EXPECT_EQ(kExpectedKeyCount, w1_filter->key_event_count()); + EXPECT_EQ(kExpectedKeyCount, root_window_filter.key_event_count()); EXPECT_EQ(1, w1_filter->mouse_event_count()); EXPECT_EQ(1, root_window_filter.mouse_event_count()); @@ -268,7 +275,7 @@ TEST_F(EventFilterTest, PostHandle) { generator.PressKey(ui::VKEY_A, 0); generator.PressLeftButton(); - EXPECT_EQ(1, d11.key_event_count()); + EXPECT_EQ(kExpectedKeyCount, d11.key_event_count()); EXPECT_EQ(1, d11.mouse_event_count()); // The delegate consumed the event. So it should no longer reach the // post-target filters. @@ -295,7 +302,7 @@ TEST_F(EventFilterTest, PostHandle) { generator.PressKey(ui::VKEY_A, 0); generator.PressLeftButton(); - EXPECT_EQ(1, w1_filter->key_event_count()); + EXPECT_EQ(kExpectedKeyCount, w1_filter->key_event_count()); EXPECT_EQ(0, d11.key_event_count()); EXPECT_EQ(1, w1_filter->mouse_event_count()); EXPECT_EQ(0, d11.mouse_event_count()); diff --git a/ui/aura/test/event_generator.cc b/ui/aura/test/event_generator.cc index ebad4f3..a2eb897 100644 --- a/ui/aura/test/event_generator.cc +++ b/ui/aura/test/event_generator.cc @@ -13,12 +13,16 @@ #include "ui/base/x/x11_util.h" #endif +#if defined(OS_WIN) +#include "ui/base/keycodes/keyboard_code_conversion.h" +#endif + namespace { class TestKeyEvent : public ui::KeyEvent { public: - TestKeyEvent(const base::NativeEvent& native_event, int flags) - : KeyEvent(native_event, false /* is_char */) { + TestKeyEvent(const base::NativeEvent& native_event, int flags, bool is_char) + : KeyEvent(native_event, is_char) { set_flags(flags); } }; @@ -309,17 +313,28 @@ void EventGenerator::DispatchKeyEvent(bool is_press, ui::KeyboardCode key_code, int flags) { #if defined(OS_WIN) + UINT key_press = WM_KEYDOWN; + uint16 character = ui::GetCharacterFromKeyCode(key_code, flags); + if (is_press && character) { + MSG native_event = { NULL, WM_KEYDOWN, key_code, 0 }; + TestKeyEvent keyev(native_event, flags, false); + Dispatch(keyev); + // On Windows, WM_KEYDOWN event is followed by WM_CHAR with a character + // if the key event cooresponds to a real character. + key_press = WM_CHAR; + key_code = static_cast<ui::KeyboardCode>(character); + } MSG native_event = - { NULL, (is_press ? WM_KEYDOWN : WM_KEYUP), key_code, 0 }; - TestKeyEvent keyev(native_event, flags); + { NULL, (is_press ? key_press : WM_KEYUP), key_code, 0 }; + TestKeyEvent keyev(native_event, flags, key_press == WM_CHAR); #else ui::EventType type = is_press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED; #if defined(USE_X11) scoped_ptr<XEvent> native_event(new XEvent); ui::InitXKeyEventForTesting(type, key_code, flags, native_event.get()); - TestKeyEvent keyev(native_event.get(), flags); + TestKeyEvent keyev(native_event.get(), flags, false); #else - ui::KeyEvent keyev(type, key_code, flags); + ui::KeyEvent keyev(type, key_code, flags, false); #endif // USE_X11 #endif // OS_WIN Dispatch(keyev); |