Compare commits

..

4 Commits

  1. 1
      .gitignore
  2. 24
      src/.clang-format
  3. 12
      src/.editorconfig
  4. 31
      src/IPCClient.c
  5. 51
      src/config.def.h
  6. 96
      src/config.h
  7. 147
      src/drw.c
  8. 15
      src/drw.h
  9. 135
      src/dwm-msg.c
  10. 927
      src/dwm.c
  11. 361
      src/ipc.c
  12. 43
      src/ipc.h
  13. 4
      src/transient.c
  14. 25
      src/util.c
  15. 77
      src/yajl_dumps.c
  16. 6
      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,12 +5,11 @@
#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));
@ -26,9 +25,7 @@ ipc_client_new(int fd)
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) { if (*list == NULL) {
@ -44,22 +41,22 @@ ipc_list_add_client(IPCClientList *list, IPCClient *nc)
} }
} }
void void ipc_list_remove_client(IPCClientList *list, IPCClient *c) {
ipc_list_remove_client(IPCClientList *list, IPCClient *c)
{
IPCClient *cprev = c->prev; IPCClient *cprev = c->prev;
IPCClient *cnext = c->next; 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) { for (IPCClient *c = list; c; c = c->next) {
if (c->fd == fd) return c; if (c->fd == fd)
return c;
} }
return NULL; return NULL;

@ -9,7 +9,8 @@ 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 =
"$HOME/bar.sh"; /* Alternate bar launch command */
static const char *fonts[] = {"monospace:size=10"}; static const char *fonts[] = {"monospace:size=10"};
static const char dmenufont[] = "monospace:size=10"; static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#222222"; static const char col_gray1[] = "#222222";
@ -31,7 +32,8 @@ static const Rule rules[] = {
* 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}, {"Gimp", NULL, NULL, 0, 1, -1},
{"Firefox", NULL, NULL, 1 << 8, 0, -1}, {"Firefox", NULL, NULL, 1 << 8, 0, -1},
}; };
@ -39,7 +41,8 @@ static const Rule rules[] = {
/* 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 */
@ -54,16 +57,27 @@ static const Layout layouts[] = {
{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 *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 const char *termcmd[] = {"st", NULL};
static Key keys[] = { static Key keys[] = {
@ -111,22 +125,17 @@ static Key keys[] = {
{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, Button1, setlayout, {0}},
{ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}}, {ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}},
{ClkWinTitle, 0, Button2, zoom, {0}}, {ClkWinTitle, 0, Button2, zoom, {0}},
@ -157,6 +166,4 @@ static IPCCommand ipccommands[] = {
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,24 +2,27 @@
#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"; /*
// Alternate bar launch command */
static const char *altbarcmd = "";
static const char *fonts[] = {"Fira Code:size=11"}; static const char *fonts[] = {"Fira Code:size=11"};
static const char dmenufont[] = "Fira Code:size=15"; 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";
@ -45,7 +48,9 @@ static const Rule rules[] = {
* 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}, {"Gimp", NULL, NULL, 0, 1, -1},
{"Firefox", NULL, NULL, 1 << 8, 0, -1}, {"Firefox", NULL, NULL, 1 << 8, 0, -1},
{"discord", NULL, NULL, 0, 0, -1}, {"discord", NULL, NULL, 0, 0, -1},
@ -56,7 +61,8 @@ static const Rule rules[] = {
/* 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 */
@ -71,27 +77,47 @@ static const Layout layouts[] = {
{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 *dmenucmd[] = {"dmenu_run", "-m", dmenumon, "-p",
"Run $", "-z", "512", NULL};
static const char *termcmd[] = {"alacritty", NULL}; static const char *termcmd[] = {"alacritty", NULL};
static const char *browsercmd[] = {"firefox", NULL}; static const char *browsercmd[] = {"firefox", NULL};
static const char *betterlockscreencmd[] = { "betterlockscreen", "--lock", "blur", NULL }; static const char *betterlockscreencmd[] = {"betterlockscreen", "--lock",
"blur", NULL};
static const char *screenshotcmd[] = {"flameshot", "gui", NULL}; static const char *screenshotcmd[] = {"flameshot", "gui", NULL};
static const char *cmuspausecmd[] = {"cmus-remote", "--pause", 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,
SHCMD("amixer -q set Master 5%+ unmute; pkill -RTMIN+1 dwmblocks")},
{MODKEY, XF86XK_AudioMute, spawn,
SHCMD("amixer -q set Master toggle; pkill -RTMIN+1 dwmblocks")},
{MODKEY | ShiftMask, XF86XK_AudioMute, spawn,
SHCMD("amixer set Capture toggle")},
//{ MODKEY, XK_d, spawn, {.v
//= dmenucmd
//}
//},
{MODKEY, XK_d, spawn, SHCMD("rofi -show drun")}, {MODKEY, XK_d, spawn, SHCMD("rofi -show drun")},
{MODKEY, XK_s, spawn, SHCMD("rofi -show ssh")}, {MODKEY, XK_s, spawn, SHCMD("rofi -show ssh")},
{MODKEY, XK_w, spawn, SHCMD("rofi -show window")}, {MODKEY, XK_w, spawn, SHCMD("rofi -show window")},
@ -127,7 +153,9 @@ static Key keys[] = {
{MODKEY, XK_f, setlayout, {.v = &layouts[1]}}, {MODKEY, XK_f, setlayout, {.v = &layouts[1]}},
{MODKEY, XK_t, setlayout, {.v = &layouts[0]}}, {MODKEY, XK_t, setlayout, {.v = &layouts[0]}},
{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}},
@ -136,7 +164,7 @@ static Key keys[] = {
{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|ShiftMask, XK_x, spawn, {.v = betterlockscreencmd} }, {MODKEY | ShiftMask, XK_l, spawn, {.v = betterlockscreencmd}},
{MODKEY, XK_Print, spawn, {.v = screenshotcmd}}, {MODKEY, XK_Print, spawn, {.v = screenshotcmd}},
{MODKEY, XK_u, spawn, {.v = cmuspausecmd}}, {MODKEY, XK_u, spawn, {.v = cmuspausecmd}},
{MODKEY, XK_g, switchgaps, {.i = +1}}, {MODKEY, XK_g, switchgaps, {.i = +1}},
@ -144,22 +172,18 @@ static Key keys[] = {
{MODKEY, XK_minus, setgaps, {.i = -1}}, {MODKEY, XK_minus, setgaps, {.i = -1}},
{MODKEY, XK_plus, setgaps, {.i = +1}}, {MODKEY, XK_plus, 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_e, 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_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
* function argument
*/
{ClkStatusText, 0, Button1, sigstatusbar, {.i = 1}}, {ClkStatusText, 0, Button1, sigstatusbar, {.i = 1}},
{ClkStatusText, 0, Button2, sigstatusbar, {.i = 2}}, {ClkStatusText, 0, Button2, sigstatusbar, {.i = 2}},
{ClkStatusText, 0, Button3, sigstatusbar, {.i = 3}}, {ClkStatusText, 0, Button3, sigstatusbar, {.i = 3}},
@ -178,7 +202,6 @@ static Button buttons[] = {
{ClkTagBar, MODKEY, Button3, toggletag, {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}),
@ -194,5 +217,4 @@ static IPCCommand ipccommands[] = {
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"
@ -12,22 +12,20 @@
#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,
0xF8};
static const long utfmin[UTF_SIZ + 1] = {0, 0, 0x80, 0x800, 0x10000}; static const long utfmin[UTF_SIZ + 1] = {0, 0, 0x80, 0x800, 0x10000};
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; static const 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,9 +56,8 @@ 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;
@ -77,9 +72,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
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,9 +94,8 @@ 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;
@ -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,7 +135,8 @@ 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;
} }
@ -155,9 +150,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
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;
@ -184,24 +175,20 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
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),
@ -291,7 +274,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
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;
@ -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,17 +381,14 @@ 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)
@ -414,9 +401,7 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w,
*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,7 +27,8 @@ 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);
@ -35,7 +36,8 @@ void drw_free(Drw *drw);
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);

@ -65,9 +65,8 @@ typedef struct dwm_ipc_header {
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];
@ -79,15 +78,19 @@ recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply)
if (n == 0) { if (n == 0) {
if (read_bytes == 0) { if (read_bytes == 0) {
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
fprintf(stderr, fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", "Unexpectedly reached EOF while reading header.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32
" total bytes.\n",
read_bytes, to_read); read_bytes, to_read);
return -2; return -2;
} else { } else {
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
fprintf(stderr, fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", "Unexpectedly reached EOF while reading header.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32
" total bytes.\n",
read_bytes, to_read); read_bytes, to_read);
return -3; return -3;
} }
@ -120,16 +123,20 @@ recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply)
// Extract payload // Extract payload
read_bytes = 0; read_bytes = 0;
while (read_bytes < *reply_size) { while (read_bytes < *reply_size) {
ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes); ssize_t n =
read(sock_fd, *reply + read_bytes, *reply_size - read_bytes);
if (n == 0) { if (n == 0) {
fprintf(stderr, "Unexpectedly reached EOF while reading payload."); fprintf(stderr,
fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n", "Unexpectedly reached EOF while reading payload.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n",
read_bytes, *reply_size); read_bytes, *reply_size);
free(*reply); free(*reply);
return -2; return -2;
} else if (n == -1) { } else if (n == -1) {
if (errno == EINTR || errno == EAGAIN) continue; if (errno == EINTR || errno == EAGAIN)
continue;
free(*reply); free(*reply);
return -1; return -1;
} }
@ -140,9 +147,8 @@ recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply)
return 0; 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) {
@ -150,7 +156,8 @@ read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **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");
@ -161,9 +168,7 @@ read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg)
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) { while (written < count) {
@ -181,9 +186,7 @@ write_socket(const void *buf, size_t count)
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);
@ -194,16 +197,17 @@ connect_to_socket()
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;
@ -220,9 +224,7 @@ send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg)
return 0; return 0;
} }
static int static int is_float(const char *s) {
is_float(const char *s)
{
size_t len = strlen(s); size_t len = strlen(s);
int is_dot_used = 0; int is_dot_used = 0;
int is_minus_used = 0; int is_minus_used = 0;
@ -245,9 +247,7 @@ is_float(const char *s)
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
@ -261,9 +261,7 @@ is_unsigned_int(const char *s)
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 // Signed int can only have digits and a negative sign at the start
@ -279,9 +277,7 @@ is_signed_int(const char *s)
return 1; return 1;
} }
static void static void flush_socket_reply() {
flush_socket_reply()
{
IPCMessageType reply_type; IPCMessageType reply_type;
uint32_t reply_size; uint32_t reply_size;
char *reply; char *reply;
@ -291,9 +287,7 @@ flush_socket_reply()
free(reply); free(reply);
} }
static void static void print_socket_reply() {
print_socket_reply()
{
IPCMessageType reply_type; IPCMessageType reply_type;
uint32_t reply_size; uint32_t reply_size;
char *reply; char *reply;
@ -305,9 +299,7 @@ print_socket_reply()
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; const unsigned char *msg;
size_t msg_size; size_t msg_size;
@ -351,35 +343,27 @@ run_command(const char *name, char *args[], int argc)
return 0; return 0;
} }
static int static int get_monitors() {
get_monitors()
{
send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *) ""); send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *) "");
print_socket_reply(); print_socket_reply();
return 0; return 0;
} }
static int static int get_tags() {
get_tags()
{
send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *) ""); send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *) "");
print_socket_reply(); print_socket_reply();
return 0; return 0;
} }
static int static int get_layouts() {
get_layouts()
{
send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *) ""); send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *) "");
print_socket_reply(); 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; const unsigned char *msg;
size_t msg_size; size_t msg_size;
@ -406,9 +390,7 @@ get_dwm_client(Window win)
return 0; return 0;
} }
static int static int subscribe(const char *event) {
subscribe(const char *event)
{
const unsigned char *msg; const unsigned char *msg;
size_t msg_size; size_t msg_size;
@ -440,9 +422,7 @@ subscribe(const char *event)
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_list args;
va_start(args, format); va_start(args, format);
@ -455,9 +435,7 @@ usage_error(const char *prog_name, const char *format, ...)
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); printf("usage: %s [options] <command> [...]\n", name);
puts(""); puts("");
puts("Commands:"); puts("Commands:");
@ -472,11 +450,15 @@ print_usage(const char *name)
puts(" get_dwm_client <window_id> Get dwm client proprties"); puts(" get_dwm_client <window_id> Get dwm client proprties");
puts(""); puts("");
puts(" subscribe [events...] Subscribe to specified events"); puts(" subscribe [events...] Subscribe to specified events");
puts(" Options: " IPC_EVENT_TAG_CHANGE ","); 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_FOCUSED_TITLE_CHANGE ","); puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE
",");
puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE
",");
puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE); puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE);
puts(""); puts("");
puts(" help Display this message"); puts(" help Display this message");
@ -487,9 +469,7 @@ print_usage(const char *name)
puts(""); 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(); connect_to_socket();
@ -504,12 +484,14 @@ main(int argc, char *argv[])
i++; 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) usage_error(prog_name, "No command specified"); if (++i >= argc)
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
@ -534,7 +516,8 @@ main(int argc, char *argv[])
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++)
subscribe(argv[j]);
} else } else
usage_error(prog_name, "Expected event name"); usage_error(prog_name, "Expected event name");
// Keep listening for events forever // Keep listening for events forever

