diff options
-rw-r--r-- | include/sway/ipc-json.h | 1 | ||||
-rw-r--r-- | sway/ipc-json.c | 61 | ||||
-rw-r--r-- | sway/ipc-server.c | 12 | ||||
-rw-r--r-- | swaymsg/main.c | 184 | ||||
-rw-r--r-- | swaymsg/swaymsg.1.txt | 7 |
5 files changed, 248 insertions, 17 deletions
diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index 02b07a23..3a5af0f5 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h | |||
@@ -10,5 +10,6 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar); | |||
10 | json_object *ipc_json_describe_container(swayc_t *c); | 10 | json_object *ipc_json_describe_container(swayc_t *c); |
11 | json_object *ipc_json_describe_container_recursive(swayc_t *c); | 11 | json_object *ipc_json_describe_container_recursive(swayc_t *c); |
12 | json_object *ipc_json_describe_window(swayc_t *c); | 12 | json_object *ipc_json_describe_window(swayc_t *c); |
13 | json_object *ipc_json_describe_input(struct libinput_device *device); | ||
13 | 14 | ||
14 | #endif | 15 | #endif |
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 6bd5204c..fba489d7 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -2,7 +2,9 @@ | |||
2 | #include <ctype.h> | 2 | #include <ctype.h> |
3 | #include <string.h> | 3 | #include <string.h> |
4 | #include <stdint.h> | 4 | #include <stdint.h> |
5 | #include <libinput.h> | ||
5 | #include "sway/container.h" | 6 | #include "sway/container.h" |
7 | #include "sway/input.h" | ||
6 | #include "sway/ipc-json.h" | 8 | #include "sway/ipc-json.h" |
7 | #include "util.h" | 9 | #include "util.h" |
8 | 10 | ||
@@ -242,6 +244,65 @@ json_object *ipc_json_describe_container(swayc_t *c) { | |||
242 | return object; | 244 | return object; |
243 | } | 245 | } |
244 | 246 | ||
247 | json_object *ipc_json_describe_input(struct libinput_device *device) { | ||
248 | char* identifier = libinput_dev_unique_id(device); | ||
249 | int vendor = libinput_device_get_id_vendor(device); | ||
250 | int product = libinput_device_get_id_product(device); | ||
251 | const char *name = libinput_device_get_name(device); | ||
252 | double width = -1, height = -1; | ||
253 | int has_size = libinput_device_get_size(device, &width, &height); | ||
254 | |||
255 | json_object *device_object = json_object_new_object(); | ||
256 | json_object_object_add(device_object,"identifier", | ||
257 | identifier ? json_object_new_string(identifier) : NULL); | ||
258 | json_object_object_add(device_object, | ||
259 | "vendor", json_object_new_int(vendor)); | ||
260 | json_object_object_add(device_object, | ||
261 | "product", json_object_new_int(product)); | ||
262 | json_object_object_add(device_object, | ||
263 | "name", json_object_new_string(name)); | ||
264 | if (has_size == 0) { | ||
265 | json_object *size_object = json_object_new_object(); | ||
266 | json_object_object_add(size_object, | ||
267 | "width", json_object_new_double(width)); | ||
268 | json_object_object_add(size_object, | ||
269 | "height", json_object_new_double(height)); | ||
270 | } else { | ||
271 | json_object_object_add(device_object, "size", NULL); | ||
272 | } | ||
273 | |||
274 | struct { | ||
275 | enum libinput_device_capability cap; | ||
276 | const char *name; | ||
277 | // If anyone feels like implementing device-specific IPC output, | ||
278 | // be my guest | ||
279 | json_object *(*describe)(struct libinput_device *); | ||
280 | } caps[] = { | ||
281 | { LIBINPUT_DEVICE_CAP_KEYBOARD, "keyboard", NULL }, | ||
282 | { LIBINPUT_DEVICE_CAP_POINTER, "pointer", NULL }, | ||
283 | { LIBINPUT_DEVICE_CAP_TOUCH, "touch", NULL }, | ||
284 | { LIBINPUT_DEVICE_CAP_TABLET_TOOL, "tablet_tool", NULL }, | ||
285 | { LIBINPUT_DEVICE_CAP_TABLET_PAD, "tablet_pad", NULL }, | ||
286 | { LIBINPUT_DEVICE_CAP_GESTURE, "gesture", NULL }, | ||
287 | { LIBINPUT_DEVICE_CAP_SWITCH, "switch", NULL } | ||
288 | }; | ||
289 | |||
290 | json_object *_caps = json_object_new_array(); | ||
291 | for (size_t i = 0; i < sizeof(caps) / sizeof(caps[0]); ++i) { | ||
292 | if (libinput_device_has_capability(device, caps[i].cap)) { | ||
293 | json_object_array_add(_caps, json_object_new_string(caps[i].name)); | ||
294 | if (caps[i].describe) { | ||
295 | json_object *desc = caps[i].describe(device); | ||
296 | json_object_object_add(device_object, caps[i].name, desc); | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | json_object_object_add(device_object, "capabilities", _caps); | ||
301 | |||
302 | free(identifier); | ||
303 | return device_object; | ||
304 | } | ||
305 | |||
245 | json_object *ipc_json_get_version() { | 306 | json_object *ipc_json_get_version() { |
246 | json_object *version = json_object_new_object(); | 307 | json_object *version = json_object_new_object(); |
247 | 308 | ||
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 6554098b..67a3cdc8 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -421,17 +421,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
421 | } | 421 | } |
422 | json_object *inputs = json_object_new_array(); | 422 | json_object *inputs = json_object_new_array(); |
423 | if (input_devices) { | 423 | if (input_devices) { |
424 | for(int i=0; i<input_devices->length; i++) { | 424 | for(int i = 0; i<input_devices->length; i++) { |
425 | struct libinput_device *device = input_devices->items[i]; | 425 | struct libinput_device *device = input_devices->items[i]; |
426 | char* identifier = libinput_dev_unique_id(device); | 426 | json_object_array_add(inputs, ipc_json_describe_input(device)); |
427 | json_object *device_object = json_object_new_object(); | ||
428 | if (!identifier) { | ||
429 | json_object_object_add(device_object, "identifier", NULL); | ||
430 | } else { | ||
431 | json_object_object_add(device_object, "identifier", json_object_new_string(identifier)); | ||
432 | } | ||
433 | json_object_array_add(inputs, device_object); | ||
434 | free(identifier); | ||
435 | } | 427 | } |
436 | } | 428 | } |
437 | const char *json_string = json_object_to_json_string(inputs); | 429 | const char *json_string = json_object_to_json_string(inputs); |
diff --git a/swaymsg/main.c b/swaymsg/main.c index 2c418127..2d2b0f60 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <stdint.h> | 7 | #include <stdint.h> |
8 | #include <sys/un.h> | 8 | #include <sys/un.h> |
9 | #include <sys/socket.h> | 9 | #include <sys/socket.h> |
10 | #include <ctype.h> | ||
10 | #include <unistd.h> | 11 | #include <unistd.h> |
11 | #include <json-c/json.h> | 12 | #include <json-c/json.h> |
12 | #include "stringop.h" | 13 | #include "stringop.h" |
@@ -18,8 +19,169 @@ void sway_terminate(int exit_code) { | |||
18 | exit(exit_code); | 19 | exit(exit_code); |
19 | } | 20 | } |
20 | 21 | ||
22 | static void pretty_print_cmd(json_object *r) { | ||
23 | bool _success; | ||
24 | json_object *success; | ||
25 | if (!json_object_object_get_ex(r, "success", &success)) { | ||
26 | _success = true; | ||
27 | } else { | ||
28 | _success = json_object_get_boolean(success); | ||
29 | } | ||
30 | if (!_success) { | ||
31 | json_object *error; | ||
32 | if (!json_object_object_get_ex(r, "error", &error)) { | ||
33 | printf("An unknkown error occured"); | ||
34 | } else { | ||
35 | printf("Error: %s\n", json_object_get_string(error)); | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | |||
40 | static void pretty_print_workspace(json_object *w) { | ||
41 | json_object *name, *rect, *visible, *output, *urgent, *layout, *focused; | ||
42 | json_object_object_get_ex(w, "name", &name); | ||
43 | json_object_object_get_ex(w, "rect", &rect); | ||
44 | json_object_object_get_ex(w, "visible", &visible); | ||
45 | json_object_object_get_ex(w, "output", &output); | ||
46 | json_object_object_get_ex(w, "urgent", &urgent); | ||
47 | json_object_object_get_ex(w, "layout", &layout); | ||
48 | json_object_object_get_ex(w, "focused", &focused); | ||
49 | printf( | ||
50 | "Workspace %s%s%s%s\n" | ||
51 | " Output: %s\n" | ||
52 | " Layout: %s\n\n", | ||
53 | json_object_get_string(name), | ||
54 | json_object_get_boolean(focused) ? " (focused)" : "", | ||
55 | !json_object_get_boolean(visible) ? " (off-screen)" : "", | ||
56 | json_object_get_boolean(urgent) ? " (urgent)" : "", | ||
57 | json_object_get_string(output), | ||
58 | json_object_get_string(layout) | ||
59 | ); | ||
60 | } | ||
61 | |||
62 | static void pretty_print_input(json_object *i) { | ||
63 | json_object *id, *name, *size, *caps; | ||
64 | json_object_object_get_ex(i, "identifier", &id); | ||
65 | json_object_object_get_ex(i, "name", &name); | ||
66 | json_object_object_get_ex(i, "size", &size); | ||
67 | json_object_object_get_ex(i, "capabilities", &caps); | ||
68 | |||
69 | printf( "Input device %s\n Type: ", json_object_get_string(name)); | ||
70 | |||
71 | struct { | ||
72 | const char *a; | ||
73 | const char *b; | ||
74 | } cap_names[] = { | ||
75 | { "keyboard", "Keyboard" }, | ||
76 | { "pointer", "Mouse" }, | ||
77 | { "touch", "Touch" }, | ||
78 | { "tablet_tool", "Tablet tool" }, | ||
79 | { "tablet_pad", "Tablet pad" }, | ||
80 | { "gesture", "Gesture" }, | ||
81 | { "switch", "Switch" }, | ||
82 | }; | ||
83 | |||
84 | size_t len = json_object_array_length(caps); | ||
85 | if (len == 0) { | ||
86 | printf("Unknown"); | ||
87 | } | ||
88 | |||
89 | json_object *cap; | ||
90 | for (size_t i = 0; i < len; ++i) { | ||
91 | cap = json_object_array_get_idx(caps, i); | ||
92 | const char *cap_s = json_object_get_string(cap); | ||
93 | const char *_name = NULL; | ||
94 | for (size_t j = 0; j < sizeof(cap_names) / sizeof(cap_names[0]); ++i) { | ||
95 | if (strcmp(cap_names[i].a, cap_s) == 0) { | ||
96 | _name = cap_names[i].b; | ||
97 | break; | ||
98 | } | ||
99 | } | ||
100 | printf("%s%s", _name ? _name : cap_s, len > 1 && i != len - 1 ? ", " : ""); | ||
101 | } | ||
102 | printf("\n Sway ID: %s\n", json_object_get_string(id)); | ||
103 | if (size) { | ||
104 | json_object *width, *height; | ||
105 | json_object_object_get_ex(size, "width", &width); | ||
106 | json_object_object_get_ex(size, "height", &height); | ||
107 | printf(" Size: %lfmm x %lfmm\n", | ||
108 | json_object_get_double(width), json_object_get_double(height)); | ||
109 | } | ||
110 | printf("\n"); | ||
111 | } | ||
112 | |||
113 | static void pretty_print_output(json_object *o) { | ||
114 | json_object *name, *rect, *focused, *active, *ws, *scale; | ||
115 | json_object_object_get_ex(o, "name", &name); | ||
116 | json_object_object_get_ex(o, "rect", &rect); | ||
117 | json_object_object_get_ex(o, "focused", &focused); | ||
118 | json_object_object_get_ex(o, "active", &active); | ||
119 | json_object_object_get_ex(o, "current_workspace", &ws); | ||
120 | json_object_object_get_ex(o, "scale", &scale); | ||
121 | json_object *x, *y, *width, *height; | ||
122 | json_object_object_get_ex(rect, "x", &x); | ||
123 | json_object_object_get_ex(rect, "y", &y); | ||
124 | json_object_object_get_ex(rect, "width", &width); | ||
125 | json_object_object_get_ex(rect, "height", &height); | ||
126 | printf( | ||
127 | "Output %s%s%s\n" | ||
128 | " Geometry: %dx%d @ %d,%d\n" | ||
129 | " Scale factor: %dx\n" | ||
130 | " Workspace: %s\n\n", | ||
131 | json_object_get_string(name), | ||
132 | json_object_get_boolean(focused) ? " (focused)" : "", | ||
133 | !json_object_get_boolean(active) ? " (inactive)" : "", | ||
134 | json_object_get_int(width), json_object_get_int(height), | ||
135 | json_object_get_int(x), json_object_get_int(y), | ||
136 | json_object_get_int(scale), | ||
137 | json_object_get_string(ws) | ||
138 | ); | ||
139 | } | ||
140 | |||
141 | static void pretty_print_version(json_object *v) { | ||
142 | json_object *ver; | ||
143 | json_object_object_get_ex(v, "human_readable", &ver); | ||
144 | printf("sway version %s\n", json_object_get_string(ver)); | ||
145 | } | ||
146 | |||
147 | static void pretty_print(int type, json_object *resp) { | ||
148 | if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && | ||
149 | type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && | ||
150 | type != IPC_GET_VERSION) { | ||
151 | printf("%s\n", json_object_to_json_string_ext(resp, | ||
152 | JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); | ||
153 | return; | ||
154 | } | ||
155 | |||
156 | if (type == IPC_GET_VERSION) { | ||
157 | pretty_print_version(resp); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | json_object *obj; | ||
162 | size_t len = json_object_array_length(resp); | ||
163 | for (size_t i = 0; i < len; ++i) { | ||
164 | obj = json_object_array_get_idx(resp, i); | ||
165 | switch (type) { | ||
166 | case IPC_COMMAND: | ||
167 | pretty_print_cmd(obj); | ||
168 | break; | ||
169 | case IPC_GET_WORKSPACES: | ||
170 | pretty_print_workspace(obj); | ||
171 | break; | ||
172 | case IPC_GET_INPUTS: | ||
173 | pretty_print_input(obj); | ||
174 | break; | ||
175 | case IPC_GET_OUTPUTS: | ||
176 | pretty_print_output(obj); | ||
177 | break; | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
21 | int main(int argc, char **argv) { | 182 | int main(int argc, char **argv) { |
22 | static int quiet = 0; | 183 | static int quiet = 0; |
184 | static int raw = 0; | ||
23 | char *socket_path = NULL; | 185 | char *socket_path = NULL; |
24 | char *cmdtype = NULL; | 186 | char *cmdtype = NULL; |
25 | 187 | ||
@@ -28,9 +190,10 @@ int main(int argc, char **argv) { | |||
28 | static struct option long_options[] = { | 190 | static struct option long_options[] = { |
29 | {"help", no_argument, NULL, 'h'}, | 191 | {"help", no_argument, NULL, 'h'}, |
30 | {"quiet", no_argument, NULL, 'q'}, | 192 | {"quiet", no_argument, NULL, 'q'}, |
31 | {"version", no_argument, NULL, 'v'}, | 193 | {"raw", no_argument, NULL, 'r'}, |
32 | {"socket", required_argument, NULL, 's'}, | 194 | {"socket", required_argument, NULL, 's'}, |
33 | {"type", required_argument, NULL, 't'}, | 195 | {"type", required_argument, NULL, 't'}, |
196 | {"version", no_argument, NULL, 'v'}, | ||
34 | {0, 0, 0, 0} | 197 | {0, 0, 0, 0} |
35 | }; | 198 | }; |
36 | 199 | ||
@@ -39,14 +202,17 @@ int main(int argc, char **argv) { | |||
39 | "\n" | 202 | "\n" |
40 | " -h, --help Show help message and quit.\n" | 203 | " -h, --help Show help message and quit.\n" |
41 | " -q, --quiet Be quiet.\n" | 204 | " -q, --quiet Be quiet.\n" |
42 | " -v, --version Show the version number and quit.\n" | 205 | " -r, --raw Use raw output even if using a tty\n" |
43 | " -s, --socket <socket> Use the specified socket.\n" | 206 | " -s, --socket <socket> Use the specified socket.\n" |
44 | " -t, --type <type> Specify the message type.\n"; | 207 | " -t, --type <type> Specify the message type.\n" |
208 | " -v, --version Show the version number and quit.\n"; | ||
209 | |||
210 | raw = !isatty(STDOUT_FILENO); | ||
45 | 211 | ||
46 | int c; | 212 | int c; |
47 | while (1) { | 213 | while (1) { |
48 | int option_index = 0; | 214 | int option_index = 0; |
49 | c = getopt_long(argc, argv, "hqvs:t:", long_options, &option_index); | 215 | c = getopt_long(argc, argv, "hqrs:t:v", long_options, &option_index); |
50 | if (c == -1) { | 216 | if (c == -1) { |
51 | break; | 217 | break; |
52 | } | 218 | } |
@@ -54,6 +220,9 @@ int main(int argc, char **argv) { | |||
54 | case 'q': // Quiet | 220 | case 'q': // Quiet |
55 | quiet = 1; | 221 | quiet = 1; |
56 | break; | 222 | break; |
223 | case 'r': // Raw | ||
224 | raw = 1; | ||
225 | break; | ||
57 | case 's': // Socket | 226 | case 's': // Socket |
58 | socket_path = strdup(optarg); | 227 | socket_path = strdup(optarg); |
59 | break; | 228 | break; |
@@ -125,7 +294,12 @@ int main(int argc, char **argv) { | |||
125 | printf("%s\n", resp); | 294 | printf("%s\n", resp); |
126 | ret = 1; | 295 | ret = 1; |
127 | } else { | 296 | } else { |
128 | printf("%s\n", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); | 297 | if (raw) { |
298 | printf("%s\n", json_object_to_json_string_ext(obj, | ||
299 | JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); | ||
300 | } else { | ||
301 | pretty_print(type, obj); | ||
302 | } | ||
129 | free(obj); | 303 | free(obj); |
130 | } | 304 | } |
131 | } | 305 | } |
diff --git a/swaymsg/swaymsg.1.txt b/swaymsg/swaymsg.1.txt index c3af28d5..1f03bee3 100644 --- a/swaymsg/swaymsg.1.txt +++ b/swaymsg/swaymsg.1.txt | |||
@@ -23,8 +23,8 @@ Options | |||
23 | *-q, \--quiet*:: | 23 | *-q, \--quiet*:: |
24 | Sends the IPC message but does not print the response from sway. | 24 | Sends the IPC message but does not print the response from sway. |
25 | 25 | ||
26 | *-v, \--version*:: | 26 | *-r, \--raw*:: |
27 | Print the version (of swaymsg) and quit. | 27 | Use raw output even if using a tty. |
28 | 28 | ||
29 | *-s, --socket* <path>:: | 29 | *-s, --socket* <path>:: |
30 | Use the specified socket path. Otherwise, swaymsg will ask sway where the | 30 | Use the specified socket path. Otherwise, swaymsg will ask sway where the |
@@ -33,6 +33,9 @@ Options | |||
33 | *-t, \--type* <type>:: | 33 | *-t, \--type* <type>:: |
34 | Specify the type of IPC message. See below. | 34 | Specify the type of IPC message. See below. |
35 | 35 | ||
36 | *-v, \--version*:: | ||
37 | Print the version (of swaymsg) and quit. | ||
38 | |||
36 | IPC Message Types | 39 | IPC Message Types |
37 | ----------------- | 40 | ----------------- |
38 | 41 | ||