Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Unified Diff: src/platform/autox/script_runner.cc

Issue 2074007: autox: Remove C++ version. (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/platform/autox/script_runner.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/platform/autox/script_runner.cc
diff --git a/src/platform/autox/script_runner.cc b/src/platform/autox/script_runner.cc
deleted file mode 100644
index 7356a4ab0c1f13f282729108649975193b54e7a1..0000000000000000000000000000000000000000
--- a/src/platform/autox/script_runner.cc
+++ /dev/null
@@ -1,426 +0,0 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "autox/script_runner.h"
-
-#include <cstdlib>
-#include <unistd.h>
-#include <utility>
-#include <vector>
-
-extern "C" {
-#include <X11/keysym.h>
-#include <X11/extensions/XTest.h>
-}
-
-#include "base/json/json_reader.h"
-#include "base/logging.h"
-#include "base/scoped_ptr.h"
-#include "base/string_util.h"
-#include "chromeos/string.h"
-
-using chromeos::SplitStringUsing;
-using std::make_pair;
-using std::map;
-using std::pair;
-using std::set;
-using std::string;
-using std::vector;
-
-namespace autox {
-
-// Check that a command got the expected number of arguments, crashing with
-// an error otherwise. Helper function for command handlers.
-static void CheckNumArgs(const ListValue& values,
- int num_args_expected,
- int command_num) {
- string command_name;
- CHECK(values.GetString(0, &command_name)); // asserted in RunScript()
- int num_args = values.GetSize() - 1;
- CHECK(num_args == num_args_expected)
- << "Command " << command_num << ": " << command_name << " requires "
- << num_args_expected << " argument" << (num_args_expected == 1 ? "" : "s")
- << " (got " << num_args << " instead)";
-}
-
-// Given a string beginning with '\', interpret a prefix of the following
-// characters as an escaped keysym name (e.g. "\(Return)". The extracted
-// keysym is stored in 'keysym_out', and the number of characters that
-// should be skipped to get to the next character in the string (including
-// the leading '\') are stored in 'escaped_length_out'. Returns false if
-// unable to interpret the escaped sequence.
-static bool ConvertEscapedStringToKeySym(const string& escaped_str,
- KeySym* keysym_out,
- int* escaped_length_out) {
- CHECK(keysym_out);
- CHECK(escaped_length_out);
- CHECK(escaped_str[0] == '\\');
-
- if (escaped_str.size() < 2)
- return false;
-
- if (escaped_str[1] == '\\') {
- *keysym_out = XK_backslash;
- *escaped_length_out = 2;
- return true;
- }
-
- if (escaped_str[1] != '(')
- return false;
- size_t end_pos = escaped_str.find(')', 2);
- if (end_pos == string::npos || end_pos == 2)
- return false;
- *keysym_out = XStringToKeysym(escaped_str.substr(2, end_pos - 2).c_str());
- *escaped_length_out = end_pos + 1;
- return (*keysym_out != NoSymbol);
-}
-
-
-ScriptRunner::ScriptRunner(Display* display)
- : display_(display) {
- // TODO: This is probably incomplete. I can't find any existing function
- // that does something similar, though.
- chars_to_keysyms_.insert(make_pair(' ', XK_space));
- chars_to_keysyms_.insert(make_pair('\n', XK_Return));
- chars_to_keysyms_.insert(make_pair('\t', XK_Tab));
- chars_to_keysyms_.insert(make_pair('~', XK_asciitilde));
- chars_to_keysyms_.insert(make_pair('!', XK_exclam));
- chars_to_keysyms_.insert(make_pair('@', XK_at));
- chars_to_keysyms_.insert(make_pair('#', XK_numbersign));
- chars_to_keysyms_.insert(make_pair('$', XK_dollar));
- chars_to_keysyms_.insert(make_pair('%', XK_percent));
- chars_to_keysyms_.insert(make_pair('^', XK_asciicircum));
- chars_to_keysyms_.insert(make_pair('&', XK_ampersand));
- chars_to_keysyms_.insert(make_pair('*', XK_asterisk));
- chars_to_keysyms_.insert(make_pair('(', XK_parenleft));
- chars_to_keysyms_.insert(make_pair(')', XK_parenright));
- chars_to_keysyms_.insert(make_pair('-', XK_minus));
- chars_to_keysyms_.insert(make_pair('_', XK_underscore));
- chars_to_keysyms_.insert(make_pair('+', XK_plus));
- chars_to_keysyms_.insert(make_pair('=', XK_equal));
- chars_to_keysyms_.insert(make_pair('{', XK_braceleft));
- chars_to_keysyms_.insert(make_pair('[', XK_bracketleft));
- chars_to_keysyms_.insert(make_pair('}', XK_braceright));
- chars_to_keysyms_.insert(make_pair(']', XK_bracketright));
- chars_to_keysyms_.insert(make_pair('|', XK_bar));
- chars_to_keysyms_.insert(make_pair(':', XK_colon));
- chars_to_keysyms_.insert(make_pair(';', XK_semicolon));
- chars_to_keysyms_.insert(make_pair('"', XK_quotedbl));
- chars_to_keysyms_.insert(make_pair('\'', XK_apostrophe));
- chars_to_keysyms_.insert(make_pair(',', XK_comma));
- chars_to_keysyms_.insert(make_pair('<', XK_less));
- chars_to_keysyms_.insert(make_pair('.', XK_period));
- chars_to_keysyms_.insert(make_pair('>', XK_greater));
- chars_to_keysyms_.insert(make_pair('/', XK_slash));
- chars_to_keysyms_.insert(make_pair('?', XK_question));
-
- LoadKeyboardMapping();
-}
-
-void ScriptRunner::RunScript(const string& script) {
- CHECK(display_);
-
- // Reading JSON programmatically is pretty ugly, but the general
- // structure is a dictionary with "script" mapping to a list of commands,
- // where each command is itself a list consisting of a command name
- // followed by the command's arguments:
- //
- // { "script": [
- // [ "motion", 20, 40 ],
- // [ "button_down", 1 ],
- // [ "motion", 400, 300 ],
- // [ "button_up", 1 ],
- // ],
- // }
- //
- // TODO: The toplevel dictionary is there to support additional
- // parameters that will inevitably be needed at some point.
-
- scoped_ptr<Value> toplevel_value(base::JSONReader::Read(script, true));
- CHECK(toplevel_value.get())
- << "Unable to parse script as JSON";
- CHECK(toplevel_value->IsType(Value::TYPE_DICTIONARY))
- << "Toplevel value must be a dictionary";
- DictionaryValue* toplevel_dict =
- static_cast<DictionaryValue*>(toplevel_value.get());
-
- Value* script_value = NULL;
- CHECK(toplevel_dict->Get(L"script", &script_value))
- << "No \"script\" value in toplevel dictionary";
- CHECK(script_value->IsType(Value::TYPE_LIST))
- << "\"script\" value must be a list";
- ListValue* script_list = static_cast<ListValue*>(script_value);
- const int num_commands = script_list->GetSize();
-
- for (int command_num = 0; command_num < num_commands; ++command_num) {
- Value* command_value = NULL;
- CHECK(script_list->Get(command_num, &command_value));
- CHECK(command_value->IsType(Value::TYPE_LIST))
- << "Command " << command_num << ": not a list";
- ListValue* command_list = static_cast<ListValue*>(command_value);
-
- CHECK(!command_list->empty())
- << "Command " << command_num << ": list is empty";
- Value* command_name_value = NULL;
- CHECK(command_list->Get(0, &command_name_value));
- CHECK(command_name_value->IsType(Value::TYPE_STRING))
- << "Command " << command_num << ": list must start with string";
- string command_name;
- CHECK(command_name_value->GetAsString(&command_name));
-
- if (command_name == "button_down")
- HandleButtonCommand(command_num, *command_list, true);
- else if (command_name == "button_up")
- HandleButtonCommand(command_num, *command_list, false);
- else if (command_name == "hotkey")
- HandleHotkeyCommand(command_num, *command_list);
- else if (command_name == "key_down")
- HandleKeyCommand(command_num, *command_list, true);
- else if (command_name == "key_up")
- HandleKeyCommand(command_num, *command_list, false);
- else if (command_name == "motion")
- HandleMotionCommand(command_num, *command_list, true);
- else if (command_name == "motion_relative")
- HandleMotionCommand(command_num, *command_list, false);
- else if (command_name == "sleep")
- HandleSleepCommand(command_num, *command_list);
- else if (command_name == "string")
- HandleStringCommand(command_num, *command_list);
- else
- CHECK(false) << "Command " << command_num << ": unknown command \""
- << command_name << "\"";
- }
-}
-
-void ScriptRunner::LoadKeyboardMapping() {
- int min_keycode = 0, max_keycode = 0;
- XDisplayKeycodes(display_, &min_keycode, &max_keycode);
- int num_keycodes = max_keycode - min_keycode + 1;
-
- int keysyms_per_keycode = 0;
- KeySym* keysyms = XGetKeyboardMapping(
- display_, min_keycode, num_keycodes, &keysyms_per_keycode);
- CHECK(keysyms);
- CHECK(keysyms_per_keycode >= 1);
-
- keysyms_to_keycodes_.clear();
- for (int i = 0; i < num_keycodes; ++i) {
- KeyCode keycode = min_keycode + i;
- for (int j = 0; j < keysyms_per_keycode; ++j) {
- // This is poorly documented, but it appears to match up with
- // xmodmap's documentation: the first keysym is typed without any
- // modifiers, the second keysym is typed with Shift, the third with
- // Mode_switch, and the fourth with both Shift and Mode_switch ("Up
- // to eight keysyms may be attached to a key, however the last four
- // are not used in any major X server implementation"). We only care
- // about the first two.
- if (j > 1)
- continue;
-
- KeySym keysym = keysyms[i * keysyms_per_keycode + j];
- if (keysym == NoSymbol)
- continue;
-
- // If we already found a way to type this keysym, only replace it if
- // the old way required Shift but the new one doesn't.
- if (keysyms_to_keycodes_.count(keysym) &&
- (!keysyms_to_keycodes_[keysym].second || j != 0))
- continue;
-
- bool shift_required = (j == 1);
- keysyms_to_keycodes_[keysym] = make_pair(keycode, shift_required);
- }
- }
- XFree(keysyms);
-}
-
-bool ScriptRunner::ConvertCharToKeySym(char ch, KeySym* keysym_out) {
- CHECK(keysym_out);
-
- if (isalnum(ch)) {
- string keysym_name(1, ch);
- *keysym_out = XStringToKeysym(keysym_name.c_str());
- return (keysym_out != NoSymbol);
- }
-
- map<char, KeySym>::const_iterator it = chars_to_keysyms_.find(ch);
- if (it == chars_to_keysyms_.end())
- return false;
- *keysym_out = it->second;
- return true;
-}
-
-bool ScriptRunner::KeySymRequiresShift(KeySym keysym) {
- map<KeySym, pair<KeyCode, bool> >::const_iterator it =
- keysyms_to_keycodes_.find(keysym);
- return (it != keysyms_to_keycodes_.end()) ? it->second.second : false;
-}
-
-KeyCode ScriptRunner::GetKeyCodeForKeySym(KeySym keysym) {
- map<KeySym, pair<KeyCode, bool> >::const_iterator it =
- keysyms_to_keycodes_.find(keysym);
- return (it != keysyms_to_keycodes_.end()) ? it->second.first : 0;
-}
-
-void ScriptRunner::HandleButtonCommand(int command_num,
- const ListValue& values,
- bool button_down) {
- CheckNumArgs(values, 1, command_num);
- int button = 1;
- CHECK(values.GetInteger(1, &button)) << "Command " << command_num;
- XTestFakeButtonEvent(display_, button, button_down ? True : False, 0);
- XFlush(display_);
-}
-
-void ScriptRunner::HandleHotkeyCommand(int command_num,
- const ListValue& values) {
- CheckNumArgs(values, 1, command_num);
- string text;
- CHECK(values.GetString(1, &text)) << "Command " << command_num;
- CHECK(!text.empty()) << "Command " << command_num;
-
- vector<string> parts;
- SplitStringUsing(text, "-", &parts);
- CHECK(parts.size() >= 2) << "Command " << command_num;
-
- bool saw_shift = false;
-
- vector<KeyCode> keycodes;
- for (vector<string>::const_iterator it = parts.begin();
- it != parts.end(); ++it) {
- string keysym_name = *it;
- // Map some convenient short names to full keysym names.
- if (keysym_name == "Ctrl")
- keysym_name = "Control_L";
- else if (keysym_name == "Alt")
- keysym_name = "Alt_L";
- else if (keysym_name == "Shift")
- keysym_name = "Shift_L";
-
- KeySym keysym = XStringToKeysym(keysym_name.c_str());
- CHECK(keysym != NoSymbol)
- << "Command " << command_num << ": Unable to look "
- << "up keysym with name \"" << keysym_name << "\"";
-
- if (keysym == XK_Shift_L || keysym == XK_Shift_R)
- saw_shift = true;
-
- KeyCode keycode = GetKeyCodeForKeySym(keysym);
- CHECK(keycode != 0) << "Command " << command_num << ": Unable to convert "
- << "keysym " << keysym << " (\"" << keysym_name
- << "\") to keycode";
-
- // Crash if we're being asked to press a key that requires Shift and the
- // Shift key wasn't pressed already (but let it slide if they're just
- // asking for an uppercase letter).
- CHECK(!KeySymRequiresShift(keysym) || saw_shift ||
- (isupper(keysym_name[0]) && keysym_name[1] == '\0'))
- << "Command " << command_num << ": Keysym " << keysym_name
- << " requires the Shift key to be held, but it wasn't seen earlier in "
- << "the key combo. Either press Shift first or use the keycode's "
- << "non-shifted keysym";
-
- keycodes.push_back(keycode);
- }
-
- // Press the keys in order and then release them in reverse order.
- for (vector<KeyCode>::const_iterator it = keycodes.begin();
- it != keycodes.end(); ++it) {
- XTestFakeKeyEvent(display_, *it, True, 0);
- }
- for (vector<KeyCode>::const_reverse_iterator it = keycodes.rbegin();
- it != keycodes.rend(); ++it) {
- XTestFakeKeyEvent(display_, *it, False, 0);
- }
- XFlush(display_);
-}
-
-void ScriptRunner::HandleKeyCommand(int command_num,
- const ListValue& values,
- bool key_down) {
- CheckNumArgs(values, 1, command_num);
- string keysym_name;
- CHECK(values.GetString(1, &keysym_name)) << "Command " << command_num;
-
- KeySym keysym = XStringToKeysym(keysym_name.c_str());
- CHECK(keysym != NoSymbol) << "Command " << command_num << ": Unable to look "
- << "up keysym with name \"" << keysym_name << "\"";
- KeyCode keycode = GetKeyCodeForKeySym(keysym);
- CHECK(keycode != 0) << "Command " << command_num << ": Unable to convert "
- << "keysym " << keysym << " to keycode";
-
- CHECK(!KeySymRequiresShift(keysym))
- << "Command " << command_num << ": Keysym " << keysym_name << " cannot "
- << "be typed with the \"key\" command since it requires the Shift key "
- << "to be held. Either use \"string\" or use separate \"key\" commands, "
- << "one with Shift and then one with the keycode's non-shifted keysym";
-
- XTestFakeKeyEvent(display_, keycode, key_down ? True : False, 0);
- XFlush(display_);
-}
-
-void ScriptRunner::HandleMotionCommand(int command_num,
- const ListValue& values,
- bool absolute) {
- CheckNumArgs(values, 2, command_num);
- int x = 0, y = 0;
- CHECK(values.GetInteger(1, &x)) << "Command " << command_num;
- CHECK(values.GetInteger(2, &y)) << "Command " << command_num;
- if (absolute)
- XTestFakeMotionEvent(display_, 0, x, y, 0);
- else
- XTestFakeRelativeMotionEvent(display_, x, y, 0);
- XFlush(display_);
-}
-
-void ScriptRunner::HandleSleepCommand(int command_num,
- const ListValue& values) {
- CheckNumArgs(values, 1, command_num);
- int time_ms = 0;
- CHECK(values.GetInteger(1, &time_ms)) << "Command " << command_num;
- usleep(1000LL * time_ms);
-}
-
-void ScriptRunner::HandleStringCommand(int command_num,
- const ListValue& values) {
- CheckNumArgs(values, 1, command_num);
- string text;
- CHECK(values.GetString(1, &text)) << "Command " << command_num;
-
- KeyCode shift_keycode = GetKeyCodeForKeySym(XK_Shift_L);
- CHECK(shift_keycode) << "Unable to look up keycode for XK_Shift_L";
-
- for (size_t i = 0; i < text.size(); ++i) {
- char ch = text[i];
-
- KeySym keysym;
- if (ch == '\\') {
- int num_chars_to_skip = 1;
- CHECK(ConvertEscapedStringToKeySym(
- text.substr(i), &keysym, &num_chars_to_skip))
- << "Command " << command_num << ": Unable to convert escaped "
- << "sequence at beginning of \"" << text.substr(i) << "\" to keysym";
- CHECK(num_chars_to_skip >= 1);
- i += num_chars_to_skip - 1; // - 1 to compensate for loop's ++i
- } else {
- CHECK(ConvertCharToKeySym(ch, &keysym))
- << "Command " << command_num << ": Unable to convert character '"
- << ch << "' to keysym";
- }
- KeyCode keycode = GetKeyCodeForKeySym(keysym);
- CHECK(keycode != 0) << "Command " << command_num << ": Unable to convert "
- << "keysym " << keysym << " to keycode";
-
- bool shift_required = KeySymRequiresShift(keysym);
- if (shift_required)
- XTestFakeKeyEvent(display_, shift_keycode, True, 0);
- XTestFakeKeyEvent(display_, keycode, True, 0);
- XTestFakeKeyEvent(display_, keycode, False, 0);
- if (shift_required)
- XTestFakeKeyEvent(display_, shift_keycode, False, 0);
- }
- XFlush(display_);
-}
-
-} // namespace autox
« no previous file with comments | « src/platform/autox/script_runner.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698