--- a/src/X11Handler.h Sun Mar 28 19:09:44 2021 +0200
+++ b/src/X11Handler.h Sun Mar 28 21:02:02 2021 +0200
@@ -51,24 +51,47 @@
}
};
+ class Event {
+ public:
+
+ enum class Type {
+ KEY,
+ BUTTON,
+ MOTION,
+ UNKNOWN
+ };
+
+ enum class State {
+ PRESSED,
+ RELEASED,
+ UNKNOWN
+ };
+
+ Type type = Type::UNKNOWN;
+ State state = State::UNKNOWN;
+ int key = -1;
+ int button = -1;
+ unsigned long screen = 0;
+ unsigned long delay = 1;
+ int x = -1;
+ int y = -1;
+ } currentEvent;
+
Display display;
- std::ostream& output; // TODO: remove
Configuration& configuration;
- const char QUOTE = '"'; // TODO: remove
std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: probably not needed
- std::vector<relpipe::reader::handlers::AttributeMetadata> firstAttributes;
- relpipe::common::type::Integer valueCount = 0;
+ std::vector<relpipe::reader::handlers::AttributeMetadata> attributes;
+ relpipe::common::type::Integer attributeIndex = 0;
public:
- X11Handler(std::ostream& output, Configuration& configuration) : output(output), configuration(configuration) {
+ X11Handler(Configuration& configuration) : configuration(configuration) {
display.display = XOpenDisplay(nullptr);
}
void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
if (display.display) {
- if (firstAttributes.empty()) {
- firstAttributes = attributes;
- if (configuration.writeHeader) for (auto attr : attributes) attribute(attr.getAttributeName());
+ if (this->attributes.empty()) {
+ this->attributes = attributes;
} else {
throw std::logic_error("Only a single relation can be converted to the X11 format.");
}
@@ -79,29 +102,53 @@
}
void attribute(const relpipe::common::type::StringX& value) override {
- valueCount++;
-
- if (value.size() > 0) {
- output << QUOTE;
- for (auto ch : convertor.to_bytes(value)) {
- if (ch == QUOTE) output << QUOTE << QUOTE;
- else output << ch;
- }
- output << QUOTE;
+ if (attributes[attributeIndex].getAttributeName() == L"device") {
+ // TODO: maybe add some filtering based on device ID
+ } else if (attributes[attributeIndex].getAttributeName() == L"type") {
+ if (value == L"key") currentEvent.type = Event::Type::KEY;
+ else if (value == L"button") currentEvent.type = Event::Type::BUTTON;
+ else if (value == L"motion") currentEvent.type = Event::Type::MOTION;
+ else currentEvent.type == Event::Type::UNKNOWN; // TODO: throw exception or print warning?
+ } else if (attributes[attributeIndex].getAttributeName() == L"state") {
+ if (value == L"pressed") currentEvent.state = Event::State::PRESSED;
+ else if (value == L"released") currentEvent.state = Event::State::RELEASED;
+ else currentEvent.state == Event::State::UNKNOWN; // TODO: throw exception or print warning?
+ } else if (attributes[attributeIndex].getAttributeName() == L"button") {
+ currentEvent.button = stol(value);
+ } else if (attributes[attributeIndex].getAttributeName() == L"key") {
+ currentEvent.key = stol(value);
+ } else if (attributes[attributeIndex].getAttributeName() == L"delay") {
+ currentEvent.delay = stoul(value);
+ } else if (attributes[attributeIndex].getAttributeName() == L"screen") {
+ currentEvent.screen = stol(value);
+ } else if (attributes[attributeIndex].getAttributeName() == L"x") {
+ currentEvent.x = stol(value);
+ } else if (attributes[attributeIndex].getAttributeName() == L"y") {
+ currentEvent.y = stol(value);
+ } else {
+ // ignore other attributes
}
- if (valueCount % firstAttributes.size()) {
- output << ",";
- } else {
- output << "\r\n";
- valueCount = 0;
- // XTestFakeKeyEvent(display.display, 38, true, 0);
- // XTestFakeKeyEvent(display.display, 38, false, 0);
+ attributeIndex++;
+
+ if (attributeIndex % attributes.size() == 0) {
+ if (currentEvent.type == Event::Type::KEY) {
+ XTestFakeKeyEvent(display.display, currentEvent.key, currentEvent.state == Event::State::PRESSED, 1);
+ } else if (currentEvent.type == Event::Type::BUTTON) {
+ XTestFakeButtonEvent(display.display, currentEvent.button, currentEvent.state == Event::State::PRESSED, currentEvent.delay);
+ } else if (currentEvent.type == Event::Type::MOTION) {
+ XTestFakeMotionEvent(display.display, currentEvent.screen, currentEvent.x, currentEvent.y, currentEvent.delay);
+ } else {
+ std::wcerr << L"Unsupported event" << std::endl;
+ }
+
+ attributeIndex = 0;
+ currentEvent = Event();
}
}
void endOfPipe() {
- output.flush();
+ // XTestDiscard(display.display); // TODO: wait before discard?
}
};
--- a/src/relpipe-out-x11.cpp Sun Mar 28 19:09:44 2021 +0200
+++ b/src/relpipe-out-x11.cpp Sun Mar 28 21:02:02 2021 +0200
@@ -36,14 +36,14 @@
int main(int argc, char**argv) {
CLI cli(argc, argv);
CLI::untieStdIO();
-
+
int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR;
try {
CLIParser cliParser;
Configuration configuration = cliParser.parse(cli.arguments());
std::shared_ptr<RelationalReader> reader(Factory::create(std::cin));
- X11Handler handler(std::cout, configuration);
+ X11Handler handler(configuration);
reader->addHandler(&handler);
reader->process();