ipc: add query for mode bindings

This commit is contained in:
Ronan Pigott 2020-07-16 12:11:09 -07:00 committed by Ronan Pigott
parent cffb006feb
commit c98ef97eed
3 changed files with 232 additions and 76 deletions

View File

@ -8,6 +8,8 @@
json_object *ipc_json_get_version(void);
json_object *ipc_json_get_binding_mode(void);
json_object *ipc_json_describe_binding(struct sway_binding *binding);
json_object *ipc_json_describe_binding_mode(struct sway_mode *mode);
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);

View File

@ -16,6 +16,7 @@
#include "sway/output.h"
#include "sway/input/input-manager.h"
#include "sway/input/cursor.h"
#include "sway/input/keyboard.h"
#include "sway/input/seat.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
#include "sway/desktop/idle_inhibit_v1.h"
@ -1319,3 +1320,193 @@ json_object *ipc_json_get_binding_mode(void) {
json_object_new_string(config->current_mode->name));
return current_mode;
}
json_object *ipc_json_describe_binding_flags(uint32_t flags) {
json_object *json_flags = json_object_new_array();
if (flags & BINDING_RELEASE) {
json_object_array_add(json_flags, json_object_new_string("release"));
} else if (flags & BINDING_LOCKED) {
json_object_array_add(json_flags, json_object_new_string("locked"));
} else if (flags & BINDING_BORDER) {
json_object_array_add(json_flags, json_object_new_string("border"));
} else if (flags & BINDING_CONTENTS) {
json_object_array_add(json_flags, json_object_new_string("contents"));
} else if (flags & BINDING_TITLEBAR) {
json_object_array_add(json_flags, json_object_new_string("titlebar"));
} else if (flags & BINDING_CODE) {
json_object_array_add(json_flags, json_object_new_string("code"));
} else if (flags & BINDING_RELOAD) {
json_object_array_add(json_flags, json_object_new_string("reload"));
} else if (flags & BINDING_INHIBITED) {
json_object_array_add(json_flags, json_object_new_string("inhibited"));
} else if (flags & BINDING_NOREPEAT) {
json_object_array_add(json_flags, json_object_new_string("norepeat"));
}
return json_flags;
}
json_object *ipc_json_describe_switch_binding(struct sway_switch_binding *binding) {
json_object *json_binding = json_object_new_object();
json_object_object_add(json_binding, "command", json_object_new_string(binding->command));
json_object *type = NULL;
switch (binding->type) {
case WLR_SWITCH_TYPE_LID:
type = json_object_new_string("lid");
break;
case WLR_SWITCH_TYPE_TABLET_MODE:
type = json_object_new_string("tablet_mode");
break;
}
json_object_object_add(json_binding, "type", type);
json_object *trigger = NULL;
switch (binding->trigger) {
case SWAY_SWITCH_TRIGGER_OFF:
trigger = json_object_new_string("off");
break;
case SWAY_SWITCH_TRIGGER_ON:
trigger = json_object_new_string("on");
break;
case SWAY_SWITCH_TRIGGER_TOGGLE:
trigger = json_object_new_string("on");
break;
}
json_object_object_add(json_binding, "trigger", trigger);
json_object *flags = ipc_json_describe_binding_flags(binding->flags);
json_object_object_add(json_binding, "flags", flags);
return json_binding;
}
json_object *ipc_json_describe_binding(struct sway_binding *binding) {
json_object *json_binding = json_object_new_object();
json_object_object_add(json_binding, "command", json_object_new_string(binding->command));
const char *names[10];
int len = get_modifier_names(names, binding->modifiers);
json_object *modifiers = json_object_new_array();
for (int i = 0; i < len; ++i) {
json_object_array_add(modifiers, json_object_new_string(names[i]));
}
json_object_object_add(json_binding, "modifiers", modifiers);
json_object *input_codes = json_object_new_array();
int input_code = 0;
json_object *symbols = json_object_new_array();
json_object *symbol = NULL;
json_object *binding_flags = ipc_json_describe_binding_flags(binding->flags);
json_object_object_add(json_binding, "flags", binding_flags);
switch (binding->type) {
case BINDING_KEYCODE:
json_object_object_add(json_binding, "type", json_object_new_string("keycode"));
// bindcode: populate input_codes
uint32_t keycode;
for (int i = 0; i < binding->keys->length; ++i) {
keycode = *(uint32_t *)binding->keys->items[i];
json_object_array_add(input_codes, json_object_new_int(keycode));
if (i == 0) {
input_code = keycode;
}
}
break;
case BINDING_KEYSYM:
json_object_object_add(json_binding, "type", json_object_new_string("keysym"));
goto symbols;
case BINDING_MOUSESYM:
json_object_object_add(json_binding, "type", json_object_new_string("mousesym"));
goto symbols;
case BINDING_MOUSECODE:
json_object_object_add(json_binding, "type", json_object_new_string("mousecode"));
symbols:; // bindsym/mouse: populate symbols
uint32_t keysym;
char buffer[64];
for (int i = 0; i < binding->keys->length; ++i) {
keysym = *(uint32_t *)binding->keys->items[i];
if (keysym >= BTN_LEFT && keysym <= BTN_LEFT + 8) {
snprintf(buffer, 64, "button%u", keysym - BTN_LEFT + 1);
} else if (xkb_keysym_get_name(keysym, buffer, 64) < 0) {
continue;
}
json_object *str = json_object_new_string(buffer);
if (i == 0) {
// str is owned by both symbol and symbols. Make sure
// to bump the ref count.
json_object_array_add(symbols, json_object_get(str));
symbol = str;
} else {
json_object_array_add(symbols, str);
}
}
break;
default:
json_object_put(input_codes);
json_object_put(symbols);
json_object_put(json_binding);
return NULL; // do not send any event
}
json_object_object_add(json_binding, "input_codes", input_codes);
json_object_object_add(json_binding, "input_code", json_object_new_int(input_code));
json_object_object_add(json_binding, "symbols", symbols);
json_object_object_add(json_binding, "symbol", symbol);
bool mouse = binding->type == BINDING_MOUSECODE ||
binding->type == BINDING_MOUSESYM;
json_object_object_add(json_binding, "input_type", mouse
? json_object_new_string("mouse")
: json_object_new_string("keyboard"));
json_object_object_add(json_binding, "input_device",
json_object_new_string(binding->input));
return json_binding;
}
json_object *ipc_json_describe_binding_mode(struct sway_mode *mode) {
json_object *json_mode = json_object_new_object();
json_object_object_add(json_mode, "name", json_object_new_string(mode->name));
json_object *bindings = json_object_new_array();
for (int i = 0; i < mode->keysym_bindings->length; i++) {
struct sway_binding *binding = mode->keysym_bindings->items[i];
json_object *json_binding = ipc_json_describe_binding(binding);
if (json_binding) {
json_object_array_add(bindings, json_binding);
}
}
for (int i = 0; i < mode->keycode_bindings->length; i++) {
struct sway_binding *binding = mode->keycode_bindings->items[i];
json_object *json_binding = ipc_json_describe_binding(binding);
if (json_binding) {
json_object_array_add(bindings, json_binding);
}
}
for (int i = 0; i < mode->mouse_bindings->length; i++) {
struct sway_binding *binding = mode->mouse_bindings->items[i];
json_object *json_binding = ipc_json_describe_binding(binding);
if (json_binding) {
json_object_array_add(bindings, json_binding);
}
}
for (int i = 0; i < mode->switch_bindings->length; i++) {
struct sway_switch_binding *binding = mode->switch_bindings->items[i];
json_object *json_binding = ipc_json_describe_switch_binding(binding);
if (json_binding) {
json_object_array_add(bindings, json_binding);
}
}
json_object_object_add(json_mode, "bindings", bindings);
return json_mode;
}

