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
|
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 IpcReply {
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 IpcReply? receive(InputStream stream) {
var header = stream.read_bytes(14);
uint8 *data = 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 result = stream.read_bytes(pl_length);
return {pl_type, (string)result.get_data()};
}
internal async IpcReply? receive_async(InputStream stream) {
var header = yield stream.read_bytes_async(14, Priority.DEFAULT, null);
uint8 *data = 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 result = yield stream.read_bytes_async(pl_length, Priority.DEFAULT, null);
return {pl_type, (string)result.get_data()};
}
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;
}
}
}
|