add support for .xoatrc
This commit is contained in:
18
client.c
18
client.c
@@ -71,7 +71,7 @@ Client* window_build_client(Window win)
|
|||||||
? 1:0;
|
? 1:0;
|
||||||
|
|
||||||
// detect our own title bars
|
// detect our own title bars
|
||||||
if (TITLE)
|
if (settings.title)
|
||||||
for_monitors(i, m) for_spots(j)
|
for_monitors(i, m) for_spots(j)
|
||||||
if (m->bars[j] && m->bars[j]->window == c->window)
|
if (m->bars[j] && m->bars[j]->window == c->window)
|
||||||
{ c->ours = 1; c->manage = 0; break; }
|
{ c->ours = 1; c->manage = 0; break; }
|
||||||
@@ -160,9 +160,9 @@ void client_free(Client *c)
|
|||||||
void client_update_border(Client *c)
|
void client_update_border(Client *c)
|
||||||
{
|
{
|
||||||
XColor color; Colormap map = DefaultColormap(display, DefaultScreen(display));
|
XColor color; Colormap map = DefaultColormap(display, DefaultScreen(display));
|
||||||
char *colorname = c->window == current ? BORDER_FOCUS: (c->urgent ? BORDER_URGENT: BORDER_BLUR);
|
char *colorname = c->window == current ? settings.border_focus: (c->urgent ? settings.border_urgent: settings.border_blur);
|
||||||
XSetWindowBorder(display, c->window, XAllocNamedColor(display, map, colorname, &color, &color) ? color.pixel: None);
|
XSetWindowBorder(display, c->window, XAllocNamedColor(display, map, colorname, &color, &color) ? color.pixel: None);
|
||||||
XSetWindowBorderWidth(display, c->window, c->full ? 0: BORDER);
|
XSetWindowBorderWidth(display, c->window, c->full ? 0: settings.border);
|
||||||
}
|
}
|
||||||
|
|
||||||
int client_send_wm_protocol(Client *c, Atom protocol)
|
int client_send_wm_protocol(Client *c, Atom protocol)
|
||||||
@@ -206,8 +206,8 @@ void client_place_spot(Client *c, int spot, int mon, int force)
|
|||||||
{
|
{
|
||||||
x += (w - c->attr.width)/2;
|
x += (w - c->attr.width)/2;
|
||||||
y += (h - c->attr.height)/2;
|
y += (h - c->attr.height)/2;
|
||||||
w = c->attr.width + BORDER*2;
|
w = c->attr.width + settings.border * 2;
|
||||||
h = c->attr.height + BORDER*2;
|
h = c->attr.height + settings.border * 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (c->full)
|
if (c->full)
|
||||||
@@ -234,7 +234,7 @@ void client_place_spot(Client *c, int spot, int mon, int force)
|
|||||||
w = m->w;
|
w = m->w;
|
||||||
}
|
}
|
||||||
|
|
||||||
w -= BORDER*2; h -= BORDER*2;
|
w -= settings.border * 2; h -= settings.border * 2;
|
||||||
int sw = w, sh = h; long sr; XSizeHints size;
|
int sw = w, sh = h; long sr; XSizeHints size;
|
||||||
|
|
||||||
if (XGetWMNormalHints(display, c->window, &size, &sr))
|
if (XGetWMNormalHints(display, c->window, &size, &sr))
|
||||||
@@ -261,8 +261,8 @@ void client_place_spot(Client *c, int spot, int mon, int force)
|
|||||||
if (h < sh) y += (sh-h)/2;
|
if (h < sh) y += (sh-h)/2;
|
||||||
|
|
||||||
// bump onto screen
|
// bump onto screen
|
||||||
x = MAX(m->x, MIN(x, m->x + m->w - w - BORDER*2));
|
x = MAX(m->x, MIN(x, m->x + m->w - w - settings.border * 2));
|
||||||
y = MAX(m->y, MIN(y, m->y + m->h - h - BORDER*2));
|
y = MAX(m->y, MIN(y, m->y + m->h - h - settings.border * 2));
|
||||||
|
|
||||||
XMoveResizeWindow(display, c->window, x, y, w, h);
|
XMoveResizeWindow(display, c->window, x, y, w, h);
|
||||||
}
|
}
|
||||||
@@ -298,7 +298,7 @@ void client_raise_family(Client *c)
|
|||||||
|
|
||||||
client_stack_family(c, &raise);
|
client_stack_family(c, &raise);
|
||||||
|
|
||||||
if (!c->full && TITLE)
|
if (!c->full && settings.title)
|
||||||
{
|
{
|
||||||
// raise spot's title bar in case some other fullscreen or max v/h window has obscured
|
// raise spot's title bar in case some other fullscreen or max v/h window has obscured
|
||||||
Monitor *m = &monitors[c->monitor];
|
Monitor *m = &monitors[c->monitor];
|
||||||
|
|||||||
432
config.c
Normal file
432
config.c
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
MIT/X11 License
|
||||||
|
Copyright (c) 2014 Sean Pringle <sean.pringle@gmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CONFIG_BORDER "border"
|
||||||
|
#define CONFIG_BORDER_BLUR "border_blur"
|
||||||
|
#define CONFIG_BORDER_FOCUS "border_focus"
|
||||||
|
#define CONFIG_BORDER_URGENT "border_urgent"
|
||||||
|
#define CONFIG_GAP "gap"
|
||||||
|
#define CONFIG_TITLE "title"
|
||||||
|
#define CONFIG_TITLE_BLUR "title_blur"
|
||||||
|
#define CONFIG_TITLE_FOCUS "title_focus"
|
||||||
|
#define CONFIG_TITLE_ELLIPSIS "title_ellipsis"
|
||||||
|
#define CONFIG_LAYOUTS "layouts"
|
||||||
|
|
||||||
|
#define CONFIG_UINT_NAMES CONFIG_BORDER "|" CONFIG_GAP "|" CONFIG_TITLE_ELLIPSIS
|
||||||
|
#define CONFIG_STR_NAMES CONFIG_BORDER_BLUR "|" CONFIG_BORDER_FOCUS "|" CONFIG_BORDER_URGENT "|" CONFIG_TITLE "|" CONFIG_TITLE_BLUR "|" CONFIG_TITLE_FOCUS
|
||||||
|
|
||||||
|
#define CONFIG_ACTIONS "action_move_direction|action_focus_direction|action_move|action_focus|action_close|action_cycle|action_raise_nth|action_command|action_find_or_start|action_move_monitor|action_focus_monitor|action_fullscreen|action_maximize_vert|action_maximize_horz|action_maximize"
|
||||||
|
|
||||||
|
void
|
||||||
|
rtrim(char *str)
|
||||||
|
{
|
||||||
|
char *end = str + strlen(str);
|
||||||
|
while (end && --end >= str && isspace(*end)) *end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ltrim(char *str)
|
||||||
|
{
|
||||||
|
while (isspace(*str)) memmove(str, str+1, strlen(str+1)+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
trim(char *str)
|
||||||
|
{
|
||||||
|
ltrim(str);
|
||||||
|
rtrim(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
configure()
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
FILE *file = NULL;
|
||||||
|
char tmp[1024];
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
|
||||||
|
settings.border = BORDER;
|
||||||
|
settings.border_blur = strdup(BORDER_BLUR);
|
||||||
|
settings.border_focus = strdup(BORDER_FOCUS);
|
||||||
|
settings.border_urgent = strdup(BORDER_URGENT);
|
||||||
|
settings.gap = GAP;
|
||||||
|
settings.title = TITLE ? strdup(TITLE): NULL;
|
||||||
|
settings.title_blur = strdup(TITLE_BLUR);
|
||||||
|
settings.title_focus = strdup(TITLE_FOCUS);
|
||||||
|
settings.title_ellipsis = TITLE_ELLIPSIS;
|
||||||
|
|
||||||
|
settings.layout_count = sizeof(layouts) / sizeof(Layout);
|
||||||
|
settings.layouts = calloc(settings.layout_count, sizeof(Layout));
|
||||||
|
|
||||||
|
for (i = 0; i < settings.layout_count; i++)
|
||||||
|
memmove(&settings.layouts[i], &layouts[i], sizeof(Layout));
|
||||||
|
|
||||||
|
settings.binding_count = sizeof(keys) / sizeof(Binding);
|
||||||
|
settings.bindings = calloc(settings.binding_count, sizeof(Binding));
|
||||||
|
|
||||||
|
for (i = 0; i < settings.binding_count; i++)
|
||||||
|
memmove(&settings.bindings[i], &keys[i], sizeof(Binding));
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s/.xoatrc", home);
|
||||||
|
|
||||||
|
if (home && (file = fopen(tmp, "r")) && file)
|
||||||
|
{
|
||||||
|
while (fgets(tmp, sizeof(tmp), file))
|
||||||
|
{
|
||||||
|
if (regex_match("^[[:space:]]*(" CONFIG_UINT_NAMES ")[[:space:]]+([0-9]+)", tmp))
|
||||||
|
{
|
||||||
|
unsigned n = strtoul(regex_matches[2], NULL, 10);
|
||||||
|
|
||||||
|
char *names[] = {
|
||||||
|
CONFIG_BORDER,
|
||||||
|
CONFIG_GAP,
|
||||||
|
CONFIG_TITLE_ELLIPSIS,
|
||||||
|
};
|
||||||
|
unsigned int *values[] = {
|
||||||
|
&settings.border,
|
||||||
|
&settings.gap,
|
||||||
|
&settings.title_ellipsis,
|
||||||
|
};
|
||||||
|
for (i = 0; i < sizeof(names) / sizeof(char*); i++)
|
||||||
|
{
|
||||||
|
if (strcmp(regex_matches[1], names[i]) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "set [%s] to [%u]\n", names[i], n);
|
||||||
|
*(values[i]) = n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (regex_match("^[[:space:]]*(" CONFIG_STR_NAMES ")[[:space:]]+(.+)", tmp))
|
||||||
|
{
|
||||||
|
rtrim(regex_matches[2]);
|
||||||
|
|
||||||
|
char *names[] = {
|
||||||
|
CONFIG_BORDER_BLUR,
|
||||||
|
CONFIG_BORDER_FOCUS,
|
||||||
|
CONFIG_BORDER_URGENT,
|
||||||
|
CONFIG_TITLE,
|
||||||
|
CONFIG_TITLE_BLUR,
|
||||||
|
CONFIG_TITLE_FOCUS,
|
||||||
|
};
|
||||||
|
char **values[] = {
|
||||||
|
&settings.border_blur,
|
||||||
|
&settings.border_focus,
|
||||||
|
&settings.border_urgent,
|
||||||
|
&settings.title,
|
||||||
|
&settings.title_blur,
|
||||||
|
&settings.title_focus,
|
||||||
|
};
|
||||||
|
for (i = 0; i < sizeof(names) / sizeof(char*); i++)
|
||||||
|
{
|
||||||
|
if (strcmp(regex_matches[1], names[i]) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "set [%s] to [%s]\n", names[i], regex_matches[2]);
|
||||||
|
free(*(values[i]));
|
||||||
|
*(values[i]) = strdup(regex_matches[2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (regex_match("^[[:space:]]*(layouts)[[:space:]]+([1-9])", tmp))
|
||||||
|
{
|
||||||
|
unsigned int n = strtoul(regex_matches[2], NULL, 10);
|
||||||
|
fprintf(stderr, "using [%u] monitor layout%s\n", n, n > 1 ? "s":"");
|
||||||
|
|
||||||
|
free(settings.layouts);
|
||||||
|
settings.layout_count = n;
|
||||||
|
settings.layouts = calloc(settings.layout_count, sizeof(Layout));
|
||||||
|
|
||||||
|
for (i = 0; i < settings.layout_count && i < sizeof(layouts) / sizeof(Layout); i++)
|
||||||
|
memmove(&settings.layouts[i], &layouts[i], sizeof(Layout));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (regex_match("^[[:space:]]*layout[[:space:]]([0-9])(.+)", tmp))
|
||||||
|
{
|
||||||
|
unsigned int n = strtoul(regex_matches[1], NULL, 10);
|
||||||
|
if (!have_layout(n))
|
||||||
|
{
|
||||||
|
for (i = settings.layout_count; i < n+1; i++)
|
||||||
|
{
|
||||||
|
settings.layout_count++;
|
||||||
|
settings.layouts = realloc(settings.layouts, sizeof(Layout) * settings.layout_count);
|
||||||
|
memmove(&settings.layouts[i], &settings.layouts[0], sizeof(Layout));
|
||||||
|
fprintf(stderr, "creating layout [%u]\n", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s", regex_matches[2]);
|
||||||
|
|
||||||
|
if (regex_match("^[[:space:]]spot_start[[:space:]]+(smart|current|spot1|spot2|spot3)", tmp))
|
||||||
|
{
|
||||||
|
char *names[] = {
|
||||||
|
"smart",
|
||||||
|
"current",
|
||||||
|
"spot1",
|
||||||
|
"spot2",
|
||||||
|
"spot3",
|
||||||
|
};
|
||||||
|
short values[] = {
|
||||||
|
SMART,
|
||||||
|
CURRENT,
|
||||||
|
SPOT1,
|
||||||
|
SPOT2,
|
||||||
|
SPOT3,
|
||||||
|
};
|
||||||
|
for (i = 0; i < sizeof(names) / sizeof(char*); i++)
|
||||||
|
{
|
||||||
|
if (strcmp(regex_matches[1], names[i]) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "layout [%u] spot_start [%s]\n", n, regex_matches[1]);
|
||||||
|
settings.layouts[n].spot_start = values[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (regex_match("^[[:space:]]spot1_align[[:space:]]+(left|right)", tmp))
|
||||||
|
{
|
||||||
|
char *names[] = {
|
||||||
|
"left",
|
||||||
|
"right",
|
||||||
|
};
|
||||||
|
short values[] = {
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
};
|
||||||
|
for (i = 0; i < sizeof(names) / sizeof(char*); i++)
|
||||||
|
{
|
||||||
|
if (strcmp(regex_matches[1], names[i]) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "layout [%u] spot1_align [%s]\n", n, regex_matches[1]);
|
||||||
|
settings.layouts[n].spot1_align = values[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (regex_match("^[[:space:]]spot1_width_pct[[:space:]]+([0-9]+)", tmp))
|
||||||
|
{
|
||||||
|
unsigned int w = strtoul(regex_matches[1], NULL, 10);
|
||||||
|
if (w < 50 || w > 90)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "layout [%u] spot1_width_pct out of bounds [%u]!\n", n, w);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "layout [%u] spot1_width_pct [%u%%]\n", n, w);
|
||||||
|
settings.layouts[n].spot1_width_pct = w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (regex_match("^[[:space:]]spot2_height_pct[[:space:]]+([0-9]+)", tmp))
|
||||||
|
{
|
||||||
|
unsigned int h = strtoul(regex_matches[1], NULL, 10);
|
||||||
|
if (h < 50 || h > 90)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "layout [%u] spot2_height_pct out of bounds [%u]!\n", n, h);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "layout [%u] spot2_height_pct [%u%%]\n", n, h);
|
||||||
|
settings.layouts[n].spot2_height_pct = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (regex_match("^[[:space:]]*bind[[:space:]]+([^[:space:]]+)[[:space:]]+(" CONFIG_ACTIONS ")(.*)", tmp))
|
||||||
|
{
|
||||||
|
unsigned int modifier = 0;
|
||||||
|
char *str = regex_matches[1];
|
||||||
|
fprintf(stderr, "binding");
|
||||||
|
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
if ((strncmp(str, "Mod1" , 4)) == 0)
|
||||||
|
{
|
||||||
|
modifier |= Mod1Mask;
|
||||||
|
fprintf(stderr, " [Mod1]");
|
||||||
|
str += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((strncmp(str, "Mod2" , 4)) == 0)
|
||||||
|
{
|
||||||
|
modifier |= Mod2Mask;
|
||||||
|
fprintf(stderr, " [Mod2]");
|
||||||
|
str += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((strncmp(str, "Mod3" , 4)) == 0)
|
||||||
|
{
|
||||||
|
modifier |= Mod3Mask;
|
||||||
|
fprintf(stderr, " [Mod3]");
|
||||||
|
str += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((strncmp(str, "Mod4" , 4)) == 0)
|
||||||
|
{
|
||||||
|
modifier |= Mod4Mask;
|
||||||
|
fprintf(stderr, " [Mod4]");
|
||||||
|
str += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((strncmp(str, "Mod5" , 4)) == 0)
|
||||||
|
{
|
||||||
|
modifier |= Mod5Mask;
|
||||||
|
fprintf(stderr, " [Mod5]");
|
||||||
|
str += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((strncmp(str, "Shift", 5)) == 0)
|
||||||
|
{
|
||||||
|
modifier |= ShiftMask;
|
||||||
|
fprintf(stderr, " [Shift]");
|
||||||
|
str += 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (*str == '+') str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifier == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " AnyModifier");
|
||||||
|
modifier = AnyModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*str)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " malformed key binding [%s]\n", regex_matches[1]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeySym keysym = XStringToKeysym(str);
|
||||||
|
|
||||||
|
if (keysym == NoSymbol)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " unknown key symbol [%s]\n", str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, " [%s]", str);
|
||||||
|
|
||||||
|
int num = 0;
|
||||||
|
char *data = NULL;
|
||||||
|
void *action = NULL;
|
||||||
|
trim(regex_matches[3]);
|
||||||
|
|
||||||
|
char *names[] = {
|
||||||
|
"action_move",
|
||||||
|
"action_focus",
|
||||||
|
"action_move_direction",
|
||||||
|
"action_focus_direction",
|
||||||
|
"action_close",
|
||||||
|
"action_cycle",
|
||||||
|
"action_raise_nth",
|
||||||
|
"action_command",
|
||||||
|
"action_find_or_start",
|
||||||
|
"action_move_monitor",
|
||||||
|
"action_focus_monitor",
|
||||||
|
"action_fullscreen",
|
||||||
|
"action_maximize_vert",
|
||||||
|
"action_maximize_horz",
|
||||||
|
"action_maximize",
|
||||||
|
};
|
||||||
|
void *actions[] = {
|
||||||
|
action_move,
|
||||||
|
action_focus,
|
||||||
|
action_move_direction,
|
||||||
|
action_focus_direction,
|
||||||
|
action_close,
|
||||||
|
action_cycle,
|
||||||
|
action_raise_nth,
|
||||||
|
action_command,
|
||||||
|
action_find_or_start,
|
||||||
|
action_move_monitor,
|
||||||
|
action_focus_monitor,
|
||||||
|
action_fullscreen,
|
||||||
|
action_maximize_vert,
|
||||||
|
action_maximize_horz,
|
||||||
|
action_maximize,
|
||||||
|
};
|
||||||
|
for (i = 0; i < sizeof(names) / sizeof(char*); i++)
|
||||||
|
{
|
||||||
|
if (strcmp(names[i], regex_matches[2]) == 0)
|
||||||
|
{
|
||||||
|
action = actions[i];
|
||||||
|
fprintf(stderr, " to [%s %s]\n", regex_matches[2], regex_matches[3]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((0 == strcmp(regex_matches[2], "action_move")) || 0 == strcmp(regex_matches[2], "action_focus"))
|
||||||
|
{
|
||||||
|
if (strcmp(regex_matches[3], "spot1") == 0) num = SPOT1;
|
||||||
|
if (strcmp(regex_matches[3], "spot2") == 0) num = SPOT2;
|
||||||
|
if (strcmp(regex_matches[3], "spot3") == 0) num = SPOT3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == strcmp(regex_matches[2], "action_move_direction") || 0 == strcmp(regex_matches[2], "action_focus_direction"))
|
||||||
|
{
|
||||||
|
if (strcmp(regex_matches[3], "left" ) == 0) num = LEFT;
|
||||||
|
if (strcmp(regex_matches[3], "right") == 0) num = RIGHT;
|
||||||
|
if (strcmp(regex_matches[3], "up" ) == 0) num = UP;
|
||||||
|
if (strcmp(regex_matches[3], "down" ) == 0) num = DOWN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == strcmp(regex_matches[2], "action_command") || 0 == strcmp(regex_matches[2], "action_find_or_start"))
|
||||||
|
{
|
||||||
|
data = regex_matches[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == strcmp(regex_matches[2], "action_raise_nth") || 0 == strcmp(regex_matches[2], "action_move_monitor") || 0 == strcmp(regex_matches[2], "action_focus_monitor"))
|
||||||
|
{
|
||||||
|
num = strtol(regex_matches[3], NULL, 10);
|
||||||
|
}
|
||||||
|
for (i = 0; i < settings.binding_count; i++)
|
||||||
|
{
|
||||||
|
if (settings.bindings[i].mod == modifier && settings.bindings[i].key == keysym)
|
||||||
|
{
|
||||||
|
settings.bindings[i].act = action;
|
||||||
|
settings.bindings[i].data = data;
|
||||||
|
settings.bindings[i].num = num;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == settings.binding_count)
|
||||||
|
{
|
||||||
|
settings.binding_count++;
|
||||||
|
settings.bindings = realloc(settings.bindings, sizeof(Binding) * settings.binding_count);
|
||||||
|
settings.bindings[i].mod = modifier;
|
||||||
|
settings.bindings[i].key = keysym;
|
||||||
|
settings.bindings[i].act = action;
|
||||||
|
settings.bindings[i].data = data;
|
||||||
|
settings.bindings[i].num = num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
config.h
30
config.h
@@ -64,8 +64,9 @@ Layout layouts[] = {
|
|||||||
// action_fullscreen
|
// action_fullscreen
|
||||||
// action_maximize_vert
|
// action_maximize_vert
|
||||||
// action_maximize_horz
|
// action_maximize_horz
|
||||||
|
// action_maximize
|
||||||
|
|
||||||
// If you use "AnyModifier" place those keys at the end of the array.
|
// If using "AnyModifier" place those keys at the end of the array.
|
||||||
Binding keys[] = {
|
Binding keys[] = {
|
||||||
|
|
||||||
// Change focus to a spot by direction.
|
// Change focus to a spot by direction.
|
||||||
@@ -86,17 +87,6 @@ Binding keys[] = {
|
|||||||
// Cycle through all windows in the current spot.
|
// Cycle through all windows in the current spot.
|
||||||
{ .mod = Mod4Mask, .key = XK_grave, .act = action_cycle },
|
{ .mod = Mod4Mask, .key = XK_grave, .act = action_cycle },
|
||||||
|
|
||||||
// Raise nth window in the current spot.
|
|
||||||
{ .mod = Mod4Mask, .key = XK_1, .act = action_raise_nth, .num = 1 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_2, .act = action_raise_nth, .num = 2 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_3, .act = action_raise_nth, .num = 3 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_4, .act = action_raise_nth, .num = 4 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_5, .act = action_raise_nth, .num = 5 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_6, .act = action_raise_nth, .num = 6 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_7, .act = action_raise_nth, .num = 7 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_8, .act = action_raise_nth, .num = 8 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_9, .act = action_raise_nth, .num = 9 },
|
|
||||||
|
|
||||||
// Gracefully close the current window.
|
// Gracefully close the current window.
|
||||||
{ .mod = Mod4Mask, .key = XK_Escape, .act = action_close },
|
{ .mod = Mod4Mask, .key = XK_Escape, .act = action_close },
|
||||||
|
|
||||||
@@ -106,21 +96,9 @@ Binding keys[] = {
|
|||||||
{ .mod = Mod4Mask, .key = XK_h, .act = action_maximize_horz },
|
{ .mod = Mod4Mask, .key = XK_h, .act = action_maximize_horz },
|
||||||
{ .mod = Mod4Mask, .key = XK_m, .act = action_maximize },
|
{ .mod = Mod4Mask, .key = XK_m, .act = action_maximize },
|
||||||
|
|
||||||
// Switch focus between monitors.
|
|
||||||
{ .mod = Mod4Mask, .key = XK_Next, .act = action_focus_monitor, .num = -1 },
|
|
||||||
{ .mod = Mod4Mask, .key = XK_Prior, .act = action_focus_monitor, .num = +1 },
|
|
||||||
|
|
||||||
// Move windows between monitors.
|
|
||||||
{ .mod = ShiftMask|Mod4Mask, .key = XK_Next, .act = action_move_monitor, .num = -1 },
|
|
||||||
{ .mod = ShiftMask|Mod4Mask, .key = XK_Prior, .act = action_move_monitor, .num = +1 },
|
|
||||||
|
|
||||||
// Launcher
|
// Launcher
|
||||||
{ .mod = Mod4Mask, .key = XK_x, .act = action_command, .data = "dmenu_run" },
|
{ .mod = Mod4Mask, .key = XK_x, .act = action_command, .data = "dmenu_run" },
|
||||||
|
|
||||||
// Find or start apps by WM_CLASS (lower case match).
|
// Example
|
||||||
// Only works for apps that use some form of their binary name as their class...
|
// { .mod = AnyModifier, .key = XK_F1, .act = action_find_or_start, .data = "xterm" },
|
||||||
{ .mod = AnyModifier, .key = XK_F1, .act = action_find_or_start, .data = "xterm" },
|
|
||||||
{ .mod = AnyModifier, .key = XK_F2, .act = action_find_or_start, .data = "firefox" },
|
|
||||||
{ .mod = AnyModifier, .key = XK_F3, .act = action_find_or_start, .data = "pcmanfm" },
|
|
||||||
{ .mod = AnyModifier, .key = XK_F4, .act = action_find_or_start, .data = "sublime-text" },
|
|
||||||
};
|
};
|
||||||
10
event.c
10
event.c
@@ -50,7 +50,7 @@ void configure_request(XEvent *ev)
|
|||||||
if (e->value_mask & CWWidth) wc.width = e->width;
|
if (e->value_mask & CWWidth) wc.width = e->width;
|
||||||
if (e->value_mask & CWHeight) wc.height = e->height;
|
if (e->value_mask & CWHeight) wc.height = e->height;
|
||||||
if (e->value_mask & CWStackMode) wc.stack_mode = e->detail;
|
if (e->value_mask & CWStackMode) wc.stack_mode = e->detail;
|
||||||
if (e->value_mask & CWBorderWidth) wc.border_width = BORDER;
|
if (e->value_mask & CWBorderWidth) wc.border_width = settings.border;
|
||||||
XConfigureWindow(display, c->window, e->value_mask, &wc);
|
XConfigureWindow(display, c->window, e->value_mask, &wc);
|
||||||
}
|
}
|
||||||
client_free(c);
|
client_free(c);
|
||||||
@@ -75,7 +75,7 @@ void map_request(XEvent *e)
|
|||||||
{
|
{
|
||||||
c->monitor = current_mon;
|
c->monitor = current_mon;
|
||||||
Monitor *m = &monitors[c->monitor];
|
Monitor *m = &monitors[c->monitor];
|
||||||
int spot = have_layout(c->monitor) ? layouts[c->monitor].spot_start: SMART;
|
int spot = have_layout(c->monitor) ? settings.layouts[c->monitor].spot_start: SMART;
|
||||||
|
|
||||||
if (spot == CURRENT)
|
if (spot == CURRENT)
|
||||||
{
|
{
|
||||||
@@ -129,9 +129,9 @@ void key_press(XEvent *ev)
|
|||||||
while (XCheckTypedEvent(display, KeyPress, ev));
|
while (XCheckTypedEvent(display, KeyPress, ev));
|
||||||
|
|
||||||
Binding *bind = NULL;
|
Binding *bind = NULL;
|
||||||
for (int i = 0; i < sizeof(keys)/sizeof(Binding) && !bind; i++)
|
for (int i = 0; i < settings.binding_count && !bind; i++)
|
||||||
if (keys[i].key == key && (keys[i].mod == AnyModifier || keys[i].mod == state))
|
if (settings.bindings[i].key == key && (settings.bindings[i].mod == AnyModifier || settings.bindings[i].mod == state))
|
||||||
bind = &keys[i];
|
bind = &settings.bindings[i];
|
||||||
|
|
||||||
if (bind && bind->act)
|
if (bind && bind->act)
|
||||||
{
|
{
|
||||||
|
|||||||
174
regex.c
Normal file
174
regex.c
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
MIT/X11 License
|
||||||
|
Copyright (c) 2014 Sean Pringle <sean.pringle@gmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define REGEX_CACHE 8
|
||||||
|
#define REGEX_GROUPS 8
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int hash;
|
||||||
|
char *pattern;
|
||||||
|
regex_t regex;
|
||||||
|
unsigned int used;
|
||||||
|
} RegexCache;
|
||||||
|
|
||||||
|
RegexCache regex_cache[REGEX_CACHE];
|
||||||
|
|
||||||
|
regex_t*
|
||||||
|
regex(const char *pattern)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
unsigned int hash = 0;
|
||||||
|
regex_t *re = NULL;
|
||||||
|
RegexCache *rc = NULL;
|
||||||
|
|
||||||
|
while (pattern[i])
|
||||||
|
{
|
||||||
|
hash = 33 * hash + pattern[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
// have we compiled this regex before?
|
||||||
|
for (i = 0; i < REGEX_CACHE; i++)
|
||||||
|
{
|
||||||
|
rc = ®ex_cache[i];
|
||||||
|
if (rc->hash == hash && rc->pattern && !strcmp(pattern, rc->pattern))
|
||||||
|
{
|
||||||
|
re = &rc->regex;
|
||||||
|
rc->used++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!re)
|
||||||
|
{
|
||||||
|
int slot = 0;
|
||||||
|
// look for a free cache slot
|
||||||
|
for (i = 0; i < REGEX_CACHE; i++)
|
||||||
|
{
|
||||||
|
if (!regex_cache[i].pattern)
|
||||||
|
{
|
||||||
|
slot = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (regex_cache[slot].pattern)
|
||||||
|
{
|
||||||
|
// choose the least used
|
||||||
|
for (i = 0; i < REGEX_CACHE; i++)
|
||||||
|
{
|
||||||
|
if (regex_cache[i].used < regex_cache[slot].used)
|
||||||
|
{
|
||||||
|
slot = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ®ex_cache[slot];
|
||||||
|
|
||||||
|
if (rc->pattern)
|
||||||
|
{
|
||||||
|
regfree(&rc->regex);
|
||||||
|
free(rc->pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc->used = 0;
|
||||||
|
rc->hash = 0;
|
||||||
|
rc->pattern = NULL;
|
||||||
|
|
||||||
|
re = &rc->regex;
|
||||||
|
|
||||||
|
if (regcomp(re, pattern, REG_EXTENDED) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "regex compile failure: %s", pattern);
|
||||||
|
re = NULL;
|
||||||
|
}
|
||||||
|
if (re)
|
||||||
|
{
|
||||||
|
rc->pattern = strdup(pattern);
|
||||||
|
rc->hash = hash;
|
||||||
|
rc->used = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flush_regex_cache()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < REGEX_CACHE; i++)
|
||||||
|
{
|
||||||
|
RegexCache *rc = ®ex_cache[i];
|
||||||
|
if (rc->pattern)
|
||||||
|
{
|
||||||
|
regfree(&rc->regex);
|
||||||
|
free(rc->pattern);
|
||||||
|
rc->used = 0;
|
||||||
|
rc->hash = 0;
|
||||||
|
rc->pattern = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *regex_matches[REGEX_GROUPS];
|
||||||
|
|
||||||
|
int
|
||||||
|
regex_match(const char *pattern, const char *subject)
|
||||||
|
{
|
||||||
|
int r = 0; regmatch_t pmatch[REGEX_GROUPS];
|
||||||
|
regex_t *re = regex(pattern);
|
||||||
|
if (re && subject && (r = regexec(re, subject, REGEX_GROUPS, pmatch, 0) == 0))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < REGEX_GROUPS && pmatch[i].rm_so != (size_t)-1; i++)
|
||||||
|
{
|
||||||
|
free(regex_matches[i]);
|
||||||
|
int len = pmatch[i].rm_eo - pmatch[i].rm_so;
|
||||||
|
regex_matches[i] = malloc(len + 1);
|
||||||
|
strncpy(regex_matches[i], subject + pmatch[i].rm_so, len);
|
||||||
|
regex_matches[i][len] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
regex_split(char *pattern, char **subject)
|
||||||
|
{
|
||||||
|
int r = 0; regmatch_t pmatch;
|
||||||
|
regex_t *re = regex(pattern);
|
||||||
|
if (re && *subject)
|
||||||
|
{
|
||||||
|
r = regexec(re, *subject, 1, &pmatch, 0) == 0 ?-1:0;
|
||||||
|
if (r)
|
||||||
|
{
|
||||||
|
memset(*subject + pmatch.rm_so, 0, pmatch.rm_eo - pmatch.rm_so);
|
||||||
|
*subject += pmatch.rm_eo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*subject += strlen(*subject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
23
setup.c
23
setup.c
@@ -32,6 +32,7 @@ typedef struct {
|
|||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
int i, j; Client *c; Monitor *m;
|
int i, j; Client *c; Monitor *m;
|
||||||
|
|
||||||
int screen_w = WidthOfScreen(DefaultScreenOfDisplay(display));
|
int screen_w = WidthOfScreen(DefaultScreenOfDisplay(display));
|
||||||
int screen_h = HeightOfScreen(DefaultScreenOfDisplay(display));
|
int screen_h = HeightOfScreen(DefaultScreenOfDisplay(display));
|
||||||
|
|
||||||
@@ -107,9 +108,9 @@ void setup()
|
|||||||
int x = m->x, y = m->y, w = m->w, h = m->h;
|
int x = m->x, y = m->y, w = m->w, h = m->h;
|
||||||
|
|
||||||
// determine spot layout for this monitor
|
// determine spot layout for this monitor
|
||||||
int spot1_align = have_layout(i) ? layouts[i].spot1_align : LEFT ;
|
int spot1_align = have_layout(i) ? settings.layouts[i].spot1_align : LEFT ;
|
||||||
int spot1_width_pct = have_layout(i) ? layouts[i].spot1_width_pct : 66;
|
int spot1_width_pct = have_layout(i) ? settings.layouts[i].spot1_width_pct : 66;
|
||||||
int spot2_height_pct = have_layout(i) ? layouts[i].spot2_height_pct : 66;
|
int spot2_height_pct = have_layout(i) ? settings.layouts[i].spot2_height_pct : 66;
|
||||||
|
|
||||||
// monitor rotated?
|
// monitor rotated?
|
||||||
if (m->w < m->h)
|
if (m->w < m->h)
|
||||||
@@ -176,14 +177,14 @@ void setup()
|
|||||||
XFreeModifiermap(modmap);
|
XFreeModifiermap(modmap);
|
||||||
|
|
||||||
// process config.h key bindings
|
// process config.h key bindings
|
||||||
for (i = 0; i < sizeof(keys)/sizeof(Binding); i++)
|
for (i = 0; i < settings.binding_count; i++)
|
||||||
{
|
{
|
||||||
XGrabKey(display, XKeysymToKeycode(display, keys[i].key), keys[i].mod, root, True, GrabModeAsync, GrabModeAsync);
|
XGrabKey(display, XKeysymToKeycode(display, settings.bindings[i].key), settings.bindings[i].mod, root, True, GrabModeAsync, GrabModeAsync);
|
||||||
if (keys[i].mod == AnyModifier) continue;
|
if (settings.bindings[i].mod == AnyModifier) continue;
|
||||||
|
|
||||||
XGrabKey(display, XKeysymToKeycode(display, keys[i].key), keys[i].mod|LockMask, root, True, GrabModeAsync, GrabModeAsync);
|
XGrabKey(display, XKeysymToKeycode(display, settings.bindings[i].key), settings.bindings[i].mod|LockMask, root, True, GrabModeAsync, GrabModeAsync);
|
||||||
XGrabKey(display, XKeysymToKeycode(display, keys[i].key), keys[i].mod|NumlockMask, root, True, GrabModeAsync, GrabModeAsync);
|
XGrabKey(display, XKeysymToKeycode(display, settings.bindings[i].key), settings.bindings[i].mod|NumlockMask, root, True, GrabModeAsync, GrabModeAsync);
|
||||||
XGrabKey(display, XKeysymToKeycode(display, keys[i].key), keys[i].mod|LockMask|NumlockMask, root, True, GrabModeAsync, GrabModeAsync);
|
XGrabKey(display, XKeysymToKeycode(display, settings.bindings[i].key), settings.bindings[i].mod|LockMask|NumlockMask, root, True, GrabModeAsync, GrabModeAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we grab buttons to do click-to-focus. all clicks get passed through to apps.
|
// we grab buttons to do click-to-focus. all clicks get passed through to apps.
|
||||||
@@ -191,13 +192,13 @@ void setup()
|
|||||||
XGrabButton(display, Button3, AnyModifier, root, True, ButtonPressMask, GrabModeSync, GrabModeSync, None, None);
|
XGrabButton(display, Button3, AnyModifier, root, True, ButtonPressMask, GrabModeSync, GrabModeSync, None, None);
|
||||||
|
|
||||||
// create title bars
|
// create title bars
|
||||||
if (TITLE)
|
if (settings.title)
|
||||||
{
|
{
|
||||||
STACK_FREE(&windows);
|
STACK_FREE(&windows);
|
||||||
for_monitors(i, m) for_spots(j)
|
for_monitors(i, m) for_spots(j)
|
||||||
{
|
{
|
||||||
m->bars[j] = textbox_create(root, TB_AUTOHEIGHT|TB_LEFT, m->spots[j].x, m->spots[j].y, m->spots[j].w, 0,
|
m->bars[j] = textbox_create(root, TB_AUTOHEIGHT|TB_LEFT, m->spots[j].x, m->spots[j].y, m->spots[j].w, 0,
|
||||||
TITLE, TITLE_BLUR, BORDER_BLUR, NULL, NULL);
|
settings.title, settings.title_blur, settings.border_blur, NULL, NULL);
|
||||||
XSelectInput(display, m->bars[j]->window, ExposureMask);
|
XSelectInput(display, m->bars[j]->window, ExposureMask);
|
||||||
|
|
||||||
m->spots[j].y += m->bars[j]->h;
|
m->spots[j].y += m->bars[j]->h;
|
||||||
|
|||||||
16
spot.c
16
spot.c
@@ -50,24 +50,24 @@ void spot_update_bar(int spot, int mon)
|
|||||||
name = strdup(tmp);
|
name = strdup(tmp);
|
||||||
if (name)
|
if (name)
|
||||||
{
|
{
|
||||||
if (TITLE_ELLIPSIS > 0 && strlen(name) > TITLE_ELLIPSIS)
|
if (settings.title_ellipsis > 0 && strlen(name) > settings.title_ellipsis)
|
||||||
{
|
{
|
||||||
name = realloc(name, strlen(name)+4);
|
name = realloc(name, strlen(name)+4);
|
||||||
strcpy(name+TITLE_ELLIPSIS, "...");
|
strcpy(name+settings.title_ellipsis, "...");
|
||||||
}
|
}
|
||||||
len += snprintf(title+len, MAX(0, SPOT_BUFF-len), " [%d] %s ", n++, name);
|
len += snprintf(title+len, MAX(0, SPOT_BUFF-len), " [%d] %s ", n++, name);
|
||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
if (tmp) XFree(tmp);
|
if (tmp) XFree(tmp);
|
||||||
}
|
}
|
||||||
if (TITLE)
|
if (settings.title)
|
||||||
{
|
{
|
||||||
if (c && !c->full && *title && m->bars[spot])
|
if (c && !c->full && *title && m->bars[spot])
|
||||||
{
|
{
|
||||||
int focus = c->window == current || (spot == current_spot && mon == current_mon);
|
int focus = c->window == current || (spot == current_spot && mon == current_mon);
|
||||||
char *color = focus && c->window == current ? TITLE_FOCUS : TITLE_BLUR;
|
char *color = focus && c->window == current ? settings.title_focus : settings.title_blur;
|
||||||
char *border = focus && c->window == current ? BORDER_FOCUS: BORDER_BLUR;
|
char *border = focus && c->window == current ? settings.border_focus: settings.border_blur;
|
||||||
textbox_font(m->bars[spot], TITLE, color, border);
|
textbox_font(m->bars[spot], settings.title, color, border);
|
||||||
textbox_text(m->bars[spot], title);
|
textbox_text(m->bars[spot], title);
|
||||||
textbox_draw(m->bars[spot]);
|
textbox_draw(m->bars[spot]);
|
||||||
textbox_show(m->bars[spot]);
|
textbox_show(m->bars[spot]);
|
||||||
@@ -81,7 +81,7 @@ void spot_update_bar(int spot, int mon)
|
|||||||
void update_bars()
|
void update_bars()
|
||||||
{
|
{
|
||||||
int i, j; Monitor *m;
|
int i, j; Monitor *m;
|
||||||
if (TITLE) for_monitors(i, m) for_spots(j)
|
if (settings.title) for_monitors(i, m) for_spots(j)
|
||||||
spot_update_bar(j, i);
|
spot_update_bar(j, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ Window spot_try_focus_top_window(int spot, int mon, Window except)
|
|||||||
int spot_choose_by_direction(int spot, int mon, int dir)
|
int spot_choose_by_direction(int spot, int mon, int dir)
|
||||||
{
|
{
|
||||||
Monitor *m = &monitors[mon];
|
Monitor *m = &monitors[mon];
|
||||||
int spot1_align = have_layout(mon) ? layouts[mon].spot1_align : LEFT ;
|
int spot1_align = have_layout(mon) ? settings.layouts[mon].spot1_align : LEFT ;
|
||||||
|
|
||||||
if (m->w < m->h) // rotated?
|
if (m->w < m->h) // rotated?
|
||||||
{
|
{
|
||||||
|
|||||||
25
xoat.c
25
xoat.c
@@ -45,6 +45,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
@@ -53,6 +54,7 @@ Display *display;
|
|||||||
|
|
||||||
#include "atom.c"
|
#include "atom.c"
|
||||||
#include "textbox.c"
|
#include "textbox.c"
|
||||||
|
#include "regex.c"
|
||||||
|
|
||||||
#define STACK 64
|
#define STACK 64
|
||||||
#define MONITORS 3
|
#define MONITORS 3
|
||||||
@@ -98,7 +100,25 @@ typedef struct _Layout {
|
|||||||
short spot_start, spot1_align, spot1_width_pct, spot2_height_pct;
|
short spot_start, spot1_align, spot1_width_pct, spot2_height_pct;
|
||||||
} Layout;
|
} Layout;
|
||||||
|
|
||||||
#define have_layout(i) (sizeof(layouts) / sizeof(Layout) > (i))
|
typedef struct _Settings {
|
||||||
|
unsigned int border;
|
||||||
|
char *border_blur;
|
||||||
|
char *border_focus;
|
||||||
|
char *border_urgent;
|
||||||
|
unsigned int gap;
|
||||||
|
char *title;
|
||||||
|
char *title_blur;
|
||||||
|
char *title_focus;
|
||||||
|
unsigned int title_ellipsis;
|
||||||
|
|
||||||
|
unsigned int layout_count;
|
||||||
|
Layout *layouts;
|
||||||
|
|
||||||
|
unsigned int binding_count;
|
||||||
|
Binding *bindings;
|
||||||
|
} Settings;
|
||||||
|
|
||||||
|
#define have_layout(i) (settings.layout_count > (i))
|
||||||
|
|
||||||
Client* window_build_client(Window);
|
Client* window_build_client(Window);
|
||||||
void client_free(Client*);
|
void client_free(Client*);
|
||||||
@@ -161,6 +181,7 @@ short current_spot, current_mon;
|
|||||||
Window root, ewmh, current = None;
|
Window root, ewmh, current = None;
|
||||||
Stack windows;
|
Stack windows;
|
||||||
static int (*xerror)(Display *, XErrorEvent *);
|
static int (*xerror)(Display *, XErrorEvent *);
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
void catch_exit(int sig)
|
void catch_exit(int sig)
|
||||||
{
|
{
|
||||||
@@ -182,6 +203,7 @@ void exec_cmd(char *cmd)
|
|||||||
#include "spot.c"
|
#include "spot.c"
|
||||||
#include "event.c"
|
#include "event.c"
|
||||||
#include "action.c"
|
#include "action.c"
|
||||||
|
#include "config.c"
|
||||||
#include "setup.c"
|
#include "setup.c"
|
||||||
|
|
||||||
void (*handlers[LASTEvent])(XEvent*) = {
|
void (*handlers[LASTEvent])(XEvent*) = {
|
||||||
@@ -236,6 +258,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configure();
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
// main event loop
|
// main event loop
|
||||||
|
|||||||
Reference in New Issue
Block a user