first working version v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 28 Mar 2021 21:02:02 +0200
branchv_0
changeset 3 2c4e533e9e33
parent 2 6851c08c6260
child 4 e5baa07d6e60
first working version
src/X11Handler.h
src/relpipe-out-x11.cpp
--- 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();