diff options
author | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-22 18:49:01 +0000 |
---|---|---|
committer | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-22 18:49:01 +0000 |
commit | 56281735c6141a07f03fff2e9be6ac0eaccdc76f (patch) | |
tree | 68dd5c8aa05f4567698e054ab2ccc2a8e4bf1d86 /ash | |
parent | 394bf06fa36b57a7dbd7e2bae35c8d9cc70af7f0 (diff) | |
download | chromium_src-56281735c6141a07f03fff2e9be6ac0eaccdc76f.zip chromium_src-56281735c6141a07f03fff2e9be6ac0eaccdc76f.tar.gz chromium_src-56281735c6141a07f03fff2e9be6ac0eaccdc76f.tar.bz2 |
Only block internal touchpad and allow external mice to continue working in maximize mode.
BUG=362881
TEST=Manual, plug in an external mouse and observe it continues working when device is in maximize mode while internal touchpad does not.
Review URL: https://codereview.chromium.org/269633005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272254 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/ash.gyp | 3 | ||||
-rw-r--r-- | ash/wm/maximize_mode/internal_input_device_list.h | 32 | ||||
-rw-r--r-- | ash/wm/maximize_mode/internal_input_device_list_x11.cc | 55 | ||||
-rw-r--r-- | ash/wm/maximize_mode/internal_input_device_list_x11.h | 38 | ||||
-rw-r--r-- | ash/wm/maximize_mode/maximize_mode_controller.h | 3 | ||||
-rw-r--r-- | ash/wm/maximize_mode/maximize_mode_controller_unittest.cc | 25 | ||||
-rw-r--r-- | ash/wm/maximize_mode/maximize_mode_event_blocker.cc | 74 | ||||
-rw-r--r-- | ash/wm/maximize_mode/maximize_mode_event_blocker.h | 13 |
8 files changed, 230 insertions, 13 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index c463286..6d8fece 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -574,6 +574,9 @@ 'wm/lock_state_controller.cc', 'wm/lock_state_controller.h', 'wm/lock_state_observer.h', + 'wm/maximize_mode/internal_input_device_list.h', + 'wm/maximize_mode/internal_input_device_list_x11.cc', + 'wm/maximize_mode/internal_input_device_list_x11.h', 'wm/maximize_mode/maximize_mode_controller.cc', 'wm/maximize_mode/maximize_mode_controller.h', 'wm/maximize_mode/maximize_mode_event_blocker.cc', diff --git a/ash/wm/maximize_mode/internal_input_device_list.h b/ash/wm/maximize_mode/internal_input_device_list.h new file mode 100644 index 0000000..ab8c86b --- /dev/null +++ b/ash/wm/maximize_mode/internal_input_device_list.h @@ -0,0 +1,32 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_MAXIMIZE_MODE_INTERNAL_INPUT_DEVICE_LIST_H_ +#define ASH_WM_MAXIMIZE_MODE_INTERNAL_INPUT_DEVICE_LIST_H_ + +#include "ash/ash_export.h" +#include "base/macros.h" + +namespace ui { +class Event; +} + +namespace ash { + +// Identifies which input devices are internal and provides a helper function to +// test if an input event came from an internal device. +class ASH_EXPORT InternalInputDeviceList { + public: + InternalInputDeviceList() {} + virtual ~InternalInputDeviceList() {} + + virtual bool IsEventFromInternalDevice(const ui::Event* event) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(InternalInputDeviceList); +}; + +} // namespace ash + +#endif // ASH_WM_MAXIMIZE_MODE_INTERNAL_INPUT_DEVICE_LIST_H_ diff --git a/ash/wm/maximize_mode/internal_input_device_list_x11.cc b/ash/wm/maximize_mode/internal_input_device_list_x11.cc new file mode 100644 index 0000000..9a490ec --- /dev/null +++ b/ash/wm/maximize_mode/internal_input_device_list_x11.cc @@ -0,0 +1,55 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/maximize_mode/internal_input_device_list_x11.h" + +#include <X11/extensions/XInput2.h> +#include <X11/Xlib.h> + +#include "base/strings/string_util.h" +#include "ui/events/event.h" +#include "ui/events/x/device_data_manager.h" +#include "ui/events/x/device_list_cache_x.h" +#include "ui/gfx/x/x11_types.h" + +namespace ash { + +namespace { + +// The name of the xinput device corresponding to the internal touchpad. +const char kInternalTouchpadName[] = "Elan Touchpad"; + +// The name of the xinput device corresponding to the internal keyboard. +const char kInternalKeyboardName[] = "AT Translated Set 2 keyboard"; + +} // namespace + +InternalInputDeviceListX11::InternalInputDeviceListX11() { + if (ui::DeviceDataManager::GetInstance()->IsXInput2Available()) { + XIDeviceList xi_dev_list = ui::DeviceListCacheX::GetInstance()-> + GetXI2DeviceList(gfx::GetXDisplay()); + for (int i = 0; i < xi_dev_list.count; ++i) { + std::string device_name(xi_dev_list[i].name); + base::TrimWhitespaceASCII(device_name, base::TRIM_TRAILING, &device_name); + if (device_name == kInternalTouchpadName || + device_name == kInternalKeyboardName) + internal_device_ids_.insert(xi_dev_list[i].deviceid); + } + } +} + +InternalInputDeviceListX11::~InternalInputDeviceListX11() { +} + +bool InternalInputDeviceListX11::IsEventFromInternalDevice( + const ui::Event* event) { + if (!event->HasNativeEvent()) + return false; + XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>( + event->native_event()->xcookie.data); + return internal_device_ids_.find(xiev->sourceid) != + internal_device_ids_.end(); +} + +} // namespace ash diff --git a/ash/wm/maximize_mode/internal_input_device_list_x11.h b/ash/wm/maximize_mode/internal_input_device_list_x11.h new file mode 100644 index 0000000..3ef0de8 --- /dev/null +++ b/ash/wm/maximize_mode/internal_input_device_list_x11.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_MAXIMIZE_MODE_INTERNAL_INPUT_DEVICE_LIST_X11_H_ +#define ASH_WM_MAXIMIZE_MODE_INTERNAL_INPUT_DEVICE_LIST_X11_H_ + +#include <set> + +#include "ash/wm/maximize_mode/internal_input_device_list.h" +#include "base/macros.h" + +namespace ui { +class Event; +} + +namespace ash { + +// Identifies which input devices are internal and provides a helper function to +// test if an input event came from an internal device. +class InternalInputDeviceListX11 : public InternalInputDeviceList { + public: + InternalInputDeviceListX11(); + virtual ~InternalInputDeviceListX11(); + + // InternalInputDeviceList: + virtual bool IsEventFromInternalDevice(const ui::Event* event) OVERRIDE; + + private: + // Tracks the device ids of internal input devices. + std::set<int> internal_device_ids_; + + DISALLOW_COPY_AND_ASSIGN(InternalInputDeviceListX11); +}; + +} // namespace ash + +#endif // ASH_WM_MAXIMIZE_MODE_INTERNAL_INPUT_DEVICE_LIST_X11_H_ diff --git a/ash/wm/maximize_mode/maximize_mode_controller.h b/ash/wm/maximize_mode/maximize_mode_controller.h index 6363211..4d19dcc 100644 --- a/ash/wm/maximize_mode/maximize_mode_controller.h +++ b/ash/wm/maximize_mode/maximize_mode_controller.h @@ -17,6 +17,7 @@ class EventHandler; namespace ash { +class MaximizeModeControllerTest; class MaximizeModeEventBlocker; // MaximizeModeController listens to accelerometer events and automatically @@ -53,6 +54,8 @@ class ASH_EXPORT MaximizeModeController : public AccelerometerObserver { const gfx::Vector3dF& lid) OVERRIDE; private: + friend class MaximizeModeControllerTest; + // Detect hinge rotation from |base| and |lid| accelerometers and // automatically start / stop maximize mode. void HandleHingeRotation(const gfx::Vector3dF& base, diff --git a/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc b/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc index 5509107..4145281 100644 --- a/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc +++ b/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc @@ -14,6 +14,8 @@ #include "ash/test/test_screenshot_delegate.h" #include "ash/test/test_system_tray_delegate.h" #include "ash/test/test_volume_control_delegate.h" +#include "ash/wm/maximize_mode/internal_input_device_list.h" +#include "ash/wm/maximize_mode/maximize_mode_event_blocker.h" #include "ui/aura/test/event_generator.h" #include "ui/events/event_handler.h" #include "ui/gfx/vector3d_f.h" @@ -58,6 +60,21 @@ void EventCounter::OnEvent(ui::Event* event) { event_count_++; } +// A test internal input device list which pretends that all events are from +// internal devices to allow verifying that the event blocking works. +class TestInternalInputDeviceList : public InternalInputDeviceList { + public: + TestInternalInputDeviceList() {} + virtual ~TestInternalInputDeviceList() {} + + virtual bool IsEventFromInternalDevice(const ui::Event* event) OVERRIDE { + return true; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestInternalInputDeviceList); +}; + } // namespace // Test accelerometer data taken with the lid at less than 180 degrees while @@ -109,6 +126,13 @@ class MaximizeModeControllerTest : public test::AshTestBase { return Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled(); } + // Overrides the internal input device list for the current event targeters + // with one which always returns true. + void InstallTestInternalDeviceList() { + maximize_mode_controller()->event_blocker_->internal_devices_.reset( + new TestInternalInputDeviceList); + } + gfx::Display::Rotation GetInternalDisplayRotation() const { return Shell::GetInstance()->display_manager()->GetDisplayInfo( gfx::Display::InternalDisplayId()).rotation(); @@ -326,6 +350,7 @@ TEST_F(MaximizeModeControllerTest, BlocksKeyboardAndMouse) { TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, 1.0f), gfx::Vector3dF(1.0f, 0.0f, 0.0f)); ASSERT_TRUE(IsMaximizeModeStarted()); + InstallTestInternalDeviceList(); event_generator.PressKey(ui::VKEY_ESCAPE, 0); event_generator.ReleaseKey(ui::VKEY_ESCAPE, 0); diff --git a/ash/wm/maximize_mode/maximize_mode_event_blocker.cc b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc index fd2362f..572886c 100644 --- a/ash/wm/maximize_mode/maximize_mode_event_blocker.cc +++ b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc @@ -5,10 +5,18 @@ #include "ash/wm/maximize_mode/maximize_mode_event_blocker.h" #include "ash/shell.h" +#include "ash/wm/maximize_mode/internal_input_device_list.h" #include "base/memory/scoped_ptr.h" #include "ui/aura/client/cursor_client.h" +#include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tree_host.h" #include "ui/events/event_targeter.h" #include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/point.h" + +#if defined(USE_X11) +#include "ash/wm/maximize_mode/internal_input_device_list_x11.h" +#endif namespace ash { @@ -17,11 +25,11 @@ namespace { // Event targeter to prevent delivery of mouse and touchpad events while // maximize mode is active. Other events such as touch are passed on to the // default targeter. -// TODO(flackr): This should only stop events from the internal keyboard and -// touchpad. class BlockKeyboardAndTouchpadTargeter : public ui::EventTargeter { public: - BlockKeyboardAndTouchpadTargeter(); + BlockKeyboardAndTouchpadTargeter( + aura::Window* root_window, + MaximizeModeEventBlocker* event_blocker); virtual ~BlockKeyboardAndTouchpadTargeter(); // Sets the default targeter to use when the event is not being blocked. @@ -32,16 +40,34 @@ class BlockKeyboardAndTouchpadTargeter : public ui::EventTargeter { ui::Event* event) OVERRIDE; private: + // A weak pointer to the root window on which this targeter will be set. The + // root window owns this targeter. + aura::Window* root_window_; + + // A weak pointer to the event blocker which owns the scoped targeter owning + // this targeter. + MaximizeModeEventBlocker* event_blocker_; + // A weak pointer to the targeter this targeter is wrapping. The // default_targeter is owned by the ScopedWindowTargeter which will be valid // as long as this targeter is alive. ui::EventTargeter* default_targeter_; + // The last known mouse location to lock the cursor in place to when events + // come from the internal touchpad. + gfx::Point last_mouse_location_; + DISALLOW_COPY_AND_ASSIGN(BlockKeyboardAndTouchpadTargeter); }; -BlockKeyboardAndTouchpadTargeter::BlockKeyboardAndTouchpadTargeter() - : default_targeter_(NULL) { +BlockKeyboardAndTouchpadTargeter::BlockKeyboardAndTouchpadTargeter( + aura::Window* root_window, + MaximizeModeEventBlocker* event_blocker) + : root_window_(root_window), + event_blocker_(event_blocker), + default_targeter_(NULL), + last_mouse_location_(root_window->GetHost()->dispatcher()-> + GetLastMouseLocationInRoot()) { } BlockKeyboardAndTouchpadTargeter::~BlockKeyboardAndTouchpadTargeter() { @@ -55,19 +81,37 @@ void BlockKeyboardAndTouchpadTargeter::SetDefaultTargeter( ui::EventTarget* BlockKeyboardAndTouchpadTargeter::FindTargetForEvent( ui::EventTarget* root, ui::Event* event) { - if (event->IsMouseEvent() || - event->IsMouseWheelEvent() || - event->IsScrollEvent()) { + bool internal_device = event_blocker_->internal_devices() && + event_blocker_->internal_devices()->IsEventFromInternalDevice(event); + if (event->IsMouseEvent()) { + if (internal_device) { + // The cursor movement is handled at a lower level which is not blocked. + // Move the mouse cursor back to its last known location resulting from + // an external mouse to prevent the internal touchpad from moving it. + root_window_->GetHost()->MoveCursorToHostLocation( + last_mouse_location_); + return NULL; + } else { + // Track the last location seen from an external mouse event. + last_mouse_location_ = + static_cast<ui::MouseEvent*>(event)->root_location(); + root_window_->GetHost()->ConvertPointToHost(&last_mouse_location_); + } + } else if (internal_device && (event->IsMouseWheelEvent() || + event->IsScrollEvent())) { return NULL; - } - if (event->IsKeyEvent() && event->HasNativeEvent()) { + } else if (event->IsKeyEvent() && event->HasNativeEvent()) { + // TODO(flackr): Disable events only from the internal keyboard device + // when we begin using XI2 events for keyboard events + // (http://crbug.com/368750) and can tell which device the event is + // coming from, http://crbug.com/362881. // TODO(bruthig): Fix this to block rewritten volume keys // (i.e. F9 and F10) from the device's keyboard. https://crbug.com/368669 ui::KeyEvent* key_event = static_cast<ui::KeyEvent*>(event); if (key_event->key_code() != ui::VKEY_VOLUME_DOWN && key_event->key_code() != ui::VKEY_VOLUME_UP #if defined(OS_CHROMEOS) - && key_event->key_code() != ui::VKEY_POWER + && key_event->key_code() != ui::VKEY_POWER #endif ) { return NULL; @@ -78,7 +122,11 @@ ui::EventTarget* BlockKeyboardAndTouchpadTargeter::FindTargetForEvent( } // namespace -MaximizeModeEventBlocker::MaximizeModeEventBlocker() { +MaximizeModeEventBlocker::MaximizeModeEventBlocker() +#if defined(USE_X11) + : internal_devices_(new InternalInputDeviceListX11) +#endif + { Shell::GetInstance()->AddShellObserver(this); // Hide the cursor as mouse events will be blocked. @@ -107,7 +155,7 @@ void MaximizeModeEventBlocker::OnRootWindowAdded(aura::Window* root_window) { void MaximizeModeEventBlocker::AddEventTargeterOn( aura::Window* root_window) { BlockKeyboardAndTouchpadTargeter* targeter = - new BlockKeyboardAndTouchpadTargeter(); + new BlockKeyboardAndTouchpadTargeter(root_window, this); aura::ScopedWindowTargeter* scoped_targeter = new aura::ScopedWindowTargeter( root_window, scoped_ptr<ui::EventTargeter>(targeter)); targeter->SetDefaultTargeter(scoped_targeter->old_targeter()); diff --git a/ash/wm/maximize_mode/maximize_mode_event_blocker.h b/ash/wm/maximize_mode/maximize_mode_event_blocker.h index 9e4a1a0..4f7fae7 100644 --- a/ash/wm/maximize_mode/maximize_mode_event_blocker.h +++ b/ash/wm/maximize_mode/maximize_mode_event_blocker.h @@ -5,8 +5,11 @@ #ifndef ASH_WM_MAXIMIZE_MODE_MAXIMIZE_MODE_EVENT_BLOCKER_H_ #define ASH_WM_MAXIMIZE_MODE_MAXIMIZE_MODE_EVENT_BLOCKER_H_ +#include <set> + #include "ash/shell_observer.h" #include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "ui/aura/scoped_window_targeter.h" @@ -16,6 +19,9 @@ class Window; namespace ash { +class InternalInputDeviceList; +class MaximizeModeControllerTest; + // A class which blocks mouse and keyboard events while instantiated by // replacing the root window event targeter. class MaximizeModeEventBlocker : public ShellObserver { @@ -23,14 +29,21 @@ class MaximizeModeEventBlocker : public ShellObserver { MaximizeModeEventBlocker(); virtual ~MaximizeModeEventBlocker(); + InternalInputDeviceList* internal_devices() { + return internal_devices_.get(); + } + // ShellObserver: virtual void OnRootWindowAdded(aura::Window* root_window) OVERRIDE; private: + friend class MaximizeModeControllerTest; + // Adds an event targeter on |root_window| to block mouse and keyboard events. void AddEventTargeterOn(aura::Window* root_window); ScopedVector<aura::ScopedWindowTargeter> targeters_; + scoped_ptr<InternalInputDeviceList> internal_devices_; DISALLOW_COPY_AND_ASSIGN(MaximizeModeEventBlocker); }; |