My build of dwm
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 

432 líneas
12 KiB

  1. diff --git a/config.def.h b/config.def.h
  2. index 1c0b587..bb8f3f7 100644
  3. --- a/config.def.h
  4. +++ b/config.def.h
  5. @@ -16,6 +16,7 @@ static const char *colors[][3] = {
  6. /* fg bg border */
  7. [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
  8. [SchemeSel] = { col_gray4, col_cyan, col_cyan },
  9. + [SchemeHid] = { col_cyan, col_gray1, col_cyan },
  10. };
  11. /* tagging */
  12. @@ -64,8 +65,10 @@ static Key keys[] = {
  13. { MODKEY, XK_p, spawn, {.v = dmenucmd } },
  14. { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
  15. { MODKEY, XK_b, togglebar, {0} },
  16. - { MODKEY, XK_j, focusstack, {.i = +1 } },
  17. - { MODKEY, XK_k, focusstack, {.i = -1 } },
  18. + { MODKEY, XK_j, focusstackvis, {.i = +1 } },
  19. + { MODKEY, XK_k, focusstackvis, {.i = -1 } },
  20. + { MODKEY|ShiftMask, XK_j, focusstackhid, {.i = +1 } },
  21. + { MODKEY|ShiftMask, XK_k, focusstackhid, {.i = -1 } },
  22. { MODKEY, XK_i, incnmaster, {.i = +1 } },
  23. { MODKEY, XK_d, incnmaster, {.i = -1 } },
  24. { MODKEY, XK_h, setmfact, {.f = -0.05} },
  25. @@ -84,6 +87,8 @@ static Key keys[] = {
  26. { MODKEY, XK_period, focusmon, {.i = +1 } },
  27. { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
  28. { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
  29. + { MODKEY, XK_s, show, {0} },
  30. + { MODKEY, XK_h, hide, {0} },
  31. TAGKEYS( XK_1, 0)
  32. TAGKEYS( XK_2, 1)
  33. TAGKEYS( XK_3, 2)
  34. @@ -102,6 +107,7 @@ static Button buttons[] = {
  35. /* click event mask button function argument */
  36. { ClkLtSymbol, 0, Button1, setlayout, {0} },
  37. { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
  38. + { ClkWinTitle, 0, Button1, togglewin, {0} },
  39. { ClkWinTitle, 0, Button2, zoom, {0} },
  40. { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
  41. { ClkClientWin, MODKEY, Button1, movemouse, {0} },
  42. diff --git a/dwm.c b/dwm.c
  43. index 4465af1..e780189 100644
  44. --- a/dwm.c
  45. +++ b/dwm.c
  46. @@ -50,6 +50,7 @@
  47. #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
  48. * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
  49. #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
  50. +#define HIDDEN(C) ((getstate(C->win) == IconicState))
  51. #define LENGTH(X) (sizeof X / sizeof X[0])
  52. #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
  53. #define WIDTH(X) ((X)->w + 2 * (X)->bw)
  54. @@ -59,7 +60,7 @@
  55. /* enums */
  56. enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
  57. -enum { SchemeNorm, SchemeSel }; /* color schemes */
  58. +enum { SchemeNorm, SchemeSel, SchemeHid }; /* color schemes */
  59. enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
  60. NetWMFullscreen, NetActiveWindow, NetWMWindowType,
  61. NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
  62. @@ -117,6 +118,8 @@ struct Monitor {
  63. int nmaster;
  64. int num;
  65. int by; /* bar geometry */
  66. + int btw; /* width of tasks portion of bar */
  67. + int bt; /* number of tasks */
  68. int mx, my, mw, mh; /* screen size */
  69. int wx, wy, ww, wh; /* window area */
  70. unsigned int seltags;
  71. @@ -124,6 +127,7 @@ struct Monitor {
  72. unsigned int tagset[2];
  73. int showbar;
  74. int topbar;
  75. + int hidsel;
  76. Client *clients;
  77. Client *sel;
  78. Client *stack;
  79. @@ -168,12 +172,16 @@ static void expose(XEvent *e);
  80. static void focus(Client *c);
  81. static void focusin(XEvent *e);
  82. static void focusmon(const Arg *arg);
  83. -static void focusstack(const Arg *arg);
  84. +static void focusstackvis(const Arg *arg);
  85. +static void focusstackhid(const Arg *arg);
  86. +static void focusstack(int inc, int vis);
  87. static int getrootptr(int *x, int *y);
  88. static long getstate(Window w);
  89. static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
  90. static void grabbuttons(Client *c, int focused);
  91. static void grabkeys(void);
  92. +static void hide(const Arg *arg);
  93. +static void hidewin(Client *c);
  94. static void incnmaster(const Arg *arg);
  95. static void keypress(XEvent *e);
  96. static void killclient(const Arg *arg);
  97. @@ -203,6 +211,8 @@ static void setlayout(const Arg *arg);
  98. static void setmfact(const Arg *arg);
  99. static void setup(void);
  100. static void seturgent(Client *c, int urg);
  101. +static void show(const Arg *arg);
  102. +static void showwin(Client *c);
  103. static void showhide(Client *c);
  104. static void sigchld(int unused);
  105. static void spawn(const Arg *arg);
  106. @@ -213,6 +223,7 @@ static void togglebar(const Arg *arg);
  107. static void togglefloating(const Arg *arg);
  108. static void toggletag(const Arg *arg);
  109. static void toggleview(const Arg *arg);
  110. +static void togglewin(const Arg *arg);
  111. static void unfocus(Client *c, int setfocus);
  112. static void unmanage(Client *c, int destroyed);
  113. static void unmapnotify(XEvent *e);
  114. @@ -439,10 +450,25 @@ buttonpress(XEvent *e)
  115. arg.ui = 1 << i;
  116. } else if (ev->x < x + blw)
  117. click = ClkLtSymbol;
  118. - else if (ev->x > selmon->ww - TEXTW(stext))
  119. + /* 2px right padding */
  120. + else if (ev->x > selmon->ww - TEXTW(stext) + lrpad - 2)
  121. click = ClkStatusText;
  122. - else
  123. - click = ClkWinTitle;
  124. + else {
  125. + x += blw;
  126. + c = m->clients;
  127. +
  128. + if (c) {
  129. + do {
  130. + if (!ISVISIBLE(c))
  131. + continue;
  132. + else
  133. + x += (1.0 / (double)m->bt) * m->btw;
  134. + } while (ev->x > x && (c = c->next));
  135. +
  136. + click = ClkWinTitle;
  137. + arg.v = c;
  138. + }
  139. + }
  140. } else if ((c = wintoclient(ev->window))) {
  141. focus(c);
  142. restack(selmon);
  143. @@ -452,7 +478,7 @@ buttonpress(XEvent *e)
  144. for (i = 0; i < LENGTH(buttons); i++)
  145. if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
  146. && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
  147. - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
  148. + buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
  149. }
  150. void
  151. @@ -695,7 +721,7 @@ dirtomon(int dir)
  152. void
  153. drawbar(Monitor *m)
  154. {
  155. - int x, w, sw = 0;
  156. + int x, w, sw = 0, n = 0, scm;
  157. int boxs = drw->fonts->h / 9;
  158. int boxw = drw->fonts->h / 6 + 2;
  159. unsigned int i, occ = 0, urg = 0;
  160. @@ -709,6 +735,8 @@ drawbar(Monitor *m)
  161. }
  162. for (c = m->clients; c; c = c->next) {
  163. + if (ISVISIBLE(c))
  164. + n++;
  165. occ |= c->tags;
  166. if (c->isurgent)
  167. urg |= c->tags;
  168. @@ -729,16 +757,37 @@ drawbar(Monitor *m)
  169. x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
  170. if ((w = m->ww - sw - x) > bh) {
  171. - if (m->sel) {
  172. - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
  173. - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
  174. - if (m->sel->isfloating)
  175. - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
  176. + if (n > 0) {
  177. + int remainder = w % n;
  178. + int tabw = (1.0 / (double)n) * w + 1;
  179. + for (c = m->clients; c; c = c->next) {
  180. + if (!ISVISIBLE(c))
  181. + continue;
  182. + if (m->sel == c)
  183. + scm = SchemeSel;
  184. + else if (HIDDEN(c))
  185. + scm = SchemeHid;
  186. + else
  187. + scm = SchemeNorm;
  188. + drw_setscheme(drw, scheme[scm]);
  189. +
  190. + if (remainder >= 0) {
  191. + if (remainder == 0) {
  192. + tabw--;
  193. + }
  194. + remainder--;
  195. + }
  196. + drw_text(drw, x, 0, tabw, bh, lrpad / 2, c->name, 0);
  197. + x += tabw;
  198. + }
  199. } else {
  200. drw_setscheme(drw, scheme[SchemeNorm]);
  201. drw_rect(drw, x, 0, w, bh, 1, 1);
  202. }
  203. }
  204. +
  205. + m->bt = n;
  206. + m->btw = w;
  207. drw_map(drw, m->barwin, 0, 0, m->ww, bh);
  208. }
  209. @@ -784,9 +833,17 @@ void
  210. focus(Client *c)
  211. {
  212. if (!c || !ISVISIBLE(c))
  213. - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
  214. - if (selmon->sel && selmon->sel != c)
  215. + for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext);
  216. + if (selmon->sel && selmon->sel != c) {
  217. unfocus(selmon->sel, 0);
  218. +
  219. + if (selmon->hidsel) {
  220. + hidewin(selmon->sel);
  221. + if (c)
  222. + arrange(c->mon);
  223. + selmon->hidsel = 0;
  224. + }
  225. + }
  226. if (c) {
  227. if (c->mon != selmon)
  228. selmon = c->mon;
  229. @@ -830,28 +887,57 @@ focusmon(const Arg *arg)
  230. }
  231. void
  232. -focusstack(const Arg *arg)
  233. +focusstackvis(const Arg *arg)
  234. +{
  235. + focusstack(arg->i, 0);
  236. +}
  237. +
  238. +void
  239. +focusstackhid(const Arg *arg)
  240. +{
  241. + focusstack(arg->i, 1);
  242. +}
  243. +
  244. +void
  245. +focusstack(int inc, int hid)
  246. {
  247. Client *c = NULL, *i;
  248. - if (!selmon->sel)
  249. + if (!selmon->sel && !hid)
  250. return;
  251. - if (arg->i > 0) {
  252. - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
  253. + if (!selmon->clients)
  254. + return;
  255. +
  256. + if (inc > 0) {
  257. + if (selmon->sel)
  258. + for (c = selmon->sel->next;
  259. + c && (!ISVISIBLE(c) || (!hid && HIDDEN(c)));
  260. + c = c->next);
  261. if (!c)
  262. - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
  263. + for (c = selmon->clients;
  264. + c && (!ISVISIBLE(c) || (!hid && HIDDEN(c)));
  265. + c = c->next);
  266. } else {
  267. - for (i = selmon->clients; i != selmon->sel; i = i->next)
  268. - if (ISVISIBLE(i))
  269. - c = i;
  270. + if (selmon->sel) {
  271. + for (i = selmon->clients; i != selmon->sel; i = i->next)
  272. + if (ISVISIBLE(i) && !(!hid && HIDDEN(i)))
  273. + c = i;
  274. + } else
  275. + c = selmon->clients;
  276. if (!c)
  277. for (; i; i = i->next)
  278. - if (ISVISIBLE(i))
  279. + if (ISVISIBLE(i) && !(!hid && HIDDEN(i)))
  280. c = i;
  281. }
  282. +
  283. if (c) {
  284. focus(c);
  285. restack(selmon);
  286. +
  287. + if (HIDDEN(c)) {
  288. + showwin(c);
  289. + c->mon->hidsel = 1;
  290. + }
  291. }
  292. }
  293. @@ -963,6 +1049,36 @@ grabkeys(void)
  294. }
  295. }
  296. +void
  297. +hide(const Arg *arg)
  298. +{
  299. + hidewin(selmon->sel);
  300. + focus(NULL);
  301. + arrange(selmon);
  302. +}
  303. +
  304. +void
  305. +hidewin(Client *c) {
  306. + if (!c || HIDDEN(c))
  307. + return;
  308. +
  309. + Window w = c->win;
  310. + static XWindowAttributes ra, ca;
  311. +
  312. + // more or less taken directly from blackbox's hide() function
  313. + XGrabServer(dpy);
  314. + XGetWindowAttributes(dpy, root, &ra);
  315. + XGetWindowAttributes(dpy, w, &ca);
  316. + // prevent UnmapNotify events
  317. + XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask);
  318. + XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask);
  319. + XUnmapWindow(dpy, w);
  320. + setclientstate(c, IconicState);
  321. + XSelectInput(dpy, root, ra.your_event_mask);
  322. + XSelectInput(dpy, w, ca.your_event_mask);
  323. + XUngrabServer(dpy);
  324. +}
  325. +
  326. void
  327. incnmaster(const Arg *arg)
  328. {
  329. @@ -1067,12 +1183,14 @@ manage(Window w, XWindowAttributes *wa)
  330. XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
  331. (unsigned char *) &(c->win), 1);
  332. XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
  333. - setclientstate(c, NormalState);
  334. + if (!HIDDEN(c))
  335. + setclientstate(c, NormalState);
  336. if (c->mon == selmon)
  337. unfocus(selmon->sel, 0);
  338. c->mon->sel = c;
  339. arrange(c->mon);
  340. - XMapWindow(dpy, c->win);
  341. + if (!HIDDEN(c))
  342. + XMapWindow(dpy, c->win);
  343. focus(NULL);
  344. }
  345. @@ -1195,7 +1313,7 @@ movemouse(const Arg *arg)
  346. Client *
  347. nexttiled(Client *c)
  348. {
  349. - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
  350. + for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next);
  351. return c;
  352. }
  353. @@ -1248,6 +1366,16 @@ propertynotify(XEvent *e)
  354. void
  355. quit(const Arg *arg)
  356. {
  357. + // fix: reloading dwm keeps all the hidden clients hidden
  358. + Monitor *m;
  359. + Client *c;
  360. + for (m = mons; m; m = m->next) {
  361. + if (m) {
  362. + for (c = m->stack; c; c = c->next)
  363. + if (c && HIDDEN(c)) showwin(c);
  364. + }
  365. + }
  366. +
  367. running = 0;
  368. }
  369. @@ -1610,6 +1738,25 @@ seturgent(Client *c, int urg)
  370. XFree(wmh);
  371. }
  372. +void
  373. +show(const Arg *arg)
  374. +{
  375. + if (selmon->hidsel)
  376. + selmon->hidsel = 0;
  377. + showwin(selmon->sel);
  378. +}
  379. +
  380. +void
  381. +showwin(Client *c)
  382. +{
  383. + if (!c || !HIDDEN(c))
  384. + return;
  385. +
  386. + XMapWindow(dpy, c->win);
  387. + setclientstate(c, NormalState);
  388. + arrange(c->mon);
  389. +}
  390. +
  391. void
  392. showhide(Client *c)
  393. {
  394. @@ -1746,6 +1893,23 @@ toggleview(const Arg *arg)
  395. }
  396. }
  397. +void
  398. +togglewin(const Arg *arg)
  399. +{
  400. + Client *c = (Client*)arg->v;
  401. +
  402. + if (c == selmon->sel) {
  403. + hidewin(c);
  404. + focus(NULL);
  405. + arrange(c->mon);
  406. + } else {
  407. + if (HIDDEN(c))
  408. + showwin(c);
  409. + focus(c);
  410. + restack(selmon);
  411. + }
  412. +}
  413. +
  414. void
  415. unfocus(Client *c, int setfocus)
  416. {