Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.6 KiB

  1. static Systray *systray = NULL;
  2. static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
  3. int
  4. width_systray(Bar *bar, BarArg *a)
  5. {
  6. unsigned int w = 0;
  7. Client *i;
  8. if (!systray)
  9. return 1;
  10. if (showsystray)
  11. for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next);
  12. return w ? w + lrpad - systrayspacing : 0;
  13. }
  14. int
  15. draw_systray(Bar *bar, BarArg *a)
  16. {
  17. if (!showsystray)
  18. return 0;
  19. XSetWindowAttributes wa;
  20. XWindowChanges wc;
  21. Client *i;
  22. unsigned int w;
  23. if (!systray) {
  24. /* init systray */
  25. if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
  26. die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
  27. wa.override_redirect = True;
  28. wa.event_mask = ButtonPressMask|ExposureMask;
  29. wa.border_pixel = 0;
  30. systray->h = MIN(a->h, drw->fonts->h);
  31. wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
  32. systray->win = XCreateSimpleWindow(dpy, root, bar->bx + a->x + lrpad / 2, bar->by + a->y + (a->h - systray->h) / 2, MIN(a->w, 1), systray->h, 0, 0, scheme[SchemeNorm][ColBg].pixel);
  33. XChangeWindowAttributes(dpy, systray->win, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &wa);
  34. XSelectInput(dpy, systray->win, SubstructureNotifyMask);
  35. XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
  36. PropModeReplace, (unsigned char *)&systrayorientation, 1);
  37. XChangeProperty(dpy, systray->win, netatom[NetWMWindowType], XA_ATOM, 32,
  38. PropModeReplace, (unsigned char *)&netatom[NetWMWindowTypeDock], 1);
  39. XMapRaised(dpy, systray->win);
  40. XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
  41. if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
  42. sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
  43. XSync(dpy, False);
  44. } else {
  45. fprintf(stderr, "dwm: unable to obtain system tray.\n");
  46. free(systray);
  47. systray = NULL;
  48. return 0;
  49. }
  50. }
  51. systray->bar = bar;
  52. wc.stack_mode = Above;
  53. wc.sibling = bar->win;
  54. XConfigureWindow(dpy, systray->win, CWSibling|CWStackMode, &wc);
  55. drw_setscheme(drw, scheme[SchemeNorm]);
  56. for (w = 0, i = systray->icons; i; i = i->next) {
  57. wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
  58. XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
  59. XMapRaised(dpy, i->win);
  60. i->x = w;
  61. XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
  62. w += i->w;
  63. if (i->next)
  64. w += systrayspacing;
  65. if (i->mon != bar->mon)
  66. i->mon = bar->mon;
  67. }
  68. XMoveResizeWindow(dpy, systray->win, bar->bx + a->x + lrpad / 2, (w ? bar->by + a->y + (a->h - systray->h) / 2: -bar->by - a->y), MAX(w, 1), systray->h);
  69. return w;
  70. }
  71. int
  72. click_systray(Bar *bar, Arg *arg, BarArg *a)
  73. {
  74. return -1;
  75. }
  76. void
  77. removesystrayicon(Client *i)
  78. {
  79. Client **ii;
  80. if (!showsystray || !i)
  81. return;
  82. for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
  83. if (ii)
  84. *ii = i->next;
  85. free(i);
  86. drawbarwin(systray->bar);
  87. }
  88. void
  89. resizerequest(XEvent *e)
  90. {
  91. XResizeRequestEvent *ev = &e->xresizerequest;
  92. Client *i;
  93. if ((i = wintosystrayicon(ev->window))) {
  94. updatesystrayicongeom(i, ev->width, ev->height);
  95. drawbarwin(systray->bar);
  96. }
  97. }
  98. void
  99. updatesystrayicongeom(Client *i, int w, int h)
  100. {
  101. if (!systray)
  102. return;
  103. int icon_height = systray->h;
  104. if (i) {
  105. i->h = icon_height;
  106. if (w == h)
  107. i->w = icon_height;
  108. else if (h == icon_height)
  109. i->w = w;
  110. else
  111. i->w = (int) ((float)icon_height * ((float)w / (float)h));
  112. applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
  113. /* force icons into the systray dimensions if they don't want to */
  114. if (i->h > icon_height) {
  115. if (i->w == i->h)
  116. i->w = icon_height;
  117. else
  118. i->w = (int) ((float)icon_height * ((float)i->w / (float)i->h));
  119. i->h = icon_height;
  120. }
  121. if (i->w > 2 * icon_height)
  122. i->w = icon_height;
  123. }
  124. }
  125. void
  126. updatesystrayiconstate(Client *i, XPropertyEvent *ev)
  127. {
  128. long flags;
  129. int code = 0;
  130. if (!showsystray || !systray || !i || ev->atom != xatom[XembedInfo] ||
  131. !(flags = getatomprop(i, xatom[XembedInfo])))
  132. return;
  133. if (flags & XEMBED_MAPPED && !i->tags) {
  134. i->tags = 1;
  135. code = XEMBED_WINDOW_ACTIVATE;
  136. XMapRaised(dpy, i->win);
  137. setclientstate(i, NormalState);
  138. }
  139. else if (!(flags & XEMBED_MAPPED) && i->tags) {
  140. i->tags = 0;
  141. code = XEMBED_WINDOW_DEACTIVATE;
  142. XUnmapWindow(dpy, i->win);
  143. setclientstate(i, WithdrawnState);
  144. }
  145. else
  146. return;
  147. sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
  148. systray->win, XEMBED_EMBEDDED_VERSION);
  149. }
  150. Client *
  151. wintosystrayicon(Window w)
  152. {
  153. if (!systray)
  154. return NULL;
  155. Client *i = NULL;
  156. if (!showsystray || !w)
  157. return i;
  158. for (i = systray->icons; i && i->win != w; i = i->next);
  159. return i;
  160. }