Compare commits

..

4 Commits

  1. 1
      .gitignore
  2. 24
      src/.clang-format
  3. 12
      src/.editorconfig
  4. 89
      src/IPCClient.c
  5. 16
      src/IPCClient.h
  6. 267
      src/config.def.h
  7. 348
      src/config.h
  8. 187
      src/drw.c
  9. 19
      src/drw.h
  10. 799
      src/dwm-msg.c
  11. 1391
      src/dwm.c
  12. 1809
      src/ipc.c
  13. 111
      src/ipc.h
  14. 6
      src/transient.c
  15. 229
      src/util.c
  16. 6
      src/util.h
  17. 173
      src/yajl_dumps.c
  18. 40
      src/yajl_dumps.h

1
.gitignore vendored

@ -8,3 +8,4 @@ src/ewm.desktop
pkg/
*.pkg*
src/compile_commands.json

@ -0,0 +1,24 @@
---
BasedOnStyle: LLVM
IndentWidth: 4
AllowShortFunctionsOnASingleLine: 'None'
AllowShortIfStatementsOnASingleLine: 'Never'
AlignAfterOpenBracket: 'Align'
AlignConsecutiveAssignments: 'Consecutive'
AlignConsecutiveBitFields: 'Consecutive'
AlignConsecutiveMacros: 'Consecutive'
AlignOperands: 'AlignAfterOperator'
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowShortBlocksOnASingleLine: 'Empty'
AllowShortLoopsOnASingleLine: false
BreakBeforeBraces: 'Attach'
BreakBeforeBinaryOperators: 'NonAssignment'
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceBeforeParens: 'ControlStatements'
TabWidth: 4
UseTab: 'ForIndentation'
ColumnLimit: 78
UseCRLF: false
DeriveLineEnding: false

@ -0,0 +1,12 @@
# This file is for unifying the coding style for different editors and IDEs
# See editorconfig.org
root = true
[*.{c,h,cpp,hpp}]
indent_style = tab
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

@ -5,62 +5,59 @@
#include "util.h"
IPCClient *
ipc_client_new(int fd)
{
IPCClient *c = (IPCClient *)malloc(sizeof(IPCClient));
IPCClient *ipc_client_new(int fd) {
IPCClient *c = (IPCClient *) malloc(sizeof(IPCClient));
if (c == NULL) return NULL;
if (c == NULL)
return NULL;
// Initialize struct
memset(&c->event, 0, sizeof(struct epoll_event));
// Initialize struct
memset(&c->event, 0, sizeof(struct epoll_event));
c->buffer_size = 0;
c->buffer = NULL;
c->fd = fd;
c->event.data.fd = fd;
c->next = NULL;
c->prev = NULL;
c->subscriptions = 0;
c->buffer_size = 0;
c->buffer = NULL;
c->fd = fd;
c->event.data.fd = fd;
c->next = NULL;
c->prev = NULL;
c->subscriptions = 0;
return c;
return c;
}
void
ipc_list_add_client(IPCClientList *list, IPCClient *nc)
{
DEBUG("Adding client with fd %d to list\n", nc->fd);
if (*list == NULL) {
// List is empty, point list at first client
*list = nc;
} else {
IPCClient *c;
// Go to last client in list
for (c = *list; c && c->next; c = c->next)
;
c->next = nc;
nc->prev = c;
}
void ipc_list_add_client(IPCClientList *list, IPCClient *nc) {
DEBUG("Adding client with fd %d to list\n", nc->fd);
if (*list == NULL) {
// List is empty, point list at first client
*list = nc;
} else {
IPCClient *c;
// Go to last client in list
for (c = *list; c && c->next; c = c->next)
;
c->next = nc;
nc->prev = c;
}
}
void
ipc_list_remove_client(IPCClientList *list, IPCClient *c)
{
IPCClient *cprev = c->prev;
IPCClient *cnext = c->next;
void ipc_list_remove_client(IPCClientList *list, IPCClient *c) {
IPCClient *cprev = c->prev;
IPCClient *cnext = c->next;
if (cprev != NULL) cprev->next = c->next;
if (cnext != NULL) cnext->prev = c->prev;
if (c == *list) *list = c->next;
if (cprev != NULL)
cprev->next = c->next;
if (cnext != NULL)
cnext->prev = c->prev;
if (c == *list)
*list = c->next;
}
IPCClient *
ipc_list_get_client(IPCClientList list, int fd)
{
for (IPCClient *c = list; c; c = c->next) {
if (c->fd == fd) return c;
}
IPCClient *ipc_list_get_client(IPCClientList list, int fd) {
for (IPCClient *c = list; c; c = c->next) {
if (c->fd == fd)
return c;
}
return NULL;
return NULL;
}

@ -11,15 +11,15 @@ typedef struct IPCClient IPCClient;
* linked list
*/
struct IPCClient {
int fd;
int subscriptions;
int fd;
int subscriptions;
char *buffer;
uint32_t buffer_size;
char *buffer;
uint32_t buffer_size;
struct epoll_event event;
IPCClient *next;
IPCClient *prev;
struct epoll_event event;
IPCClient *next;
IPCClient *prev;
};
typedef IPCClient *IPCClientList;
@ -58,4 +58,4 @@ void ipc_list_remove_client(IPCClientList *list, IPCClient *c);
*/
IPCClient *ipc_list_get_client(IPCClientList list, int fd);
#endif // IPC_CLIENT_H_
#endif // IPC_CLIENT_H_

@ -1,162 +1,169 @@
/* See LICENSE file for copyright and license details. */
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int gappx = 5; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const int usealtbar = 1; /* 1 means use non-dwm status bar */
static const char *altbarclass = "Polybar"; /* Alternate bar class name */
static const char *alttrayname = "tray"; /* Polybar tray instance name */
static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444";
static const char col_gray3[] = "#bbbbbb";
static const char col_gray4[] = "#eeeeee";
static const char col_cyan[] = "#005577";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int gappx = 5; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const int usealtbar = 1; /* 1 means use non-dwm status bar */
static const char *altbarclass = "Polybar"; /* Alternate bar class name */
static const char *alttrayname = "tray"; /* Polybar tray instance name */
static const char *altbarcmd =
"$HOME/bar.sh"; /* Alternate bar launch command */
static const char *fonts[] = {"monospace:size=10"};
static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444";
static const char col_gray3[] = "#bbbbbb";
static const char col_gray4[] = "#eeeeee";
static const char col_cyan[] = "#005577";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = {col_gray3, col_gray1, col_gray2},
[SchemeSel] = {col_gray4, col_cyan, col_cyan},
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const char *tags[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor
*/
{"Gimp", NULL, NULL, 0, 1, -1},
{"Firefox", NULL, NULL, 1 << 8, 0, -1},
};
/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints =
1; /* 1 means respect size hints in tiled resizals */
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
/* symbol arrange function */
{"[]=", tile}, /* first entry is default */
{"><>", NULL}, /* no layout function means floating behavior */
{"[M]", monocle},
};
/* key definitions */
#define MODKEY Mod1Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
#define TAGKEYS(KEY, TAG) \
{MODKEY, KEY, view, {.ui = 1 << TAG}}, \
{MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \
{MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}}, \
{MODKEY | ControlMask | ShiftMask, \
KEY, \
toggletag, \
{.ui = 1 << TAG}},
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
#define SHCMD(cmd) \
{ \
.v = (const char *[]) { \
"/bin/sh", "-c", cmd, NULL \
} \
}
#define STATUSBAR "dwmblocks"
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
static char dmenumon[2] =
"0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = {
"dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf",
col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL};
static const char *termcmd[] = {"st", NULL};
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Down, moveresize, {.v = "0x 25y 0w 0h" } },
{ MODKEY, XK_Up, moveresize, {.v = "0x -25y 0w 0h" } },
{ MODKEY, XK_Right, moveresize, {.v = "25x 0y 0w 0h" } },
{ MODKEY, XK_Left, moveresize, {.v = "-25x 0y 0w 0h" } },
{ MODKEY|ShiftMask, XK_Down, moveresize, {.v = "0x 0y 0w 25h" } },
{ MODKEY|ShiftMask, XK_Up, moveresize, {.v = "0x 0y 0w -25h" } },
{ MODKEY|ShiftMask, XK_Right, moveresize, {.v = "0x 0y 25w 0h" } },
{ MODKEY|ShiftMask, XK_Left, moveresize, {.v = "0x 0y -25w 0h" } },
{ MODKEY|ControlMask, XK_Up, moveresizeedge, {.v = "t"} },
{ MODKEY|ControlMask, XK_Down, moveresizeedge, {.v = "b"} },
{ MODKEY|ControlMask, XK_Left, moveresizeedge, {.v = "l"} },
{ MODKEY|ControlMask, XK_Right, moveresizeedge, {.v = "r"} },
{ MODKEY|ControlMask|ShiftMask, XK_Up, moveresizeedge, {.v = "T"} },
{ MODKEY|ControlMask|ShiftMask, XK_Down, moveresizeedge, {.v = "B"} },
{ MODKEY|ControlMask|ShiftMask, XK_Left, moveresizeedge, {.v = "L"} },
{ MODKEY|ControlMask|ShiftMask, XK_Right, moveresizeedge, {.v = "R"} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
{ MODKEY, XK_minus, setgaps, {.i = -1 } },
{ MODKEY, XK_equal, setgaps, {.i = +1 } },
{ MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY|ShiftMask, XK_q, quit, {0} },
/* modifier key function argument */
{MODKEY, XK_p, spawn, {.v = dmenucmd}},
{MODKEY | ShiftMask, XK_Return, spawn, {.v = termcmd}},
{MODKEY, XK_b, togglebar, {0}},
{MODKEY, XK_j, focusstack, {.i = +1}},
{MODKEY, XK_k, focusstack, {.i = -1}},
{MODKEY, XK_i, incnmaster, {.i = +1}},
{MODKEY, XK_d, incnmaster, {.i = -1}},
{MODKEY, XK_h, setmfact, {.f = -0.05}},
{MODKEY, XK_l, setmfact, {.f = +0.05}},
{MODKEY, XK_Return, zoom, {0}},
{MODKEY, XK_Down, moveresize, {.v = "0x 25y 0w 0h"}},
{MODKEY, XK_Up, moveresize, {.v = "0x -25y 0w 0h"}},
{MODKEY, XK_Right, moveresize, {.v = "25x 0y 0w 0h"}},
{MODKEY, XK_Left, moveresize, {.v = "-25x 0y 0w 0h"}},
{MODKEY | ShiftMask, XK_Down, moveresize, {.v = "0x 0y 0w 25h"}},
{MODKEY | ShiftMask, XK_Up, moveresize, {.v = "0x 0y 0w -25h"}},
{MODKEY | ShiftMask, XK_Right, moveresize, {.v = "0x 0y 25w 0h"}},
{MODKEY | ShiftMask, XK_Left, moveresize, {.v = "0x 0y -25w 0h"}},
{MODKEY | ControlMask, XK_Up, moveresizeedge, {.v = "t"}},
{MODKEY | ControlMask, XK_Down, moveresizeedge, {.v = "b"}},
{MODKEY | ControlMask, XK_Left, moveresizeedge, {.v = "l"}},
{MODKEY | ControlMask, XK_Right, moveresizeedge, {.v = "r"}},
{MODKEY | ControlMask | ShiftMask, XK_Up, moveresizeedge, {.v = "T"}},
{MODKEY | ControlMask | ShiftMask, XK_Down, moveresizeedge, {.v = "B"}},
{MODKEY | ControlMask | ShiftMask, XK_Left, moveresizeedge, {.v = "L"}},
{MODKEY | ControlMask | ShiftMask, XK_Right, moveresizeedge, {.v = "R"}},
{MODKEY, XK_Tab, view, {0}},
{MODKEY | ShiftMask, XK_c, killclient, {0}},
{MODKEY, XK_t, setlayout, {.v = &layouts[0]}},
{MODKEY, XK_f, setlayout, {.v = &layouts[1]}},
{MODKEY, XK_m, setlayout, {.v = &layouts[2]}},
{MODKEY, XK_space, setlayout, {0}},
{MODKEY | ShiftMask, XK_space, togglefloating, {0}},
{MODKEY | ShiftMask, XK_f, togglefullscr, {0}},
{MODKEY, XK_0, view, {.ui = ~0}},
{MODKEY | ShiftMask, XK_0, tag, {.ui = ~0}},
{MODKEY, XK_comma, focusmon, {.i = -1}},
{MODKEY, XK_period, focusmon, {.i = +1}},
{MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}},
{MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}},
{MODKEY, XK_minus, setgaps, {.i = -1}},
{MODKEY, XK_equal, setgaps, {.i = +1}},
{MODKEY | ShiftMask, XK_equal, setgaps, {.i = 0}},
TAGKEYS(XK_1, 0) TAGKEYS(XK_2, 1) TAGKEYS(XK_3, 2) TAGKEYS(XK_4, 3)
TAGKEYS(XK_5, 4) TAGKEYS(XK_6, 5) TAGKEYS(XK_7, 6) TAGKEYS(XK_8, 7)
TAGKEYS(XK_9, 8){MODKEY | ShiftMask, XK_q, quit, {0}},
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
* ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button1, sigstatusbar, {.i = 1} },
{ ClkStatusText, 0, Button2, sigstatusbar, {.i = 2} },
{ ClkStatusText, 0, Button3, sigstatusbar, {.i = 3} },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
/* click event mask button function argument
*/
{ClkLtSymbol, 0, Button1, setlayout, {0}},
{ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}},
{ClkWinTitle, 0, Button2, zoom, {0}},
{ClkStatusText, 0, Button1, sigstatusbar, {.i = 1}},
{ClkStatusText, 0, Button2, sigstatusbar, {.i = 2}},
{ClkStatusText, 0, Button3, sigstatusbar, {.i = 3}},
{ClkClientWin, MODKEY, Button1, movemouse, {0}},
{ClkClientWin, MODKEY, Button2, togglefloating, {0}},
{ClkClientWin, MODKEY, Button3, resizemouse, {0}},
{ClkTagBar, 0, Button1, view, {0}},
{ClkTagBar, 0, Button3, toggleview, {0}},
{ClkTagBar, MODKEY, Button1, tag, {0}},
{ClkTagBar, MODKEY, Button3, toggletag, {0}},
};
static const char *ipcsockpath = "/tmp/dwm.sock";
static const char *ipcsockpath = "/tmp/dwm.sock";
static IPCCommand ipccommands[] = {
IPCCOMMAND( view, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( toggleview, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( tag, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( toggletag, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( tagmon, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( focusmon, 1, {ARG_TYPE_SINT} ),
IPCCOMMAND( focusstack, 1, {ARG_TYPE_SINT} ),
IPCCOMMAND( zoom, 1, {ARG_TYPE_NONE} ),
IPCCOMMAND( incnmaster, 1, {ARG_TYPE_SINT} ),
IPCCOMMAND( killclient, 1, {ARG_TYPE_SINT} ),
IPCCOMMAND( togglefloating, 1, {ARG_TYPE_NONE} ),
IPCCOMMAND( setmfact, 1, {ARG_TYPE_FLOAT} ),
IPCCOMMAND( setlayoutsafe, 1, {ARG_TYPE_PTR} ),
IPCCOMMAND( quit, 1, {ARG_TYPE_NONE} )
};
IPCCOMMAND(view, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(toggleview, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(tag, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(toggletag, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(tagmon, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(focusmon, 1, {ARG_TYPE_SINT}),
IPCCOMMAND(focusstack, 1, {ARG_TYPE_SINT}),
IPCCOMMAND(zoom, 1, {ARG_TYPE_NONE}),
IPCCOMMAND(incnmaster, 1, {ARG_TYPE_SINT}),
IPCCOMMAND(killclient, 1, {ARG_TYPE_SINT}),
IPCCOMMAND(togglefloating, 1, {ARG_TYPE_NONE}),
IPCCOMMAND(setmfact, 1, {ARG_TYPE_FLOAT}),
IPCCOMMAND(setlayoutsafe, 1, {ARG_TYPE_PTR}),
IPCCOMMAND(quit, 1, {ARG_TYPE_NONE})};

@ -2,197 +2,219 @@
#include <X11/XF86keysym.h>
#define STATUSBAR "dwmblocks"
/* appearance */
static const unsigned int borderpx = 2; /* border pixel of windows */
static const unsigned int snap = 0; /* snap pixel (32)*/
static const unsigned int gappx = 0;
static const unsigned int gapmodes[] = { 0, 20 };
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 0; /* 0 means bottom bar */
static const int barverticalpadding = 6; /* Vertical bar padding */
static const int usealtbar = 1; /* 1 means use non-dwm status bar */
static const unsigned int borderpx = 0; /* border pixel of windows */
static const unsigned int snap = 0; /* snap pixel (32)*/
static const unsigned int gappx = 0;
static const unsigned int gapmodes[] = {20, 0};
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const int barverticalpadding = 6; /* Vertical bar padding */
static const int usealtbar = 0; /* 1 means use non-dwm status bar */
static const char *altbarclass = "Polybar"; /* Alternate bar class name */
static const char *alttrayname = "tray"; /* Polybar tray instance name */
static const char *altbarcmd = "$HOME/.config/polybar/launch"; /* Alternate bar launch command */
static const char *fonts[] = { "Fira Code:size=11" };
static const char dmenufont[] = "Fira Code:size=15";
static const char *altbarclass = "Polybar"; /* Alternate bar class name */
static const char *alttrayname = "tray"; /* Polybar tray instance name */
// static const char *altbarcmd = "$HOME/.config/polybar/launch"; /*
// Alternate bar launch command */
static const char *altbarcmd = "";
static const char *fonts[] = {"Fira Code:size=11"};
static const char dmenufont[] = "Fira Code:size=15";
static const char bg_alt_color[] = "#272a34";
static const char bg_color[] = "#282c34";
static const char text_color[] = "#bbc2cf";
static const char selected_color[] = "#81a2be";
static const char border_color_sel[] = "#444953";
static const char border_color_norm[] = "#32373f";
static const char bg_color[] = "#181818";
static const char bg_alt_color[] = "#111111";
static const char text_color[] = "#bbc2cf";
static const char selected_color[] = "#81a2be";
static const char border_color_sel[] = "#444953";
static const char border_color_norm[] = "#32373f";
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444";
static const char col_gray3[] = "#bbbbbb";
static const char col_gray4[] = "#eeeeee";
static const char col_cyan[] = "#5f819d";
//static const char col_cyan[] = "#51afef";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { text_color, bg_color, border_color_norm },
[SchemeSel] = { col_cyan, bg_alt_color, border_color_sel },
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444";
static const char col_gray3[] = "#bbbbbb";
static const char col_gray4[] = "#eeeeee";
static const char col_cyan[] = "#5f819d";
// static const char col_cyan[] = "#51afef";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = {text_color, bg_color, border_color_norm},
[SchemeSel] = {col_cyan, bg_alt_color, border_color_sel},
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const char *tags[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
{ "discord", NULL, NULL, 0, 0, -1 },
{ "Steam", NULL, NULL, 0, 0, -1 },
{ "Qemu-system-x86_64", NULL, NULL, 0, 1, -1 },
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask
* isfloating monitor
*/
{"Gimp", NULL, NULL, 0, 1, -1},
{"Firefox", NULL, NULL, 1 << 8, 0, -1},
{"discord", NULL, NULL, 0, 0, -1},
{"Steam", NULL, NULL, 0, 0, -1},
{"Qemu-system-x86_64", NULL, NULL, 0, 1, -1},
};
/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints =
1; /* 1 means respect size hints in tiled resizals */
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL },
{ "[M]", monocle },
/* symbol arrange function */
{"[]=", tile}, /* first entry is default */
{"><>", NULL},
{"[M]", monocle},
};
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
#define TAGKEYS(KEY, TAG) \
{MODKEY, KEY, view, {.ui = 1 << TAG}}, \
{MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \
{MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}}, \
{MODKEY | ControlMask | ShiftMask, \
KEY, \
toggletag, \
{.ui = 1 << TAG}},
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
#define SHCMD(cmd) \
{ \
.v = (const char *[]) { \
"/bin/sh", "-c", cmd, NULL \
} \
}
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-p", "Run $", "-z", "512", NULL };
static const char *termcmd[] = { "alacritty", NULL };
static const char *browsercmd[] = { "firefox", NULL };
static const char *betterlockscreencmd[] = { "betterlockscreen", "--lock", "blur", NULL };
static const char *screenshotcmd[] = { "flameshot", "gui", NULL };
static const char *cmuspausecmd[] = { "cmus-remote", "--pause", NULL };
static char dmenumon[2] =
"0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = {"dmenu_run", "-m", dmenumon, "-p",
"Run $", "-z", "512", NULL};
static const char *termcmd[] = {"alacritty", NULL};
static const char *browsercmd[] = {"firefox", NULL};
static const char *betterlockscreencmd[] = {"betterlockscreen", "--lock",
"blur", NULL};
static const char *screenshotcmd[] = {"flameshot", "gui", NULL};
static const char *cmuspausecmd[] = {"cmus-remote", "--pause", NULL};
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XF86XK_AudioLowerVolume, spawn, SHCMD("amixer -q set Master 5%- unmute; pkill -RTMIN+1 dwmblocks") },
{ MODKEY, XF86XK_AudioRaiseVolume, spawn, SHCMD("amixer -q set Master 5%+ unmute; pkill -RTMIN+1 dwmblocks") },
{ MODKEY, XF86XK_AudioMute, spawn, SHCMD("amixer -q set Master toggle; pkill -RTMIN+1 dwmblocks") },
{ MODKEY|ShiftMask, XF86XK_AudioMute, spawn, SHCMD("amixer set Capture toggle") },
//{ MODKEY, XK_d, spawn, {.v = dmenucmd } },
{ MODKEY, XK_d, spawn, SHCMD("rofi -show drun")},
{ MODKEY, XK_s, spawn, SHCMD("rofi -show ssh")},
{ MODKEY, XK_w, spawn, SHCMD("rofi -show window")},
{ MODKEY, XK_r, spawn, SHCMD("rofi -show run")},
{ MODKEY, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_e, spawn, {.v = browsercmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_p, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_q, killclient, {0} },
{ MODKEY, XK_Down, moveresize, {.v = "0x 25y 0w 0h" } },
{ MODKEY, XK_Up, moveresize, {.v = "0x -25y 0w 0h" } },
{ MODKEY, XK_Right, moveresize, {.v = "25x 0y 0w 0h" } },
{ MODKEY, XK_Left, moveresize, {.v = "-25x 0y 0w 0h" } },
{ MODKEY|ShiftMask, XK_Down, moveresize, {.v = "0x 0y 0w 25h" } },
{ MODKEY|ShiftMask, XK_Up, moveresize, {.v = "0x 0y 0w -25h" } },
{ MODKEY|ShiftMask, XK_Right, moveresize, {.v = "0x 0y 25w 0h" } },
{ MODKEY|ShiftMask, XK_Left, moveresize, {.v = "0x 0y -25w 0h" } },
{ MODKEY|ControlMask, XK_Up, moveresizeedge, {.v = "t"} },
{ MODKEY|ControlMask, XK_Down, moveresizeedge, {.v = "b"} },
{ MODKEY|ControlMask, XK_Left, moveresizeedge, {.v = "l"} },
{ MODKEY|ControlMask, XK_Right, moveresizeedge, {.v = "r"} },
{ MODKEY|ControlMask|ShiftMask, XK_Up, moveresizeedge, {.v = "T"} },
{ MODKEY|ControlMask|ShiftMask, XK_Down, moveresizeedge, {.v = "B"} },
{ MODKEY|ControlMask|ShiftMask, XK_Left, moveresizeedge, {.v = "L"} },
{ MODKEY|ControlMask|ShiftMask, XK_Right, moveresizeedge, {.v = "R"} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
//{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_x, spawn, {.v = betterlockscreencmd} },
{ MODKEY, XK_Print, spawn, {.v = screenshotcmd} },
{ MODKEY, XK_u, spawn, {.v = cmuspausecmd} },
{ MODKEY, XK_g, switchgaps, {.i = +1 } },
{ MODKEY, XK_v, switchgaps, {.i = -1 } },
{ MODKEY, XK_minus, setgaps, {.i = -1 } },
{ MODKEY, XK_plus, setgaps, {.i = +1 } },
{ MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY|ShiftMask, XK_e, quit, {0} },
/* modifier key
* function argument
*/
{MODKEY, XF86XK_AudioLowerVolume, spawn,
SHCMD("amixer -q set Master 5%- unmute; pkill -RTMIN+1 dwmblocks")},
{MODKEY, XF86XK_AudioRaiseVolume, spawn,
SHCMD("amixer -q set Master 5%+ unmute; pkill -RTMIN+1 dwmblocks")},
{MODKEY, XF86XK_AudioMute, spawn,
SHCMD("amixer -q set Master toggle; pkill -RTMIN+1 dwmblocks")},
{MODKEY | ShiftMask, XF86XK_AudioMute, spawn,
SHCMD("amixer set Capture toggle")},
//{ MODKEY, XK_d, spawn, {.v
//= dmenucmd
//}
//},
{MODKEY, XK_d, spawn, SHCMD("rofi -show drun")},
{MODKEY, XK_s, spawn, SHCMD("rofi -show ssh")},
{MODKEY, XK_w, spawn, SHCMD("rofi -show window")},
{MODKEY, XK_r, spawn, SHCMD("rofi -show run")},
{MODKEY, XK_Return, spawn, {.v = termcmd}},
{MODKEY, XK_e, spawn, {.v = browsercmd}},
{MODKEY, XK_b, togglebar, {0}},
{MODKEY, XK_j, focusstack, {.i = +1}},
{MODKEY, XK_k, focusstack, {.i = -1}},
{MODKEY, XK_i, incnmaster, {.i = +1}},
{MODKEY, XK_p, incnmaster, {.i = -1}},
{MODKEY, XK_h, setmfact, {.f = -0.05}},
{MODKEY, XK_l, setmfact, {.f = +0.05}},
{MODKEY | ShiftMask, XK_Return, zoom, {0}},
{MODKEY, XK_Tab, view, {0}},
{MODKEY | ShiftMask, XK_q, killclient, {0}},
{MODKEY, XK_Down, moveresize, {.v = "0x 25y 0w 0h"}},
{MODKEY, XK_Up, moveresize, {.v = "0x -25y 0w 0h"}},
{MODKEY, XK_Right, moveresize, {.v = "25x 0y 0w 0h"}},
{MODKEY, XK_Left, moveresize, {.v = "-25x 0y 0w 0h"}},
{MODKEY | ShiftMask, XK_Down, moveresize, {.v = "0x 0y 0w 25h"}},
{MODKEY | ShiftMask, XK_Up, moveresize, {.v = "0x 0y 0w -25h"}},
{MODKEY | ShiftMask, XK_Right, moveresize, {.v = "0x 0y 25w 0h"}},
{MODKEY | ShiftMask, XK_Left, moveresize, {.v = "0x 0y -25w 0h"}},
{MODKEY | ControlMask, XK_Up, moveresizeedge, {.v = "t"}},
{MODKEY | ControlMask, XK_Down, moveresizeedge, {.v = "b"}},
{MODKEY | ControlMask, XK_Left, moveresizeedge, {.v = "l"}},
{MODKEY | ControlMask, XK_Right, moveresizeedge, {.v = "r"}},
{MODKEY | ControlMask | ShiftMask, XK_Up, moveresizeedge, {.v = "T"}},
{MODKEY | ControlMask | ShiftMask, XK_Down, moveresizeedge, {.v = "B"}},
{MODKEY | ControlMask | ShiftMask, XK_Left, moveresizeedge, {.v = "L"}},
{MODKEY | ControlMask | ShiftMask, XK_Right, moveresizeedge, {.v = "R"}},
{MODKEY, XK_f, setlayout, {.v = &layouts[1]}},
{MODKEY, XK_t, setlayout, {.v = &layouts[0]}},
{MODKEY, XK_m, setlayout, {.v = &layouts[2]}},
//{ MODKEY, XK_space, setlayout,
//{0}
//},
{MODKEY | ShiftMask, XK_space, togglefloating, {0}},
{MODKEY | ShiftMask, XK_f, togglefullscr, {0}},
{MODKEY, XK_0, view, {.ui = ~0}},
{MODKEY | ShiftMask, XK_0, tag, {.ui = ~0}},
{MODKEY, XK_comma, focusmon, {.i = -1}},
{MODKEY, XK_period, focusmon, {.i = +1}},
{MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}},
{MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}},
{MODKEY | ShiftMask, XK_l, spawn, {.v = betterlockscreencmd}},
{MODKEY, XK_Print, spawn, {.v = screenshotcmd}},
{MODKEY, XK_u, spawn, {.v = cmuspausecmd}},
{MODKEY, XK_g, switchgaps, {.i = +1}},
{MODKEY, XK_v, switchgaps, {.i = -1}},
{MODKEY, XK_minus, setgaps, {.i = -1}},
{MODKEY, XK_plus, setgaps, {.i = +1}},
{MODKEY | ShiftMask, XK_equal, setgaps, {.i = 0}},
TAGKEYS(XK_1, 0) TAGKEYS(XK_2, 1) TAGKEYS(XK_3, 2) TAGKEYS(XK_4, 3)
TAGKEYS(XK_5, 4) TAGKEYS(XK_6, 5) TAGKEYS(XK_7, 6) TAGKEYS(XK_8, 7)
TAGKEYS(XK_9, 8){MODKEY | ShiftMask, XK_e, quit, {0}},
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
* ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkStatusText, 0, Button1, sigstatusbar, {.i = 1} },
{ ClkStatusText, 0, Button2, sigstatusbar, {.i = 2} },
{ ClkStatusText, 0, Button3, sigstatusbar, {.i = 3} },
{ ClkStatusText, 0, Button4, sigstatusbar, {.i = 4} },
{ ClkStatusText, 0, Button5, sigstatusbar, {.i = 5} },
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
/* click event mask button
* function argument
*/
{ClkStatusText, 0, Button1, sigstatusbar, {.i = 1}},
{ClkStatusText, 0, Button2, sigstatusbar, {.i = 2}},
{ClkStatusText, 0, Button3, sigstatusbar, {.i = 3}},
{ClkStatusText, 0, Button4, sigstatusbar, {.i = 4}},
{ClkStatusText, 0, Button5, sigstatusbar, {.i = 5}},
{ClkLtSymbol, 0, Button1, setlayout, {0}},
{ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}},
{ClkWinTitle, 0, Button2, zoom, {0}},
{ClkStatusText, 0, Button2, spawn, {.v = termcmd}},
{ClkClientWin, MODKEY, Button1, movemouse, {0}},
{ClkClientWin, MODKEY, Button2, togglefloating, {0}},
{ClkClientWin, MODKEY, Button3, resizemouse, {0}},
{ClkTagBar, 0, Button1, view, {0}},
{ClkTagBar, 0, Button3, toggleview, {0}},
{ClkTagBar, MODKEY, Button1, tag, {0}},
{ClkTagBar, MODKEY, Button3, toggletag, {0}},
};
static const char *ipcsockpath = "/tmp/dwm.sock";
static const char *ipcsockpath = "/tmp/dwm.sock";
static IPCCommand ipccommands[] = {
IPCCOMMAND( view, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( toggleview, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( tag, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( toggletag, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( tagmon, 1, {ARG_TYPE_UINT} ),
IPCCOMMAND( focusmon, 1, {ARG_TYPE_SINT} ),
IPCCOMMAND( focusstack, 1, {ARG_TYPE_SINT} ),
IPCCOMMAND( zoom, 1, {ARG_TYPE_NONE} ),
IPCCOMMAND( incnmaster, 1, {ARG_TYPE_SINT} ),
IPCCOMMAND( killclient, 1, {ARG_TYPE_SINT} ),
IPCCOMMAND( togglefloating, 1, {ARG_TYPE_NONE} ),
IPCCOMMAND( setmfact, 1, {ARG_TYPE_FLOAT} ),
IPCCOMMAND( setlayoutsafe, 1, {ARG_TYPE_PTR} ),
IPCCOMMAND( quit, 1, {ARG_TYPE_NONE} )
};
IPCCOMMAND(view, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(toggleview, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(tag, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(toggletag, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(tagmon, 1, {ARG_TYPE_UINT}),
IPCCOMMAND(focusmon, 1, {ARG_TYPE_SINT}),
IPCCOMMAND(focusstack, 1, {ARG_TYPE_SINT}),
IPCCOMMAND(zoom, 1, {ARG_TYPE_NONE}),
IPCCOMMAND(incnmaster, 1, {ARG_TYPE_SINT}),
IPCCOMMAND(killclient, 1, {ARG_TYPE_SINT}),
IPCCOMMAND(togglefloating, 1, {ARG_TYPE_NONE}),
IPCCOMMAND(setmfact, 1, {ARG_TYPE_FLOAT}),
IPCCOMMAND(setlayoutsafe, 1, {ARG_TYPE_PTR}),
IPCCOMMAND(quit, 1, {ARG_TYPE_NONE})};

@ -1,9 +1,9 @@
/* See LICENSE file for copyright and license details. */
#include <X11/Xft/Xft.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
#include "drw.h"
#include "util.h"
@ -11,23 +11,21 @@
#define UTF_INVALID 0xFFFD
#define UTF_SIZ 4
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0,
0xF8};
static const long utfmin[UTF_SIZ + 1] = {0, 0, 0x80, 0x800, 0x10000};
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF,
0x10FFFF};
static long
utf8decodebyte(const char c, size_t *i)
{
static long utf8decodebyte(const char c, size_t *i) {
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
return (unsigned char)c & ~utfmask[*i];
if (((unsigned char) c & utfmask[*i]) == utfbyte[*i])
return (unsigned char) c & ~utfmask[*i];
return 0;
}
static size_t
utf8validate(long *u, size_t i)
{
static size_t utf8validate(long *u, size_t i) {
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
*u = UTF_INVALID;
for (i = 1; *u > utfmax[i]; ++i)
@ -35,9 +33,7 @@ utf8validate(long *u, size_t i)
return i;
}
static size_t
utf8decode(const char *c, long *u, size_t clen)
{
static size_t utf8decode(const char *c, long *u, size_t clen) {
size_t i, j, len, type;
long udecoded;
@ -60,26 +56,23 @@ utf8decode(const char *c, long *u, size_t clen)
return len;
}
Drw *
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
{
Drw *drw_create(Display *dpy, int screen, Window root, unsigned int w,
unsigned int h) {
Drw *drw = ecalloc(1, sizeof(Drw));
drw->dpy = dpy;
drw->screen = screen;
drw->root = root;
drw->w = w;
drw->h = h;
drw->dpy = dpy;
drw->screen = screen;
drw->root = root;
drw->w = w;
drw->h = h;
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
drw->gc = XCreateGC(dpy, root, 0, NULL);
drw->gc = XCreateGC(dpy, root, 0, NULL);
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
return drw;
}
void
drw_resize(Drw *drw, unsigned int w, unsigned int h)
{
void drw_resize(Drw *drw, unsigned int w, unsigned int h) {
if (!drw)
return;
@ -87,12 +80,11 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h)
drw->h = h;
if (drw->drawable)
XFreePixmap(drw->dpy, drw->drawable);
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h,
DefaultDepth(drw->dpy, drw->screen));
}
void
drw_free(Drw *drw)
{
void drw_free(Drw *drw) {
XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc);
drw_fontset_free(drw->fonts);
@ -102,11 +94,10 @@ drw_free(Drw *drw)
/* This function is an implementation detail. Library users should use
* drw_fontset_create instead.
*/
static Fnt *
xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
{
static Fnt *xfont_create(Drw *drw, const char *fontname,
FcPattern *fontpattern) {
Fnt *font;
XftFont *xfont = NULL;
XftFont *xfont = NULL;
FcPattern *pattern = NULL;
if (fontname) {
@ -116,11 +107,14 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
* behaviour whereas the former just results in missing-character
* rectangles being drawn, at least with some fonts. */
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
fprintf(stderr, "error, cannot load font from name: '%s'\n",
fontname);
return NULL;
}
if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
fprintf(stderr,
"error, cannot parse font name to pattern: '%s'\n",
fontname);
XftFontClose(drw->dpy, xfont);
return NULL;
}
@ -141,23 +135,22 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
* and lots more all over the internet.
*/
FcBool iscol;
if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
if (FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch
&& iscol) {
XftFontClose(drw->dpy, xfont);
return NULL;
}
font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont;
font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont;
font->pattern = pattern;
font->h = xfont->ascent + xfont->descent;
font->dpy = drw->dpy;
font->h = xfont->ascent + xfont->descent;
font->dpy = drw->dpy;
return font;
}
static void
xfont_free(Fnt *font)
{
static void xfont_free(Fnt *font) {
if (!font)
return;
if (font->pattern)
@ -166,9 +159,7 @@ xfont_free(Fnt *font)
free(font);
}
Fnt*
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
{
Fnt *drw_fontset_create(Drw *drw, const char *fonts[], size_t fontcount) {
Fnt *cur, *ret = NULL;
size_t i;
@ -178,30 +169,26 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
for (i = 1; i <= fontcount; i++) {
if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
cur->next = ret;
ret = cur;
ret = cur;
}
}
return (drw->fonts = ret);
}
void
drw_fontset_free(Fnt *font)
{
void drw_fontset_free(Fnt *font) {
if (font) {
drw_fontset_free(font->next);
xfont_free(font);
}
}
void
drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
{
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname) {
if (!drw || !dest || !clrname)
return;
if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen),
clrname, dest))
DefaultColormap(drw->dpy, drw->screen), clrname,
dest))
die("error, cannot allocate color '%s'", clrname);
dest->pixel |= 0xff << 24;
@ -209,14 +196,13 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
/* Wrapper to create color schemes. The caller has to call free(3) on the
* returned color scheme when done using it. */
Clr *
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
{
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) {
size_t i;
Clr *ret;
/* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
if (!drw || !clrnames || clrcount < 2
|| !(ret = ecalloc(clrcount, sizeof(XftColor))))
return NULL;
for (i = 0; i < clrcount; i++)
@ -224,35 +210,31 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
return ret;
}
void
drw_setfontset(Drw *drw, Fnt *set)
{
void drw_setfontset(Drw *drw, Fnt *set) {
if (drw)
drw->fonts = set;
}
void
drw_setscheme(Drw *drw, Clr *scm)
{
void drw_setscheme(Drw *drw, Clr *scm) {
if (drw)
drw->scheme = scm;
}
void
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
{
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h,
int filled, int invert) {
if (!drw || !drw->scheme)
return;
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
XSetForeground(drw->dpy, drw->gc,
invert ? drw->scheme[ColBg].pixel
: drw->scheme[ColFg].pixel);
if (filled)
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
else
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
}
int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
{
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h,
unsigned int lpad, const char *text, int invert) {
char buf[1024];
int ty;
unsigned int ew;
@ -274,7 +256,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
if (!render) {
w = ~w;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XSetForeground(drw->dpy, drw->gc,
drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
d = XftDrawCreate(drw->dpy, drw->drawable,
DefaultVisual(drw->dpy, drw->screen),
@ -286,12 +269,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
usedfont = drw->fonts;
while (1) {
utf8strlen = 0;
utf8str = text;
nextfont = NULL;
utf8str = text;
nextfont = NULL;
while (*text) {
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
charexists =
charexists
|| XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) {
if (curfont == usedfont) {
utf8strlen += utf8charlen;
@ -325,7 +310,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
if (render) {
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
usedfont->xfont, x, ty,
(XftChar8 *) buf, len);
}
x += ew;
w -= ew;
@ -336,7 +322,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
break;
} else if (nextfont) {
charexists = 0;
usedfont = nextfont;
usedfont = nextfont;
} else {
/* Regardless of whether or not a fallback font is found, the
* character must be drawn. */
@ -346,8 +332,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
FcCharSetAddChar(fccharset, utf8codepoint);
if (!drw->fonts->pattern) {
/* Refer to the comment in xfont_create for more information. */
die("the first font in the cache must be loaded from a font string.");
/* Refer to the comment in xfont_create for more information.
*/
die("the first font in the cache must be loaded from a font "
"string.");
}
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
@ -364,8 +352,11 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
if (match) {
usedfont = xfont_create(drw, NULL, match);
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
if (usedfont
&& XftCharExists(drw->dpy, usedfont->xfont,
utf8codepoint)) {
for (curfont = drw->fonts; curfont->next;
curfont = curfont->next)
; /* NOP */
curfont->next = usedfont;
} else {
@ -381,9 +372,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
return x + (render ? w : 0);
}
void
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
{
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w,
unsigned int h) {
if (!drw)
return;
@ -391,32 +381,27 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
XSync(drw->dpy, False);
}
unsigned int
drw_fontset_getwidth(Drw *drw, const char *text)
{
unsigned int drw_fontset_getwidth(Drw *drw, const char *text) {
if (!drw || !drw->fonts || !text)
return 0;
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
}
void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
{
void drw_font_getexts(Fnt *font, const char *text, unsigned int len,
unsigned int *w, unsigned int *h) {
XGlyphInfo ext;
if (!font || !text)
return;
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *) text, len, &ext);
if (w)
*w = ext.xOff;
if (h)
*h = font->h;
}
Cur *
drw_cur_create(Drw *drw, int shape)
{
Cur *drw_cur_create(Drw *drw, int shape) {
Cur *cur;
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
@ -427,9 +412,7 @@ drw_cur_create(Drw *drw, int shape)
return cur;
}
void
drw_cur_free(Drw *drw, Cur *cursor)
{
void drw_cur_free(Drw *drw, Cur *cursor) {
if (!cursor)
return;

@ -27,15 +27,17 @@ typedef struct {
} Drw;
/* Drawable abstraction */
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w,
unsigned int h);
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
void drw_free(Drw *drw);
/* Fnt abstraction */
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt* set);
Fnt *drw_fontset_create(Drw *drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt *set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len,
unsigned int *w, unsigned int *h);
/* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
@ -50,8 +52,11 @@ void drw_setfontset(Drw *drw, Fnt *set);
void drw_setscheme(Drw *drw, Clr *scm);
/* Drawing functions */
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h,
int filled, int invert);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h,
unsigned int lpad, const char *text, int invert);
/* Map functions */
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w,
unsigned int h);

@ -15,310 +15,302 @@
// clang-format off
#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' }
// clang-format on
#define IPC_MAGIC_LEN 7 // Not including null char
#define IPC_MAGIC_LEN 7 // Not including null char
#define IPC_EVENT_TAG_CHANGE "tag_change_event"
#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event"
#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event"
#define IPC_EVENT_TAG_CHANGE "tag_change_event"
#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event"
#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event"
#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_change_event"
#define IPC_EVENT_FOCUSED_TITLE_CHANGE "focused_title_change_event"
#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_change_event"
#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
#define YINT(num) yajl_gen_integer(gen, num)
#define YSTR(str) yajl_gen_string(gen, (unsigned char *) str, strlen(str))
#define YINT(num) yajl_gen_integer(gen, num)
#define YDOUBLE(num) yajl_gen_double(gen, num)
#define YBOOL(v) yajl_gen_bool(gen, v)
#define YNULL() yajl_gen_null(gen)
#define YARR(body) \
{ \
yajl_gen_array_open(gen); \
body; \
yajl_gen_array_close(gen); \
}
#define YMAP(body) \
{ \
yajl_gen_map_open(gen); \
body; \
yajl_gen_map_close(gen); \
}
#define YBOOL(v) yajl_gen_bool(gen, v)
#define YNULL() yajl_gen_null(gen)
#define YARR(body) \
{ \
yajl_gen_array_open(gen); \
body; \
yajl_gen_array_close(gen); \
}
#define YMAP(body) \
{ \
yajl_gen_map_open(gen); \
body; \
yajl_gen_map_close(gen); \
}
typedef unsigned long Window;
const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock";
static int sock_fd = -1;
const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock";
static int sock_fd = -1;
static unsigned int ignore_reply = 0;
typedef enum IPCMessageType {
IPC_TYPE_RUN_COMMAND = 0,
IPC_TYPE_GET_MONITORS = 1,
IPC_TYPE_GET_TAGS = 2,
IPC_TYPE_GET_LAYOUTS = 3,
IPC_TYPE_GET_DWM_CLIENT = 4,
IPC_TYPE_SUBSCRIBE = 5,
IPC_TYPE_EVENT = 6
IPC_TYPE_RUN_COMMAND = 0,
IPC_TYPE_GET_MONITORS = 1,
IPC_TYPE_GET_TAGS = 2,
IPC_TYPE_GET_LAYOUTS = 3,
IPC_TYPE_GET_DWM_CLIENT = 4,
IPC_TYPE_SUBSCRIBE = 5,
IPC_TYPE_EVENT = 6
} IPCMessageType;
// Every IPC message must begin with this
typedef struct dwm_ipc_header {
uint8_t magic[IPC_MAGIC_LEN];
uint32_t size;
uint8_t type;
uint8_t magic[IPC_MAGIC_LEN];
uint32_t size;
uint8_t type;
} __attribute((packed)) dwm_ipc_header_t;
static int
recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply)
{
uint32_t read_bytes = 0;
const int32_t to_read = sizeof(dwm_ipc_header_t);
char header[to_read];
char *walk = header;
// Try to read header
while (read_bytes < to_read) {
ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes);
if (n == 0) {
if (read_bytes == 0) {
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n",
read_bytes, to_read);
return -2;
} else {
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n",
read_bytes, to_read);
return -3;
}
} else if (n == -1) {
return -1;
}
read_bytes += n;
}
// Check if magic string in header matches
if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) {
fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n",
IPC_MAGIC_LEN, walk, IPC_MAGIC);
return -3;
}
walk += IPC_MAGIC_LEN;
// Extract reply size
memcpy(reply_size, walk, sizeof(uint32_t));
walk += sizeof(uint32_t);
// Extract message type
memcpy(msg_type, walk, sizeof(uint8_t));
walk += sizeof(uint8_t);
(*reply) = malloc(*reply_size);
// Extract payload
read_bytes = 0;
while (read_bytes < *reply_size) {
ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes);
if (n == 0) {
fprintf(stderr, "Unexpectedly reached EOF while reading payload.");
fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n",
read_bytes, *reply_size);
free(*reply);
return -2;
} else if (n == -1) {
if (errno == EINTR || errno == EAGAIN) continue;
free(*reply);
return -1;
}
read_bytes += n;
}
return 0;
static int recv_message(uint8_t *msg_type, uint32_t *reply_size,
uint8_t **reply) {
uint32_t read_bytes = 0;
const int32_t to_read = sizeof(dwm_ipc_header_t);
char header[to_read];
char *walk = header;
// Try to read header
while (read_bytes < to_read) {
ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes);
if (n == 0) {
if (read_bytes == 0) {
fprintf(stderr,
"Unexpectedly reached EOF while reading header.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32
" total bytes.\n",
read_bytes, to_read);
return -2;
} else {
fprintf(stderr,
"Unexpectedly reached EOF while reading header.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32
" total bytes.\n",
read_bytes, to_read);
return -3;
}
} else if (n == -1) {
return -1;
}
read_bytes += n;
}
// Check if magic string in header matches
if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) {
fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n",
IPC_MAGIC_LEN, walk, IPC_MAGIC);
return -3;
}
walk += IPC_MAGIC_LEN;
// Extract reply size
memcpy(reply_size, walk, sizeof(uint32_t));
walk += sizeof(uint32_t);
// Extract message type
memcpy(msg_type, walk, sizeof(uint8_t));
walk += sizeof(uint8_t);
(*reply) = malloc(*reply_size);
// Extract payload
read_bytes = 0;
while (read_bytes < *reply_size) {
ssize_t n =
read(sock_fd, *reply + read_bytes, *reply_size - read_bytes);
if (n == 0) {
fprintf(stderr,
"Unexpectedly reached EOF while reading payload.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n",
read_bytes, *reply_size);
free(*reply);
return -2;
} else if (n == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
free(*reply);
return -1;
}
read_bytes += n;
}
return 0;
}
static int
read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg)
{
int ret = -1;
static int read_socket(IPCMessageType *msg_type, uint32_t *msg_size,
char **msg) {
int ret = -1;
while (ret != 0) {
ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg);
while (ret != 0) {
ret = recv_message((uint8_t *) msg_type, msg_size, (uint8_t **) msg);
if (ret < 0) {
// Try again (non-fatal error)
if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue;
if (ret < 0) {
// Try again (non-fatal error)
if (ret == -1 && (errno == EINTR || errno == EAGAIN))
continue;
fprintf(stderr, "Error receiving response from socket. ");
fprintf(stderr, "The connection might have been lost.\n");
exit(2);
}
}
fprintf(stderr, "Error receiving response from socket. ");
fprintf(stderr, "The connection might have been lost.\n");
exit(2);
}
}
return 0;
return 0;
}
static ssize_t
write_socket(const void *buf, size_t count)
{
size_t written = 0;
while (written < count) {
const ssize_t n =
write(sock_fd, ((uint8_t *)buf) + written, count - written);
if (n == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
continue;
else
return n;
}
written += n;
}
return written;
static ssize_t write_socket(const void *buf, size_t count) {
size_t written = 0;
while (written < count) {
const ssize_t n =
write(sock_fd, ((uint8_t *) buf) + written, count - written);
if (n == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
continue;
else
return n;
}
written += n;
}
return written;
}
static void
connect_to_socket()
{
struct sockaddr_un addr;
static void connect_to_socket() {
struct sockaddr_un addr;
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
// Initialize struct to 0
memset(&addr, 0, sizeof(struct sockaddr_un));
// Initialize struct to 0
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, DEFAULT_SOCKET_PATH);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, DEFAULT_SOCKET_PATH);
connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un));
connect(sock, (const struct sockaddr *) &addr,
sizeof(struct sockaddr_un));
sock_fd = sock;
sock_fd = sock;
}
static int
send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg)
{
dwm_ipc_header_t header = {
.magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type};
static int send_message(IPCMessageType msg_type, uint32_t msg_size,
uint8_t *msg) {
dwm_ipc_header_t header = {.magic = IPC_MAGIC_ARR,
.size = msg_size,
.type = msg_type};
size_t header_size = sizeof(dwm_ipc_header_t);
size_t total_size = header_size + msg_size;
size_t header_size = sizeof(dwm_ipc_header_t);
size_t total_size = header_size + msg_size;
uint8_t buffer[total_size];
uint8_t buffer[total_size];
// Copy header to buffer
memcpy(buffer, &header, header_size);
// Copy message to buffer
memcpy(buffer + header_size, msg, header.size);
// Copy header to buffer
memcpy(buffer, &header, header_size);
// Copy message to buffer
memcpy(buffer + header_size, msg, header.size);
write_socket(buffer, total_size);
write_socket(buffer, total_size);
return 0;
return 0;
}
static int
is_float(const char *s)
{
size_t len = strlen(s);
int is_dot_used = 0;
int is_minus_used = 0;
// Floats can only have one decimal point in between or digits
// Optionally, floats can also be below zero (negative)
for (int i = 0; i < len; i++) {
if (isdigit(s[i]))
continue;
else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) {
is_dot_used = 1;
continue;
} else if (!is_minus_used && s[i] == '-' && i == 0) {
is_minus_used = 1;
continue;
} else
return 0;
}
return 1;
static int is_float(const char *s) {
size_t len = strlen(s);
int is_dot_used = 0;
int is_minus_used = 0;
// Floats can only have one decimal point in between or digits
// Optionally, floats can also be below zero (negative)
for (int i = 0; i < len; i++) {
if (isdigit(s[i]))
continue;
else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) {
is_dot_used = 1;
continue;
} else if (!is_minus_used && s[i] == '-' && i == 0) {
is_minus_used = 1;
continue;
} else
return 0;
}
return 1;
}
static int
is_unsigned_int(const char *s)
{
size_t len = strlen(s);
static int is_unsigned_int(const char *s) {
size_t len = strlen(s);
// Unsigned int can only have digits
for (int i = 0; i < len; i++) {
if (isdigit(s[i]))
continue;
else
return 0;
}
// Unsigned int can only have digits
for (int i = 0; i < len; i++) {
if (isdigit(s[i]))
continue;
else
return 0;
}
return 1;
return 1;
}
static int
is_signed_int(const char *s)
{
size_t len = strlen(s);
// Signed int can only have digits and a negative sign at the start
for (int i = 0; i < len; i++) {
if (isdigit(s[i]))
continue;
else if (i == 0 && s[i] == '-') {
continue;
} else
return 0;
}
return 1;
static int is_signed_int(const char *s) {
size_t len = strlen(s);
// Signed int can only have digits and a negative sign at the start
for (int i = 0; i < len; i++) {
if (isdigit(s[i]))
continue;
else if (i == 0 && s[i] == '-') {
continue;
} else
return 0;
}
return 1;
}
static void
flush_socket_reply()
{
IPCMessageType reply_type;
uint32_t reply_size;
char *reply;
static void flush_socket_reply() {
IPCMessageType reply_type;
uint32_t reply_size;
char *reply;
read_socket(&reply_type, &reply_size, &reply);
read_socket(&reply_type, &reply_size, &reply);
free(reply);
free(reply);
}
static void
print_socket_reply()
{
IPCMessageType reply_type;
uint32_t reply_size;
char *reply;
static void print_socket_reply() {
IPCMessageType reply_type;
uint32_t reply_size;
char *reply;
read_socket(&reply_type, &reply_size, &reply);
read_socket(&reply_type, &reply_size, &reply);
printf("%.*s\n", reply_size, reply);
fflush(stdout);
free(reply);
printf("%.*s\n", reply_size, reply);
fflush(stdout);
free(reply);
}
static int
run_command(const char *name, char *args[], int argc)
{
const unsigned char *msg;
size_t msg_size;
static int run_command(const char *name, char *args[], int argc) {
const unsigned char *msg;
size_t msg_size;
yajl_gen gen = yajl_gen_alloc(NULL);
yajl_gen gen = yajl_gen_alloc(NULL);
// Message format:
// {
// "command": "<name>",
// "args": [ ... ]
// }
// clang-format off
// Message format:
// {
// "command": "<name>",
// "args": [ ... ]
// }
// clang-format off
YMAP(
YSTR("command"); YSTR(name);
YSTR("args"); YARR(
@ -335,214 +327,205 @@ run_command(const char *name, char *args[], int argc)
}
)
)
// clang-format on
// clang-format on
yajl_gen_get_buf(gen, &msg, &msg_size);
yajl_gen_get_buf(gen, &msg, &msg_size);
send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *)msg);
send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *) msg);
if (!ignore_reply)
print_socket_reply();
else
flush_socket_reply();
if (!ignore_reply)
print_socket_reply();
else
flush_socket_reply();
yajl_gen_free(gen);
yajl_gen_free(gen);
return 0;
return 0;
}
static int
get_monitors()
{
send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)"");
print_socket_reply();
return 0;
static int get_monitors() {
send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *) "");
print_socket_reply();
return 0;
}
static int
get_tags()
{
send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)"");
print_socket_reply();
static int get_tags() {
send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *) "");
print_socket_reply();
return 0;
return 0;
}
static int
get_layouts()
{
send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)"");
print_socket_reply();
static int get_layouts() {
send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *) "");
print_socket_reply();
return 0;
return 0;
}
static int
get_dwm_client(Window win)
{
const unsigned char *msg;
size_t msg_size;
static int get_dwm_client(Window win) {
const unsigned char *msg;
size_t msg_size;
yajl_gen gen = yajl_gen_alloc(NULL);
yajl_gen gen = yajl_gen_alloc(NULL);
// Message format:
// {
// "client_window_id": "<win>"
// }
// clang-format off
// Message format:
// {
// "client_window_id": "<win>"
// }
// clang-format off
YMAP(
YSTR("client_window_id"); YINT(win);
)
// clang-format on
// clang-format on
yajl_gen_get_buf(gen, &msg, &msg_size);
yajl_gen_get_buf(gen, &msg, &msg_size);
send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *)msg);
send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *) msg);
print_socket_reply();
print_socket_reply();
yajl_gen_free(gen);
yajl_gen_free(gen);
return 0;
return 0;
}
static int
subscribe(const char *event)
{
const unsigned char *msg;
size_t msg_size;
static int subscribe(const char *event) {
const unsigned char *msg;
size_t msg_size;
yajl_gen gen = yajl_gen_alloc(NULL);
yajl_gen gen = yajl_gen_alloc(NULL);
// Message format:
// {
// "event": "<event>",
// "action": "subscribe"
// }
// clang-format off
// Message format:
// {
// "event": "<event>",
// "action": "subscribe"
// }
// clang-format off
YMAP(
YSTR("event"); YSTR(event);
YSTR("action"); YSTR("subscribe");
)
// clang-format on
// clang-format on
yajl_gen_get_buf(gen, &msg, &msg_size);
yajl_gen_get_buf(gen, &msg, &msg_size);
send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *)msg);
send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *) msg);
if (!ignore_reply)
print_socket_reply();
else
flush_socket_reply();
if (!ignore_reply)
print_socket_reply();
else
flush_socket_reply();
yajl_gen_free(gen);
yajl_gen_free(gen);
return 0;
return 0;
}
static void
usage_error(const char *prog_name, const char *format, ...)
{
va_list args;
va_start(args, format);
static void usage_error(const char *prog_name, const char *format, ...) {
va_list args;
va_start(args, format);
fprintf(stderr, "Error: ");
vfprintf(stderr, format, args);
fprintf(stderr, "\nusage: %s <command> [...]\n", prog_name);
fprintf(stderr, "Try '%s help'\n", prog_name);
fprintf(stderr, "Error: ");
vfprintf(stderr, format, args);
fprintf(stderr, "\nusage: %s <command> [...]\n", prog_name);
fprintf(stderr, "Try '%s help'\n", prog_name);
va_end(args);
exit(1);
va_end(args);
exit(1);
}
static void
print_usage(const char *name)
{
printf("usage: %s [options] <command> [...]\n", name);
puts("");
puts("Commands:");
puts(" run_command <name> [args...] Run an IPC command");
puts("");
puts(" get_monitors Get monitor properties");
puts("");
puts(" get_tags Get list of tags");
puts("");
puts(" get_layouts Get list of layouts");
puts("");
puts(" get_dwm_client <window_id> Get dwm client proprties");
puts("");
puts(" subscribe [events...] Subscribe to specified events");
puts(" Options: " IPC_EVENT_TAG_CHANGE ",");
puts(" " IPC_EVENT_LAYOUT_CHANGE ",");
puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ",");
puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ",");
puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ",");
puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE);
puts("");
puts(" help Display this message");
puts("");
puts("Options:");
puts(" --ignore-reply Don't print reply messages from");
puts(" run_command and subscribe.");
puts("");
static void print_usage(const char *name) {
printf("usage: %s [options] <command> [...]\n", name);
puts("");
puts("Commands:");
puts(" run_command <name> [args...] Run an IPC command");
puts("");
puts(" get_monitors Get monitor properties");
puts("");
puts(" get_tags Get list of tags");
puts("");
puts(" get_layouts Get list of layouts");
puts("");
puts(" get_dwm_client <window_id> Get dwm client proprties");
puts("");
puts(" subscribe [events...] Subscribe to specified events");
puts(" Options: " IPC_EVENT_TAG_CHANGE
",");
puts(" " IPC_EVENT_LAYOUT_CHANGE ",");
puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE
",");
puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE
",");
puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE
",");
puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE);
puts("");
puts(" help Display this message");
puts("");
puts("Options:");
puts(" --ignore-reply Don't print reply messages from");
puts(" run_command and subscribe.");
puts("");
}
int
main(int argc, char *argv[])
{
const char *prog_name = argv[0];
connect_to_socket();
if (sock_fd == -1) {
fprintf(stderr, "Failed to connect to socket\n");
return 1;
}
int i = 1;
if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) {
ignore_reply = 1;
i++;
}
if (i >= argc) usage_error(prog_name, "Expected an argument, got none");
if (strcmp(argv[i], "help") == 0)
print_usage(prog_name);
else if (strcmp(argv[i], "run_command") == 0) {
if (++i >= argc) usage_error(prog_name, "No command specified");
// Command name
char *command = argv[i];
// Command arguments are everything after command name
char **command_args = argv + ++i;
// Number of command arguments
int command_argc = argc - i;
run_command(command, command_args, command_argc);
} else if (strcmp(argv[i], "get_monitors") == 0) {
get_monitors();
} else if (strcmp(argv[i], "get_tags") == 0) {
get_tags();
} else if (strcmp(argv[i], "get_layouts") == 0) {
get_layouts();
} else if (strcmp(argv[i], "get_dwm_client") == 0) {
if (++i < argc) {
if (is_unsigned_int(argv[i])) {
Window win = atol(argv[i]);
get_dwm_client(win);
} else
usage_error(prog_name, "Expected unsigned integer argument");
} else
usage_error(prog_name, "Expected the window id");
} else if (strcmp(argv[i], "subscribe") == 0) {
if (++i < argc) {
for (int j = i; j < argc; j++) subscribe(argv[j]);
} else
usage_error(prog_name, "Expected event name");
// Keep listening for events forever
while (1) {
print_socket_reply();
}
} else
usage_error(prog_name, "Invalid argument '%s'", argv[i]);
return 0;
int main(int argc, char *argv[]) {
const char *prog_name = argv[0];
connect_to_socket();
if (sock_fd == -1) {
fprintf(stderr, "Failed to connect to socket\n");
return 1;
}
int i = 1;
if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) {
ignore_reply = 1;
i++;
}
if (i >= argc)
usage_error(prog_name, "Expected an argument, got none");
if (strcmp(argv[i], "help") == 0)
print_usage(prog_name);
else if (strcmp(argv[i], "run_command") == 0) {
if (++i >= argc)
usage_error(prog_name, "No command specified");
// Command name
char *command = argv[i];
// Command arguments are everything after command name
char **command_args = argv + ++i;
// Number of command arguments
int command_argc = argc - i;
run_command(command, command_args, command_argc);
} else if (strcmp(argv[i], "get_monitors") == 0) {
get_monitors();
} else if (strcmp(argv[i], "get_tags") == 0) {
get_tags();
} else if (strcmp(argv[i], "get_layouts") == 0) {
get_layouts();
} else if (strcmp(argv[i], "get_dwm_client") == 0) {
if (++i < argc) {
if (is_unsigned_int(argv[i])) {
Window win = atol(argv[i]);
get_dwm_client(win);
} else
usage_error(prog_name, "Expected unsigned integer argument");
} else
usage_error(prog_name, "Expected the window id");
} else if (strcmp(argv[i], "subscribe") == 0) {
if (++i < argc) {
for (int j = i; j < argc; j++)
subscribe(argv[j]);
} else
usage_error(prog_name, "Expected event name");
// Keep listening for events forever
while (1) {
print_socket_reply();
}
} else
usage_error(prog_name, "Invalid argument '%s'", argv[i]);
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -17,67 +17,67 @@
// clang-format on
typedef enum IPCMessageType {
IPC_TYPE_RUN_COMMAND = 0,
IPC_TYPE_GET_MONITORS = 1,
IPC_TYPE_GET_TAGS = 2,
IPC_TYPE_GET_LAYOUTS = 3,
IPC_TYPE_GET_DWM_CLIENT = 4,
IPC_TYPE_SUBSCRIBE = 5,
IPC_TYPE_EVENT = 6
IPC_TYPE_RUN_COMMAND = 0,
IPC_TYPE_GET_MONITORS = 1,
IPC_TYPE_GET_TAGS = 2,
IPC_TYPE_GET_LAYOUTS = 3,
IPC_TYPE_GET_DWM_CLIENT = 4,
IPC_TYPE_SUBSCRIBE = 5,
IPC_TYPE_EVENT = 6
} IPCMessageType;
typedef enum IPCEvent {
IPC_EVENT_TAG_CHANGE = 1 << 0,
IPC_EVENT_CLIENT_FOCUS_CHANGE = 1 << 1,
IPC_EVENT_LAYOUT_CHANGE = 1 << 2,
IPC_EVENT_MONITOR_FOCUS_CHANGE = 1 << 3,
IPC_EVENT_FOCUSED_TITLE_CHANGE = 1 << 4,
IPC_EVENT_FOCUSED_STATE_CHANGE = 1 << 5
IPC_EVENT_TAG_CHANGE = 1 << 0,
IPC_EVENT_CLIENT_FOCUS_CHANGE = 1 << 1,
IPC_EVENT_LAYOUT_CHANGE = 1 << 2,
IPC_EVENT_MONITOR_FOCUS_CHANGE = 1 << 3,
IPC_EVENT_FOCUSED_TITLE_CHANGE = 1 << 4,
IPC_EVENT_FOCUSED_STATE_CHANGE = 1 << 5
} IPCEvent;
typedef enum IPCSubscriptionAction {
IPC_ACTION_UNSUBSCRIBE = 0,
IPC_ACTION_SUBSCRIBE = 1
IPC_ACTION_UNSUBSCRIBE = 0,
IPC_ACTION_SUBSCRIBE = 1
} IPCSubscriptionAction;
/**
* Every IPC packet starts with this structure
*/
typedef struct dwm_ipc_header {
uint8_t magic[IPC_MAGIC_LEN];
uint32_t size;
uint8_t type;
uint8_t magic[IPC_MAGIC_LEN];
uint32_t size;
uint8_t type;
} __attribute((packed)) dwm_ipc_header_t;
typedef enum ArgType {
ARG_TYPE_NONE = 0,
ARG_TYPE_UINT = 1,
ARG_TYPE_SINT = 2,
ARG_TYPE_FLOAT = 3,
ARG_TYPE_PTR = 4,
ARG_TYPE_STR = 5
ARG_TYPE_NONE = 0,
ARG_TYPE_UINT = 1,
ARG_TYPE_SINT = 2,
ARG_TYPE_FLOAT = 3,
ARG_TYPE_PTR = 4,
ARG_TYPE_STR = 5
} ArgType;
/**
* An IPCCommand function can have either of these function signatures
*/
typedef union ArgFunction {
void (*single_param)(const Arg *);
void (*array_param)(const Arg *, int);
void (*single_param)(const Arg *);
void (*array_param)(const Arg *, int);
} ArgFunction;
typedef struct IPCCommand {
char *name;
ArgFunction func;
unsigned int argc;
ArgType *arg_types;
char *name;
ArgFunction func;
unsigned int argc;
ArgType *arg_types;
} IPCCommand;
typedef struct IPCParsedCommand {
char *name;
Arg *args;
ArgType *arg_types;
unsigned int argc;
char *name;
Arg *args;
ArgType *arg_types;
unsigned int argc;
} IPCParsedCommand;
/**
@ -88,15 +88,15 @@ typedef struct IPCParsedCommand {
* @param commands Address of IPCCommands array defined in config.h
* @param commands_len Length of commands[] array
*
* @return int The file descriptor of the socket if it was successfully created,
* -1 otherwise
* @return int The file descriptor of the socket if it was successfully
* created, -1 otherwise
*/
int ipc_init(const char *socket_path, const int p_epoll_fd,
IPCCommand commands[], const int commands_len);
/**
* Uninitialize the socket and module. Free allocated memory and restore static
* variables to their state before ipc_init
* Uninitialize the socket and module. Free allocated memory and restore
* static variables to their state before ipc_init
*/
void ipc_cleanup();
@ -150,16 +150,16 @@ int ipc_accept_client();
* @param c Address of IPCClient
* @param msg_type Address to IPCMessageType variable which will be assigned
* the message type of the received message
* @param msg_size Address to uint32_t variable which will be assigned the size
* of the received message
* @param msg_size Address to uint32_t variable which will be assigned the
* size of the received message
* @param msg Address to char* variable which will be assigned the address of
* the received message. This must be freed using free().
*
* @return 0 on success, -1 on error reading message, -2 if reading the message
* resulted in EAGAIN, EINTR, or EWOULDBLOCK.
* @return 0 on success, -1 on error reading message, -2 if reading the
* message resulted in EAGAIN, EINTR, or EWOULDBLOCK.
*/
int ipc_read_client(IPCClient *c, IPCMessageType *msg_type, uint32_t *msg_size,
char **msg);
int ipc_read_client(IPCClient *c, IPCMessageType *msg_type,
uint32_t *msg_size, char **msg);
/**
* Write any pending buffer of the client to the client's socket
@ -204,8 +204,8 @@ void ipc_prepare_reply_failure(IPCClient *c, IPCMessageType msg_type,
void ipc_prepare_reply_success(IPCClient *c, IPCMessageType msg_type);
/**
* Send a tag_change_event to all subscribers. Should be called only when there
* has been a tag state change.
* Send a tag_change_event to all subscribers. Should be called only when
* there has been a tag state change.
*
* @param mon_num The index of the monitor (Monitor.num property)
* @param old_state The old tag state
@ -259,7 +259,8 @@ void ipc_monitor_focus_change_event(const int last_mon_num,
* @param new_name New name of the client window
*/
void ipc_focused_title_change_event(const int mon_num, const Window client_id,
const char *old_name, const char *new_name);
const char *old_name,
const char *new_name);
/**
* Send a focused_state_change_event to all subscribers. Should only be called
@ -285,8 +286,8 @@ void ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon);
/**
* Handle an epoll event caused by a registered IPC client. Read, process, and
* handle any received messages from clients. Write pending buffer to client if
* the client is ready to receive messages. Drop clients that have sent an
* handle any received messages from clients. Write pending buffer to client
* if the client is ready to receive messages. Drop clients that have sent an
* EPOLLHUP.
*
* @param ev Associated epoll event returned by epoll_wait
@ -304,16 +305,18 @@ void ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon);
int ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
Monitor **lastselmon, Monitor *selmon,
const char *tags[], const int tags_len,
const Layout *layouts, const int layouts_len);
const Layout *layouts,
const int layouts_len);
/**
* Handle an epoll event caused by the IPC socket. This function only handles an
* EPOLLIN event indicating a new client requesting to connect to the socket.
* Handle an epoll event caused by the IPC socket. This function only handles
* an EPOLLIN event indicating a new client requesting to connect to the
* socket.
*
* @param ev Associated epoll event returned by epoll_wait
*
* @return 0, if the event was successfully handled, -1 if not an EPOLLIN event
* or if a new IPC client connection request could not be accepted.
* @return 0, if the event was successfully handled, -1 if not an EPOLLIN
* event or if a new IPC client connection request could not be accepted.
*/
int ipc_handle_socket_epoll_event(struct epoll_event *ev);

@ -1,9 +1,9 @@
/* cc transient.c -o transient -lX11 */
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
Display *d;
@ -16,7 +16,7 @@ int main(void) {
exit(1);
r = DefaultRootWindow(d);
f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0);
f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0);
h.min_width = h.max_width = h.min_height = h.max_height = 400;
h.flags = PMinSize | PMaxSize;
XSetWMNormalHints(d, f, &h);

@ -1,16 +1,14 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include "util.h"
void *
ecalloc(size_t nmemb, size_t size)
{
void *ecalloc(size_t nmemb, size_t size) {
void *p;
if (!(p = calloc(nmemb, size)))
@ -18,15 +16,14 @@ ecalloc(size_t nmemb, size_t size)
return p;
}
void
die(const char *fmt, ...) {
void die(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
fputc(' ', stderr);
perror(NULL);
} else {
@ -36,135 +33,127 @@ die(const char *fmt, ...) {
exit(1);
}
int
normalizepath(const char *path, char **normal)
{
size_t len = strlen(path);
*normal = (char *)malloc((len + 1) * sizeof(char));
const char *walk = path;
const char *match;
size_t newlen = 0;
while ((match = strchr(walk, '/'))) {
// Copy everything between match and walk
strncpy(*normal + newlen, walk, match - walk);
newlen += match - walk;
walk += match - walk;
// Skip all repeating slashes
while (*walk == '/')
walk++;
// If not last character in path
if (walk != path + len)
(*normal)[newlen++] = '/';
}
int normalizepath(const char *path, char **normal) {
size_t len = strlen(path);
*normal = (char *) malloc((len + 1) * sizeof(char));
const char *walk = path;
const char *match;
size_t newlen = 0;
while ((match = strchr(walk, '/'))) {
// Copy everything between match and walk
strncpy(*normal + newlen, walk, match - walk);
newlen += match - walk;
walk += match - walk;
// Skip all repeating slashes
while (*walk == '/')
walk++;
// If not last character in path
if (walk != path + len)
(*normal)[newlen++] = '/';
}
(*normal)[newlen++] = '\0';
(*normal)[newlen++] = '\0';
// Copy remaining path
strcat(*normal, walk);
newlen += strlen(walk);
// Copy remaining path
strcat(*normal, walk);
newlen += strlen(walk);
*normal = (char *)realloc(*normal, newlen * sizeof(char));
*normal = (char *) realloc(*normal, newlen * sizeof(char));
return 0;
return 0;
}
int
parentdir(const char *path, char **parent)
{
char *normal;
char *walk;
int parentdir(const char *path, char **parent) {
char *normal;
char *walk;
normalizepath(path, &normal);
normalizepath(path, &normal);
// Pointer to last '/'
if (!(walk = strrchr(normal, '/'))) {
free(normal);
return -1;
}
// Pointer to last '/'
if (!(walk = strrchr(normal, '/'))) {
free(normal);
return -1;
}
// Get path up to last '/'
size_t len = walk - normal;
*parent = (char *)malloc((len + 1) * sizeof(char));
// Get path up to last '/'
size_t len = walk - normal;
*parent = (char *) malloc((len + 1) * sizeof(char));
// Copy path up to last '/'
strncpy(*parent, normal, len);
// Add null char
(*parent)[len] = '\0';
// Copy path up to last '/'
strncpy(*parent, normal, len);
// Add null char
(*parent)[len] = '\0';
free(normal);
free(normal);
return 0;
return 0;
}
int
mkdirp(const char *path)
{
char *normal;
char *walk;
size_t normallen;
normalizepath(path, &normal);
normallen = strlen(normal);
walk = normal;
while (walk < normal + normallen + 1) {
// Get length from walk to next /
size_t n = strcspn(walk, "/");
// Skip path /
if (n == 0) {
walk++;
continue;
}
// Length of current path segment
size_t curpathlen = walk - normal + n;
char curpath[curpathlen + 1];
struct stat s;
// Copy path segment to stat
strncpy(curpath, normal, curpathlen);
strcpy(curpath + curpathlen, "");
int res = stat(curpath, &s);
if (res < 0) {
if (errno == ENOENT) {
DEBUG("Making directory %s\n", curpath);
if (mkdir(curpath, 0700) < 0) {
fprintf(stderr, "Failed to make directory %s\n", curpath);
perror("");
free(normal);
return -1;
}
} else {
fprintf(stderr, "Error statting directory %s\n", curpath);
perror("");
free(normal);
return -1;
}
}
// Continue to next path segment
walk += n;
}
free(normal);
return 0;
int mkdirp(const char *path) {
char *normal;
char *walk;
size_t normallen;
normalizepath(path, &normal);
normallen = strlen(normal);
walk = normal;
while (walk < normal + normallen + 1) {
// Get length from walk to next /
size_t n = strcspn(walk, "/");
// Skip path /
if (n == 0) {
walk++;
continue;
}
// Length of current path segment
size_t curpathlen = walk - normal + n;
char curpath[curpathlen + 1];
struct stat s;
// Copy path segment to stat
strncpy(curpath, normal, curpathlen);
strcpy(curpath + curpathlen, "");
int res = stat(curpath, &s);
if (res < 0) {
if (errno == ENOENT) {
DEBUG("Making directory %s\n", curpath);
if (mkdir(curpath, 0700) < 0) {
fprintf(stderr, "Failed to make directory %s\n", curpath);
perror("");
free(normal);
return -1;
}
} else {
fprintf(stderr, "Error statting directory %s\n", curpath);
perror("");
free(normal);
return -1;
}
}
// Continue to next path segment
walk += n;
}
free(normal);
return 0;
}
int
nullterminate(char **str, size_t *len)
{
if ((*str)[*len - 1] == '\0')
return 0;
int nullterminate(char **str, size_t *len) {
if ((*str)[*len - 1] == '\0')
return 0;
(*len)++;
*str = (char*)realloc(*str, *len * sizeof(char));
(*str)[*len - 1] = '\0';
(*len)++;
*str = (char *) realloc(*str, *len * sizeof(char));
(*str)[*len - 1] = '\0';
return 0;
return 0;
}

@ -1,8 +1,8 @@
/* See LICENSE file for copyright and license details. */
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
#ifdef _DEBUG
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)

@ -2,36 +2,30 @@
#include <stdint.h>
int
dump_tag(yajl_gen gen, const char *name, const int tag_mask)
{
// clang-format off
int dump_tag(yajl_gen gen, const char *name, const int tag_mask) {
// clang-format off
YMAP(
YSTR("bit_mask"); YINT(tag_mask);
YSTR("name"); YSTR(name);
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_tags(yajl_gen gen, const char *tags[], int tags_len)
{
// clang-format off
int dump_tags(yajl_gen gen, const char *tags[], int tags_len) {
// clang-format off
YARR(
for (int i = 0; i < tags_len; i++)
dump_tag(gen, tags[i], 1 << i);
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_client(yajl_gen gen, Client *c)
{
// clang-format off
int dump_client(yajl_gen gen, Client *c) {
// clang-format off
YMAP(
YSTR("name"); YSTR(c->name);
YSTR("tags"); YINT(c->tags);
@ -90,15 +84,13 @@ dump_client(yajl_gen gen, Client *c)
YSTR("is_fullscreen"); YBOOL(c->isfullscreen);
)
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_monitor(yajl_gen gen, Monitor *mon, int is_selected)
{
// clang-format off
int dump_monitor(yajl_gen gen, Monitor *mon, int is_selected) {
// clang-format off
YMAP(
YSTR("master_factor"); YDOUBLE(mon->mfact);
YSTR("num_master"); YINT(mon->nmaster);
@ -156,15 +148,13 @@ dump_monitor(yajl_gen gen, Monitor *mon, int is_selected)
YSTR("window_id"); YINT(mon->barwin);
)
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon)
{
// clang-format off
int dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon) {
// clang-format off
YARR(
for (Monitor *mon = mons; mon; mon = mon->next) {
if (mon == selmon)
@ -173,15 +163,14 @@ dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon)
dump_monitor(gen, mon, 0);
}
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len)
{
// clang-format off
int dump_layouts(yajl_gen gen, const Layout layouts[],
const int layouts_len) {
// clang-format off
YARR(
for (int i = 0; i < layouts_len; i++) {
YMAP(
@ -192,30 +181,26 @@ dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len)
)
}
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_tag_state(yajl_gen gen, TagState state)
{
// clang-format off
int dump_tag_state(yajl_gen gen, TagState state) {
// clang-format off
YMAP(
YSTR("selected"); YINT(state.selected);
YSTR("occupied"); YINT(state.occupied);
YSTR("urgent"); YINT(state.urgent);
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
TagState new_state)
{
// clang-format off
int dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
TagState new_state) {
// clang-format off
YMAP(
YSTR("tag_change_event"); YMAP(
YSTR("monitor_number"); YINT(mon_num);
@ -223,16 +208,14 @@ dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
YSTR("new_state"); dump_tag_state(gen, new_state);
)
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_client_focus_change_event(yajl_gen gen, Client *old_client,
Client *new_client, int mon_num)
{
// clang-format off
int dump_client_focus_change_event(yajl_gen gen, Client *old_client,
Client *new_client, int mon_num) {
// clang-format off
YMAP(
YSTR("client_focus_change_event"); YMAP(
YSTR("monitor_number"); YINT(mon_num);
@ -240,17 +223,16 @@ dump_client_focus_change_event(yajl_gen gen, Client *old_client,
YSTR("new_win_id"); new_client == NULL ? YNULL() : YINT(new_client->win);
)
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_layout_change_event(yajl_gen gen, const int mon_num,
const char *old_symbol, const Layout *old_layout,
const char *new_symbol, const Layout *new_layout)
{
// clang-format off
int dump_layout_change_event(yajl_gen gen, const int mon_num,
const char *old_symbol, const Layout *old_layout,
const char *new_symbol,
const Layout *new_layout) {
// clang-format off
YMAP(
YSTR("layout_change_event"); YMAP(
YSTR("monitor_number"); YINT(mon_num);
@ -260,33 +242,30 @@ dump_layout_change_event(yajl_gen gen, const int mon_num,
YSTR("new_address"); YINT((uintptr_t)new_layout);
)
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
const int new_mon_num)
{
// clang-format off
int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
const int new_mon_num) {
// clang-format off
YMAP(
YSTR("monitor_focus_change_event"); YMAP(
YSTR("old_monitor_number"); YINT(last_mon_num);
YSTR("new_monitor_number"); YINT(new_mon_num);
)
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_focused_title_change_event(yajl_gen gen, const int mon_num,
const Window client_id, const char *old_name,
const char *new_name)
{
// clang-format off
int dump_focused_title_change_event(yajl_gen gen, const int mon_num,
const Window client_id,
const char *old_name,
const char *new_name) {
// clang-format off
YMAP(
YSTR("focused_title_change_event"); YMAP(
YSTR("monitor_number"); YINT(mon_num);
@ -295,15 +274,13 @@ dump_focused_title_change_event(yajl_gen gen, const int mon_num,
YSTR("new_name"); YSTR(new_name);
)
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_client_state(yajl_gen gen, const ClientState *state)
{
// clang-format off
int dump_client_state(yajl_gen gen, const ClientState *state) {
// clang-format off
YMAP(
YSTR("old_state"); YBOOL(state->oldstate);
YSTR("is_fixed"); YBOOL(state->isfixed);
@ -312,18 +289,16 @@ dump_client_state(yajl_gen gen, const ClientState *state)
YSTR("is_urgent"); YBOOL(state->isurgent);
YSTR("never_focus"); YBOOL(state->neverfocus);
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_focused_state_change_event(yajl_gen gen, const int mon_num,
const Window client_id,
const ClientState *old_state,
const ClientState *new_state)
{
// clang-format off
int dump_focused_state_change_event(yajl_gen gen, const int mon_num,
const Window client_id,
const ClientState *old_state,
const ClientState *new_state) {
// clang-format off
YMAP(
YSTR("focused_state_change_event"); YMAP(
YSTR("monitor_number"); YINT(mon_num);
@ -332,20 +307,18 @@ dump_focused_state_change_event(yajl_gen gen, const int mon_num,
YSTR("new_state"); dump_client_state(gen, new_state);
)
)
// clang-format on
// clang-format on
return 0;
return 0;
}
int
dump_error_message(yajl_gen gen, const char *reason)
{
// clang-format off
int dump_error_message(yajl_gen gen, const char *reason) {
// clang-format off
YMAP(
YSTR("result"); YSTR("error");
YSTR("reason"); YSTR(reason);
)
// clang-format on
// clang-format on
return 0;
return 0;
}

@ -4,23 +4,23 @@
#include <string.h>
#include <yajl/yajl_gen.h>
#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
#define YINT(num) yajl_gen_integer(gen, num)
#define YSTR(str) yajl_gen_string(gen, (unsigned char *) str, strlen(str))
#define YINT(num) yajl_gen_integer(gen, num)
#define YDOUBLE(num) yajl_gen_double(gen, num)
#define YBOOL(v) yajl_gen_bool(gen, v)
#define YNULL() yajl_gen_null(gen)
#define YARR(body) \
{ \
yajl_gen_array_open(gen); \
body; \
yajl_gen_array_close(gen); \
}
#define YMAP(body) \
{ \
yajl_gen_map_open(gen); \
body; \
yajl_gen_map_close(gen); \
}
#define YBOOL(v) yajl_gen_bool(gen, v)
#define YNULL() yajl_gen_null(gen)
#define YARR(body) \
{ \
yajl_gen_array_open(gen); \
body; \
yajl_gen_array_close(gen); \
}
#define YMAP(body) \
{ \
yajl_gen_map_open(gen); \
body; \
yajl_gen_map_close(gen); \
}
int dump_tag(yajl_gen gen, const char *name, const int tag_mask);
@ -44,14 +44,16 @@ int dump_client_focus_change_event(yajl_gen gen, Client *old_client,
int dump_layout_change_event(yajl_gen gen, const int mon_num,
const char *old_symbol, const Layout *old_layout,
const char *new_symbol, const Layout *new_layout);
const char *new_symbol,
const Layout *new_layout);
int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
const int new_mon_num);
int dump_focused_title_change_event(yajl_gen gen, const int mon_num,
const Window client_id,
const char *old_name, const char *new_name);
const char *old_name,
const char *new_name);
int dump_client_state(yajl_gen gen, const ClientState *state);
@ -62,4 +64,4 @@ int dump_focused_state_change_event(yajl_gen gen, const int mon_num,
int dump_error_message(yajl_gen gen, const char *reason);
#endif // YAJL_DUMPS_H_
#endif // YAJL_DUMPS_H_

Loading…
Cancel
Save