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.

205 lines
3.8 KiB

  1. #include <X11/Xlib-xcb.h>
  2. #include <xcb/res.h>
  3. #ifdef __OpenBSD__
  4. #include <sys/sysctl.h>
  5. #include <kvm.h>
  6. #endif /* __OpenBSD__ */
  7. static int scanner;
  8. static xcb_connection_t *xcon;
  9. int
  10. swallow(Client *p, Client *c)
  11. {
  12. Client *s;
  13. if (c->noswallow > 0 || c->isterminal)
  14. return 0;
  15. if (c->noswallow < 0 && !swallowfloating && c->isfloating)
  16. return 0;
  17. XMapWindow(dpy, c->win);
  18. detach(c);
  19. detachstack(c);
  20. setclientstate(c, WithdrawnState);
  21. XUnmapWindow(dpy, p->win);
  22. p->swallowing = c;
  23. c->mon = p->mon;
  24. Window w = p->win;
  25. p->win = c->win;
  26. c->win = w;
  27. XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace,
  28. (unsigned char *) &(p->win), 1);
  29. updatetitle(p);
  30. s = scanner ? c : p;
  31. #if BAR_EWMHTAGS_PATCH
  32. setfloatinghint(s);
  33. #endif // BAR_EWMHTAGS_PATCH
  34. XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h);
  35. arrange(p->mon);
  36. configure(p);
  37. updateclientlist();
  38. return 1;
  39. }
  40. void
  41. unswallow(Client *c)
  42. {
  43. c->win = c->swallowing->win;
  44. free(c->swallowing);
  45. c->swallowing = NULL;
  46. XDeleteProperty(dpy, c->win, netatom[NetClientList]);
  47. /* unfullscreen the client */
  48. setfullscreen(c, 0);
  49. updatetitle(c);
  50. arrange(c->mon);
  51. XMapWindow(dpy, c->win);
  52. XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
  53. #if BAR_EWMHTAGS_PATCH
  54. setfloatinghint(c);
  55. #endif // BAR_EWMHTAGS_PATCH
  56. setclientstate(c, NormalState);
  57. focus(NULL);
  58. arrange(c->mon);
  59. }
  60. pid_t
  61. winpid(Window w)
  62. {
  63. pid_t result = 0;
  64. #ifdef __linux__
  65. xcb_res_client_id_spec_t spec = {0};
  66. spec.client = w;
  67. spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
  68. xcb_generic_error_t *e = NULL;
  69. xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
  70. xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
  71. if (!r)
  72. return (pid_t)0;
  73. xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
  74. for (; i.rem; xcb_res_client_id_value_next(&i)) {
  75. spec = i.data->spec;
  76. if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
  77. uint32_t *t = xcb_res_client_id_value_value(i.data);
  78. result = *t;
  79. break;
  80. }
  81. }
  82. free(r);
  83. if (result == (pid_t)-1)
  84. result = 0;
  85. #endif /* __linux__ */
  86. #ifdef __OpenBSD__
  87. Atom type;
  88. int format;
  89. unsigned long len, bytes;
  90. unsigned char *prop;
  91. pid_t ret;
  92. if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
  93. return 0;
  94. ret = *(pid_t*)prop;
  95. XFree(prop);
  96. result = ret;
  97. #endif /* __OpenBSD__ */
  98. return result;
  99. }
  100. pid_t
  101. getparentprocess(pid_t p)
  102. {
  103. unsigned int v = 0;
  104. #ifdef __linux__
  105. FILE *f;
  106. char buf[256];
  107. snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
  108. if (!(f = fopen(buf, "r")))
  109. return (pid_t)0;
  110. if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1)
  111. v = (pid_t)0;
  112. fclose(f);
  113. #endif /* __linux__ */
  114. #ifdef __OpenBSD__
  115. int n;
  116. kvm_t *kd;
  117. struct kinfo_proc *kp;
  118. kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
  119. if (!kd)
  120. return 0;
  121. kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n);
  122. v = kp->p_ppid;
  123. #endif /* __OpenBSD__ */
  124. return (pid_t)v;
  125. }
  126. int
  127. isdescprocess(pid_t p, pid_t c)
  128. {
  129. while (p != c && c != 0)
  130. c = getparentprocess(c);
  131. return (int)c;
  132. }
  133. Client *
  134. termforwin(const Client *w)
  135. {
  136. Client *c;
  137. Monitor *m;
  138. if (!w->pid || w->isterminal)
  139. return NULL;
  140. c = selmon->sel;
  141. if (c && c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
  142. return c;
  143. for (m = mons; m; m = m->next) {
  144. for (c = m->clients; c; c = c->next) {
  145. if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
  146. return c;
  147. }
  148. }
  149. return NULL;
  150. }
  151. Client *
  152. swallowingclient(Window w)
  153. {
  154. Client *c;
  155. Monitor *m;
  156. for (m = mons; m; m = m->next) {
  157. for (c = m->clients; c; c = c->next) {
  158. if (c->swallowing && c->swallowing->win == w)
  159. return c;
  160. }
  161. }
  162. return NULL;
  163. }