qi3pc 0.4.1
Qt based library to communicate with i3wm via its IPC API
Loading...
Searching...
No Matches
qi3pc.h
1#ifndef QI3PC_H
2#define QI3PC_H
3
4#include "qi3pc_global.h"
5#include <QtNetwork/qlocalsocket.h>
6#include <QDebug>
7#include <QJsonArray>
8#include <QJsonDocument>
9#include <QJsonObject>
10#include <QMutexLocker>
11#include <QProcessEnvironment>
12#include <QTime>
13
14#include <i3/ipc.h>
15
16#include <optional>
17#include <string>
18#include <QLoggingCategory>
19
20Q_DECLARE_LOGGING_CATEGORY(Qi3pcLogger);
29class QI3PCSHARED_EXPORT qi3pc : public QObject
30{
31 Q_OBJECT
32
33public:
34 static constexpr auto IpcMagicString = std::string("i3-ipc");
35 static constexpr auto IpcMagicLength = IpcMagicString.length();
36
43 enum class IpcEvent : quint32
44 {
45 Workspace = I3_IPC_EVENT_WORKSPACE,
46 Output = I3_IPC_EVENT_OUTPUT,
47 Mode = I3_IPC_EVENT_MODE,
48 Window = I3_IPC_EVENT_WINDOW,
49 BarUpdate = I3_IPC_EVENT_BARCONFIG_UPDATE,
50 Binding = I3_IPC_EVENT_BINDING,
51 Shutdown = I3_IPC_EVENT_SHUTDOWN,
52 Tick = I3_IPC_EVENT_TICK
53 };
54
61 enum class IpcType : quint32
62 {
63 Command = I3_IPC_REPLY_TYPE_COMMAND,
64 Workspaces = I3_IPC_REPLY_TYPE_WORKSPACES,
65 Subscribe = I3_IPC_REPLY_TYPE_SUBSCRIBE,
66 Outputs = I3_IPC_REPLY_TYPE_OUTPUTS,
67 Tree = I3_IPC_REPLY_TYPE_TREE,
68 Marks = I3_IPC_REPLY_TYPE_MARKS,
69 BarConfig = I3_IPC_REPLY_TYPE_BAR_CONFIG,
70 Version = I3_IPC_REPLY_TYPE_VERSION,
71 BindingModes = I3_IPC_REPLY_TYPE_BINDING_MODES,
72 Config = I3_IPC_REPLY_TYPE_CONFIG,
73 Tick = I3_IPC_REPLY_TYPE_TICK,
74 Sync = I3_IPC_REPLY_TYPE_SYNC,
75 BindingState = I3_IPC_REPLY_TYPE_GET_BINDING_STATE
76 };
77
85 enum class WorkspaceChange
86 {
87 Empty,
88 Focus,
89 Init,
90 Move,
91 Reload,
92 Rename,
93 Restored,
94 Urgent,
95 Unknown
96 };
97
104 enum class OutputChange
105 {
106 Unspecified,
107 Unknown
108 };
109
116 enum class WindowChange
117 {
118 New,
119 Close,
120 Focus,
121 Title,
122 Fullscreen,
123 Move,
124 Floating,
125 Urgent,
126 Mark,
127 Unknown
128 };
129
136 enum class ShutdownChange
137 {
138 Restart,
139 Exit,
140 Unknown
141 };
142
149 enum class BindingChange
150 {
151 Run,
152 Unknown
153 };
154
156 using DataObject = std::optional<std::pair<QJsonObject, qint64>>;
157
159 using DataArray = std::optional<std::pair<QJsonArray, qint64>>;
160
162 using DataString = std::optional<std::pair<QString, qint64>>;
163
170 struct ParseError {
172 QString error;
173
175 QString input;
176
186
194 QString toString() const;
195
201 bool operator==(const ParseError& other) const;
202
215 static std::optional<ParseError> FromJSON(const QJsonObject& json);
216
217 private:
219 using QStringMemberPtr = QString ParseError::*;
220
222 inline static constexpr auto _MEMBERS = std::to_array<std::pair<const char*, QStringMemberPtr>>
223 ({
224 {"error", &ParseError::error},
225 {"input", &ParseError::input},
226 {"errorposition", &ParseError::errorPosition}
227 });
228 };
229
231 using Error = std::optional<ParseError>;
232
239 using CommandResults = std::vector<std::pair<bool, Error>>;
240
247 using Message = std::optional<std::pair<QJsonDocument, quint32>>;
248
253 explicit qi3pc(QObject* parent = nullptr);
254
260 explicit qi3pc(const QString& socketPath, QObject* parent);
261
268 virtual ~qi3pc();
269
281 bool connect();
282
289 bool isConnected();
290
297 bool disconnect();
298
305 void subscribe(const QStringList& events);
306
314 static QString FindSocketPath();
315
322 static QString FindSocketPathFromI3Binary();
323
328 QString socketPath() const;
329
343 template<IpcType Type>
344 requires(Type != IpcType::Subscribe && Type != IpcType::Tick)
345 void sendMessage(const QByteArray& payload = QByteArray()) {
346 WritePayload(m_messageSocket, payload, Type);
347 }
348
353 void sendTick(const QByteArray& payload = QByteArray());
354
361 const DataArray& workspaces() const;
362
369 const DataObject& tree() const;
370
377 const DataArray& outputs() const;
378
385 const DataArray& marks() const;
386
395 const DataObject& barConfigs() const;
396
404 const DataObject& version() const;
405
412 const DataArray& bindingModes() const;
413
420 const DataObject& config() const;
421
428 const DataString& bindingState() const;
429
430public slots:
437 void fetchWorkspaces();
438
445 void fetchTree();
446
454 void fetchOutputs();
455
462 void fetchMarks();
463
473 void fetchBarConfig(const QString& id);
474
481 void fetchBarConfigs();
482
490 void fetchVersion();
491
499 void fetchBindingModes();
500
507 void fetchConfig();
508
515 void fetchBindingState();
516
517private:
523 Message processMessage(QLocalSocket& socket);
524
528 void processEvent();
529
533 void processReply();
534
539 void processWorkspaceEvent(const QJsonDocument& doc);
540
545 void processOutputEvent(const QJsonDocument& doc);
546
551 void processModeEvent(const QJsonDocument& doc);
552
557 void processWindowEvent(const QJsonDocument& doc);
558
563 void processBarUpdateEvent(const QJsonDocument& doc);
564
569 void processBindingEvent(const QJsonDocument& doc);
570
575 void processShutdownEvent(const QJsonDocument& doc);
576
581 void processTickEvent(const QJsonDocument& doc);
582
587 void processCommandReply(const QJsonDocument& doc);
588
593 void processWorkspaceReply(const QJsonDocument& doc);
594
599 void processOutputReply(const QJsonDocument& doc);
600
605 void processTreeReply(const QJsonDocument& doc);
606
611 void processMarkReply(const QJsonDocument& doc);
612
617 void processBarConfigReply(const QJsonDocument& doc);
618
623 void processVersionReply(const QJsonDocument& doc);
624
629 void processBindingModesReply(const QJsonDocument& doc);
630
635 void processConfigReply(const QJsonDocument& doc);
636
641 void processTickReply(const QJsonDocument& doc);
642
647 void processSyncReply(const QJsonDocument& doc);
648
653 void processBindingStateReply(const QJsonDocument& doc);
654
660 static WorkspaceChange WorkspaceChangeFromString(const QString& s);
661
667 static WindowChange WindowChangeFromString(const QString& s);
668
674 static ShutdownChange ShutdownChangeFromString(const QString& s);
675
681 static OutputChange OutputChangeFromString(const QString& s);
682
688 static BindingChange BindingChangeFromString(const QString& s);
689
697 static void WritePayload(QLocalSocket& socket, const QByteArray& payload, IpcType type);
698
699private:
700 QString m_socketPath;
701
702 QLocalSocket m_eventSocket;
703 QLocalSocket m_messageSocket;
704
714
715signals:
724
732 void tickSent(bool success);
733
742 void synced(bool success);
743
751 void subscribed(bool success);
752
760 const QJsonObject& current,
761 const QJsonObject& old);
767
774 void modeEvent(QString change, bool pango);
775
781 void windowEvent(qi3pc::WindowChange change, const QJsonObject& container);
782
788 void barUpdateEvent(const QJsonObject& doc);
789
799 void bindingEvent(qi3pc::BindingChange change, const QJsonObject& binding, const QString& mode);
800
806
814 void tickEvent(const QString& payload);
815
824
833
840
849
857 void barConfigUpdated(const QJsonObject& config);
858
867 void newBarConfig(const QString& id);
868
878
888
896
904};
905
906#endif // QI3PC_H
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 barConfigUpdated(const QJsonObject &config)
Signal emitted when a specific bar's (cached) config have been updated. At this point the configurati...
void sendMessage(const QByteArray &payload=QByteArray())
Send a message with the specified type and payload to i3.
Definition qi3pc.h:345
DataObject m_version
Definition qi3pc.h:710
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.
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.
DataString m_bindingState
Definition qi3pc.h:712
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.
DataArray m_marks
Definition qi3pc.h:708
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 constexpr auto IpcMagicLength
Definition qi3pc.h:35
void windowEvent(qi3pc::WindowChange change, const QJsonObject &container)
Signal emitted when a window changes.
QLocalSocket m_eventSocket
Definition qi3pc.h:702
void subscribe(const QStringList &events)
Subscribe to a list of events.
Definition qi3pc.cpp:641
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.
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
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
IpcType
Types of message/replies the API send/expect to/from i3wm.
Definition qi3pc.h:62
static constexpr auto IpcMagicString
Definition qi3pc.h:34
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 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.
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
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
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 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 DataArray & outputs() const
Get the (cached) list of outputs.
Definition qi3pc.cpp:533
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 ParseError::* QStringMemberPtr
QString member pointer of ParseError.
Definition qi3pc.h:219
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