swaybar: implement mouse events for tray

This commit is contained in:
Ian Fan 2018-12-07 12:39:35 +00:00
parent fa2c5282c1
commit 6becde0246
3 changed files with 97 additions and 2 deletions

View file

@ -70,6 +70,8 @@ struct swaybar_output {
struct pool_buffer *current_buffer; struct pool_buffer *current_buffer;
bool dirty; bool dirty;
bool frame_scheduled; bool frame_scheduled;
uint32_t output_height, output_width, output_x, output_y;
}; };
struct swaybar_workspace { struct swaybar_workspace {

View file

@ -215,12 +215,16 @@ struct wl_output_listener output_listener = {
static void xdg_output_handle_logical_position(void *data, static void xdg_output_handle_logical_position(void *data,
struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y) { struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y) {
// Who cares struct swaybar_output *output = data;
output->output_x = x;
output->output_y = y;
} }
static void xdg_output_handle_logical_size(void *data, static void xdg_output_handle_logical_size(void *data,
struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) { struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) {
// Who cares struct swaybar_output *output = data;
output->output_height = height;
output->output_width = width;
} }
static void xdg_output_handle_done(void *data, static void xdg_output_handle_done(void *data,

View file

@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include "swaybar/bar.h" #include "swaybar/bar.h"
#include "swaybar/config.h" #include "swaybar/config.h"
#include "swaybar/input.h"
#include "swaybar/tray/host.h" #include "swaybar/tray/host.h"
#include "swaybar/tray/icon.h" #include "swaybar/tray/icon.h"
#include "swaybar/tray/item.h" #include "swaybar/tray/item.h"
@ -13,6 +14,7 @@
#include "cairo.h" #include "cairo.h"
#include "list.h" #include "list.h"
#include "log.h" #include "log.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
// TODO menu // TODO menu
@ -248,6 +250,83 @@ void destroy_sni(struct swaybar_sni *sni) {
free(sni); free(sni);
} }
static void handle_click(struct swaybar_sni *sni, int x, int y,
enum x11_button button, int delta) {
const char *method = sni->tray->bar->config->tray_bindings[button];
if (!method) {
static const char *default_bindings[10] = {
"nop",
"Activate",
"SecondaryActivate",
"ContextMenu",
"ScrollUp",
"ScrollDown",
"ScrollLeft",
"ScrollRight",
"nop",
"nop"
};
method = default_bindings[button];
}
if (strcmp(method, "nop") == 0) {
return;
}
if (sni->item_is_menu && strcmp(method, "Activate") == 0) {
method = "ContextMenu";
}
if (strncmp(method, "Scroll", strlen("Scroll")) == 0) {
char dir = method[strlen("Scroll")];
char *orientation = (dir = 'U' || dir == 'D') ? "vertical" : "horizontal";
int sign = (dir == 'U' || dir == 'L') ? -1 : 1;
int ret = sd_bus_call_method_async(sni->tray->bus, NULL, sni->service,
sni->path, sni->interface, "Scroll", NULL, NULL, "is",
delta*sign, orientation);
if (ret < 0) {
wlr_log(WLR_DEBUG, "Failed to scroll on SNI: %s", strerror(-ret));
}
} else {
int ret = sd_bus_call_method_async(sni->tray->bus, NULL, sni->service,
sni->path, sni->interface, method, NULL, NULL, "ii", x, y);
if (ret < 0) {
wlr_log(WLR_DEBUG, "Failed to click on SNI: %s", strerror(-ret));
}
}
}
static int cmp_sni_id(const void *item, const void *cmp_to) {
const struct swaybar_sni *sni = item;
return strcmp(sni->watcher_id, cmp_to);
}
static enum hotspot_event_handling icon_hotspot_callback(
struct swaybar_output *output, struct swaybar_hotspot *hotspot,
int x, int y, enum x11_button button, void *data) {
wlr_log(WLR_DEBUG, "Clicked on Status Notifier Item '%s'", (char *)data);
struct swaybar_tray *tray = output->bar->tray;
int idx = list_seq_find(tray->items, cmp_sni_id, data);
if (idx != -1) {
struct swaybar_sni *sni = tray->items->items[idx];
// guess global position since wayland doesn't expose it
struct swaybar_config *config = tray->bar->config;
int global_x = output->output_x + config->gaps.left + x;
bool top_bar = config->position & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
int global_y = output->output_y + (top_bar ? config->gaps.top + y:
(int) output->output_height - config->gaps.bottom - y);
wlr_log(WLR_DEBUG, "Guessing click at (%d, %d)", global_x, global_y);
handle_click(sni, global_x, global_y, button, 1); // TODO get delta from event
return HOTSPOT_IGNORE;
} else {
wlr_log(WLR_DEBUG, "but it doesn't exist");
}
return HOTSPOT_PROCESS;
}
uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x, uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
struct swaybar_sni *sni) { struct swaybar_sni *sni) {
uint32_t height = output->height * output->scale; uint32_t height = output->height * output->scale;
@ -316,5 +395,15 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
cairo_surface_destroy(icon); cairo_surface_destroy(icon);
struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
hotspot->x = *x;
hotspot->y = 0;
hotspot->width = height;
hotspot->height = height;
hotspot->callback = icon_hotspot_callback;
hotspot->destroy = free;
hotspot->data = strdup(sni->watcher_id);
wl_list_insert(&output->hotspots, &hotspot->link);
return output->height; return output->height;
} }