Add systray
This commit is contained in:
parent
59c1200fde
commit
2004e5dddf
5
bar.h
5
bar.h
|
@ -12,8 +12,9 @@
|
|||
*/
|
||||
static const BarRule barrules[] = {
|
||||
/* monitor bar alignment widthfunc drawfunc clickfunc name */
|
||||
{ -1, 0, BAR_ALIGN_RIGHT, width_tags, draw_tags, click_tags, "tags" },
|
||||
{ -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, "tags" },
|
||||
{ -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, "layout" },
|
||||
{ 'A', 0, BAR_ALIGN_LEFT, width_status, draw_status, click_status, "status" },
|
||||
//{ 'A', 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, "status" },
|
||||
{ 'A', 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, "systray" },
|
||||
{ -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, "wintitle" },
|
||||
};
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
/* Todo: fill this with shit */
|
||||
#include "../toggle.h"
|
||||
#include "tags.c"
|
||||
#include "layoutindicator.c"
|
||||
#include "statusbar.c"
|
||||
#include "title.c"
|
||||
#if USESYSTRAY
|
||||
#include "systray.c"
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
/* Todo: fill this with shit */
|
||||
#include "../toggle.h"
|
||||
#include "tags.h"
|
||||
#include "layoutindicator.h"
|
||||
#include "statusbar.h"
|
||||
#include "title.h"
|
||||
#if USESYSTRAY
|
||||
#include "systray.h"
|
||||
#endif
|
||||
|
|
178
bar/systray.c
Normal file
178
bar/systray.c
Normal file
|
@ -0,0 +1,178 @@
|
|||
static Systray *systray = NULL;
|
||||
static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
|
||||
|
||||
int
|
||||
width_systray(Bar *bar, BarWidthArg *a)
|
||||
{
|
||||
unsigned int w = 0;
|
||||
Client *i;
|
||||
if (!systray)
|
||||
return 1;
|
||||
if (!hidesystray)
|
||||
for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next);
|
||||
return w ? w + lrpad - systrayspacing : 0;
|
||||
}
|
||||
|
||||
int
|
||||
draw_systray(Bar *bar, BarDrawArg *a)
|
||||
{
|
||||
if (hidesystray) {
|
||||
if (systray)
|
||||
XMoveWindow(dpy, systray->win, -500, bar->by);
|
||||
return a->x;
|
||||
}
|
||||
|
||||
XSetWindowAttributes wa;
|
||||
Client *i;
|
||||
unsigned int w;
|
||||
|
||||
if (!systray) {
|
||||
/* init systray */
|
||||
if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
|
||||
die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
|
||||
|
||||
wa.override_redirect = True;
|
||||
wa.event_mask = ButtonPressMask|ExposureMask;
|
||||
wa.border_pixel = 0;
|
||||
wa.background_pixel = 0;
|
||||
wa.colormap = cmap;
|
||||
systray->win = XCreateWindow(dpy, root, bar->bx + a->x + lrpad / 2, bar->by, MAX(a->w + 40, 1), bar->bh, 0, depth,
|
||||
InputOutput, visual,
|
||||
CWOverrideRedirect|CWBorderPixel|CWBackPixel|CWColormap|CWEventMask, &wa); // CWBackPixmap
|
||||
|
||||
XSelectInput(dpy, systray->win, SubstructureNotifyMask);
|
||||
XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
|
||||
PropModeReplace, (unsigned char *)&systrayorientation, 1);
|
||||
XChangeProperty(dpy, systray->win, netatom[NetSystemTrayVisual], XA_VISUALID, 32,
|
||||
PropModeReplace, (unsigned char *)&visual->visualid, 1);
|
||||
XChangeProperty(dpy, systray->win, netatom[NetWMWindowType], XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *)&netatom[NetWMWindowTypeDock], 1);
|
||||
XMapRaised(dpy, systray->win);
|
||||
XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
|
||||
if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
|
||||
sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
|
||||
XSync(dpy, False);
|
||||
} else {
|
||||
fprintf(stderr, "speedwm: unable to obtain system tray.\n");
|
||||
free(systray);
|
||||
systray = NULL;
|
||||
return a->x;
|
||||
}
|
||||
}
|
||||
|
||||
systray->bar = bar;
|
||||
|
||||
drw_setscheme(drw, scheme[SchemeSystray]);
|
||||
for (w = 0, i = systray->icons; i; i = i->next) {
|
||||
wa.background_pixel = 0;
|
||||
XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
|
||||
XMapRaised(dpy, i->win);
|
||||
i->x = w;
|
||||
XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
|
||||
w += i->w;
|
||||
if (i->next)
|
||||
w += systrayspacing;
|
||||
if (i->mon != bar->mon)
|
||||
i->mon = bar->mon;
|
||||
}
|
||||
|
||||
XMoveResizeWindow(dpy, systray->win, bar->bx + a->x + lrpad / 2, (w ? bar->by : -bar->by), MAX(w, 1), bar->bh);
|
||||
return a->x + a->w;
|
||||
}
|
||||
|
||||
int
|
||||
click_systray(Bar *bar, Arg *arg, BarClickArg *a)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
removesystrayicon(Client *i)
|
||||
{
|
||||
Client **ii;
|
||||
|
||||
if (hidesystray || !i)
|
||||
return;
|
||||
for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
|
||||
if (ii)
|
||||
*ii = i->next;
|
||||
free(i);
|
||||
drawbarwin(systray->bar);
|
||||
}
|
||||
|
||||
void
|
||||
resizerequest(XEvent *e)
|
||||
{
|
||||
XResizeRequestEvent *ev = &e->xresizerequest;
|
||||
Client *i;
|
||||
|
||||
if ((i = wintosystrayicon(ev->window))) {
|
||||
updatesystrayicongeom(i, ev->width, ev->height);
|
||||
drawbarwin(systray->bar);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
updatesystrayicongeom(Client *i, int w, int h)
|
||||
{
|
||||
if (i) {
|
||||
i->h = bh;
|
||||
if (w == h)
|
||||
i->w = bh;
|
||||
else if (h == bh)
|
||||
i->w = w;
|
||||
else
|
||||
i->w = (int) ((float)bh * ((float)w / (float)h));
|
||||
applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
|
||||
/* force icons into the systray dimensions if they don't want to */
|
||||
if (i->h > bh) {
|
||||
if (i->w == i->h)
|
||||
i->w = bh;
|
||||
else
|
||||
i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
|
||||
i->h = bh;
|
||||
}
|
||||
if (i->w > 2*bh)
|
||||
i->w = bh;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
updatesystrayiconstate(Client *i, XPropertyEvent *ev)
|
||||
{
|
||||
long flags;
|
||||
int code = 0;
|
||||
|
||||
if (hidesystray || !systray || !i || ev->atom != xatom[XembedInfo] ||
|
||||
!(flags = getatomprop(i, xatom[XembedInfo])))
|
||||
return;
|
||||
|
||||
if (flags & XEMBED_MAPPED && !i->tags) {
|
||||
i->tags = 1;
|
||||
code = XEMBED_WINDOW_ACTIVATE;
|
||||
XMapRaised(dpy, i->win);
|
||||
setclientstate(i, NormalState);
|
||||
}
|
||||
else if (!(flags & XEMBED_MAPPED) && i->tags) {
|
||||
i->tags = 0;
|
||||
code = XEMBED_WINDOW_DEACTIVATE;
|
||||
XUnmapWindow(dpy, i->win);
|
||||
setclientstate(i, WithdrawnState);
|
||||
}
|
||||
else
|
||||
return;
|
||||
sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
|
||||
systray->win, XEMBED_EMBEDDED_VERSION);
|
||||
}
|
||||
|
||||
Client *
|
||||
wintosystrayicon(Window w)
|
||||
{
|
||||
if (!systray)
|
||||
return NULL;
|
||||
Client *i = NULL;
|
||||
if (hidesystray || !w)
|
||||
return i;
|
||||
for (i = systray->icons; i && i->win != w; i = i->next);
|
||||
return i;
|
||||
}
|
41
bar/systray.h
Normal file
41
bar/systray.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
||||
#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
|
||||
|
||||
/* XEMBED messages */
|
||||
#define XEMBED_EMBEDDED_NOTIFY 0
|
||||
#define XEMBED_WINDOW_ACTIVATE 1
|
||||
#define XEMBED_FOCUS_IN 4
|
||||
#define XEMBED_MODALITY_ON 10
|
||||
|
||||
#define XEMBED_MAPPED (1 << 0)
|
||||
#define XEMBED_WINDOW_ACTIVATE 1
|
||||
#define XEMBED_WINDOW_DEACTIVATE 2
|
||||
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 0
|
||||
#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
|
||||
|
||||
/* enums */
|
||||
enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
|
||||
|
||||
typedef struct Systray Systray;
|
||||
struct Systray {
|
||||
Window win;
|
||||
Client *icons;
|
||||
Bar *bar;
|
||||
};
|
||||
|
||||
/* bar integration */
|
||||
static int width_systray(Bar *bar, BarWidthArg *a);
|
||||
static int draw_systray(Bar *bar, BarDrawArg *a);
|
||||
static int click_systray(Bar *bar, Arg *arg, BarClickArg *a);
|
||||
|
||||
/* function declarations */
|
||||
static Atom getatomprop(Client *c, Atom prop);
|
||||
static void removesystrayicon(Client *i);
|
||||
static void resizerequest(XEvent *e);
|
||||
static void updatesystrayicongeom(Client *i, int w, int h);
|
||||
static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
|
||||
static void togglesystray();
|
||||
static Client *wintosystrayicon(Window w);
|
||||
|
|
@ -22,7 +22,7 @@ speedwm.bar.hide.floating: 0 ! Hide the floating window indicator (0/
|
|||
speedwm.bar.hide.layout: 0 ! Hide the layout indicator (0/1)
|
||||
speedwm.bar.hide.sticky: 0 ! Hide the sticky indicator (0/1)
|
||||
speedwm.bar.hide.status: 0 ! Hide the status bar (0/1)
|
||||
speedwm.bar.hide.systray: 1 ! Hide the systray (0/1)
|
||||
speedwm.bar.hide.systray: 0 ! Hide the systray (0/1)
|
||||
speedwm.bar.hide.title: 0 ! Hide the window title (0/1)
|
||||
speedwm.bar.hide.unseltitle: 0 ! Hide the unselected window title (0/1)
|
||||
speedwm.bar.hide.icon: 0 ! Hide the window icon (0/1)
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
- 58 - Remove the scratchpad
|
||||
- 59 - Reset layout/mfact
|
||||
- 60 - Reset mastercount
|
||||
- 61 - Show/Hide systray
|
||||
- 61 - Unused
|
||||
- 62 - Hide all windows
|
||||
- 63 - Show all windows
|
||||
- 64 - Reset mfact
|
||||
|
|
|
@ -79,11 +79,6 @@ static Key keys[] = {
|
|||
{ MODIFIER1|CONTROL|SHIFT, -1, XK_b, spawn, cmd( "speedwm-btctrl" ) },
|
||||
{ MODIFIER1|CONTROL|SHIFT, -1, XK_r, spawn, cmd( "libspeedwm --perform core_wm_restart; speedwm -s 'Loading'" ) },
|
||||
|
||||
/* System tray */
|
||||
#if USESYSTRAY
|
||||
{ MODIFIER1, -1, XK_s, togglesystray, {0} },
|
||||
#endif
|
||||
|
||||
/* Switcher */
|
||||
#if USESWITCHER
|
||||
{ MODIFIER1, -1, XK_Tab, switcherstart, {0} },
|
||||
|
|
|
@ -143,7 +143,7 @@ static int hideunselectedtitle = 0; /* Hide unselected title (1)
|
|||
static int hidestatus = 0; /* Hide status bar (1) or show (0) */
|
||||
static int hideicon = 0; /* Hide icon (1) or show (0) */
|
||||
static int hidetags = 0; /* Hide status bar (1) or show (0) */
|
||||
static int hidesystray = 1; /* Hide systray by default (1) or show (0) */
|
||||
static int hidesystray = 0; /* Hide systray by default (1) or show (0) */
|
||||
static int hideemptytags = 1; /* Hide empty tags (1) or show (0) */
|
||||
static int hidetagpowerline = 0; /* Hide tag powerline (1) or show (0) */
|
||||
static int hidetitlepowerline = 0; /* Hide title powerline (1) or show (0) */
|
||||
|
|
3
signal.h
3
signal.h
|
@ -67,9 +67,6 @@ static Signal signals[] = {
|
|||
{ 58, scratchpad_remove, {0} },
|
||||
{ 59, reset_layout, {0} },
|
||||
{ 60, resetmastercount, {0} },
|
||||
#if USESYSTRAY
|
||||
{ 61, togglesystray, {0} },
|
||||
#endif
|
||||
{ 62, hideall, {0} },
|
||||
{ 63, showall, {0} },
|
||||
{ 64, reset_mfact, {0} },
|
||||
|
|
252
speedwm.c
252
speedwm.c
|
@ -104,6 +104,10 @@ enum { NetSupported, NetWMName,
|
|||
NetWMWindowTypeDialog, NetClientList, NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop,
|
||||
#if USEFADE
|
||||
NetWMWindowsOpacity,
|
||||
#endif
|
||||
#if USESYSTRAY
|
||||
NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
|
||||
NetSystemTrayVisual, NetWMWindowTypeDock, NetSystemTrayOrientationHorz,
|
||||
#endif
|
||||
NetClientListStacking, NetClientInfo, NetLast }; /* EWMH atoms */
|
||||
|
||||
|
@ -460,10 +464,13 @@ static Atom getatomprop(Client *c, Atom prop);
|
|||
static int getrootptr(int *x, int *y);
|
||||
static long getstate(Window w);
|
||||
static unsigned int getsystraywidth();
|
||||
//static void resizebarwin(Monitor *m);
|
||||
|
||||
/* systray */
|
||||
#if USESYSTRAY
|
||||
static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
|
||||
#else
|
||||
static int sendevent(Client *c, Atom proto);
|
||||
#endif
|
||||
|
||||
|
||||
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
||||
static void grabbuttons(Client *c, int focused);
|
||||
|
@ -781,9 +788,17 @@ static void (*handler[LASTEvent]) (XEvent *) = {
|
|||
[MapRequest] = maprequest,
|
||||
[MotionNotify] = motionnotify,
|
||||
[PropertyNotify] = propertynotify,
|
||||
#if USESYSTRAY
|
||||
[ResizeRequest] = resizerequest,
|
||||
#endif
|
||||
[UnmapNotify] = unmapnotify
|
||||
};
|
||||
#if USESYSTRAY
|
||||
static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast], motifatom;
|
||||
#else
|
||||
static Atom wmatom[WMLast], netatom[NetLast], motifatom;
|
||||
#endif
|
||||
|
||||
#if USEIPC
|
||||
static int epoll_fd;
|
||||
static int dpy_fd;
|
||||
|
@ -1409,6 +1424,17 @@ cleanup(void)
|
|||
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
||||
while (mons)
|
||||
cleanupmon(mons);
|
||||
#if USESYSTRAY
|
||||
if (!hidesystray && systray) {
|
||||
while (systray->icons)
|
||||
removesystrayicon(systray->icons);
|
||||
if (systray->win) {
|
||||
XUnmapWindow(dpy, systray->win);
|
||||
XDestroyWindow(dpy, systray->win);
|
||||
}
|
||||
free(systray);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < CurLast; i++)
|
||||
drw_cur_free(drw, cursor[i]);
|
||||
|
@ -1454,9 +1480,50 @@ clientmessage(XEvent *e)
|
|||
{
|
||||
XClientMessageEvent *cme = &e->xclient;
|
||||
Client *c = wintoclient(cme->window);
|
||||
|
||||
unsigned int i;
|
||||
|
||||
#if USESYSTRAY
|
||||
XWindowAttributes wa;
|
||||
XSetWindowAttributes swa;
|
||||
|
||||
if (!hidesystray && systray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
|
||||
/* add systray icons */
|
||||
if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
|
||||
if (!(c = (Client *)calloc(1, sizeof(Client))))
|
||||
die("fatal: could not malloc() %u bytes\n", sizeof(Client));
|
||||
if (!(c->win = cme->data.l[2])) {
|
||||
free(c);
|
||||
return;
|
||||
}
|
||||
|
||||
c->mon = selmon;
|
||||
c->next = systray->icons;
|
||||
systray->icons = c;
|
||||
XGetWindowAttributes(dpy, c->win, &wa);
|
||||
c->x = c->oldx = c->y = c->oldy = 0;
|
||||
c->w = c->oldw = wa.width;
|
||||
c->h = c->oldh = wa.height;
|
||||
c->oldbw = wa.border_width;
|
||||
c->bw = 0;
|
||||
c->isfloating = True;
|
||||
/* reuse tags field as mapped status */
|
||||
c->tags = 1;
|
||||
updatesizehints(c);
|
||||
updatesystrayicongeom(c, wa.width, wa.height);
|
||||
XAddToSaveSet(dpy, c->win);
|
||||
XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
|
||||
XReparentWindow(dpy, c->win, systray->win, 0, 0);
|
||||
/* use parents background color */
|
||||
swa.background_pixel = scheme[SchemeSystray][ColBg].pixel; /* might be a good idea to change this to SchemeBar */
|
||||
XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
|
||||
sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
|
||||
XSync(dpy, False);
|
||||
setclientstate(c, NormalState);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!c)
|
||||
return;
|
||||
if (cme->message_type == netatom[NetWMState]) {
|
||||
|
@ -1779,12 +1846,19 @@ destroynotify(XEvent *e)
|
|||
Monitor *m;
|
||||
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
||||
|
||||
if ((c = wintoclient(ev->window)))
|
||||
if ((c = wintoclient(ev->window))) {
|
||||
unmanage(c, 1);
|
||||
|
||||
else if ((c = swallowingclient(ev->window)))
|
||||
#if USESYSTRAY
|
||||
} else if (!hidesystray && (c = wintosystrayicon(ev->window))) {
|
||||
removesystrayicon(c);
|
||||
drawbarwin(systray->bar);
|
||||
#endif
|
||||
|
||||
} else if ((c = swallowingclient(ev->window))) {
|
||||
unmanage(c->swallowing, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* run ltmenu */
|
||||
#if USEMOUSE
|
||||
|
@ -2500,10 +2574,25 @@ getatomprop(Client *c, Atom prop)
|
|||
unsigned char *p = NULL;
|
||||
Atom da, atom = None;
|
||||
|
||||
#if USESYSTRAY
|
||||
Atom req = XA_ATOM;
|
||||
if (prop == xatom[XembedInfo])
|
||||
req = xatom[XembedInfo];
|
||||
#endif
|
||||
|
||||
#if USESYSTRAY
|
||||
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
|
||||
#else
|
||||
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
|
||||
#endif
|
||||
&da, &di, &dl, &dl, &p) == Success && p) {
|
||||
atom = *(Atom *)p;
|
||||
|
||||
#if USESYSTRAY
|
||||
if (da == xatom[XembedInfo] && dl == 2)
|
||||
atom = ((Atom *)p)[1];
|
||||
#endif
|
||||
|
||||
XFree(p);
|
||||
}
|
||||
return atom;
|
||||
|
@ -2642,8 +2731,6 @@ hidewin(Client *c) {
|
|||
XSelectInput(dpy, root, ra.your_event_mask);
|
||||
XSelectInput(dpy, w, ca.your_event_mask);
|
||||
XUngrabServer(dpy);
|
||||
|
||||
c->ishidden = 1;
|
||||
}
|
||||
|
||||
#if USEIPC
|
||||
|
@ -2900,8 +2987,6 @@ showwin(Client *c)
|
|||
if (!c || !HIDDEN(c))
|
||||
return;
|
||||
|
||||
c->ishidden = 0;
|
||||
|
||||
XMapWindow(dpy, c->win);
|
||||
setclientstate(c, NormalState);
|
||||
arrange(c->mon);
|
||||
|
@ -3166,7 +3251,11 @@ killclient(const Arg *arg)
|
|||
{
|
||||
if (!selmon->sel || selmon->sel->ispermanent)
|
||||
return;
|
||||
#if USESYSTRAY
|
||||
if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0, 0, 0)) {
|
||||
#else
|
||||
if (!sendevent(selmon->sel, wmatom[WMDelete])) {
|
||||
#endif
|
||||
XGrabServer(dpy);
|
||||
XSetErrorHandler(xerrordummy);
|
||||
XSetCloseDownMode(dpy, DestroyAll);
|
||||
|
@ -3187,7 +3276,11 @@ killunsel(const Arg *arg)
|
|||
|
||||
for (i = selmon->clients; i; i = i->next) {
|
||||
if (ISVISIBLE(i) && i != selmon->sel) {
|
||||
#if USESYSTRAY
|
||||
if (!sendevent(i->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0, 0, 0)) {
|
||||
#else
|
||||
if (!sendevent(selmon->sel, wmatom[WMDelete])) {
|
||||
#endif
|
||||
XGrabServer(dpy);
|
||||
XSetErrorHandler(xerrordummy);
|
||||
XSetCloseDownMode(dpy, DestroyAll);
|
||||
|
@ -3388,6 +3481,14 @@ maprequest(XEvent *e)
|
|||
static XWindowAttributes wa;
|
||||
XMapRequestEvent *ev = &e->xmaprequest;
|
||||
|
||||
#if USESYSTRAY
|
||||
Client *i;
|
||||
|
||||
if (!hidesystray && systray && (i = wintosystrayicon(ev->window))) {
|
||||
sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
|
||||
drawbarwin(systray->bar);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
|
||||
return;
|
||||
|
@ -3440,8 +3541,8 @@ window_map(Display *dpy, Client *c, int deiconify)
|
|||
Window win = c->win;
|
||||
|
||||
/* fix: hidden windows immediately get mapped */
|
||||
if (c->ishidden)
|
||||
return;
|
||||
//if (c->ishidden)
|
||||
// return;
|
||||
|
||||
if (deiconify)
|
||||
window_set_state(dpy, win, NormalState);
|
||||
|
@ -4232,6 +4333,18 @@ propertynotify(XEvent *e)
|
|||
Window trans;
|
||||
XPropertyEvent *ev = &e->xproperty;
|
||||
|
||||
#if USESYSTRAY
|
||||
if (!hidesystray && (c = wintosystrayicon(ev->window))) {
|
||||
if (ev->atom == XA_WM_NORMAL_HINTS) {
|
||||
updatesizehints(c);
|
||||
updatesystrayicongeom(c, c->w, c->h);
|
||||
}
|
||||
else
|
||||
updatesystrayiconstate(c, ev);
|
||||
drawbarwin(systray->bar);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ev->window == root) && (ev->atom == XA_WM_NAME)) {
|
||||
if (!getsignal())
|
||||
updatestatus();
|
||||
|
@ -4798,27 +4911,121 @@ setdesktopnames(void)
|
|||
XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]);
|
||||
}
|
||||
|
||||
/*
|
||||
int
|
||||
#if USESYSTRAY
|
||||
sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
|
||||
#else
|
||||
sendevent(Client *c, Atom proto)
|
||||
#endif
|
||||
{
|
||||
int n;
|
||||
Atom *protocols;
|
||||
int exists = 0;
|
||||
XEvent ev;
|
||||
|
||||
#if USESYSTRAY
|
||||
Atom mt;
|
||||
#endif
|
||||
|
||||
#if USESYSTRAY
|
||||
if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
|
||||
mt = wmatom[WMProtocols];
|
||||
if (XGetWMProtocols(dpy, w, &protocols, &n)) {
|
||||
while (!exists && n--)
|
||||
exists = protocols[n] == proto;
|
||||
XFree(protocols);
|
||||
}
|
||||
} else {
|
||||
exists = True;
|
||||
mt = proto;
|
||||
#else
|
||||
if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
|
||||
while (!exists && n--)
|
||||
exists = protocols[n] == proto;
|
||||
XFree(protocols);
|
||||
}
|
||||
#endif
|
||||
if (exists) {
|
||||
ev.type = ClientMessage;
|
||||
ev.xclient.format = 32;
|
||||
#if USESYSTRAY
|
||||
ev.xclient.window = w;
|
||||
ev.xclient.message_type = mt;
|
||||
ev.xclient.data.l[0] = d0;
|
||||
ev.xclient.data.l[1] = d1;
|
||||
ev.xclient.data.l[2] = d2;
|
||||
ev.xclient.data.l[3] = d3;
|
||||
ev.xclient.data.l[4] = d4;
|
||||
XSendEvent(dpy, w, False, mask, &ev);
|
||||
#else
|
||||
ev.xclient.window = c->win;
|
||||
ev.xclient.message_type = wmatom[WMProtocols];
|
||||
ev.xclient.data.l[0] = proto;
|
||||
ev.xclient.data.l[1] = CurrentTime;
|
||||
XSendEvent(dpy, c->win, False, NoEventMask, &ev);
|
||||
#endif
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
#if USESYSTRAY
|
||||
sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
|
||||
#else
|
||||
sendevent(Client *c, Atom proto)
|
||||
#endif
|
||||
{
|
||||
int n;
|
||||
#if USESYSTRAY
|
||||
Atom *protocols, mt;
|
||||
#else
|
||||
Atom *protocols;
|
||||
#endif
|
||||
int exists = 0;
|
||||
XEvent ev;
|
||||
|
||||
#if USESYSTRAY
|
||||
if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
|
||||
mt = wmatom[WMProtocols];
|
||||
#endif
|
||||
|
||||
#if USESYSTRAY
|
||||
if (XGetWMProtocols(dpy, w, &protocols, &n)) {
|
||||
#else
|
||||
if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
|
||||
#endif
|
||||
while (!exists && n--)
|
||||
exists = protocols[n] == proto;
|
||||
XFree(protocols);
|
||||
}
|
||||
#if USESYSTRAY
|
||||
} else {
|
||||
exists = True;
|
||||
mt = proto;
|
||||
}
|
||||
#endif
|
||||
if (exists) {
|
||||
ev.type = ClientMessage;
|
||||
ev.xclient.format = 32;
|
||||
#if USESYSTRAY
|
||||
ev.xclient.window = w;
|
||||
ev.xclient.message_type = mt;
|
||||
ev.xclient.data.l[0] = d0;
|
||||
ev.xclient.data.l[1] = d1;
|
||||
ev.xclient.data.l[2] = d2;
|
||||
ev.xclient.data.l[3] = d3;
|
||||
ev.xclient.data.l[4] = d4;
|
||||
XSendEvent(dpy, w, False, mask, &ev);
|
||||
#else
|
||||
ev.xclient.window = c->win;
|
||||
ev.xclient.message_type = wmatom[WMProtocols];
|
||||
ev.xclient.data.l[0] = proto;
|
||||
ev.xclient.data.l[1] = CurrentTime;
|
||||
XSendEvent(dpy, c->win, False, NoEventMask, &ev);
|
||||
#endif
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
|
@ -4842,7 +5049,11 @@ setfocus(Client *c)
|
|||
XA_WINDOW, 32, PropModeReplace,
|
||||
(unsigned char *) &(c->win), 1);
|
||||
}
|
||||
#if USESYSTRAY
|
||||
sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
|
||||
#else
|
||||
sendevent(c, wmatom[WMTakeFocus]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5023,6 +5234,18 @@ setup(void)
|
|||
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
|
||||
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
|
||||
|
||||
#if USESYSTRAY
|
||||
netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
|
||||
netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
|
||||
netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
|
||||
netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
|
||||
netatom[NetSystemTrayVisual] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_VISUAL", False);
|
||||
netatom[NetWMWindowTypeDock] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
|
||||
xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
|
||||
xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
|
||||
xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
|
||||
#endif
|
||||
|
||||
if (fullscreenhidebar)
|
||||
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
|
||||
|
||||
|
@ -5683,6 +5906,13 @@ unmapnotify(XEvent *e)
|
|||
setclientstate(c, WithdrawnState);
|
||||
else
|
||||
unmanage(c, 0);
|
||||
#if USESYSTRAY
|
||||
} else if (!hidesystray && (c = wintosystrayicon(ev->window))) {
|
||||
/* KLUDGE! sometimes icons occasionally unmap their windows, but do
|
||||
* _not_ destroy them. We map those windows back */
|
||||
XMapRaised(dpy, c->win);
|
||||
drawbarwin(systray->bar);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
toggle.h
2
toggle.h
|
@ -19,7 +19,7 @@ Not compatible with BSDs so for those, set this to 0. */
|
|||
|
||||
/* Miscellanious */
|
||||
#define USESWITCHER 1 /* Whether or not to include the switcher */
|
||||
#define USESYSTRAY 0 /* Whether or not to include the systray */
|
||||
#define USESYSTRAY 1 /* Whether or not to include the systray */
|
||||
#define USEROUNDCORNERS 1 /* Whether or not to include rounded corners */
|
||||
#define USEMEDIA 1 /* Whether or not to include media keys */
|
||||
#define USEMOUSE 1 /* Whether or not to include mouse binds */
|
||||
|
|
Loading…
Reference in a new issue