summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruint23 <[email protected]>2025-05-03 09:09:09 +0100
committeruint23 <[email protected]>2025-05-03 09:09:47 +0100
commit1743a7c340ee17fb8d3e41fa2a777bcadcb1a867 (patch)
treee5e282e7f72e5581b689c75fb424f00a50779420
parent01736e075e1348c539abd7066cd0a741a61710df (diff)
update parser so binds will not overlap from pervious binds + parser is more simple
-rw-r--r--Makefile2
-rw-r--r--build/parser.obin0 -> 39960 bytes
-rw-r--r--build/sxwm.obin0 -> 141224 bytes
-rw-r--r--default_sxrc70
-rw-r--r--src/config.h260
-rw-r--r--src/defs.h58
-rw-r--r--src/parser.c508
-rw-r--r--src/parser.h7
-rw-r--r--src/sxwm.c146
-rwxr-xr-xsxwmbin0 -> 135960 bytes
10 files changed, 484 insertions, 567 deletions
diff --git a/Makefile b/Makefile
index 7c69201..2b2e550 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
CC ?= gcc
-CFLAGS ?= -std=c99 -Wall -Wextra -O3 -Isrc
+CFLAGS ?= -std=c99 -Wall -Wextra -O3 -Isrc -g
LDFLAGS ?= -lX11 -lXinerama -lXcursor
PREFIX ?= /usr/local
diff --git a/build/parser.o b/build/parser.o
new file mode 100644
index 0000000..e471159
--- /dev/null
+++ b/build/parser.o
Binary files differ
diff --git a/build/sxwm.o b/build/sxwm.o
new file mode 100644
index 0000000..d762c27
--- /dev/null
+++ b/build/sxwm.o
Binary files differ
diff --git a/default_sxrc b/default_sxrc
index f973f08..c6f96e8 100644
--- a/default_sxrc
+++ b/default_sxrc
@@ -18,54 +18,54 @@ motion_throttle : 60 # Set to screen refresh rate for smoothest motions
mod_key : super
# Application Launchers:
-bind : [mod + Return] : "st"
-bind : [mod + b] : "firefox"
-bind : [mod + p] : "dmenu_run"
+bind : mod + Return : "st"
+bind : mod + b : "firefox"
+bind : mod + p : "dmenu_run"
# Window Management:
-bind : [mod + shift + q] : close_window
-bind : [mod + shift + e] : quit
+call : mod + shift + q : close_window
+call : mod + shift + e : quit
# Focus Movement:
-bind : [mod + j] : focus_next
-bind : [mod + k] : focus_prev
+call : mod + j : focus_next
+call : mod + k : focus_prev
# Master/Stack Movement
-bind : [mod + shift + j] : master_next
-bind : [mod + shift + k] : master_previous
+call : mod + shift + j : master_next
+call : mod + shift + k : master_previous
# Master Area Resize
-bind : [mod + l] : master_increase
-bind : [mod + h] : master_decrease
+call : mod + l : master_increase
+call : mod + h : master_decrease
# Gaps
-bind : [mod + equal] : increase_gaps
-bind : [mod + minus] : decrease_gaps
+call : mod + equal : increase_gaps
+call : mod + minus : decrease_gaps
# Floating/Fullscreen
-bind : [mod + space] : toggle_floating
-bind : [mod + shift + space] : global_floating
-bind : [mod + shift + f] : fullscreen
+call : mod + space : toggle_floating
+call : mod + shift + space : global_floating
+call : mod + shift + f : fullscreen
# Reload Config
-bind : [mod + r] : reload_config
+call : mod + r : reload_config
# Workspaces (1-9)
-bind : [mod + 1] : change_ws1
-bind : [mod + shift + 1] : moveto_ws1
-bind : [mod + 2] : change_ws2
-bind : [mod + shift + 2] : moveto_ws2
-bind : [mod + 3] : change_ws3
-bind : [mod + shift + 3] : moveto_ws3
-bind : [mod + 4] : change_ws4
-bind : [mod + shift + 4] : moveto_ws4
-bind : [mod + 5] : change_ws5
-bind : [mod + shift + 5] : moveto_ws5
-bind : [mod + 6] : change_ws6
-bind : [mod + shift + 6] : moveto_ws6
-bind : [mod + 7] : change_ws7
-bind : [mod + shift + 7] : moveto_ws7
-bind : [mod + 8] : change_ws8
-bind : [mod + shift + 8] : moveto_ws8
-bind : [mod + 9] : change_ws9
-bind : [mod + shift + 9] : moveto_ws9 \ No newline at end of file
+workspace : [mod + 1] : move 1
+workspace : [mod + shift + 1] : swap 1
+workspace : [mod + 2] : move 2
+workspace : [mod + shift + 2] : swap 2
+workspace : [mod + 3] : move 3
+workspace : [mod + shift + 3] : swap 3
+workspace : [mod + 4] : move 4
+workspace : [mod + shift + 4] : swap 4
+workspace : [mod + 5] : move 5
+workspace : [mod + shift + 5] : swap 5
+workspace : [mod + 6] : move 6
+workspace : [mod + shift + 6] : swap 6
+workspace : [mod + 7] : move 7
+workspace : [mod + shift + 7] : swap 7
+workspace : [mod + 8] : move 8
+workspace : [mod + shift + 8] : swap 8
+workspace : [mod + 9] : move 9
+workspace : [mod + shift + 9] : swap 9 \ No newline at end of file
diff --git a/src/config.h b/src/config.h
index 64e664b..ccc28ea 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,211 +1,53 @@
/* See LICENSE for more information on use */
-
-/*
- * ——————————————< Appearance >—————————————— *
- *
- * In this section you can configure the
- * settings for sxwm. You can ignore the
- * #define as it is C specific syntax
- *
- * GAPS (px):
- * How many pixels between windows and
- * screen edges (including bar)
- * BORDER_WIDTH (px):
- * How thick your border is
- *
- * BORDER_FOC_COL (hex):
- * The colour of your border when the
- * window is focused
- *
- * BORDER_UFOC_COL (hex):
- * The colour of your border when the
- * window is unfocused
- *
- * MASTER_WIDTH (int):
- * % of the screen the master window
- * should take
- *
- * RESIZE_MASTER_AMT (%):
- * % of the master width you want to
- * increment by
- *
- * MOTION_THROTTLE (int):
- * Usually you should set this to your
- * screen refreshrate. This is set so
- * there is no exessive number of
- * requests being sent to the X server
- *
- * SNAP_DISTANCE (px):
- * How many pixels away from the screen
- * until the window *snaps* to the edge
- *
- * NUM_WORKSPACES (int):
- * This is how many workspaces you want in
- * this window manager. Best to leave it
- * default (9).
- *
- * WORKSPACE_NAMES (char[]):
- * This is just the label that will appear
- * on your status bar. Doesn't have to be
- * a number, it can be anything. Ignore
- * the "\0", this is just a NULL that says
- * to start again, otherwise it would be
- * all of them concatenated together.
- *
- * ———————————————————————————————————————————*
-*/
-
-#define NUM_WORKSPACES 9
-#define WORKSPACE_NAMES \
- "1" "\0"\
- "2" "\0"\
- "3" "\0"\
- "4" "\0"\
- "5" "\0"\
- "6" "\0"\
- "7" "\0"\
- "8" "\0"\
- "9" "\0"\
-
-/*
- * ————————————< Keys & Bindins >—————————————*
- *
- * This is where you set your keybinds to
- * execute apps. You can use the CMD macro
- * to make new variables.
- *
- * How do you make a command to run an app
- * It's simple! Just do this:
- *
- * CALL(appcallname, "app", "arg2", ...);
- *
- * What is appcallname? This is just the
- * variable name given to this string of
- * commands given to execvp, the function
- * that executes these programs.
- *
- * ———————————————————————————————————————————*
- *
-*/
-
-CMD(terminal, "st");
-CMD(browser, "firefox");
-
-/*
- * ———————————————< Bindings >————————————————*
- *
- * This is where you assign keybinds to
- * perform some actions.
- *
- * How do you bind keys? In sxwm, there is
- * three ways to bind keys to perform
- * tasks:
- *
- * BIND, CALL or WORKSPACE.
- * CALL, calls a function,
- * BIND, executes a specified
- * program.
- * WORKSPACE, sets the bind to move
- * and item to said workspace or to
- * change to that workspace.
- *
- * USEAGE:
- * BIND(MODIFIERS, KEY, FUNCTION)
- *
- * MODIFIERS:
- * The mod keys you want held down
- * for the task to execute. I have
- * also defined SHIFT as a substitute
- * for ShiftMask.
- *
- * KEY:
- * The key to press in combination
- * with the MODIFERS to run the task.
- *
- * FUNCTION:
- * The task to execute. Depending on
- * whether you're calling CALL or
- * BIND, this will execute a program
- * or call a function.
- *
- * If you're
- * calling a function, just put the
- * name of the funtion.
- *
- * Otherwise, put the program you
- * either defined with the CMD above
- * or you can skip that step and just
- * do something like this to create a
- * "string" in the bindings array:
- *
- * { "program", "arg1", NULL }
- *
- * End the line with a comma, as this is
- * an array.
- *
- * ———————————————————————————————————————————*
-*/
-
-/*< This is your modifier key (ALT/SUPER) >*/
+#include <X11/Xlib.h>
#include <X11/keysym.h>
-const Binding binds[] =
-{
-/*————< Mod4MaskIFIER(S) >< KEY >—————< FUNCTION >——*/
-
-/*———————< Here are your functions calls >————— — */
-
- CALL(Mod4Mask|SHIFT, e, quit),
- CALL(Mod4Mask|SHIFT, q, close_focused),
-
- CALL(Mod4Mask, j, focus_next),
- CALL(Mod4Mask, k, focus_prev),
-
- CALL(Mod4Mask|SHIFT, j, move_master_next),
- CALL(Mod4Mask|SHIFT, k, move_master_prev),
-
- CALL(Mod4Mask, l, resize_master_add),
- CALL(Mod4Mask, h, resize_master_sub),
-
- CALL(Mod4Mask, equal, inc_gaps),
- CALL(Mod4Mask, minus, dec_gaps),
-
- CALL(Mod4Mask, space, toggle_floating),
- CALL(Mod4Mask|SHIFT, space, toggle_floating_global),
-
- CALL(Mod4Mask|SHIFT, f, toggle_fullscreen),
-
-/*—————< Here are your executable functions >—————*/
-
- BIND(Mod4Mask, Return, terminal),
- BIND(Mod4Mask, b, browser),
-
-/*—————< This is for workspaces >—————————————————*/
-
- CALL(Mod4Mask, 1, change_ws1),
- CALL(Mod4Mask|SHIFT, 1, moveto_ws1),
-
- CALL(Mod4Mask, 2, change_ws2),
- CALL(Mod4Mask|SHIFT, 2, moveto_ws2),
-
- CALL(Mod4Mask, 3, change_ws3),
- CALL(Mod4Mask|SHIFT, 3, moveto_ws3),
-
- CALL(Mod4Mask, 4, change_ws4),
- CALL(Mod4Mask|SHIFT, 4, moveto_ws4),
-
- CALL(Mod4Mask, 5, change_ws5),
- CALL(Mod4Mask|SHIFT, 5, moveto_ws5),
-
- CALL(Mod4Mask, 6, change_ws6),
- CALL(Mod4Mask|SHIFT, 6, moveto_ws6),
-
- CALL(Mod4Mask, 7, change_ws7),
- CALL(Mod4Mask|SHIFT, 7, moveto_ws7),
-
- CALL(Mod4Mask, 8, change_ws8),
- CALL(Mod4Mask|SHIFT, 8, moveto_ws8),
-
- CALL(Mod4Mask, 9, change_ws9),
- CALL(Mod4Mask|SHIFT, 9, moveto_ws9),
-
-};
+#include "defs.h"
+
+CMD(terminal, "st");
+CMD(browser, "firefox");
+
+const Binding binds[] = {
+ {Mod4Mask | ShiftMask, XK_e, {.fn = quit}, TYPE_FUNC},
+ {Mod4Mask | ShiftMask, XK_q, {.fn = close_focused}, TYPE_FUNC},
+
+ {Mod4Mask, XK_j, {.fn = focus_next}, TYPE_FUNC},
+ {Mod4Mask, XK_k, {.fn = focus_prev}, TYPE_FUNC},
+
+ {Mod4Mask | ShiftMask, XK_j, {.fn = move_master_next}, TYPE_FUNC},
+ {Mod4Mask | ShiftMask, XK_k, {.fn = move_master_prev}, TYPE_FUNC},
+
+ {Mod4Mask, XK_l, {.fn = resize_master_add}, TYPE_FUNC},
+ {Mod4Mask, XK_h, {.fn = resize_master_sub}, TYPE_FUNC},
+
+ {Mod4Mask, XK_equal, {.fn = inc_gaps}, TYPE_FUNC},
+ {Mod4Mask, XK_minus, {.fn = dec_gaps}, TYPE_FUNC},
+
+ {Mod4Mask, XK_space, {.fn = toggle_floating}, TYPE_FUNC},
+ {Mod4Mask | ShiftMask, XK_space, {.fn = toggle_floating_global}, TYPE_FUNC},
+ {Mod4Mask | ShiftMask, XK_f, {.fn = toggle_fullscreen}, TYPE_FUNC},
+
+ {Mod4Mask, XK_Return, {.cmd = terminal}, TYPE_CMD},
+ {Mod4Mask, XK_b, {.cmd = browser}, TYPE_CMD},
+ {Mod4Mask, XK_p, {.cmd = (const char *[]){"dmenu_run", NULL}}, TYPE_CMD},
+
+ {Mod4Mask, XK_r, {.fn = reload_config}, TYPE_FUNC},
+
+ {Mod4Mask, XK_1, {.ws = 0}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_1, {.ws = 0}, TYPE_MWKSP},
+ {Mod4Mask, XK_2, {.ws = 1}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_2, {.ws = 1}, TYPE_MWKSP},
+ {Mod4Mask, XK_3, {.ws = 2}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_3, {.ws = 2}, TYPE_MWKSP},
+ {Mod4Mask, XK_4, {.ws = 3}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_4, {.ws = 3}, TYPE_MWKSP},
+ {Mod4Mask, XK_5, {.ws = 4}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_5, {.ws = 4}, TYPE_MWKSP},
+ {Mod4Mask, XK_6, {.ws = 5}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_6, {.ws = 5}, TYPE_MWKSP},
+ {Mod4Mask, XK_7, {.ws = 6}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_7, {.ws = 6}, TYPE_MWKSP},
+ {Mod4Mask, XK_8, {.ws = 7}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_8, {.ws = 7}, TYPE_MWKSP},
+ {Mod4Mask, XK_9, {.ws = 8}, TYPE_CWKSP},
+ {Mod4Mask | ShiftMask, XK_9, {.ws = 8}, TYPE_MWKSP},
+}; \ No newline at end of file
diff --git a/src/defs.h b/src/defs.h
index 9257fbc..174ae27 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -1,5 +1,6 @@
/* See LICENSE for more information on use */
#pragma once
+#include <X11/Xlib.h>
#define SXWM_VERSION "sxwm ver. 1.4"
#define SXWM_AUTHOR "(C) Abhinav Prasai 2025"
#define SXWM_LICINFO "See LICENSE for more info"
@@ -22,46 +23,22 @@
#define CMD(name, ...) \
const char *name[] = { __VA_ARGS__, NULL }
+#define TYPE_CWKSP 0
+#define TYPE_MWKSP 1
+#define TYPE_FUNC 2
+#define TYPE_CMD 3
-#include <X11/Xlib.h>
-#define INIT_WORKSPACE \
-void change_ws1(void);\
-void moveto_ws1(void);\
-void change_ws2(void);\
-void moveto_ws2(void);\
-void change_ws3(void);\
-void moveto_ws3(void);\
-void change_ws4(void);\
-void moveto_ws4(void);\
-void change_ws5(void);\
-void moveto_ws5(void);\
-void change_ws6(void);\
-void moveto_ws6(void);\
-void change_ws7(void);\
-void moveto_ws7(void);\
-void change_ws8(void);\
-void moveto_ws8(void);\
-void change_ws9(void);\
-void moveto_ws9(void);\
-void change_ws1(void) { change_workspace(0); update_net_client_list(); } \
-void moveto_ws1(void) { move_to_workspace(0); update_net_client_list(); }\
-void change_ws2(void) { change_workspace(1); update_net_client_list(); } \
-void moveto_ws2(void) { move_to_workspace(1); update_net_client_list(); }\
-void change_ws3(void) { change_workspace(2); update_net_client_list(); } \
-void moveto_ws3(void) { move_to_workspace(2); update_net_client_list(); }\
-void change_ws4(void) { change_workspace(3); update_net_client_list(); } \
-void moveto_ws4(void) { move_to_workspace(3); update_net_client_list(); }\
-void change_ws5(void) { change_workspace(4); update_net_client_list(); } \
-void moveto_ws5(void) { move_to_workspace(4); update_net_client_list(); }\
-void change_ws6(void) { change_workspace(5); update_net_client_list(); } \
-void moveto_ws6(void) { move_to_workspace(5); update_net_client_list(); }\
-void change_ws7(void) { change_workspace(6); update_net_client_list(); } \
-void moveto_ws7(void) { move_to_workspace(6); update_net_client_list(); }\
-void change_ws8(void) { change_workspace(7); update_net_client_list(); } \
-void moveto_ws8(void) { move_to_workspace(7); update_net_client_list(); }\
-void change_ws9(void) { change_workspace(8); update_net_client_list(); } \
-void moveto_ws9(void) { move_to_workspace(8); update_net_client_list(); }\
-
+#define NUM_WORKSPACES 9
+#define WORKSPACE_NAMES \
+ "1" "\0"\
+ "2" "\0"\
+ "3" "\0"\
+ "4" "\0"\
+ "5" "\0"\
+ "6" "\0"\
+ "7" "\0"\
+ "8" "\0"\
+ "9" "\0"\
typedef enum {
DRAG_NONE,
@@ -75,13 +52,14 @@ typedef void (*EventHandler)(XEvent *);
typedef union {
const char **cmd;
void (*fn)(void);
+ int ws;
} Action;
typedef struct {
int mods;
KeySym keysym;
Action action;
- Bool is_func;
+ int type;
} Binding;
typedef struct Client{
diff --git a/src/parser.c b/src/parser.c
index d2efba7..7cf7b18 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,267 +1,323 @@
-/* See LICENSE for more information on use */
-#define _POSIX_C_SOURCE 200809L /* for strdup */
+#define _POSIX_C_SOURCE 200809L
#include <ctype.h>
-#include <linux/limits.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
#include <X11/keysym.h>
-#include <X11/keysymdef.h>
#include "parser.h"
-#define MAX_LINE 512
+#include "defs.h"
-static const struct { const char *name; void (*fn)(void); } call_table[] = {
- { "close_window", close_focused },
- { "decrease_gaps", dec_gaps },
- { "focus_next", focus_next },
- { "focus_previous", focus_prev },
- { "increase_gaps", inc_gaps },
- { "master_next", move_master_next },
- { "master_previous", move_master_prev },
- { "quit", quit },
- { "reload_config", reload_config },
- { "master_increase", resize_master_add },
- { "master_decrease", resize_master_sub },
- { "toggle_floating", toggle_floating },
- { "global_floating", toggle_floating_global },
- { "fullscreen", toggle_fullscreen },
- { NULL, NULL }
-};
+static const struct {
+ const char *name;
+ void (*fn)(void);
+} call_table[] = {{"close_window", close_focused},
+ {"decrease_gaps", dec_gaps},
+ {"focus_next", focus_next},
+ {"focus_prev", focus_prev},
+ {"increase_gaps", inc_gaps},
+ {"master_next", move_master_next},
+ {"master_previous", move_master_prev},
+ {"quit", quit},
+ {"reload_config", reload_config},
+ {"master_increase", resize_master_add},
+ {"master_decrease", resize_master_sub},
+ {"toggle_floating", toggle_floating},
+ {"global_floating", toggle_floating_global},
+ {"fullscreen", toggle_fullscreen},
+ {NULL, NULL}};
-/* helpers */
-static char*
-strip(char *s)
+static void remap_and_dedupe_binds(Config *cfg)
{
- while (isspace((unsigned char)*s)) s++;
- if (!*s) return s;
- char *end = s + strlen(s) - 1;
- while (end > s && isspace((unsigned char)*end)) *end-- = '\0';
- return s;
+ for (int i = 0; i < cfg->bindsn; i++) {
+ Binding *b = &cfg->binds[i];
+ if (b->mods & (Mod1Mask | Mod4Mask)) {
+ unsigned others = b->mods & ~(Mod1Mask | Mod4Mask);
+ b->mods = others | cfg->modkey;
+ }
+ }
+
+ for (int i = 0; i < cfg->bindsn; i++) {
+ for (int j = i + 1; j < cfg->bindsn; j++) {
+ if (cfg->binds[i].mods == cfg->binds[j].mods && cfg->binds[i].keysym == cfg->binds[j].keysym) {
+ memmove(&cfg->binds[j], &cfg->binds[j + 1], sizeof(Binding) * (cfg->bindsn - j - 1));
+ cfg->bindsn--;
+ j--;
+ }
+ }
+ }
}
-static char*
-strip_quotes(char *s)
+static char *strip(char *s)
{
- size_t len = strlen(s);
- if (len > 0 && s[0] == '"') {
- s++;
- len--;
- }
- if (len > 0 && s[len-1] == '"') {
- s[len-1] = '\0';
- }
- return s;
+ while (*s && isspace((unsigned char)*s)) {
+ s++;
+ }
+ char *e = s + strlen(s) - 1;
+ while (e > s && isspace((unsigned char)*e)) {
+ *e-- = '\0';
+ }
+ return s;
}
-static const char** build_argv(char *cmdline)
+static char *strip_quotes(char *s)
{
- char **argv = calloc(MAX_ARGS + 1, sizeof(char *));
- if (!argv) return NULL;
-
- int argc = 0;
- char *tok = strtok(cmdline, " \t");
- while (tok && argc < MAX_ARGS) {
- argv[argc++] = strdup(tok);
- tok = strtok(NULL, " \t");
- }
- argv[argc] = NULL;
- return (const char **)argv;
+ size_t L = strlen(s);
+ if (L > 0 && s[0] == '"') {
+ s++;
+ L--;
+ }
+ if (L > 0 && s[L - 1] == '"') {
+ s[L - 1] = '\0';
+ }
+ return s;
}
-unsigned int
-parse_mods(const char *mods, Config *user_config)
+static Binding *alloc_bind(Config *cfg, unsigned mods, KeySym ks)
{
- unsigned int m = 0;
- char buf[MAX_LINE];
- strncpy(buf, mods, sizeof(buf)-1);
- buf[sizeof(buf)-1] = '\0';
-
- for (char *tok = strtok(buf, "+"); tok; tok = strtok(NULL, "+")) {
- for (char *p = tok; *p; p++) *p = tolower((unsigned char)*p);
- if (strcmp(tok, "mod") == 0) m |= user_config->modkey;
- else if (strcmp(tok, "shift") == 0) m |= ShiftMask;
- else if (strcmp(tok, "ctrl") == 0) m |= ControlMask;
- else if (strcmp(tok, "alt") == 0) m |= Mod1Mask;
- else if (strcmp(tok, "super") == 0) m |= Mod4Mask;
- }
- return m;
+ for (int i = 0; i < cfg->bindsn; i++) {
+ if (cfg->binds[i].mods == (int)mods && cfg->binds[i].keysym == ks) {
+ return &cfg->binds[i];
+ }
+ }
+ if (cfg->bindsn >= 256) {
+ return NULL;
+ }
+ Binding *b = &cfg->binds[cfg->bindsn++];
+ b->mods = mods;
+ b->keysym = ks;
+ return b;
}
-KeySym
-parse_keysym(const char *key)
+static unsigned parse_combo(const char *combo, Config *cfg, KeySym *out_ks)
{
- char buf[64];
- size_t len = strlen(key);
- if (len >= sizeof(buf)) len = sizeof(buf) - 1;
-
- if (len == 1) {
- buf[0] = key[0];
- buf[1] = '\0';
- } else {
- buf[0] = toupper((unsigned char)key[0]);
- for (size_t i = 1; i < len; i++)
- buf[i] = tolower((unsigned char)key[i]);
- buf[len] = '\0';
- }
-
- KeySym ks = XStringToKeysym(buf);
- if (ks == NoSymbol) {
- for (size_t i = 0; i < len; i++)
- buf[i] = toupper((unsigned char)key[i]);
- buf[len] = '\0';
- ks = XStringToKeysym(buf);
- }
- if (ks == NoSymbol)
- fprintf(stderr, "sxwmrc: unknown keysym '%s'\n", key);
- return ks;
+ unsigned m = 0;
+ KeySym ks = NoSymbol;
+ char buf[256];
+ strncpy(buf, combo, sizeof buf - 1);
+ for (char *p = buf; *p; p++) {
+ if (*p == '+' || isspace((unsigned char)*p)) {
+ *p = '+';
+ }
+ }
+ buf[sizeof buf - 1] = '\0';
+ for (char *tok = strtok(buf, "+"); tok; tok = strtok(NULL, "+")) {
+ for (char *q = tok; *q; q++) {
+ *q = tolower((unsigned char)*q);
+ }
+ if (!strcmp(tok, "mod")) {
+ m |= cfg->modkey;
+ } else if (!strcmp(tok, "shift")) {
+ m |= ShiftMask;
+ } else if (!strcmp(tok, "ctrl")) {
+ m |= ControlMask;
+ } else if (!strcmp(tok, "alt")) {
+ m |= Mod1Mask;
+ } else if (!strcmp(tok, "super")) {
+ m |= Mod4Mask;
+ } else {
+ ks = parse_keysym(tok);
+ }
+ }
+ *out_ks = ks;
+ return m;
}
-void
-handler(char *command, char *arg, int mods, KeySym keysym, Action action,
- Bool is_func, Config *user_config)
+int parser(Config *cfg)
{
- if (strcmp(command, "bind") == 0) {
- /* check if binding already exists */
- int slot = user_config->bindsn;
- for (int i = 0; i < user_config->bindsn; i++) {
- if (user_config->binds[i].mods == mods &&
- user_config->binds[i].keysym == keysym) {
- slot = i;
- break;
- }
- }
+ char path[PATH_MAX];
+ const char *home = getenv("HOME");
+ if (!home) {
+ fputs("sxwmrc: HOME not set\n", stderr);
+ return -1;
+ }
+ snprintf(path, sizeof path, "%s/.config/sxwmrc", home);
+ FILE *f = fopen(path, "r");
+ if (!f) {
+ fprintf(stderr, "sxwmrc: cannot open %s\n", path);
+ return -1;
+ }
- if (slot == user_config->bindsn)
- user_config->bindsn++;
+ char line[512];
+ int lineno = 0;
+ while (fgets(line, sizeof line, f)) {
+ lineno++;
+ char *s = strip(line);
+ if (!*s || *s == '#') {
+ continue;
+ }
- Binding *b = &user_config->binds[slot];
- b->mods = mods;
- b->keysym = keysym;
- b->is_func = is_func;
+ char *sep = strchr(s, ':');
+ if (!sep) {
+ fprintf(stderr, "sxwmrc:%d: missing ':'\n", lineno);
+ continue;
+ }
+ *sep = '\0';
+ char *key = strip(s);
+ char *rest = strip(sep + 1);
- if (is_func) {
- for (size_t j = 0; call_table[j].name; j++) {
- if (strcmp(arg, call_table[j].name) == 0) {
- b->action.fn = call_table[j].fn;
- break;
- }
- }
- } else {
- b->action.cmd = action.cmd;
- }
- return;
- }
+ if (!strcmp(key, "mod_key")) {
+ unsigned m = parse_mods(rest, cfg);
+ if (m & (Mod1Mask | Mod4Mask)) {
+ cfg->modkey = m;
+ } else {
+ fprintf(stderr, "sxwmrc:%d: unknown mod_key '%s'\n", lineno, rest);
+ }
+ } else if (!strcmp(key, "gaps")) {
+ cfg->gaps = atoi(rest);
+ } else if (!strcmp(key, "border_width")) {
+ cfg->border_width = atoi(rest);
+ } else if (!strcmp(key, "focused_border_colour")) {
+ cfg->border_foc_col = parse_col(rest);
+ } else if (!strcmp(key, "unfocused_border_colour")) {
+ cfg->border_ufoc_col = parse_col(rest);
+ } else if (!strcmp(key, "swap_border_colour")) {
+ cfg->border_swap_col = parse_col(rest);
+ } else if (!strcmp(key, "master_width")) {
+ cfg->master_width = atoi(rest) / 100.0f;
+ } else if (!strcmp(key, "motion_throttle")) {
+ cfg->motion_throttle = atoi(rest);
+ } else if (!strcmp(key, "resize_master_amount")) {
+ cfg->resize_master_amt = atoi(rest);
+ } else if (!strcmp(key, "snap_distance")) {
+ cfg->snap_distance = atoi(rest);
+ } else if (!strcmp(key, "call") || !strcmp(key, "bind")) {
+ char *mid = strchr(rest, ':');
+ if (!mid) {
+ fprintf(stderr, "sxwmrc:%d: '%s' missing action\n", lineno, key);
+ continue;
+ }
+ *mid = '\0';
+ char *combo = strip(rest);
+ char *act = strip(mid + 1);
- if (strcmp(command, "gaps") == 0) user_config->gaps = atoi(arg);
- else if (strcmp(command, "border_width") == 0) user_config->border_width = atoi(arg);
- else if (strcmp(command, "focused_border_colour") == 0) user_config->border_foc_col = parse_col(arg);
- else if (strcmp(command, "unfocused_border_colour") == 0) user_config->border_ufoc_col = parse_col(arg);
- else if (strcmp(command, "swap_border_colour") == 0) user_config->border_swap_col = parse_col(arg);
- else if (strcmp(command, "master_width") == 0) user_config->master_width = atoi(arg) / 100.0f;
- else if (strcmp(command, "motion_throttle") == 0) user_config->motion_throttle = atoi(arg);
- else if (strcmp(command, "resize_master_amount") == 0) user_config->resize_master_amt = atoi(arg);
- else if (strcmp(command, "snap_distance") == 0) user_config->snap_distance = atoi(arg);
- else if (strcmp(command, "mod_key") == 0) user_config->modkey = parse_mods(arg, user_config);
- else
- fprintf(stderr, "sxwmrc: unknown setting '%s'\n", command);
-}
-int
-parser(Config *user_config)
-{
- char *home = getenv("HOME");
- if (!home) {
- fputs("sxwmrc: HOME not set\n", stderr);
- return -1;
- }
+ KeySym ks;
+ unsigned mods = parse_combo(combo, cfg, &ks);
+ if (ks == NoSymbol) {
+ fprintf(stderr, "sxwmrc:%d: bad key in '%s'\n", lineno, combo);
+ continue;
+ }
+ Binding *b = alloc_bind(cfg, mods, ks);
+ if (!b) {
+ fputs("sxwm: too many binds\n", stderr);
+ break;
+ }
- char path[PATH_MAX];
- snprintf(path, sizeof(path), "%s/.config/sxwmrc", home);
- FILE *f = fopen(path, "r");
- if (!f) {
- fprintf(stderr, "sxwmrc: cannot open '%s'\n", path);
- return -1;
- }
+ if (*act == '"' && !strcmp(key, "bind")) {
+ b->type = TYPE_CMD;
+ b->action.cmd = build_argv(strip_quotes(act));
+ } else {
+ b->type = TYPE_FUNC;
+ Bool found = False;
+ for (int i = 0; call_table[i].name; i++) {
+ if (!strcmp(act, call_table[i].name)) {
+ b->action.fn = call_table[i].fn;
+ found = True;
+ break;
+ }
+ }
+ if (!found) {
+ fprintf(stderr, "sxwmrc:%d: unknown function '%s'\n", lineno, act);
+ }
+ }
+ } else if (!strcmp(key, "workspace")) {
+ char *mid = strchr(rest, ':');
+ if (!mid) {
+ fprintf(stderr, "sxwmrc:%d: workspace missing action\n", lineno);
+ continue;
+ }
+ *mid = '\0';
+ char *combo = strip(rest);
+ char *act = strip(mid + 1);
- char line[MAX_LINE];
- int lineno = 0;
- while (fgets(line, sizeof(line), f)) {
- lineno++;
- char *s = strip(line);
- if (!*s || *s == '#') continue;
+ KeySym ks;
+ unsigned mods = parse_combo(combo, cfg, &ks);
+ if (ks == NoSymbol) {
+ fprintf(stderr, "sxwmrc:%d: bad key in '%s'\n", lineno, combo);
+ continue;
+ }
+ Binding *b = alloc_bind(cfg, mods, ks);
+ if (!b) {
+ fputs("sxwm: too many binds\n", stderr);
+ break;
+ }
- /* split key : value */
- char *sep = strchr(s, ':');
- if (!sep) {
- fprintf(stderr, "sxwmrc:%d: missing ':'\n", lineno);
- continue;
- }
- *sep = '\0';
- char *key = strip(s);
- char *val = strip(sep + 1);
+ int n;
+ if (sscanf(act, "move %d", &n) == 1 && n >= 1 && n <= NUM_WORKSPACES) {
+ b->type = TYPE_CWKSP;
+ b->action.ws = n - 1;
+ } else if (sscanf(act, "swap %d", &n) == 1 && n >= 1 && n <= NUM_WORKSPACES) {
+ b->type = TYPE_MWKSP;
+ b->action.ws = n - 1;
+ } else {
+ fprintf(stderr, "sxwmrc:%d: invalid workspace action '%s'\n", lineno, act);
+ }
+ } else {
+ fprintf(stderr, "sxwmrc:%d: unknown option '%s'\n", lineno, key);
+ }
+ }
- if (strcmp(key, "bind") == 0) {
- /* bind parsing */
- char *mid = strchr(val, ':');
- if (!mid) {
- fprintf(stderr, "sxwmrc:%d: bind missing action\n", lineno);
- continue;
- }
- *mid = '\0';
- char *combo = strip(val);
- char *act = strip(mid + 1);
+ fclose(f);
+ remap_and_dedupe_binds(cfg);
+ return 0;
+}
- if (*combo == '[') {
- combo++;
- }
- size_t L = strlen(combo);
- if (L && combo[L-1] == ']') {
- combo[L-1] = '\0';
- }
+int parse_mods(const char *mods, Config *cfg)
+{
+ KeySym dummy;
+ return parse_combo(mods, cfg, &dummy);
+}
- /* parse mods & key */
- unsigned int mods = 0;
- char key_part[64] = {0};
- char tokbuf[MAX_LINE];
- strncpy(tokbuf, combo, sizeof(tokbuf)-1);
- tokbuf[sizeof(tokbuf)-1] = '\0';
+KeySym parse_keysym(const char *key)
+{
+ KeySym ks = XStringToKeysym(key);
+ if (ks != NoSymbol) {
+ return ks;
+ }
- for (char *tok = strtok(tokbuf, "+"); tok; tok = strtok(NULL, "+")) {
- char *p = strip(tok);
- for (char *c = p; *c; c++) *c = tolower((unsigned char)*c);
- if (strcmp(p, "mod") == 0) mods |= user_config->modkey;
- else if (strcmp(p, "shift") == 0) mods |= ShiftMask;
- else if (strcmp(p, "ctrl") == 0) mods |= ControlMask;
- else if (strcmp(p, "alt") == 0) mods |= Mod1Mask;
- else if (strcmp(p, "super") == 0) mods |= Mod4Mask;
- else strncpy(key_part, p, sizeof(key_part)-1);
- }
+ char buf[64];
+ size_t n = strlen(key);
+ if (n >= sizeof buf) {
+ n = sizeof buf - 1;
+ }
- KeySym ks = parse_keysym(key_part);
- if (!ks) continue;
+ buf[0] = toupper((unsigned char)key[0]);
+ for (size_t i = 1; i < n; i++) {
+ buf[i] = tolower((unsigned char)key[i]);
+ }
+ buf[n] = '\0';
+ ks = XStringToKeysym(buf);
+ if (ks != NoSymbol) {
+ return ks;
+ }
- Action a = { .cmd = NULL };
- Bool is_fn = False;
- if (*act == '"') {
- char act_buf[MAX_LINE];
- strncpy(act_buf, strip_quotes(act), sizeof(act_buf)-1);
- act_buf[sizeof(act_buf)-1] = '\0';
- a.cmd = build_argv(act_buf);
- fprintf(stderr, "[DEBUG parser] Parsed bind: mods=0x%x, keysym=0x%lx, cmd='%s'\n", mods, ks, act);
- } else {
- is_fn = True;
- fprintf(stderr, "[DEBUG parser] Parsed bind: mods=0x%x, keysym=0x%lx, func='%s'\n", mods, ks, act);
- }
+ for (size_t i = 0; i < n; i++) {
+ buf[i] = toupper((unsigned char)key[i]);
+ }
+ buf[n] = '\0';
+ ks = XStringToKeysym(buf);
+ if (ks != NoSymbol) {
+ return ks;
+ }
- handler("bind", act, mods, ks, a, is_fn, user_config);
+ fprintf(stderr, "sxwmrc: unknown keysym '%s'\n", key);
+ return NoSymbol;
+}
- } else {
- /* normal settings */
- handler(key, val, 0, 0, (Action){ .cmd = NULL }, False, user_config);
- }
- }
+const char **build_argv(const char *cmd)
+{
+ char *dup = strdup(cmd);
+ char *saveptr, *tok;
+ const char **argv = malloc(MAX_ARGS * sizeof *argv);
+ int i = 0;
- fclose(f);
- return 0;
-}
+ for (tok = strtok_r(dup, " \t", &saveptr); tok && i < MAX_ARGS - 1; tok = strtok_r(NULL, " \t", &saveptr)) {
+ if (*tok) {
+ argv[i++] = strdup(tok);
+ }
+ }
+ argv[i] = NULL;
+ free(dup);
+ return argv;
+} \ No newline at end of file
diff --git a/src/parser.h b/src/parser.h
index 15f82d0..2e132fe 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -1,9 +1,8 @@
-/* See LICENSE for more information on use */
#pragma once
#include "defs.h"
#define MAX_ARGS 64
-void handler(char *command, char *arg, int mods, KeySym keysym, Action action, Bool is_func, Config *user_config);
+const char **build_argv(const char *cmd);
int parser(Config *user_config);
-unsigned int parse_mods(const char *mods, Config *user_config);
-KeySym parse_keysym(const char *key);
+int parse_mods(const char *mods, Config *user_config);
+KeySym parse_keysym(const char *key); \ No newline at end of file
diff --git a/src/sxwm.c b/src/sxwm.c
index 3f3050d..6cf6d4b 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -83,7 +83,6 @@ void update_net_client_list(void);
void update_struts(void);
int xerr(Display *dpy, XErrorEvent *ee);
void xev_case(XEvent *xev);
-INIT_WORKSPACE
#include "config.h"
Atom atom_net_current_desktop;
@@ -155,7 +154,7 @@ Client *add_client(Window w, int ws)
focused = c;
}
- ++open_windows;
+ open_windows++;
XSelectInput(dpy, w,
EnterWindowMask | LeaveWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask);
@@ -176,7 +175,7 @@ Client *add_client(Window w, int ws)
/* need better way to determine mon */
int cx = c->x + c->w / 2, cy = c->y + c->h / 2;
c->mon = 0;
- for (int i = 0; i < monsn; ++i) {
+ for (int i = 0; i < monsn; i++) {
if (cx >= mons[i].x && cx < mons[i].x + mons[i].w && cy >= mons[i].y && cy < mons[i].y + mons[i].h) {
c->mon = i;
break;
@@ -236,7 +235,7 @@ void close_focused(void)
Atom *protos;
int n;
if (XGetWMProtocols(dpy, focused->win, &protos, &n) && protos) {
- for (int i = 0; i < n; ++i)
+ for (int i = 0; i < n; i++)
if (protos[i] == atom_wm_delete) {
XEvent ev = {.xclient = {.type = ClientMessage,
.window = focused->win,
@@ -258,7 +257,7 @@ void close_focused(void)
void dec_gaps(void)
{
if (user_config.gaps > 0) {
- --user_config.gaps;
+ user_config.gaps--;
tile();
update_borders();
}
@@ -305,7 +304,7 @@ void focus_prev(void)
int get_monitor_for(Client *c)
{
int cx = c->x + c->w / 2, cy = c->y + c->h / 2;
- for (int i = 0; i < monsn; ++i) {
+ for (int i = 0; i < monsn; i++) {
if (cx >= (int)mons[i].x && cx < mons[i].x + mons[i].w && cy >= (int)mons[i].y && cy < mons[i].y + mons[i].h)
return i;
}
@@ -314,17 +313,29 @@ int get_monitor_for(Client *c)
void grab_keys(void)
{
- KeyCode keycode;
- int modifiers[] = {0, LockMask, Mod2Mask, LockMask | Mod2Mask};
-
+ const int guards[] = {0,
+ LockMask,
+ Mod2Mask,
+ LockMask | Mod2Mask,
+ Mod5Mask,
+ LockMask | Mod5Mask,
+ Mod2Mask | Mod5Mask,
+ LockMask | Mod2Mask | Mod5Mask};
XUngrabKey(dpy, AnyKey, AnyModifier, root);
- for (int i = 0; i < user_config.bindsn; ++i) {
- if ((keycode = XKeysymToKeycode(dpy, user_config.binds[i].keysym))) {
- for (unsigned int j = 0; j < LENGTH(modifiers); ++j) {
- XGrabKey(dpy, keycode, user_config.binds[i].mods | modifiers[j], root, True, GrabModeAsync,
- GrabModeAsync);
- }
- }
+
+ for (int i = 0; i < user_config.bindsn; i++) {
+ Binding *b = &user_config.binds[i];
+
+ if ((b->type == TYPE_CWKSP && b->mods != user_config.modkey) ||
+ (b->type == TYPE_MWKSP && b->mods != (user_config.modkey | ShiftMask)))
+ continue;
+
+ KeyCode kc = XKeysymToKeycode(dpy, b->keysym);
+ if (!kc)
+ continue;
+
+ for (size_t g = 0; g < sizeof guards / sizeof *guards; g++)
+ XGrabKey(dpy, kc, b->mods | guards[g], root, True, GrabModeAsync, GrabModeAsync);
}
}
@@ -440,7 +451,7 @@ void hdl_client_msg(XEvent *xev)
if (xev->xclient.message_type == XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False)) {
Window target = xev->xclient.data.l[0];
- for (int ws = 0; ws < NUM_WORKSPACES; ++ws) {
+ for (int ws = 0; ws < NUM_WORKSPACES; ws++) {
for (Client *c = workspaces[ws]; c; c = c->next) {
if (c->win == target) {
/* do NOT move to current ws */
@@ -472,7 +483,7 @@ void hdl_config_req(XEvent *xev)
XConfigureRequestEvent *e = &xev->xconfigurerequest;
Client *c = NULL;
- for (int ws = 0; ws < NUM_WORKSPACES && !c; ++ws)
+ for (int ws = 0; ws < NUM_WORKSPACES && !c; ws++)
for (c = workspaces[ws]; c; c = c->next)
if (c->win == e->window) {
break;
@@ -532,7 +543,7 @@ void hdl_destroy_ntf(XEvent *xev)
free(c);
update_net_client_list();
- --open_windows;
+ open_windows--;
}
tile();
@@ -561,16 +572,28 @@ void hdl_enter(XEvent *xev)
void hdl_keypress(XEvent *xev)
{
- KeySym keysym = XLookupKeysym(&xev->xkey, 0);
- unsigned int mods = clean_mask(xev->xkey.state);
-
- for (int i = 0; i < user_config.bindsn; ++i) {
- if (keysym == user_config.binds[i].keysym && mods == (unsigned int)clean_mask(user_config.binds[i].mods)) {
- if (user_config.binds[i].is_func) {
- user_config.binds[i].action.fn();
- }
- else {
- spawn(user_config.binds[i].action.cmd);
+ KeySym ks = XkbKeycodeToKeysym(dpy, xev->xkey.keycode, 0, 0);
+ int mods = clean_mask(xev->xkey.state);
+
+ for (int i = 0; i < user_config.bindsn; i++) {
+ Binding *b = &user_config.binds[i];
+ if (b->keysym == ks && clean_mask(b->mods) == mods) {
+ switch (b->type) {
+ case TYPE_CMD:
+ spawn(b->action.cmd);
+ break;
+ case TYPE_FUNC:
+ if (b->action.fn)
+ b->action.fn();
+ break;
+ case TYPE_CWKSP:
+ change_workspace(b->action.ws);
+ update_net_client_list();
+ break;
+ case TYPE_MWKSP:
+ move_to_workspace(b->action.ws);
+ update_net_client_list();
+ break;
}
return;
}
@@ -622,8 +645,8 @@ void hdl_map_req(XEvent *xev)
XMapRequestEvent *me = &xev->xmaprequest;
Window w = me->window;
- /* if we already manage it, only map if it’s on the current workspace */
- for (int ws = 0; ws < NUM_WORKSPACES; ++ws) {
+ /* only manage if on current ws */
+ for (int ws = 0; ws < NUM_WORKSPACES; ws++) {
for (Client *c = workspaces[ws]; c; c = c->next) {
if (c->win == w) {
if (c->ws == current_ws)
@@ -656,7 +679,7 @@ void hdl_map_req(XEvent *xev)
Atom splash = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
Atom popup = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False);
- for (unsigned long i = 0; i < nitems; ++i) {
+ for (unsigned long i = 0; i < nitems; i++) {
if (types[i] == dock) {
XFree(types);
XMapWindow(dpy, w);
@@ -735,7 +758,7 @@ void hdl_motion(XEvent *xev)
unsigned int mask;
XQueryPointer(dpy, root, &root_ret, &child, &rx, &ry, &wx, &wy, &mask);
- static Client *last_swap_target = NULL;
+ Client *last_swap_target = NULL;
Client *new_target = NULL;
for (Client *c = workspaces[current_ws]; c; c = c->next) {
@@ -839,7 +862,7 @@ void update_struts(void)
if (!XQueryTree(dpy, root, &root_ret, &parent_ret, &children, &nchildren))
return;
- for (unsigned int i = 0; i < nchildren; ++i) {
+ for (unsigned int i = 0; i < nchildren; i++) {
Window w = children[i];
Atom actual_type;
@@ -853,7 +876,7 @@ void update_struts(void)
continue;
Bool is_dock = False;
- for (unsigned long j = 0; j < nitems; ++j) {
+ for (unsigned long j = 0; j < nitems; j++) {
if (types[j] == atom_net_wm_window_type_dock) {
is_dock = True;
break;
@@ -891,7 +914,7 @@ void update_struts(void)
void inc_gaps(void)
{
- ++user_config.gaps;
+ user_config.gaps++;
tile();
update_borders();
}
@@ -910,12 +933,12 @@ void init_defaults(void)
default_config.snap_distance = 5;
default_config.bindsn = 0;
- for (unsigned long i = 0; i < LENGTH(binds); ++i) {
+ for (unsigned long i = 0; i < LENGTH(binds); i++) {
default_config.binds[i].mods = binds[i].mods;
default_config.binds[i].keysym = binds[i].keysym;
default_config.binds[i].action.cmd = binds[i].action.cmd;
- default_config.binds[i].is_func = binds[i].is_func;
- ++default_config.bindsn;
+ default_config.binds[i].type = binds[i].type;
+ default_config.bindsn++;
}
user_config = default_config;
@@ -1028,7 +1051,7 @@ long parse_col(const char *hex)
void quit(void)
{
- for (int ws = 0; ws < NUM_WORKSPACES; ++ws) {
+ for (int ws = 0; ws < NUM_WORKSPACES; ws++) {
for (Client *c = workspaces[ws]; c; c = c->next) {
XUnmapWindow(dpy, c->win);
XKillClient(dpy, c->win);
@@ -1045,13 +1068,33 @@ void quit(void)
void reload_config(void)
{
puts("sxwm: reloading config...");
- memset(user_config.binds, 0, sizeof(user_config.binds));
+ memset(&user_config, 0, sizeof(user_config));
+
+ for (int i = 0; i < user_config.bindsn; i++) {
+ free(user_config.binds[i].action.cmd);
+ user_config.binds[i].action.cmd = NULL;
+
+ user_config.binds[i].action.fn = NULL;
+ user_config.binds[i].type = -1;
+ user_config.binds[i].keysym = 0;
+ user_config.binds[i].mods = 0;
+ }
+
init_defaults();
if (parser(&user_config)) {
fprintf(stderr, "sxrc: error parsing config file\n");
init_defaults();
}
grab_keys();
+ XUngrabButton(dpy, AnyButton, AnyModifier, root);
+ XGrabButton(dpy, Button1, user_config.modkey, root, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+ GrabModeAsync, GrabModeAsync, None, None);
+ XGrabButton(dpy, Button1, user_config.modkey | ShiftMask, root, True,
+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None);
+ XGrabButton(dpy, Button3, user_config.modkey, root, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+ GrabModeAsync, GrabModeAsync, None, None);
+ XSync(dpy, False);
+
tile();
update_borders();
}
@@ -1090,7 +1133,7 @@ void scan_existing_windows(void)
unsigned int nchildren;
if (XQueryTree(dpy, root, &root_return, &parent_return, &children, &nchildren)) {
- for (unsigned int i = 0; i < nchildren; ++i) {
+ for (unsigned int i = 0; i < nchildren; i++) {
XWindowAttributes wa;
if (!XGetWindowAttributes(dpy, children[i], &wa) || wa.override_redirect || wa.map_state != IsViewable) {
continue;
@@ -1114,7 +1157,7 @@ void send_wm_take_focus(Window w)
Atom *protos;
int n;
if (XGetWMProtocols(dpy, w, &protos, &n)) {
- for (int i = 0; i < n; ++i) {
+ for (int i = 0; i < n; i++) {
if (protos[i] == wm_take_focus) {
XEvent ev = {
.xclient = {.type = ClientMessage, .window = w, .message_type = wm_protocols, .format = 32}};
@@ -1164,7 +1207,7 @@ void setup(void)
GrabModeAsync, GrabModeAsync, None, None);
XSync(dpy, False);
- for (int i = 0; i < LASTEvent; ++i) {
+ for (int i = 0; i < LASTEvent; i++) {
evtable[i] = hdl_dummy;
}
@@ -1308,7 +1351,7 @@ void tile(void)
}
}
- for (int m = 0; m < monsn; ++m) {
+ for (int m = 0; m < monsn; m++) {
int mon_x = mons[m].x;
int mon_y = mons[m].y;
int mon_w = mons[m].w;
@@ -1387,7 +1430,7 @@ void tile(void)
c->y = wc.y;
c->w = wc.width;
c->h = wc.height;
- ++i;
+ i++;
}
}
update_borders();
@@ -1513,7 +1556,7 @@ void update_monitors(void)
scr_width = XDisplayWidth(dpy, DefaultScreen(dpy));
scr_height = XDisplayHeight(dpy, DefaultScreen(dpy));
- for (int s = 0; s < ScreenCount(dpy); ++s) {
+ for (int s = 0; s < ScreenCount(dpy); s++) {
Window scr_root = RootWindow(dpy, s);
XDefineCursor(dpy, scr_root, c_normal);
}
@@ -1521,7 +1564,7 @@ void update_monitors(void)
if (XineramaIsActive(dpy)) {
info = XineramaQueryScreens(dpy, &monsn);
mons = malloc(sizeof *mons * monsn);
- for (int i = 0; i < monsn; ++i) {
+ for (int i = 0; i < monsn; i++) {
mons[i].x = info[i].x_org;
mons[i].y = info[i].y_org;
mons[i].w = info[i].width;
@@ -1545,10 +1588,9 @@ void update_net_client_list(void)
{
Window wins[MAXCLIENTS];
int n = 0;
- for (int ws = 0; ws < NUM_WORKSPACES; ++ws) {
+ for (int ws = 0; ws < NUM_WORKSPACES; ws++) {
for (Client *c = workspaces[ws]; c; c = c->next) {
- wins[n++] = c->win; /* has to be n++ or well get an off by one error
- i think */
+ wins[n++] = c->win;
}
}
Atom prop = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
@@ -1567,7 +1609,7 @@ int xerr(Display *dpy, XErrorEvent *ee)
{X_ConfigureWindow, BadMatch},
};
- for (size_t i = 0; i < sizeof(ignore) / sizeof(ignore[0]); ++i) {
+ for (size_t i = 0; i < sizeof(ignore) / sizeof(ignore[0]); i++) {
if ((ignore[i].req == 0 || ignore[i].req == ee->request_code) && (ignore[i].code == ee->error_code)) {
return 0;
}
diff --git a/sxwm b/sxwm
new file mode 100755
index 0000000..70f8fe8
--- /dev/null
+++ b/sxwm
Binary files differ