mirror of
https://github.com/swaywm/sway.git
synced 2024-12-28 07:56:31 +01:00
Reorganize Tray Code
Remove tray code from bar.c and render.c
This commit is contained in:
parent
790887ce76
commit
1451ee8fd1
5 changed files with 152 additions and 123 deletions
|
@ -15,6 +15,9 @@ struct bar {
|
||||||
int ipc_socketfd;
|
int ipc_socketfd;
|
||||||
int status_read_fd;
|
int status_read_fd;
|
||||||
pid_t status_command_pid;
|
pid_t status_command_pid;
|
||||||
|
#ifdef ENABLE_TRAY
|
||||||
|
pid_t xembed_pid;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct output {
|
struct output {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "swaybar/tray/dbus.h"
|
#include "swaybar/tray/dbus.h"
|
||||||
#include "swaybar/tray/sni.h"
|
#include "swaybar/tray/sni.h"
|
||||||
|
#include "swaybar/bar.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
extern struct tray *tray;
|
extern struct tray *tray;
|
||||||
|
@ -14,13 +15,18 @@ struct tray {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the tray host with D-Bus
|
* Processes a mouse event on the bar
|
||||||
*/
|
*/
|
||||||
int init_tray();
|
void tray_mouse_event(struct output *output, int x, int y,
|
||||||
|
uint32_t button, uint32_t state);
|
||||||
|
|
||||||
|
uint32_t tray_render(struct output *output, struct config *config);
|
||||||
|
|
||||||
|
void tray_upkeep(struct bar *bar);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an item if `x` and `y` collide with it and NULL otherwise
|
* Initializes the tray with D-Bus
|
||||||
*/
|
*/
|
||||||
struct StatusNotifierItem *collides_with_sni(int x, int y);
|
void init_tray();
|
||||||
|
|
||||||
#endif /* _SWAYBAR_TRAY_H */
|
#endif /* _SWAYBAR_TRAY_H */
|
||||||
|
|
|
@ -27,6 +27,9 @@ static void bar_init(struct bar *bar) {
|
||||||
bar->config = init_config();
|
bar->config = init_config();
|
||||||
bar->status = init_status_line();
|
bar->status = init_status_line();
|
||||||
bar->outputs = create_list();
|
bar->outputs = create_list();
|
||||||
|
#ifdef ENABLE_TRAY
|
||||||
|
bar->xembed_pid = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spawn_status_cmd_proc(struct bar *bar) {
|
static void spawn_status_cmd_proc(struct bar *bar) {
|
||||||
|
@ -57,24 +60,6 @@ static void spawn_status_cmd_proc(struct bar *bar) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_TRAY
|
|
||||||
static void spawn_xembed_sni_proxy() {
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (pid == 0) {
|
|
||||||
int wstatus;
|
|
||||||
do {
|
|
||||||
pid = fork();
|
|
||||||
if (pid == 0) {
|
|
||||||
execlp("xembedsniproxy", "xembedsniproxy", NULL);
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
waitpid(pid, &wstatus, 0);
|
|
||||||
} while (!WIFEXITED(wstatus));
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct output *new_output(const char *name) {
|
struct output *new_output(const char *name) {
|
||||||
struct output *output = malloc(sizeof(struct output));
|
struct output *output = malloc(sizeof(struct output));
|
||||||
output->name = strdup(name);
|
output->name = strdup(name);
|
||||||
|
@ -122,27 +107,7 @@ static void mouse_button_notify(struct window *window, int x, int y,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_TRAY
|
#ifdef ENABLE_TRAY
|
||||||
uint32_t tray_padding = swaybar.config->tray_padding;
|
tray_mouse_event(clicked_output, x, y, button, state_w);
|
||||||
int tray_width = window->width * window->scale;
|
|
||||||
|
|
||||||
for (int i = 0; i < clicked_output->items->length; ++i) {
|
|
||||||
struct sni_icon_ref *item =
|
|
||||||
clicked_output->items->items[i];
|
|
||||||
int icon_width = cairo_image_surface_get_width(item->icon);
|
|
||||||
|
|
||||||
tray_width -= tray_padding;
|
|
||||||
if (x <= tray_width && x >= tray_width - icon_width) {
|
|
||||||
if (button == swaybar.config->activate_button) {
|
|
||||||
sni_activate(item->ref, x, y);
|
|
||||||
} else if (button == swaybar.config->context_button) {
|
|
||||||
sni_context_menu(item->ref, x, y);
|
|
||||||
} else if (button == swaybar.config->secondary_button) {
|
|
||||||
sni_secondary(item->ref, x, y);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tray_width -= icon_width;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,20 +200,7 @@ void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) {
|
||||||
spawn_status_cmd_proc(bar);
|
spawn_status_cmd_proc(bar);
|
||||||
|
|
||||||
#ifdef ENABLE_TRAY
|
#ifdef ENABLE_TRAY
|
||||||
// We should have at least one output to serve the tray to
|
init_tray(bar);
|
||||||
if (!swaybar.config->tray_output || strcmp(swaybar.config->tray_output, "none") != 0) {
|
|
||||||
/* Connect to the D-Bus */
|
|
||||||
dbus_init();
|
|
||||||
|
|
||||||
/* Start the SNI watcher */
|
|
||||||
init_sni_watcher();
|
|
||||||
|
|
||||||
/* Start the SNI host */
|
|
||||||
init_tray();
|
|
||||||
|
|
||||||
/* Start xembedsniproxy */
|
|
||||||
spawn_xembed_sni_proxy();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,6 +252,8 @@ void bar_run(struct bar *bar) {
|
||||||
|
|
||||||
event_loop_poll();
|
event_loop_poll();
|
||||||
#ifdef ENABLE_TRAY
|
#ifdef ENABLE_TRAY
|
||||||
|
tray_upkeep(bar);
|
||||||
|
|
||||||
dispatch_dbus();
|
dispatch_dbus();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,72 +302,9 @@ void render(struct output *output, struct config *config, struct status_line *li
|
||||||
cairo_paint(cairo);
|
cairo_paint(cairo);
|
||||||
|
|
||||||
#ifdef ENABLE_TRAY
|
#ifdef ENABLE_TRAY
|
||||||
// Tray icons
|
uint32_t tray_width = tray_render(output, config);
|
||||||
uint32_t tray_padding = config->tray_padding;
|
|
||||||
unsigned int tray_width = window->width * window->scale;
|
|
||||||
const int item_size = (window->height * window->scale) - (2 * tray_padding);
|
|
||||||
|
|
||||||
if (item_size < 0) {
|
|
||||||
// Can't render items if the padding is too large
|
|
||||||
goto no_tray;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config->tray_output && strcmp(config->tray_output, output->name) != 0) {
|
|
||||||
goto no_tray;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < tray->items->length; ++i) {
|
|
||||||
struct StatusNotifierItem *item =
|
|
||||||
tray->items->items[i];
|
|
||||||
if (!item->image) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sni_icon_ref *render_item = NULL;
|
|
||||||
int j;
|
|
||||||
for (j = i; j < output->items->length; ++j) {
|
|
||||||
struct sni_icon_ref *ref =
|
|
||||||
output->items->items[j];
|
|
||||||
if (ref->ref == item) {
|
|
||||||
render_item = ref;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
sni_icon_ref_free(ref);
|
|
||||||
list_del(output->items, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!render_item) {
|
|
||||||
render_item = sni_icon_ref_create(item, item_size);
|
|
||||||
list_add(output->items, render_item);
|
|
||||||
} else if (item->dirty) {
|
|
||||||
// item needs re-render
|
|
||||||
sni_icon_ref_free(render_item);
|
|
||||||
output->items->items[j] = render_item =
|
|
||||||
sni_icon_ref_create(item, item_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
tray_width -= tray_padding;
|
|
||||||
tray_width -= item_size;
|
|
||||||
|
|
||||||
cairo_operator_t op = cairo_get_operator(cairo);
|
|
||||||
cairo_set_operator(cairo, CAIRO_OPERATOR_OVER);
|
|
||||||
cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding);
|
|
||||||
cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
cairo_set_operator(cairo, op);
|
|
||||||
|
|
||||||
item->dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (tray_width != window->width * window->scale) {
|
|
||||||
tray_width -= tray_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
no_tray:
|
|
||||||
#else
|
#else
|
||||||
const int tray_width = window->width * window->scale;
|
const uint32_t tray_width = window->width * window->scale;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Command output
|
// Command output
|
||||||
|
|
|
@ -2,12 +2,15 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <dbus/dbus.h>
|
#include <dbus/dbus.h>
|
||||||
#include "swaybar/bar.h"
|
#include "swaybar/bar.h"
|
||||||
#include "swaybar/tray/tray.h"
|
#include "swaybar/tray/tray.h"
|
||||||
#include "swaybar/tray/dbus.h"
|
#include "swaybar/tray/dbus.h"
|
||||||
#include "swaybar/tray/sni.h"
|
#include "swaybar/tray/sni.h"
|
||||||
|
#include "swaybar/tray/sni_watcher.h"
|
||||||
#include "swaybar/bar.h"
|
#include "swaybar/bar.h"
|
||||||
|
#include "swaybar/config.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
@ -184,7 +187,7 @@ static DBusHandlerResult signal_handler(DBusConnection *connection,
|
||||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int init_tray() {
|
static int init_host() {
|
||||||
tray = (struct tray *)malloc(sizeof(tray));
|
tray = (struct tray *)malloc(sizeof(tray));
|
||||||
|
|
||||||
tray->items = create_list();
|
tray->items = create_list();
|
||||||
|
@ -277,3 +280,129 @@ err:
|
||||||
free(name);
|
free(name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tray_mouse_event(struct output *output, int x, int y,
|
||||||
|
uint32_t button, uint32_t state) {
|
||||||
|
|
||||||
|
struct window *window = output->window;
|
||||||
|
uint32_t tray_padding = swaybar.config->tray_padding;
|
||||||
|
int tray_width = window->width * window->scale;
|
||||||
|
|
||||||
|
for (int i = 0; i < output->items->length; ++i) {
|
||||||
|
struct sni_icon_ref *item =
|
||||||
|
output->items->items[i];
|
||||||
|
int icon_width = cairo_image_surface_get_width(item->icon);
|
||||||
|
|
||||||
|
tray_width -= tray_padding;
|
||||||
|
if (x <= tray_width && x >= tray_width - icon_width) {
|
||||||
|
if (button == swaybar.config->activate_button) {
|
||||||
|
sni_activate(item->ref, x, y);
|
||||||
|
} else if (button == swaybar.config->context_button) {
|
||||||
|
sni_context_menu(item->ref, x, y);
|
||||||
|
} else if (button == swaybar.config->secondary_button) {
|
||||||
|
sni_secondary(item->ref, x, y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tray_width -= icon_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tray_render(struct output *output, struct config *config) {
|
||||||
|
struct window *window = output->window;
|
||||||
|
cairo_t *cairo = window->cairo;
|
||||||
|
|
||||||
|
// Tray icons
|
||||||
|
uint32_t tray_padding = config->tray_padding;
|
||||||
|
uint32_t tray_width = window->width * window->scale;
|
||||||
|
const int item_size = (window->height * window->scale) - (2 * tray_padding);
|
||||||
|
|
||||||
|
if (item_size < 0) {
|
||||||
|
// Can't render items if the padding is too large
|
||||||
|
return tray_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->tray_output && strcmp(config->tray_output, output->name) != 0) {
|
||||||
|
return tray_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < tray->items->length; ++i) {
|
||||||
|
struct StatusNotifierItem *item =
|
||||||
|
tray->items->items[i];
|
||||||
|
if (!item->image) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sni_icon_ref *render_item = NULL;
|
||||||
|
int j;
|
||||||
|
for (j = i; j < output->items->length; ++j) {
|
||||||
|
struct sni_icon_ref *ref =
|
||||||
|
output->items->items[j];
|
||||||
|
if (ref->ref == item) {
|
||||||
|
render_item = ref;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
sni_icon_ref_free(ref);
|
||||||
|
list_del(output->items, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!render_item) {
|
||||||
|
render_item = sni_icon_ref_create(item, item_size);
|
||||||
|
list_add(output->items, render_item);
|
||||||
|
} else if (item->dirty) {
|
||||||
|
// item needs re-render
|
||||||
|
sni_icon_ref_free(render_item);
|
||||||
|
output->items->items[j] = render_item =
|
||||||
|
sni_icon_ref_create(item, item_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
tray_width -= tray_padding;
|
||||||
|
tray_width -= item_size;
|
||||||
|
|
||||||
|
cairo_operator_t op = cairo_get_operator(cairo);
|
||||||
|
cairo_set_operator(cairo, CAIRO_OPERATOR_OVER);
|
||||||
|
cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding);
|
||||||
|
cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size);
|
||||||
|
cairo_fill(cairo);
|
||||||
|
cairo_set_operator(cairo, op);
|
||||||
|
|
||||||
|
item->dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (tray_width != window->width * window->scale) {
|
||||||
|
tray_width -= tray_padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tray_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tray_upkeep(struct bar *bar) {
|
||||||
|
if (!bar->xembed_pid ||
|
||||||
|
(bar->xembed_pid == waitpid(bar->xembed_pid, NULL, WNOHANG))) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
execlp("xembedsniproxy", "xembedsniproxy", NULL);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
} else {
|
||||||
|
bar->xembed_pid = pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_tray(struct bar *bar) {
|
||||||
|
if (!bar->config->tray_output || strcmp(bar->config->tray_output, "none") != 0) {
|
||||||
|
/* Connect to the D-Bus */
|
||||||
|
dbus_init();
|
||||||
|
|
||||||
|
/* Start the SNI watcher */
|
||||||
|
init_sni_watcher();
|
||||||
|
|
||||||
|
/* Start the SNI host */
|
||||||
|
init_host();
|
||||||
|
|
||||||
|
/* Start xembedsniproxy */
|
||||||
|
tray_upkeep(bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue