feat(ipc): add 'get cursorpos' and 'get option <name>' queries

This commit is contained in:
Ernesto Cruz 2026-06-20 00:23:54 +01:00
parent 8e356692f6
commit fa4f144b9d
5 changed files with 276 additions and 0 deletions

View file

@ -1,3 +1,4 @@
#include <cjson/cJSON.h>
#include <ctype.h>
#include <libgen.h>
#include <stdbool.h>
@ -3016,6 +3017,244 @@ bool parse_option(Config *config, char *key, char *value) {
return true;
}
static cJSON *ipc_color_to_hex(const float c[4]) {
unsigned r = (unsigned)(c[0] * 255.0f + 0.5f);
unsigned g = (unsigned)(c[1] * 255.0f + 0.5f);
unsigned b = (unsigned)(c[2] * 255.0f + 0.5f);
unsigned a = (unsigned)(c[3] * 255.0f + 0.5f);
char buf[11];
snprintf(buf, sizeof(buf), "0x%02X%02X%02X%02X", r, g, b, a);
return cJSON_CreateString(buf);
}
static cJSON *ipc_curve_to_json(const double v[4]) {
cJSON *arr = cJSON_CreateArray();
for (int i = 0; i < 4; i++)
cJSON_AddItemToArray(arr, cJSON_CreateNumber(v[i]));
return arr;
}
cJSON *read_option(Config *config, const char *key) {
#define OPT_NUM(k, f) \
if (strcmp(key, k) == 0) \
return cJSON_CreateNumber(config->f)
#define OPT_STR(k, f) \
if (strcmp(key, k) == 0) \
return cJSON_CreateString(config->f)
#define OPT_STRP(k, f) \
if (strcmp(key, k) == 0) \
return config->f ? cJSON_CreateString(config->f) : cJSON_CreateNull()
#define OPT_COLOR(k, f) \
if (strcmp(key, k) == 0) \
return ipc_color_to_hex(config->f)
#define OPT_CURVE(k, f) \
if (strcmp(key, k) == 0) \
return ipc_curve_to_json(config->f)
OPT_STR("keymode", keymode);
OPT_NUM("animations", animations);
OPT_NUM("layer_animations", layer_animations);
OPT_STR("animation_type_open", animation_type_open);
OPT_STR("animation_type_close", animation_type_close);
OPT_STR("layer_animation_type_open", layer_animation_type_open);
OPT_STR("layer_animation_type_close", layer_animation_type_close);
OPT_NUM("animation_fade_in", animation_fade_in);
OPT_NUM("animation_fade_out", animation_fade_out);
OPT_NUM("tag_animation_direction", tag_animation_direction);
OPT_NUM("zoom_initial_ratio", zoom_initial_ratio);
OPT_NUM("zoom_end_ratio", zoom_end_ratio);
OPT_NUM("fadein_begin_opacity", fadein_begin_opacity);
OPT_NUM("fadeout_begin_opacity", fadeout_begin_opacity);
OPT_NUM("animation_duration_move", animation_duration_move);
OPT_NUM("animation_duration_open", animation_duration_open);
OPT_NUM("animation_duration_tag", animation_duration_tag);
OPT_NUM("animation_duration_close", animation_duration_close);
OPT_NUM("animation_duration_focus", animation_duration_focus);
OPT_CURVE("animation_curve_move", animation_curve_move);
OPT_CURVE("animation_curve_open", animation_curve_open);
OPT_CURVE("animation_curve_tag", animation_curve_tag);
OPT_CURVE("animation_curve_close", animation_curve_close);
OPT_CURVE("animation_curve_focus", animation_curve_focus);
OPT_CURVE("animation_curve_opafadein", animation_curve_opafadein);
OPT_CURVE("animation_curve_opafadeout", animation_curve_opafadeout);
OPT_NUM("scroller_structs", scroller_structs);
OPT_NUM("scroller_default_proportion", scroller_default_proportion);
OPT_NUM("scroller_default_proportion_single",
scroller_default_proportion_single);
OPT_NUM("scroller_ignore_proportion_single",
scroller_ignore_proportion_single);
OPT_NUM("scroller_focus_center", scroller_focus_center);
OPT_NUM("scroller_prefer_center", scroller_prefer_center);
OPT_NUM("scroller_prefer_overspread", scroller_prefer_overspread);
OPT_NUM("edge_scroller_pointer_focus", edge_scroller_pointer_focus);
OPT_NUM("edge_scroller_focus_allow_speed", edge_scroller_focus_allow_speed);
OPT_NUM("focus_cross_monitor", focus_cross_monitor);
OPT_NUM("exchange_cross_monitor", exchange_cross_monitor);
OPT_NUM("scratchpad_cross_monitor", scratchpad_cross_monitor);
OPT_NUM("focus_cross_tag", focus_cross_tag);
OPT_NUM("view_current_to_back", view_current_to_back);
OPT_NUM("blur", blur);
OPT_NUM("blur_layer", blur_layer);
OPT_NUM("blur_optimized", blur_optimized);
OPT_NUM("border_radius", border_radius);
OPT_NUM("blur_params_num_passes", blur_params.num_passes);
OPT_NUM("blur_params_radius", blur_params.radius);
OPT_NUM("blur_params_noise", blur_params.noise);
OPT_NUM("blur_params_brightness", blur_params.brightness);
OPT_NUM("blur_params_contrast", blur_params.contrast);
OPT_NUM("blur_params_saturation", blur_params.saturation);
OPT_NUM("shadows", shadows);
OPT_NUM("shadow_only_floating", shadow_only_floating);
OPT_NUM("layer_shadows", layer_shadows);
OPT_NUM("shadows_size", shadows_size);
OPT_NUM("shadows_blur", shadows_blur);
OPT_NUM("shadows_position_x", shadows_position_x);
OPT_NUM("shadows_position_y", shadows_position_y);
OPT_NUM("single_scratchpad", single_scratchpad);
OPT_NUM("xwayland_persistence", xwayland_persistence);
OPT_NUM("syncobj_enable", syncobj_enable);
OPT_NUM("tag_carousel", tag_carousel);
OPT_NUM("drag_tile_refresh_interval", drag_tile_refresh_interval);
OPT_NUM("drag_floating_refresh_interval", drag_floating_refresh_interval);
OPT_NUM("allow_tearing", allow_tearing);
OPT_NUM("allow_shortcuts_inhibit", allow_shortcuts_inhibit);
OPT_NUM("allow_lock_transparent", allow_lock_transparent);
OPT_NUM("no_border_when_single", no_border_when_single);
OPT_NUM("no_radius_when_single", no_radius_when_single);
OPT_NUM("snap_distance", snap_distance);
OPT_NUM("enable_floating_snap", enable_floating_snap);
OPT_NUM("drag_tile_to_tile", drag_tile_to_tile);
OPT_NUM("drag_tile_small", drag_tile_small);
OPT_NUM("swipe_min_threshold", swipe_min_threshold);
OPT_NUM("focused_opacity", focused_opacity);
OPT_NUM("unfocused_opacity", unfocused_opacity);
OPT_STR("xkb_rules_rules", xkb_rules_rules);
OPT_STR("xkb_rules_model", xkb_rules_model);
OPT_STR("xkb_rules_layout", xkb_rules_layout);
OPT_STR("xkb_rules_variant", xkb_rules_variant);
OPT_STR("xkb_rules_options", xkb_rules_options);
OPT_NUM("new_is_master", new_is_master);
OPT_NUM("default_mfact", default_mfact);
OPT_NUM("default_nmaster", default_nmaster);
OPT_NUM("center_master_overspread", center_master_overspread);
OPT_NUM("center_when_single_stack", center_when_single_stack);
OPT_NUM("dwindle_vsplit", dwindle_vsplit);
OPT_NUM("dwindle_hsplit", dwindle_hsplit);
OPT_NUM("dwindle_preserve_split", dwindle_preserve_split);
OPT_NUM("dwindle_smart_split", dwindle_smart_split);
OPT_NUM("dwindle_smart_resize", dwindle_smart_resize);
OPT_NUM("dwindle_drop_simple_split", dwindle_drop_simple_split);
OPT_NUM("dwindle_manual_split", dwindle_manual_split);
OPT_NUM("dwindle_split_ratio", dwindle_split_ratio);
OPT_NUM("hotarea_size", hotarea_size);
OPT_NUM("hotarea_corner", hotarea_corner);
OPT_NUM("enable_hotarea", enable_hotarea);
OPT_NUM("ov_tab_mode", ov_tab_mode);
OPT_NUM("ov_no_resize", ov_no_resize);
OPT_NUM("overviewgappi", overviewgappi);
OPT_NUM("overviewgappo", overviewgappo);
OPT_NUM("cursor_hide_timeout", cursor_hide_timeout);
OPT_NUM("cursor_hide_on_keypress", cursor_hide_on_keypress);
OPT_NUM("axis_bind_apply_timeout", axis_bind_apply_timeout);
OPT_NUM("focus_on_activate", focus_on_activate);
OPT_NUM("numlockon", numlockon);
OPT_NUM("idleinhibit_ignore_visible", idleinhibit_ignore_visible);
OPT_NUM("sloppyfocus", sloppyfocus);
OPT_NUM("warpcursor", warpcursor);
OPT_NUM("drag_corner", drag_corner);
OPT_NUM("drag_warp_cursor", drag_warp_cursor);
OPT_NUM("smartgaps", smartgaps);
OPT_NUM("repeat_rate", repeat_rate);
OPT_NUM("repeat_delay", repeat_delay);
OPT_NUM("disable_trackpad", disable_trackpad);
OPT_NUM("tap_to_click", tap_to_click);
OPT_NUM("tap_and_drag", tap_and_drag);
OPT_NUM("drag_lock", drag_lock);
OPT_NUM("mouse_natural_scrolling", mouse_natural_scrolling);
OPT_NUM("trackpad_natural_scrolling", trackpad_natural_scrolling);
OPT_NUM("cursor_size", cursor_size);
OPT_STRP("cursor_theme", cursor_theme);
OPT_STRP("tab_bar_decorate_font_desc", tabdata.font_desc);
OPT_COLOR("tab_bar_decorate_fg_color", tabdata.fg_color);
OPT_COLOR("tab_bar_decorate_bg_color", tabdata.bg_color);
OPT_COLOR("tab_bar_decorate_focus_fg_color", tabdata.focus_fg_color);
OPT_COLOR("tab_bar_decorate_focus_bg_color", tabdata.focus_bg_color);
OPT_COLOR("tab_bar_decorate_border_color", tabdata.border_color);
OPT_NUM("tab_bar_decorate_border_width", tabdata.border_width);
OPT_NUM("tab_bar_decorate_corner_radius", tabdata.corner_radius);
OPT_NUM("tab_bar_decorate_padding_x", tabdata.padding_x);
OPT_NUM("tab_bar_decorate_padding_y", tabdata.padding_y);
OPT_STRP("jump_label_decorate_font_desc", jumplabeldata.font_desc);
OPT_COLOR("jump_label_decorate_fg_color", jumplabeldata.fg_color);
OPT_COLOR("jump_label_decorate_bg_color", jumplabeldata.bg_color);
OPT_COLOR("jump_label_decorate_focus_fg_color",
jumplabeldata.focus_fg_color);
OPT_COLOR("jump_label_decorate_focus_bg_color",
jumplabeldata.focus_bg_color);
OPT_COLOR("jump_label_decorate_border_color", jumplabeldata.border_color);
OPT_NUM("jump_label_decorate_border_width", jumplabeldata.border_width);
OPT_NUM("jump_label_decorate_corner_radius", jumplabeldata.corner_radius);
OPT_NUM("jump_label_decorate_padding_x", jumplabeldata.padding_x);
OPT_NUM("jump_label_decorate_padding_y", jumplabeldata.padding_y);
OPT_NUM("disable_while_typing", disable_while_typing);
OPT_NUM("left_handed", left_handed);
OPT_NUM("middle_button_emulation", middle_button_emulation);
OPT_NUM("mouse_accel_profile", mouse_accel_profile);
OPT_NUM("mouse_accel_speed", mouse_accel_speed);
OPT_NUM("trackpad_accel_profile", trackpad_accel_profile);
OPT_NUM("trackpad_accel_speed", trackpad_accel_speed);
OPT_NUM("scroll_method", scroll_method);
OPT_NUM("scroll_button", scroll_button);
OPT_NUM("click_method", click_method);
OPT_NUM("send_events_mode", send_events_mode);
OPT_NUM("button_map", button_map);
OPT_NUM("axis_scroll_factor", axis_scroll_factor);
OPT_STRP("tablet_map_to_mon", tablet_map_to_mon);
OPT_NUM("trackpad_scroll_factor", trackpad_scroll_factor);
OPT_NUM("gappih", gappih);
OPT_NUM("gappiv", gappiv);
OPT_NUM("gappoh", gappoh);
OPT_NUM("gappov", gappov);
OPT_NUM("scratchpad_width_ratio", scratchpad_width_ratio);
OPT_NUM("scratchpad_height_ratio", scratchpad_height_ratio);
OPT_NUM("borderpx", borderpx);
OPT_NUM("tab_bar_height", tab_bar_height);
OPT_COLOR("rootcolor", rootcolor);
OPT_COLOR("shadowscolor", shadowscolor);
OPT_COLOR("bordercolor", bordercolor);
OPT_COLOR("dropcolor", dropcolor);
OPT_COLOR("splitcolor", splitcolor);
OPT_COLOR("focuscolor", focuscolor);
OPT_COLOR("maximizescreencolor", maximizescreencolor);
OPT_COLOR("urgentcolor", urgentcolor);
OPT_COLOR("scratchpadcolor", scratchpadcolor);
OPT_COLOR("globalcolor", globalcolor);
OPT_COLOR("overlaycolor", overlaycolor);
#undef OPT_NUM
#undef OPT_STR
#undef OPT_STRP
#undef OPT_COLOR
#undef OPT_CURVE
if (strcmp(key, "scroller_proportion_preset") == 0) {
cJSON *arr = cJSON_CreateArray();
for (int32_t i = 0; i < config->scroller_proportion_preset_count; i++)
cJSON_AddItemToArray(
arr, cJSON_CreateNumber(config->scroller_proportion_preset[i]));
return arr;
}
if (strcmp(key, "circle_layout") == 0) {
cJSON *arr = cJSON_CreateArray();
for (int32_t i = 0; i < config->circle_layout_count; i++)
cJSON_AddItemToArray(arr,
cJSON_CreateString(config->circle_layout[i]));
return arr;
}
return NULL;
}
bool parse_config_line(Config *config, const char *line) {
char key[256], value[256];
if (sscanf(line, "%255[^=]=%255[^\n]", key, value) != 2) {

View file

@ -237,6 +237,15 @@ static void handle_command(int client_fd, const char *cmd_raw) {
if (strcmp(cmd, "get version") == 0) {
resp = cJSON_CreateObject();
cJSON_AddStringToObject(resp, "version", VERSION);
} else if (strcmp(cmd, "get cursorpos") == 0) {
resp = cJSON_CreateObject();
cJSON_AddNumberToObject(resp, "x", cursor->x);
cJSON_AddNumberToObject(resp, "y", cursor->y);
Monitor *m = xytomon(cursor->x, cursor->y);
if (m)
cJSON_AddStringToObject(resp, "monitor", m->wlr_output->name);
else
cJSON_AddNullToObject(resp, "monitor");
} else if (strcmp(cmd, "get keymode") == 0) {
resp = cJSON_CreateObject();
cJSON_AddStringToObject(resp, "keymode", keymode.mode);
@ -342,6 +351,16 @@ static void handle_command(int client_fd, const char *cmd_raw) {
return;
}
resp = build_monitor_tags_response(m);
} else if (strncmp(cmd, "get option ", 11) == 0) {
cJSON *val = read_option(&config, cmd + 11);
if (!val) {
send_static_json(client_fd,
"{\"error\":\"unknown or unreadable option\"}\n");
return;
}
resp = cJSON_CreateObject();
cJSON_AddStringToObject(resp, "option", cmd + 11);
cJSON_AddItemToObject(resp, "value", val);
} else if (strncmp(cmd, "dispatch ", 9) == 0) {
char *dispatch_copy = strdup(cmd_raw + 9);
char *out = dispatch_copy, *ptr = dispatch_copy;