summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/ipc.h1
-rw-r--r--sway/ipc.c50
2 files changed, 45 insertions, 6 deletions
diff --git a/include/ipc.h b/include/ipc.h
index 36957ac1..02aa1c1e 100644
--- a/include/ipc.h
+++ b/include/ipc.h
@@ -12,6 +12,7 @@ enum ipc_command_type {
12 IPC_GET_MARKS = 5, 12 IPC_GET_MARKS = 5,
13 IPC_GET_BAR_CONFIG = 6, 13 IPC_GET_BAR_CONFIG = 6,
14 IPC_GET_VERSION = 7, 14 IPC_GET_VERSION = 7,
15 IPC_SWAY_GET_PIXELS = 0x81
15}; 16};
16 17
17void ipc_init(void); 18void ipc_init(void);
diff --git a/sway/ipc.c b/sway/ipc.c
index c8e424e3..8935147d 100644
--- a/sway/ipc.c
+++ b/sway/ipc.c
@@ -139,7 +139,6 @@ static const int ipc_header_size = sizeof(ipc_magic)+8;
139 139
140int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { 140int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
141 struct ipc_client *client = data; 141 struct ipc_client *client = data;
142 sway_log(L_DEBUG, "Event on IPC client socket %d", client_fd);
143 142
144 if (mask & WLC_EVENT_ERROR) { 143 if (mask & WLC_EVENT_ERROR) {
145 sway_log(L_INFO, "IPC Client socket error, removing client"); 144 sway_log(L_INFO, "IPC Client socket error, removing client");
@@ -166,14 +165,10 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
166 if ((uint32_t)read_available >= client->payload_length) { 165 if ((uint32_t)read_available >= client->payload_length) {
167 ipc_client_handle_command(client); 166 ipc_client_handle_command(client);
168 } 167 }
169 else {
170 sway_log(L_DEBUG, "Too little data to read payload on IPC Client socket, waiting for more (%d < %d)", read_available, client->payload_length);
171 }
172 return 0; 168 return 0;
173 } 169 }
174 170
175 if (read_available < ipc_header_size) { 171 if (read_available < ipc_header_size) {
176 sway_log(L_DEBUG, "Too little data to read header on IPC Client socket, waiting for more (%d < %d)", read_available, ipc_header_size);
177 return 0; 172 return 0;
178 } 173 }
179 174
@@ -221,12 +216,37 @@ void ipc_client_disconnect(struct ipc_client *client)
221 free(client); 216 free(client);
222} 217}
223 218
219bool output_by_name_test(swayc_t *view, void *data) {
220 char *name = (char *)data;
221 if (view->type != C_OUTPUT) {
222 return false;
223 }
224 return !strcmp(name, view->name);
225}
226
227bool get_pixels_callback(const struct wlc_size *size, uint8_t *rgba, void *arg) {
228 struct ipc_client *client = (struct ipc_client *)arg;
229 char response_header[9];
230 memset(response_header, 0, sizeof(response_header));
231 response_header[0] = 1;
232 uint32_t *_size = (uint32_t *)(response_header + 1);
233 _size[0] = size->w;
234 _size[1] = size->h;
235 size_t len = sizeof(response_header) + (size->w * size->h * 4);
236 char *payload = malloc(len);
237 memcpy(payload, response_header, sizeof(response_header));
238 memcpy(payload + sizeof(response_header), rgba, len - sizeof(response_header));
239 ipc_send_reply(client, payload, len);
240 free(payload);
241 return false;
242}
243
224void ipc_client_handle_command(struct ipc_client *client) { 244void ipc_client_handle_command(struct ipc_client *client) {
225 if (!sway_assert(client != NULL, "client != NULL")) { 245 if (!sway_assert(client != NULL, "client != NULL")) {
226 return; 246 return;
227 } 247 }
228 248
229 char buf[client->payload_length + 1]; 249 char *buf = malloc(client->payload_length + 1);
230 if (client->payload_length > 0) 250 if (client->payload_length > 0)
231 { 251 {
232 ssize_t received = recv(client->fd, buf, client->payload_length, 0); 252 ssize_t received = recv(client->fd, buf, client->payload_length, 0);
@@ -234,6 +254,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
234 { 254 {
235 sway_log_errno(L_INFO, "Unable to receive payload from IPC client"); 255 sway_log_errno(L_INFO, "Unable to receive payload from IPC client");
236 ipc_client_disconnect(client); 256 ipc_client_disconnect(client);
257 free(buf);
237 return; 258 return;
238 } 259 }
239 } 260 }
@@ -257,6 +278,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
257 if (request == NULL) { 278 if (request == NULL) {
258 ipc_send_reply(client, "{\"success\": false}", 18); 279 ipc_send_reply(client, "{\"success\": false}", 18);
259 ipc_client_disconnect(client); 280 ipc_client_disconnect(client);
281 free(buf);
260 return; 282 return;
261 } 283 }
262 284
@@ -270,6 +292,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
270 ipc_send_reply(client, "{\"success\": false}", 18); 292 ipc_send_reply(client, "{\"success\": false}", 18);
271 ipc_client_disconnect(client); 293 ipc_client_disconnect(client);
272 json_object_put(request); 294 json_object_put(request);
295 free(buf);
273 return; 296 return;
274 } 297 }
275 } 298 }
@@ -325,6 +348,20 @@ void ipc_client_handle_command(struct ipc_client *client) {
325 free(full_version); 348 free(full_version);
326 break; 349 break;
327 } 350 }
351 case IPC_SWAY_GET_PIXELS:
352 {
353 char response_header[9];
354 memset(response_header, 0, sizeof(response_header));
355 buf[client->payload_length] = '\0';
356 swayc_t *output = swayc_by_test(&root_container, output_by_name_test, buf);
357 if (!output) {
358 sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name");
359 ipc_send_reply(client, response_header, sizeof(response_header));
360 break;
361 }
362 wlc_output_get_pixels(output->handle, get_pixels_callback, client);
363 break;
364 }
328 default: 365 default:
329 sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); 366 sway_log(L_INFO, "Unknown IPC command type %i", client->current_command);
330 ipc_client_disconnect(client); 367 ipc_client_disconnect(client);
@@ -332,6 +369,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
332 } 369 }
333 370
334 client->payload_length = 0; 371 client->payload_length = 0;
372 free(buf);
335} 373}
336 374
337bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { 375bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) {