forked from external/yambar
commit
e4a0b375e5
22 changed files with 324 additions and 110 deletions
|
@ -11,6 +11,8 @@
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
* Text shaping support.
|
* Text shaping support.
|
||||||
|
* Support for middle and right mouse buttons, mouse wheel and trackpad
|
||||||
|
scrolling (https://codeberg.org/dnkl/yambar/issues/39).
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -10,7 +10,7 @@ struct backend {
|
||||||
void (*loop)(struct bar *bar,
|
void (*loop)(struct bar *bar,
|
||||||
void (*expose)(const struct bar *bar),
|
void (*expose)(const struct bar *bar),
|
||||||
void (*on_mouse)(struct bar *bar, enum mouse_event event,
|
void (*on_mouse)(struct bar *bar, enum mouse_event event,
|
||||||
int x, int y));
|
enum mouse_button btn, int x, int y));
|
||||||
void (*commit)(const struct bar *bar);
|
void (*commit)(const struct bar *bar);
|
||||||
void (*refresh)(const struct bar *bar);
|
void (*refresh)(const struct bar *bar);
|
||||||
void (*set_cursor)(struct bar *bar, const char *cursor);
|
void (*set_cursor)(struct bar *bar, const char *cursor);
|
||||||
|
|
10
bar/bar.c
10
bar/bar.c
|
@ -151,7 +151,8 @@ set_cursor(struct bar *bar, const char *cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_mouse(struct bar *_bar, enum mouse_event event, int x, int y)
|
on_mouse(struct bar *_bar, enum mouse_event event, enum mouse_button btn,
|
||||||
|
int x, int y)
|
||||||
{
|
{
|
||||||
struct private *bar = _bar->private;
|
struct private *bar = _bar->private;
|
||||||
|
|
||||||
|
@ -173,7 +174,7 @@ on_mouse(struct bar *_bar, enum mouse_event event, int x, int y)
|
||||||
mx += bar->left_spacing;
|
mx += bar->left_spacing;
|
||||||
if (x >= mx && x < mx + e->width) {
|
if (x >= mx && x < mx + e->width) {
|
||||||
if (e->on_mouse != NULL)
|
if (e->on_mouse != NULL)
|
||||||
e->on_mouse(e, _bar, event, x - mx, y);
|
e->on_mouse(e, _bar, event, btn, x - mx, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ on_mouse(struct bar *_bar, enum mouse_event event, int x, int y)
|
||||||
mx += bar->left_spacing;
|
mx += bar->left_spacing;
|
||||||
if (x >= mx && x < mx + e->width) {
|
if (x >= mx && x < mx + e->width) {
|
||||||
if (e->on_mouse != NULL)
|
if (e->on_mouse != NULL)
|
||||||
e->on_mouse(e, _bar, event, x - mx, y);
|
e->on_mouse(e, _bar, event, btn, x - mx, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +206,7 @@ on_mouse(struct bar *_bar, enum mouse_event event, int x, int y)
|
||||||
mx += bar->left_spacing;
|
mx += bar->left_spacing;
|
||||||
if (x >= mx && x < mx + e->width) {
|
if (x >= mx && x < mx + e->width) {
|
||||||
if (e->on_mouse != NULL)
|
if (e->on_mouse != NULL)
|
||||||
e->on_mouse(e, _bar, event, x - mx, y);
|
e->on_mouse(e, _bar, event, btn, x - mx, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,6 +408,7 @@ bar_new(const struct bar_config *config)
|
||||||
priv->right_spacing = config->right_spacing;
|
priv->right_spacing = config->right_spacing;
|
||||||
priv->left_margin = config->left_margin;
|
priv->left_margin = config->left_margin;
|
||||||
priv->right_margin = config->right_margin;
|
priv->right_margin = config->right_margin;
|
||||||
|
priv->trackpad_sensitivity = config->trackpad_sensitivity;
|
||||||
priv->border.width = config->border.width;
|
priv->border.width = config->border.width;
|
||||||
priv->border.color = config->border.color;
|
priv->border.color = config->border.color;
|
||||||
priv->border.left_margin = config->border.left_margin;
|
priv->border.left_margin = config->border.left_margin;
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct bar_config {
|
||||||
int height;
|
int height;
|
||||||
int left_spacing, right_spacing;
|
int left_spacing, right_spacing;
|
||||||
int left_margin, right_margin;
|
int left_margin, right_margin;
|
||||||
|
int trackpad_sensitivity;
|
||||||
|
|
||||||
pixman_color_t background;
|
pixman_color_t background;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ struct private {
|
||||||
int height;
|
int height;
|
||||||
int left_spacing, right_spacing;
|
int left_spacing, right_spacing;
|
||||||
int left_margin, right_margin;
|
int left_margin, right_margin;
|
||||||
|
int trackpad_sensitivity;
|
||||||
|
|
||||||
pixman_color_t background;
|
pixman_color_t background;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <linux/memfd.h>
|
#include <linux/memfd.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
@ -112,8 +113,12 @@ struct wayland_backend {
|
||||||
struct buffer *next_buffer; /* Bar is rendering to this one */
|
struct buffer *next_buffer; /* Bar is rendering to this one */
|
||||||
struct buffer *pending_buffer; /* Finished, but not yet rendered */
|
struct buffer *pending_buffer; /* Finished, but not yet rendered */
|
||||||
|
|
||||||
|
double aggregated_scroll;
|
||||||
|
bool have_discrete;
|
||||||
|
|
||||||
void (*bar_expose)(const struct bar *bar);
|
void (*bar_expose)(const struct bar *bar);
|
||||||
void (*bar_on_mouse)(struct bar *bar, enum mouse_event event, int x, int y);
|
void (*bar_on_mouse)(struct bar *bar, enum mouse_event event,
|
||||||
|
enum mouse_button btn, int x, int y);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -246,6 +251,8 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
|
||||||
struct seat *seat = data;
|
struct seat *seat = data;
|
||||||
struct wayland_backend *backend = seat->backend;
|
struct wayland_backend *backend = seat->backend;
|
||||||
|
|
||||||
|
backend->have_discrete = false;
|
||||||
|
|
||||||
if (backend->active_seat == seat)
|
if (backend->active_seat == seat)
|
||||||
backend->active_seat = NULL;
|
backend->active_seat = NULL;
|
||||||
}
|
}
|
||||||
|
@ -262,33 +269,81 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
|
||||||
|
|
||||||
backend->active_seat = seat;
|
backend->active_seat = seat;
|
||||||
backend->bar_on_mouse(
|
backend->bar_on_mouse(
|
||||||
backend->bar, ON_MOUSE_MOTION, seat->pointer.x, seat->pointer.y);
|
backend->bar, ON_MOUSE_MOTION, MOUSE_BTN_NONE,
|
||||||
|
seat->pointer.x, seat->pointer.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
|
uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
|
||||||
{
|
{
|
||||||
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct seat *seat = data;
|
struct seat *seat = data;
|
||||||
struct wayland_backend *backend = seat->backend;
|
struct wayland_backend *backend = seat->backend;
|
||||||
|
|
||||||
|
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||||
backend->active_seat = seat;
|
backend->active_seat = seat;
|
||||||
|
else {
|
||||||
|
enum mouse_button btn;
|
||||||
|
|
||||||
|
switch (button) {
|
||||||
|
case BTN_LEFT: btn = MOUSE_BTN_LEFT; break;
|
||||||
|
case BTN_MIDDLE: btn = MOUSE_BTN_MIDDLE; break;
|
||||||
|
case BTN_RIGHT: btn = MOUSE_BTN_RIGHT; break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
backend->bar_on_mouse(
|
backend->bar_on_mouse(
|
||||||
backend->bar, ON_MOUSE_CLICK, seat->pointer.x, seat->pointer.y);
|
backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t time, uint32_t axis, wl_fixed_t value)
|
uint32_t time, uint32_t axis, wl_fixed_t value)
|
||||||
{
|
{
|
||||||
|
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct seat *seat = data;
|
||||||
|
struct wayland_backend *backend = seat->backend;
|
||||||
|
struct private *bar = backend->bar->private;
|
||||||
|
|
||||||
|
backend->active_seat = seat;
|
||||||
|
|
||||||
|
if (backend->have_discrete)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const double amount = wl_fixed_to_double(value);
|
||||||
|
|
||||||
|
if ((backend->aggregated_scroll > 0 && amount < 0) ||
|
||||||
|
(backend->aggregated_scroll < 0 && amount > 0))
|
||||||
|
{
|
||||||
|
backend->aggregated_scroll = amount;
|
||||||
|
} else
|
||||||
|
backend->aggregated_scroll += amount;
|
||||||
|
|
||||||
|
enum mouse_button btn = backend->aggregated_scroll > 0
|
||||||
|
? MOUSE_BTN_WHEEL_DOWN
|
||||||
|
: MOUSE_BTN_WHEEL_UP;
|
||||||
|
|
||||||
|
const double step = bar->trackpad_sensitivity;
|
||||||
|
const double adjust = backend->aggregated_scroll > 0 ? -step : step;
|
||||||
|
|
||||||
|
while (fabs(backend->aggregated_scroll) >= step) {
|
||||||
|
backend->bar_on_mouse(
|
||||||
|
backend->bar, ON_MOUSE_CLICK, btn,
|
||||||
|
seat->pointer.x, seat->pointer.y);
|
||||||
|
backend->aggregated_scroll += adjust;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_pointer_frame(void *data, struct wl_pointer *wl_pointer)
|
wl_pointer_frame(void *data, struct wl_pointer *wl_pointer)
|
||||||
{
|
{
|
||||||
|
struct seat *seat = data;
|
||||||
|
struct wayland_backend *backend = seat->backend;
|
||||||
|
backend->have_discrete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -301,12 +356,36 @@ static void
|
||||||
wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t time, uint32_t axis)
|
uint32_t time, uint32_t axis)
|
||||||
{
|
{
|
||||||
|
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct seat *seat = data;
|
||||||
|
struct wayland_backend *backend = seat->backend;
|
||||||
|
backend->aggregated_scroll = 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t axis, int32_t discrete)
|
uint32_t axis, int32_t discrete)
|
||||||
{
|
{
|
||||||
|
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct seat *seat = data;
|
||||||
|
struct wayland_backend *backend = seat->backend;
|
||||||
|
backend->have_discrete = true;
|
||||||
|
|
||||||
|
enum mouse_button btn = discrete > 0
|
||||||
|
? MOUSE_BTN_WHEEL_DOWN
|
||||||
|
: MOUSE_BTN_WHEEL_UP;
|
||||||
|
|
||||||
|
int count = abs(discrete);
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < count; i++) {
|
||||||
|
backend->bar_on_mouse(
|
||||||
|
backend->bar, ON_MOUSE_CLICK, btn,
|
||||||
|
seat->pointer.x, seat->pointer.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_pointer_listener pointer_listener = {
|
static const struct wl_pointer_listener pointer_listener = {
|
||||||
|
@ -561,7 +640,7 @@ handle_global(void *data, struct wl_registry *registry,
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
||||||
const uint32_t required = 3;
|
const uint32_t required = 5;
|
||||||
if (!verify_iface_version(interface, version, required))
|
if (!verify_iface_version(interface, version, required))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1011,7 +1090,8 @@ cleanup(struct bar *_bar)
|
||||||
static void
|
static void
|
||||||
loop(struct bar *_bar,
|
loop(struct bar *_bar,
|
||||||
void (*expose)(const struct bar *bar),
|
void (*expose)(const struct bar *bar),
|
||||||
void (*on_mouse)(struct bar *bar, enum mouse_event event, int x, int y))
|
void (*on_mouse)(struct bar *bar, enum mouse_event event,
|
||||||
|
enum mouse_button btn, int x, int y))
|
||||||
{
|
{
|
||||||
struct private *bar = _bar->private;
|
struct private *bar = _bar->private;
|
||||||
struct wayland_backend *backend = bar->backend.data;
|
struct wayland_backend *backend = bar->backend.data;
|
||||||
|
|
13
bar/xcb.c
13
bar/xcb.c
|
@ -312,7 +312,8 @@ cleanup(struct bar *_bar)
|
||||||
static void
|
static void
|
||||||
loop(struct bar *_bar,
|
loop(struct bar *_bar,
|
||||||
void (*expose)(const struct bar *bar),
|
void (*expose)(const struct bar *bar),
|
||||||
void (*on_mouse)(struct bar *bar, enum mouse_event event, int x, int y))
|
void (*on_mouse)(struct bar *bar, enum mouse_event event,
|
||||||
|
enum mouse_button btn, int x, int y))
|
||||||
{
|
{
|
||||||
struct private *bar = _bar->private;
|
struct private *bar = _bar->private;
|
||||||
struct xcb_backend *backend = bar->backend.data;
|
struct xcb_backend *backend = bar->backend.data;
|
||||||
|
@ -357,7 +358,7 @@ loop(struct bar *_bar,
|
||||||
|
|
||||||
case XCB_MOTION_NOTIFY: {
|
case XCB_MOTION_NOTIFY: {
|
||||||
const xcb_motion_notify_event_t *evt = (void *)e;
|
const xcb_motion_notify_event_t *evt = (void *)e;
|
||||||
on_mouse(_bar, ON_MOUSE_MOTION, evt->event_x, evt->event_y);
|
on_mouse(_bar, ON_MOUSE_MOTION, MOUSE_BTN_NONE, evt->event_x, evt->event_y);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +367,13 @@ loop(struct bar *_bar,
|
||||||
|
|
||||||
case XCB_BUTTON_RELEASE: {
|
case XCB_BUTTON_RELEASE: {
|
||||||
const xcb_button_release_event_t *evt = (void *)e;
|
const xcb_button_release_event_t *evt = (void *)e;
|
||||||
on_mouse(_bar, ON_MOUSE_CLICK, evt->event_x, evt->event_y);
|
|
||||||
|
switch (evt->detail) {
|
||||||
|
case 1: case 2: case 3: case 4: case 5:
|
||||||
|
on_mouse(_bar, ON_MOUSE_CLICK,
|
||||||
|
evt->detail, evt->event_x, evt->event_y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,26 @@ conf_verify_dict(keychain_t *chain, const struct yml_node *node,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
conf_verify_on_click(keychain_t *chain, const struct yml_node *node)
|
||||||
|
{
|
||||||
|
/* on-click: <command> */
|
||||||
|
const char *s = yml_value_as_string(node);
|
||||||
|
if (s != NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
static const struct attr_info info[] = {
|
||||||
|
{"left", false, &conf_verify_string},
|
||||||
|
{"middle", false, &conf_verify_string},
|
||||||
|
{"right", false, &conf_verify_string},
|
||||||
|
{"wheel-up", false, &conf_verify_string},
|
||||||
|
{"wheel-down", false, &conf_verify_string},
|
||||||
|
{NULL, false, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
return conf_verify_dict(chain, node, info);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
conf_verify_color(keychain_t *chain, const struct yml_node *node)
|
conf_verify_color(keychain_t *chain, const struct yml_node *node)
|
||||||
{
|
{
|
||||||
|
@ -403,6 +423,8 @@ conf_verify_bar(const struct yml_node *bar)
|
||||||
{"center", false, &verify_module_list},
|
{"center", false, &verify_module_list},
|
||||||
{"right", false, &verify_module_list},
|
{"right", false, &verify_module_list},
|
||||||
|
|
||||||
|
{"trackpad-sensitivity", false, &conf_verify_int},
|
||||||
|
|
||||||
{NULL, false, NULL},
|
{NULL, false, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ bool conf_verify_list(keychain_t *chain, const struct yml_node *node,
|
||||||
bool conf_verify_dict(keychain_t *chain, const struct yml_node *node,
|
bool conf_verify_dict(keychain_t *chain, const struct yml_node *node,
|
||||||
const struct attr_info info[]); /* NULL-terminated list */
|
const struct attr_info info[]); /* NULL-terminated list */
|
||||||
|
|
||||||
|
bool conf_verify_on_click(keychain_t *chain, const struct yml_node *node);
|
||||||
bool conf_verify_color(keychain_t *chain, const struct yml_node *node);
|
bool conf_verify_color(keychain_t *chain, const struct yml_node *node);
|
||||||
bool conf_verify_font(keychain_t *chain, const struct yml_node *node);
|
bool conf_verify_font(keychain_t *chain, const struct yml_node *node);
|
||||||
|
|
||||||
|
|
41
config.c
41
config.c
|
@ -139,8 +139,37 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited)
|
||||||
int right = margin != NULL ? yml_value_as_int(margin) :
|
int right = margin != NULL ? yml_value_as_int(margin) :
|
||||||
right_margin != NULL ? yml_value_as_int(right_margin) : 0;
|
right_margin != NULL ? yml_value_as_int(right_margin) : 0;
|
||||||
|
|
||||||
const char *on_click_template
|
const char *on_click_templates[MOUSE_BTN_COUNT] = {NULL};
|
||||||
= on_click != NULL ? yml_value_as_string(on_click) : NULL;
|
if (on_click != NULL) {
|
||||||
|
const char *legacy = yml_value_as_string(on_click);
|
||||||
|
|
||||||
|
if (legacy != NULL)
|
||||||
|
on_click_templates[MOUSE_BTN_LEFT] = legacy;
|
||||||
|
|
||||||
|
if (yml_is_dict(on_click)) {
|
||||||
|
for (struct yml_dict_iter it = yml_dict_iter(on_click);
|
||||||
|
it.key != NULL;
|
||||||
|
yml_dict_next(&it))
|
||||||
|
{
|
||||||
|
const char *key = yml_value_as_string(it.key);
|
||||||
|
const char *template = yml_value_as_string(it.value);
|
||||||
|
|
||||||
|
if (strcmp(key, "left") == 0)
|
||||||
|
on_click_templates[MOUSE_BTN_LEFT] = template;
|
||||||
|
else if (strcmp(key, "middle") == 0)
|
||||||
|
on_click_templates[MOUSE_BTN_MIDDLE] = template;
|
||||||
|
else if (strcmp(key, "right") == 0)
|
||||||
|
on_click_templates[MOUSE_BTN_RIGHT] = template;
|
||||||
|
else if (strcmp(key, "wheel-up") == 0)
|
||||||
|
on_click_templates[MOUSE_BTN_WHEEL_UP] = template;
|
||||||
|
else if (strcmp(key, "wheel-down") == 0)
|
||||||
|
on_click_templates[MOUSE_BTN_WHEEL_DOWN] = template;
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct deco *deco = deco_node != NULL ? conf_to_deco(deco_node) : NULL;
|
struct deco *deco = deco_node != NULL ? conf_to_deco(deco_node) : NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -159,7 +188,7 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited)
|
||||||
|
|
||||||
/* Instantiate base/common particle */
|
/* Instantiate base/common particle */
|
||||||
struct particle *common = particle_common_new(
|
struct particle *common = particle_common_new(
|
||||||
left, right, on_click_template, font, foreground, deco);
|
left, right, on_click_templates, font, foreground, deco);
|
||||||
|
|
||||||
const struct particle_iface *iface = plugin_load_particle(type);
|
const struct particle_iface *iface = plugin_load_particle(type);
|
||||||
|
|
||||||
|
@ -223,6 +252,12 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
|
||||||
if (right_margin != NULL)
|
if (right_margin != NULL)
|
||||||
conf.right_margin = yml_value_as_int(right_margin);
|
conf.right_margin = yml_value_as_int(right_margin);
|
||||||
|
|
||||||
|
const struct yml_node *trackpad_sensitivity =
|
||||||
|
yml_get_value(bar, "trackpad-sensitivity");
|
||||||
|
conf.trackpad_sensitivity = trackpad_sensitivity != NULL
|
||||||
|
? yml_value_as_int(trackpad_sensitivity)
|
||||||
|
: 30;
|
||||||
|
|
||||||
const struct yml_node *border = yml_get_value(bar, "border");
|
const struct yml_node *border = yml_get_value(bar, "border");
|
||||||
if (border != NULL) {
|
if (border != NULL) {
|
||||||
const struct yml_node *width = yml_get_value(border, "width");
|
const struct yml_node *width = yml_get_value(border, "width");
|
||||||
|
|
|
@ -109,6 +109,12 @@ types that are frequently used:
|
||||||
: color
|
: color
|
||||||
: no
|
: no
|
||||||
: Default foreground (text) color to use
|
: Default foreground (text) color to use
|
||||||
|
| trackpad-sensitivity
|
||||||
|
: int
|
||||||
|
: no
|
||||||
|
: How easy it is to trigger wheel-up and wheel-down on-click
|
||||||
|
handlers. Higher values means you need to drag your finger a longer
|
||||||
|
distance. The default is 30.
|
||||||
| left
|
| left
|
||||||
: list
|
: list
|
||||||
: no
|
: no
|
||||||
|
|
74
particle.c
74
particle.c
|
@ -22,31 +22,41 @@ particle_default_destroy(struct particle *particle)
|
||||||
if (particle->deco != NULL)
|
if (particle->deco != NULL)
|
||||||
particle->deco->destroy(particle->deco);
|
particle->deco->destroy(particle->deco);
|
||||||
fcft_destroy(particle->font);
|
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);
|
free(particle);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct particle *
|
struct particle *
|
||||||
particle_common_new(int left_margin, int right_margin,
|
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 fcft_font *font, pixman_color_t foreground,
|
||||||
struct deco *deco)
|
struct deco *deco)
|
||||||
{
|
{
|
||||||
struct particle *p = calloc(1, sizeof(*p));
|
struct particle *p = calloc(1, sizeof(*p));
|
||||||
p->left_margin = left_margin;
|
p->left_margin = left_margin;
|
||||||
p->right_margin = right_margin;
|
p->right_margin = right_margin;
|
||||||
p->on_click_template =
|
|
||||||
on_click_template != NULL ? strdup(on_click_template) : NULL;
|
|
||||||
p->foreground = foreground;
|
p->foreground = foreground;
|
||||||
p->font = font;
|
p->font = font;
|
||||||
p->deco = deco;
|
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;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
exposable_default_destroy(struct exposable *exposable)
|
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);
|
free(exposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,20 +151,37 @@ err:
|
||||||
|
|
||||||
void
|
void
|
||||||
exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
|
exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
enum mouse_event event, int x, int y)
|
enum mouse_event event, enum mouse_button btn,
|
||||||
|
int x, int y)
|
||||||
{
|
{
|
||||||
LOG_DBG("on_mouse: exposable=%p, event=%s, x=%d, y=%d (on-click=%s)",
|
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
|
||||||
exposable, event == ON_MOUSE_MOTION ? "motion" : "click", x, y,
|
static const char *button_name[] = {
|
||||||
exposable->on_click);
|
[MOUSE_BTN_NONE] = "none",
|
||||||
|
[MOUSE_BTN_LEFT] = "left",
|
||||||
|
[MOUSE_BTN_MIDDLE] = "middle",
|
||||||
|
[MOUSE_BTN_RIGHT] = "right",
|
||||||
|
[MOUSE_BTN_COUNT] = "count",
|
||||||
|
[MOUSE_BTN_WHEEL_UP] = "wheel-up",
|
||||||
|
[MOUSE_BTN_WHEEL_DOWN] = "wheel-down",
|
||||||
|
};
|
||||||
|
LOG_DBG("on_mouse: exposable=%p, event=%s, btn=%s, x=%d, y=%d (on-click=%s)",
|
||||||
|
exposable, event == ON_MOUSE_MOTION ? "motion" : "click",
|
||||||
|
button_name[btn], x, y, exposable->on_click[btn]);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If we have a handler, change cursor to a hand */
|
/* 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 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 */
|
/* Need a writeable copy, whose scope *we* control */
|
||||||
char *cmd = strdup(exposable->on_click);
|
char *cmd = strdup(exposable->on_click[btn]);
|
||||||
LOG_DBG("cmd = \"%s\"", exposable->on_click);
|
LOG_DBG("cmd = \"%s\"", exposable->on_click[btn]);
|
||||||
|
|
||||||
char **argv;
|
char **argv;
|
||||||
if (!tokenize_cmdline(cmd, &argv)) {
|
if (!tokenize_cmdline(cmd, &argv)) {
|
||||||
|
@ -172,15 +199,15 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
|
|
||||||
int wstatus;
|
int wstatus;
|
||||||
if (waitpid(pid, &wstatus, 0) == -1)
|
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 (WIFEXITED(wstatus)) {
|
||||||
if (WEXITSTATUS(wstatus) != 0)
|
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
|
} 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 {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Use a pipe with O_CLOEXEC to communicate exec() failure
|
* Use a pipe with O_CLOEXEC to communicate exec() failure
|
||||||
|
@ -250,6 +277,7 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
|
|
||||||
/* Close *all* other FDs (e.g. script modules' FDs) */
|
/* Close *all* other FDs (e.g. script modules' FDs) */
|
||||||
for (int i = STDERR_FILENO + 1; i < 65536; i++)
|
for (int i = STDERR_FILENO + 1; i < 65536; i++)
|
||||||
|
if (i != pipe_fds[1])
|
||||||
close(i);
|
close(i);
|
||||||
|
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
|
@ -267,6 +295,8 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
|
|
||||||
int _errno = 0;
|
int _errno = 0;
|
||||||
ssize_t ret = read(pipe_fds[0], &_errno, sizeof(_errno));
|
ssize_t ret = read(pipe_fds[0], &_errno, sizeof(_errno));
|
||||||
|
close(pipe_fds[0]);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* Pipe was closed - child succeeded with exec() */
|
/* Pipe was closed - child succeeded with exec() */
|
||||||
_exit(0);
|
_exit(0);
|
||||||
|
@ -281,11 +311,17 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct exposable *
|
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));
|
struct exposable *exposable = calloc(1, sizeof(*exposable));
|
||||||
exposable->particle = particle;
|
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->destroy = &exposable_default_destroy;
|
||||||
exposable->on_mouse = &exposable_default_on_mouse;
|
exposable->on_mouse = &exposable_default_on_mouse;
|
||||||
return exposable;
|
return exposable;
|
||||||
|
|
36
particle.h
36
particle.h
|
@ -7,13 +7,31 @@
|
||||||
#include "decoration.h"
|
#include "decoration.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
|
enum mouse_event {
|
||||||
|
ON_MOUSE_MOTION,
|
||||||
|
ON_MOUSE_CLICK,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mouse_button {
|
||||||
|
MOUSE_BTN_NONE,
|
||||||
|
MOUSE_BTN_LEFT,
|
||||||
|
MOUSE_BTN_MIDDLE,
|
||||||
|
MOUSE_BTN_RIGHT,
|
||||||
|
MOUSE_BTN_WHEEL_UP,
|
||||||
|
MOUSE_BTN_WHEEL_DOWN,
|
||||||
|
|
||||||
|
MOUSE_BTN_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
struct bar;
|
struct bar;
|
||||||
|
|
||||||
struct particle {
|
struct particle {
|
||||||
void *private;
|
void *private;
|
||||||
|
|
||||||
int left_margin, right_margin;
|
int left_margin, right_margin;
|
||||||
char *on_click_template;
|
|
||||||
|
bool have_on_click_template;
|
||||||
|
char *on_click_templates[MOUSE_BTN_COUNT];
|
||||||
|
|
||||||
pixman_color_t foreground;
|
pixman_color_t foreground;
|
||||||
struct fcft_font *font;
|
struct fcft_font *font;
|
||||||
|
@ -24,17 +42,13 @@ struct particle {
|
||||||
const struct tag_set *tags);
|
const struct tag_set *tags);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mouse_event {
|
|
||||||
ON_MOUSE_MOTION,
|
|
||||||
ON_MOUSE_CLICK,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exposable {
|
struct exposable {
|
||||||
const struct particle *particle;
|
const struct particle *particle;
|
||||||
void *private;
|
void *private;
|
||||||
|
|
||||||
int width; /* Should be set by begin_expose(), at latest */
|
int width; /* Should be set by begin_expose(), at latest */
|
||||||
char *on_click;
|
char *on_click[MOUSE_BTN_COUNT];
|
||||||
|
|
||||||
void (*destroy)(struct exposable *exposable);
|
void (*destroy)(struct exposable *exposable);
|
||||||
int (*begin_expose)(struct exposable *exposable);
|
int (*begin_expose)(struct exposable *exposable);
|
||||||
|
@ -42,31 +56,31 @@ struct exposable {
|
||||||
int x, int y, int height);
|
int x, int y, int height);
|
||||||
|
|
||||||
void (*on_mouse)(struct exposable *exposable, struct bar *bar,
|
void (*on_mouse)(struct exposable *exposable, struct bar *bar,
|
||||||
enum mouse_event event, int x, int y);
|
enum mouse_event event, enum mouse_button btn, int x, int y);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct particle *particle_common_new(
|
struct particle *particle_common_new(
|
||||||
int left_margin, int right_margin, const char *on_click_template,
|
int left_margin, int right_margin, const char *on_click_templates[],
|
||||||
struct fcft_font *font, pixman_color_t foreground, struct deco *deco);
|
struct fcft_font *font, pixman_color_t foreground, struct deco *deco);
|
||||||
|
|
||||||
void particle_default_destroy(struct particle *particle);
|
void particle_default_destroy(struct particle *particle);
|
||||||
|
|
||||||
struct exposable *exposable_common_new(
|
struct exposable *exposable_common_new(
|
||||||
const struct particle *particle, const char *on_click);
|
const struct particle *particle, const struct tag_set *tags);
|
||||||
void exposable_default_destroy(struct exposable *exposable);
|
void exposable_default_destroy(struct exposable *exposable);
|
||||||
void exposable_render_deco(
|
void exposable_render_deco(
|
||||||
const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height);
|
const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height);
|
||||||
|
|
||||||
void exposable_default_on_mouse(
|
void exposable_default_on_mouse(
|
||||||
struct exposable *exposable, struct bar *bar,
|
struct exposable *exposable, struct bar *bar,
|
||||||
enum mouse_event event, int x, int y);
|
enum mouse_event event, enum mouse_button btn, int x, int y);
|
||||||
|
|
||||||
/* List of attributes *all* particles implement */
|
/* List of attributes *all* particles implement */
|
||||||
#define PARTICLE_COMMON_ATTRS \
|
#define PARTICLE_COMMON_ATTRS \
|
||||||
{"margin", false, &conf_verify_int}, \
|
{"margin", false, &conf_verify_int}, \
|
||||||
{"left-margin", false, &conf_verify_int}, \
|
{"left-margin", false, &conf_verify_int}, \
|
||||||
{"right-margin", false, &conf_verify_int}, \
|
{"right-margin", false, &conf_verify_int}, \
|
||||||
{"on-click", false, &conf_verify_string}, \
|
{"on-click", false, &conf_verify_on_click}, \
|
||||||
{"font", false, &conf_verify_font}, \
|
{"font", false, &conf_verify_font}, \
|
||||||
{"foreground", false, &conf_verify_color}, \
|
{"foreground", false, &conf_verify_color}, \
|
||||||
{"deco", false, &conf_verify_decoration}, \
|
{"deco", false, &conf_verify_decoration}, \
|
||||||
|
|
|
@ -67,13 +67,12 @@ dynlist_expose(const struct exposable *exposable, pixman_image_t *pix, int x, in
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_mouse(struct exposable *exposable, struct bar *bar,
|
on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
enum mouse_event event, int x, int y)
|
enum mouse_event event, enum mouse_button btn, int x, int y)
|
||||||
{
|
{
|
||||||
//const struct particle *p = exposable->particle;
|
|
||||||
const struct private *e = exposable->private;
|
const struct private *e = exposable->private;
|
||||||
|
|
||||||
if (exposable->on_click != NULL) {
|
if (exposable->on_click[btn] != NULL) {
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +81,7 @@ on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
if (x >= px && x < px + e->exposables[i]->width) {
|
if (x >= px && x < px + e->exposables[i]->width) {
|
||||||
if (e->exposables[i]->on_mouse != NULL) {
|
if (e->exposables[i]->on_mouse != NULL) {
|
||||||
e->exposables[i]->on_mouse(
|
e->exposables[i]->on_mouse(
|
||||||
e->exposables[i], bar, event, x - px, y);
|
e->exposables[i], bar, event, btn, x - px, y);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +90,7 @@ on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("on_mouse missed all sub-particles");
|
LOG_DBG("on_mouse missed all sub-particles");
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct exposable *
|
struct exposable *
|
||||||
|
|
|
@ -22,13 +22,9 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
|
||||||
static struct exposable *
|
static struct exposable *
|
||||||
instantiate(const struct particle *particle, const struct tag_set *tags)
|
instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
{
|
{
|
||||||
char *on_click = tags_expand_template(particle->on_click_template, tags);
|
struct exposable *exposable = exposable_common_new(particle, tags);
|
||||||
|
|
||||||
struct exposable *exposable = exposable_common_new(particle, on_click);
|
|
||||||
exposable->begin_expose = &begin_expose;
|
exposable->begin_expose = &begin_expose;
|
||||||
exposable->expose = &expose;
|
exposable->expose = &expose;
|
||||||
|
|
||||||
free(on_click);
|
|
||||||
return exposable;
|
return exposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,14 +75,17 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_mouse(struct exposable *exposable, struct bar *bar,
|
on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
enum mouse_event event, int x, int y)
|
enum mouse_event event, enum mouse_button btn, int x, int y)
|
||||||
{
|
{
|
||||||
const struct particle *p = exposable->particle;
|
const struct particle *p = exposable->particle;
|
||||||
const struct eprivate *e = exposable->private;
|
const struct eprivate *e = exposable->private;
|
||||||
|
|
||||||
if (exposable->on_click != NULL) {
|
if ((event == ON_MOUSE_MOTION &&
|
||||||
|
exposable->particle->have_on_click_template) ||
|
||||||
|
exposable->on_click[btn] != NULL)
|
||||||
|
{
|
||||||
/* We have our own handler */
|
/* We have our own handler */
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +94,7 @@ on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
if (x >= px && x < px + e->exposables[i]->width) {
|
if (x >= px && x < px + e->exposables[i]->width) {
|
||||||
if (e->exposables[i]->on_mouse != NULL) {
|
if (e->exposables[i]->on_mouse != NULL) {
|
||||||
e->exposables[i]->on_mouse(
|
e->exposables[i]->on_mouse(
|
||||||
e->exposables[i], bar, event, x - px, y);
|
e->exposables[i], bar, event, btn, x - px, y);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +103,7 @@ on_mouse(struct exposable *exposable, struct bar *bar,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We're between sub-particles (or in the left/right margin) */
|
/* We're between sub-particles (or in the left/right margin) */
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct exposable *
|
static struct exposable *
|
||||||
|
@ -121,16 +124,12 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
assert(e->exposables[i] != NULL);
|
assert(e->exposables[i] != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *on_click = tags_expand_template(particle->on_click_template, tags);
|
struct exposable *exposable = exposable_common_new(particle, tags);
|
||||||
|
|
||||||
struct exposable *exposable = exposable_common_new(particle, on_click);
|
|
||||||
exposable->private = e;
|
exposable->private = e;
|
||||||
exposable->destroy = &exposable_destroy;
|
exposable->destroy = &exposable_destroy;
|
||||||
exposable->begin_expose = &begin_expose;
|
exposable->begin_expose = &begin_expose;
|
||||||
exposable->expose = &expose;
|
exposable->expose = &expose;
|
||||||
exposable->on_mouse = &on_mouse;
|
exposable->on_mouse = &on_mouse;
|
||||||
|
|
||||||
free(on_click);
|
|
||||||
return exposable;
|
return exposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,26 +61,29 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
||||||
int x, int y)
|
enum mouse_button btn, int x, int y)
|
||||||
{
|
{
|
||||||
const struct particle *p = exposable->particle;
|
const struct particle *p = exposable->particle;
|
||||||
const struct eprivate *e = exposable->private;
|
const struct eprivate *e = exposable->private;
|
||||||
|
|
||||||
if (exposable->on_click != NULL) {
|
if ((event == ON_MOUSE_MOTION &&
|
||||||
|
exposable->particle->have_on_click_template) ||
|
||||||
|
exposable->on_click[btn] != NULL)
|
||||||
|
{
|
||||||
/* We have our own handler */
|
/* We have our own handler */
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int px = p->left_margin;
|
int px = p->left_margin;
|
||||||
if (x >= px && x < px + e->exposable->width) {
|
if (x >= px && x < px + e->exposable->width) {
|
||||||
if (e->exposable->on_mouse != NULL)
|
if (e->exposable->on_mouse != NULL)
|
||||||
e->exposable->on_mouse(e->exposable, bar, event, x - px, y);
|
e->exposable->on_mouse(e->exposable, bar, event, btn, x - px, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In the left- or right margin */
|
/* In the left- or right margin */
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct exposable *
|
static struct exposable *
|
||||||
|
@ -119,15 +122,12 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
|
|
||||||
assert(e->exposable != NULL);
|
assert(e->exposable != NULL);
|
||||||
|
|
||||||
char *on_click = tags_expand_template(particle->on_click_template, tags);
|
struct exposable *exposable = exposable_common_new(particle, tags);
|
||||||
struct exposable *exposable = exposable_common_new(particle, on_click);
|
|
||||||
exposable->private = e;
|
exposable->private = e;
|
||||||
exposable->destroy = &exposable_destroy;
|
exposable->destroy = &exposable_destroy;
|
||||||
exposable->begin_expose = &begin_expose;
|
exposable->begin_expose = &begin_expose;
|
||||||
exposable->expose = &expose;
|
exposable->expose = &expose;
|
||||||
exposable->on_mouse = &on_mouse;
|
exposable->on_mouse = &on_mouse;
|
||||||
|
|
||||||
free(on_click);
|
|
||||||
return exposable;
|
return exposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,10 +85,13 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
||||||
int x, int y)
|
enum mouse_button btn, int x, int y)
|
||||||
{
|
{
|
||||||
if (exposable->on_click == NULL) {
|
if ((event == ON_MOUSE_MOTION &&
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable->particle->have_on_click_template) ||
|
||||||
|
exposable->on_click[btn] != NULL)
|
||||||
|
{
|
||||||
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +123,7 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
||||||
/* Mouse is over the start-marker */
|
/* Mouse is over the start-marker */
|
||||||
struct exposable *start = e->exposables[0];
|
struct exposable *start = e->exposables[0];
|
||||||
if (start->on_mouse != NULL)
|
if (start->on_mouse != NULL)
|
||||||
start->on_mouse(start, bar, event, x - p->left_margin, y);
|
start->on_mouse(start, bar, event, btn, x - p->left_margin, y);
|
||||||
} else {
|
} else {
|
||||||
/* Mouse if over left margin */
|
/* Mouse if over left margin */
|
||||||
bar->set_cursor(bar, "left_ptr");
|
bar->set_cursor(bar, "left_ptr");
|
||||||
|
@ -139,7 +142,7 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
||||||
/* Mouse is over the end-marker */
|
/* Mouse is over the end-marker */
|
||||||
struct exposable *end = e->exposables[e->count - 1];
|
struct exposable *end = e->exposables[e->count - 1];
|
||||||
if (end->on_mouse != NULL)
|
if (end->on_mouse != NULL)
|
||||||
end->on_mouse(end, bar, event, x - x_offset - clickable_width, y);
|
end->on_mouse(end, bar, event, btn, x - x_offset - clickable_width, y);
|
||||||
} else {
|
} else {
|
||||||
/* Mouse is over the right margin */
|
/* Mouse is over the right margin */
|
||||||
bar->set_cursor(bar, "left_ptr");
|
bar->set_cursor(bar, "left_ptr");
|
||||||
|
@ -148,7 +151,9 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember the original handler, so that we can restore it */
|
/* Remember the original handler, so that we can restore it */
|
||||||
char *original = exposable->on_click;
|
char *original[MOUSE_BTN_COUNT];
|
||||||
|
for (size_t i = 0; i < MOUSE_BTN_COUNT; i++)
|
||||||
|
original[i] = exposable->on_click[i];
|
||||||
|
|
||||||
if (event == ON_MOUSE_CLICK) {
|
if (event == ON_MOUSE_CLICK) {
|
||||||
long where = clickable_width > 0
|
long where = clickable_width > 0
|
||||||
|
@ -160,17 +165,21 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
||||||
.count = 1,
|
.count = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
exposable->on_click = tags_expand_template(exposable->on_click, &tags);
|
tags_expand_templates(
|
||||||
|
exposable->on_click, (const char **)exposable->on_click,
|
||||||
|
MOUSE_BTN_COUNT, &tags);
|
||||||
tag_set_destroy(&tags);
|
tag_set_destroy(&tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call default implementation, which will execute our handler */
|
/* Call default implementation, which will execute our handler */
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
|
|
||||||
if (event == ON_MOUSE_CLICK) {
|
if (event == ON_MOUSE_CLICK) {
|
||||||
/* Reset handler string */
|
/* Reset handler string */
|
||||||
free(exposable->on_click);
|
for (size_t i = 0; i < MOUSE_BTN_COUNT; i++) {
|
||||||
exposable->on_click = original;
|
free(exposable->on_click[i]);
|
||||||
|
exposable->on_click[i] = original[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,10 +222,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
for (size_t i = 0; i < epriv->count; i++)
|
for (size_t i = 0; i < epriv->count; i++)
|
||||||
assert(epriv->exposables[i] != NULL);
|
assert(epriv->exposables[i] != NULL);
|
||||||
|
|
||||||
char *on_click = tags_expand_template(particle->on_click_template, tags);
|
struct exposable *exposable = exposable_common_new(particle, tags);
|
||||||
|
|
||||||
struct exposable *exposable = exposable_common_new(particle, on_click);
|
|
||||||
free(on_click);
|
|
||||||
|
|
||||||
exposable->private = epriv;
|
exposable->private = epriv;
|
||||||
exposable->destroy = &exposable_destroy;
|
exposable->destroy = &exposable_destroy;
|
||||||
|
|
|
@ -57,26 +57,29 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
|
||||||
int x, int y)
|
enum mouse_button btn, int x, int y)
|
||||||
{
|
{
|
||||||
const struct particle *p = exposable->particle;
|
const struct particle *p = exposable->particle;
|
||||||
const struct eprivate *e = exposable->private;
|
const struct eprivate *e = exposable->private;
|
||||||
|
|
||||||
if (exposable->on_click != NULL) {
|
if ((event == ON_MOUSE_MOTION &&
|
||||||
|
exposable->particle->have_on_click_template) ||
|
||||||
|
exposable->on_click[btn] != NULL)
|
||||||
|
{
|
||||||
/* We have our own handler */
|
/* We have our own handler */
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int px = p->left_margin;
|
int px = p->left_margin;
|
||||||
if (x >= px && x < px + e->exposable->width) {
|
if (x >= px && x < px + e->exposable->width) {
|
||||||
if (e->exposable->on_mouse != NULL)
|
if (e->exposable->on_mouse != NULL)
|
||||||
e->exposable->on_mouse(e->exposable, bar, event, x - px, y);
|
e->exposable->on_mouse(e->exposable, bar, event, btn, x - px, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In the left- or right margin */
|
/* In the left- or right margin */
|
||||||
exposable_default_on_mouse(exposable, bar, event, x, y);
|
exposable_default_on_mouse(exposable, bar, event, btn, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -146,15 +149,12 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
e->exposable = pp->instantiate(pp, tags);
|
e->exposable = pp->instantiate(pp, tags);
|
||||||
assert(e->exposable != NULL);
|
assert(e->exposable != NULL);
|
||||||
|
|
||||||
char *on_click = tags_expand_template(particle->on_click_template, tags);
|
struct exposable *exposable = exposable_common_new(particle, tags);
|
||||||
struct exposable *exposable = exposable_common_new(particle, on_click);
|
|
||||||
exposable->private = e;
|
exposable->private = e;
|
||||||
exposable->destroy = &exposable_destroy;
|
exposable->destroy = &exposable_destroy;
|
||||||
exposable->begin_expose = &begin_expose;
|
exposable->begin_expose = &begin_expose;
|
||||||
exposable->expose = &expose;
|
exposable->expose = &expose;
|
||||||
exposable->on_mouse = &on_mouse;
|
exposable->on_mouse = &on_mouse;
|
||||||
|
|
||||||
free(on_click);
|
|
||||||
return exposable;
|
return exposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,15 +269,11 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *on_click = tags_expand_template(particle->on_click_template, tags);
|
struct exposable *exposable = exposable_common_new(particle, tags);
|
||||||
|
|
||||||
struct exposable *exposable = exposable_common_new(particle, on_click);
|
|
||||||
exposable->private = e;
|
exposable->private = e;
|
||||||
exposable->destroy = &exposable_destroy;
|
exposable->destroy = &exposable_destroy;
|
||||||
exposable->begin_expose = &begin_expose;
|
exposable->begin_expose = &begin_expose;
|
||||||
exposable->expose = &expose;
|
exposable->expose = &expose;
|
||||||
|
|
||||||
free(on_click);
|
|
||||||
return exposable;
|
return exposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
tag.c
8
tag.c
|
@ -533,3 +533,11 @@ tags_expand_template(const char *template, const struct tag_set *tags)
|
||||||
|
|
||||||
return formatted.s;
|
return formatted.s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tags_expand_templates(char *expanded[], const char *template[], size_t nmemb,
|
||||||
|
const struct tag_set *tags)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < nmemb; i++)
|
||||||
|
expanded[i] = tags_expand_template(template[i], tags);
|
||||||
|
}
|
||||||
|
|
3
tag.h
3
tag.h
|
@ -50,3 +50,6 @@ void tag_set_destroy(struct tag_set *set);
|
||||||
|
|
||||||
/* Utility functions */
|
/* Utility functions */
|
||||||
char *tags_expand_template(const char *template, const struct tag_set *tags);
|
char *tags_expand_template(const char *template, const struct tag_set *tags);
|
||||||
|
void tags_expand_templates(
|
||||||
|
char *expanded[], const char *template[], size_t nmemb,
|
||||||
|
const struct tag_set *tags);
|
||||||
|
|
Loading…
Add table
Reference in a new issue