bar_cmd_bind: utilize mouse button helpers

This modifies `bar_cmd_bindsym` to use `get_mouse_bindsym` for parsing
mouse buttons. This also introduces `cmd_bar_bindcode`, which will use
`get_mouse_bindcode` for parsing mouse buttons. Like sway bindings, the
two commands are encapsulated in a single file with shared code.

This also modifies swaybar to operate off of event codes rather than x11
button numbers, which allows for any mouse button to be used.

This introduces two new IPC properties:
- For `get_bar_config`, `event_code` has been added to the `bindings`
section and will include to event code for the button. If the event code
can be mapped to a x11 button, `input_code` will still be the x11 button
number. Otherwise, `input_code` will be `0`.
- Likewise for `click_events`, `event` has been added and will include
the event code for the button clicked. If the event code can be mapped
to a x11 button, `button` will still be the x11 button number.
Otherwise, `button` will be `0`.
master
Brian Ashworth 6 years ago
parent 212baf2f75
commit 3d6440ec26

@ -183,6 +183,7 @@ sway_cmd cmd_workspace;
sway_cmd cmd_ws_auto_back_and_forth; sway_cmd cmd_ws_auto_back_and_forth;
sway_cmd cmd_workspace_layout; sway_cmd cmd_workspace_layout;
sway_cmd bar_cmd_bindcode;
sway_cmd bar_cmd_binding_mode_indicator; sway_cmd bar_cmd_binding_mode_indicator;
sway_cmd bar_cmd_bindsym; sway_cmd bar_cmd_bindsym;
sway_cmd bar_cmd_colors; sway_cmd bar_cmd_colors;

@ -28,6 +28,6 @@ void i3bar_block_unref(struct i3bar_block *block);
bool i3bar_handle_readable(struct status_line *status); bool i3bar_handle_readable(struct status_line *status);
enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, enum hotspot_event_handling i3bar_block_send_click(struct status_line *status,
struct i3bar_block *block, int x, int y, int rx, int ry, int w, int h, struct i3bar_block *block, int x, int y, int rx, int ry, int w, int h,
enum x11_button button); uint32_t button);
#endif #endif

@ -4,6 +4,11 @@
#include <wayland-client.h> #include <wayland-client.h>
#include "list.h" #include "list.h"
#define SWAY_SCROLL_UP KEY_MAX + 1
#define SWAY_SCROLL_DOWN KEY_MAX + 2
#define SWAY_SCROLL_LEFT KEY_MAX + 3
#define SWAY_SCROLL_RIGHT KEY_MAX + 4
struct swaybar; struct swaybar;
struct swaybar_output; struct swaybar_output;
@ -39,8 +44,8 @@ struct swaybar_hotspot {
struct wl_list link; // swaybar_output::hotspots struct wl_list link; // swaybar_output::hotspots
int x, y, width, height; int x, y, width, height;
enum hotspot_event_handling (*callback)(struct swaybar_output *output, enum hotspot_event_handling (*callback)(struct swaybar_output *output,
struct swaybar_hotspot *hotspot, int x, int y, struct swaybar_hotspot *hotspot, int x, int y, uint32_t button,
enum x11_button button, void *data); void *data);
void (*destroy)(void *data); void (*destroy)(void *data);
void *data; void *data;
}; };

