summaryrefslogtreecommitdiffstats
path: root/ash/wm
diff options
context:
space:
mode:
authoravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-25 17:00:18 +0000
committeravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-25 17:00:18 +0000
commitfbfe5e5483677eaffd57d4d98a427841f9fece73 (patch)
tree331d0d373df812e0595bfc6e6c31f564607e19c5 /ash/wm
parent3a94b248df450e40596b57b27a06ffb4a9dc42df (diff)
downloadchromium_src-fbfe5e5483677eaffd57d4d98a427841f9fece73.zip
chromium_src-fbfe5e5483677eaffd57d4d98a427841f9fece73.tar.gz
chromium_src-fbfe5e5483677eaffd57d4d98a427841f9fece73.tar.bz2
Revert "Block internal PlatformEvents before they are dispatched in touchview."
This reverts r279732. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@279734 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/wm')
-rw-r--r--ash/wm/maximize_mode/internal_input_device_list.h32
-rw-r--r--ash/wm/maximize_mode/internal_input_device_list_x11.cc58
-rw-r--r--ash/wm/maximize_mode/internal_input_device_list_x11.h38
-rw-r--r--ash/wm/maximize_mode/maximize_mode_controller.cc10
-rw-r--r--ash/wm/maximize_mode/maximize_mode_controller.h8
-rw-r--r--ash/wm/maximize_mode/maximize_mode_controller_unittest.cc180
-rw-r--r--ash/wm/maximize_mode/maximize_mode_event_blocker.cc165
-rw-r--r--ash/wm/maximize_mode/maximize_mode_event_blocker.h53
-rw-r--r--ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h17
-rw-r--r--ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.cc141
-rw-r--r--ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h43
11 files changed, 532 insertions, 213 deletions
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..93727ec
--- /dev/null
+++ b/ash/wm/maximize_mode/internal_input_device_list_x11.cc
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/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_x11.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::DeviceDataManagerX11::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() ||
+ event->native_event()->type != GenericEvent) {
+ 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.cc b/ash/wm/maximize_mode/maximize_mode_controller.cc
index 36f6f25..a32812a 100644
--- a/ash/wm/maximize_mode/maximize_mode_controller.cc
+++ b/ash/wm/maximize_mode/maximize_mode_controller.cc
@@ -10,8 +10,8 @@
#include "ash/ash_switches.h"
#include "ash/display/display_manager.h"
#include "ash/shell.h"
+#include "ash/wm/maximize_mode/maximize_mode_event_blocker.h"
#include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
-#include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h"
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/metrics/histogram.h"
@@ -21,10 +21,6 @@
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/vector3d_f.h"
-#if defined(USE_X11)
-#include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h"
-#endif
-
namespace ash {
namespace {
@@ -354,9 +350,7 @@ void MaximizeModeController::EnterMaximizeMode() {
current_rotation_ = user_rotation_ = display_manager->
GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
EnableMaximizeModeWindowManager(true);
-#if defined(USE_X11)
- event_blocker_.reset(new ScopedDisableInternalMouseAndKeyboardX11);
-#endif
+ event_blocker_.reset(new MaximizeModeEventBlocker);
#if defined(OS_CHROMEOS)
event_handler_.reset(new ScreenshotActionHandler);
#endif
diff --git a/ash/wm/maximize_mode/maximize_mode_controller.h b/ash/wm/maximize_mode/maximize_mode_controller.h
index 54db3f3..8445bfa 100644
--- a/ash/wm/maximize_mode/maximize_mode_controller.h
+++ b/ash/wm/maximize_mode/maximize_mode_controller.h
@@ -23,7 +23,7 @@ class EventHandler;
namespace ash {
class MaximizeModeControllerTest;
-class ScopedDisableInternalMouseAndKeyboard;
+class MaximizeModeEventBlocker;
class MaximizeModeWindowManager;
class MaximizeModeWindowManagerTest;
@@ -136,9 +136,9 @@ class ASH_EXPORT MaximizeModeController : public AccelerometerObserver,
// The maximized window manager (if enabled).
scoped_ptr<MaximizeModeWindowManager> maximize_mode_window_manager_;
- // A helper class which when instantiated will block native events from the
- // internal keyboard and touchpad.
- scoped_ptr<ScopedDisableInternalMouseAndKeyboard> event_blocker_;
+ // An event targeter controller which traps mouse and keyboard events while
+ // maximize mode is engaged.
+ scoped_ptr<MaximizeModeEventBlocker> event_blocker_;
// An event handler used to detect screenshot actions while in maximize mode.
scoped_ptr<ui::EventHandler> event_handler_;
diff --git a/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc b/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc
index 089a232..8afb9e3 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"
@@ -29,6 +31,54 @@ namespace {
const float kDegreesToRadians = 3.14159265f / 180.0f;
+// Filter to count the number of events seen.
+class EventCounter : public ui::EventHandler {
+ public:
+ EventCounter();
+ virtual ~EventCounter();
+
+ // Overridden from ui::EventHandler:
+ virtual void OnEvent(ui::Event* event) OVERRIDE;
+
+ void reset() {
+ event_count_ = 0;
+ }
+
+ size_t event_count() const { return event_count_; }
+
+ private:
+ size_t event_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventCounter);
+};
+
+EventCounter::EventCounter() : event_count_(0) {
+ Shell::GetInstance()->AddPreTargetHandler(this);
+}
+
+EventCounter::~EventCounter() {
+ Shell::GetInstance()->RemovePreTargetHandler(this);
+}
+
+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
@@ -80,6 +130,13 @@ class MaximizeModeControllerTest : public test::AshTestBase {
return maximize_mode_controller()->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();
@@ -263,6 +320,78 @@ TEST_F(MaximizeModeControllerTest, RotationOnlyInMaximizeMode) {
EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation());
}
+// Tests that maximize mode blocks keyboard and mouse events but not touch
+// events.
+TEST_F(MaximizeModeControllerTest, BlocksKeyboardAndMouse) {
+ aura::Window* root = Shell::GetPrimaryRootWindow();
+ aura::test::EventGenerator event_generator(root, root);
+ EventCounter counter;
+
+ event_generator.PressKey(ui::VKEY_ESCAPE, 0);
+ event_generator.ReleaseKey(ui::VKEY_ESCAPE, 0);
+ EXPECT_GT(counter.event_count(), 0u);
+ counter.reset();
+
+ event_generator.ClickLeftButton();
+ EXPECT_GT(counter.event_count(), 0u);
+ counter.reset();
+
+ event_generator.ScrollSequence(
+ gfx::Point(), base::TimeDelta::FromMilliseconds(5), 0, 100, 5, 2);
+ EXPECT_GT(counter.event_count(), 0u);
+ counter.reset();
+
+ event_generator.MoveMouseWheel(0, 10);
+ EXPECT_GT(counter.event_count(), 0u);
+ counter.reset();
+
+ event_generator.PressTouch();
+ event_generator.ReleaseTouch();
+ EXPECT_GT(counter.event_count(), 0u);
+ counter.reset();
+
+ // Open up 270 degrees.
+ 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);
+ EXPECT_EQ(0u, counter.event_count());
+ counter.reset();
+
+ event_generator.ClickLeftButton();
+ EXPECT_EQ(0u, counter.event_count());
+ counter.reset();
+
+ event_generator.ScrollSequence(
+ gfx::Point(), base::TimeDelta::FromMilliseconds(5), 0, 100, 5, 2);
+ EXPECT_EQ(0u, counter.event_count());
+ counter.reset();
+
+ event_generator.MoveMouseWheel(0, 10);
+ EXPECT_EQ(0u, counter.event_count());
+ counter.reset();
+
+ // Touch should not be blocked.
+ event_generator.PressTouch();
+ event_generator.ReleaseTouch();
+ EXPECT_GT(counter.event_count(), 0u);
+ counter.reset();
+
+ gfx::Vector3dF base;
+
+ // Lid open 90 degrees.
+ TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, 1.0f),
+ gfx::Vector3dF(-1.0f, 0.0f, 0.0f));
+
+ event_generator.PressKey(ui::VKEY_ESCAPE, 0);
+ event_generator.ReleaseKey(ui::VKEY_ESCAPE, 0);
+ EXPECT_GT(counter.event_count(), 0u);
+ counter.reset();
+}
+
#if defined(OS_CHROMEOS)
// Tests that a screenshot can be taken in maximize mode by holding volume down
// and pressing power.
@@ -293,6 +422,57 @@ TEST_F(MaximizeModeControllerTest, Screenshot) {
}
#endif // OS_CHROMEOS
+#if defined(USE_X11)
+// Tests that maximize mode allows volume up/down events originating
+// from dedicated buttons versus remapped keyboard buttons.
+TEST_F(MaximizeModeControllerTest, AllowsVolumeControl) {
+ aura::Window* root = Shell::GetPrimaryRootWindow();
+ aura::test::EventGenerator event_generator(root, root);
+
+ TestVolumeControlDelegate* volume_delegate =
+ new TestVolumeControlDelegate(true);
+ ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
+ scoped_ptr<VolumeControlDelegate>(volume_delegate).Pass());
+
+ // Trigger maximize mode by opening to 270 to begin the test in maximize mode.
+ TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, -1.0f),
+ gfx::Vector3dF(-1.0f, 0.0f, 0.0f));
+ ASSERT_TRUE(IsMaximizeModeStarted());
+
+ ui::ScopedXI2Event xevent;
+
+ // Verify F9 button event is blocked
+ ASSERT_EQ(0, volume_delegate->handle_volume_down_count());
+ xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
+ ui::KeyEvent press_f9(xevent, false /* is_char */);
+ press_f9.set_flags(ui::EF_FUNCTION_KEY);
+ event_generator.Dispatch(&press_f9);
+ EXPECT_EQ(0, volume_delegate->handle_volume_down_count());
+
+ // Verify F10 button event is blocked
+ ASSERT_EQ(0, volume_delegate->handle_volume_up_count());
+ xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_VOLUME_UP, ui::EF_NONE);
+ ui::KeyEvent press_f10(xevent, false /* is_char */);
+ press_f10.set_flags(ui::EF_FUNCTION_KEY);
+ event_generator.Dispatch(&press_f10);
+ EXPECT_EQ(0, volume_delegate->handle_volume_up_count());
+
+ // Verify volume down button event is not blocked
+ ASSERT_EQ(0, volume_delegate->handle_volume_down_count());
+ xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
+ ui::KeyEvent press_vol_down(xevent, false /* is_char */);
+ event_generator.Dispatch(&press_vol_down);
+ EXPECT_EQ(1, volume_delegate->handle_volume_down_count());
+
+ // Verify volume up event is not blocked
+ ASSERT_EQ(0, volume_delegate->handle_volume_up_count());
+ xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_VOLUME_UP, ui::EF_NONE);
+ ui::KeyEvent press_vol_up(xevent, false /* is_char */);
+ event_generator.Dispatch(&press_vol_up);
+ EXPECT_EQ(1, volume_delegate->handle_volume_up_count());
+}
+#endif // defined(USE_X11)
+
TEST_F(MaximizeModeControllerTest, LaptopTest) {
// Feeds in sample accelerometer data and verifies that there are no
// transitions into touchview / maximize mode while shaking the device around
diff --git a/ash/wm/maximize_mode/maximize_mode_event_blocker.cc b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc
new file mode 100644
index 0000000..24b1d7d
--- /dev/null
+++ b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc
@@ -0,0 +1,165 @@
+// 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/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 {
+
+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.
+class BlockKeyboardAndTouchpadTargeter : public ui::EventTargeter {
+ public:
+ BlockKeyboardAndTouchpadTargeter(
+ aura::Window* root_window,
+ MaximizeModeEventBlocker* event_blocker);
+ virtual ~BlockKeyboardAndTouchpadTargeter();
+
+ // Sets the default targeter to use when the event is not being blocked.
+ void SetDefaultTargeter(EventTargeter* default_targeter);
+
+ // Overridden from ui::EventTargeter:
+ virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
+ 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(
+ 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() {
+}
+
+void BlockKeyboardAndTouchpadTargeter::SetDefaultTargeter(
+ ui::EventTargeter* default_targeter) {
+ default_targeter_ = default_targeter;
+}
+
+ui::EventTarget* BlockKeyboardAndTouchpadTargeter::FindTargetForEvent(
+ ui::EventTarget* root,
+ ui::Event* event) {
+ 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;
+ } 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.
+ ui::KeyEvent* key_event = static_cast<ui::KeyEvent*>(event);
+ if ((key_event->flags() & ui::EF_FUNCTION_KEY) ||
+ (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
+#endif
+ )
+ ) {
+ return NULL;
+ }
+ }
+ return default_targeter_->FindTargetForEvent(root, event);
+}
+
+} // namespace
+
+MaximizeModeEventBlocker::MaximizeModeEventBlocker()
+#if defined(USE_X11)
+ : internal_devices_(new InternalInputDeviceListX11)
+#endif
+ {
+ Shell::GetInstance()->AddShellObserver(this);
+
+ // Hide the cursor as mouse events will be blocked.
+ aura::client::CursorClient* cursor_client_ =
+ aura::client::GetCursorClient(Shell::GetTargetRootWindow());
+ if (cursor_client_)
+ cursor_client_->HideCursor();
+
+ // Block keyboard and mouse events on all existing and new root windows for
+ // the lifetime of this class.
+ aura::Window::Windows root_windows(Shell::GetAllRootWindows());
+ for (aura::Window::Windows::iterator iter = root_windows.begin();
+ iter != root_windows.end(); ++iter) {
+ AddEventTargeterOn(*iter);
+ }
+}
+
+MaximizeModeEventBlocker::~MaximizeModeEventBlocker() {
+ Shell::GetInstance()->RemoveShellObserver(this);
+}
+
+void MaximizeModeEventBlocker::OnRootWindowAdded(aura::Window* root_window) {
+ AddEventTargeterOn(root_window);
+}
+
+void MaximizeModeEventBlocker::AddEventTargeterOn(
+ aura::Window* root_window) {
+ BlockKeyboardAndTouchpadTargeter* targeter =
+ 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());
+ targeters_.push_back(scoped_targeter);
+}
+
+} // namespace ash
diff --git a/ash/wm/maximize_mode/maximize_mode_event_blocker.h b/ash/wm/maximize_mode/maximize_mode_event_blocker.h
new file mode 100644
index 0000000..4f7fae7
--- /dev/null
+++ b/ash/wm/maximize_mode/maximize_mode_event_blocker.h
@@ -0,0 +1,53 @@
+// 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_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"
+
+namespace aura {
+class Window;
+} // namespace aura
+
+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 {
+ public:
+ 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);
+};
+
+} // namespace ash
+
+#endif // ASH_WM_MAXIMIZE_MODE_MAXIMIZE_MODE_EVENT_BLOCKER_H_
diff --git a/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h b/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h
deleted file mode 100644
index 6a1cbde..0000000
--- a/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WM_MAXIMIZE_MODE_SCOPED_DISABLE_INTERNAL_MOUSE_AND_KEYBOARD_H_
-#define ASH_WM_MAXIMIZE_MODE_SCOPED_DISABLE_INTERNAL_MOUSE_AND_KEYBOARD_H_
-
-namespace ash {
-
-class ScopedDisableInternalMouseAndKeyboard {
- public:
- virtual ~ScopedDisableInternalMouseAndKeyboard() {}
-};
-
-} // namespace ash
-
-#endif // ASH_WM_MAXIMIZE_MODE_SCOPED_DISABLE_INTERNAL_MOUSE_AND_KEYBOARD_H_
diff --git a/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.cc b/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.cc
deleted file mode 100644
index 0997333..0000000
--- a/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h"
-
-#include <set>
-#include <X11/extensions/XInput2.h>
-#include <X11/Xlib.h>
-
-#include "ash/display/display_controller.h"
-#include "ash/screen_util.h"
-#include "ash/shell.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/events/event.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/keycodes/keyboard_codes_posix.h"
-#include "ui/events/platform/platform_event_source.h"
-#include "ui/events/x/device_data_manager_x11.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";
-
-// Device id used to indicate that a device has not been detected.
-const int kDeviceIdNone = -1;
-
-gfx::Point GetMouseLocationInScreen() {
- return aura::Env::GetInstance()->last_mouse_location();
-}
-
-void SetMouseLocationInScreen(const gfx::Point& screen_location) {
- gfx::Display display = ash::ScreenUtil::FindDisplayContainingPoint(
- screen_location);
- if (!display.is_valid())
- return;
- aura::Window* root_window = Shell::GetInstance()->display_controller()->
- GetRootWindowForDisplayId(display.id());
- gfx::Point host_location(screen_location);
- aura::client::ScreenPositionClient* client =
- aura::client::GetScreenPositionClient(root_window);
- if (client)
- client->ConvertPointFromScreen(root_window, &host_location);
- root_window->GetHost()->MoveCursorTo(host_location);
-}
-
-} // namespace
-
-ScopedDisableInternalMouseAndKeyboardX11::
- ScopedDisableInternalMouseAndKeyboardX11()
- : touchpad_device_id_(kDeviceIdNone),
- keyboard_device_id_(kDeviceIdNone),
- last_mouse_location_(GetMouseLocationInScreen()) {
-
- ui::DeviceDataManagerX11* device_data_manager =
- static_cast<ui::DeviceDataManagerX11*>(
- ui::DeviceDataManager::GetInstance());
- if (device_data_manager->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) {
- touchpad_device_id_ = xi_dev_list[i].deviceid;
- device_data_manager->DisableDevice(touchpad_device_id_);
- } else if (device_name == kInternalKeyboardName) {
- keyboard_device_id_ = xi_dev_list[i].deviceid;
- device_data_manager->DisableDevice(keyboard_device_id_);
- }
- }
- }
- // Allow the accessible keys present on the side of some devices to continue
- // working.
- scoped_ptr<std::set<ui::KeyboardCode> > excepted_keys(
- new std::set<ui::KeyboardCode>);
- excepted_keys->insert(ui::VKEY_VOLUME_DOWN);
- excepted_keys->insert(ui::VKEY_VOLUME_UP);
- excepted_keys->insert(ui::VKEY_POWER);
- device_data_manager->DisableKeyboard(excepted_keys.Pass());
- ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
-}
-
-ScopedDisableInternalMouseAndKeyboardX11::
- ~ScopedDisableInternalMouseAndKeyboardX11() {
- ui::DeviceDataManagerX11* device_data_manager =
- static_cast<ui::DeviceDataManagerX11*>(
- ui::DeviceDataManager::GetInstance());
- if (touchpad_device_id_ != kDeviceIdNone)
- device_data_manager->EnableDevice(touchpad_device_id_);
- if (keyboard_device_id_ != kDeviceIdNone)
- device_data_manager->EnableDevice(keyboard_device_id_);
- device_data_manager->EnableKeyboard();
- ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
-}
-
-void ScopedDisableInternalMouseAndKeyboardX11::WillProcessEvent(
- const ui::PlatformEvent& event) {
-}
-
-void ScopedDisableInternalMouseAndKeyboardX11::DidProcessEvent(
- const ui::PlatformEvent& event) {
- if (event->type != GenericEvent)
- return;
- XIDeviceEvent* xievent =
- static_cast<XIDeviceEvent*>(event->xcookie.data);
- ui::DeviceDataManagerX11* device_data_manager =
- static_cast<ui::DeviceDataManagerX11*>(
- ui::DeviceDataManager::GetInstance());
- if (xievent->evtype != XI_Motion ||
- device_data_manager->IsFlingEvent(event) ||
- device_data_manager->IsScrollEvent(event) ||
- device_data_manager->IsCMTMetricsEvent(event)) {
- return;
- }
- if (xievent->sourceid == touchpad_device_id_) {
- // The cursor will have already moved even though the move event will be
- // blocked. Move the mouse cursor back to its last known location resulting
- // from an external mouse to prevent the internal touchpad from moving it.
- SetMouseLocationInScreen(last_mouse_location_);
- } else {
- // Track the last location seen from an external mouse event.
- last_mouse_location_ = GetMouseLocationInScreen();
- }
-}
-
-} // namespace ash
diff --git a/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h b/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h
deleted file mode 100644
index 2a1416b..0000000
--- a/ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WM_MAXIMIZE_MODE_SCOPED_DISABLE_INTERNAL_MOUSE_AND_KEYBOARD_X11_H_
-#define ASH_WM_MAXIMIZE_MODE_SCOPED_DISABLE_INTERNAL_MOUSE_AND_KEYBOARD_X11_H_
-
-#include <vector>
-
-#include "ash/ash_export.h"
-#include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h"
-#include "base/macros.h"
-#include "ui/events/platform/platform_event_observer.h"
-#include "ui/gfx/point.h"
-
-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 ScopedDisableInternalMouseAndKeyboardX11
- : public ScopedDisableInternalMouseAndKeyboard,
- public ui::PlatformEventObserver {
- public:
- ScopedDisableInternalMouseAndKeyboardX11();
- virtual ~ScopedDisableInternalMouseAndKeyboardX11();
-
- // ui::PlatformEventObserver:
- virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
- virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
- private:
- int touchpad_device_id_;
- int keyboard_device_id_;
-
- // Tracks the last known mouse cursor location caused before blocking the
- // internal touchpad or caused by an external mouse.
- gfx::Point last_mouse_location_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedDisableInternalMouseAndKeyboardX11);
-};
-
-} // namespace ash
-
-#endif // ASH_WM_MAXIMIZE_MODE_SCOPED_DISABLE_INTERNAL_MOUSE_AND_KEYBOARD_X11_H_