diff --git a/include/sway/config.h b/include/sway/config.h index 7146623e..bf047d40 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -398,7 +398,7 @@ struct seat_attachment_config *seat_config_get_attachment( void apply_seat_config(struct seat_config *seat); int output_name_cmp(const void *item, const void *data); -struct output_config *new_output_config(); +struct output_config *new_output_config(const char *name); void merge_output_config(struct output_config *dst, struct output_config *src); void apply_output_config(struct output_config *oc, swayc_t *output); void free_output_config(struct output_config *oc); diff --git a/sway/commands/output.c b/sway/commands/output.c index 7988e3e4..8cc74bcc 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -20,253 +20,260 @@ static char *bg_options[] = { "tile", }; +static struct cmd_results *cmd_output_mode(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", "Missing mode argument."); + } + + char *end; + output->width = strtol(argv[*i], &end, 10); + if (*end) { + // Format is 1234x4321 + if (*end != 'x') { + return cmd_results_new(CMD_INVALID, "output", + "Invalid mode width."); + } + ++end; + output->height = strtol(end, &end, 10); + if (*end) { + if (*end != '@') { + return cmd_results_new(CMD_INVALID, "output", + "Invalid mode height."); + } + ++end; + output->refresh_rate = strtof(end, &end); + if (strcasecmp("Hz", end) != 0) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid mode refresh rate."); + } + } + } else { + // Format is 1234 4321 + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing mode argument (height)."); + } + output->height = strtol(argv[*i], &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid mode height."); + } + } + + return NULL; +} + +static struct cmd_results *cmd_output_position(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing position argument."); + } + + char *end; + output->x = strtol(argv[*i], &end, 10); + if (*end) { + // Format is 1234,4321 + if (*end != ',') { + return cmd_results_new(CMD_INVALID, "output", + "Invalid position x."); + } + ++end; + output->y = strtol(end, &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid position y."); + } + } else { + // Format is 1234 4321 (legacy) + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing position argument (y)."); + } + output->y = strtol(argv[*i], &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid position y."); + } + } + + return NULL; +} + +static struct cmd_results *cmd_output_scale(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing scale argument."); + } + + char *end; + output->scale = strtof(argv[*i], &end); + if (*end) { + return cmd_results_new(CMD_INVALID, "output", "Invalid scale."); + } + + return NULL; +} + +static struct cmd_results *cmd_output_transform(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing transform argument."); + } + + char *value = argv[*i]; + if (strcmp(value, "normal") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + } else if (strcmp(value, "90") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_90; + } else if (strcmp(value, "180") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_180; + } else if (strcmp(value, "270") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_270; + } else if (strcmp(value, "flipped") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; + } else if (strcmp(value, "flipped-90") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; + } else if (strcmp(value, "flipped-180") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; + } else if (strcmp(value, "flipped-270") == 0) { + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; + } else { + return cmd_results_new(CMD_INVALID, "output", + "Invalid output transform."); + } + + return NULL; +} + +static struct cmd_results *cmd_output_background(struct output_config *output, + int *i, int argc, char **argv) { + if (++*i >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing background file or color specification."); + } + const char *background = argv[*i]; + if (*i + 1 >= argc) { + return cmd_results_new(CMD_INVALID, "output", + "Missing background scaling mode or `solid_color`."); + } + const char *background_option = argv[*i]; + + if (strcasecmp(background_option, "solid_color") == 0) { + output->background = strdup(background); + output->background_option = strdup("solid_color"); + } else { + bool valid = false; + char *mode; + size_t j; + for (j = 0; j < (size_t)(argc - *i); ++j) { + mode = argv[*i + j]; + size_t n = sizeof(bg_options) / sizeof(char *); + for (size_t k = 0; k < n; ++k) { + if (strcasecmp(mode, bg_options[k]) == 0) { + valid = true; + break; + } + } + if (valid) { + break; + } + } + if (!valid) { + return cmd_results_new(CMD_INVALID, "output", + "Missing background scaling mode."); + } + + wordexp_t p; + char *src = join_args(argv + *i - 1, j); + if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { + return cmd_results_new(CMD_INVALID, "output", + "Invalid syntax (%s).", src); + } + free(src); + src = p.we_wordv[0]; + if (config->reading && *src != '/') { + char *conf = strdup(config->current_config); + if (conf) { + char *conf_path = dirname(conf); + src = malloc(strlen(conf_path) + strlen(src) + 2); + if (src) { + sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); + } else { + sway_log(L_ERROR, + "Unable to allocate background source"); + } + free(conf); + } else { + sway_log(L_ERROR, "Unable to allocate background source"); + } + } + if (!src || access(src, F_OK) == -1) { + wordfree(&p); + return cmd_results_new(CMD_INVALID, "output", + "Background file unreadable (%s).", src); + } + + output->background = strdup(src); + output->background_option = strdup(mode); + if (src != p.we_wordv[0]) { + free(src); + } + wordfree(&p); + + *i += j; + } + + return NULL; +} + struct cmd_results *cmd_output(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) { return error; } - const char *name = argv[0]; - struct output_config *output = new_output_config(); + struct output_config *output = new_output_config(argv[0]); if (!output) { sway_log(L_ERROR, "Failed to allocate output config"); return NULL; } - output->name = strdup(name); - int i; - for (i = 1; i < argc; ++i) { + for (int i = 1; i < argc; ++i) { const char *command = argv[i]; - if (strcasecmp(command, "disable") == 0) { + if (strcasecmp(command, "enable") == 0) { + output->enabled = 1; + } else if (strcasecmp(command, "disable") == 0) { output->enabled = 0; } else if (strcasecmp(command, "mode") == 0 || strcasecmp(command, "resolution") == 0 || strcasecmp(command, "res") == 0) { - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing mode argument."); - goto fail; - } - - int width = -1, height = -1; - float refresh_rate = -1; - - char *end; - width = strtol(argv[i], &end, 10); - if (*end) { - // Format is 1234x4321 - if (*end != 'x') { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid mode width."); - goto fail; - } - ++end; - height = strtol(end, &end, 10); - if (*end) { - if (*end != '@') { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid mode height."); - goto fail; - } - ++end; - refresh_rate = strtof(end, &end); - if (strcasecmp("Hz", end) != 0) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid mode refresh rate."); - goto fail; - } - } - } else { - // Format is 1234 4321 - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing mode argument (height)."); - goto fail; - } - height = strtol(argv[i], &end, 10); - if (*end) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid mode height."); - goto fail; - } - } - output->width = width; - output->height = height; - output->refresh_rate = refresh_rate; + error = cmd_output_mode(output, &i, argc, argv); } else if (strcasecmp(command, "position") == 0 || strcasecmp(command, "pos") == 0) { - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing position argument."); - goto fail; - } - - int x = -1, y = -1; - - char *end; - x = strtol(argv[i], &end, 10); - if (*end) { - // Format is 1234,4321 - if (*end != ',') { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid position x."); - goto fail; - } - ++end; - y = strtol(end, &end, 10); - if (*end) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid position y."); - goto fail; - } - } else { - // Format is 1234 4321 (legacy) - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing position argument (y)."); - goto fail; - } - y = strtol(argv[i], &end, 10); - if (*end) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid position y."); - goto fail; - } - } - - output->x = x; - output->y = y; + error = cmd_output_position(output, &i, argc, argv); } else if (strcasecmp(command, "scale") == 0) { - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing scale parameter."); - goto fail; - } - char *end; - output->scale = strtof(argv[i], &end); - if (*end) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid scale."); - goto fail; - } + error = cmd_output_scale(output, &i, argc, argv); } else if (strcasecmp(command, "transform") == 0) { - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing transform parameter."); - goto fail; - } - char *value = argv[i]; - if (strcmp(value, "normal") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_NORMAL; - } else if (strcmp(value, "90") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_90; - } else if (strcmp(value, "180") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_180; - } else if (strcmp(value, "270") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_270; - } else if (strcmp(value, "flipped") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; - } else if (strcmp(value, "flipped-90") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; - } else if (strcmp(value, "flipped-180") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; - } else if (strcmp(value, "flipped-270") == 0) { - output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; - } else { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid output transform."); - goto fail; - } + error = cmd_output_transform(output, &i, argc, argv); } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) { - wordexp_t p; - if (++i >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing background file or color specification."); - goto fail; - } - if (i + 1 >= argc) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing background scaling mode or `solid_color`."); - goto fail; - } - if (strcasecmp(argv[i + 1], "solid_color") == 0) { - output->background = strdup(argv[argc - 2]); - output->background_option = strdup("solid_color"); - } else { - // argv[i+j]=bg_option - bool valid = false; - char *mode; - size_t j; - for (j = 0; j < (size_t) (argc - i); ++j) { - mode = argv[i + j]; - size_t n = sizeof(bg_options) / sizeof(char *); - for (size_t k = 0; k < n; ++k) { - if (strcasecmp(mode, bg_options[k]) == 0) { - valid = true; - break; - } - } - if (valid) { - break; - } - } - if (!valid) { - error = cmd_results_new(CMD_INVALID, "output", - "Missing background scaling mode."); - goto fail; - } - - char *src = join_args(argv + i, j); - if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { - error = cmd_results_new(CMD_INVALID, "output", - "Invalid syntax (%s).", src); - goto fail; - } - free(src); - src = p.we_wordv[0]; - if (config->reading && *src != '/') { - char *conf = strdup(config->current_config); - if (conf) { - char *conf_path = dirname(conf); - src = malloc(strlen(conf_path) + strlen(src) + 2); - if (src) { - sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); - } else { - sway_log(L_ERROR, - "Unable to allocate background source"); - } - free(conf); - } else { - sway_log(L_ERROR, - "Unable to allocate background source"); - } - } - if (!src || access(src, F_OK) == -1) { - error = cmd_results_new(CMD_INVALID, "output", - "Background file unreadable (%s).", src); - wordfree(&p); - goto fail; - } - - output->background = strdup(src); - output->background_option = strdup(mode); - if (src != p.we_wordv[0]) { - free(src); - } - wordfree(&p); - - i += j; - } + error = cmd_output_background(output, &i, argc, argv); } else { error = cmd_results_new(CMD_INVALID, "output", "Invalid output subcommand: %s.", command); + } + + if (error != NULL) { goto fail; } } - i = list_seq_find(config->output_configs, output_name_cmp, name); + int i = list_seq_find(config->output_configs, output_name_cmp, output->name); if (i >= 0) { // merge existing config struct output_config *oc = config->output_configs->items[i]; diff --git a/sway/config/output.c b/sway/config/output.c index ff3f73a3..f336c949 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -14,11 +14,16 @@ int output_name_cmp(const void *item, const void *data) { return strcmp(output->name, name); } -struct output_config *new_output_config() { +struct output_config *new_output_config(const char *name) { struct output_config *oc = calloc(1, sizeof(struct output_config)); if (oc == NULL) { return NULL; } + oc->name = strdup(name); + if (oc->name == NULL) { + free(oc); + return NULL; + } oc->enabled = -1; oc->width = oc->height = -1; oc->refresh_rate = -1; diff --git a/sway/main.c b/sway/main.c index bd69395a..c18e2677 100644 --- a/sway/main.c +++ b/sway/main.c @@ -15,12 +15,12 @@ #include #include #endif +#include #include "sway/config.h" #include "sway/server.h" #include "sway/layout.h" #include "sway/ipc-server.h" #include "ipc-client.h" -#include "log.h" #include "readline.h" #include "stringop.h" #include "util.h" @@ -126,7 +126,7 @@ static void log_env() { "SWAYSOCK" }; for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { - sway_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); + wlr_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); } } @@ -141,14 +141,14 @@ static void log_distro() { for (size_t i = 0; i < sizeof(paths) / sizeof(char *); ++i) { FILE *f = fopen(paths[i], "r"); if (f) { - sway_log(L_INFO, "Contents of %s:", paths[i]); + wlr_log(L_INFO, "Contents of %s:", paths[i]); while (!feof(f)) { char *line; if (!(line = read_line(f))) { break; } if (*line) { - sway_log(L_INFO, "%s", line); + wlr_log(L_INFO, "%s", line); } free(line); } @@ -161,7 +161,7 @@ static void log_kernel() { return; FILE *f = popen("uname -a", "r"); if (!f) { - sway_log(L_INFO, "Unable to determine kernel version"); + wlr_log(L_INFO, "Unable to determine kernel version"); return; } while (!feof(f)) { @@ -170,7 +170,7 @@ static void log_kernel() { break; } if (*line) { - sway_log(L_INFO, "%s", line); + wlr_log(L_INFO, "%s", line); } free(line); } @@ -181,14 +181,14 @@ static void security_sanity_check() { // TODO: Notify users visually if this has issues struct stat s; if (stat("/proc", &s)) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "!! DANGER !! /proc is not available - sway CANNOT enforce security rules!"); } #ifdef __linux__ cap_flag_value_t v; cap_t cap = cap_get_proc(); if (!cap || cap_get_flag(cap, CAP_SYS_PTRACE, CAP_PERMITTED, &v) != 0 || v != CAP_SET) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "!! DANGER !! Sway does not have CAP_SYS_PTRACE and cannot enforce security rules for processes running as other users."); } if (cap) { @@ -204,13 +204,13 @@ static void executable_sanity_check() { stat(exe, &sb); // We assume that cap_get_file returning NULL implies ENODATA if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "sway executable has both the s(g)uid bit AND file caps set."); - sway_log(L_ERROR, + wlr_log(L_ERROR, "This is strongly discouraged (and completely broken)."); - sway_log(L_ERROR, + wlr_log(L_ERROR, "Please clear one of them (either the suid bit, or the file caps)."); - sway_log(L_ERROR, + wlr_log(L_ERROR, "If unsure, strip the file caps."); exit(EXIT_FAILURE); } @@ -221,16 +221,16 @@ static void executable_sanity_check() { static void drop_permissions(bool keep_caps) { if (getuid() != geteuid() || getgid() != getegid()) { if (setgid(getgid()) != 0) { - sway_log(L_ERROR, "Unable to drop root"); + wlr_log(L_ERROR, "Unable to drop root"); exit(EXIT_FAILURE); } if (setuid(getuid()) != 0) { - sway_log(L_ERROR, "Unable to drop root"); + wlr_log(L_ERROR, "Unable to drop root"); exit(EXIT_FAILURE); } } if (setuid(0) != -1) { - sway_log(L_ERROR, "Root privileges can be restored."); + wlr_log(L_ERROR, "Root privileges can be restored."); exit(EXIT_FAILURE); } #ifdef __linux__ @@ -238,11 +238,11 @@ static void drop_permissions(bool keep_caps) { // Drop every cap except CAP_SYS_PTRACE cap_t caps = cap_init(); cap_value_t keep = CAP_SYS_PTRACE; - sway_log(L_INFO, "Dropping extra capabilities"); + wlr_log(L_INFO, "Dropping extra capabilities"); if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || cap_set_proc(caps)) { - sway_log(L_ERROR, "Failed to drop extra capabilities"); + wlr_log(L_ERROR, "Failed to drop extra capabilities"); exit(EXIT_FAILURE); } } @@ -330,22 +330,22 @@ int main(int argc, char **argv) { // TODO: switch logging over to wlroots? if (debug) { - init_log(L_DEBUG); + wlr_log_init(L_DEBUG, NULL); } else if (verbose || validate) { - init_log(L_INFO); + wlr_log_init(L_INFO, NULL); } else { - init_log(L_ERROR); + wlr_log_init(L_ERROR, NULL); } if (optind < argc) { // Behave as IPC client if(optind != 1) { - sway_log(L_ERROR, "Don't use options with the IPC client"); + wlr_log(L_ERROR, "Don't use options with the IPC client"); exit(EXIT_FAILURE); } drop_permissions(false); char *socket_path = getenv("SWAYSOCK"); if (!socket_path) { - sway_log(L_ERROR, "Unable to retrieve socket path"); + wlr_log(L_ERROR, "Unable to retrieve socket path"); exit(EXIT_FAILURE); } char *command = join_args(argv + optind, argc - optind); @@ -359,7 +359,7 @@ int main(int argc, char **argv) { if (getuid() != geteuid() || getgid() != getegid()) { // Retain capabilities after setuid() if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { - sway_log(L_ERROR, "Cannot keep caps after setuid()"); + wlr_log(L_ERROR, "Cannot keep caps after setuid()"); exit(EXIT_FAILURE); } suid = true; @@ -380,7 +380,7 @@ int main(int argc, char **argv) { // prevent ipc from crashing sway signal(SIGPIPE, SIG_IGN); - sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); + wlr_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); init_layout(); diff --git a/sway/server.c b/sway/server.c index 32c8f03c..365094ef 100644 --- a/sway/server.c +++ b/sway/server.c @@ -10,12 +10,12 @@ #include // TODO WLR: make Xwayland optional #include +#include #include "sway/server.h" #include "sway/input/input-manager.h" -#include "log.h" bool server_init(struct sway_server *server) { - sway_log(L_DEBUG, "Initializing Wayland server"); + wlr_log(L_DEBUG, "Initializing Wayland server"); server->wl_display = wl_display_create(); server->wl_event_loop = wl_display_get_event_loop(server->wl_display); @@ -55,7 +55,8 @@ bool server_init(struct sway_server *server) { server->wl_shell_surface.notify = handle_wl_shell_surface; server->socket = wl_display_add_socket_auto(server->wl_display); - if (!sway_assert(server->socket, "Unable to open wayland socket")) { + if (!server->socket) { + wlr_log(L_ERROR, "Unable to open wayland socket"); wlr_backend_destroy(server->backend); return false; } @@ -71,11 +72,11 @@ void server_fini(struct sway_server *server) { } void server_run(struct sway_server *server) { - sway_log(L_INFO, "Running compositor on wayland display '%s'", + wlr_log(L_INFO, "Running compositor on wayland display '%s'", server->socket); setenv("_WAYLAND_DISPLAY", server->socket, true); - if (!sway_assert(wlr_backend_start(server->backend), - "Failed to start backend")) { + if (!wlr_backend_start(server->backend)) { + wlr_log(L_ERROR, "Failed to start backend"); wlr_backend_destroy(server->backend); return; } diff --git a/swaymsg/main.c b/swaymsg/main.c index b431872a..8a720fca 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -107,29 +107,42 @@ static void pretty_print_input(json_object *i) { } static void pretty_print_output(json_object *o) { - json_object *name, *rect, *focused, *active, *ws, *scale; + json_object *name, *rect, *focused, *active, *ws; json_object_object_get_ex(o, "name", &name); json_object_object_get_ex(o, "rect", &rect); json_object_object_get_ex(o, "focused", &focused); json_object_object_get_ex(o, "active", &active); json_object_object_get_ex(o, "current_workspace", &ws); + json_object *make, *model, *serial, *scale, *refresh, *transform; + json_object_object_get_ex(o, "make", &make); + json_object_object_get_ex(o, "model", &model); + json_object_object_get_ex(o, "serial", &serial); json_object_object_get_ex(o, "scale", &scale); + json_object_object_get_ex(o, "refresh", &refresh); + json_object_object_get_ex(o, "transform", &transform); json_object *x, *y, *width, *height; json_object_object_get_ex(rect, "x", &x); json_object_object_get_ex(rect, "y", &y); json_object_object_get_ex(rect, "width", &width); json_object_object_get_ex(rect, "height", &height); printf( - "Output %s%s%s\n" - " Geometry: %dx%d @ %d,%d\n" + "Output %s '%s %s %s'%s%s\n" + " Mode: %dx%d @ %f Hz\n" + " Position: %d,%d\n" " Scale factor: %dx\n" + " Transform: %s\n" " Workspace: %s\n\n", json_object_get_string(name), + json_object_get_string(make), + json_object_get_string(model), + json_object_get_string(serial), json_object_get_boolean(focused) ? " (focused)" : "", !json_object_get_boolean(active) ? " (inactive)" : "", json_object_get_int(width), json_object_get_int(height), + (float)json_object_get_int(refresh) / 1000, json_object_get_int(x), json_object_get_int(y), json_object_get_int(scale), + json_object_get_string(transform), json_object_get_string(ws) ); }