Index: ash/wm/maximize_mode/maximize_mode_event_blocker.cc |
diff --git a/ash/wm/maximize_mode/maximize_mode_event_blocker.cc b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc |
index e283149b6fe66755d368efea094e209f45419b0c..f9fef09b0d25d521ce92370fef760c59317ca6f4 100644 |
--- a/ash/wm/maximize_mode/maximize_mode_event_blocker.cc |
+++ b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc |
@@ -4,23 +4,42 @@ |
#include "ash/wm/maximize_mode/maximize_mode_event_blocker.h" |
+#if defined(USE_X11) |
+#include <X11/extensions/XInput2.h> |
+#include <X11/Xlib.h> |
+#endif |
sadrul
2014/05/02 01:44:47
I think these still go below, grouped with the blo
flackr
2014/05/07 01:39:23
Done.
|
+ |
#include "ash/shell.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/strings/string_util.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/gfx/point.h" |
+ |
+#if defined(USE_X11) |
+#include "ui/events/x/device_data_manager.h" |
+#include "ui/events/x/device_list_cache_x.h" |
+#include "ui/gfx/x/x11_types.h" |
+#endif |
namespace ash { |
namespace { |
+#if defined(USE_X11) |
+// The name of the xinput device corresponding to the internal touchpad. |
+const char kInternalTouchpadName[] = "Elan Touchpad"; |
+#endif |
+ |
// 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, |
+ std::set<int>* internal_device_ids); |
virtual ~BlockKeyboardAndTouchpadTargeter(); |
// Sets the default targeter to use when the event is not being blocked. |
@@ -31,16 +50,32 @@ class BlockKeyboardAndTouchpadTargeter : public ui::EventTargeter { |
ui::Event* event) OVERRIDE; |
private: |
+ // A weak pointer to the root window on which this targeter will be set. |
+ aura::Window* root_window_; |
+ |
+ // A weak pointer to the set of device ids to block. |
+ std::set<int>* internal_device_ids_; |
+ |
// 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, |
+ std::set<int>* internal_device_ids) |
+ : root_window_(root_window), |
+ internal_device_ids_(internal_device_ids), |
+ default_targeter_(NULL), |
+ last_mouse_location_(root_window->GetHost()->dispatcher()-> |
+ GetLastMouseLocationInRoot()) { |
} |
BlockKeyboardAndTouchpadTargeter::~BlockKeyboardAndTouchpadTargeter() { |
@@ -54,8 +89,33 @@ void BlockKeyboardAndTouchpadTargeter::SetDefaultTargeter( |
ui::EventTarget* BlockKeyboardAndTouchpadTargeter::FindTargetForEvent( |
ui::EventTarget* root, |
ui::Event* event) { |
- if (event->HasNativeEvent() && (event->IsMouseEvent() || event->IsKeyEvent())) |
- return NULL; |
+ if (event->HasNativeEvent()) { |
+ if (event->IsMouseEvent()) { |
+#if defined(USE_X11) |
+ XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>( |
+ event->native_event()->xcookie.data); |
+ if (internal_device_ids_->find(xiev->sourceid) != |
+ internal_device_ids_->end()) { |
+ 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)->location(); |
+ root_window_->GetHost()->GetRootTransform().TransformPoint( |
+ &last_mouse_location_); |
+ } |
+#else |
+ return NULL; |
+#endif |
+ } else if (event->IsKeyEvent()) { |
+ // 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. |
+ return NULL; |
+ } |
+ } |
return default_targeter_->FindTargetForEvent(root, event); |
} |
@@ -64,6 +124,19 @@ ui::EventTarget* BlockKeyboardAndTouchpadTargeter::FindTargetForEvent( |
MaximizeModeEventBlocker::MaximizeModeEventBlocker() { |
Shell::GetInstance()->AddShellObserver(this); |
+#if defined(USE_X11) |
+ 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) |
+ internal_device_ids_.insert(xi_dev_list[i].deviceid); |
+ } |
+ } |
+#endif |
+ |
// Hide the cursor as mouse events will be blocked. |
aura::client::CursorClient* cursor_client_ = |
aura::client::GetCursorClient(Shell::GetTargetRootWindow()); |
@@ -90,7 +163,8 @@ void MaximizeModeEventBlocker::OnRootWindowAdded(aura::Window* root_window) { |
void MaximizeModeEventBlocker::AddEventTargeterOn( |
aura::Window* root_window) { |
BlockKeyboardAndTouchpadTargeter* targeter = |
- new BlockKeyboardAndTouchpadTargeter(); |
+ new BlockKeyboardAndTouchpadTargeter(root_window, |
+ &internal_device_ids_); |
aura::ScopedWindowTargeter* scoped_targeter = new aura::ScopedWindowTargeter( |
root_window, scoped_ptr<ui::EventTargeter>(targeter)); |
targeter->SetDefaultTargeter(scoped_targeter->old_targeter()); |