aboutsummaryrefslogtreecommitdiffstats
path: root/dwl.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwl.c')
-rw-r--r--dwl.c108
1 files changed, 101 insertions, 7 deletions
diff --git a/dwl.c b/dwl.c
index 5dd1510..ee6ad30 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2,6 +2,7 @@
* See LICENSE file for copyright and license details.
*/
#include <fcntl.h>
+#include <dbus/dbus.h>
#include <getopt.h>
#include <libinput.h>
#include <linux/input-event-codes.h>
@@ -78,6 +79,9 @@
#include "util.h"
#include "drwl.h"
+#include "dbus.h"
+#include "systray/tray.h"
+#include "systray/watcher.h"
/* macros */
#define MAX(A, B) ((A) > (B) ? (A) : (B))
@@ -96,7 +100,7 @@ enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
enum { XDGShell, LayerShell, X11 }; /* client types */
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
-enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */
+enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot, ClkTray }; /* clicks */
typedef union {
int i;
@@ -221,6 +225,7 @@ struct Monitor {
int real_width, real_height; /* non-scaled */
float scale;
} b; /* bar area */
+ Tray *tray;
struct wlr_box w; /* window area, layout-relative */
struct wl_list layers[4]; /* LayerSurface.link */
const Layout *lt[2];
@@ -412,6 +417,9 @@ static void movecenter(const Arg *arg);
static void togglegaps(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
+static void trayactivate(const Arg *arg);
+static void traymenu(const Arg *arg);
+static void traynotify(void *data);
static void unlocksession(struct wl_listener *listener, void *data);
static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
static void unmapnotify(struct wl_listener *listener, void *data);
@@ -501,6 +509,10 @@ static Monitor *selmon;
static char stext[256];
static struct wl_event_source *status_event_source;
+static DBusConnection *bus_conn;
+static struct wl_event_source *bus_source;
+static Watcher watcher = {.running = 0};
+
static const struct wlr_buffer_impl buffer_impl = {
.destroy = bufdestroy,
.begin_data_ptr_access = bufdatabegin,
@@ -834,8 +846,8 @@ bufrelease(struct wl_listener *listener, void *data)
void
buttonpress(struct wl_listener *listener, void *data)
{
- unsigned int i = 0, x = 0;
- double cx;
+ unsigned int i = 0, x = 0, ti = 0;
+ double cx, tx = 0;
unsigned int click;
struct wlr_pointer_button_event *event = data;
struct wlr_keyboard *keyboard;
@@ -845,6 +857,7 @@ buttonpress(struct wl_listener *listener, void *data)
Arg arg = {0};
Client *c;
const Button *b;
+ int traywidth;
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
handlecursoractivity();
@@ -865,6 +878,8 @@ buttonpress(struct wl_listener *listener, void *data)
(node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) &&
(buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) {
cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale;
+ traywidth = tray_get_width(selmon->tray);
+
do
x += TEXTW(selmon, tags[i]);
while (cx >= x && ++i < LENGTH(tags));
@@ -873,8 +888,16 @@ buttonpress(struct wl_listener *listener, void *data)
arg.ui = 1 << i;
} else if (cx < x + TEXTW(selmon, selmon->ltsymbol))
click = ClkLtSymbol;
- else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) {
+ else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2) && cx < selmon->b.width - traywidth) {
click = ClkStatus;
+ } else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) {
+ unsigned int tray_n_items = watcher_get_n_items(&watcher);
+ tx = selmon->b.width - traywidth;
+ do
+ tx += tray_n_items ? (int)(traywidth / tray_n_items) : 0;
+ while (cx >= tx && ++ti < tray_n_items);
+ click = ClkTray;
+ arg.ui = ti;
} else
click = ClkTitle;
}
@@ -888,7 +911,12 @@ buttonpress(struct wl_listener *listener, void *data)
mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
for (b = buttons; b < END(buttons); b++) {
if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) {
- b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg);
+ if (click == ClkTagBar && b->arg.i == 0)
+ b->func(&arg);
+ else if (click == ClkTray && b->arg.i == 0)
+ b->func(&arg);
+ else
+ b->func(&b->arg);
return;
}
}
@@ -966,6 +994,15 @@ cleanup(void)
destroykeyboardgroup(&kb_group->destroy, NULL);
+ if (watcher.running)
+ watcher_stop(&watcher);
+
+ if (showbar && showsystray) {
+ stopbus(bus_conn, bus_source);
+ dbus_connection_unref(bus_conn);
+ }
+
+
/* If it's not destroyed manually, it will cause a use-after-free of wlr_seat.
* Destroy it until it's fixed on the wlroots side */
wlr_backend_destroy(backend);
@@ -994,6 +1031,9 @@ cleanupmon(struct wl_listener *listener, void *data)
for (i = 0; i < LENGTH(m->pool); i++)
wlr_buffer_drop(&m->pool[i]->base);
+ if (showsystray)
+ destroytray(m->tray);
+
drwl_setimage(m->drw, NULL);
drwl_destroy(m->drw);
@@ -1762,6 +1802,7 @@ dirtomon(enum wlr_direction dir)
void
drawbar(Monitor *m)
{
+ int traywidth = 0;
int x, w, tw = 0;
int boxs = m->drw->font->height / 9;
int boxw = m->drw->font->height / 6 + 2;
@@ -1774,11 +1815,13 @@ drawbar(Monitor *m)
if (!(buf = bufmon(m)))
return;
+ traywidth = tray_get_width(m->tray);
+
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
drwl_setscheme(m->drw, colors[SchemeNorm]);
tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */
- drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0);
+ drwl_text(m->drw, m->b.width - (tw + traywidth), 0, tw, m->b.height, 0, stext, 0);
}
wl_list_for_each(c, &clients, link) {
@@ -1804,7 +1847,7 @@ drawbar(Monitor *m)
drwl_setscheme(m->drw, colors[SchemeNorm]);
x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0);
- if ((w = m->b.width - tw - x) > m->b.height) {
+ if ((w = m->b.width - (tw + x + traywidth)) > m->b.height) {
if (c) {
drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]);
drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0);
@@ -1816,6 +1859,15 @@ drawbar(Monitor *m)
}
}
+ if (traywidth > 0) {
+ pixman_image_composite32(PIXMAN_OP_SRC,
+ m->tray->image, NULL, m->drw->image,
+ 0, 0,
+ 0, 0,
+ m->b.width - traywidth, 0,
+ traywidth, m->b.height);
+ }
+
wlr_scene_buffer_set_dest_size(m->scene_buffer,
m->b.real_width, m->b.real_height);
wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x,
@@ -1825,6 +1877,26 @@ drawbar(Monitor *m)
}
void
+traynotify(void *data)
+{
+ Monitor *m = data;
+
+ drawbar(m);
+}
+
+void
+trayactivate(const Arg *arg)
+{
+ tray_leftclicked(selmon->tray, arg->ui);
+}
+
+void
+traymenu(const Arg *arg)
+{
+ tray_rightclicked(selmon->tray, arg->ui, dmenucmd);
+}
+
+void
drawbars(void)
{
Monitor *m = NULL;
@@ -3278,6 +3350,15 @@ setup(void)
status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy),
STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL);
+ bus_conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
+ if (!bus_conn)
+ die("Failed to connect to bus");
+ bus_source = startbus(bus_conn, event_loop);
+ if (!bus_source)
+ die("Failed to start listening to bus events");
+ if (showbar && showsystray)
+ watcher_start(&watcher, bus_conn, event_loop);
+
/* Make sure XWayland clients don't connect to the parent X server,
* e.g when running in the x11 backend or the wayland backend and the
* compositor has Xwayland support */
@@ -3825,6 +3906,7 @@ updatebar(Monitor *m)
size_t i;
int rw, rh;
char fontattrs[12];
+ Tray *tray;
wlr_output_transformed_resolution(m->wlr_output, &rw, &rh);
m->b.width = rw;
@@ -3850,6 +3932,18 @@ updatebar(Monitor *m)
m->lrpad = m->drw->font->height;
m->b.height = m->drw->font->height + 2;
m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale);
+
+ if (showsystray) {
+ if (m->tray)
+ destroytray(m->tray);
+ tray = createtray(m,
+ m->b.height, systrayspacing, colors[SchemeNorm], fonts, fontattrs,
+ &traynotify, &watcher);
+ if (!tray)
+ die("Couldn't create tray for monitor");
+ m->tray = tray;
+ wl_list_insert(&watcher.trays, &tray->link);
+ }
}
void