SHARE
TWEET

Untitled

a guest Jun 15th, 2012 87 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --- dwm.c.orig  2012-05-26 15:42:46.462912626 +0200
  2. +++ src/dwm-6.0/dwm.c   2012-05-26 15:42:15.122913347 +0200
  3. @@ -56,12 +56,30 @@
  4.  #define TAGMASK                 ((1 << LENGTH(tags)) - 1)
  5.  #define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height)
  6.  
  7. +#define SYSTEM_TRAY_REQUEST_DOCK    0
  8. +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
  9. +
  10. +/* XEMBED messages */
  11. +#define XEMBED_EMBEDDED_NOTIFY      0
  12. +#define XEMBED_WINDOW_ACTIVATE      1
  13. +#define XEMBED_FOCUS_IN             4
  14. +#define XEMBED_MODALITY_ON         10
  15. +
  16. +#define XEMBED_MAPPED              (1 << 0)
  17. +#define XEMBED_WINDOW_ACTIVATE      1
  18. +#define XEMBED_WINDOW_DEACTIVATE    2
  19. +
  20. +#define VERSION_MAJOR               0
  21. +#define VERSION_MINOR               0
  22. +#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
  23. +
  24.  /* enums */
  25.  enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
  26.  enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
  27. -enum { NetSupported, NetWMName, NetWMState,
  28. -       NetWMFullscreen, NetActiveWindow, NetWMWindowType,
  29. -       NetWMWindowTypeDialog, NetLast };     /* EWMH atoms */
  30. +enum { NetSupported, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
  31. +          NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType,
  32. +          NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */
  33. +enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
  34.  enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
  35.  enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
  36.         ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
  37. @@ -165,6 +183,12 @@
  38.         int monitor;
  39.  } Rule;
  40.  
  41. +typedef struct Systray   Systray;
  42. +struct Systray {
  43. +       Window win;
  44. +       Client *icons;
  45. +};
  46. +
  47.  /* function declarations */
  48.  static void applyrules(Client *c);
  49.  static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
  50. @@ -197,9 +221,11 @@
  51.  static void focusin(XEvent *e);
  52.  static void focusmon(const Arg *arg);
  53.  static void focusstack(const Arg *arg);
  54. +static Atom getatomprop(Client *c, Atom prop);
  55.  static XftColor getcolor(const char *colstr);
  56.  static Bool getrootptr(int *x, int *y);
  57.  static long getstate(Window w);
  58. +static unsigned int getsystraywidth();
  59.  static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
  60.  static void grabbuttons(Client *c, Bool focused);
  61.  static void grabkeys(void);
  62. @@ -218,13 +244,16 @@
  63.  static void propertynotify(XEvent *e);
  64.  static void quit(const Arg *arg);
  65.  static Monitor *recttomon(int x, int y, int w, int h);
  66. +static void removesystrayicon(Client *i);
  67.  static void resize(Client *c, int x, int y, int w, int h, Bool interact);
  68. +static void resizebarwin(Monitor *m);
  69.  static void resizeclient(Client *c, int x, int y, int w, int h);
  70.  static void resizemouse(const Arg *arg);
  71. +static void resizerequest(XEvent *e);
  72.  static void restack(Monitor *m);
  73.  static void run(void);
  74.  static void scan(void);
  75. -static Bool sendevent(Client *c, Atom proto);
  76. +static Bool sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
  77.  static void sendmon(Client *c, Monitor *m);
  78.  static void setclientstate(Client *c, long state);
  79.  static void setfocus(Client *c);
  80. @@ -252,12 +281,16 @@
  81.  static void updatenumlockmask(void);
  82.  static void updatesizehints(Client *c);
  83.  static void updatestatus(void);
  84. +static void updatesystray(void);
  85. +static void updatesystrayicongeom(Client *i, int w, int h);
  86. +static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
  87.  static void updatewindowtype(Client *c);
  88.  static void updatetitle(Client *c);
  89.  static void updatewmhints(Client *c);
  90.  static void view(const Arg *arg);
  91.  static Client *wintoclient(Window w);
  92.  static Monitor *wintomon(Window w);
  93. +static Client *wintosystrayicon(Window w);
  94.  static int xerror(Display *dpy, XErrorEvent *ee);
  95.  static int xerrordummy(Display *dpy, XErrorEvent *ee);
  96.  static int xerrorstart(Display *dpy, XErrorEvent *ee);
  97. @@ -265,6 +298,8 @@
  98.  static void bstack(Monitor *m);
  99.  
  100.  /* variables */
  101. +static Systray *systray = NULL;
  102. +static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
  103.  static const char broken[] = "broken";
  104.  static char stext[256];
  105.  static int screen;
  106. @@ -286,9 +321,10 @@
  107.         [MapRequest] = maprequest,
  108.         [MotionNotify] = motionnotify,
  109.         [PropertyNotify] = propertynotify,
  110. +       [ResizeRequest] = resizerequest,
  111.         [UnmapNotify] = unmapnotify
  112.  };
  113. -static Atom wmatom[WMLast], netatom[NetLast];
  114. +static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
  115.  static Bool running = True;
  116.  static Cursor cursor[CurLast];
  117.  static Display *dpy;
  118. @@ -506,6 +542,11 @@
  119.         XFreeCursor(dpy, cursor[CurMove]);
  120.         while(mons)
  121.                 cleanupmon(mons);
  122. +       if(showsystray) {
  123. +               XUnmapWindow(dpy, systray->win);
  124. +               XDestroyWindow(dpy, systray->win);
  125. +               free(systray);
  126. +       }
  127.         XSync(dpy, False);
  128.         XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
  129.  }
  130. @@ -542,9 +583,48 @@
  131.  
  132.  void
  133.  clientmessage(XEvent *e) {
  134. +       XWindowAttributes wa;
  135. +       XSetWindowAttributes swa;
  136.         XClientMessageEvent *cme = &e->xclient;
  137.         Client *c = wintoclient(cme->window);
  138.  
  139. +       if(showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
  140. +               /* add systray icons */
  141. +               if(cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
  142. +                       if(!(c = (Client *)calloc(1, sizeof(Client))))
  143. +                               die("fatal: could not malloc() %u bytes\n", sizeof(Client));
  144. +                       c->win = cme->data.l[2];
  145. +                       c->mon = selmon;
  146. +                       c->next = systray->icons;
  147. +                       systray->icons = c;
  148. +                       XGetWindowAttributes(dpy, c->win, &wa);
  149. +                       c->x = c->oldx = c->y = c->oldy = 0;
  150. +                       c->w = c->oldw = wa.width;
  151. +                       c->h = c->oldh = wa.height;
  152. +                       c->oldbw = wa.border_width;
  153. +                       c->bw = 0;
  154. +                       c->isfloating = True;
  155. +                       /* reuse tags field as mapped status */
  156. +                       c->tags = 1;
  157. +                       updatesizehints(c);
  158. +                       updatesystrayicongeom(c, wa.width, wa.height);
  159. +                       XAddToSaveSet(dpy, c->win);
  160. +                       XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
  161. +                       XReparentWindow(dpy, c->win, systray->win, 0, 0);
  162. +                       /* use parents background pixmap */
  163. +                       swa.background_pixmap = ParentRelative;
  164. +                       XChangeWindowAttributes(dpy, c->win, CWBackPixmap, &swa);
  165. +                       sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  166. +                       /* FIXME not sure if I have to send these events, too */
  167. +                       sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  168. +                       sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  169. +                       sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  170. +                       resizebarwin(selmon);
  171. +                       updatesystray();
  172. +                       setclientstate(c, NormalState);
  173. +               }
  174. +               return;
  175. +       }
  176.         if(!c)
  177.                 return;
  178.         if(cme->message_type == netatom[NetWMState]) {
  179. @@ -595,7 +675,7 @@
  180.                         dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
  181.                         updatebars();
  182.                         for(m = mons; m; m = m->next)
  183. -                               XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
  184. +                               resizebarwin(m);
  185.                         focus(NULL);
  186.                         arrange(NULL);
  187.                 }
  188. @@ -693,6 +773,11 @@
  189.  
  190.         if((c = wintoclient(ev->window)))
  191.                 unmanage(c, True);
  192. +       else if((c = wintosystrayicon(ev->window))) {
  193. +               removesystrayicon(c);
  194. +               resizebarwin(selmon);
  195. +               updatesystray();
  196. +       }
  197.  }
  198.  
  199.  void
  200. @@ -748,6 +833,7 @@
  201.         XftColor *col;
  202.         Client *c;
  203.  
  204. +       resizebarwin(m);
  205.         for(c = m->clients; c; c = c->next) {
  206.                 occ |= c->tags;
  207.                 if(c->isurgent)
  208. @@ -769,6 +855,9 @@
  209.         if(m == selmon) { /* status is only drawn on selected monitor */
  210.                 dc.w = TEXTW(stext);
  211.                 dc.x = m->ww - dc.w;
  212. +               if(showsystray && m == selmon) {
  213. +                       dc.x -= getsystraywidth();
  214. +               }
  215.                 if(dc.x < x) {
  216.                         dc.x = x;
  217.                         dc.w = m->ww - x;
  218. @@ -797,6 +886,7 @@
  219.  
  220.         for(m = mons; m; m = m->next)
  221.                 drawbar(m);
  222. +       updatesystray();
  223.  }
  224.  
  225.  void
  226. @@ -944,10 +1034,17 @@
  227.         unsigned long dl;
  228.         unsigned char *p = NULL;
  229.         Atom da, atom = None;
  230. +       /* FIXME getatomprop should return the number of items and a pointer to
  231. +        * the stored data instead of this workaround */
  232. +       Atom req = XA_ATOM;
  233. +       if(prop == xatom[XembedInfo])
  234. +               req = xatom[XembedInfo];
  235.  
  236. -       if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
  237. +       if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
  238.                               &da, &di, &dl, &dl, &p) == Success && p) {
  239.                 atom = *(Atom *)p;
  240. +               if(da == xatom[XembedInfo] && dl == 2)
  241. +                       atom = ((Atom *)p)[1];
  242.                 XFree(p);
  243.         }
  244.         return atom;
  245. @@ -989,6 +1086,15 @@
  246.         return result;
  247.  }
  248.  
  249. +unsigned int
  250. +getsystraywidth() {
  251. +       unsigned int w = 0;
  252. +       Client *i;
  253. +       if(showsystray)
  254. +               for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
  255. +       return w ? w + systrayspacing : 1;
  256. +}
  257. +
  258.  Bool
  259.  gettextprop(Window w, Atom atom, char *text, unsigned int size) {
  260.         char **list = NULL;
  261. @@ -1101,7 +1207,7 @@
  262.  killclient(const Arg *arg) {
  263.         if(!selmon->sel)
  264.                 return;
  265. -       if(!sendevent(selmon->sel, wmatom[WMDelete])) {
  266. +       if(!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
  267.                 XGrabServer(dpy);
  268.                 XSetErrorHandler(xerrordummy);
  269.                 XSetCloseDownMode(dpy, DestroyAll);
  270. @@ -1185,6 +1291,12 @@
  271.  maprequest(XEvent *e) {
  272.         static XWindowAttributes wa;
  273.         XMapRequestEvent *ev = &e->xmaprequest;
  274. +       Client *i;
  275. +       if((i = wintosystrayicon(ev->window))) {
  276. +               sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
  277. +       resizebarwin(selmon);
  278. +               updatesystray();
  279. +       }
  280.  
  281.         if(!XGetWindowAttributes(dpy, ev->window, &wa))
  282.                 return;
  283. @@ -1298,6 +1410,16 @@
  284.         Window trans;
  285.         XPropertyEvent *ev = &e->xproperty;
  286.  
  287. +       if((c = wintosystrayicon(ev->window))) {
  288. +               if(ev->atom == XA_WM_NORMAL_HINTS) {
  289. +                       updatesizehints(c);
  290. +                       updatesystrayicongeom(c, c->w, c->h);
  291. +               }
  292. +               else
  293. +                       updatesystrayiconstate(c, ev);
  294. +               resizebarwin(selmon);
  295. +               updatesystray();
  296. +       }
  297.         if((ev->window == root) && (ev->atom == XA_WM_NAME))
  298.                 updatestatus();
  299.         else if(ev->state == PropertyDelete)
  300. @@ -1347,12 +1469,33 @@
  301.  }
  302.  
  303.  void
  304. +removesystrayicon(Client *i) {
  305. +       Client **ii;
  306. +
  307. +       if(!showsystray || !i)
  308. +               return;
  309. +       for(ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
  310. +       if(ii)
  311. +               *ii = i->next;
  312. +       free(i);
  313. +}
  314. +
  315. +
  316. +void
  317.  resize(Client *c, int x, int y, int w, int h, Bool interact) {
  318.         if(applysizehints(c, &x, &y, &w, &h, interact))
  319.                 resizeclient(c, x, y, w, h);
  320.  }
  321.  
  322.  void
  323. +resizebarwin(Monitor *m) {
  324. +       unsigned int w = m->ww;
  325. +       if(showsystray && m == selmon)
  326. +               w -= getsystraywidth();
  327. +       XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
  328. +}
  329. +
  330. +void
  331.  resizeclient(Client *c, int x, int y, int w, int h) {
  332.         XWindowChanges wc;
  333.  
  334. @@ -1418,6 +1561,18 @@
  335.  }
  336.  
  337.  void
  338. +resizerequest(XEvent *e) {
  339. +       XResizeRequestEvent *ev = &e->xresizerequest;
  340. +       Client *i;
  341. +
  342. +       if((i = wintosystrayicon(ev->window))) {
  343. +               updatesystrayicongeom(i, ev->width, ev->height);
  344. +               resizebarwin(selmon);
  345. +               updatesystray();
  346. +       }
  347. +}
  348. +
  349. +void
  350.  restack(Monitor *m) {
  351.         Client *c;
  352.         XEvent ev;
  353. @@ -1501,25 +1656,35 @@
  354.  }
  355.  
  356.  Bool
  357. -sendevent(Client *c, Atom proto) {
  358. +sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) {
  359.         int n;
  360. -       Atom *protocols;
  361. +       Atom *protocols, mt;
  362.         Bool exists = False;
  363.         XEvent ev;
  364.  
  365. -       if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
  366. -               while(!exists && n--)
  367. -                       exists = protocols[n] == proto;
  368. -               XFree(protocols);
  369. +       if(proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
  370. +               mt = wmatom[WMProtocols];
  371. +               if(XGetWMProtocols(dpy, w, &protocols, &n)) {
  372. +                       while(!exists && n--)
  373. +                               exists = protocols[n] == proto;
  374. +                       XFree(protocols);
  375. +               }
  376. +       }
  377. +       else {
  378. +               exists = True;
  379. +               mt = proto;
  380.         }
  381.         if(exists) {
  382.                 ev.type = ClientMessage;
  383. -               ev.xclient.window = c->win;
  384. -               ev.xclient.message_type = wmatom[WMProtocols];
  385. +               ev.xclient.window = w;
  386. +               ev.xclient.message_type = mt;
  387.                 ev.xclient.format = 32;
  388. -               ev.xclient.data.l[0] = proto;
  389. -               ev.xclient.data.l[1] = CurrentTime;
  390. -               XSendEvent(dpy, c->win, False, NoEventMask, &ev);
  391. +               ev.xclient.data.l[0] = d0;
  392. +               ev.xclient.data.l[1] = d1;
  393. +               ev.xclient.data.l[2] = d2;
  394. +               ev.xclient.data.l[3] = d3;
  395. +               ev.xclient.data.l[4] = d4;
  396. +               XSendEvent(dpy, w, False, mask, &ev);
  397.         }
  398.         return exists;
  399.  }
  400. @@ -1528,7 +1693,7 @@
  401.  setfocus(Client *c) {
  402.         if(!c->neverfocus)
  403.                 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
  404. -       sendevent(c, wmatom[WMTakeFocus]);
  405. +       sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
  406.  }
  407.  
  408.  void
  409. @@ -1608,11 +1773,17 @@
  410.         wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
  411.         netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
  412.         netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
  413. +       netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
  414. +       netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
  415. +       netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
  416.         netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
  417.         netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
  418.         netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
  419.         netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
  420.         netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
  421. +       xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
  422. +       xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
  423. +       xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
  424.         /* init cursors */
  425.         cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  426.         cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  427. @@ -1627,7 +1798,9 @@
  428.         dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
  429.         dc.gc = XCreateGC(dpy, root, 0, NULL);
  430.         XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
  431. -       /* init bars */
  432. +    /* init system tray */
  433. +    updatesystray();
  434. +    /* init bars */
  435.         updatebars();
  436.         updatestatus();
  437.         /* EWMH support per view */
  438. @@ -1731,7 +1904,18 @@
  439.  togglebar(const Arg *arg) {
  440.         selmon->showbar = !selmon->showbar;
  441.         updatebarpos(selmon);
  442. -       XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
  443. +       resizebarwin(selmon);
  444. +       if(showsystray) {
  445. +               XWindowChanges wc;
  446. +               if(!selmon->showbar)
  447. +                       wc.y = -bh;
  448. +               else if(selmon->showbar) {
  449. +                       wc.y = 0;
  450. +                       if(!selmon->topbar)
  451. +                               wc.y = selmon->mh - bh;
  452. +               }
  453. +               XConfigureWindow(dpy, systray->win, CWY, &wc);
  454. +       }
  455.         arrange(selmon);
  456.  }
  457.  
  458. @@ -1827,18 +2011,28 @@
  459.                 else
  460.                         unmanage(c, False);
  461.         }
  462. +       else if((c = wintosystrayicon(ev->window))) {
  463. +               removesystrayicon(c);
  464. +               resizebarwin(selmon);
  465. +               updatesystray();
  466. +       }
  467.  }
  468.  
  469.  void
  470.  updatebars(void) {
  471. +       unsigned int w;
  472.         Monitor *m;
  473. +
  474.         XSetWindowAttributes wa = {
  475.                 .override_redirect = True,
  476.                 .background_pixmap = ParentRelative,
  477.                 .event_mask = ButtonPressMask|ExposureMask
  478.         };
  479.         for(m = mons; m; m = m->next) {
  480. -               m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
  481. +               w = m->ww;
  482. +               if(showsystray && m == selmon)
  483. +                       w -= getsystraywidth();
  484. +               m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
  485.                                           CopyFromParent, DefaultVisual(dpy, screen),
  486.                                           CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
  487.                 XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
  488. @@ -2022,6 +2216,104 @@
  489.  }
  490.  
  491.  void
  492. +updatesystrayicongeom(Client *i, int w, int h) {
  493. +       if(i) {
  494. +               i->h = bh;
  495. +               if(w == h)
  496. +                       i->w = bh;
  497. +               else if(h == bh)
  498. +                       i->w = w;
  499. +               else
  500. +                       i->w = (int) ((float)bh * ((float)w / (float)h));
  501. +               applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
  502. +               /* force icons into the systray dimenons if they don't want to */
  503. +               if(i->h > bh) {
  504. +                       if(i->w == i->h)
  505. +                               i->w = bh;
  506. +                       else
  507. +                               i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
  508. +                       i->h = bh;
  509. +               }
  510. +       }
  511. +}
  512. +
  513. +void
  514. +updatesystrayiconstate(Client *i, XPropertyEvent *ev) {
  515. +       long flags;
  516. +       int code = 0;
  517. +
  518. +       if(!showsystray || !i || ev->atom != xatom[XembedInfo] ||
  519. +                       !(flags = getatomprop(i, xatom[XembedInfo])))
  520. +               return;
  521. +
  522. +       if(flags & XEMBED_MAPPED && !i->tags) {
  523. +               i->tags = 1;
  524. +               code = XEMBED_WINDOW_ACTIVATE;
  525. +               XMapRaised(dpy, i->win);
  526. +               setclientstate(i, NormalState);
  527. +       }
  528. +       else if(!(flags & XEMBED_MAPPED) && i->tags) {
  529. +               i->tags = 0;
  530. +               code = XEMBED_WINDOW_DEACTIVATE;
  531. +               XUnmapWindow(dpy, i->win);
  532. +               setclientstate(i, WithdrawnState);
  533. +       }
  534. +       else
  535. +               return;
  536. +       sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
  537. +                       systray->win, XEMBED_EMBEDDED_VERSION);
  538. +}
  539. +
  540. +void
  541. +updatesystray(void) {
  542. +       XSetWindowAttributes wa;
  543. +       Client *i;
  544. +       unsigned int x = selmon->mx + selmon->mw;
  545. +       unsigned int w = 1;
  546. +
  547. +       if(!showsystray)
  548. +               return;
  549. +       if(!systray) {
  550. +               /* init systray */
  551. +               if(!(systray = (Systray *)calloc(1, sizeof(Systray))))
  552. +                       die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
  553. +               systray->win = XCreateSimpleWindow(dpy, root, x, selmon->by, w, bh, 0, 0, dc.sel[ColBG].pixel);
  554. +               wa.event_mask        = ButtonPressMask | ExposureMask;
  555. +               wa.override_redirect = True;
  556. +               wa.background_pixmap = ParentRelative;
  557. +               wa.background_pixel  = dc.norm[ColBG].pixel;
  558. +               XSelectInput(dpy, systray->win, SubstructureNotifyMask);
  559. +               XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
  560. +                               PropModeReplace, (unsigned char *)&systrayorientation, 1);
  561. +               XChangeWindowAttributes(dpy, systray->win, CWEventMask | CWOverrideRedirect | CWBackPixel, &wa);
  562. +               XMapRaised(dpy, systray->win);
  563. +               XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
  564. +               if(XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
  565. +                       sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
  566. +                       XSync(dpy, False);
  567. +               }
  568. +               else {
  569. +                       fprintf(stderr, "dwm: unable to obtain system tray.\n");
  570. +                       free(systray);
  571. +                       systray = NULL;
  572. +                       return;
  573. +               }
  574. +       }
  575. +       for(w = 0, i = systray->icons; i; i = i->next) {
  576. +               XMapRaised(dpy, i->win);
  577. +               w += systrayspacing;
  578. +               XMoveResizeWindow(dpy, i->win, (i->x = w), 0, i->w, i->h);
  579. +               w += i->w;
  580. +               if(i->mon != selmon)
  581. +                       i->mon = selmon;
  582. +       }
  583. +       w = w ? w + systrayspacing : 1;
  584. +       x -= w;
  585. +       XMoveResizeWindow(dpy, systray->win, x, selmon->by, w, bh);
  586. +       XSync(dpy, False);
  587. +}
  588. +
  589. +void
  590.  updatewindowtype(Client *c) {
  591.         Atom state = getatomprop(c, netatom[NetWMState]);
  592.         Atom wtype = getatomprop(c, netatom[NetWMWindowType]);
  593. @@ -2106,6 +2398,16 @@
  594.         return selmon;
  595.  }
  596.  
  597. +Client *
  598. +wintosystrayicon(Window w) {
  599. +       Client *i = NULL;
  600. +
  601. +       if(!showsystray || !w)
  602. +               return i;
  603. +       for(i = systray->icons; i && i->win != w; i = i->next) ;
  604. +       return i;
  605. +}
  606. +
  607.  /* There's no way to check accesses to destroyed windows, thus those cases are
  608.   * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  609.   * default error handler, which may call exit.  */
RAW Paste Data
Top