forked from external/yambar
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:
parent
af163d3f77
commit
c79ffbe057
15 changed files with 163 additions and 90 deletions
63
particle.c
63
particle.c
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue