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

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

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

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

@ -27,15 +27,17 @@ typedef struct {
} Drw; } Drw;
/* Drawable abstraction */ /* 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_resize(Drw *drw, unsigned int w, unsigned int h);
void drw_free(Drw *drw); void drw_free(Drw *drw);
/* Fnt abstraction */ /* Fnt abstraction */
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); Fnt *drw_fontset_create(Drw *drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt* set); void drw_fontset_free(Fnt *set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text); 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 */ /* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); 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); void drw_setscheme(Drw *drw, Clr *scm);
/* Drawing functions */ /* Drawing functions */
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 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); 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 */ /* 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 // clang-format off
#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' } #define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' }
// clang-format on // 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_TAG_CHANGE "tag_change_event"
#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event" #define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event"
#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event" #define IPC_EVENT_LAYOUT_CHANGE "layout_change_event"
#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_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_TITLE_CHANGE "focused_title_change_event"
#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_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 YSTR(str) yajl_gen_string(gen, (unsigned char *) str, strlen(str))
#define YINT(num) yajl_gen_integer(gen, num) #define YINT(num) yajl_gen_integer(gen, num)
#define YDOUBLE(num) yajl_gen_double(gen, num) #define YDOUBLE(num) yajl_gen_double(gen, num)
#define YBOOL(v) yajl_gen_bool(gen, v) #define YBOOL(v) yajl_gen_bool(gen, v)
#define YNULL() yajl_gen_null(gen) #define YNULL() yajl_gen_null(gen)
#define YARR(body) \ #define YARR(body) \
{ \ { \
yajl_gen_array_open(gen); \ yajl_gen_array_open(gen); \
body; \ body; \
yajl_gen_array_close(gen); \ yajl_gen_array_close(gen); \
} }
#define YMAP(body) \ #define YMAP(body) \
{ \ { \
yajl_gen_map_open(gen); \ yajl_gen_map_open(gen); \
body; \ body; \
yajl_gen_map_close(gen); \ yajl_gen_map_close(gen); \
} }
typedef unsigned long Window; typedef unsigned long Window;
const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock"; const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock";
static int sock_fd = -1; static int sock_fd = -1;
static unsigned int ignore_reply = 0; static unsigned int ignore_reply = 0;
typedef enum IPCMessageType { typedef enum IPCMessageType {
IPC_TYPE_RUN_COMMAND = 0, IPC_TYPE_RUN_COMMAND = 0,
IPC_TYPE_GET_MONITORS = 1, IPC_TYPE_GET_MONITORS = 1,
IPC_TYPE_GET_TAGS = 2, IPC_TYPE_GET_TAGS = 2,
IPC_TYPE_GET_LAYOUTS = 3, IPC_TYPE_GET_LAYOUTS = 3,
IPC_TYPE_GET_DWM_CLIENT = 4, IPC_TYPE_GET_DWM_CLIENT = 4,
IPC_TYPE_SUBSCRIBE = 5, IPC_TYPE_SUBSCRIBE = 5,
IPC_TYPE_EVENT = 6 IPC_TYPE_EVENT = 6
} IPCMessageType; } IPCMessageType;
// Every IPC message must begin with this // Every IPC message must begin with this
typedef struct dwm_ipc_header { typedef struct dwm_ipc_header {
uint8_t magic[IPC_MAGIC_LEN]; uint8_t magic[IPC_MAGIC_LEN];
uint32_t size; uint32_t size;
uint8_t type; uint8_t type;
} __attribute((packed)) dwm_ipc_header_t; } __attribute((packed)) dwm_ipc_header_t;
static int static int recv_message(uint8_t *msg_type, uint32_t *reply_size,
recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply) uint8_t **reply) {
{ uint32_t read_bytes = 0;
uint32_t read_bytes = 0; const int32_t to_read = sizeof(dwm_ipc_header_t);
const int32_t to_read = sizeof(dwm_ipc_header_t); char header[to_read];
char header[to_read]; char *walk = header;
char *walk = header;
// Try to read header
// Try to read header while (read_bytes < to_read) {
while (read_bytes < to_read) { ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes);
ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes);
if (n == 0) {
if (n == 0) { if (read_bytes == 0) {
if (read_bytes == 0) { fprintf(stderr,
fprintf(stderr, "Unexpectedly reached EOF while reading header."); "Unexpectedly reached EOF while reading header.");
fprintf(stderr, fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", "Read %" PRIu32 " bytes, expected %" PRIu32
read_bytes, to_read); " total bytes.\n",
return -2; read_bytes, to_read);
} else { return -2;
fprintf(stderr, "Unexpectedly reached EOF while reading header."); } else {
fprintf(stderr, fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", "Unexpectedly reached EOF while reading header.");
read_bytes, to_read); fprintf(stderr,
return -3; "Read %" PRIu32 " bytes, expected %" PRIu32
} " total bytes.\n",
} else if (n == -1) { read_bytes, to_read);
return -1; return -3;
} }
} else if (n == -1) {
read_bytes += n; return -1;
} }
// Check if magic string in header matches read_bytes += n;
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); // Check if magic string in header matches
return -3; 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);
walk += IPC_MAGIC_LEN; return -3;
}
// Extract reply size
memcpy(reply_size, walk, sizeof(uint32_t)); walk += IPC_MAGIC_LEN;
walk += sizeof(uint32_t);
// Extract reply size
// Extract message type memcpy(reply_size, walk, sizeof(uint32_t));
memcpy(msg_type, walk, sizeof(uint8_t)); walk += sizeof(uint32_t);
walk += sizeof(uint8_t);
// Extract message type
(*reply) = malloc(*reply_size); memcpy(msg_type, walk, sizeof(uint8_t));
walk += sizeof(uint8_t);
// Extract payload
read_bytes = 0; (*reply) = malloc(*reply_size);
while (read_bytes < *reply_size) {
ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes); // Extract payload
read_bytes = 0;
if (n == 0) { while (read_bytes < *reply_size) {
fprintf(stderr, "Unexpectedly reached EOF while reading payload."); ssize_t n =
fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n", read(sock_fd, *reply + read_bytes, *reply_size - read_bytes);
read_bytes, *reply_size);
free(*reply); if (n == 0) {
return -2; fprintf(stderr,
} else if (n == -1) { "Unexpectedly reached EOF while reading payload.");
if (errno == EINTR || errno == EAGAIN) continue; fprintf(stderr,
free(*reply); "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n",
return -1; read_bytes, *reply_size);
} free(*reply);
return -2;
read_bytes += n; } else if (n == -1) {
} if (errno == EINTR || errno == EAGAIN)
continue;
return 0; free(*reply);
return -1;
}
read_bytes += n;
}
return 0;
} }
static int static int read_socket(IPCMessageType *msg_type, uint32_t *msg_size,
read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg) char **msg) {
{ int ret = -1;
int ret = -1;
while (ret != 0) { while (ret != 0) {
ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg); ret = recv_message((uint8_t *) msg_type, msg_size, (uint8_t **) msg);
if (ret < 0) { if (ret < 0) {
// Try again (non-fatal error) // Try again (non-fatal error)
if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue; if (ret == -1 && (errno == EINTR || errno == EAGAIN))
continue;
fprintf(stderr, "Error receiving response from socket. "); fprintf(stderr, "Error receiving response from socket. ");
fprintf(stderr, "The connection might have been lost.\n"); fprintf(stderr, "The connection might have been lost.\n");
exit(2); exit(2);
} }
} }
return 0; return 0;
} }
static ssize_t static ssize_t write_socket(const void *buf, size_t count) {
write_socket(const void *buf, size_t count) size_t written = 0;
{
size_t written = 0; while (written < count) {
const ssize_t n =
while (written < count) { write(sock_fd, ((uint8_t *) buf) + written, count - written);
const ssize_t n =
write(sock_fd, ((uint8_t *)buf) + written, count - written); if (n == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
if (n == -1) { continue;
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) else
continue; return n;
else }
return n; written += n;
} }
written += n; return written;
}
return written;
} }
static void static void connect_to_socket() {
connect_to_socket() struct sockaddr_un addr;
{
struct sockaddr_un addr;
int sock = socket(AF_UNIX, SOCK_STREAM, 0); int sock = socket(AF_UNIX, SOCK_STREAM, 0);
// Initialize struct to 0 // Initialize struct to 0
memset(&addr, 0, sizeof(struct sockaddr_un)); memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX; addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, DEFAULT_SOCKET_PATH); 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 static int send_message(IPCMessageType msg_type, uint32_t msg_size,
send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg) uint8_t *msg) {
{ dwm_ipc_header_t header = {.magic = IPC_MAGIC_ARR,
dwm_ipc_header_t header = { .size = msg_size,
.magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type}; .type = msg_type};
size_t header_size = sizeof(dwm_ipc_header_t); size_t header_size = sizeof(dwm_ipc_header_t);
size_t total_size = header_size + msg_size; size_t total_size = header_size + msg_size;
uint8_t buffer[total_size]; uint8_t buffer[total_size];
// Copy header to buffer // Copy header to buffer
memcpy(buffer, &header, header_size); memcpy(buffer, &header, header_size);
// Copy message to buffer // Copy message to buffer
memcpy(buffer + header_size, msg, header.size); memcpy(buffer + header_size, msg, header.size);
write_socket(buffer, total_size); write_socket(buffer, total_size);
return 0; return 0;
} }
static int static int is_float(const char *s) {
is_float(const char *s) size_t len = strlen(s);
{ int is_dot_used = 0;
size_t len = strlen(s); int is_minus_used = 0;
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)
// Floats can only have one decimal point in between or digits for (int i = 0; i < len; i++) {
// Optionally, floats can also be below zero (negative) if (isdigit(s[i]))
for (int i = 0; i < len; i++) { continue;
if (isdigit(s[i])) else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) {
continue; is_dot_used = 1;
else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) { continue;
is_dot_used = 1; } else if (!is_minus_used && s[i] == '-' && i == 0) {
continue; is_minus_used = 1;
} else if (!is_minus_used && s[i] == '-' && i == 0) { continue;
is_minus_used = 1; } else
continue; return 0;
} else }
return 0;
} return 1;
return 1;
} }
static int static int is_unsigned_int(const char *s) {
is_unsigned_int(const char *s) size_t len = strlen(s);
{
size_t len = strlen(s);
// Unsigned int can only have digits // Unsigned int can only have digits
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if (isdigit(s[i])) if (isdigit(s[i]))
continue; continue;
else else
return 0; return 0;
} }
return 1; return 1;
} }
static int static int is_signed_int(const char *s) {
is_signed_int(const char *s) size_t len = strlen(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++) {
// Signed int can only have digits and a negative sign at the start if (isdigit(s[i]))
for (int i = 0; i < len; i++) { continue;
if (isdigit(s[i])) else if (i == 0 && s[i] == '-') {
continue; continue;
else if (i == 0 && s[i] == '-') { } else
continue; return 0;
} else }
return 0;
} return 1;
return 1;
} }
static void static void flush_socket_reply() {
flush_socket_reply() IPCMessageType reply_type;
{ uint32_t reply_size;
IPCMessageType reply_type; char *reply;
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 static void print_socket_reply() {
print_socket_reply() IPCMessageType reply_type;
{ uint32_t reply_size;
IPCMessageType reply_type; char *reply;
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); printf("%.*s\n", reply_size, reply);
fflush(stdout); fflush(stdout);
free(reply); free(reply);
} }
static int static int run_command(const char *name, char *args[], int argc) {
run_command(const char *name, char *args[], int argc) const unsigned char *msg;
{ size_t msg_size;
const unsigned char *msg;
size_t msg_size;
yajl_gen gen = yajl_gen_alloc(NULL); yajl_gen gen = yajl_gen_alloc(NULL);
// Message format: // Message format:
// { // {
// "command": "<name>", // "command": "<name>",
// "args": [ ... ] // "args": [ ... ]
// } // }
// clang-format off // clang-format off
YMAP( YMAP(
YSTR("command"); YSTR(name); YSTR("command"); YSTR(name);
YSTR("args"); YARR( 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) if (!ignore_reply)
print_socket_reply(); print_socket_reply();
else else
flush_socket_reply(); flush_socket_reply();
yajl_gen_free(gen); yajl_gen_free(gen);
return 0; return 0;
} }
static int static int get_monitors() {
get_monitors() send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *) "");
{ print_socket_reply();
send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)""); return 0;
print_socket_reply();
return 0;
} }
static int static int get_tags() {
get_tags() send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *) "");
{ print_socket_reply();
send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)"");
print_socket_reply();
return 0; return 0;
} }
static int static int get_layouts() {
get_layouts() send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *) "");
{ print_socket_reply();
send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)"");
print_socket_reply();
return 0; return 0;
} }
static int static int get_dwm_client(Window win) {
get_dwm_client(Window win) const unsigned char *msg;
{ size_t msg_size;
const unsigned char *msg;
size_t msg_size;
yajl_gen gen = yajl_gen_alloc(NULL); yajl_gen gen = yajl_gen_alloc(NULL);
// Message format: // Message format:
// { // {
// "client_window_id": "<win>" // "client_window_id": "<win>"
// } // }
// clang-format off // clang-format off
YMAP( YMAP(
YSTR("client_window_id"); YINT(win); 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 static int subscribe(const char *event) {
subscribe(const char *event) const unsigned char *msg;
{ size_t msg_size;
const unsigned char *msg;
size_t msg_size;
yajl_gen gen = yajl_gen_alloc(NULL); yajl_gen gen = yajl_gen_alloc(NULL);
// Message format: // Message format:
// { // {
// "event": "<event>", // "event": "<event>",
// "action": "subscribe" // "action": "subscribe"
// } // }
// clang-format off // clang-format off
YMAP( YMAP(
YSTR("event"); YSTR(event); YSTR("event"); YSTR(event);
YSTR("action"); YSTR("subscribe"); 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) if (!ignore_reply)
print_socket_reply(); print_socket_reply();
else else
flush_socket_reply(); flush_socket_reply();
yajl_gen_free(gen); yajl_gen_free(gen);
return 0; return 0;
} }
static void static void usage_error(const char *prog_name, const char *format, ...) {
usage_error(const char *prog_name, const char *format, ...) va_list args;
{ va_start(args, format);
va_list args;
va_start(args, format);
fprintf(stderr, "Error: "); fprintf(stderr, "Error: ");
vfprintf(stderr, format, args); vfprintf(stderr, format, args);
fprintf(stderr, "\nusage: %s <command> [...]\n", prog_name); fprintf(stderr, "\nusage: %s <command> [...]\n", prog_name);
fprintf(stderr, "Try '%s help'\n", prog_name); fprintf(stderr, "Try '%s help'\n", prog_name);
va_end(args); va_end(args);
exit(1); exit(1);
} }
static void static void print_usage(const char *name) {
print_usage(const char *name) printf("usage: %s [options] <command> [...]\n", name);
{ puts("");
printf("usage: %s [options] <command> [...]\n", name); puts("Commands:");
puts(""); puts(" run_command <name> [args...] Run an IPC command");
puts("Commands:"); puts("");
puts(" run_command <name> [args...] Run an IPC command"); puts(" get_monitors Get monitor properties");
puts(""); puts("");
puts(" get_monitors Get monitor properties"); puts(" get_tags Get list of tags");
puts(""); puts("");
puts(" get_tags Get list of tags"); puts(" get_layouts Get list of layouts");
puts(""); puts("");
puts(" get_layouts Get list of layouts"); puts(" get_dwm_client <window_id> Get dwm client proprties");
puts(""); puts("");
puts(" get_dwm_client <window_id> Get dwm client proprties"); puts(" subscribe [events...] Subscribe to specified events");
puts(""); puts(" Options: " IPC_EVENT_TAG_CHANGE
puts(" subscribe [events...] Subscribe to specified events"); ",");
puts(" Options: " IPC_EVENT_TAG_CHANGE ","); puts(" " IPC_EVENT_LAYOUT_CHANGE ",");
puts(" " IPC_EVENT_LAYOUT_CHANGE ","); puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE
puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ","); ",");
puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ","); puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE
puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ","); ",");
puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE); puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE
puts(""); ",");
puts(" help Display this message"); puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE);
puts(""); puts("");
puts("Options:"); puts(" help Display this message");
puts(" --ignore-reply Don't print reply messages from"); puts("");
puts(" run_command and subscribe."); puts("Options:");
puts(""); puts(" --ignore-reply Don't print reply messages from");
puts(" run_command and subscribe.");
puts("");
} }
int int main(int argc, char *argv[]) {
main(int argc, char *argv[]) const char *prog_name = argv[0];
{
const char *prog_name = argv[0]; connect_to_socket();
if (sock_fd == -1) {
connect_to_socket(); fprintf(stderr, "Failed to connect to socket\n");
if (sock_fd == -1) { return 1;
fprintf(stderr, "Failed to connect to socket\n"); }
return 1;
} int i = 1;
if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) {
int i = 1; ignore_reply = 1;
if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) { i++;
ignore_reply = 1; }
i++;
} if (i >= argc)
usage_error(prog_name, "Expected an argument, got none");
if (i >= argc) usage_error(prog_name, "Expected an argument, got none");
if (strcmp(argv[i], "help") == 0)
if (strcmp(argv[i], "help") == 0) print_usage(prog_name);
print_usage(prog_name); else if (strcmp(argv[i], "run_command") == 0) {
else if (strcmp(argv[i], "run_command") == 0) { if (++i >= argc)
if (++i >= argc) usage_error(prog_name, "No command specified"); usage_error(prog_name, "No command specified");
// Command name // Command name
char *command = argv[i]; char *command = argv[i];
// Command arguments are everything after command name // Command arguments are everything after command name
char **command_args = argv + ++i; char **command_args = argv + ++i;
// Number of command arguments // Number of command arguments
int command_argc = argc - i; int command_argc = argc - i;
run_command(command, command_args, command_argc); run_command(command, command_args, command_argc);
} else if (strcmp(argv[i], "get_monitors") == 0) { } else if (strcmp(argv[i], "get_monitors") == 0) {
get_monitors(); get_monitors();
} else if (strcmp(argv[i], "get_tags") == 0) { } else if (strcmp(argv[i], "get_tags") == 0) {
get_tags(); get_tags();
} else if (strcmp(argv[i], "get_layouts") == 0) { } else if (strcmp(argv[i], "get_layouts") == 0) {
get_layouts(); get_layouts();
} else if (strcmp(argv[i], "get_dwm_client") == 0) { } else if (strcmp(argv[i], "get_dwm_client") == 0) {
if (++i < argc) { if (++i < argc) {
if (is_unsigned_int(argv[i])) { if (is_unsigned_int(argv[i])) {
Window win = atol(argv[i]); Window win = atol(argv[i]);
get_dwm_client(win); get_dwm_client(win);
} else } else
usage_error(prog_name, "Expected unsigned integer argument"); usage_error(prog_name, "Expected unsigned integer argument");
} else } else
usage_error(prog_name, "Expected the window id"); usage_error(prog_name, "Expected the window id");
} else if (strcmp(argv[i], "subscribe") == 0) { } else if (strcmp(argv[i], "subscribe") == 0) {
if (++i < argc) { if (++i < argc) {
for (int j = i; j < argc; j++) subscribe(argv[j]); for (int j = i; j < argc; j++)
} else subscribe(argv[j]);
usage_error(prog_name, "Expected event name"); } else
// Keep listening for events forever usage_error(prog_name, "Expected event name");
while (1) { // Keep listening for events forever
print_socket_reply(); while (1) {
} print_socket_reply();
} else }
usage_error(prog_name, "Invalid argument '%s'", argv[i]); } else
usage_error(prog_name, "Invalid argument '%s'", argv[i]);
return 0;
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 // clang-format on
typedef enum IPCMessageType { typedef enum IPCMessageType {
IPC_TYPE_RUN_COMMAND = 0, IPC_TYPE_RUN_COMMAND = 0,
IPC_TYPE_GET_MONITORS = 1, IPC_TYPE_GET_MONITORS = 1,
IPC_TYPE_GET_TAGS = 2, IPC_TYPE_GET_TAGS = 2,
IPC_TYPE_GET_LAYOUTS = 3, IPC_TYPE_GET_LAYOUTS = 3,
IPC_TYPE_GET_DWM_CLIENT = 4, IPC_TYPE_GET_DWM_CLIENT = 4,
IPC_TYPE_SUBSCRIBE = 5, IPC_TYPE_SUBSCRIBE = 5,
IPC_TYPE_EVENT = 6 IPC_TYPE_EVENT = 6
} IPCMessageType; } IPCMessageType;
typedef enum IPCEvent { typedef enum IPCEvent {
IPC_EVENT_TAG_CHANGE = 1 << 0, IPC_EVENT_TAG_CHANGE = 1 << 0,
IPC_EVENT_CLIENT_FOCUS_CHANGE = 1 << 1, IPC_EVENT_CLIENT_FOCUS_CHANGE = 1 << 1,
IPC_EVENT_LAYOUT_CHANGE = 1 << 2, IPC_EVENT_LAYOUT_CHANGE = 1 << 2,
IPC_EVENT_MONITOR_FOCUS_CHANGE = 1 << 3, IPC_EVENT_MONITOR_FOCUS_CHANGE = 1 << 3,
IPC_EVENT_FOCUSED_TITLE_CHANGE = 1 << 4, IPC_EVENT_FOCUSED_TITLE_CHANGE = 1 << 4,
IPC_EVENT_FOCUSED_STATE_CHANGE = 1 << 5 IPC_EVENT_FOCUSED_STATE_CHANGE = 1 << 5
} IPCEvent; } IPCEvent;
typedef enum IPCSubscriptionAction { typedef enum IPCSubscriptionAction {
IPC_ACTION_UNSUBSCRIBE = 0, IPC_ACTION_UNSUBSCRIBE = 0,
IPC_ACTION_SUBSCRIBE = 1 IPC_ACTION_SUBSCRIBE = 1
} IPCSubscriptionAction; } IPCSubscriptionAction;
/** /**
* Every IPC packet starts with this structure * Every IPC packet starts with this structure
*/ */
typedef struct dwm_ipc_header { typedef struct dwm_ipc_header {
uint8_t magic[IPC_MAGIC_LEN]; uint8_t magic[IPC_MAGIC_LEN];
uint32_t size; uint32_t size;
uint8_t type; uint8_t type;
} __attribute((packed)) dwm_ipc_header_t; } __attribute((packed)) dwm_ipc_header_t;
typedef enum ArgType { typedef enum ArgType {
ARG_TYPE_NONE = 0, ARG_TYPE_NONE = 0,
ARG_TYPE_UINT = 1, ARG_TYPE_UINT = 1,
ARG_TYPE_SINT = 2, ARG_TYPE_SINT = 2,
ARG_TYPE_FLOAT = 3, ARG_TYPE_FLOAT = 3,
ARG_TYPE_PTR = 4, ARG_TYPE_PTR = 4,
ARG_TYPE_STR = 5 ARG_TYPE_STR = 5
} ArgType; } ArgType;
/** /**
* An IPCCommand function can have either of these function signatures * An IPCCommand function can have either of these function signatures
*/ */
typedef union ArgFunction { typedef union ArgFunction {
void (*single_param)(const Arg *); void (*single_param)(const Arg *);
void (*array_param)(const Arg *, int); void (*array_param)(const Arg *, int);
} ArgFunction; } ArgFunction;
typedef struct IPCCommand { typedef struct IPCCommand {
char *name; char *name;
ArgFunction func; ArgFunction func;
unsigned int argc; unsigned int argc;
ArgType *arg_types; ArgType *arg_types;
} IPCCommand; } IPCCommand;
typedef struct IPCParsedCommand { typedef struct IPCParsedCommand {
char *name; char *name;
Arg *args; Arg *args;
ArgType *arg_types; ArgType *arg_types;
unsigned int argc; unsigned int argc;
} IPCParsedCommand; } IPCParsedCommand;
/** /**
@ -88,15 +88,15 @@ typedef struct IPCParsedCommand {
* @param commands Address of IPCCommands array defined in config.h * @param commands Address of IPCCommands array defined in config.h
* @param commands_len Length of commands[] array * @param commands_len Length of commands[] array
* *
* @return int The file descriptor of the socket if it was successfully created, * @return int The file descriptor of the socket if it was successfully
* -1 otherwise * created, -1 otherwise
*/ */
int ipc_init(const char *socket_path, const int p_epoll_fd, int ipc_init(const char *socket_path, const int p_epoll_fd,
IPCCommand commands[], const int commands_len); IPCCommand commands[], const int commands_len);
/** /**
* Uninitialize the socket and module. Free allocated memory and restore static * Uninitialize the socket and module. Free allocated memory and restore
* variables to their state before ipc_init * static variables to their state before ipc_init
*/ */
void ipc_cleanup(); void ipc_cleanup();
@ -150,16 +150,16 @@ int ipc_accept_client();
* @param c Address of IPCClient * @param c Address of IPCClient
* @param msg_type Address to IPCMessageType variable which will be assigned * @param msg_type Address to IPCMessageType variable which will be assigned
* the message type of the received message * the message type of the received message
* @param msg_size Address to uint32_t variable which will be assigned the size * @param msg_size Address to uint32_t variable which will be assigned the
* of the received message * size of the received message
* @param msg Address to char* variable which will be assigned the address of * @param msg Address to char* variable which will be assigned the address of
* the received message. This must be freed using free(). * the received message. This must be freed using free().
* *
* @return 0 on success, -1 on error reading message, -2 if reading the message * @return 0 on success, -1 on error reading message, -2 if reading the
* resulted in EAGAIN, EINTR, or EWOULDBLOCK. * message resulted in EAGAIN, EINTR, or EWOULDBLOCK.
*/ */
int ipc_read_client(IPCClient *c, IPCMessageType *msg_type, uint32_t *msg_size, int ipc_read_client(IPCClient *c, IPCMessageType *msg_type,
char **msg); uint32_t *msg_size, char **msg);
/** /**
* Write any pending buffer of the client to the client's socket * 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); void ipc_prepare_reply_success(IPCClient *c, IPCMessageType msg_type);
/** /**
* Send a tag_change_event to all subscribers. Should be called only when there * Send a tag_change_event to all subscribers. Should be called only when
* has been a tag state change. * there has been a tag state change.
* *
* @param mon_num The index of the monitor (Monitor.num property) * @param mon_num The index of the monitor (Monitor.num property)
* @param old_state The old tag state * @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 * @param new_name New name of the client window
*/ */
void ipc_focused_title_change_event(const int mon_num, const Window client_id, 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 * 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 an epoll event caused by a registered IPC client. Read, process, and
* handle any received messages from clients. Write pending buffer to client if * handle any received messages from clients. Write pending buffer to client
* the client is ready to receive messages. Drop clients that have sent an * if the client is ready to receive messages. Drop clients that have sent an
* EPOLLHUP. * EPOLLHUP.
* *
* @param ev Associated epoll event returned by epoll_wait * @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, int ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
Monitor **lastselmon, Monitor *selmon, Monitor **lastselmon, Monitor *selmon,
const char *tags[], const int tags_len, 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 * Handle an epoll event caused by the IPC socket. This function only handles
* EPOLLIN event indicating a new client requesting to connect to the socket. * an EPOLLIN event indicating a new client requesting to connect to the
* socket.
* *
* @param ev Associated epoll event returned by epoll_wait * @param ev Associated epoll event returned by epoll_wait
* *
* @return 0, if the event was successfully handled, -1 if not an EPOLLIN event * @return 0, if the event was successfully handled, -1 if not an EPOLLIN
* or if a new IPC client connection request could not be accepted. * event or if a new IPC client connection request could not be accepted.
*/ */
int ipc_handle_socket_epoll_event(struct epoll_event *ev); int ipc_handle_socket_epoll_event(struct epoll_event *ev);

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

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

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

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

@ -4,23 +4,23 @@
#include <string.h> #include <string.h>
#include <yajl/yajl_gen.h> #include <yajl/yajl_gen.h>
#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) #define YSTR(str) yajl_gen_string(gen, (unsigned char *) str, strlen(str))
#define YINT(num) yajl_gen_integer(gen, num) #define YINT(num) yajl_gen_integer(gen, num)
#define YDOUBLE(num) yajl_gen_double(gen, num) #define YDOUBLE(num) yajl_gen_double(gen, num)
#define YBOOL(v) yajl_gen_bool(gen, v) #define YBOOL(v) yajl_gen_bool(gen, v)
#define YNULL() yajl_gen_null(gen) #define YNULL() yajl_gen_null(gen)
#define YARR(body) \ #define YARR(body) \
{ \ { \
yajl_gen_array_open(gen); \ yajl_gen_array_open(gen); \
body; \ body; \
yajl_gen_array_close(gen); \ yajl_gen_array_close(gen); \
} }
#define YMAP(body) \ #define YMAP(body) \
{ \ { \
yajl_gen_map_open(gen); \ yajl_gen_map_open(gen); \
body; \ body; \
yajl_gen_map_close(gen); \ yajl_gen_map_close(gen); \
} }
int dump_tag(yajl_gen gen, const char *name, const int tag_mask); 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, int dump_layout_change_event(yajl_gen gen, const int mon_num,
const char *old_symbol, const Layout *old_layout, 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, int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
const int new_mon_num); const int new_mon_num);
int dump_focused_title_change_event(yajl_gen gen, const int mon_num, int dump_focused_title_change_event(yajl_gen gen, const int mon_num,
const Window client_id, 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); 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); int dump_error_message(yajl_gen gen, const char *reason);
#endif // YAJL_DUMPS_H_ #endif // YAJL_DUMPS_H_

Loading…
Cancel
Save