Chromium Code Reviews| 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..7762abd9ca043fa0934792d8598d314b3273985e 100644 |
| --- a/ash/wm/maximize_mode/maximize_mode_event_blocker.cc |
| +++ b/ash/wm/maximize_mode/maximize_mode_event_blocker.cc |
| @@ -6,21 +6,38 @@ |
| #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 <X11/extensions/XInput2.h> |
| +#include <X11/Xlib.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" |
| +#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 +48,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_; |
|
sadrul
2014/05/07 13:59:23
We expect that the root-window will outlive this t
flackr
2014/05/14 16:46:56
Yes, commented.
|
| + |
| + // 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 +87,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_); |
|
sadrul
2014/05/07 13:59:23
Add a comment here about why we are doing this (it
flackr
2014/05/14 16:46:56
Done.
|
| + 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_); |
|
sadrul
2014/05/07 13:59:23
Use WindowTreeHost::ConvertPointToHost on the even
flackr
2014/05/14 16:46:56
Done.
|
| + } |
| +#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 +122,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); |
|
sadrul
2014/05/07 13:59:23
How safe is it to assume that the name is ASCII?
flackr
2014/05/14 16:46:56
It should be safe, TrimWhitespaceASCII uses std::s
|
| + 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 +161,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()); |