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.

196 lines
5.3 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. #if BAR_ALPHA_PATCH
  32. wa.background_pixel = 0;
  33. wa.colormap = cmap;
  34. systray->win = XCreateWindow(dpy, root, bar->bx + a->x + lrpad / 2, bar->by + a->y + (a->h - systray->h) / 2, MAX(a->w + 40, 1), systray->h, 0, depth,
  35. InputOutput, visual,
  36. CWOverrideRedirect|CWBorderPixel|CWBackPixel|CWColormap|CWEventMask, &wa); // CWBackPixmap
  37. #else
  38. wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
  39. 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);
  40. XChangeWindowAttributes(dpy, systray->win, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &wa);
  41. #endif // BAR_ALPHA_PATCH
  42. XSelectInput(dpy, systray->win, SubstructureNotifyMask);
  43. XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
  44. PropModeReplace, (unsigned char *)&systrayorientation, 1);
  45. #if BAR_ALPHA_PATCH
  46. XChangeProperty(dpy, systray->win, netatom[NetSystemTrayVisual], XA_VISUALID, 32,
  47. PropModeReplace, (unsigned char *)&visual->visualid, 1);
  48. #endif // BAR_ALPHA_PATCH
  49. XChangeProperty(dpy, systray->win, netatom[NetWMWindowType], XA_ATOM, 32,
  50. PropModeReplace, (unsigned char *)&netatom[NetWMWindowTypeDock], 1);
  51. XMapRaised(dpy, systray->win);
  52. XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
  53. if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
  54. sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
  55. XSync(dpy, False);
  56. } else {
  57. fprintf(stderr, "dwm: unable to obtain system tray.\n");
  58. free(systray);
  59. systray = NULL;
  60. return 0;
  61. }
  62. }
  63. systray->bar = bar;
  64. wc.stack_mode = Above;
  65. wc.sibling = bar->win;
  66. XConfigureWindow(dpy, systray->win, CWSibling|CWStackMode, &wc);
  67. drw_setscheme(drw, scheme[SchemeNorm]);
  68. for (w = 0, i = systray->icons; i; i = i->next) {
  69. #if BAR_ALPHA_PATCH
  70. wa.background_pixel = 0;
  71. #else
  72. wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
  73. #endif // BAR_ALPHA_PATCH
  74. XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
  75. XMapRaised(dpy, i->win);
  76. i->x = w;
  77. XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
  78. w += i->w;
  79. if (i->next)
  80. w += systrayspacing;
  81. if (i->mon != bar->mon)
  82. i->mon = bar->mon;
  83. }
  84. 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);
  85. return w;
  86. }
  87. int
  88. click_systray(Bar *bar, Arg *arg, BarArg *a)
  89. {
  90. return -1;
  91. }
  92. void
  93. removesystrayicon(Client *i)
  94. {
  95. Client **ii;
  96. if (!showsystray || !i)
  97. return;
  98. for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
  99. if (ii)
  100. *ii = i->next;
  101. free(i);
  102. drawbarwin(systray->bar);
  103. }
  104. void
  105. resizerequest(XEvent *e)
  106. {
  107. XResizeRequestEvent *ev = &e->xresizerequest;
  108. Client *i;
  109. if ((i = wintosystrayicon(ev->window))) {
  110. updatesystrayicongeom(i, ev->width, ev->height);
  111. drawbarwin(systray->bar);
  112. }
  113. }
  114. void
  115. updatesystrayicongeom(Client *i, int w, int h)
  116. {
  117. if (!systray)
  118. return;
  119. int icon_height = systray->h;
  120. if (i) {
  121. i->h = icon_height;
  122. if (w == h)
  123. i->w = icon_height;
  124. else if (h == icon_height)
  125. i->w = w;
  126. else
  127. i->w = (int) ((float)icon_height * ((float)w / (float)h));
  128. applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
  129. /* force icons into the systray dimensions if they don't want to */
  130. if (i->h > icon_height) {
  131. if (i->w == i->h)
  132. i->w = icon_height;
  133. else
  134. i->w = (int) ((float)icon_height * ((float)i->w / (float)i->h));
  135. i->h = icon_height;
  136. }
  137. if (i->w > 2 * icon_height)
  138. i->w = icon_height;
  139. }
  140. }
  141. void
  142. updatesystrayiconstate(Client *i, XPropertyEvent *ev)
  143. {
  144. long flags;
  145. int code = 0;
  146. if (!showsystray || !systray || !i || ev->atom != xatom[XembedInfo] ||
  147. !(flags = getatomprop(i, xatom[XembedInfo])))
  148. return;
  149. if (flags & XEMBED_MAPPED && !i->tags) {
  150. i->tags = 1;
  151. code = XEMBED_WINDOW_ACTIVATE;
  152. XMapRaised(dpy, i->win);
  153. setclientstate(i, NormalState);
  154. }
  155. else if (!(flags & XEMBED_MAPPED) && i->tags) {
  156. i->tags = 0;
  157. code = XEMBED_WINDOW_DEACTIVATE;
  158. XUnmapWindow(dpy, i->win);
  159. setclientstate(i, WithdrawnState);
  160. }
  161. else
  162. return;
  163. sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
  164. systray->win, XEMBED_EMBEDDED_VERSION);
  165. }
  166. Client *
  167. wintosystrayicon(Window w)
  168. {
  169. if (!systray)
  170. return NULL;
  171. Client *i = NULL;
  172. if (!showsystray || !w)
  173. return i;
  174. for (i = systray->icons; i && i->win != w; i = i->next);
  175. return i;
  176. }