17 #pragma once |
17 #pragma once |
18 |
18 |
19 #include <codecvt> |
19 #include <codecvt> |
20 #include <memory> |
20 #include <memory> |
21 #include <iostream> |
21 #include <iostream> |
|
22 #include <stdexcept> |
|
23 |
|
24 #include <X11/extensions/XInput.h> |
22 |
25 |
23 #include "Configuration.h" |
26 #include "Configuration.h" |
24 |
27 |
25 namespace relpipe { |
28 namespace relpipe { |
26 namespace in { |
29 namespace in { |
27 namespace x11 { |
30 namespace x11 { |
28 |
31 |
29 class X11Command { |
32 class X11Command { |
30 private: |
33 private: |
31 |
34 |
|
35 class Display { |
|
36 public: |
|
37 ::Display* display = nullptr; |
|
38 // TODO: more OOP |
|
39 |
|
40 virtual ~Display() { |
|
41 if (display) XCloseDisplay(display); |
|
42 } |
|
43 |
|
44 }; |
|
45 |
|
46 class DeviceList { |
|
47 public: |
|
48 XDeviceInfo* items = nullptr; |
|
49 int count = 0; |
|
50 // TODO: more OOP |
|
51 |
|
52 virtual ~DeviceList() { |
|
53 if (items) XFreeDeviceList(items); |
|
54 } |
|
55 |
|
56 }; |
|
57 |
|
58 |
32 std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings and use platform encoding as default |
59 std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings and use platform encoding as default |
33 |
60 |
34 void processRelation(RelationConfiguration& configuration, std::shared_ptr<writer::RelationalWriter> writer) { |
61 void listInputDevices(Display& display, Configuration& configuration, std::shared_ptr<writer::RelationalWriter> writer) { |
35 // Write header / metadata: |
62 writer->startRelation(L"x11_input_device",{ |
36 std::vector<relpipe::writer::AttributeMetadata> attributesMetadata; |
63 {L"id", relpipe::writer::TypeId::INTEGER}, |
37 for (AttributeRecipe ar : configuration.attributes) attributesMetadata.push_back({ar.name, ar.type}); |
64 {L"name", relpipe::writer::TypeId::STRING}, |
38 writer->startRelation(configuration.relation, attributesMetadata, configuration.writeHeader); |
65 // TODO: device type name and ID |
|
66 }, true); |
39 |
67 |
40 // Write records from CLI: |
68 DeviceList devices; |
41 for (auto value : configuration.values) writer->writeAttribute(value); |
69 devices.items = XListInputDevices(display.display, &devices.count); |
42 |
70 |
43 // Write records from STDIN: |
71 for (int i = 0; i < devices.count; i++) { |
44 if (configuration.valueStream) { |
72 relpipe::common::type::Integer id = (devices.items + i)->id; |
45 std::stringstream rawValue; |
73 relpipe::common::type::StringX name = convertor.from_bytes((devices.items + i)->name); |
46 while (true) { |
74 |
47 char ch = 0; |
75 writer->writeAttribute(&id, typeid (id)); |
48 configuration.valueStream->get(ch); |
76 writer->writeAttribute(&name, typeid (name)); |
49 if (ch == 0 && configuration.valueStream->good()) { |
77 |
50 writer->writeAttribute(convertor.from_bytes(rawValue.str())); |
|
51 rawValue.str(""); |
|
52 rawValue.clear(); |
|
53 } else if (configuration.valueStream->good()) { |
|
54 rawValue << ch; |
|
55 } else if (configuration.valueStream->eof()) { |
|
56 return; |
|
57 } else { |
|
58 throw relpipe::cli::RelpipeCLIException(L"Error while reading values from the input stream.", relpipe::cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: better exception |
|
59 } |
|
60 } |
|
61 } |
78 } |
|
79 } |
62 |
80 |
|
81 void listInputEvents(Display& display, Configuration& configuration, std::shared_ptr<writer::RelationalWriter> writer) { |
|
82 writer->startRelation(L"x11_input_event",{ |
|
83 {L"device_id", relpipe::writer::TypeId::INTEGER}, |
|
84 }, true); |
|
85 |
|
86 // TODO: list events |
63 } |
87 } |
64 |
88 |
65 public: |
89 public: |
66 |
90 |
67 void process(Configuration& configuration, std::shared_ptr<writer::RelationalWriter> writer) { |
91 void process(Configuration& configuration, std::shared_ptr<writer::RelationalWriter> writer) { |
68 for (RelationConfiguration& relationConfiguration : configuration.relationConfigurations) processRelation(relationConfiguration, writer); |
92 Display display; |
|
93 display.display = XOpenDisplay(nullptr); |
|
94 |
|
95 if (display.display) { |
|
96 if (configuration.listInputDevices) listInputDevices(display, configuration, writer); |
|
97 if (configuration.listInputEvents) listInputEvents(display, configuration, writer); |
|
98 } else { |
|
99 throw std::invalid_argument("Unable to open display. Please check the $DISPLAY variable."); |
|
100 } |
69 } |
101 } |
70 }; |
102 }; |
71 |
103 |
72 } |
104 } |
73 } |
105 } |