qi3pc 0.4.1
Qt based library to communicate with i3wm via its IPC API
Loading...
Searching...
No Matches
qi3pc.cpp
1#include <QDebug>
2
3#include "qi3pc.h"
4
5Q_LOGGING_CATEGORY(Qi3pcLogger, "qi3pc", QtMsgType::QtDebugMsg)
6
7qi3pc::qi3pc(QObject* parent)
8 : qi3pc(FindSocketPath(), parent)
9{}
10
11qi3pc::qi3pc(const QString& serverPath, QObject* parent)
12 : QObject(parent)
13{
14 m_socketPath = serverPath;
15
16 m_barConfigs = std::make_pair(QJsonObject(), QDateTime::currentMSecsSinceEpoch());
17 if (m_socketPath.isEmpty()) {
18 throw std::invalid_argument("The provided server path must not be empty.");
19 }
20
21 QObject::connect(
22 &m_eventSocket, &QLocalSocket::readyRead, this, &qi3pc::processEvent);
23 QObject::connect(
24 &m_messageSocket, &QLocalSocket::readyRead, this, &qi3pc::processReply);
25}
26
28{
29 m_eventSocket.close();
30 m_messageSocket.close();
31
32 m_eventSocket.abort();
33 m_messageSocket.abort();
34}
35
36void
38{
40 if (!m) {
41 return;
42 }
43
44 auto [data, type] = m.value();
45
46 if (type & (1u << 31)) {
47 switch (static_cast<IpcEvent>(type)) {
48 case IpcEvent::Workspace:
50 break;
51 case IpcEvent::Output:
53 break;
54 case IpcEvent::Mode:
55 processModeEvent(data);
56 break;
57 case IpcEvent::Window:
59 break;
60 case IpcEvent::BarUpdate:
62 break;
63 case IpcEvent::Binding:
65 break;
66 case IpcEvent::Shutdown:
68 break;
69 case IpcEvent::Tick:
70 processTickEvent(data);
71 break;
72 default:
73 std::string log = "Received event of unsupported type IpcType::%u";
74 qCWarning(Qi3pcLogger, log.c_str(), type, IpcType::Subscribe);
75 break;
76 }
77 } else {
78 switch (static_cast<IpcType>(type)) {
79 case IpcType::Subscribe:
80 emit subscribed(data["success"].toBool());
81 break;
82 case IpcType::Tick:
83 processTickReply(data);
84 break;
85 default:
86 std::string log = "Received message IpcType::%u while expecting IpcEvent, IpcType::Subscribe (IpcType::%u),"
87 "or IpcType::Tick (IpcType::%u)";
88 qCWarning(Qi3pcLogger, log.c_str(), type, IpcType::Subscribe, IpcType::Tick);
89 break;
90 }
91 }
92}
93
94void
96{
98 if (!m) {
99 return;
100 }
101
102 auto [data, type] = m.value();
103
104 std::string log;
105 switch (static_cast<IpcType>(type)) {
106 case IpcType::Command:
108 break;
109 case IpcType::Workspaces:
111 break;
112 case IpcType::Subscribe:
113 log = "Received reply of type IpcType::Subscribe (IpcType::%u): unexpected.";
114 qCWarning(Qi3pcLogger, log.c_str(), IpcType::Subscribe);
115 break;
116 case IpcType::Outputs:
117 processOutputReply(data);
118 break;
119 case IpcType::Tree:
120 processTreeReply(data);
121 break;
122 case IpcType::Marks:
123 processMarkReply(data);
124 break;
125 case IpcType::BarConfig:
127 break;
128 case IpcType::Version:
130 break;
131 case IpcType::BindingModes:
133 break;
134 case IpcType::Config:
135 processConfigReply(data);
136 break;
137 case IpcType::Tick:
138 log = "Received reply of type IpcType::Tick (IpcType::%u): unexpected.";
139 qCWarning(Qi3pcLogger, log.c_str(), IpcType::Tick);
140 break;
141 case IpcType::Sync:
142 processSyncReply(data);
143 break;
144 case IpcType::BindingState:
146 break;
147 default:
148 log = "Received reply of unsupported type IpcType::%u.";
149 qCWarning(Qi3pcLogger, log.c_str(), type);
150 break;
151 }
152}
153
154void
155qi3pc::processCommandReply(const QJsonDocument& doc)
156{
157 auto results = doc.array();
158 if (results.empty()) {
159 qCWarning(Qi3pcLogger) << "Received empty command reply:" << doc.toJson();
160 emit commandRan({{false, ParseError{}}});
161 }
162
163 CommandResults result;
164 for (auto jsonObject: std::as_const(results)) {
165 auto object = jsonObject.toObject();
166 if (!object.contains("success")) {
167 qCWarning(Qi3pcLogger) << "Command reply does not contain success key. Skipping:" << object;
168 continue;
169 }
170
171 if (auto success = object["success"].toBool(); success) {
172 result.push_back({true, {}});
173 } else {
174 result.push_back({false, ParseError::FromJSON(object)});
175 }
176 }
177
178 emit commandRan(result);
179}
180
181void
182qi3pc::processWorkspaceReply(const QJsonDocument& doc)
183{
184 m_workspaces = std::make_pair(doc.array(), QDateTime::currentMSecsSinceEpoch());
186}
187
188void
189qi3pc::processOutputReply(const QJsonDocument& doc)
190{
191 m_outputs = std::make_pair(doc.array(), QDateTime::currentMSecsSinceEpoch());
193}
194
195void
196qi3pc::processTreeReply(const QJsonDocument& doc)
197{
198 m_tree = std::make_pair(doc.object(), QDateTime::currentMSecsSinceEpoch());
199 emit treeUpdated(m_tree);
200}
201
202void
203qi3pc::processMarkReply(const QJsonDocument& doc)
204{
205 m_marks = std::make_pair(doc.array(), QDateTime::currentMSecsSinceEpoch());
206 emit marksUpdated(m_marks);
207}
208
209void
210qi3pc::processBarConfigReply(const QJsonDocument& doc)
211{
212 if (const auto& ids = doc.array(); !ids.isEmpty()) {
213 for (auto ref : ids) {
214 if (auto id = ref.toString();
215 m_barConfigs->first[id] == QJsonValue::Null) {
216 emit newBarConfig(id);
217 }
218 }
219 } else {
220 auto id = doc["id"].toString();
221 auto config = doc.object();
222 m_barConfigs->first[id] = config;
223 m_barConfigs->second = QDateTime::currentMSecsSinceEpoch();
225 }
226}
227
228void
229qi3pc::processVersionReply(const QJsonDocument& doc)
230{
231 m_version = std::make_pair(doc.object(), QDateTime::currentMSecsSinceEpoch());
233}
234
235void
236qi3pc::processBindingModesReply(const QJsonDocument& doc)
237{
238 m_bindingModes = std::make_pair(doc.array(), QDateTime::currentMSecsSinceEpoch());
240}
241
242void
243qi3pc::processConfigReply(const QJsonDocument& doc)
244{
245 m_config = std::make_pair(doc.object(), QDateTime::currentMSecsSinceEpoch());
247}
248
249void
250qi3pc::processTickReply(const QJsonDocument& doc)
251{
252 emit tickSent(doc["success"].toBool());
253}
254
255void
256qi3pc::processSyncReply(const QJsonDocument& doc)
257{
258 emit synced(doc["success"].toBool());
259}
260
261void
262qi3pc::processBindingStateReply(const QJsonDocument& doc)
263{
264 m_bindingState = std::make_pair(doc["name"].toString(), QDateTime::currentMSecsSinceEpoch());
266}
267
268void
269qi3pc::processWorkspaceEvent(const QJsonDocument& doc)
270{
271 auto change = WorkspaceChangeFromString(doc["change"].toString());
272
273 if (change == WorkspaceChange::Unknown) {
274 qCWarning(Qi3pcLogger) << "Received workspace event with unknown change string" << doc["change"].toString();
275 return;
276 }
277
278 auto old = doc["old"].toObject();
279 auto current = doc["current"].toObject();
280 emit workspaceEvent(change, current, old);
281}
282
283void
284qi3pc::processOutputEvent(const QJsonDocument& data)
285{
286 auto change = OutputChangeFromString(data["change"].toString());
287
288 if (change == OutputChange::Unknown) {
289 qCWarning(Qi3pcLogger) << "Received output event with unknown change string" << data["change"].toString();
290 return;
291 }
292
293 emit outputEvent(change);
294}
295
296void
297qi3pc::processModeEvent(const QJsonDocument& doc)
298{
299 emit modeEvent(doc["change"].toString(), doc["pango_markup"].toBool());
300}
301
302void
303qi3pc::processWindowEvent(const QJsonDocument& doc)
304{
305 auto change = WindowChangeFromString(doc["change"].toString());
306
307 if (change == WindowChange::Unknown) {
308 qCWarning(Qi3pcLogger) << "Received window event with unknown change string" << doc["change"].toString();
309 return;
310 }
311
312 emit windowEvent(change, doc["container"].toObject());
313}
314
315void
316qi3pc::processBarUpdateEvent(const QJsonDocument& doc)
317{
318 emit barUpdateEvent(doc.object());
319}
320
321void
322qi3pc::processBindingEvent(const QJsonDocument& doc)
323{
324 auto change = BindingChangeFromString(doc["change"].toString());
325
326 if (change == BindingChange::Unknown) {
327 qCWarning(Qi3pcLogger) << "Received binding event with unknown change string" << doc["change"].toString();
328 return;
329 }
330
331 emit bindingEvent(change, doc["binding"].toObject(), doc["mode"].toString());
332}
333
334void
335qi3pc::processShutdownEvent(const QJsonDocument& doc)
336{
337 auto change = ShutdownChangeFromString(doc["change"].toString());
338
339 if (change == ShutdownChange::Unknown) {
340 qCWarning(Qi3pcLogger) << "Received shutdown event with unknown change string" << doc["change"].toString();
341 return;
342 }
343
344 emit shutdownEvent(change);
345}
346
347void
348qi3pc::processTickEvent(const QJsonDocument& doc)
349{
350 if(auto first = doc["first"].toBool(); !first) {
351 emit tickEvent(doc["payload"].toString());
352 }
353}
354
357{
358 if (s == "focus") {
360 } else if (s == "init") {
362 } else if (s == "empty") {
364 } else if (s == "urgent") {
366 } else if (s == "reload") {
368 } else if (s == "rename") {
370 } else if (s == "restored") {
372 } else if (s == "move") {
374 } else {
376 }
377}
378
381{
382 if (s == "new") {
383 return WindowChange::New;
384 } else if (s == "close") {
385 return WindowChange::Close;
386 } else if (s == "focus") {
387 return WindowChange::Focus;
388 } else if (s == "title") {
389 return WindowChange::Title;
390 } else if (s == "fullscreen_mode") {
392 } else if (s == "move") {
393 return WindowChange::Move;
394 } else if (s == "floating") {
396 } else if (s == "urgent") {
398 } else if (s == "mark") {
399 return WindowChange::Mark;
400 } else {
402 }
403}
404
407{
408 if (s == "restart") {
410 } else if (s == "exit") {
412 } else {
414 }
415}
416
419{
420 if (s == "unspecified") {
422 } else {
424 }
425}
426
429{
430 if (s == "run") {
431 return BindingChange::Run;
432 } else {
434 }
435}
436
438qi3pc::processMessage(QLocalSocket& socket)
439{
440 char c[IpcMagicLength];
441 if (auto read_size = socket.read(c, IpcMagicLength);
442 read_size != IpcMagicLength) {
443 qCWarning(Qi3pcLogger) << "Insufficient data read for IPC magic string. Seeked"
444 << IpcMagicLength <<"bytes. - Read" << read_size << "bytes.";
445 return {};
446 }
447
448 if (auto s = std::string(c, IpcMagicLength); s != IpcMagicString) {
449 qCWarning(Qi3pcLogger) << "Unexpected magic string in message. Expected"
450 << qi3pc::IpcMagicString << ". - Found" << s << ".";
451 return {};
452 }
453
454 quint32 size;
455 if (auto read_size = socket.read(reinterpret_cast<char*>(&size), sizeof size);
456 read_size != sizeof size) {
457 qCWarning(Qi3pcLogger) << "Insufficient data read for message size. Seeked"
458 << sizeof size <<"bytes. - Read" << read_size << "bytes.";
459 return {};
460 }
461
462 quint32 type;
463 if (auto read_size = socket.read(reinterpret_cast<char*>(&type), sizeof type);
464 read_size != sizeof type) {
465 qCWarning(Qi3pcLogger) << "Insufficient data read for message type. Seeked"
466 << sizeof type <<"bytes. - Read" << read_size << "bytes.";
467 return {};
468 }
469
470 QJsonParseError parseError;
471 auto payload = socket.read(size);
472
473 if (socket.bytesAvailable() > 0) {
474 emit socket.readyRead();
475 }
476
477 QJsonDocument data = QJsonDocument::fromJson(payload, &parseError);
478 if (parseError.error != QJsonParseError::NoError) {
479 qCWarning(Qi3pcLogger) << "Parsing message body failed - JSON parse error:"
480 << parseError.errorString() << "in:" << payload;
481 return {};
482 }
483
484 return std::make_pair(data, type);
485}
486
487QString
489{
490 if (auto path = QProcessEnvironment::systemEnvironment().value("I3SOCK");
491 !path.isEmpty()) {
492 return path;
493 }
494
495 // TODO: try to get socket path from root window property
497}
498
499QString
501{
502 QProcess process;
503 process.start("i3", QStringList("--get-socketpath"));
504 process.waitForReadyRead();
505 auto path = QString(process.readAllStandardOutput()).trimmed();
506 process.kill();
507 process.waitForFinished();
508 return path;
509}
510
511QString
513{
514 return m_socketPath;
515}
516
517const
520{
521 return m_workspaces;
522}
523
524const
527{
528 return m_tree;
529}
530
531const
534{
535 return m_outputs;
536}
537
538const
541{
542 return m_marks;
543}
544
545const
548{
549 return m_barConfigs;
550}
551
552const
555{
556 return m_version;
557}
558
559const
562{
563 return m_bindingModes;
564}
565
566const
569{
570 return m_config;
571}
572
573const
576{
577 return m_bindingState;
578}
579
580bool
582{
583
584 m_messageSocket.connectToServer(m_socketPath);
585 m_eventSocket.connectToServer(m_socketPath);
586
587 if (m_messageSocket.state() != QLocalSocket::ConnectedState)
588 {
589 m_messageSocket.waitForConnected();
590 }
591
592 if (m_eventSocket.state() != QLocalSocket::ConnectedState)
593 {
594 m_eventSocket.waitForConnected();
595 }
596
597 return m_messageSocket.state() == QLocalSocket::ConnectedState &&
598 m_eventSocket.state() == QLocalSocket::ConnectedState;
599}
600
601bool
603{
604 m_messageSocket.disconnectFromServer();
605 m_eventSocket.disconnectFromServer();
606
607 if (m_messageSocket.state() != QLocalSocket::UnconnectedState)
608 {
609 m_messageSocket.waitForDisconnected();
610 }
611
612 if (m_eventSocket.state() != QLocalSocket::UnconnectedState)
613 {
614 m_eventSocket.waitForDisconnected();
615 }
616
617 return m_messageSocket.state() == QLocalSocket::UnconnectedState &&
618 m_eventSocket.state() == QLocalSocket::UnconnectedState;
619}
620
621bool
623{
624 if (m_messageSocket.state() == QLocalSocket::ConnectingState ||
625 m_eventSocket.state() == QLocalSocket::ConnectingState) {
626 m_messageSocket.waitForConnected();
627 m_eventSocket.waitForConnected();
628 }
629
630 return m_messageSocket.state() == QLocalSocket::ConnectedState &&
631 m_eventSocket.state() == QLocalSocket::ConnectedState;
632}
633
634void
635qi3pc::sendTick(const QByteArray& payload)
636{
637 WritePayload(m_eventSocket, payload, IpcType::Tick);
638}
639
640void
641qi3pc::subscribe(const QStringList& events)
642{
643 if (events.isEmpty()) {
644 qCWarning(Qi3pcLogger) << "Requested to subscibe to empty event list. Nothing to do.";
645 return;
646 }
647
650 QJsonDocument(QJsonArray::fromStringList(events)).toJson(),
651 IpcType::Subscribe);
652 m_eventSocket.flush();
653}
654
655void
656qi3pc::WritePayload(QLocalSocket& socket, const QByteArray& payload, IpcType type)
657{
658 QByteArray message;
659 QDataStream stream(&message, QIODevice::WriteOnly);
660
661 stream.writeRawData(qi3pc::IpcMagicString.data(), qi3pc::IpcMagicLength);
662
663 qint32 size = payload.size();
664 stream.writeRawData(reinterpret_cast<const char*>(&size), sizeof size);
665 stream.writeRawData(reinterpret_cast<const char*>(&type), sizeof type);
666
667 if (size > 0) {
668 stream.writeRawData(payload.constData(), size);
669 }
670
671 socket.write(message);
672}
673
674void
679
680void
685
686void
691
692void
697
698void
703
704void
709
710void
715
716void
721
722void
723qi3pc::fetchBarConfig(const QString& id)
724{
725 QByteArray payload;
726 payload.append(id.toStdString().c_str());
728}
729
730void
735
737qi3pc::ParseError::FromJSON(const QJsonObject& json)
738{
739 if(!json.contains("parse_error")) {
740 return {};
741 }
742 auto ret = ParseError {};
743 for (const auto& [name, member]: ParseError::_MEMBERS) {
744 if (json.contains(name)) {
745 ret.*member = json[name].toString();
746 }
747 }
748
749 return ret;
750}
751
752bool
754 return error == other.error &&
755 input == other.input &&
757}
758
759QString
761{
762 auto str = QString("{");
763 for (const auto& [name, member]: ParseError::_MEMBERS) {
764 str += QString(name) + ":'" + this->*member + "',";
765 }
766
767 return str + "}";
768}
ShutdownChange
Types of change a shutdown event can have.
Definition qi3pc.h:137
void configUpdated(const qi3pc::DataObject &config)
Signal emitted when the (cached) config have been updated.
DataArray m_workspaces
Definition qi3pc.h:706
void treeUpdated(const qi3pc::DataObject &tree)
Signal emitted when the layout tree cache have been updated.
WindowChange
Types of change a window event can have.
Definition qi3pc.h:117
void processOutputEvent(const QJsonDocument &doc)
Handle data received from an output event.
Definition qi3pc.cpp:284
void barConfigUpdated(const QJsonObject &config)
Signal emitted when a specific bar's (cached) config have been updated. At this point the configurati...
void fetchConfig()
Signal to emit to trigger an update of the (cached) config.
Definition qi3pc.cpp:711
void processBindingEvent(const QJsonDocument &doc)
Handle data received from a binding event.
Definition qi3pc.cpp:322
void sendMessage(const QByteArray &payload=QByteArray())
Send a message with the specified type and payload to i3.
Definition qi3pc.h:345
void fetchBarConfigs()
Signal to emit to update the list of bar configurations.
Definition qi3pc.cpp:717
DataObject m_version
Definition qi3pc.h:710
void fetchBindingModes()
Signal to emit to trigger an update of the (cached) list of modes.
Definition qi3pc.cpp:705
std::vector< std::pair< bool, Error > > CommandResults
Pairs of qi3pc::Error and boolean.
Definition qi3pc.h:239
std::optional< std::pair< QJsonDocument, quint32 > > Message
Optional pair of a JSON document with a qi3pc::IpcType received with a message or an event before it ...
Definition qi3pc.h:247
void barUpdateEvent(const QJsonObject &doc)
Signal emitted when a bar's configuration have been updated.
QLocalSocket m_messageSocket
Definition qi3pc.h:703
void workspacesUpdated(const qi3pc::DataArray &workspaces)
Signal emitted when the (cached) list of workspaces have been updated.
void synced(bool success)
Signal emitted when a sync message have been replied to by i3.
std::optional< ParseError > Error
Optional qi3pc::ParseError. The optional is empty when the error could not be parsed.
Definition qi3pc.h:231
void tickSent(bool success)
Signal emitted when a tick have been processed by i3.
void processBindingModesReply(const QJsonDocument &doc)
Handle data received in a binding mode reply.
Definition qi3pc.cpp:236
QString socketPath() const
Get the socket path selected at construction.
Definition qi3pc.cpp:512
DataObject m_config
Definition qi3pc.h:713
const DataArray & marks() const
Get the (cached) list of set marks.
Definition qi3pc.cpp:540
void subscribed(bool success)
Signal emitted when a subscribe message have been replied to.
void processSyncReply(const QJsonDocument &doc)
Handle data received from a sync reply.
Definition qi3pc.cpp:256
DataString m_bindingState
Definition qi3pc.h:712
void fetchBarConfig(const QString &id)
Signal to emit to update the (cached) configuration of a certain bar.
Definition qi3pc.cpp:723
void processBarUpdateEvent(const QJsonDocument &doc)
Handle data received from a bar update event.
Definition qi3pc.cpp:316
void bindingStateUpdated(const qi3pc::DataString &state)
Signal emitted when the (cached) current binding state have been updated.
void outputEvent(qi3pc::OutputChange change)
Signal emitted when the output(s) change.
void processBarConfigReply(const QJsonDocument &doc)
Handle data received from a bar config reply.
Definition qi3pc.cpp:210
void fetchTree()
Signal to emit to trigger an update of the (cached) layout tree.
Definition qi3pc.cpp:681
void processReply()
Read data from the message socket.
Definition qi3pc.cpp:95
DataArray m_marks
Definition qi3pc.h:708
void fetchOutputs()
Signal to emit to trigger an update of the (cached) outputs.
Definition qi3pc.cpp:687
void versionUpdated(const qi3pc::DataObject &version)
Signal emitted when the (cached) i3 version have been updated.
void outputsUpdated(const qi3pc::DataArray &outputs)
Signal emitted when (cached) outputs have been updated.
bool connect()
Start listening to messages and events from the window manager.
Definition qi3pc.cpp:581
void modeEvent(QString change, bool pango)
Signal emitted when the binding mode changes.
static ShutdownChange ShutdownChangeFromString(const QString &s)
Convert a string into a shutdown change object.
Definition qi3pc.cpp:406
void processMarkReply(const QJsonDocument &doc)
Handle data received from a mark reply.
Definition qi3pc.cpp:203
static constexpr auto IpcMagicLength
Definition qi3pc.h:35
void fetchBindingState()
Request update of the (cached) binding state.
Definition qi3pc.cpp:731
void windowEvent(qi3pc::WindowChange change, const QJsonObject &container)
Signal emitted when a window changes.
static WorkspaceChange WorkspaceChangeFromString(const QString &s)
Convert a string into a workspace change object.
Definition qi3pc.cpp:356
QLocalSocket m_eventSocket
Definition qi3pc.h:702
static BindingChange BindingChangeFromString(const QString &s)
Convert a string into a binding change object.
Definition qi3pc.cpp:428
void processWindowEvent(const QJsonDocument &doc)
Handle data received from a window event.
Definition qi3pc.cpp:303
void subscribe(const QStringList &events)
Subscribe to a list of events.
Definition qi3pc.cpp:641
void fetchMarks()
Signal to emit to trigger an update of the (cached) list of marks.
Definition qi3pc.cpp:693
void processVersionReply(const QJsonDocument &doc)
Handle data received from a version reply.
Definition qi3pc.cpp:229
static WindowChange WindowChangeFromString(const QString &s)
Convert a string into a window change object.
Definition qi3pc.cpp:380
const DataArray & workspaces() const
Get the list of (cached) workspaces.
Definition qi3pc.cpp:519
void newBarConfig(const QString &id)
Signal emitted when a new bar config have been added to the cache.
void processWorkspaceReply(const QJsonDocument &doc)
Handle data received from a workspace reply.
Definition qi3pc.cpp:182
void fetchVersion()
Signal to emit to trigger a cache update for the i3wm version.
Definition qi3pc.cpp:699
bool disconnect()
Stop listening to messages and events from the window manager.
Definition qi3pc.cpp:602
static QString FindSocketPath()
Find the path to the i3 ipc local unix socket.
Definition qi3pc.cpp:488
void processConfigReply(const QJsonDocument &doc)
Handle data received from a config reply.
Definition qi3pc.cpp:243
const DataString & bindingState() const
Get the (cached) binding state.
Definition qi3pc.cpp:575
static void WritePayload(QLocalSocket &socket, const QByteArray &payload, IpcType type)
Send a message with the specified type and payload to i3 using the specified socket.
Definition qi3pc.cpp:656
void processTickReply(const QJsonDocument &doc)
Handle data received from a tick reply.
Definition qi3pc.cpp:250
void processTickEvent(const QJsonDocument &doc)
Handle data received from a tick event.
Definition qi3pc.cpp:348
void processBindingStateReply(const QJsonDocument &doc)
Handle data received from a binding state event reply.
Definition qi3pc.cpp:262
void sendTick(const QByteArray &payload=QByteArray())
Send a tick message with the spoecified payload.
Definition qi3pc.cpp:635
IpcType
Types of message/replies the API send/expect to/from i3wm.
Definition qi3pc.h:62
const DataArray & bindingModes() const
Get the (cached) list of binding modes.
Definition qi3pc.cpp:561
static constexpr auto IpcMagicString
Definition qi3pc.h:34
void processTreeReply(const QJsonDocument &doc)
Handle data received from a tree reply.
Definition qi3pc.cpp:196
void processShutdownEvent(const QJsonDocument &doc)
Handle data received from a shutdowm event.
Definition qi3pc.cpp:335
virtual ~qi3pc()
Simple destructor for the qi3pc class.
Definition qi3pc.cpp:27
DataObject m_barConfigs
Definition qi3pc.h:709
void tickEvent(const QString &payload)
Signal emitted when subscribing to tick events or when a tick message have been sent to the ipc conne...
BindingChange
Types of change a binding event can have.
Definition qi3pc.h:150
void processModeEvent(const QJsonDocument &doc)
Handle data received from a mode event.
Definition qi3pc.cpp:297
Message processMessage(QLocalSocket &socket)
Read one message using the socket parameter.
Definition qi3pc.cpp:438
void marksUpdated(const qi3pc::DataArray &marks)
Signal emitted when the (cached) list of marks have been updated.
void commandRan(CommandResults result)
Signal emitted when a command have been ran by i3.
void processEvent()
Read data from the event socket.
Definition qi3pc.cpp:37
OutputChange
Types of change an output event can have.
Definition qi3pc.h:105
std::optional< std::pair< QJsonObject, qint64 > > DataObject
Optional pair of a JSON object with its last update time.
Definition qi3pc.h:156
WorkspaceChange
Types of change a workspace event can have.
Definition qi3pc.h:86
void processCommandReply(const QJsonDocument &doc)
Handle data received from a run command reply.
Definition qi3pc.cpp:155
DataArray m_bindingModes
Definition qi3pc.h:711
qi3pc(QObject *parent=nullptr)
Construct a qi3pc object.
Definition qi3pc.cpp:7
void bindingEvent(qi3pc::BindingChange change, const QJsonObject &binding, const QString &mode)
Signal emitteed when a binding have been triggered to run a command.
const DataObject & tree() const
Get the (cached) i3 layout tree.
Definition qi3pc.cpp:526
void fetchWorkspaces()
Signal to emit to trigger an update of the list of workspace cache.
Definition qi3pc.cpp:675
void processOutputReply(const QJsonDocument &doc)
Handle data received from an output reply.
Definition qi3pc.cpp:189
DataArray m_outputs
Definition qi3pc.h:707
void shutdownEvent(qi3pc::ShutdownChange change)
Signal emitted when the ipc socket is about to shutdown.
const DataObject & config() const
Get the (cached) data read from the config file.
Definition qi3pc.cpp:568
void workspaceEvent(qi3pc::WorkspaceChange change, const QJsonObject &current, const QJsonObject &old)
Signal emitted with a workspace event's data preprocessed.
std::optional< std::pair< QString, qint64 > > DataString
Optional pair of a string with its last update time.
Definition qi3pc.h:162
static OutputChange OutputChangeFromString(const QString &s)
Convert a string into an output change object.
Definition qi3pc.cpp:418
static QString FindSocketPathFromI3Binary()
Find the path to the i3 ipc local unix socket using the i3 binary.
Definition qi3pc.cpp:500
void bindingModesUpdated(const qi3pc::DataArray &modes)
Signal emitted when the (cached) list of modes have been updated.
std::optional< std::pair< QJsonArray, qint64 > > DataArray
Optional pair of a JSON array with its last update time.
Definition qi3pc.h:159
const DataObject & version() const
Get the (cached) i3 version object.
Definition qi3pc.cpp:554
bool isConnected()
Check if the connection to the ipc socket is established.
Definition qi3pc.cpp:622
DataObject m_tree
Definition qi3pc.h:705
QString m_socketPath
Definition qi3pc.h:700
const DataObject & barConfigs() const
Get the (cached) list of all bar configurations.
Definition qi3pc.cpp:547
const DataArray & outputs() const
Get the (cached) list of outputs.
Definition qi3pc.cpp:533
void processWorkspaceEvent(const QJsonDocument &doc)
Handle data received from a workspace event.
Definition qi3pc.cpp:269
IpcEvent
Types of events offered by i3wm's IPC API.
Definition qi3pc.h:44
The Err struct contains the attributes of a parsing error from i3wm when trying to run an unparsable ...
Definition qi3pc.h:170
static constexpr auto _MEMBERS
Mapping of i3wm's parse error reply's attributes to members of ParseError.
Definition qi3pc.h:222
QString errorPosition
The position where the error was detected in the input.
Definition qi3pc.h:185
QString input
The command that failed to run.
Definition qi3pc.h:175
QString toString() const
Convert to a json like string.
Definition qi3pc.cpp:760
QString error
Human readble error message.
Definition qi3pc.h:172
bool operator==(const ParseError &other) const
Memberwise comparison of this ParseError and another.
Definition qi3pc.cpp:753
static std::optional< ParseError > FromJSON(const QJsonObject &json)
Build an optional ParseError from a QJsonObject.
Definition qi3pc.cpp:737