Tray: Implement dbusmenu

Co-authored-by: Ian Fan <ianfan0@gmail.com>
Co-authored-by: Nathan Schulte <nmschulte@gmail.com>

Signed-off-by: Felix Weilbach <felix.weilbach@t-online.de>
This commit is contained in:
Felix Weilbach 2021-05-30 20:45:01 +02:00 committed by Giancarlo Razzolini
parent 3fc5ba6feb
commit fffe886a14
No known key found for this signature in database
GPG key ID: 354AAB6377B981BC
11 changed files with 1468 additions and 11 deletions

View file

@ -33,6 +33,7 @@ struct swaybar {
struct zxdg_output_manager_v1 *xdg_output_manager; struct zxdg_output_manager_v1 *xdg_output_manager;
struct wp_cursor_shape_manager_v1 *cursor_shape_manager; struct wp_cursor_shape_manager_v1 *cursor_shape_manager;
struct wl_shm *shm; struct wl_shm *shm;
struct xdg_wm_base *wm_base;
struct swaybar_config *config; struct swaybar_config *config;
struct status_line *status; struct status_line *status;

View file

@ -15,6 +15,7 @@
struct swaybar; struct swaybar;
struct swaybar_output; struct swaybar_output;
struct swaybar_seat;
struct swaybar_pointer { struct swaybar_pointer {
struct wl_pointer *pointer; struct wl_pointer *pointer;
@ -48,8 +49,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, double x, double y, uint32_t button, struct swaybar_hotspot *hotspot, struct swaybar_seat *seat, uint32_t serial,
bool released, void *data); double x, double y, uint32_t button, bool released, void *data);
void (*destroy)(void *data); void (*destroy)(void *data);
void *data; void *data;
}; };

View file

@ -0,0 +1,27 @@
#ifndef _SWAYBAR_TRAY_DBUSMENU_H
#define _SWAYBAR_TRAY_DBUSMENU_H
#include "swaybar/bar.h"
#include "swaybar/tray/item.h"
void swaybar_dbusmenu_open(struct swaybar_sni *sni,
struct swaybar_output *output, struct swaybar_seat *seat, uint32_t serial,
int x, int y);
bool dbusmenu_pointer_button(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, uint32_t time_, uint32_t button, uint32_t state);
bool dbusmenu_pointer_motion(struct swaybar_seat *seat, struct wl_pointer *wl_pointer,
uint32_t time_, wl_fixed_t surface_x, wl_fixed_t surface_y);
bool dbusmenu_pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y);
bool dbusmenu_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
struct wl_surface *surface);
bool dbusmenu_pointer_frame(struct swaybar_seat *data, struct wl_pointer *wl_pointer);
bool dbusmenu_pointer_axis(struct swaybar_seat *data, struct wl_pointer *wl_pointer);
#endif

View file

@ -18,6 +18,7 @@ struct swaybar_pixmap {
struct swaybar_sni_slot { struct swaybar_sni_slot {
struct wl_list link; // swaybar_sni::slots struct wl_list link; // swaybar_sni::slots
struct swaybar_sni *sni; struct swaybar_sni *sni;
int menu_id;
const char *prop; const char *prop;
const char *type; const char *type;
void *dest; void *dest;
@ -48,6 +49,7 @@ struct swaybar_sni {
char *icon_theme_path; // non-standard KDE property char *icon_theme_path; // non-standard KDE property
struct wl_list slots; // swaybar_sni_slot::link struct wl_list slots; // swaybar_sni_slot::link
char **menu_icon_theme_paths;
}; };
struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray); struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray);

View file

@ -32,6 +32,9 @@ struct swaybar_tray {
list_t *basedirs; // char * list_t *basedirs; // char *
list_t *themes; // struct swaybar_theme * list_t *themes; // struct swaybar_theme *
struct swaybar_dbusmenu *menu;
struct swaybar_dbusmenu_menu *menu_pointer_focus;
}; };
struct swaybar_tray *create_tray(struct swaybar *bar); struct swaybar_tray *create_tray(struct swaybar *bar);

View file

