ipc: remove extraneous properties from get_outputs reply

The GET_OUTPUTS IPC reply was including many tree/node properties
(id, type, orientation, percent, urgent, marks, layout, border,
current_border_width, deco_rect, window_rect, geometry, window,
nodes, floating_nodes, focus, fullscreen_mode, sticky, floating,
scratchpad_state) that are only meaningful for containers in
GET_TREE, not for outputs.

Create a dedicated function for building the GET_OUTPUTS reply that
only includes the documented output-specific fields (name, make,
model, serial, active, dpms, power, primary, scale, transform,
current_workspace, modes, current_mode, rect, hdr) plus sway-specific
output configuration fields (scale_filter, adaptive_sync_status,
max_render_time, allow_tearing, non_desktop, features, focused,
subpixel_hinting).

This improves i3 IPC compatibility and reduces reply size.

Fixes: https://github.com/swaywm/sway/issues/2685
This commit is contained in:
claude-bot 2026-02-07 21:32:35 -05:00
parent 845cdb190f
commit 37454c0cac
3 changed files with 97 additions and 6 deletions

View file

@ -11,6 +11,7 @@ json_object *ipc_json_get_binding_mode(void);
json_object *ipc_json_describe_disabled_output(struct sway_output *o); json_object *ipc_json_describe_disabled_output(struct sway_output *o);
json_object *ipc_json_describe_non_desktop_output(struct sway_output_non_desktop *o); json_object *ipc_json_describe_non_desktop_output(struct sway_output_non_desktop *o);
json_object *ipc_json_describe_enabled_output_ipc(struct sway_output *output);
json_object *ipc_json_describe_node(struct sway_node *node); json_object *ipc_json_describe_node(struct sway_node *node);
json_object *ipc_json_describe_node_recursive(struct sway_node *node); json_object *ipc_json_describe_node_recursive(struct sway_node *node);
json_object *ipc_json_describe_input(struct sway_input_device *device); json_object *ipc_json_describe_input(struct sway_input_device *device);

View file

@ -456,6 +456,96 @@ json_object *ipc_json_describe_non_desktop_output(struct sway_output_non_desktop
return object; return object;
} }
json_object *ipc_json_describe_enabled_output_ipc(struct sway_output *output) {
struct wlr_output *wlr_output = output->wlr_output;
json_object *object = json_object_new_object();
// i3-compatible fields
json_object_object_add(object, "name",
json_object_new_string(wlr_output->name));
json_object_object_add(object, "active", json_object_new_boolean(true));
json_object_object_add(object, "primary", json_object_new_boolean(false));
struct wlr_box box;
output_get_box(output, &box);
json_object_object_add(object, "rect", ipc_json_create_rect(&box));
struct sway_workspace *ws = output_get_active_workspace(output);
if (ws) {
json_object_object_add(object, "current_workspace",
json_object_new_string(ws->name));
} else {
json_object_object_add(object, "current_workspace", NULL);
}
// Sway-specific fields for output configuration
json_object_object_add(object, "non_desktop", json_object_new_boolean(false));
json_object_object_add(object, "make",
json_object_new_string(wlr_output->make ? wlr_output->make : "Unknown"));
json_object_object_add(object, "model",
json_object_new_string(wlr_output->model ? wlr_output->model : "Unknown"));
json_object_object_add(object, "serial",
json_object_new_string(wlr_output->serial ? wlr_output->serial : "Unknown"));
json_object_object_add(object, "dpms",
json_object_new_boolean(wlr_output->enabled));
json_object_object_add(object, "power",
json_object_new_boolean(wlr_output->enabled));
json_object_object_add(object, "scale",
json_object_new_double(wlr_output->scale));
json_object_object_add(object, "scale_filter",
json_object_new_string(
sway_output_scale_filter_to_string(output->scale_filter)));
json_object_object_add(object, "transform",
json_object_new_string(
ipc_json_output_transform_description(wlr_output->transform)));
json_object_object_add(object, "adaptive_sync_status",
json_object_new_string(
ipc_json_output_adaptive_sync_status_description(
wlr_output->adaptive_sync_status)));
json_object_object_add(object, "max_render_time",
json_object_new_int(output->max_render_time));
json_object_object_add(object, "allow_tearing",
json_object_new_boolean(output->allow_tearing));
json_object_object_add(object, "hdr",
json_object_new_boolean(output->hdr));
// Modes
json_object *modes_array = json_object_new_array();
struct wlr_output_mode *mode;
wl_list_for_each(mode, &wlr_output->modes, link) {
json_object *mode_object = ipc_json_output_mode_description(mode);
json_object_array_add(modes_array, mode_object);
}
json_object_object_add(object, "modes", modes_array);
json_object *current_mode_object;
if (wlr_output->current_mode != NULL) {
current_mode_object =
ipc_json_output_mode_description(wlr_output->current_mode);
} else {
current_mode_object = json_object_new_object();
json_object_object_add(current_mode_object, "width",
json_object_new_int(wlr_output->width));
json_object_object_add(current_mode_object, "height",
json_object_new_int(wlr_output->height));
json_object_object_add(current_mode_object, "refresh",
json_object_new_int(wlr_output->refresh));
}
json_object_object_add(object, "current_mode", current_mode_object);
// Features
json_object *features_object = json_object_new_object();
json_object_object_add(features_object, "adaptive_sync",
json_object_new_boolean(wlr_output->adaptive_sync_supported ||
wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED));
json_object_object_add(features_object, "hdr",
json_object_new_boolean(output_supports_hdr(wlr_output, NULL)));
json_object_object_add(object, "features", features_object);
return object;
}
static json_object *ipc_json_describe_scratchpad_output(void) { static json_object *ipc_json_describe_scratchpad_output(void) {
struct wlr_box box; struct wlr_box box;
root_get_box(root, &box); root_get_box(root, &box);

View file

@ -680,20 +680,20 @@ void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_lengt
json_object *outputs = json_object_new_array(); json_object *outputs = json_object_new_array();
for (int i = 0; i < root->outputs->length; ++i) { for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i]; struct sway_output *output = root->outputs->items[i];
json_object *output_json = ipc_json_describe_node(&output->node); json_object *output_json =
ipc_json_describe_enabled_output_ipc(output);
// override the default focused indicator because it's set
// differently for the get_outputs reply
struct sway_seat *seat = input_manager_get_default_seat(); struct sway_seat *seat = input_manager_get_default_seat();
struct sway_workspace *focused_ws = struct sway_workspace *focused_ws =
seat_get_focused_workspace(seat); seat_get_focused_workspace(seat);
bool focused = focused_ws && output == focused_ws->output; bool focused = focused_ws && output == focused_ws->output;
json_object_object_del(output_json, "focused");
json_object_object_add(output_json, "focused", json_object_object_add(output_json, "focused",
json_object_new_boolean(focused)); json_object_new_boolean(focused));
const char *subpixel = sway_wl_output_subpixel_to_string(output->wlr_output->subpixel); const char *subpixel =
json_object_object_add(output_json, "subpixel_hinting", json_object_new_string(subpixel)); sway_wl_output_subpixel_to_string(output->wlr_output->subpixel);
json_object_object_add(output_json, "subpixel_hinting",
json_object_new_string(subpixel));
json_object_array_add(outputs, output_json); json_object_array_add(outputs, output_json);
} }
struct sway_output *output; struct sway_output *output;