summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-22 18:49:01 +0000
committerflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-22 18:49:01 +0000
commit56281735c6141a07f03fff2e9be6ac0eaccdc76f (patch)
tree68dd5c8aa05f4567698e054ab2ccc2a8e4bf1d86 /ash
parent394bf06fa36b57a7dbd7e2bae35c8d9cc70af7f0 (diff)
downloadchromium_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.gyp3
-rw-r--r--ash/wm/maximize_mode/internal_input_device_list.h32
-rw-r--r--ash/wm/maximize_mode/internal_input_device_list_x11.cc55
-rw-r--r--ash/wm/maximize_mode/internal_input_device_list_x11.h38
-rw-r--r--ash/wm/maximize_mode/maximize_mode_controller.h3
-rw-r--r--ash/wm/maximize_mode/maximize_mode_controller_unittest.cc25
-rw-r--r--ash/wm/maximize_mode/maximize_mode_event_blocker.cc74
-rw-r--r--ash/wm/maximize_mode/maximize_mode_event_blocker.h13
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);
};