File diff suppressed because it is too large Load Diff

@ -31,9 +31,7 @@ static const int IPC_SOCKET_BACKLOG = 5;
* Create IPC socket at specified path and return file descriptor to socket. * Create IPC socket at specified path and return file descriptor to socket.
* This initializes the static variable sockaddr. * This initializes the static variable sockaddr.
*/ */
static int static int ipc_create_socket(const char *filename) {
ipc_create_socket(const char *filename)
{
char *normal_filename; char *normal_filename;
char *parent; char *parent;
const size_t addr_size = sizeof(struct sockaddr_un); const size_t addr_size = sizeof(struct sockaddr_un);
@ -44,8 +42,8 @@ ipc_create_socket(const char *filename)
// In case socket file exists // In case socket file exists
unlink(normal_filename); unlink(normal_filename);
// For portability clear the addr structure, since some implementations have // For portability clear the addr structure, since some implementations
// nonstandard fields in the structure // have nonstandard fields in the structure
memset(&sockaddr, 0, addr_size); memset(&sockaddr, 0, addr_size);
parentdir(normal_filename, &parent); parentdir(normal_filename, &parent);
@ -83,17 +81,16 @@ ipc_create_socket(const char *filename)
} }
/** /**
* Internal function used to receive IPC messages from a given file descriptor. * Internal function used to receive IPC messages from a given file
* descriptor.
* *
* Returns -1 on error reading (could be EAGAIN or EINTR) * Returns -1 on error reading (could be EAGAIN or EINTR)
* Returns -2 if EOF before header could be read * Returns -2 if EOF before header could be read
* Returns -3 if invalid IPC header * Returns -3 if invalid IPC header
* Returns -4 if message length exceeds MAX_MESSAGE_SIZE * Returns -4 if message length exceeds MAX_MESSAGE_SIZE
*/ */
static int static int ipc_recv_message(int fd, uint8_t *msg_type, uint32_t *reply_size,
ipc_recv_message(int fd, 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];
@ -105,15 +102,19 @@ ipc_recv_message(int fd, uint8_t *msg_type, uint32_t *reply_size,
if (n == 0) { if (n == 0) {
if (read_bytes == 0) { if (read_bytes == 0) {
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
fprintf(stderr, fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", "Unexpectedly reached EOF while reading header.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32
" total bytes.\n",
read_bytes, to_read); read_bytes, to_read);
return -2; return -2;
} else { } else {
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
fprintf(stderr, fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", "Unexpectedly reached EOF while reading header.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32
" total bytes.\n",
read_bytes, to_read); read_bytes, to_read);
return -3; return -3;
} }
@ -155,18 +156,22 @@ ipc_recv_message(int fd, uint8_t *msg_type, uint32_t *reply_size,
read_bytes = 0; read_bytes = 0;
while (read_bytes < *reply_size) { while (read_bytes < *reply_size) {
const ssize_t n = read(fd, *reply + read_bytes, *reply_size - read_bytes); const ssize_t n =
read(fd, *reply + read_bytes, *reply_size - read_bytes);
if (n == 0) { if (n == 0) {
fprintf(stderr, "Unexpectedly reached EOF while reading payload."); fprintf(stderr,
fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n", "Unexpectedly reached EOF while reading payload.");
fprintf(stderr,
"Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n",
read_bytes, *reply_size); read_bytes, *reply_size);
free(*reply); free(*reply);
return -2; return -2;
} else if (n == -1) { } else if (n == -1) {
// TODO: Should we return and wait for another epoll event? // TODO: Should we return and wait for another epoll event?
// This would require saving the partial read in some way. // This would require saving the partial read in some way.
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) continue; if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
continue;
free(*reply); free(*reply);
return -1; return -1;
@ -186,13 +191,12 @@ ipc_recv_message(int fd, uint8_t *msg_type, uint32_t *reply_size,
* Returns -1 on unknown error trying to write, errno will carry over from * Returns -1 on unknown error trying to write, errno will carry over from
* write() call * write() call
*/ */
static ssize_t static ssize_t ipc_write_message(int fd, const void *buf, size_t count) {
ipc_write_message(int fd, const void *buf, size_t count)
{
size_t written = 0; size_t written = 0;
while (written < count) { while (written < count) {
const ssize_t n = write(fd, (uint8_t *)buf + written, count - written); const ssize_t n =
write(fd, (uint8_t *) buf + written, count - written);
if (n == -1) { if (n == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) if (errno == EAGAIN || errno == EWOULDBLOCK)
@ -215,20 +219,16 @@ ipc_write_message(int fd, const void *buf, size_t count)
* handle, set yajl options, and in the future any other initialization that * handle, set yajl options, and in the future any other initialization that
* should occur for event messages. * should occur for event messages.
*/ */
static void static void ipc_event_init_message(yajl_gen *gen) {
ipc_event_init_message(yajl_gen *gen)
{
*gen = yajl_gen_alloc(NULL); *gen = yajl_gen_alloc(NULL);
yajl_gen_config(*gen, yajl_gen_beautify, 1); yajl_gen_config(*gen, yajl_gen_beautify, 1);
} }
/** /**
* Prepares buffers of IPC subscribers of specified event using buffer from yajl * Prepares buffers of IPC subscribers of specified event using buffer from
* handle. * yajl handle.
*/ */
static void static void ipc_event_prepare_send_message(yajl_gen gen, IPCEvent event) {
ipc_event_prepare_send_message(yajl_gen gen, IPCEvent event)
{
const unsigned char *buffer; const unsigned char *buffer;
size_t len = 0; size_t len = 0;
@ -251,21 +251,17 @@ ipc_event_prepare_send_message(yajl_gen gen, IPCEvent event)
* handle, set yajl options, and in the future any other initialization that * handle, set yajl options, and in the future any other initialization that
* should occur for reply messages. * should occur for reply messages.
*/ */
static void static void ipc_reply_init_message(yajl_gen *gen) {
ipc_reply_init_message(yajl_gen *gen)
{
*gen = yajl_gen_alloc(NULL); *gen = yajl_gen_alloc(NULL);
yajl_gen_config(*gen, yajl_gen_beautify, 1); yajl_gen_config(*gen, yajl_gen_beautify, 1);
} }
/** /**
* Prepares the IPC client's buffer with a message using the buffer of the yajl * Prepares the IPC client's buffer with a message using the buffer of the
* handle. * yajl handle.
*/ */
static void static void ipc_reply_prepare_send_message(yajl_gen gen, IPCClient *c,
ipc_reply_prepare_send_message(yajl_gen gen, IPCClient *c, IPCMessageType msg_type) {
IPCMessageType msg_type)
{
const unsigned char *buffer; const unsigned char *buffer;
size_t len = 0; size_t len = 0;
@ -284,9 +280,7 @@ ipc_reply_prepare_send_message(yajl_gen gen, IPCClient *c,
* Returns 0 if a command with the specified name was found * Returns 0 if a command with the specified name was found
* Returns -1 if a command with the specified name could not be found * Returns -1 if a command with the specified name could not be found
*/ */
static int static int ipc_get_ipc_command(const char *name, IPCCommand *ipc_command) {
ipc_get_ipc_command(const char *name, IPCCommand *ipc_command)
{
for (int i = 0; i < ipc_commands_len; i++) { for (int i = 0; i < ipc_commands_len; i++) {
if (strcmp(ipc_commands[i].name, name) == 0) { if (strcmp(ipc_commands[i].name, name) == 0) {
*ipc_command = ipc_commands[i]; *ipc_command = ipc_commands[i];
@ -307,9 +301,8 @@ ipc_get_ipc_command(const char *name, IPCCommand *ipc_command)
* Returns 0 if the message was successfully parsed * Returns 0 if the message was successfully parsed
* Returns -1 otherwise * Returns -1 otherwise
*/ */
static int static int ipc_parse_run_command(char *msg,
ipc_parse_run_command(char *msg, IPCParsedCommand *parsed_command) IPCParsedCommand *parsed_command) {
{
char error_buffer[1000]; char error_buffer[1000];
yajl_val parent = yajl_tree_parse(msg, error_buffer, 1000); yajl_val parent = yajl_tree_parse(msg, error_buffer, 1000);
@ -336,7 +329,8 @@ ipc_parse_run_command(char *msg, IPCParsedCommand *parsed_command)
const char *command_name = YAJL_GET_STRING(command_val); const char *command_name = YAJL_GET_STRING(command_val);
size_t command_name_len = strlen(command_name); size_t command_name_len = strlen(command_name);
parsed_command->name = (char *)malloc((command_name_len + 1) * sizeof(char)); parsed_command->name =
(char *) malloc((command_name_len + 1) * sizeof(char));
strcpy(parsed_command->name, command_name); strcpy(parsed_command->name, command_name);
DEBUG("Received command: %s\n", parsed_command->name); DEBUG("Received command: %s\n", parsed_command->name);
@ -409,11 +403,10 @@ ipc_parse_run_command(char *msg, IPCParsedCommand *parsed_command)
/** /**
* Free the members of a IPCParsedCommand struct * Free the members of a IPCParsedCommand struct
*/ */
static void static void ipc_free_parsed_command_members(IPCParsedCommand *command) {
ipc_free_parsed_command_members(IPCParsedCommand *command)
{
for (int i = 0; i < command->argc; i++) { for (int i = 0; i < command->argc; i++) {
if (command->arg_types[i] == ARG_TYPE_STR) free((void *)command->args[i].v); if (command->arg_types[i] == ARG_TYPE_STR)
free((void *) command->args[i].v);
} }
free(command->args); free(command->args);
free(command->arg_types); free(command->arg_types);
@ -428,10 +421,10 @@ ipc_free_parsed_command_members(IPCParsedCommand *command)
* Returns -1 if the argument count doesn't match * Returns -1 if the argument count doesn't match
* Returns -2 if the argument types don't match * Returns -2 if the argument types don't match
*/ */
static int static int ipc_validate_run_command(IPCParsedCommand *parsed,
ipc_validate_run_command(IPCParsedCommand *parsed, const IPCCommand actual) const IPCCommand actual) {
{ if (actual.argc != parsed->argc)
if (actual.argc != parsed->argc) return -1; return -1;
for (int i = 0; i < parsed->argc; i++) { for (int i = 0; i < parsed->argc; i++) {
ArgType ptype = parsed->arg_types[i]; ArgType ptype = parsed->arg_types[i];
@ -458,9 +451,7 @@ ipc_validate_run_command(IPCParsedCommand *parsed, const IPCCommand actual)
* Returns 0 if a valid event name was given * Returns 0 if a valid event name was given
* Returns -1 otherwise * Returns -1 otherwise
*/ */
static int static int ipc_event_stoi(const char *subscription, IPCEvent *event) {
ipc_event_stoi(const char *subscription, IPCEvent *event)
{
if (strcmp(subscription, "tag_change_event") == 0) if (strcmp(subscription, "tag_change_event") == 0)
*event = IPC_EVENT_TAG_CHANGE; *event = IPC_EVENT_TAG_CHANGE;
else if (strcmp(subscription, "client_focus_change_event") == 0) else if (strcmp(subscription, "client_focus_change_event") == 0)
@ -479,16 +470,15 @@ ipc_event_stoi(const char *subscription, IPCEvent *event)
} }
/** /**
* Parse a IPC_TYPE_SUBSCRIBE message from a client. This function extracts the * Parse a IPC_TYPE_SUBSCRIBE message from a client. This function extracts
* event name and the subscription action from the message. * the event name and the subscription action from the message.
* *
* Returns 0 if message was successfully parsed * Returns 0 if message was successfully parsed
* Returns -1 otherwise * Returns -1 otherwise
*/ */
static int static int ipc_parse_subscribe(const char *msg,
ipc_parse_subscribe(const char *msg, IPCSubscriptionAction *subscribe, IPCSubscriptionAction *subscribe,
IPCEvent *event) IPCEvent *event) {
{
char error_buffer[100]; char error_buffer[100];
yajl_val parent = yajl_tree_parse((char *) msg, error_buffer, 100); yajl_val parent = yajl_tree_parse((char *) msg, error_buffer, 100);
@ -514,7 +504,8 @@ ipc_parse_subscribe(const char *msg, IPCSubscriptionAction *subscribe,
const char *event_str = YAJL_GET_STRING(event_val); const char *event_str = YAJL_GET_STRING(event_val);
DEBUG("Received event: %s\n", event_str); DEBUG("Received event: %s\n", event_str);
if (ipc_event_stoi(event_str, event) < 0) return -1; if (ipc_event_stoi(event_str, event) < 0)
return -1;
const char *action_path[] = {"action", 0}; const char *action_path[] = {"action", 0};
yajl_val action_val = yajl_tree_get(parent, action_path, yajl_t_string); yajl_val action_val = yajl_tree_get(parent, action_path, yajl_t_string);
@ -547,9 +538,7 @@ ipc_parse_subscribe(const char *msg, IPCSubscriptionAction *subscribe,
* Returns 0 if message was successfully parsed * Returns 0 if message was successfully parsed
* Returns -1 otherwise * Returns -1 otherwise
*/ */
static int static int ipc_parse_get_dwm_client(const char *msg, Window *win) {
ipc_parse_get_dwm_client(const char *msg, Window *win)
{
char error_buffer[100]; char error_buffer[100];
yajl_val parent = yajl_tree_parse(msg, error_buffer, 100); yajl_val parent = yajl_tree_parse(msg, error_buffer, 100);
@ -581,20 +570,19 @@ ipc_parse_get_dwm_client(const char *msg, Window *win)
/** /**
* Called when an IPC_TYPE_RUN_COMMAND message is received from a client. This * Called when an IPC_TYPE_RUN_COMMAND message is received from a client. This
* function parses, executes the given command, and prepares a reply message to * function parses, executes the given command, and prepares a reply message
* the client indicating success/failure. * to the client indicating success/failure.
* *
* NOTE: There is currently no check for argument validity beyond the number of * NOTE: There is currently no check for argument validity beyond the number
* arguments given and types of arguments. There is also no way to check if the * of arguments given and types of arguments. There is also no way to check if
* function succeeded based on dwm's void(const Arg*) function types. Pointer * the function succeeded based on dwm's void(const Arg*) function types.
* arguments can cause crashes if they are not validated in the function itself. * Pointer arguments can cause crashes if they are not validated in the
* function itself.
* *
* Returns 0 if message was successfully parsed * Returns 0 if message was successfully parsed
* Returns -1 on failure parsing message * Returns -1 on failure parsing message
*/ */
static int static int ipc_run_command(IPCClient *ipc_client, char *msg) {
ipc_run_command(IPCClient *ipc_client, char *msg)
{
IPCParsedCommand parsed_command; IPCParsedCommand parsed_command;
IPCCommand ipc_command; IPCCommand ipc_command;
@ -609,7 +597,8 @@ ipc_run_command(IPCClient *ipc_client, char *msg)
if (ipc_get_ipc_command(parsed_command.name, &ipc_command) < 0) { if (ipc_get_ipc_command(parsed_command.name, &ipc_command) < 0) {
ipc_prepare_reply_failure(ipc_client, IPC_TYPE_RUN_COMMAND, ipc_prepare_reply_failure(ipc_client, IPC_TYPE_RUN_COMMAND,
"Command %s not found", parsed_command.name); "Command %s not found",
parsed_command.name);
ipc_free_parsed_command_members(&parsed_command); ipc_free_parsed_command_members(&parsed_command);
return -1; return -1;
} }
@ -630,7 +619,8 @@ ipc_run_command(IPCClient *ipc_client, char *msg)
if (parsed_command.argc == 1) if (parsed_command.argc == 1)
ipc_command.func.single_param(parsed_command.args); ipc_command.func.single_param(parsed_command.args);
else if (parsed_command.argc > 1) else if (parsed_command.argc > 1)
ipc_command.func.array_param(parsed_command.args, parsed_command.argc); ipc_command.func.array_param(parsed_command.args,
parsed_command.argc);
DEBUG("Called function for command %s\n", parsed_command.name); DEBUG("Called function for command %s\n", parsed_command.name);
@ -644,9 +634,7 @@ ipc_run_command(IPCClient *ipc_client, char *msg)
* Called when an IPC_TYPE_GET_MONITORS message is received from a client. It * Called when an IPC_TYPE_GET_MONITORS message is received from a client. It
* prepares a reply with the properties of all of the monitors in JSON. * prepares a reply with the properties of all of the monitors in JSON.
*/ */
static void static void ipc_get_monitors(IPCClient *c, Monitor *mons, Monitor *selmon) {
ipc_get_monitors(IPCClient *c, Monitor *mons, Monitor *selmon)
{
yajl_gen gen; yajl_gen gen;
ipc_reply_init_message(&gen); ipc_reply_init_message(&gen);
dump_monitors(gen, mons, selmon); dump_monitors(gen, mons, selmon);
@ -658,9 +646,8 @@ ipc_get_monitors(IPCClient *c, Monitor *mons, Monitor *selmon)
* Called when an IPC_TYPE_GET_TAGS message is received from a client. It * Called when an IPC_TYPE_GET_TAGS message is received from a client. It
* prepares a reply with info about all the tags in JSON. * prepares a reply with info about all the tags in JSON.
*/ */
static void static void ipc_get_tags(IPCClient *c, const char *tags[],
ipc_get_tags(IPCClient *c, const char *tags[], const int tags_len) const int tags_len) {
{
yajl_gen gen; yajl_gen gen;
ipc_reply_init_message(&gen); ipc_reply_init_message(&gen);
@ -673,9 +660,8 @@ ipc_get_tags(IPCClient *c, const char *tags[], const int tags_len)
* Called when an IPC_TYPE_GET_LAYOUTS message is received from a client. It * Called when an IPC_TYPE_GET_LAYOUTS message is received from a client. It
* prepares a reply with a JSON array of available layouts * prepares a reply with a JSON array of available layouts
*/ */
static void static void ipc_get_layouts(IPCClient *c, const Layout layouts[],
ipc_get_layouts(IPCClient *c, const Layout layouts[], const int layouts_len) const int layouts_len) {
{
yajl_gen gen; yajl_gen gen;
ipc_reply_init_message(&gen); ipc_reply_init_message(&gen);
@ -685,20 +671,20 @@ ipc_get_layouts(IPCClient *c, const Layout layouts[], const int layouts_len)
} }
/** /**
* Called when an IPC_TYPE_GET_DWM_CLIENT message is received from a client. It * Called when an IPC_TYPE_GET_DWM_CLIENT message is received from a client.
* prepares a JSON reply with the properties of the client with the specified * It prepares a JSON reply with the properties of the client with the
* window XID. * specified window XID.
* *
* Returns 0 if the message was successfully parsed and if the client with the * Returns 0 if the message was successfully parsed and if the client with the
* specified window XID was found * specified window XID was found
* Returns -1 if the message could not be parsed * Returns -1 if the message could not be parsed
*/ */
static int static int ipc_get_dwm_client(IPCClient *ipc_client, const char *msg,
ipc_get_dwm_client(IPCClient *ipc_client, const char *msg, const Monitor *mons) const Monitor *mons) {
{
Window win; Window win;
if (ipc_parse_get_dwm_client(msg, &win) < 0) return -1; if (ipc_parse_get_dwm_client(msg, &win) < 0)
return -1;
// Find client with specified window XID // Find client with specified window XID
for (const Monitor *m = mons; m; m = m->next) for (const Monitor *m = mons; m; m = m->next)
@ -722,20 +708,19 @@ ipc_get_dwm_client(IPCClient *ipc_client, const char *msg, const Monitor *mons)
/** /**
* Called when an IPC_TYPE_SUBSCRIBE message is received from a client. It * Called when an IPC_TYPE_SUBSCRIBE message is received from a client. It
* subscribes/unsubscribes the client from the specified event and replies with * subscribes/unsubscribes the client from the specified event and replies
* the result. * with the result.
* *
* Returns 0 if the message was successfully parsed. * Returns 0 if the message was successfully parsed.
* Returns -1 if the message could not be parsed * Returns -1 if the message could not be parsed
*/ */
static int static int ipc_subscribe(IPCClient *c, const char *msg) {
ipc_subscribe(IPCClient *c, const char *msg)
{
IPCSubscriptionAction action = IPC_ACTION_SUBSCRIBE; IPCSubscriptionAction action = IPC_ACTION_SUBSCRIBE;
IPCEvent event = 0; IPCEvent event = 0;
if (ipc_parse_subscribe(msg, &action, &event)) { if (ipc_parse_subscribe(msg, &action, &event)) {
ipc_prepare_reply_failure(c, IPC_TYPE_SUBSCRIBE, "Event does not exist"); ipc_prepare_reply_failure(c, IPC_TYPE_SUBSCRIBE,
"Event does not exist");
return -1; return -1;
} }
@ -755,15 +740,14 @@ ipc_subscribe(IPCClient *c, const char *msg)
return 0; return 0;
} }
int int ipc_init(const char *socket_path, const int p_epoll_fd,
ipc_init(const char *socket_path, const int p_epoll_fd, IPCCommand commands[], IPCCommand commands[], const int commands_len) {
const int commands_len)
{
// Initialize struct to 0 // Initialize struct to 0
memset(&sock_epoll_event, 0, sizeof(sock_epoll_event)); memset(&sock_epoll_event, 0, sizeof(sock_epoll_event));
int socket_fd = ipc_create_socket(socket_path); int socket_fd = ipc_create_socket(socket_path);
if (socket_fd < 0) return -1; if (socket_fd < 0)
return -1;
ipc_commands = commands; ipc_commands = commands;
ipc_commands_len = commands_len; ipc_commands_len = commands_len;
@ -781,9 +765,7 @@ ipc_init(const char *socket_path, const int p_epoll_fd, IPCCommand commands[],
return socket_fd; return socket_fd;
} }
void void ipc_cleanup() {
ipc_cleanup()
{
IPCClient *c = ipc_clients; IPCClient *c = ipc_clients;
// Free clients and their buffers // Free clients and their buffers
while (c) { while (c) {
@ -809,27 +791,19 @@ ipc_cleanup()
close(sock_fd); close(sock_fd);
} }
int int ipc_get_sock_fd() {
ipc_get_sock_fd()
{
return sock_fd; return sock_fd;
} }
IPCClient * IPCClient *ipc_get_client(int fd) {
ipc_get_client(int fd)
{
return ipc_list_get_client(ipc_clients, fd); return ipc_list_get_client(ipc_clients, fd);
} }
int int ipc_is_client_registered(int fd) {
ipc_is_client_registered(int fd)
{
return (ipc_get_client(fd) != NULL); return (ipc_get_client(fd) != NULL);
} }
int int ipc_accept_client() {
ipc_accept_client()
{
int fd = -1; int fd = -1;
struct sockaddr_un client_addr; struct sockaddr_un client_addr;
@ -852,7 +826,8 @@ ipc_accept_client()
} }
IPCClient *nc = ipc_client_new(fd); IPCClient *nc = ipc_client_new(fd);
if (nc == NULL) return -1; if (nc == NULL)
return -1;
// Wake up to messages from this client // Wake up to messages from this client
nc->event.data.fd = fd; nc->event.data.fd = fd;
@ -866,9 +841,7 @@ ipc_accept_client()
return fd; return fd;
} }
int int ipc_drop_client(IPCClient *c) {
ipc_drop_client(IPCClient *c)
{
int fd = c->fd; int fd = c->fd;
shutdown(fd, SHUT_RDWR); shutdown(fd, SHUT_RDWR);
int res = close(fd); int res = close(fd);
@ -891,21 +864,20 @@ ipc_drop_client(IPCClient *c)
return res; return res;
} }
int int ipc_read_client(IPCClient *c, IPCMessageType *msg_type,
ipc_read_client(IPCClient *c, IPCMessageType *msg_type, uint32_t *msg_size, uint32_t *msg_size, char **msg) {
char **msg)
{
int fd = c->fd; int fd = c->fd;
int ret = int ret = ipc_recv_message(fd, (uint8_t *) msg_type, msg_size,
ipc_recv_message(fd, (uint8_t *)msg_type, msg_size, (uint8_t **)msg); (uint8_t **) msg);
if (ret < 0) { if (ret < 0) {
// This will happen if these errors occur while reading header // This will happen if these errors occur while reading header
if (ret == -1 && if (ret == -1
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
return -2; return -2;
fprintf(stderr, "Error reading message: dropping client at fd %d\n", fd); fprintf(stderr, "Error reading message: dropping client at fd %d\n",
fd);
ipc_drop_client(c); ipc_drop_client(c);
return -1; return -1;
@ -929,12 +901,11 @@ ipc_read_client(IPCClient *c, IPCMessageType *msg_type, uint32_t *msg_size,
return 0; return 0;
} }
ssize_t ssize_t ipc_write_client(IPCClient *c) {
ipc_write_client(IPCClient *c)
{
const ssize_t n = ipc_write_message(c->fd, c->buffer, c->buffer_size); const ssize_t n = ipc_write_message(c->fd, c->buffer, c->buffer_size);
if (n < 0) return n; if (n < 0)
return n;
// TODO: Deal with client timeouts // TODO: Deal with client timeouts
@ -959,12 +930,11 @@ ipc_write_client(IPCClient *c)
return n; return n;
} }
void void ipc_prepare_send_message(IPCClient *c, const IPCMessageType msg_type,
ipc_prepare_send_message(IPCClient *c, const IPCMessageType msg_type, const uint32_t msg_size, const char *msg) {
const uint32_t msg_size, const char *msg) dwm_ipc_header_t header = {.magic = IPC_MAGIC_ARR,
{ .type = msg_type,
dwm_ipc_header_t header = { .size = msg_size};
.magic = IPC_MAGIC_ARR, .type = msg_type, .size = msg_size};
uint32_t header_size = sizeof(dwm_ipc_header_t); uint32_t header_size = sizeof(dwm_ipc_header_t);
uint32_t packet_size = header_size + msg_size; uint32_t packet_size = header_size + msg_size;
@ -987,10 +957,8 @@ ipc_prepare_send_message(IPCClient *c, const IPCMessageType msg_type,
epoll_ctl(epoll_fd, EPOLL_CTL_MOD, c->fd, &c->event); epoll_ctl(epoll_fd, EPOLL_CTL_MOD, c->fd, &c->event);
} }
void void ipc_prepare_reply_failure(IPCClient *c, IPCMessageType msg_type,
ipc_prepare_reply_failure(IPCClient *c, IPCMessageType msg_type, const char *format, ...) {
const char *format, ...)
{
yajl_gen gen; yajl_gen gen;
va_list args; va_list args;
@ -1013,39 +981,32 @@ ipc_prepare_reply_failure(IPCClient *c, IPCMessageType msg_type,
free(buffer); free(buffer);
} }
void void ipc_prepare_reply_success(IPCClient *c, IPCMessageType msg_type) {
ipc_prepare_reply_success(IPCClient *c, IPCMessageType msg_type)
{
const char *success_msg = "{\"result\":\"success\"}"; const char *success_msg = "{\"result\":\"success\"}";
const size_t msg_len = strlen(success_msg) + 1; // +1 for null char const size_t msg_len = strlen(success_msg) + 1; // +1 for null char
ipc_prepare_send_message(c, msg_type, msg_len, success_msg); ipc_prepare_send_message(c, msg_type, msg_len, success_msg);
} }
void void ipc_tag_change_event(int mon_num, TagState old_state,
ipc_tag_change_event(int mon_num, TagState old_state, TagState new_state) TagState new_state) {
{
yajl_gen gen; yajl_gen gen;
ipc_event_init_message(&gen); ipc_event_init_message(&gen);
dump_tag_event(gen, mon_num, old_state, new_state); dump_tag_event(gen, mon_num, old_state, new_state);
ipc_event_prepare_send_message(gen, IPC_EVENT_TAG_CHANGE); ipc_event_prepare_send_message(gen, IPC_EVENT_TAG_CHANGE);
} }
void void ipc_client_focus_change_event(int mon_num, Client *old_client,
ipc_client_focus_change_event(int mon_num, Client *old_client, Client *new_client) {
Client *new_client)
{
yajl_gen gen; yajl_gen gen;
ipc_event_init_message(&gen); ipc_event_init_message(&gen);
dump_client_focus_change_event(gen, old_client, new_client, mon_num); dump_client_focus_change_event(gen, old_client, new_client, mon_num);
ipc_event_prepare_send_message(gen, IPC_EVENT_CLIENT_FOCUS_CHANGE); ipc_event_prepare_send_message(gen, IPC_EVENT_CLIENT_FOCUS_CHANGE);
} }
void void ipc_layout_change_event(const int mon_num, const char *old_symbol,
ipc_layout_change_event(const int mon_num, const char *old_symbol,
const Layout *old_layout, const char *new_symbol, const Layout *old_layout, const char *new_symbol,
const Layout *new_layout) const Layout *new_layout) {
{
yajl_gen gen; yajl_gen gen;
ipc_event_init_message(&gen); ipc_event_init_message(&gen);
dump_layout_change_event(gen, mon_num, old_symbol, old_layout, new_symbol, dump_layout_change_event(gen, mon_num, old_symbol, old_layout, new_symbol,
@ -1053,30 +1014,27 @@ ipc_layout_change_event(const int mon_num, const char *old_symbol,
ipc_event_prepare_send_message(gen, IPC_EVENT_LAYOUT_CHANGE); ipc_event_prepare_send_message(gen, IPC_EVENT_LAYOUT_CHANGE);
} }
void void ipc_monitor_focus_change_event(const int last_mon_num,
ipc_monitor_focus_change_event(const int last_mon_num, const int new_mon_num) const int new_mon_num) {
{
yajl_gen gen; yajl_gen gen;
ipc_event_init_message(&gen); ipc_event_init_message(&gen);
dump_monitor_focus_change_event(gen, last_mon_num, new_mon_num); dump_monitor_focus_change_event(gen, last_mon_num, new_mon_num);
ipc_event_prepare_send_message(gen, IPC_EVENT_MONITOR_FOCUS_CHANGE); ipc_event_prepare_send_message(gen, IPC_EVENT_MONITOR_FOCUS_CHANGE);
} }
void void ipc_focused_title_change_event(const int mon_num, const Window client_id,
ipc_focused_title_change_event(const int mon_num, const Window client_id, const char *old_name,
const char *old_name, const char *new_name) const char *new_name) {
{
yajl_gen gen; yajl_gen gen;
ipc_event_init_message(&gen); ipc_event_init_message(&gen);
dump_focused_title_change_event(gen, mon_num, client_id, old_name, new_name); dump_focused_title_change_event(gen, mon_num, client_id, old_name,
new_name);
ipc_event_prepare_send_message(gen, IPC_EVENT_FOCUSED_TITLE_CHANGE); ipc_event_prepare_send_message(gen, IPC_EVENT_FOCUSED_TITLE_CHANGE);
} }
void void ipc_focused_state_change_event(const int mon_num, const Window client_id,
ipc_focused_state_change_event(const int mon_num, const Window client_id,
const ClientState *old_state, const ClientState *old_state,
const ClientState *new_state) const ClientState *new_state) {
{
yajl_gen gen; yajl_gen gen;
ipc_event_init_message(&gen); ipc_event_init_message(&gen);
dump_focused_state_change_event(gen, mon_num, client_id, old_state, dump_focused_state_change_event(gen, mon_num, client_id, old_state,
@ -1084,20 +1042,21 @@ ipc_focused_state_change_event(const int mon_num, const Window client_id,
ipc_event_prepare_send_message(gen, IPC_EVENT_FOCUSED_STATE_CHANGE); ipc_event_prepare_send_message(gen, IPC_EVENT_FOCUSED_STATE_CHANGE);
} }
void void ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon) {
ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon)
{
for (Monitor *m = mons; m; m = m->next) { for (Monitor *m = mons; m; m = m->next) {
unsigned int urg = 0, occ = 0, tagset = 0; unsigned int urg = 0, occ = 0, tagset = 0;
for (Client *c = m->clients; c; c = c->next) { for (Client *c = m->clients; c; c = c->next) {
occ |= c->tags; occ |= c->tags;
if (c->isurgent) urg |= c->tags; if (c->isurgent)
urg |= c->tags;
} }
tagset = m->tagset[m->seltags]; tagset = m->tagset[m->seltags];
TagState new_state = {.selected = tagset, .occupied = occ, .urgent = urg}; TagState new_state = {.selected = tagset,
.occupied = occ,
.urgent = urg};
if (memcmp(&m->tagstate, &new_state, sizeof(TagState)) != 0) { if (memcmp(&m->tagstate, &new_state, sizeof(TagState)) != 0) {
ipc_tag_change_event(m->num, m->tagstate, new_state); ipc_tag_change_event(m->num, m->tagstate, new_state);
@ -1109,22 +1068,24 @@ ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon)
m->lastsel = m->sel; m->lastsel = m->sel;
} }
if (strcmp(m->ltsymbol, m->lastltsymbol) != 0 || if (strcmp(m->ltsymbol, m->lastltsymbol) != 0
m->lastlt != m->lt[m->sellt]) { || m->lastlt != m->lt[m->sellt]) {
ipc_layout_change_event(m->num, m->lastltsymbol, m->lastlt, m->ltsymbol, ipc_layout_change_event(m->num, m->lastltsymbol, m->lastlt,
m->lt[m->sellt]); m->ltsymbol, m->lt[m->sellt]);
strcpy(m->lastltsymbol, m->ltsymbol); strcpy(m->lastltsymbol, m->ltsymbol);
m->lastlt = m->lt[m->sellt]; m->lastlt = m->lt[m->sellt];
} }
if (*lastselmon != selmon) { if (*lastselmon != selmon) {
if (*lastselmon != NULL) if (*lastselmon != NULL)
ipc_monitor_focus_change_event((*lastselmon)->num, selmon->num); ipc_monitor_focus_change_event((*lastselmon)->num,
selmon->num);
*lastselmon = selmon; *lastselmon = selmon;
} }
Client *sel = m->sel; Client *sel = m->sel;
if (!sel) continue; if (!sel)
continue;
ClientState *o = &m->sel->prevstate; ClientState *o = &m->sel->prevstate;
ClientState n = {.oldstate = sel->oldstate, ClientState n = {.oldstate = sel->oldstate,
.isfixed = sel->isfixed, .isfixed = sel->isfixed,
@ -1139,12 +1100,11 @@ ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon)
} }
} }
int int ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
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) {
int fd = ev->data.fd; int fd = ev->data.fd;
IPCClient *c = ipc_get_client(fd); IPCClient *c = ipc_get_client(fd);
@ -1153,14 +1113,16 @@ ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
ipc_drop_client(c); ipc_drop_client(c);
} else if (ev->events & EPOLLOUT) { } else if (ev->events & EPOLLOUT) {
DEBUG("Sending message to client at fd %d...\n", fd); DEBUG("Sending message to client at fd %d...\n", fd);
if (c->buffer_size) ipc_write_client(c); if (c->buffer_size)
ipc_write_client(c);
} else if (ev->events & EPOLLIN) { } else if (ev->events & EPOLLIN) {
IPCMessageType msg_type = 0; IPCMessageType msg_type = 0;
uint32_t msg_size = 0; uint32_t msg_size = 0;
char *msg = NULL; char *msg = NULL;
DEBUG("Received message from fd %d\n", fd); DEBUG("Received message from fd %d\n", fd);
if (ipc_read_client(c, &msg_type, &msg_size, &msg) < 0) return -1; if (ipc_read_client(c, &msg_type, &msg_size, &msg) < 0)
return -1;
if (msg_type == IPC_TYPE_GET_MONITORS) if (msg_type == IPC_TYPE_GET_MONITORS)
ipc_get_monitors(c, mons, selmon); ipc_get_monitors(c, mons, selmon);
@ -1169,12 +1131,15 @@ ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
else if (msg_type == IPC_TYPE_GET_LAYOUTS) else if (msg_type == IPC_TYPE_GET_LAYOUTS)
ipc_get_layouts(c, layouts, layouts_len); ipc_get_layouts(c, layouts, layouts_len);
else if (msg_type == IPC_TYPE_RUN_COMMAND) { else if (msg_type == IPC_TYPE_RUN_COMMAND) {
if (ipc_run_command(c, msg) < 0) return -1; if (ipc_run_command(c, msg) < 0)
return -1;
ipc_send_events(mons, lastselmon, selmon); ipc_send_events(mons, lastselmon, selmon);
} else if (msg_type == IPC_TYPE_GET_DWM_CLIENT) { } else if (msg_type == IPC_TYPE_GET_DWM_CLIENT) {
if (ipc_get_dwm_client(c, msg, mons) < 0) return -1; if (ipc_get_dwm_client(c, msg, mons) < 0)
return -1;
} else if (msg_type == IPC_TYPE_SUBSCRIBE) { } else if (msg_type == IPC_TYPE_SUBSCRIBE) {
if (ipc_subscribe(c, msg) < 0) return -1; if (ipc_subscribe(c, msg) < 0)
return -1;
} else { } else {
fprintf(stderr, "Invalid message type received from fd %d", fd); fprintf(stderr, "Invalid message type received from fd %d", fd);
ipc_prepare_reply_failure(c, msg_type, "Invalid message type: %d", ipc_prepare_reply_failure(c, msg_type, "Invalid message type: %d",
@ -1182,17 +1147,17 @@ ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
} }
free(msg); free(msg);
} else { } else {
fprintf(stderr, "Epoll event returned %d from fd %d\n", ev->events, fd); fprintf(stderr, "Epoll event returned %d from fd %d\n", ev->events,
fd);
return -1; return -1;
} }
return 0; return 0;
} }
int int ipc_handle_socket_epoll_event(struct epoll_event *ev) {
ipc_handle_socket_epoll_event(struct epoll_event *ev) if (!(ev->events & EPOLLIN))
{ return -1;
if (!(ev->events & EPOLLIN)) return -1;
// EPOLLIN means incoming client connection request // EPOLLIN means incoming client connection request
fputs("Received EPOLLIN event on socket\n", stderr); fputs("Received EPOLLIN event on socket\n", stderr);

@ -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;

@ -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,8 +16,7 @@ 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);
@ -36,9 +33,7 @@ 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); size_t len = strlen(path);
*normal = (char *) malloc((len + 1) * sizeof(char)); *normal = (char *) malloc((len + 1) * sizeof(char));
const char *walk = path; const char *walk = path;
@ -71,9 +66,7 @@ normalizepath(const char *path, char **normal)
return 0; return 0;
} }
int int parentdir(const char *path, char **parent) {
parentdir(const char *path, char **parent)
{
char *normal; char *normal;
char *walk; char *walk;
@ -99,9 +92,7 @@ parentdir(const char *path, char **parent)
return 0; return 0;
} }
int int mkdirp(const char *path) {
mkdirp(const char *path)
{
char *normal; char *normal;
char *walk; char *walk;
size_t normallen; size_t normallen;
@ -156,9 +147,7 @@ mkdirp(const char *path)
return 0; return 0;
} }
int int nullterminate(char **str, size_t *len) {
nullterminate(char **str, size_t *len)
{
if ((*str)[*len - 1] == '\0') if ((*str)[*len - 1] == '\0')
return 0; return 0;

@ -2,9 +2,7 @@
#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);
@ -15,9 +13,7 @@ dump_tag(yajl_gen gen, const char *name, const int tag_mask)
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++)
@ -28,9 +24,7 @@ dump_tags(yajl_gen gen, const char *tags[], int tags_len)
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);
@ -95,9 +89,7 @@ dump_client(yajl_gen gen, Client *c)
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);
@ -161,9 +153,7 @@ dump_monitor(yajl_gen gen, Monitor *mon, int is_selected)
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) {
@ -178,9 +168,8 @@ dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon)
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++) {
@ -197,9 +186,7 @@ dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len)
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);
@ -211,10 +198,8 @@ dump_tag_state(yajl_gen gen, TagState state)
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(
@ -228,10 +213,8 @@ dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
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(
@ -245,11 +228,10 @@ dump_client_focus_change_event(yajl_gen gen, Client *old_client,
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 Layout *new_layout) const char *new_symbol,
{ const Layout *new_layout) {
// clang-format off // clang-format off
YMAP( YMAP(
YSTR("layout_change_event"); YMAP( YSTR("layout_change_event"); YMAP(
@ -265,10 +247,8 @@ dump_layout_change_event(yajl_gen gen, const int mon_num,
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(
@ -281,11 +261,10 @@ dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
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(
@ -300,9 +279,7 @@ dump_focused_title_change_event(yajl_gen gen, const int mon_num,
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);
@ -317,12 +294,10 @@ dump_client_state(yajl_gen gen, const ClientState *state)
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(
@ -337,9 +312,7 @@ dump_focused_state_change_event(yajl_gen gen, const int mon_num,
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");

@ -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);

Loading…
Cancel
Save