@ -28,6 +28,7 @@
#include "pool-buffer.h" #include "pool-buffer.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h"
void free_workspaces(struct wl_list *list) { void free_workspaces(struct wl_list *list) {
struct swaybar_workspace *ws, *tmp; struct swaybar_workspace *ws, *tmp;
@ -364,6 +365,8 @@ static void handle_global(void *data, struct wl_registry *registry,
} else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) { } else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) {
bar->cursor_shape_manager = wl_registry_bind(registry, name, bar->cursor_shape_manager = wl_registry_bind(registry, name,
&wp_cursor_shape_manager_v1_interface, 1); &wp_cursor_shape_manager_v1_interface, 1);
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
bar->wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
} }
} }
@ -538,6 +541,7 @@ void bar_teardown(struct swaybar *bar) {
#if HAVE_TRAY #if HAVE_TRAY
destroy_tray(bar->tray); destroy_tray(bar->tray);
#endif #endif
xdg_wm_base_destroy(bar->wm_base);
free_outputs(&bar->outputs); free_outputs(&bar->outputs);
free_outputs(&bar->unused_outputs); free_outputs(&bar->unused_outputs);
free_seats(&bar->seats); free_seats(&bar->seats);

View file

@ -10,6 +10,10 @@
#include "swaybar/input.h" #include "swaybar/input.h"
#include "swaybar/ipc.h" #include "swaybar/ipc.h"
#if HAVE_TRAY
#include "swaybar/tray/dbusmenu.h"
#endif
void free_hotspots(struct wl_list *list) { void free_hotspots(struct wl_list *list) {
struct swaybar_hotspot *hotspot, *tmp; struct swaybar_hotspot *hotspot, *tmp;
wl_list_for_each_safe(hotspot, tmp, list, link) { wl_list_for_each_safe(hotspot, tmp, list, link) {
@ -131,10 +135,23 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
pointer->serial = serial; pointer->serial = serial;
update_cursor(seat); update_cursor(seat);
} }
#if HAVE_TRAY
if (dbusmenu_pointer_enter(data, wl_pointer, serial, surface, surface_x,
surface_y)) {
return;
}
#endif
} }
static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, struct wl_surface *surface) { uint32_t serial, struct wl_surface *surface) {
#if HAVE_TRAY
if (dbusmenu_pointer_leave(data, wl_pointer, serial, surface)) {
return;
}
#endif
struct swaybar_seat *seat = data; struct swaybar_seat *seat = data;
seat->pointer.current = NULL; seat->pointer.current = NULL;
} }
@ -144,6 +161,11 @@ static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
struct swaybar_seat *seat = data; struct swaybar_seat *seat = data;
seat->pointer.x = wl_fixed_to_double(surface_x); seat->pointer.x = wl_fixed_to_double(surface_x);
seat->pointer.y = wl_fixed_to_double(surface_y); seat->pointer.y = wl_fixed_to_double(surface_y);
#if HAVE_TRAY
if (dbusmenu_pointer_motion(data, wl_pointer, time, surface_x, surface_y)) {
return;
}
#endif
} }
static bool check_bindings(struct swaybar *bar, uint32_t button, static bool check_bindings(struct swaybar *bar, uint32_t button,
@ -160,6 +182,7 @@ static bool check_bindings(struct swaybar *bar, uint32_t button,
} }
static bool process_hotspots(struct swaybar_output *output, static bool process_hotspots(struct swaybar_output *output,
struct swaybar_seat *seat, uint32_t serial,
double x, double y, uint32_t button, uint32_t state) { double x, double y, uint32_t button, uint32_t state) {
bool released = state == WL_POINTER_BUTTON_STATE_RELEASED; bool released = state == WL_POINTER_BUTTON_STATE_RELEASED;
struct swaybar_hotspot *hotspot; struct swaybar_hotspot *hotspot;
@ -167,7 +190,7 @@ static bool process_hotspots(struct swaybar_output *output,
if (x >= hotspot->x && y >= hotspot->y if (x >= hotspot->x && y >= hotspot->y
&& 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, x, y, if (HOTSPOT_IGNORE == hotspot->callback(output, hotspot, seat, serial, x, y,
button, released, hotspot->data)) { button, released, hotspot->data)) {
return true; return true;
} }
@ -180,13 +203,19 @@ static bool process_hotspots(struct swaybar_output *output,
static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, static void 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) {
struct swaybar_seat *seat = data; struct swaybar_seat *seat = data;
#if HAVE_TRAY
if (dbusmenu_pointer_button(seat, wl_pointer, serial, time, button,
state)) {
return;
}
#endif
struct swaybar_pointer *pointer = &seat->pointer; struct swaybar_pointer *pointer = &seat->pointer;
struct swaybar_output *output = pointer->current; struct swaybar_output *output = pointer->current;
if (!sway_assert(output, "button with no active output")) { if (!sway_assert(output, "button with no active output")) {
return; return;
} }
if (process_hotspots(output, pointer->x, pointer->y, button, state)) { if (process_hotspots(output, seat, serial, pointer->x, pointer->y, button, state)) {
return; return;
} }
@ -240,7 +269,7 @@ static void process_discrete_scroll(struct swaybar_seat *seat,
struct swaybar_output *output, struct swaybar_pointer *pointer, struct swaybar_output *output, struct swaybar_pointer *pointer,
uint32_t axis, wl_fixed_t value) { uint32_t axis, wl_fixed_t value) {
uint32_t button = wl_axis_to_button(axis, value); uint32_t button = wl_axis_to_button(axis, value);
if (process_hotspots(output, pointer->x, pointer->y, button, WL_POINTER_BUTTON_STATE_PRESSED)) { if (process_hotspots(output, seat, 0, pointer->x, pointer->y, button, WL_POINTER_BUTTON_STATE_PRESSED)) {
// (Currently hotspots don't do anything on release events, so no need to emit one) // (Currently hotspots don't do anything on release events, so no need to emit one)
return; return;
} }
@ -297,6 +326,12 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
return; return;
} }
#if HAVE_TRAY
if (dbusmenu_pointer_axis(data, wl_pointer)) {
return;
}
#endif
// If there's a while since the last scroll event, // If there's a while since the last scroll event,
// set 'value' to zero as if to reset the "virtual scroll wheel" // set 'value' to zero as if to reset the "virtual scroll wheel"
if (seat->axis[axis].discrete_steps == 0 && if (seat->axis[axis].discrete_steps == 0 &&
@ -313,6 +348,12 @@ static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) {
struct swaybar_pointer *pointer = &seat->pointer; struct swaybar_pointer *pointer = &seat->pointer;
struct swaybar_output *output = pointer->current; struct swaybar_output *output = pointer->current;
#if HAVE_TRAY
if (dbusmenu_pointer_frame(data, wl_pointer)) {
return;
}
#endif
if (output == NULL) { if (output == NULL) {
return; return;
} }
@ -420,7 +461,7 @@ static void wl_touch_up(void *data, struct wl_touch *wl_touch,
} }
if (time - slot->time < 500) { if (time - slot->time < 500) {
// Tap, treat it like a pointer click // Tap, treat it like a pointer click
process_hotspots(slot->output, slot->x, slot->y, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); process_hotspots(slot->output, seat, serial, slot->x, slot->y, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
// (Currently hotspots don't do anything on release events, so no need to emit one) // (Currently hotspots don't do anything on release events, so no need to emit one)
} }
slot->output = NULL; slot->output = NULL;

View file

@ -3,7 +3,8 @@ tray_files = have_tray ? [
'tray/icon.c', 'tray/icon.c',
'tray/item.c', 'tray/item.c',
'tray/tray.c', 'tray/tray.c',
'tray/watcher.c' 'tray/watcher.c',
'tray/dbusmenu.c'
] : [] ] : []
swaybar_deps = [ swaybar_deps = [

View file

@ -159,6 +159,7 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color,
static enum hotspot_event_handling block_hotspot_callback( static enum hotspot_event_handling block_hotspot_callback(
struct swaybar_output *output, struct swaybar_hotspot *hotspot, struct swaybar_output *output, struct swaybar_hotspot *hotspot,
struct swaybar_seat *seat, uint32_t serial,
double x, double y, uint32_t button, bool released, void *data) { double x, double y, uint32_t button, bool released, 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;
@ -598,6 +599,7 @@ static uint32_t render_binding_mode_indicator(struct render_context *ctx,
static enum hotspot_event_handling workspace_hotspot_callback( static enum hotspot_event_handling workspace_hotspot_callback(
struct swaybar_output *output, struct swaybar_hotspot *hotspot, struct swaybar_output *output, struct swaybar_hotspot *hotspot,
struct swaybar_seat *seat, uint32_t serial,
double x, double y, uint32_t button, bool released, void *data) { double x, double y, uint32_t button, bool released, void *data) {
if (button != BTN_LEFT) { if (button != BTN_LEFT) {
return HOTSPOT_PROCESS; return HOTSPOT_PROCESS;

1367
swaybar/tray/dbusmenu.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,7 @@
#include "swaybar/config.h" #include "swaybar/config.h"
#include "swaybar/image.h" #include "swaybar/image.h"
#include "swaybar/input.h" #include "swaybar/input.h"
#include "swaybar/tray/dbusmenu.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"
@ -332,8 +333,9 @@ void destroy_sni(struct swaybar_sni *sni) {
free(sni); free(sni);
} }
static void handle_click(struct swaybar_sni *sni, int x, int y, static void handle_click(struct swaybar_sni *sni, struct swaybar_output *output,
uint32_t button, int delta) { struct swaybar_seat *seat, uint32_t serial, int x, int y, uint32_t button,
int delta) {
const char *method = NULL; const char *method = NULL;
struct tray_binding *binding = NULL; struct tray_binding *binding = NULL;
wl_list_for_each(binding, &sni->tray->bar->config->tray_bindings, link) { wl_list_for_each(binding, &sni->tray->bar->config->tray_bindings, link) {
@ -364,7 +366,11 @@ static void handle_click(struct swaybar_sni *sni, int x, int y,
method = "ContextMenu"; method = "ContextMenu";
} }
if (strncmp(method, "Scroll", strlen("Scroll")) == 0) { if (strcmp(method, "ContextMenu") == 0) {
if (sni->menu && !sni->tray->menu) {
swaybar_dbusmenu_open(sni, output, seat, serial, x, y);
}
} else if (strncmp(method, "Scroll", strlen("Scroll")) == 0) {
char dir = method[strlen("Scroll")]; char dir = method[strlen("Scroll")];
char *orientation = (dir == 'U' || dir == 'D') ? "vertical" : "horizontal"; char *orientation = (dir == 'U' || dir == 'D') ? "vertical" : "horizontal";
int sign = (dir == 'U' || dir == 'L') ? -1 : 1; int sign = (dir == 'U' || dir == 'L') ? -1 : 1;
@ -384,6 +390,7 @@ static int cmp_sni_id(const void *item, const void *cmp_to) {
static enum hotspot_event_handling icon_hotspot_callback( static enum hotspot_event_handling icon_hotspot_callback(
struct swaybar_output *output, struct swaybar_hotspot *hotspot, struct swaybar_output *output, struct swaybar_hotspot *hotspot,
struct swaybar_seat *seat, uint32_t serial,
double x, double y, uint32_t button, bool released, void *data) { double x, double y, uint32_t button, bool released, void *data) {
sway_log(SWAY_DEBUG, "Clicked on %s", (char *)data); sway_log(SWAY_DEBUG, "Clicked on %s", (char *)data);
@ -405,7 +412,8 @@ static enum hotspot_event_handling icon_hotspot_callback(
(int) output->output_height - config->gaps.bottom - y); (int) output->output_height - config->gaps.bottom - y);
sway_log(SWAY_DEBUG, "Guessing click position at (%d, %d)", global_x, global_y); sway_log(SWAY_DEBUG, "Guessing click position at (%d, %d)", global_x, global_y);
handle_click(sni, global_x, global_y, button, 1); // TODO get delta from event // TODO get delta from event
handle_click(sni, output, seat, serial, global_x, global_y, button, 1);
return HOTSPOT_IGNORE; return HOTSPOT_IGNORE;
} else { } else {
sway_log(SWAY_DEBUG, "but it doesn't exist"); sway_log(SWAY_DEBUG, "but it doesn't exist");