@ -8,6 +8,7 @@
// Must be in alphabetical order for bsearch // Must be in alphabetical order for bsearch
static struct cmd_handler bar_handlers[] = { static struct cmd_handler bar_handlers[] = {
{ "bindcode", bar_cmd_bindcode },
{ "binding_mode_indicator", bar_cmd_binding_mode_indicator }, { "binding_mode_indicator", bar_cmd_binding_mode_indicator },
{ "bindsym", bar_cmd_bindsym }, { "bindsym", bar_cmd_bindsym },
{ "colors", bar_cmd_colors }, { "colors", bar_cmd_colors },

@ -0,0 +1,106 @@
#include <libevdev/libevdev.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/input/cursor.h"
#include "list.h"
#include "log.h"
#include "stringop.h"
static struct cmd_results *bar_cmd_bind(int argc, char **argv, bool code) {
const char *command = code ? "bar bindcode" : "bar bindsym";
struct cmd_results *error = NULL;
if ((error = checkarg(argc, command, EXPECTED_AT_LEAST, 2))) {
return error;
}
if (!config->current_bar) {
return cmd_results_new(CMD_FAILURE, command, "No bar defined.");
}
struct bar_binding *binding = calloc(1, sizeof(struct bar_binding));
if (!binding) {
return cmd_results_new(CMD_FAILURE, command,
"Unable to allocate bar binding");
}
binding->release = false;
if (strcmp("--release", argv[0]) == 0) {
binding->release = true;
argv++;
argc--;
}
char *message = NULL;
if (code) {
binding->button = get_mouse_bindcode(argv[0], &message);
} else {
binding->button = get_mouse_bindsym(argv[0], &message);
}
if (message) {
free_bar_binding(binding);
error = cmd_results_new(CMD_INVALID, command, message);
free(message);
return error;
} else if (!binding->button) {
free_bar_binding(binding);
return cmd_results_new(CMD_INVALID, command,
"Unknown button %s", argv[0]);
}
const char *name = libevdev_event_code_get_name(EV_KEY, binding->button);
if (!name) {
switch (binding->button) {
case SWAY_SCROLL_UP:
name = "SWAY_SCROLL_UP";
break;
case SWAY_SCROLL_DOWN:
name = "SWAY_SCROLL_DOWN";
break;
case SWAY_SCROLL_LEFT:
name = "SWAY_SCROLL_LEFT";
break;
case SWAY_SCROLL_RIGHT:
name = "SWAY_SCROLL_RIGHT";
break;
default:
// Unreachable
break;
}
}
binding->command = join_args(argv + 1, argc - 1);
list_t *bindings = config->current_bar->bindings;
bool overwritten = false;
for (int i = 0; i < bindings->length; i++) {
struct bar_binding *other = bindings->items[i];
if (other->button == binding->button &&
other->release == binding->release) {
overwritten = true;
bindings->items[i] = binding;
free_bar_binding(other);
wlr_log(WLR_DEBUG, "[bar %s] Updated binding for %u (%s)%s",
config->current_bar->id, binding->button, name,
binding->release ? " - release" : "");
break;
}
}
if (!overwritten) {
list_add(bindings, binding);
wlr_log(WLR_DEBUG, "[bar %s] Added binding for %u (%s)%s",
config->current_bar->id, binding->button, name,
binding->release ? " - release" : "");
}
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
struct cmd_results *bar_cmd_bindcode(int argc, char **argv) {
return bar_cmd_bind(argc, argv, true);
}
struct cmd_results *bar_cmd_bindsym(int argc, char **argv) {
return bar_cmd_bind(argc, argv, false);
}

@ -1,68 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "list.h"
#include "log.h"
#include "stringop.h"
struct cmd_results *bar_cmd_bindsym(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "bar bindsym", EXPECTED_AT_LEAST, 2))) {
return error;
}
if (!config->current_bar) {
return cmd_results_new(CMD_FAILURE, "bar bindsym", "No bar defined.");
}
struct bar_binding *binding = calloc(1, sizeof(struct bar_binding));
if (!binding) {
return cmd_results_new(CMD_FAILURE, "bar bindsym",
"Unable to allocate bar binding");
}
binding->release = false;
if (strcmp("--release", argv[0]) == 0) {
binding->release = true;
argv++;
argc--;
}
binding->button = 0;
if (strncasecmp(argv[0], "button", strlen("button")) == 0 &&
strlen(argv[0]) == strlen("button0")) {
binding->button = argv[0][strlen("button")] - '0';
}
if (binding->button < 1 || binding->button > 9) {
free_bar_binding(binding);
return cmd_results_new(CMD_FAILURE, "bar bindsym",
"Only button<1-9> is supported");
}
binding->command = join_args(argv + 1, argc - 1);
list_t *bindings = config->current_bar->bindings;
bool overwritten = false;
for (int i = 0; i < bindings->length; i++) {
struct bar_binding *other = bindings->items[i];
if (other->button == binding->button &&
other->release == binding->release) {
overwritten = true;
bindings->items[i] = binding;
free_bar_binding(other);
wlr_log(WLR_DEBUG, "[bar %s] Updated binding for button%u%s",
config->current_bar->id, binding->button,
binding->release ? " (release)" : "");
break;
}
}
if (!overwritten) {
list_add(bindings, binding);
wlr_log(WLR_DEBUG, "[bar %s] Added binding for button%u%s",
config->current_bar->id, binding->button,
binding->release ? " (release)" : "");
}
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}

