input_device_settings.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright (c) 2012 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 "chrome/browser/chromeos/system/input_device_settings.h" 6 7#include <stdarg.h> 8#include <string> 9#include <vector> 10 11#include "base/bind.h" 12#include "base/chromeos/chromeos_version.h" 13#include "base/command_line.h" 14#include "base/file_util.h" 15#include "base/files/file_path.h" 16#include "base/message_loop.h" 17#include "base/process.h" 18#include "base/process_util.h" 19#include "base/strings/stringprintf.h" 20#include "base/threading/sequenced_worker_pool.h" 21#include "content/public/browser/browser_thread.h" 22 23namespace chromeos { 24namespace system { 25 26namespace { 27 28const char kTpControl[] = "/opt/google/touchpad/tpcontrol"; 29const char kMouseControl[] = "/opt/google/mouse/mousecontrol"; 30 31bool ScriptExists(const std::string& script) { 32 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 33 return file_util::PathExists(base::FilePath(script)); 34} 35 36// Executes the input control script asynchronously, if it exists. 37void ExecuteScriptOnFileThread(const std::vector<std::string>& argv) { 38 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 39 DCHECK(!argv.empty()); 40 const std::string& script(argv[0]); 41 42 // Script must exist on device. 43 DCHECK(!base::chromeos::IsRunningOnChromeOS() || ScriptExists(script)); 44 45 if (!ScriptExists(script)) 46 return; 47 48 base::ProcessHandle handle; 49 base::LaunchProcess(CommandLine(argv), base::LaunchOptions(), &handle); 50 base::EnsureProcessGetsReaped(handle); 51} 52 53void ExecuteScript(int argc, ...) { 54 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 55 std::vector<std::string> argv; 56 va_list vl; 57 va_start(vl, argc); 58 for (int i = 0; i < argc; ++i) { 59 argv.push_back(va_arg(vl, const char*)); 60 } 61 va_end(vl); 62 63 content::BrowserThread::GetBlockingPool()->PostTask(FROM_HERE, 64 base::Bind(&ExecuteScriptOnFileThread, argv)); 65} 66 67void SetPointerSensitivity(const char* script, int value) { 68 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 69 DCHECK(value >= kMinPointerSensitivity && value <= kMaxPointerSensitivity); 70 ExecuteScript( 71 3, script, "sensitivity", base::StringPrintf("%d", value).c_str()); 72} 73 74void SetTPControl(const char* control, bool enabled) { 75 ExecuteScript(3, kTpControl, control, enabled ? "on" : "off"); 76} 77 78void DeviceExistsBlockingPool(const char* script, bool* exists) { 79 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 80 *exists = false; 81 if (!ScriptExists(script)) 82 return; 83 84 std::vector<std::string> argv; 85 argv.push_back(script); 86 argv.push_back("status"); 87 std::string output; 88 // Output is empty if the device is not found. 89 *exists = base::GetAppOutput(CommandLine(argv), &output) && !output.empty(); 90 DVLOG(1) << "DeviceExistsBlockingPool:" << script << "=" << *exists; 91} 92 93void RunCallbackUIThread(bool* exists, const DeviceExistsCallback& callback) { 94 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 95 DVLOG(1) << "RunCallbackUIThread " << *exists; 96 callback.Run(*exists); 97} 98 99void DeviceExists(const char* script, const DeviceExistsCallback& callback) { 100 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 101 102 bool* exists = new bool(false); 103 content::BrowserThread::GetBlockingPool()->PostTaskAndReply(FROM_HERE, 104 base::Bind(&DeviceExistsBlockingPool, script, exists), 105 base::Bind(&RunCallbackUIThread, base::Owned(exists), callback)); 106} 107 108} // namespace 109 110namespace touchpad_settings { 111 112void TouchpadExists(const DeviceExistsCallback& callback) { 113 DeviceExists(kTpControl, callback); 114} 115 116// Sets the touchpad sensitivity in the range [1, 5]. 117void SetSensitivity(int value) { 118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 119 SetPointerSensitivity(kTpControl, value); 120} 121 122void SetTapToClick(bool enabled) { 123 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 124 SetTPControl("taptoclick", enabled); 125} 126 127void SetThreeFingerClick(bool enabled) { 128 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 129 130 SetTPControl("three_finger_click", enabled); 131 // For Alex/ZGB. 132 SetTPControl("t5r2_three_finger_click", enabled); 133} 134 135void SetThreeFingerSwipe(bool enabled) { 136 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 137 SetTPControl("three_finger_swipe", enabled); 138} 139 140void SetTapDragging(bool enabled) { 141 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 142 SetTPControl("tap_dragging", enabled); 143} 144 145} // namespace touchpad_settings 146 147namespace mouse_settings { 148 149void MouseExists(const DeviceExistsCallback& callback) { 150 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 151 DeviceExists(kMouseControl, callback); 152} 153 154// Sets the touchpad sensitivity in the range [1, 5]. 155void SetSensitivity(int value) { 156 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 157 SetPointerSensitivity(kMouseControl, value); 158} 159 160void SetPrimaryButtonRight(bool right) { 161 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 162 ExecuteScript(3, kMouseControl, "swap_left_right", right ? "1" : "0"); 163} 164 165} // namespace mouse_settings 166 167} // namespace system 168} // namespace chromeos 169