diff options
Diffstat (limited to 'modules')
29 files changed, 1333 insertions, 0 deletions
diff --git a/modules/autostart/autostart.c b/modules/autostart/autostart.c new file mode 100644 index 0000000..d947972 --- /dev/null +++ b/modules/autostart/autostart.c @@ -0,0 +1,18 @@ +void +runautostart(void) +{ + const char *const *cmd = autostart; + + if (fork() == 0) { + setsid(); + + while (*cmd != NULL) { + if (fork() == 0) { + execl("/bin/sh", "sh", "-c", *cmd, NULL); + exit(1); + } + cmd++; + } + exit(0); + } +} diff --git a/modules/autostart/autostart.h b/modules/autostart/autostart.h new file mode 100644 index 0000000..10a6f88 --- /dev/null +++ b/modules/autostart/autostart.h @@ -0,0 +1 @@ +static void runautostart(void); diff --git a/modules/betterresize/betterresize.c b/modules/betterresize/betterresize.c new file mode 100644 index 0000000..d35f0c0 --- /dev/null +++ b/modules/betterresize/betterresize.c @@ -0,0 +1,124 @@ +void +resizemouse(const Arg *arg) +{ + Client *c; + Monitor *m; + XEvent ev; +#if LOCK_MOVE_RESIZE_REFRESH_RATE + Time lasttime = 0; +#endif + if (!(c = selmon->sel) || c->isfullscreen) + return; + + restack(selmon); + + int orig_x = c->x; + int orig_y = c->y; + int orig_w = c->w; + int orig_h = c->h; + + int rx, ry; + Window junkwin; + int junk_signed; + unsigned int junk; + if (!XQueryPointer(dpy, c->win, &junkwin, &junkwin, &junk_signed, &junk_signed, &rx, &ry, &junk)) + return; + int left = rx < orig_w / 3; + int right = rx > orig_w * 2 / 3; + int top = ry < orig_h / 3; + int bottom = ry > orig_h * 2 / 3; +#if BR_CHANGE_CURSOR + Cursor cur; + if (top && left) cur = cursor[CurNW]->cursor; + else if (top && right) cur = cursor[CurNE]->cursor; + else if (bottom && left) cur = cursor[CurSW]->cursor; + else if (bottom && right) cur = cursor[CurSE]->cursor; + else if (top) cur = cursor[CurN]->cursor; + else if (bottom) cur = cursor[CurS]->cursor; + else if (left) cur = cursor[CurW]->cursor; + else if (right) cur = cursor[CurE]->cursor; + else cur = cursor[CurResize]->cursor; // fallback +#else + Cursor cur = cursor[CurResize]->cursor; +#endif + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cur, CurrentTime) != GrabSuccess) + return; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + + if (ev.type == MotionNotify) { +#if LOCK_MOVE_RESIZE_REFRESH_RATE + if (ev.xmotion.time - lasttime <= (1000 / refreshrate)) + continue; + lasttime = ev.xmotion.time; +#endif + int dx = ev.xmotion.x_root - (orig_x + rx); + int dy = ev.xmotion.y_root - (orig_y + ry); + + int nx = orig_x; + int ny = orig_y; + int nw = orig_w; + int nh = orig_h; + + if (left) nw = orig_w - dx; + else if (right) nw = orig_w + dx; + + if (top) nh = orig_h - dy; + else if (bottom) nh = orig_h + dy; + + int min_w = MAX(1, c->minw); + int min_h = MAX(1, c->minh); + + if (nw < min_w) nw = min_w; + if (nh < min_h) nh = min_h; + + if (left) nx = orig_x + (orig_w - nw); + if (top) ny = orig_y + (orig_h - nh); + + int dx_final = nw - orig_w; + int dy_final = nh - orig_h; +#if !RESIZINIG_WINDOWS_IN_ALL_LAYOUTS_FLOATS_THEM + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange && + (abs(dx_final) > snap || abs(dy_final) > snap)) { +#else + if (!c->isfloating && (abs(dx_final) > snap || abs(dy_final) > snap)) { +#endif + if (nx >= selmon->wx && nx + nw <= selmon->wx + selmon->ww && + ny >= selmon->wy && ny + nh <= selmon->wy + selmon->wh) { + + togglefloating(NULL); + + orig_x = c->x; + orig_y = c->y; + orig_w = c->w; + orig_h = c->h; + } + } +#if USE_RESIZECLIENT_FUNC + resizeclient(c, nx, ny, nw, nh); +#else + resize(c, nx, ny, nw, nh, 1); +#endif + drawbar(selmon); //fix for issue 1 + } + } while (ev.type != ButtonRelease); + + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +#if ENHANCED_TOGGLE_FLOATING && RESTORE_SIZE_AND_POS_ETF + c->wasmanuallyedited = 1; + if (c->isfloating) { + c->sfx = c->x; + c->sfy = c->y; + c->sfw = c->w; + c->sfh = c->h; + } +#endif +} diff --git a/modules/directionalfocus/directionalfocus.c b/modules/directionalfocus/directionalfocus.c new file mode 100644 index 0000000..5d1ebcb --- /dev/null +++ b/modules/directionalfocus/directionalfocus.c @@ -0,0 +1,113 @@ +void +focusdir(const Arg *arg) +{ + Client *s = selmon->sel, *f = NULL, *c, *next; + + if (!s) + return; + + unsigned int score = -1; + unsigned int client_score; + int isfloating = s->isfloating; + + next = s->next; + if (!next) + next = s->mon->clients; + for (c = next; c != s; c = next) { + + next = c->next; + if (!next) + next = s->mon->clients; + + if (!ISVISIBLE(c) || c->isfloating != isfloating) + continue; + +#if INFINITE_TAGS + if (selmon->lt[selmon->sellt]->arrange == NULL) { + + int s_cx = s->x + s->w / 2; + int s_cy = s->y + s->h / 2; + int c_cx = c->x + c->w / 2; + int c_cy = c->y + c->h / 2; + + int dx = c_cx - s_cx; /* positive = c is to the right */ + int dy = c_cy - s_cy; /* positive = c is below */ + + int axial, lateral; + + switch (arg->i) { + case 0: /* left */ + if (dx >= 0) continue; + axial = -dx; + lateral = abs(dy); + break; + case 1: /* right */ + if (dx <= 0) continue; + axial = dx; + lateral = abs(dy); + break; + case 2: /* up */ + if (dy >= 0) continue; + axial = -dy; + lateral = abs(dx); + break; + default: + case 3: /* down */ + if (dy <= 0) continue; + axial = dy; + lateral = abs(dx); + break; + } + + client_score = axial + (unsigned int)((long)lateral * lateral) / (axial + 1); + } else +#endif + { + int dist; + int dirweight = 20; + switch (arg->i) { + case 0: + dist = s->x - c->x - c->w; + client_score = + dirweight * abs(dist) + + abs(s->y - c->y); + break; + case 1: + dist = c->x - s->x - s->w; + client_score = + dirweight * abs(dist) + + abs(c->y - s->y); + break; + case 2: + dist = s->y - c->y - c->h; + client_score = + dirweight * abs(dist) + + abs(s->x - c->x); + break; + default: + case 3: + dist = c->y - s->y - s->h; + client_score = + dirweight * abs(dist) + + abs(c->x - s->x); + break; + } + } + + if (client_score < score) { + score = client_score; + f = c; + } + } + + if (f && f != s) { + focus(f); +#if INFINITE_TAGS + centerwindow(NULL); +#endif +#if WARP_TO_CLIENT && WARP_TO_CENTER_OF_WINDOW_AFFECTED_BY_FOCUSSTACK + warptoclient(f); +#endif + restack(f->mon); + } +} diff --git a/modules/directionalfocus/directionalfocus.h b/modules/directionalfocus/directionalfocus.h new file mode 100644 index 0000000..773341a --- /dev/null +++ b/modules/directionalfocus/directionalfocus.h @@ -0,0 +1 @@ +static void focusdir(const Arg *arg); diff --git a/modules/directionalmove/directionalmove.c b/modules/directionalmove/directionalmove.c new file mode 100644 index 0000000..d83c792 --- /dev/null +++ b/modules/directionalmove/directionalmove.c @@ -0,0 +1,84 @@ +void +movedir(const Arg *arg) +{ + if (selmon->lt[selmon->sellt]->arrange != tile) return; + Client *s = selmon->sel, *f = NULL, *c, *next; + if (!s) + return; + unsigned int score = -1; + unsigned int client_score; + int dist; + int dirweight = 20; + int isfloating = s->isfloating; + next = s->next; + if (!next) + next = s->mon->clients; + for (c = next; c != s; c = next) { + next = c->next; + if (!next) + next = s->mon->clients; + if (!ISVISIBLE(c) || c->isfloating != isfloating) + continue; + switch (arg->i) { + case 0: // left + dist = s->x - c->x - c->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(s->y - c->y); + break; + case 1: // right + dist = c->x - s->x - s->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(c->y - s->y); + break; + case 2: // up + dist = s->y - c->y - c->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(s->x - c->x); + break; + default: + case 3: // down + dist = c->y - s->y - s->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(c->x - s->x); + break; + } + if (((arg->i == 0 || arg->i == 2) && client_score <= score) || client_score < score) { + score = client_score; + f = c; + } + } + if (!f || f == s) + return; + + Client *ps = NULL, *pf = NULL, *p; + for (p = s->mon->clients; p; p = p->next) { + if (p->next == s) ps = p; + if (p->next == f) pf = p; + } + + if (s->next == f) { + if (ps) ps->next = f; else s->mon->clients = f; + s->next = f->next; + f->next = s; + } else if (f->next == s) { + if (pf) pf->next = s; else s->mon->clients = s; + f->next = s->next; + s->next = f; + } else { + if (ps) ps->next = f; else s->mon->clients = f; + if (pf) pf->next = s; else s->mon->clients = s; + Client *tmp = s->next; + s->next = f->next; + f->next = tmp; + } + + focus(s); +#if WARP_TO_CLIENT && WARP_TO_CENTER_OF_WINDOW_AFFECTED_BY_FOCUSSTACK + warptoclient(f); +#endif + arrange(s->mon); +} diff --git a/modules/directionalmove/directionalmove.h b/modules/directionalmove/directionalmove.h new file mode 100644 index 0000000..69e9f0f --- /dev/null +++ b/modules/directionalmove/directionalmove.h @@ -0,0 +1 @@ +static void movedir(const Arg *arg); diff --git a/modules/etf/etf.c b/modules/etf/etf.c new file mode 100644 index 0000000..dfb69fe --- /dev/null +++ b/modules/etf/etf.c @@ -0,0 +1,91 @@ +#if !RESTORE_SIZE_AND_POS_ETF +void +enhancedtogglefloating(const Arg *arg) +{ + if (!selmon->sel || selmon->sel->isfullscreen) + return; + Client *c = selmon->sel; + const Layout *prevlayout = selmon->lt[selmon->sellt]; + c->isfloating = !c->isfloating; + if (c->isfloating) { + int w = c->sfw > 0 ? c->sfw : c->w; + int h = c->sfh > 0 ? c->sfh : c->h; + resize(c, + c->mon->wx + (c->mon->ww - w) / 2, + c->mon->wy + (c->mon->wh - h) / 2, + w, h, 0); + } else { + int tiled_sellt = -1; + for (int i = 0; i < LENGTH(layouts); i++) { + if (selmon->lt[i]->arrange != NULL) { + tiled_sellt = i; + break; + } + } + if (tiled_sellt != -1) { + selmon->sellt = tiled_sellt; + arrange(selmon); + } + for (int i = 0; i < LENGTH(layouts); i++) { + if (selmon->lt[i] == prevlayout) { + selmon->sellt = i; + break; + } + } + } + arrange(selmon); +#if WARP_TO_CLIENT && WARP_TO_CENTER_OF_WINDOW_AFFECTED_BY_ENHANCED_TOGGLE_FLOATING + warptoclient(selmon->sel); +#endif +} +#else +void +enhancedtogglefloating(const Arg *arg) +{ + if (!selmon->sel || selmon->sel->isfullscreen) + return; + Client *c = selmon->sel; + const Layout *prevlayout = selmon->lt[selmon->sellt]; + c->isfloating = !c->isfloating; + if (c->isfloating) { + int w = c->sfw > 0 ? c->sfw : c->w; + int h = c->sfh > 0 ? c->sfh : c->h; + if (!c->wasmanuallyedited) { + resize(c, + c->mon->wx + (c->mon->ww - w) / 2, + c->mon->wy + (c->mon->wh - h) / 2, + w, h, 0); + } else { + resize(c, c->sfx, c->sfy, w, h, 0); + } + c->sfx = c->x; c->sfy = c->y; + c->sfw = c->w; c->sfh = c->h; + } else { + c->sfx = c->x; + c->sfy = c->y; + c->sfw = c->w; + c->sfh = c->h; + int tiled_sellt = -1; + for (int i = 0; i < LENGTH(layouts); i++) { + if (selmon->lt[i]->arrange != NULL) { + tiled_sellt = i; + break; + } + } + if (tiled_sellt != -1) { + selmon->sellt = tiled_sellt; + arrange(selmon); + } + for (int i = 0; i < LENGTH(layouts); i++) { + if (selmon->lt[i] == prevlayout) { + selmon->sellt = i; + break; + } + } + } + arrange(selmon); +#if WARP_TO_CLIENT && WARP_TO_CENTER_OF_WINDOW_AFFECTED_BY_ENHANCED_TOGGLE_FLOATING + warptoclient(selmon->sel); +#endif +} +#endif diff --git a/modules/etf/etf.h b/modules/etf/etf.h new file mode 100644 index 0000000..9b2b127 --- /dev/null +++ b/modules/etf/etf.h @@ -0,0 +1 @@ +static void enhancedtogglefloating(const Arg *arg); diff --git a/modules/ewmh_tags/ewmh_tags.c b/modules/ewmh_tags/ewmh_tags.c new file mode 100644 index 0000000..12e8e26 --- /dev/null +++ b/modules/ewmh_tags/ewmh_tags.c @@ -0,0 +1,42 @@ +void +setcurrentdesktop(void){ + long data[] = { 0 }; + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +void setdesktopnames(void){ + XTextProperty text; + Xutf8TextListToTextProperty(dpy, (char **)tags, TAGSLENGTH, XUTF8StringStyle, &text); + XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]); +} + +void +setnumdesktops(void){ + long data[] = { TAGSLENGTH }; + XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +void +setviewport(void){ + long data[] = { 0, 0 }; + XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 2); +} + +void +updatecurrentdesktop(void){ + long rawdata[] = { selmon->tagset[selmon->seltags] }; + int i=0; + while(*rawdata >> (i+1)){ + i++; + } + long data[] = { i }; + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +void +updatewmdesktop(Client *c) +{ + unsigned long desktop = c->tags ? ffs(c->tags) - 1 : 0; + XChangeProperty(dpy, c->win, netatom[NetDesktopNum], XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&desktop, 1); +} diff --git a/modules/ewmh_tags/ewmh_tags.h b/modules/ewmh_tags/ewmh_tags.h new file mode 100644 index 0000000..74137c8 --- /dev/null +++ b/modules/ewmh_tags/ewmh_tags.h @@ -0,0 +1,8 @@ +#define TAGSLENGTH (LENGTH(tags)) + +static void setcurrentdesktop(void); +static void setdesktopnames(void); +static void setnumdesktops(void); +static void setviewport(void); +static void updatecurrentdesktop(void); +static void updatewmdesktop(Client *c);
\ No newline at end of file diff --git a/modules/externalbars/externalbars.c b/modules/externalbars/externalbars.c new file mode 100644 index 0000000..b84fe06 --- /dev/null +++ b/modules/externalbars/externalbars.c @@ -0,0 +1,195 @@ +static ExternalBarStrut *ebarstruts = NULL; +static Atom eb_atom_strut = None; +static Atom eb_atom_strut_partial = None; +static int eb_scanning = 0; + +void +externalbars_init_atoms(void) +{ + if (eb_atom_strut == None) + eb_atom_strut = XInternAtom(dpy, "_NET_WM_STRUT", False); + if (eb_atom_strut_partial == None) + eb_atom_strut_partial = XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", False); +} + +int +externalbars_read(Window w, ExternalBarStrut *out) +{ + Atom real; + int fmt; + unsigned long n, extra; + unsigned char *p = NULL; + + externalbars_init_atoms(); + memset(out, 0, sizeof *out); + out->win = w; + + /* Prefer _NET_WM_STRUT_PARTIAL (12 longs) */ + if (XGetWindowProperty(dpy, w, eb_atom_strut_partial, 0L, 12L, False, + XA_CARDINAL, &real, &fmt, &n, &extra, &p) == Success && p) { + if (n >= 4) { + long *s = (long *)p; + out->left = (int)s[0]; out->right = (int)s[1]; + out->top = (int)s[2]; out->bottom = (int)s[3]; + if (n >= 12) { + out->left_start_y = (int)s[4]; out->left_end_y = (int)s[5]; + out->right_start_y = (int)s[6]; out->right_end_y = (int)s[7]; + out->top_start_x = (int)s[8]; out->top_end_x = (int)s[9]; + out->bottom_start_x = (int)s[10]; out->bottom_end_x = (int)s[11]; + } else { + out->left_start_y = 0; out->left_end_y = sh; + out->right_start_y = 0; out->right_end_y = sh; + out->top_start_x = 0; out->top_end_x = sw; + out->bottom_start_x = 0; out->bottom_end_x = sw; + } + XFree(p); + if (out->left == 0 && out->right == 0 && + out->top == 0 && out->bottom == 0) + return 0; + return 1; + } + XFree(p); + p = NULL; + } + + /* Fallback: plain _NET_WM_STRUT (4 longs) */ + if (XGetWindowProperty(dpy, w, eb_atom_strut, 0L, 4L, False, + XA_CARDINAL, &real, &fmt, &n, &extra, &p) == Success && p) { + if (n >= 4) { + long *s = (long *)p; + out->left = (int)s[0]; out->right = (int)s[1]; + out->top = (int)s[2]; out->bottom = (int)s[3]; + out->left_start_y = 0; out->left_end_y = sh; + out->right_start_y = 0; out->right_end_y = sh; + out->top_start_x = 0; out->top_end_x = sw; + out->bottom_start_x = 0; out->bottom_end_x = sw; + XFree(p); + if (out->left == 0 && out->right == 0 && + out->top == 0 && out->bottom == 0) + return 0; + return 1; + } + XFree(p); + } + return 0; +} + +int +externalbars_hasstrut(Window w) +{ + ExternalBarStrut tmp; + return externalbars_read(w, &tmp); +} + +void +externalbars_begin_scan(void) +{ + eb_scanning = 1; +} + +void +externalbars_end_scan(void) +{ + eb_scanning = 0; + externalbars_reapply_all(); +} + +void +externalbars_register(Window w) +{ + ExternalBarStrut tmp, *sw; + + if (!externalbars_read(w, &tmp)) + return; + + for (sw = ebarstruts; sw; sw = sw->next) { + if (sw->win == w) { + ExternalBarStrut *nxt = sw->next; + *sw = tmp; + sw->next = nxt; + if (!eb_scanning) + externalbars_reapply_all(); + return; + } + } + + sw = ecalloc(1, sizeof(ExternalBarStrut)); + *sw = tmp; + sw->next = ebarstruts; + ebarstruts = sw; + if (!eb_scanning) + externalbars_reapply_all(); +} + +void +externalbars_unregister(Window w) +{ + ExternalBarStrut **prev = &ebarstruts, *sw; + + while ((sw = *prev)) { + if (sw->win == w) { + *prev = sw->next; + free(sw); + if (!eb_scanning) + externalbars_reapply_all(); + return; + } + prev = &sw->next; + } +} + +void +externalbars_apply(Monitor *m) +{ + ExternalBarStrut *s; + int top = 0, bottom = 0, left = 0, right = 0; + + for (s = ebarstruts; s; s = s->next) { + if (s->top > 0) { + if (s->top_start_x < m->mx + m->mw && s->top_end_x > m->mx) { + int local = s->top - m->my; + if (local > 0) + top = MAX(top, MIN(local, m->mh)); + } + } + if (s->bottom > 0) { + if (s->bottom_start_x < m->mx + m->mw && s->bottom_end_x > m->mx) { + int local = s->bottom - (sh - (m->my + m->mh)); + if (local > 0) + bottom = MAX(bottom, MIN(local, m->mh)); + } + } + if (s->left > 0) { + if (s->left_start_y < m->my + m->mh && s->left_end_y > m->my) { + int local = s->left - m->mx; + if (local > 0) + left = MAX(left, MIN(local, m->mw)); + } + } + if (s->right > 0) { + if (s->right_start_y < m->my + m->mh && s->right_end_y > m->my) { + int local = s->right - (sw - (m->mx + m->mw)); + if (local > 0) + right = MAX(right, MIN(local, m->mw)); + } + } + } + + m->strut_top = top; + m->strut_bottom = bottom; + m->strut_left = left; + m->strut_right = right; +} + +void +externalbars_reapply_all(void) +{ + Monitor *m; + + for (m = mons; m; m = m->next) { + externalbars_apply(m); + updatebarpos(m); + } + if (selmon) + arrange(NULL); +} diff --git a/modules/externalbars/externalbars.h b/modules/externalbars/externalbars.h new file mode 100644 index 0000000..3e80185 --- /dev/null +++ b/modules/externalbars/externalbars.h @@ -0,0 +1,18 @@ +typedef struct ExternalBarStrut ExternalBarStrut; +struct ExternalBarStrut { + Window win; + int left, right, top, bottom; + int left_start_y, left_end_y; + int right_start_y, right_end_y; + int top_start_x, top_end_x; + int bottom_start_x, bottom_end_x; + ExternalBarStrut *next; +}; + +static void externalbars_begin_scan(void); +static void externalbars_end_scan(void); +static int externalbars_hasstrut(Window w); +static void externalbars_register(Window w); +static void externalbars_unregister(Window w); +static void externalbars_apply(Monitor *m); +static void externalbars_reapply_all(void); diff --git a/modules/fullscreen/fullscreen.c b/modules/fullscreen/fullscreen.c new file mode 100644 index 0000000..3b36575 --- /dev/null +++ b/modules/fullscreen/fullscreen.c @@ -0,0 +1,6 @@ +void +togglefullscr(const Arg *arg) +{ + if(selmon->sel) + setfullscreen(selmon->sel, !selmon->sel->isfullscreen); +} diff --git a/modules/fullscreen/fullscreen.h b/modules/fullscreen/fullscreen.h new file mode 100644 index 0000000..37e5b2d --- /dev/null +++ b/modules/fullscreen/fullscreen.h @@ -0,0 +1 @@ +static void togglefullscr(const Arg *arg); diff --git a/modules/gaps/gaps.c b/modules/gaps/gaps.c new file mode 100644 index 0000000..2e501dd --- /dev/null +++ b/modules/gaps/gaps.c @@ -0,0 +1,9 @@ +void +setgaps(const Arg *arg) +{ + if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) + selmon->gappx = 0; + else + selmon->gappx += arg->i; + arrange(selmon); +} diff --git a/modules/gaps/gaps.h b/modules/gaps/gaps.h new file mode 100644 index 0000000..2bf4000 --- /dev/null +++ b/modules/gaps/gaps.h @@ -0,0 +1 @@ +static void setgaps(const Arg *arg); diff --git a/modules/infinitetags/infinitetags.c b/modules/infinitetags/infinitetags.c new file mode 100644 index 0000000..2b08f94 --- /dev/null +++ b/modules/infinitetags/infinitetags.c @@ -0,0 +1,218 @@ +int +getcurrenttag(Monitor *m) { + unsigned int i; + for (i = 0; i < LENGTH(tags) && !(m->tagset[m->seltags] & (1 << i)); i++); + return i < LENGTH(tags) ? i : 0; +} + +void +homecanvas(const Arg *arg) { + Client *c; + int tagidx = getcurrenttag(selmon); + int cx = selmon->canvas[tagidx].cx; + int cy = selmon->canvas[tagidx].cy; + + for (c = selmon->clients; c; c = c->next) { + if (c->tags & (1 << tagidx)) { + c->x -= cx; + c->y -= cy; + XMoveWindow(dpy, c->win, c->x, c->y); + } + } + + selmon->canvas[tagidx].cx = 0; + selmon->canvas[tagidx].cy = 0; + drawbar(selmon); + XFlush(dpy); +} + +void +movecanvas(const Arg *arg) +{ + if (selmon->lt[selmon->sellt]->arrange != NULL) + return; + if (selmon->sel && selmon->sel->isfullscreen) + return; + + int tagidx = getcurrenttag(selmon); + int dx = 0, dy = 0; + +#ifndef MOVE_CANVAS_STEP +#define MOVE_CANVAS_STEP 120 +#endif + + switch(arg->i) { + case 0: dx = -MOVE_CANVAS_STEP; break; + case 1: dx = MOVE_CANVAS_STEP; break; + case 2: dy = -MOVE_CANVAS_STEP; break; + case 3: dy = MOVE_CANVAS_STEP; break; + } + + selmon->canvas[tagidx].cx -= dx; + selmon->canvas[tagidx].cy -= dy; + + Client *c; + for (c = selmon->clients; c; c = c->next) { + if (ISVISIBLE(c)) { + c->x -= dx; + c->y -= dy; + XMoveWindow(dpy, c->win, c->x, c->y); + } + } + + drawbar(selmon); +} + +void +movecanvasmouse(const Arg *arg) { + if (selmon->lt[selmon->sellt]->arrange != NULL) + return; + if (selmon->sel && selmon->sel->isfullscreen) + return; + int start_x, start_y; + Window dummy; + int di; + unsigned int dui; + int tagidx = getcurrenttag(selmon); + float multiplier = arg ? arg->f : 1.0f; + float accum_x = 0.0f, accum_y = 0.0f; + +#if LOCK_MOVE_RESIZE_REFRESH_RATE + Time lasttime = 0; +#endif + + if (!XQueryPointer(dpy, root, &dummy, &dummy, &start_x, &start_y, &di, &di, &dui)) + return; + + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + + XEvent ev; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + + switch (ev.type) { + case MotionNotify: + { +#if LOCK_MOVE_RESIZE_REFRESH_RATE + if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate)) + continue; + lasttime = ev.xmotion.time; +#endif + int nx = ev.xmotion.x - start_x; + int ny = ev.xmotion.y - start_y; + + /* accumulate subpixel remainder to not lose fractional pixels: + multiplier=0.5, nx=1: accum=0.5, dx=0 --- skip + nx=1: accum=1.0, dx=1 --- move + */ + accum_x += nx * multiplier; + accum_y += ny * multiplier; + + int dx = (int)accum_x; + int dy = (int)accum_y; + + accum_x -= dx; + accum_y -= dy; + + for (Client *c = selmon->clients; c; c = c->next) { + if (c->tags & (1 << tagidx)) { + c->x += dx; + c->y += dy; + XMoveWindow(dpy, c->win, c->x, c->y); + } + } + + selmon->canvas[tagidx].cx += dx; + selmon->canvas[tagidx].cy += dy; + drawbar(selmon); + start_x = ev.xmotion.x; + start_y = ev.xmotion.y; + } break; + } + } while (ev.type != ButtonRelease); + + XUngrabPointer(dpy, CurrentTime); +} + +void +save_canvas_positions(Monitor *m) { + Client *c; + int tagidx = getcurrenttag(m); + + m->canvas[tagidx].saved_cx = m->canvas[tagidx].cx; + m->canvas[tagidx].saved_cy = m->canvas[tagidx].cy; + + for (c = m->clients; c; c = c->next) { + if (ISVISIBLE(c)) { + c->saved_cx = c->x + m->canvas[tagidx].cx; + c->saved_cy = c->y + m->canvas[tagidx].cy; + c->saved_cw = c->w; + c->saved_ch = c->h; + c->was_on_canvas = 1; + } + } +} + +void +restore_canvas_positions(Monitor *m) { + Client *c; + int tagidx = getcurrenttag(m); + + m->canvas[tagidx].cx = m->canvas[tagidx].saved_cx; + m->canvas[tagidx].cy = m->canvas[tagidx].saved_cy; + + for (c = m->clients; c; c = c->next) { + if (ISVISIBLE(c) && c->was_on_canvas) { + if (c->isfullscreen) + continue; + c->isfloating = 1; + + int target_x = c->saved_cx - m->canvas[tagidx].cx; + int target_y = c->saved_cy - m->canvas[tagidx].cy; + + c->x = target_x; + c->y = target_y; + c->w = c->saved_cw; + c->h = c->saved_ch; + + XMoveResizeWindow(dpy, c->win, target_x, target_y, c->w, c->h); + + configure(c); + } + } + XSync(dpy, False); +} + +void +centerwindow(const Arg *arg) +{ + Client *c = (arg && arg->v) ? (Client *)arg->v : selmon->sel; + + if (!c || !c->mon || c->mon->lt[c->mon->sellt]->arrange != NULL) + return; + + Monitor *m = c->mon; + int tagidx = getcurrenttag(m); + + int dx = (m->wx + m->ww - WIDTH(c)) / 2 - c->x; + int dy = m->wy + (m->wh / 2) - (c->y + HEIGHT(c) / 2); + + if (dx == 0 && dy == 0) + return; + + Client *tmp; + for (tmp = m->clients; tmp; tmp = tmp->next) { + if (ISVISIBLE(tmp)) { + tmp->x += dx; + tmp->y += dy; + XMoveWindow(dpy, tmp->win, tmp->x, tmp->y); + } + } + + m->canvas[tagidx].cx += dx; + m->canvas[tagidx].cy += dy; + + drawbar(m); +} diff --git a/modules/infinitetags/infinitetags.h b/modules/infinitetags/infinitetags.h new file mode 100644 index 0000000..e3cc64e --- /dev/null +++ b/modules/infinitetags/infinitetags.h @@ -0,0 +1,7 @@ +static void movecanvas(const Arg *arg); +static void movecanvasmouse(const Arg *arg); +static void homecanvas(const Arg *arg); +static int getcurrenttag(Monitor *m); +static void save_canvas_positions(Monitor *m); +static void restore_canvas_positions(Monitor *m); +static void centerwindow(const Arg *arg); diff --git a/modules/moveresizekbd/moveresizekbd.c b/modules/moveresizekbd/moveresizekbd.c new file mode 100644 index 0000000..5105de4 --- /dev/null +++ b/modules/moveresizekbd/moveresizekbd.c @@ -0,0 +1,160 @@ +#if !INFINITE_TAGS +void +moveresize(const Arg *arg) +{ + if (selmon->sel && selmon->sel->isfullscreen) + return; + XEvent ev; + Monitor *m = selmon; + + if(!(m->sel && arg && arg->v && m->sel->isfloating)) { + +#if DIRECTIONAL_MOVE + if (((int *)arg->v)[0] != 0 || ((int *)arg->v)[1] != 0) { + if (((int *)arg->v)[1] > 0) movedir(&(Arg){.i = 3}); // Down + if (((int *)arg->v)[1] < 0) movedir(&(Arg){.i = 2}); // Up + if (((int *)arg->v)[0] > 0) movedir(&(Arg){.i = 1}); // Right + if (((int *)arg->v)[0] < 0) movedir(&(Arg){.i = 0}); // Left + } +#endif + return; + } + + XRaiseWindow(dpy, m->sel->win); + + resize(m->sel, m->sel->x + ((int *)arg->v)[0], + m->sel->y + ((int *)arg->v)[1], + m->sel->w + ((int *)arg->v)[2], + m->sel->h + ((int *)arg->v)[3], + True); + +#if ENHANCED_TOGGLE_FLOATING && RESTORE_SIZE_AND_POS_ETF + if (m->sel->isfloating) { + m->sel->wasmanuallyedited = 1; + m->sel->sfx = m->sel->x; + m->sel->sfy = m->sel->y; + m->sel->sfw = m->sel->w; + m->sel->sfh = m->sel->h; + } +#endif + + focus(m->sel); + +#if WARP_TO_CLIENT && WARP_TO_CENTER_OF_WINDOW_MOVED_BY_KEYBOARD + warptoclient(m->sel); +#endif + + while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +#else + + +void +moveresize(const Arg *arg) +{ + if (selmon->sel && selmon->sel->isfullscreen) + return; + int dx = ((int *)arg->v)[0]; + int dy = ((int *)arg->v)[1]; + int dw = ((int *)arg->v)[2]; + int dh = ((int *)arg->v)[3]; + + XEvent ev; + Monitor *m = selmon; + + if (!m->sel || !arg || !arg->v) + return; + + if (!m->sel->isfloating) { +#if DIRECTIONAL_MOVE + if (selmon->lt[selmon->sellt]->arrange != NULL && (dx || dy)) { + if (dy > 0) movedir(&(Arg){.i = 3}); // Down + if (dy < 0) movedir(&(Arg){.i = 2}); // Up + if (dx > 0) movedir(&(Arg){.i = 1}); // Right + if (dx < 0) movedir(&(Arg){.i = 0}); // Left + } +#endif + return; + } + + + Client *c = m->sel; + + XRaiseWindow(dpy, c->win); + + if (selmon->lt[selmon->sellt]->arrange != NULL) { + resize(c, + c->x + dx, + c->y + dy, + c->w + dw, + c->h + dh, + True); + } + else { + int nx = c->x + dx; + int ny = c->y + dy; + int nw = c->w + dw; + int nh = c->h + dh; + int canvas_dx = 0, canvas_dy = 0; + int tagidx = getcurrenttag(m); + + if (dx || dy) { + if (nx < m->wx) { + canvas_dx = nx - m->wx; + nx = m->wx; + } else if (nx + nw + 2 * c->bw > m->wx + m->ww) { + canvas_dx = (nx + nw + 2 * c->bw) - (m->wx + m->ww); + nx = m->wx + m->ww - nw - 2 * c->bw; + } + + if (ny < m->wy) { + canvas_dy = ny - m->wy; + ny = m->wy; + } else if (ny + nh + 2 * c->bw > m->wy + m->wh) { + canvas_dy = (ny + nh + 2 * c->bw) - (m->wy + m->wh); + ny = m->wy + m->wh - nh - 2 * c->bw; + } + + if (canvas_dx || canvas_dy) { + m->canvas[tagidx].cx -= canvas_dx; + m->canvas[tagidx].cy -= canvas_dy; + + Client *tmp; + for (tmp = m->clients; tmp; tmp = tmp->next) { + if (ISVISIBLE(tmp) && tmp != c) { + tmp->x -= canvas_dx; + tmp->y -= canvas_dy; + XMoveWindow(dpy, tmp->win, tmp->x, tmp->y); + } + } + } + } + + resize(c, nx, ny, nw, nh, True); + } + +#if ENHANCED_TOGGLE_FLOATING && RESTORE_SIZE_AND_POS_ETF + if (c->isfloating) { + c->wasmanuallyedited = 1; + c->sfx = c->x; + c->sfy = c->y; + c->sfw = c->w; + c->sfh = c->h; + } +#endif + + focus(c); + +#if WARP_TO_CLIENT && WARP_TO_CENTER_OF_WINDOW_MOVED_BY_KEYBOARD + warptoclient(c); +#endif + + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + +#if IT_SHOW_COORDINATES_IN_BAR + drawbar(m); +#endif + +} +#endif diff --git a/modules/moveresizekbd/moveresizekbd.h b/modules/moveresizekbd/moveresizekbd.h new file mode 100644 index 0000000..de565eb --- /dev/null +++ b/modules/moveresizekbd/moveresizekbd.h @@ -0,0 +1 @@ +static void moveresize(const Arg *arg); diff --git a/modules/vxwm_includes.c b/modules/vxwm_includes.c new file mode 100644 index 0000000..6bd0fea --- /dev/null +++ b/modules/vxwm_includes.c @@ -0,0 +1,57 @@ +#pragma once + +#if GAPS +#include "gaps/gaps.c" +#endif + +#if XRDB +#include "xrdb/xrdb.c" +#endif + +#if FULLSCREEN +#include "fullscreen/fullscreen.c" +#endif + +#if EWMH_TAGS +#include "ewmh_tags/ewmh_tags.c" +#endif + +#if WARP_TO_CLIENT +#include "warptoclient/warptoclient.c" +#endif + +#if ENHANCED_TOGGLE_FLOATING +#include "etf/etf.c" +#endif + +#if BETTER_RESIZE +#include "betterresize/betterresize.c" +#endif + +#if WINDOWMAP +#include "windowmap/windowmap.c" +#endif + +#if INFINITE_TAGS +#include "infinitetags/infinitetags.c" +#endif + +#if MOVE_RESIZE_WITH_KEYBOARD +#include "moveresizekbd/moveresizekbd.c" +#endif + +#if DIRECTIONAL_FOCUS +#include "directionalfocus/directionalfocus.c" +#endif + +#if DIRECTIONAL_MOVE +#include "directionalmove/directionalmove.c" +#endif + +#if AUTOSTART +#include "autostart/autostart.c" +#endif + +#if EXTERNAL_BARS +#include "externalbars/externalbars.c" +#endif diff --git a/modules/vxwm_includes.h b/modules/vxwm_includes.h new file mode 100644 index 0000000..b4c09a9 --- /dev/null +++ b/modules/vxwm_includes.h @@ -0,0 +1,53 @@ +#pragma once + +#if GAPS +#include "gaps/gaps.h" +#endif + +#if XRDB +#include "xrdb/xrdb.h" +#endif + +#if FULLSCREEN +#include "fullscreen/fullscreen.h" +#endif + +#if EWMH_TAGS +#include "ewmh_tags/ewmh_tags.h" +#endif + +#if WARP_TO_CLIENT +#include "warptoclient/warptoclient.h" +#endif + +#if ENHANCED_TOGGLE_FLOATING +#include "etf/etf.h" +#endif + +#if WINDOWMAP +#include "windowmap/windowmap.h" +#endif + +#if INFINITE_TAGS +#include "infinitetags/infinitetags.h" +#endif + +#if MOVE_RESIZE_WITH_KEYBOARD +#include "moveresizekbd/moveresizekbd.h" +#endif + +#if DIRECTIONAL_FOCUS +#include "directionalfocus/directionalfocus.h" +#endif + +#if DIRECTIONAL_MOVE +#include "directionalmove/directionalmove.h" +#endif + +#if AUTOSTART +#include "autostart/autostart.h" +#endif + +#if EXTERNAL_BARS +#include "externalbars/externalbars.h" +#endif diff --git a/modules/warptoclient/warptoclient.c b/modules/warptoclient/warptoclient.c new file mode 100644 index 0000000..fbedeaa --- /dev/null +++ b/modules/warptoclient/warptoclient.c @@ -0,0 +1,15 @@ +void +warptoclient(Client *c) +{ + int x, y; + + if (!c) { + XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww/2, selmon->wy + selmon->wh/2); + return; + } + + x = c->x + WIDTH(c) / 2; + y = c->y + HEIGHT(c) / 2; + + XWarpPointer(dpy, None, root, 0, 0, 0, 0, x, y); +} diff --git a/modules/warptoclient/warptoclient.h b/modules/warptoclient/warptoclient.h new file mode 100644 index 0000000..0017968 --- /dev/null +++ b/modules/warptoclient/warptoclient.h @@ -0,0 +1 @@ +static void warptoclient(Client *c); diff --git a/modules/windowmap/windowmap.c b/modules/windowmap/windowmap.c new file mode 100644 index 0000000..ef76153 --- /dev/null +++ b/modules/windowmap/windowmap.c @@ -0,0 +1,42 @@ +void +window_set_state(Display *dpy, Window win, long state) +{ + long data[] = { state, None }; + + XChangeProperty(dpy, win, wmatom[WMState], wmatom[WMState], 32, + PropModeReplace, (unsigned char*)data, 2); +} + +void +window_map(Display *dpy, Client *c, int deiconify) +{ + Window win = c->win; + + if (deiconify) + window_set_state(dpy, win, NormalState); + + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + XMapWindow(dpy, win); + focus(NULL); +} + +void +window_unmap(Display *dpy, Window win, Window root, int iconify) +{ + static XWindowAttributes ca, ra; + + XGetWindowAttributes(dpy, root, &ra); + XGetWindowAttributes(dpy, win, &ca); + + /* Prevent UnmapNotify events */ + XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask); + XSelectInput(dpy, win, ca.your_event_mask & ~StructureNotifyMask); + + XUnmapWindow(dpy, win); + focus(NULL); + if (iconify) + window_set_state(dpy, win, IconicState); + + XSelectInput(dpy, root, ra.your_event_mask); + XSelectInput(dpy, win, ca.your_event_mask); +} diff --git a/modules/windowmap/windowmap.h b/modules/windowmap/windowmap.h new file mode 100644 index 0000000..993b83a --- /dev/null +++ b/modules/windowmap/windowmap.h @@ -0,0 +1,3 @@ +static void window_set_state(Display *dpy, Window win, long state); +static void window_map(Display *dpy, Client *c, int deiconify); +static void window_unmap(Display *dpy, Window win, Window root, int iconify); diff --git a/modules/xrdb/xrdb.c b/modules/xrdb/xrdb.c new file mode 100644 index 0000000..556c6b8 --- /dev/null +++ b/modules/xrdb/xrdb.c @@ -0,0 +1,42 @@ +void +loadxrdb() +{ + Display *display; + char * resm; + XrmDatabase xrdb; + char *type; + XrmValue value; + + display = XOpenDisplay(NULL); + + if (display != NULL) { + resm = XResourceManagerString(display); + + if (resm != NULL) { + xrdb = XrmGetStringDatabase(resm); + + if (xrdb != NULL) { + XRDB_LOAD_COLOR("dwm.color0", normbordercolor); + XRDB_LOAD_COLOR("dwm.color8", selbordercolor); + XRDB_LOAD_COLOR("dwm.color0", normbgcolor); + XRDB_LOAD_COLOR("dwm.color6", normfgcolor); + XRDB_LOAD_COLOR("dwm.color0", selfgcolor); + XRDB_LOAD_COLOR("dwm.color14", selbgcolor); + } + } + } + + XCloseDisplay(display); +} + +void +xrdb(const Arg *arg) +{ + loadxrdb(); + int i; + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); + focus(NULL); + arrange(NULL); +} + diff --git a/modules/xrdb/xrdb.h b/modules/xrdb/xrdb.h new file mode 100644 index 0000000..aa7006f --- /dev/null +++ b/modules/xrdb/xrdb.h @@ -0,0 +1,20 @@ +#include <X11/Xresource.h> + +#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ + if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ + int i = 1; \ + for (; i <= 6; i++) { \ + if (value.addr[i] < 48) break; \ + if (value.addr[i] > 57 && value.addr[i] < 65) break; \ + if (value.addr[i] > 70 && value.addr[i] < 97) break; \ + if (value.addr[i] > 102) break; \ + } \ + if (i == 7) { \ + strncpy(V, value.addr, 7); \ + V[7] = '\0'; \ + } \ + } \ + } + +static void loadxrdb(void); +static void xrdb(const Arg *arg); |