@ -1,4 +1,5 @@
#include <json-c/json.h> #include <json-c/json.h>
#include <libevdev/libevdev.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include "config.h" #include "config.h"
@ -10,6 +11,7 @@
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/input/cursor.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include <wlr/types/wlr_box.h> #include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
@ -626,6 +628,31 @@ json_object *ipc_json_describe_seat(struct sway_seat *seat) {
return object; return object;
} }
static uint32_t event_to_x11_button(uint32_t event) {
switch (event) {
case BTN_LEFT:
return 1;
case BTN_MIDDLE:
return 2;
case BTN_RIGHT:
return 3;
case SWAY_SCROLL_UP:
return 4;
case SWAY_SCROLL_DOWN:
return 5;
case SWAY_SCROLL_LEFT:
return 6;
case SWAY_SCROLL_RIGHT:
return 7;
case BTN_SIDE:
return 8;
case BTN_EXTRA:
return 9;
default:
return 0;
}
}
json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
if (!sway_assert(bar, "Bar must not be NULL")) { if (!sway_assert(bar, "Bar must not be NULL")) {
return NULL; return NULL;
@ -767,6 +794,8 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
struct bar_binding *binding = bar->bindings->items[i]; struct bar_binding *binding = bar->bindings->items[i];
json_object *bind = json_object_new_object(); json_object *bind = json_object_new_object();
json_object_object_add(bind, "input_code", json_object_object_add(bind, "input_code",
json_object_new_int(event_to_x11_button(binding->button)));
json_object_object_add(bind, "event_code",
json_object_new_int(binding->button)); json_object_new_int(binding->button));
json_object_object_add(bind, "command", json_object_object_add(bind, "command",
json_object_new_string(binding->command)); json_object_new_string(binding->command));

@ -100,8 +100,8 @@ sway_sources = files(
'commands/workspace_layout.c', 'commands/workspace_layout.c',
'commands/ws_auto_back_and_forth.c', 'commands/ws_auto_back_and_forth.c',
'commands/bar/bind.c',
'commands/bar/binding_mode_indicator.c', 'commands/bar/binding_mode_indicator.c',
'commands/bar/bindsym.c',
'commands/bar/colors.c', 'commands/bar/colors.c',
'commands/bar/font.c', 'commands/bar/font.c',
'commands/bar/gaps.c', 'commands/bar/gaps.c',

@ -71,10 +71,18 @@ Sway allows configuring swaybar in the sway configuration file.
*height* <height> *height* <height>
Sets the height of the bar. Default height will match the font size. Sets the height of the bar. Default height will match the font size.
*bindsym* [--release] button<n> <command> *bindcode* [--release] <event-code> <command>
Executes _command_ when mouse button _n_ has been pressed (or if _released_ Executes _command_ when the mouse button has been pressed (or if _released_
is given, when mouse button _n_ has been released). To disable the default is given, when the button has been released). The buttons can be given as
behavior for a button, use the command _nop_. an event code, which can be obtaining from `libinput debug-events`. To
disable the default behavior for a button, use the command _nop_.
*bindsym* [--release] button[1-9]|<event-name> <command>
Executes _command_ when the mouse button has been pressed (or if _released_
is given, when the button has been released). The buttons can be given as a
x11 button number or an event name, which can be obtained from `libinput
debug-events`. To disable the default behavior for a button, use the
command _nop_.
*mode* dock|hide|invisible *mode* dock|hide|invisible
Specifies the visibility of the bar. In _dock_ mode, it is permanently Specifies the visibility of the bar. In _dock_ mode, it is permanently

@ -259,9 +259,34 @@ bool i3bar_handle_readable(struct status_line *status) {
} }
} }
static uint32_t event_to_x11_button(uint32_t event) {
switch (event) {
case BTN_LEFT:
return 1;
case BTN_MIDDLE:
return 2;
case BTN_RIGHT:
return 3;
case SWAY_SCROLL_UP:
return 4;
case SWAY_SCROLL_DOWN:
return 5;
case SWAY_SCROLL_LEFT:
return 6;
case SWAY_SCROLL_RIGHT:
return 7;
case BTN_SIDE:
return 8;
case BTN_EXTRA:
return 9;
default:
return 0;
}
}
enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, enum hotspot_event_handling i3bar_block_send_click(struct status_line *status,
struct i3bar_block *block, int x, int y, int rx, int ry, int w, int h, struct i3bar_block *block, int x, int y, int rx, int ry, int w, int h,
enum x11_button button) { uint32_t button) {
wlr_log(WLR_DEBUG, "block %s clicked", block->name); wlr_log(WLR_DEBUG, "block %s clicked", block->name);
if (!block->name || !status->click_events) { if (!block->name || !status->click_events) {
return HOTSPOT_PROCESS; return HOTSPOT_PROCESS;
@ -275,7 +300,9 @@ enum hotspot_event_handling i3bar_block_send_click(struct status_line *status,
json_object_new_string(block->instance)); json_object_new_string(block->instance));
} }
json_object_object_add(event_json, "button", json_object_new_int(button)); json_object_object_add(event_json, "button",
json_object_new_int(event_to_x11_button(button)));
json_object_object_add(event_json, "event", json_object_new_int(button));
json_object_object_add(event_json, "x", json_object_new_int(x)); json_object_object_add(event_json, "x", json_object_new_int(x));
json_object_object_add(event_json, "y", json_object_new_int(y)); json_object_object_add(event_json, "y", json_object_new_int(y));
json_object_object_add(event_json, "relative_x", json_object_new_int(rx)); json_object_object_add(event_json, "relative_x", json_object_new_int(rx));

