1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
namespace AstalSway {
private const string IPC_MAGIC = "i3-ipc";
public enum PayloadType {
MESSAGE_RUN_COMMAND = 0,
MESSAGE_GET_WORKSPACES = 1,
MESSAGE_SUBSCRIBE = 2,
MESSAGE_GET_OUTPUTS = 3,
MESSAGE_GET_TREE = 4,
MESSAGE_GET_MARKS = 5,
MESSAGE_GET_BAR_CONFIG = 6,
MESSAGE_GET_VERSION = 7,
MESSAGE_GET_BINDING_NODES = 8,
MESSAGE_GET_CONFIG = 9,
MESSAGE_SEND_TICK = 10,
MESSAGE_SYNC = 11,
MESSAGE_GET_BINDING_STATE = 12,
MESSAGE_GET_INPUTS = 100,
MESSAGE_GET_SEATS = 101,
EVENT_WORKSPACE = 0x80000000,
EVENT_MODE = 0x80000002,
EVENT_WINDOW = 0x80000003,
EVENT_BARCONFIG_UPDATE = 0x80000004,
EVENT_BINDING = 0x80000005,
EVENT_SHUTDOWN = 0x80000006,
EVENT_TICK = 0x80000007,
EVENT_BAR_STATE_UPDATE = 0x80000014,
EVENT_INPUT = 0x80000015,
}
private struct IpcReponse {
public PayloadType type;
public string payload;
}
// Basic interface to send and receive data through Sway IPjC
private class Ipc : Object {
private string SWAYSOCK = GLib.Environment.get_variable("SWAYSOCK");
internal void init() throws Error {
SWAYSOCK = GLib.Environment.get_variable("SWAYSOCK");
if (SWAYSOCK == null) {
critical("Unable to detect Sway");
return;
}
}
internal SocketConnection? connection() {
try {
SocketConnection socket = new SocketClient().connect(new UnixSocketAddress(SWAYSOCK), null);
return socket;
} catch (Error err) {
critical(err.message);
return null;
}
}
internal void send(OutputStream stream, PayloadType type, string payload) {
Array<uint8> message = new Array<uint8> ();
uint8[] magic_str = IPC_MAGIC.data;
uint32 pl_length = (uint32) payload.length;
uint32 pl_type = (uint32) type;
uint8[] pl_data = payload.data;
message.append_vals(magic_str, magic_str.length);
message.append_vals((uint8 *)&pl_length, 4);
message.append_vals((uint8 *)&pl_type, 4);
message.append_vals(pl_data, pl_data.length);
stream.write(message.data);
}
internal IpcReponse? receive(InputStream stream) {
var header = stream.read_bytes(14);
uint8 data[14] = header.get_data();
if (data == null) {
return null;
}
uint32 pl_length = *(uint32 *)&data[IPC_MAGIC.length];
PayloadType pl_type = *(uint32 *)&data[IPC_MAGIC.length+4];
var payload = stream.read_bytes(pl_length);
var result = payload.get_data();
result += '\0';
return {pl_type, (string)result};
}
internal async IpcReponse? receive_async(InputStream stream) {
var header = yield stream.read_bytes_async(14, Priority.DEFAULT, null);
uint8 data[14] = header.get_data();
if (data == null) {
return null;
}
uint32 pl_length = *(uint32 *)&data[IPC_MAGIC.length];
PayloadType pl_type = *(uint32 *)&data[IPC_MAGIC.length+4];
var payload = yield stream.read_bytes_async(pl_length, Priority.DEFAULT, null);
var result = payload.get_data();
result += '\0';
return {pl_type, (string)result};
}
public string message(PayloadType type, string payload) {
SocketConnection conn = connection();
if (conn == null) {
return "";
}
send(conn.output_stream, type, payload);
var result = receive(conn.input_stream);
conn.close(null);
return result.payload;
}
public async string message_async(PayloadType type, string payload) {
SocketConnection conn = connection();
if (conn == null) {
return "";
}
send(conn.output_stream, type, payload);
var result = yield receive_async(conn.input_stream);
conn.close(null);
return result.payload;
}
}
}
|