src/X11Handler.h
branchv_0
changeset 3 2c4e533e9e33
parent 2 6851c08c6260
child 4 e5baa07d6e60
equal deleted inserted replaced
2:6851c08c6260 3:2c4e533e9e33
    49 		virtual ~Display() {
    49 		virtual ~Display() {
    50 			if (display) XCloseDisplay(display);
    50 			if (display) XCloseDisplay(display);
    51 		}
    51 		}
    52 	};
    52 	};
    53 
    53 
       
    54 	class Event {
       
    55 	public:
       
    56 
       
    57 		enum class Type {
       
    58 			KEY,
       
    59 			BUTTON,
       
    60 			MOTION,
       
    61 			UNKNOWN
       
    62 		};
       
    63 
       
    64 		enum class State {
       
    65 			PRESSED,
       
    66 			RELEASED,
       
    67 			UNKNOWN
       
    68 		};
       
    69 
       
    70 		Type type = Type::UNKNOWN;
       
    71 		State state = State::UNKNOWN;
       
    72 		int key = -1;
       
    73 		int button = -1;
       
    74 		unsigned long screen = 0;
       
    75 		unsigned long delay = 1;
       
    76 		int x = -1;
       
    77 		int y = -1;
       
    78 	} currentEvent;
       
    79 
    54 	Display display;
    80 	Display display;
    55 	std::ostream& output; // TODO: remove
       
    56 	Configuration& configuration;
    81 	Configuration& configuration;
    57 	const char QUOTE = '"'; // TODO: remove
       
    58 	std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: probably not needed
    82 	std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: probably not needed
    59 	std::vector<relpipe::reader::handlers::AttributeMetadata> firstAttributes;
    83 	std::vector<relpipe::reader::handlers::AttributeMetadata> attributes;
    60 	relpipe::common::type::Integer valueCount = 0;
    84 	relpipe::common::type::Integer attributeIndex = 0;
    61 public:
    85 public:
    62 
    86 
    63 	X11Handler(std::ostream& output, Configuration& configuration) : output(output), configuration(configuration) {
    87 	X11Handler(Configuration& configuration) : configuration(configuration) {
    64 		display.display = XOpenDisplay(nullptr);
    88 		display.display = XOpenDisplay(nullptr);
    65 	}
    89 	}
    66 
    90 
    67 	void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
    91 	void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
    68 		if (display.display) {
    92 		if (display.display) {
    69 			if (firstAttributes.empty()) {
    93 			if (this->attributes.empty()) {
    70 				firstAttributes = attributes;
    94 				this->attributes = attributes;
    71 				if (configuration.writeHeader) for (auto attr : attributes) attribute(attr.getAttributeName());
       
    72 			} else {
    95 			} else {
    73 				throw std::logic_error("Only a single relation can be converted to the X11 format.");
    96 				throw std::logic_error("Only a single relation can be converted to the X11 format.");
    74 			}
    97 			}
    75 		} else {
    98 		} else {
    76 			throw std::invalid_argument("Unable to open display. Please check the $DISPLAY variable.");
    99 			throw std::invalid_argument("Unable to open display. Please check the $DISPLAY variable.");
    77 		}
   100 		}
    78 
   101 
    79 	}
   102 	}
    80 
   103 
    81 	void attribute(const relpipe::common::type::StringX& value) override {
   104 	void attribute(const relpipe::common::type::StringX& value) override {
    82 		valueCount++;
   105 		if (attributes[attributeIndex].getAttributeName() == L"device") {
    83 
   106 			// TODO: maybe add some filtering based on device ID
    84 		if (value.size() > 0) {
   107 		} else if (attributes[attributeIndex].getAttributeName() == L"type") {
    85 			output << QUOTE;
   108 			if (value == L"key") currentEvent.type = Event::Type::KEY;
    86 			for (auto ch : convertor.to_bytes(value)) {
   109 			else if (value == L"button") currentEvent.type = Event::Type::BUTTON;
    87 				if (ch == QUOTE) output << QUOTE << QUOTE;
   110 			else if (value == L"motion") currentEvent.type = Event::Type::MOTION;
    88 				else output << ch;
   111 			else currentEvent.type == Event::Type::UNKNOWN; // TODO: throw exception or print warning?
    89 			}
   112 		} else if (attributes[attributeIndex].getAttributeName() == L"state") {
    90 			output << QUOTE;
   113 			if (value == L"pressed") currentEvent.state = Event::State::PRESSED;
       
   114 			else if (value == L"released") currentEvent.state = Event::State::RELEASED;
       
   115 			else currentEvent.state == Event::State::UNKNOWN; // TODO: throw exception or print warning?
       
   116 		} else if (attributes[attributeIndex].getAttributeName() == L"button") {
       
   117 			currentEvent.button = stol(value);
       
   118 		} else if (attributes[attributeIndex].getAttributeName() == L"key") {
       
   119 			currentEvent.key = stol(value);
       
   120 		} else if (attributes[attributeIndex].getAttributeName() == L"delay") {
       
   121 			currentEvent.delay = stoul(value);
       
   122 		} else if (attributes[attributeIndex].getAttributeName() == L"screen") {
       
   123 			currentEvent.screen = stol(value);
       
   124 		} else if (attributes[attributeIndex].getAttributeName() == L"x") {
       
   125 			currentEvent.x = stol(value);
       
   126 		} else if (attributes[attributeIndex].getAttributeName() == L"y") {
       
   127 			currentEvent.y = stol(value);
       
   128 		} else {
       
   129 			// ignore other attributes
    91 		}
   130 		}
    92 
   131 
    93 		if (valueCount % firstAttributes.size()) {
   132 		attributeIndex++;
    94 			output << ",";
   133 
    95 		} else {
   134 		if (attributeIndex % attributes.size() == 0) {
    96 			output << "\r\n";
   135 			if (currentEvent.type == Event::Type::KEY) {
    97 			valueCount = 0;
   136 				XTestFakeKeyEvent(display.display, currentEvent.key, currentEvent.state == Event::State::PRESSED, 1);
    98 			// XTestFakeKeyEvent(display.display, 38, true, 0);
   137 			} else if (currentEvent.type == Event::Type::BUTTON) {
    99 			// XTestFakeKeyEvent(display.display, 38, false, 0);
   138 				XTestFakeButtonEvent(display.display, currentEvent.button, currentEvent.state == Event::State::PRESSED, currentEvent.delay);
       
   139 			} else if (currentEvent.type == Event::Type::MOTION) {
       
   140 				XTestFakeMotionEvent(display.display, currentEvent.screen, currentEvent.x, currentEvent.y, currentEvent.delay);
       
   141 			} else {
       
   142 				std::wcerr << L"Unsupported event" << std::endl;
       
   143 			}
       
   144 
       
   145 			attributeIndex = 0;
       
   146 			currentEvent = Event();
   100 		}
   147 		}
   101 	}
   148 	}
   102 
   149 
   103 	void endOfPipe() {
   150 	void endOfPipe() {
   104 		output.flush();
   151 		// XTestDiscard(display.display); // TODO: wait before discard?
   105 	}
   152 	}
   106 
   153 
   107 };
   154 };
   108 
   155 
   109 }
   156 }