@ -22,32 +22,16 @@ void free_hotspots(struct wl_list *list) {
} }
} }
static enum x11_button wl_button_to_x11_button(uint32_t button) { static uint32_t wl_axis_to_button(uint32_t axis, wl_fixed_t value) {
switch (button) { bool negative = wl_fixed_to_double(value) < 0;
case BTN_LEFT:
return LEFT;
case BTN_MIDDLE:
return MIDDLE;
case BTN_RIGHT:
return RIGHT;
case BTN_SIDE:
return BACK;
case BTN_EXTRA:
return FORWARD;
default:
return NONE;
}
}
static enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value) {
switch (axis) { switch (axis) {
case WL_POINTER_AXIS_VERTICAL_SCROLL: case WL_POINTER_AXIS_VERTICAL_SCROLL:
return wl_fixed_to_double(value) < 0 ? SCROLL_UP : SCROLL_DOWN; return negative ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL: case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
return wl_fixed_to_double(value) < 0 ? SCROLL_LEFT : SCROLL_RIGHT; return negative ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT;
default: default:
wlr_log(WLR_DEBUG, "Unexpected axis value on mouse scroll"); wlr_log(WLR_DEBUG, "Unexpected axis value on mouse scroll");
return NONE; return 0;
} }
} }
@ -102,12 +86,12 @@ static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
bar->pointer.y = wl_fixed_to_int(surface_y); bar->pointer.y = wl_fixed_to_int(surface_y);
} }
static bool check_bindings(struct swaybar *bar, uint32_t x11_button, static bool check_bindings(struct swaybar *bar, uint32_t button,
uint32_t state) { uint32_t state) {
bool released = state == WL_POINTER_BUTTON_STATE_RELEASED; bool released = state == WL_POINTER_BUTTON_STATE_RELEASED;
for (int i = 0; i < bar->config->bindings->length; i++) { for (int i = 0; i < bar->config->bindings->length; i++) {
struct swaybar_binding *binding = bar->config->bindings->items[i]; struct swaybar_binding *binding = bar->config->bindings->items[i];
if (binding->button == x11_button && binding->release == released) { if (binding->button == button && binding->release == released) {
ipc_execute_binding(bar, binding); ipc_execute_binding(bar, binding);
return true; return true;
} }
@ -124,7 +108,7 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
return; return;
} }
if (check_bindings(bar, wl_button_to_x11_button(button), state)) { if (check_bindings(bar, button, state)) {
return; return;
} }
@ -140,7 +124,7 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
&& x < hotspot->x + hotspot->width && x < hotspot->x + hotspot->width
&& y < hotspot->y + hotspot->height) { && y < hotspot->y + hotspot->height) {
if (HOTSPOT_IGNORE == hotspot->callback(output, hotspot, if (HOTSPOT_IGNORE == hotspot->callback(output, hotspot,
pointer->x, pointer->y, wl_button_to_x11_button(button), hotspot->data)) { pointer->x, pointer->y, button, hotspot->data)) {
return; return;
} }
} }
@ -158,7 +142,7 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
// If there is a button press binding, execute it, skip default behavior, // If there is a button press binding, execute it, skip default behavior,
// and check button release bindings // and check button release bindings
enum x11_button button = wl_axis_to_x11_button(axis, value); uint32_t button = wl_axis_to_button(axis, value);
if (check_bindings(bar, button, WL_POINTER_BUTTON_STATE_PRESSED)) { if (check_bindings(bar, button, WL_POINTER_BUTTON_STATE_PRESSED)) {
check_bindings(bar, button, WL_POINTER_BUTTON_STATE_RELEASED); check_bindings(bar, button, WL_POINTER_BUTTON_STATE_RELEASED);
return; return;

@ -237,7 +237,7 @@ static bool ipc_parse_config(
struct swaybar_binding *binding = struct swaybar_binding *binding =
calloc(1, sizeof(struct swaybar_binding)); calloc(1, sizeof(struct swaybar_binding));
binding->button = json_object_get_int( binding->button = json_object_get_int(
json_object_object_get(bindobj, "input_code")); json_object_object_get(bindobj, "event_code"));
binding->command = strdup(json_object_get_string( binding->command = strdup(json_object_get_string(
json_object_object_get(bindobj, "command"))); json_object_object_get(bindobj, "command")));
binding->release = json_object_get_boolean( binding->release = json_object_get_boolean(

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L #define _POSIX_C_SOURCE 200809L
#include <assert.h> #include <assert.h>
#include <linux/input-event-codes.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@ -126,13 +127,13 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color,
} }
} }
static enum hotspot_event_handling block_hotspot_callback(struct swaybar_output *output, static enum hotspot_event_handling block_hotspot_callback(
struct swaybar_hotspot *hotspot, struct swaybar_output *output, struct swaybar_hotspot *hotspot,
int x, int y, enum x11_button button, void *data) { int x, int y, uint32_t button, void *data) {
struct i3bar_block *block = data; struct i3bar_block *block = data;
struct status_line *status = output->bar->status; struct status_line *status = output->bar->status;
return i3bar_block_send_click(status, block, x, y, x - hotspot->x, y - hotspot->y, return i3bar_block_send_click(status, block, x, y, x - hotspot->x,
hotspot->width, hotspot->height, button); y - hotspot->y, hotspot->width, hotspot->height, button);
} }
static void i3bar_block_unref_callback(void *data) { static void i3bar_block_unref_callback(void *data) {
@ -360,10 +361,10 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo,
return output->height; return output->height;
} }
static enum hotspot_event_handling workspace_hotspot_callback(struct swaybar_output *output, static enum hotspot_event_handling workspace_hotspot_callback(
struct swaybar_hotspot *hotspot, struct swaybar_output *output, struct swaybar_hotspot *hotspot,
int x, int y, enum x11_button button, void *data) { int x, int y, uint32_t button, void *data) {
if (button != LEFT) { if (button != BTN_LEFT) {
return HOTSPOT_PROCESS; return HOTSPOT_PROCESS;
} }
ipc_send_workspace_command(output->bar, (const char *)data); ipc_send_workspace_command(output->bar, (const char *)data);

Loading…
Cancel
Save