View File

@ -399,77 +399,17 @@ void ipc_event_binding(struct sway_binding *binding) {
}
sway_log(SWAY_DEBUG, "Sending binding event");
json_object *json_binding = json_object_new_object();
json_object_object_add(json_binding, "command", json_object_new_string(binding->command));
const char *names[10];
int len = get_modifier_names(names, binding->modifiers);
json_object *modifiers = json_object_new_array();
for (int i = 0; i < len; ++i) {
json_object_array_add(modifiers, json_object_new_string(names[i]));
}
json_object_object_add(json_binding, "event_state_mask", modifiers);
json_object *input_codes = json_object_new_array();
int input_code = 0;
json_object *symbols = json_object_new_array();
json_object *symbol = NULL;
switch (binding->type) {
case BINDING_KEYCODE:; // bindcode: populate input_codes
uint32_t keycode;
for (int i = 0; i < binding->keys->length; ++i) {
keycode = *(uint32_t *)binding->keys->items[i];
json_object_array_add(input_codes, json_object_new_int(keycode));
if (i == 0) {
input_code = keycode;
}
}
break;
case BINDING_KEYSYM:
case BINDING_MOUSESYM:
case BINDING_MOUSECODE:; // bindsym/mouse: populate symbols
uint32_t keysym;
char buffer[64];
for (int i = 0; i < binding->keys->length; ++i) {
keysym = *(uint32_t *)binding->keys->items[i];
if (keysym >= BTN_LEFT && keysym <= BTN_LEFT + 8) {
snprintf(buffer, 64, "button%u", keysym - BTN_LEFT + 1);
} else if (xkb_keysym_get_name(keysym, buffer, 64) < 0) {
continue;
}
json_object *str = json_object_new_string(buffer);
if (i == 0) {
// str is owned by both symbol and symbols. Make sure
// to bump the ref count.
json_object_array_add(symbols, json_object_get(str));
symbol = str;
} else {
json_object_array_add(symbols, str);
}
}
break;
default:
json_object *json_binding = ipc_json_describe_binding(binding);
if (!json_binding) {
sway_log(SWAY_DEBUG, "Unsupported ipc binding event");
json_object_put(input_codes);
json_object_put(symbols);
json_object_put(json_binding);
return; // do not send any event
}
json_object_object_add(json_binding, "input_codes", input_codes);
json_object_object_add(json_binding, "input_code", json_object_new_int(input_code));
json_object_object_add(json_binding, "symbols", symbols);
json_object_object_add(json_binding, "symbol", symbol);
bool mouse = binding->type == BINDING_MOUSECODE ||
binding->type == BINDING_MOUSESYM;
json_object_object_add(json_binding, "input_type", mouse
? json_object_new_string("mouse")
: json_object_new_string("keyboard"));
// Modifiers are "event_state_mask" in i3 ipc binding event
json_object *modifiers = json_object_object_get(json_binding, "modifiers");
json_object_get(modifiers);
json_object_object_del(json_binding, "modifiers");
json_object_object_add(json_binding, "event_state_mask", modifiers);
json_object *json = json_object_new_object();
json_object_object_add(json, "change", json_object_new_string("run"));
@ -862,16 +802,39 @@ void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_lengt
case IPC_GET_BINDING_MODES:
{
json_object *modes = json_object_new_array();
for (int i = 0; i < config->modes->length; i++) {
struct sway_mode *mode = config->modes->items[i];
json_object_array_add(modes, json_object_new_string(mode->name));
if (!buf[0]) {
json_object *modes = json_object_new_array();
for (int i = 0; i < config->modes->length; i++) {
struct sway_mode *mode = config->modes->items[i];
json_object_array_add(modes, json_object_new_string(mode->name));
}
const char *json_string = json_object_to_json_string(modes);
ipc_send_reply(client, payload_type, json_string,
(uint32_t)strlen(json_string));
json_object_put(modes); // free
goto exit_cleanup;
} else {
struct sway_mode *mode = NULL;
for (int i = 0; i < config->modes->length; i++) {
mode = config->modes->items[i];
if (strcmp(buf, mode->name) == 0) {
break;
}
mode = NULL;
}
if (!mode) {
const char *error = "{ \"success\": false, \"error\": \"No mode with that name\" }";
ipc_send_reply(client, payload_type, error,
(uint32_t)strlen(error));
goto exit_cleanup;
} else {
json_object *json_mode = ipc_json_describe_binding_mode(mode);
const char *json_string = json_object_to_json_string(json_mode);
ipc_send_reply(client, payload_type, json_string, (uint32_t)strlen(json_string));
json_object_put(json_mode);
goto exit_cleanup;
}
}
const char *json_string = json_object_to_json_string(modes);
ipc_send_reply(client, payload_type, json_string,
(uint32_t)strlen(json_string));
json_object_put(modes); // free
goto exit_cleanup;
}
case IPC_GET_BINDING_STATE: