aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/stringop.h7
-rw-r--r--include/sway/config.h2
-rw-r--r--meson.build16
-rw-r--r--sway/commands.c61
-rw-r--r--sway/commands/create_output.c4
-rw-r--r--sway/commands/workspace.c13
-rw-r--r--sway/commands/ws_auto_back_and_forth.c2
-rw-r--r--sway/desktop/output.c9
-rw-r--r--sway/ipc-json.c22
-rw-r--r--sway/sway.5.scd8
-rw-r--r--sway/tree/output.c7
-rw-r--r--sway/tree/workspace.c61
-rw-r--r--swaymsg/main.c11
13 files changed, 158 insertions, 65 deletions
diff --git a/include/stringop.h b/include/stringop.h
index 01bbdaa9..919e605c 100644
--- a/include/stringop.h
+++ b/include/stringop.h
@@ -1,12 +1,7 @@
1#ifndef _SWAY_STRINGOP_H 1#ifndef _SWAY_STRINGOP_H
2#define _SWAY_STRINGOP_H 2#define _SWAY_STRINGOP_H
3#include <stdlib.h>
4#include "list.h"
5 3
6#if !HAVE_DECL_SETENV 4#include "list.h"
7// Not sure why we need to provide this
8extern int setenv(const char *, const char *, int);
9#endif
10 5
11// array of whitespace characters to use for delims 6// array of whitespace characters to use for delims
12extern const char whitespace[]; 7extern const char whitespace[];
diff --git a/include/sway/config.h b/include/sway/config.h
index cd56c3dc..79c4359b 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -183,7 +183,7 @@ struct side_gaps {
183 */ 183 */
184struct workspace_config { 184struct workspace_config {
185 char *workspace; 185 char *workspace;
186 char *output; 186 list_t *outputs;
187 int gaps_inner; 187 int gaps_inner;
188 struct side_gaps gaps_outer; 188 struct side_gaps gaps_outer;
189}; 189};
diff --git a/meson.build b/meson.build
index 6b23b4e3..8327b763 100644
--- a/meson.build
+++ b/meson.build
@@ -9,11 +9,17 @@ project(
9 ], 9 ],
10) 10)
11 11
12add_project_arguments('-Wno-unused-parameter', language: 'c') 12add_project_arguments(
13add_project_arguments('-Wno-unused-function', language: 'c') 13 [
14add_project_arguments('-Wno-unused-result', language: 'c') 14 '-DWL_HIDE_DEPRECATED',
15add_project_arguments('-DWL_HIDE_DEPRECATED', language: 'c') 15 '-DWLR_USE_UNSTABLE',
16add_project_arguments('-DWLR_USE_UNSTABLE', language: 'c') 16
17 '-Wno-unused-parameter',
18 '-Wno-unused-result',
19 '-Wundef',
20 ],
21 language: 'c',
22)
17 23
18cc = meson.get_compiler('c') 24cc = meson.get_compiler('c')
19 25
diff --git a/sway/commands.c b/sway/commands.c
index 37c7169a..4b86c2fa 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -353,12 +353,14 @@ struct cmd_results *config_command(char *exec) {
353 struct cmd_results *results = NULL; 353 struct cmd_results *results = NULL;
354 int argc; 354 int argc;
355 char **argv = split_args(exec, &argc); 355 char **argv = split_args(exec, &argc);
356
357 // Check for empty lines
356 if (!argc) { 358 if (!argc) {
357 results = cmd_results_new(CMD_SUCCESS, NULL, NULL); 359 results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
358 goto cleanup; 360 goto cleanup;
359 } 361 }
360 362
361 // Start block 363 // Check for the start of a block
362 if (argc > 1 && strcmp(argv[argc - 1], "{") == 0) { 364 if (argc > 1 && strcmp(argv[argc - 1], "{") == 0) {
363 char *block = join_args(argv, argc - 1); 365 char *block = join_args(argv, argc - 1);
364 results = cmd_results_new(CMD_BLOCK, block, NULL); 366 results = cmd_results_new(CMD_BLOCK, block, NULL);
@@ -366,22 +368,54 @@ struct cmd_results *config_command(char *exec) {
366 goto cleanup; 368 goto cleanup;
367 } 369 }
368 370
369 // Endblock 371 // Check for the end of a block
370 if (strcmp(argv[argc - 1], "}") == 0) { 372 if (strcmp(argv[argc - 1], "}") == 0) {
371 results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); 373 results = cmd_results_new(CMD_BLOCK_END, NULL, NULL);
372 goto cleanup; 374 goto cleanup;
373 } 375 }
374 wlr_log(WLR_INFO, "handling config command '%s'", exec); 376
377 // Make sure the command is not stored in a variable
378 if (*argv[0] == '$') {
379 argv[0] = do_var_replacement(argv[0]);
380 char *temp = join_args(argv, argc);
381 free_argv(argc, argv);
382 argv = split_args(temp, &argc);
383 free(temp);
384 if (!argc) {
385 results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
386 goto cleanup;
387 }
388 }
389
390 // Determine the command handler
391 wlr_log(WLR_INFO, "Config command: %s", exec);
375 struct cmd_handler *handler = find_handler(argv[0], NULL, 0); 392 struct cmd_handler *handler = find_handler(argv[0], NULL, 0);
376 if (!handler) { 393 if (!handler || !handler->handle) {
377 char *input = argv[0] ? argv[0] : "(empty)"; 394 char *input = argv[0] ? argv[0] : "(empty)";
378 results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); 395 char *error = handler
396 ? "This command is shimmed, but unimplemented"
397 : "Unknown/invalid command";
398 results = cmd_results_new(CMD_INVALID, input, error);
379 goto cleanup; 399 goto cleanup;
380 } 400 }
381 int i; 401
382 // Var replacement, for all but first argument of set 402 // Do variable replacement
383 // TODO commands 403 if (handler->handle == cmd_set && argc > 1 && *argv[1] == '$') {
384 for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { 404 // Escape the variable name so it does not get replaced by one shorter
405 char *temp = calloc(1, strlen(argv[1]) + 2);
406 temp[0] = '$';
407 strcpy(&temp[1], argv[1]);
408 free(argv[1]);
409 argv[1] = temp;
410 }
411 char *command = do_var_replacement(join_args(argv, argc));
412 wlr_log(WLR_INFO, "After replacement: %s", command);
413 free_argv(argc, argv);
414 argv = split_args(command, &argc);
415 free(command);
416
417 // Strip quotes and unescape the string
418 for (int i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) {
385 if (handler->handle != cmd_exec && handler->handle != cmd_exec_always 419 if (handler->handle != cmd_exec && handler->handle != cmd_exec_always
386 && handler->handle != cmd_bindsym 420 && handler->handle != cmd_bindsym
387 && handler->handle != cmd_bindcode 421 && handler->handle != cmd_bindcode
@@ -389,14 +423,11 @@ struct cmd_results *config_command(char *exec) {
389 && (*argv[i] == '\"' || *argv[i] == '\'')) { 423 && (*argv[i] == '\"' || *argv[i] == '\'')) {
390 strip_quotes(argv[i]); 424 strip_quotes(argv[i]);
391 } 425 }
392 argv[i] = do_var_replacement(argv[i]);
393 unescape_string(argv[i]); 426 unescape_string(argv[i]);
394 } 427 }
395 if (handler->handle) { 428
396 results = handler->handle(argc-1, argv+1); 429 // Run command
397 } else { 430 results = handler->handle(argc - 1, argv + 1);
398 results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented");
399 }
400 431
401cleanup: 432cleanup:
402 free_argv(argc, argv); 433 free_argv(argc, argv);
diff --git a/sway/commands/create_output.c b/sway/commands/create_output.c
index 1c2464ea..3f870acb 100644
--- a/sway/commands/create_output.c
+++ b/sway/commands/create_output.c
@@ -1,7 +1,7 @@
1#include <wlr/config.h> 1#include <wlr/config.h>
2#include <wlr/backend/multi.h> 2#include <wlr/backend/multi.h>
3#include <wlr/backend/wayland.h> 3#include <wlr/backend/wayland.h>
4#ifdef WLR_HAS_X11_BACKEND 4#if WLR_HAS_X11_BACKEND
5#include <wlr/backend/x11.h> 5#include <wlr/backend/x11.h>
6#endif 6#endif
7#include "sway/commands.h" 7#include "sway/commands.h"
@@ -18,7 +18,7 @@ static void create_output(struct wlr_backend *backend, void *data) {
18 wlr_wl_output_create(backend); 18 wlr_wl_output_create(backend);
19 *done = true; 19 *done = true;
20 } 20 }
21#ifdef WLR_HAS_X11_BACKEND 21#if WLR_HAS_X11_BACKEND
22 else if (wlr_backend_is_x11(backend)) { 22 else if (wlr_backend_is_x11(backend)) {
23 wlr_x11_output_create(backend); 23 wlr_x11_output_create(backend);
24 *done = true; 24 *done = true;
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c
index 168494d2..92118ecf 100644
--- a/sway/commands/workspace.c
+++ b/sway/commands/workspace.c
@@ -21,6 +21,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
21 return NULL; 21 return NULL;
22 } 22 }
23 wsc->workspace = strdup(ws_name); 23 wsc->workspace = strdup(ws_name);
24 wsc->outputs = create_list();
24 wsc->gaps_inner = INT_MIN; 25 wsc->gaps_inner = INT_MIN;
25 wsc->gaps_outer.top = INT_MIN; 26 wsc->gaps_outer.top = INT_MIN;
26 wsc->gaps_outer.right = INT_MIN; 27 wsc->gaps_outer.right = INT_MIN;
@@ -32,7 +33,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
32 33
33void free_workspace_config(struct workspace_config *wsc) { 34void free_workspace_config(struct workspace_config *wsc) {
34 free(wsc->workspace); 35 free(wsc->workspace);
35 free(wsc->output); 36 free_flat_list(wsc->outputs);
36 free(wsc); 37 free(wsc);
37} 38}
38 39
@@ -141,18 +142,20 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
141 } 142 }
142 } 143 }
143 if (output_location >= 0) { 144 if (output_location >= 0) {
144 if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { 145 if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST,
146 output_location + 2))) {
145 return error; 147 return error;
146 } 148 }
147 char *ws_name = join_args(argv, argc - 2); 149 char *ws_name = join_args(argv, output_location);
148 struct workspace_config *wsc = workspace_config_find_or_create(ws_name); 150 struct workspace_config *wsc = workspace_config_find_or_create(ws_name);
149 free(ws_name); 151 free(ws_name);
150 if (!wsc) { 152 if (!wsc) {
151 return cmd_results_new(CMD_FAILURE, "workspace output", 153 return cmd_results_new(CMD_FAILURE, "workspace output",
152 "Unable to allocate workspace output"); 154 "Unable to allocate workspace output");
153 } 155 }
154 free(wsc->output); 156 for (int i = output_location + 1; i < argc; ++i) {
155 wsc->output = strdup(argv[output_location + 1]); 157 list_add(wsc->outputs, strdup(argv[i]));
158 }
156 } else if (gaps_location >= 0) { 159 } else if (gaps_location >= 0) {
157 if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) { 160 if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) {
158 return error; 161 return error;
diff --git a/sway/commands/ws_auto_back_and_forth.c b/sway/commands/ws_auto_back_and_forth.c
index 3449d4cc..adb851c2 100644
--- a/sway/commands/ws_auto_back_and_forth.c
+++ b/sway/commands/ws_auto_back_and_forth.c
@@ -9,6 +9,6 @@ struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) {
9 return error; 9 return error;
10 } 10 }
11 config->auto_back_and_forth = 11 config->auto_back_and_forth =
12 !parse_boolean(argv[0], config->auto_back_and_forth); 12 parse_boolean(argv[0], config->auto_back_and_forth);
13 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 13 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
14} 14}
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index d48ddef3..c53a9c73 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -469,15 +469,6 @@ void output_damage_box(struct sway_output *output, struct wlr_box *_box) {
469 wlr_output_damage_add_box(output->damage, &box); 469 wlr_output_damage_add_box(output->damage, &box);
470} 470}
471 471
472static void output_damage_whole_container_iterator(struct sway_container *con,
473 void *data) {
474 if (!sway_assert(con->view, "expected a view")) {
475 return;
476 }
477 struct sway_output *output = data;
478 output_damage_view(output, con->view, true);
479}
480
481void output_damage_whole_container(struct sway_output *output, 472void output_damage_whole_container(struct sway_output *output,
482 struct sway_container *con) { 473 struct sway_container *con) {
483 // Pad the box by 1px, because the width is a double and might be a fraction 474 // Pad the box by 1px, because the width is a double and might be a fraction
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 4583558c..4d9a87d8 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -12,6 +12,7 @@
12#include "sway/input/seat.h" 12#include "sway/input/seat.h"
13#include <wlr/types/wlr_box.h> 13#include <wlr/types/wlr_box.h>
14#include <wlr/types/wlr_output.h> 14#include <wlr/types/wlr_output.h>
15#include <xkbcommon/xkbcommon.h>
15#include "wlr-layer-shell-unstable-v1-protocol.h" 16#include "wlr-layer-shell-unstable-v1-protocol.h"
16 17
17static const char *ipc_json_layout_description(enum sway_container_layout l) { 18static const char *ipc_json_layout_description(enum sway_container_layout l) {
@@ -503,6 +504,27 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
503 json_object_object_add(object, "type", 504 json_object_object_add(object, "type",
504 json_object_new_string(describe_device_type(device))); 505 json_object_new_string(describe_device_type(device)));
505 506
507 if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) {
508 struct wlr_keyboard *keyboard = device->wlr_device->keyboard;
509 struct xkb_keymap *keymap = keyboard->keymap;
510 struct xkb_state *state = keyboard->xkb_state;
511 xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(keymap);
512 xkb_layout_index_t layout_idx;
513 for (layout_idx = 0; layout_idx < num_layouts; layout_idx++) {
514 bool is_active =
515 xkb_state_layout_index_is_active(state,
516 layout_idx,
517 XKB_STATE_LAYOUT_EFFECTIVE);
518 if (is_active) {
519 const char *layout =
520 xkb_keymap_layout_get_name(keymap, layout_idx);
521 json_object_object_add(object, "xkb_active_layout_name",
522 json_object_new_string(layout));
523 break;
524 }
525 }
526 }
527
506 return object; 528 return object;
507} 529}
508 530
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 8f6b35f1..1a11015f 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -573,8 +573,12 @@ The default colors are:
573 Specifies that workspace _name_ should have the given gaps settings when it 573 Specifies that workspace _name_ should have the given gaps settings when it
574 is created. 574 is created.
575 575
576*workspace* <name> output <output> 576*workspace* <name> output <outputs...>
577 Specifies that workspace _name_ should be shown on the specified _output_. 577 Specifies that workspace _name_ should be shown on the specified _outputs_.
578 Multiple outputs can be listed and the first available will be used. If the
579 workspace gets placed on an output further down the list and an output that
580 is higher on the list becomes available, the workspace will be move to the
581 higher priority output.
578 582
579*workspace\_auto\_back\_and\_forth* yes|no 583*workspace\_auto\_back\_and\_forth* yes|no
580 When _yes_, repeating a workspace switch command will switch back to the 584 When _yes_, repeating a workspace switch command will switch back to the
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 2704920d..3c4614a8 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -31,6 +31,13 @@ static void restore_workspaces(struct sway_output *output) {
31 j--; 31 j--;
32 } 32 }
33 } 33 }
34
35 if (other->workspaces->length == 0) {
36 char *next = workspace_next_name(other->wlr_output->name);
37 struct sway_workspace *ws = workspace_create(other, next);
38 free(next);
39 ipc_event_workspace(NULL, ws, "init");
40 }
34 } 41 }
35 42
36 // Saved workspaces 43 // Saved workspaces
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 93ce50de..4be63311 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -33,14 +33,15 @@ struct workspace_config *workspace_find_config(const char *ws_name) {
33struct sway_output *workspace_get_initial_output(const char *name) { 33struct sway_output *workspace_get_initial_output(const char *name) {
34 // Check workspace configs for a workspace<->output pair 34 // Check workspace configs for a workspace<->output pair
35 struct workspace_config *wsc = workspace_find_config(name); 35 struct workspace_config *wsc = workspace_find_config(name);
36 if (wsc && wsc->output) { 36 if (wsc) {
37 struct sway_output *output = output_by_name(wsc->output); 37 for (int i = 0; i < wsc->outputs->length; i++) {
38 if (!output) { 38 struct sway_output *output = output_by_name(wsc->outputs->items[i]);
39 output = output_by_identifier(wsc->output); 39 if (!output) {
40 } 40 output = output_by_identifier(wsc->outputs->items[i]);
41 41 }
42 if (output) { 42 if (output) {
43 return output; 43 return output;
44 }
44 } 45 }
45 } 46 }
46 // Otherwise put it on the focused output 47 // Otherwise put it on the focused output
@@ -85,7 +86,6 @@ struct sway_workspace *workspace_create(struct sway_output *output,
85 ws->floating = create_list(); 86 ws->floating = create_list();
86 ws->tiling = create_list(); 87 ws->tiling = create_list();
87 ws->output_priority = create_list(); 88 ws->output_priority = create_list();
88 workspace_output_add_priority(ws, output);
89 89
90 ws->gaps_outer = config->gaps_outer; 90 ws->gaps_outer = config->gaps_outer;
91 ws->gaps_inner = config->gaps_inner; 91 ws->gaps_inner = config->gaps_inner;
@@ -110,9 +110,17 @@ struct sway_workspace *workspace_create(struct sway_output *output,
110 // Since default outer gaps can be smaller than the negation of 110 // Since default outer gaps can be smaller than the negation of
111 // workspace specific inner gaps, check outer gaps again 111 // workspace specific inner gaps, check outer gaps again
112 prevent_invalid_outer_gaps(ws); 112 prevent_invalid_outer_gaps(ws);
113
114 // Add output priorities
115 for (int i = 0; i < wsc->outputs->length; ++i) {
116 list_add(ws->output_priority, strdup(wsc->outputs->items[i]));
117 }
113 } 118 }
114 } 119 }
115 120
121 // If not already added, add the output to the lowest priority
122 workspace_output_add_priority(ws, output);
123
116 output_add_workspace(output, ws); 124 output_add_workspace(output, ws);
117 output_sort_workspaces(output); 125 output_sort_workspaces(output);
118 126
@@ -134,8 +142,7 @@ void workspace_destroy(struct sway_workspace *workspace) {
134 142
135 free(workspace->name); 143 free(workspace->name);
136 free(workspace->representation); 144 free(workspace->representation);
137 list_foreach(workspace->output_priority, free); 145 free_flat_list(workspace->output_priority);
138 list_free(workspace->output_priority);
139 list_free(workspace->floating); 146 list_free(workspace->floating);
140 list_free(workspace->tiling); 147 list_free(workspace->tiling);
141 list_free(workspace->current.floating); 148 list_free(workspace->current.floating);
@@ -177,8 +184,19 @@ static bool workspace_valid_on_output(const char *output_name,
177 char identifier[128]; 184 char identifier[128];
178 struct sway_output *output = output_by_name(output_name); 185 struct sway_output *output = output_by_name(output_name);
179 output_get_identifier(identifier, sizeof(identifier), output); 186 output_get_identifier(identifier, sizeof(identifier), output);
180 187
181 return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0 || strcasecmp(identifier, output_name) == 0; 188 if (!wsc) {
189 return true;
190 }
191
192 for (int i = 0; i < wsc->outputs->length; i++) {
193 if (strcmp(wsc->outputs->items[i], output_name) == 0 ||
194 strcmp(wsc->outputs->items[i], identifier) == 0) {
195 return true;
196 }
197 }
198
199 return false;
182} 200}
183 201
184static void workspace_name_from_binding(const struct sway_binding * binding, 202static void workspace_name_from_binding(const struct sway_binding * binding,
@@ -281,10 +299,19 @@ char *workspace_next_name(const char *output_name) {
281 for (int i = 0; i < config->workspace_configs->length; ++i) { 299 for (int i = 0; i < config->workspace_configs->length; ++i) {
282 // Unlike with bindings, this does not guarantee order 300 // Unlike with bindings, this does not guarantee order
283 const struct workspace_config *wsc = config->workspace_configs->items[i]; 301 const struct workspace_config *wsc = config->workspace_configs->items[i];
284 if (wsc->output && strcmp(wsc->output, output_name) == 0 302 if (workspace_by_name(wsc->workspace)) {
285 && workspace_by_name(wsc->workspace) == NULL) { 303 continue;
286 free(target); 304 }
287 target = strdup(wsc->workspace); 305 bool found = false;
306 for (int j = 0; j < wsc->outputs->length; ++j) {
307 if (strcmp(wsc->outputs->items[j], output_name) == 0) {
308 found = true;
309 free(target);
310 target = strdup(wsc->workspace);
311 break;
312 }
313 }
314 if (found) {
288 break; 315 break;
289 } 316 }
290 } 317 }
diff --git a/swaymsg/main.c b/swaymsg/main.c
index 663518f6..243b5fdc 100644
--- a/swaymsg/main.c
+++ b/swaymsg/main.c
@@ -111,7 +111,7 @@ static const char *pretty_type_name(const char *name) {
111} 111}
112 112
113static void pretty_print_input(json_object *i) { 113static void pretty_print_input(json_object *i) {
114 json_object *id, *name, *type, *product, *vendor; 114 json_object *id, *name, *type, *product, *vendor, *kbdlayout;
115 json_object_object_get_ex(i, "identifier", &id); 115 json_object_object_get_ex(i, "identifier", &id);
116 json_object_object_get_ex(i, "name", &name); 116 json_object_object_get_ex(i, "name", &name);
117 json_object_object_get_ex(i, "type", &type); 117 json_object_object_get_ex(i, "type", &type);
@@ -123,7 +123,7 @@ static void pretty_print_input(json_object *i) {
123 " Type: %s\n" 123 " Type: %s\n"
124 " Identifier: %s\n" 124 " Identifier: %s\n"
125 " Product ID: %d\n" 125 " Product ID: %d\n"
126 " Vendor ID: %d\n\n"; 126 " Vendor ID: %d\n";
127 127
128 128
129 printf(fmt, json_object_get_string(name), 129 printf(fmt, json_object_get_string(name),
@@ -131,6 +131,13 @@ static void pretty_print_input(json_object *i) {
131 json_object_get_string(id), 131 json_object_get_string(id),
132 json_object_get_int(product), 132 json_object_get_int(product),
133 json_object_get_int(vendor)); 133 json_object_get_int(vendor));
134
135 if (json_object_object_get_ex(i, "xkb_active_layout_name", &kbdlayout)) {
136 printf(" Active Keyboard Layout: %s\n",
137 json_object_get_string(kbdlayout));
138 }
139
140 printf("\n");
134} 141}
135 142
136static void pretty_print_seat(json_object *i) { 143static void pretty_print_seat(json_object *i) {