Add support binding on-click handlers to other buttons than LEFT

One can now bind the left/middle/right mouse buttons to on-click. In
fact, you can have all three buttons bound to different handlers for
the same particle. The new syntax is

    on-click:
        left: <command>
        middle: <command>
        right: <command>

Leaving one out is the same thing as not mapping it at
all. Furthermore,

    on-click: <command>

is still valid, and is a shorthand for

    on-click:
        left: <commsnd>
This commit is contained in:
Daniel Eklöf 2021-06-22 19:04:13 +02:00
parent af163d3f77
commit c79ffbe057
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
15 changed files with 163 additions and 90 deletions

View file

@ -22,31 +22,41 @@ particle_default_destroy(struct particle *particle)
if (particle->deco != NULL)
particle->deco->destroy(particle->deco);
fcft_destroy(particle->font);
free(particle->on_click_template);
for (size_t i = 0; i < MOUSE_BTN_COUNT; i++)
free(particle->on_click_templates[i]);
free(particle);
}
struct particle *
particle_common_new(int left_margin, int right_margin,
const char *on_click_template,
const char **on_click_templates,
struct fcft_font *font, pixman_color_t foreground,
struct deco *deco)
{
struct particle *p = calloc(1, sizeof(*p));
p->left_margin = left_margin;
p->right_margin = right_margin;
p->on_click_template =
on_click_template != NULL ? strdup(on_click_template) : NULL;
p->foreground = foreground;
p->font = font;
p->deco = deco;
if (on_click_templates != NULL) {
for (size_t i = 0; i < MOUSE_BTN_COUNT; i++) {
if (on_click_templates[i] != NULL) {
p->have_on_click_template = true;
p->on_click_templates[i] = strdup(on_click_templates[i]);
}
}
}
return p;
}
void
exposable_default_destroy(struct exposable *exposable)
{
free(exposable->on_click);
for (size_t i = 0; i < MOUSE_BTN_COUNT; i++)
free(exposable->on_click[i]);
free(exposable);
}
@ -144,19 +154,32 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
enum mouse_event event, enum mouse_button btn,
int x, int y)
{
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
static const char *button_name[] = {
[MOUSE_BTN_NONE] = "none",
[MOUSE_BTN_LEFT] = "left",
[MOUSE_BTN_MIDDLE] = "middle",
[MOUSE_BTN_RIGHT] = "right",
[MOUSE_BTN_COUNT] = "count",
};
LOG_DBG("on_mouse: exposable=%p, event=%s, btn=%s, x=%d, y=%d (on-click=%s)",
exposable, event == ON_MOUSE_MOTION ? "motion" : "click",
btn == MOUSE_BTN_NONE ? "none" : btn == MOUSE_BTN_LEFT ? "left" : btn == MOUSE_BTN_MIDDLE ? "middle" : "right",
x, y, exposable->on_click);
button_name[btn], x, y, exposable->on_click[btn]);
#endif
/* If we have a handler, change cursor to a hand */
bar->set_cursor(bar, exposable->on_click == NULL ? "left_ptr" : "hand2");
const char *cursor =
(exposable->particle != NULL &&
exposable->particle->have_on_click_template)
? "hand2"
: "left_ptr";
bar->set_cursor(bar, cursor);
/* If this is a mouse click, and we have a handler, execute it */
if (exposable->on_click != NULL && event == ON_MOUSE_CLICK) {
if (exposable->on_click[btn] != NULL && event == ON_MOUSE_CLICK) {
/* Need a writeable copy, whose scope *we* control */
char *cmd = strdup(exposable->on_click);
LOG_DBG("cmd = \"%s\"", exposable->on_click);
char *cmd = strdup(exposable->on_click[btn]);
LOG_DBG("cmd = \"%s\"", exposable->on_click[btn]);
char **argv;
if (!tokenize_cmdline(cmd, &argv)) {
@ -174,15 +197,15 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
int wstatus;
if (waitpid(pid, &wstatus, 0) == -1)
LOG_ERRNO("%s: failed to wait for on_click handler", exposable->on_click);
LOG_ERRNO("%s: failed to wait for on_click handler", exposable->on_click[btn]);
if (WIFEXITED(wstatus)) {
if (WEXITSTATUS(wstatus) != 0)
LOG_ERRNO_P("%s: failed to execute", WEXITSTATUS(wstatus), exposable->on_click);
LOG_ERRNO_P("%s: failed to execute", WEXITSTATUS(wstatus), exposable->on_click[btn]);
} else
LOG_ERR("%s: did not exit normally", exposable->on_click);
LOG_ERR("%s: did not exit normally", exposable->on_click[btn]);
LOG_DBG("%s: launched", exposable->on_click);
LOG_DBG("%s: launched", exposable->on_click[btn]);
} else {
/*
* Use a pipe with O_CLOEXEC to communicate exec() failure
@ -283,11 +306,17 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
}
struct exposable *
exposable_common_new(const struct particle *particle, const char *on_click)
exposable_common_new(const struct particle *particle, const struct tag_set *tags)
{
struct exposable *exposable = calloc(1, sizeof(*exposable));
exposable->particle = particle;
exposable->on_click = on_click != NULL ? strdup(on_click) : NULL;
if (particle != NULL && particle->have_on_click_template) {
tags_expand_templates(
exposable->on_click,
(const char **)particle->on_click_templates,
MOUSE_BTN_COUNT, tags);
}
exposable->destroy = &exposable_default_destroy;
exposable->on_mouse = &exposable_default_on_mouse;
return exposable;