Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ash / wm / maximize_mode / scoped_disable_internal_mouse_and_keyboard_x11.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h"
6
7 #include <set>
8 #include <X11/extensions/XInput2.h>
9 #include <X11/Xlib.h>
10
11 #include "ash/display/display_controller.h"
12 #include "ash/screen_util.h"
13 #include "ash/shell.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/strings/string_util.h"
16 #include "ui/aura/client/cursor_client.h"
17 #include "ui/aura/client/screen_position_client.h"
18 #include "ui/aura/env.h"
19 #include "ui/aura/window.h"
20 #include "ui/aura/window_event_dispatcher.h"
21 #include "ui/aura/window_tree_host.h"
22 #include "ui/events/devices/x11/device_data_manager_x11.h"
23 #include "ui/events/devices/x11/device_list_cache_x11.h"
24 #include "ui/events/event.h"
25 #include "ui/events/event_utils.h"
26 #include "ui/events/keycodes/keyboard_codes_posix.h"
27 #include "ui/events/platform/platform_event_source.h"
28 #include "ui/gfx/x/x11_types.h"
29
30 namespace ash {
31
32 namespace {
33
34 // The name of the xinput device corresponding to the internal touchpad.
35 const char kInternalTouchpadName[] = "Elan Touchpad";
36
37 // The name of the xinput device corresponding to the internal keyboard.
38 const char kInternalKeyboardName[] = "AT Translated Set 2 keyboard";
39
40 // Repeated key events have their source set to the core keyboard device.
41 // These must be disabled also until http://crbug.com/402898 is resolved.
42 const char kCoreKeyboardName[] = "Virtual core keyboard";
43
44 // Device id used to indicate that a device has not been detected.
45 const int kDeviceIdNone = -1;
46
47 gfx::Point GetMouseLocationInScreen() {
48   return aura::Env::GetInstance()->last_mouse_location();
49 }
50
51 void SetMouseLocationInScreen(const gfx::Point& screen_location) {
52   gfx::Display display = ash::ScreenUtil::FindDisplayContainingPoint(
53       screen_location);
54   if (!display.is_valid())
55     return;
56   aura::Window* root_window = Shell::GetInstance()->display_controller()->
57       GetRootWindowForDisplayId(display.id());
58   gfx::Point host_location(screen_location);
59   aura::client::ScreenPositionClient* client =
60       aura::client::GetScreenPositionClient(root_window);
61   if (client)
62     client->ConvertPointFromScreen(root_window, &host_location);
63   root_window->GetHost()->MoveCursorTo(host_location);
64 }
65
66 }  // namespace
67
68 ScopedDisableInternalMouseAndKeyboardX11::
69     ScopedDisableInternalMouseAndKeyboardX11()
70     : touchpad_device_id_(kDeviceIdNone),
71       keyboard_device_id_(kDeviceIdNone),
72       core_keyboard_device_id_(kDeviceIdNone),
73       last_mouse_location_(GetMouseLocationInScreen()) {
74
75   ui::DeviceDataManagerX11* device_data_manager =
76       static_cast<ui::DeviceDataManagerX11*>(
77           ui::DeviceDataManager::GetInstance());
78   if (device_data_manager->IsXInput2Available()) {
79     XIDeviceList xi_dev_list = ui::DeviceListCacheX11::GetInstance()->
80         GetXI2DeviceList(gfx::GetXDisplay());
81     for (int i = 0; i < xi_dev_list.count; ++i) {
82       std::string device_name(xi_dev_list[i].name);
83       base::TrimWhitespaceASCII(device_name, base::TRIM_TRAILING, &device_name);
84       if (device_name == kInternalTouchpadName) {
85         touchpad_device_id_ = xi_dev_list[i].deviceid;
86         device_data_manager->DisableDevice(touchpad_device_id_);
87         aura::client::GetCursorClient(
88             Shell::GetInstance()->GetPrimaryRootWindow())->HideCursor();
89       } else if (device_name == kInternalKeyboardName) {
90         keyboard_device_id_ = xi_dev_list[i].deviceid;
91         device_data_manager->DisableDevice(keyboard_device_id_);
92       } else if (device_name == kCoreKeyboardName) {
93         core_keyboard_device_id_ = xi_dev_list[i].deviceid;
94         device_data_manager->DisableDevice(core_keyboard_device_id_);
95       }
96     }
97   }
98   // Allow the accessible keys present on the side of some devices to continue
99   // working.
100   scoped_ptr<std::set<ui::KeyboardCode> > excepted_keys(
101       new std::set<ui::KeyboardCode>);
102   excepted_keys->insert(ui::VKEY_VOLUME_DOWN);
103   excepted_keys->insert(ui::VKEY_VOLUME_UP);
104   excepted_keys->insert(ui::VKEY_POWER);
105   device_data_manager->SetDisabledKeyboardAllowedKeys(excepted_keys.Pass());
106   ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
107 }
108
109 ScopedDisableInternalMouseAndKeyboardX11::
110     ~ScopedDisableInternalMouseAndKeyboardX11() {
111   ui::DeviceDataManagerX11* device_data_manager =
112       static_cast<ui::DeviceDataManagerX11*>(
113           ui::DeviceDataManager::GetInstance());
114   if (touchpad_device_id_ != kDeviceIdNone)
115     device_data_manager->EnableDevice(touchpad_device_id_);
116   if (keyboard_device_id_ != kDeviceIdNone)
117     device_data_manager->EnableDevice(keyboard_device_id_);
118   if (core_keyboard_device_id_ != kDeviceIdNone)
119     device_data_manager->EnableDevice(core_keyboard_device_id_);
120   device_data_manager->SetDisabledKeyboardAllowedKeys(
121       scoped_ptr<std::set<ui::KeyboardCode> >());
122   ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
123 }
124
125 void ScopedDisableInternalMouseAndKeyboardX11::WillProcessEvent(
126     const ui::PlatformEvent& event) {
127 }
128
129 void ScopedDisableInternalMouseAndKeyboardX11::DidProcessEvent(
130     const ui::PlatformEvent& event) {
131   if (event->type != GenericEvent)
132     return;
133   XIDeviceEvent* xievent =
134       static_cast<XIDeviceEvent*>(event->xcookie.data);
135   ui::DeviceDataManagerX11* device_data_manager =
136       static_cast<ui::DeviceDataManagerX11*>(
137           ui::DeviceDataManager::GetInstance());
138   if (xievent->evtype != XI_Motion ||
139       device_data_manager->IsFlingEvent(event) ||
140       device_data_manager->IsScrollEvent(event) ||
141       device_data_manager->IsCMTMetricsEvent(event)) {
142     return;
143   }
144   if (xievent->sourceid == touchpad_device_id_) {
145     // The cursor will have already moved even though the move event will be
146     // blocked. Move the mouse cursor back to its last known location resulting
147     // from an external mouse to prevent the internal touchpad from moving it.
148     SetMouseLocationInScreen(last_mouse_location_);
149   } else {
150     // Track the last location seen from an external mouse event.
151     last_mouse_location_ = GetMouseLocationInScreen();
152   }
153 }
154
155 }  // namespace ash