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