summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhinav <abhinav.prsai@gmail.com>2025-06-04 18:57:12 +0100
committerAbhinav <abhinav.prsai@gmail.com>2025-06-04 18:57:12 +0100
commit7af19e5c975c42e30c48041fc4fdd2450a5e01ea (patch)
tree5591e362e757b5432ac2e8bb9d7896c535a94c05
parent2e8038c357d0b87a3a1ed4202c4ba5b6417bc7b2 (diff)
clean up code, add contributions help, v1.6
-rw-r--r--CHANGELOG.md23
-rw-r--r--CONTRIBUTIONS.md90
-rw-r--r--README.md4
-rw-r--r--default_sxwmrc3
-rw-r--r--src/defs.h2
-rw-r--r--src/parser.c14
-rw-r--r--src/sxwm.c154
-rw-r--r--sxwm.128
-rw-r--r--sxwm.desktop2
9 files changed, 250 insertions, 70 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1db9d69..0c24308 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,17 +2,32 @@
All notable changes to this project will be documented in this file.
-#### v1.6 (current)
+#### v1.6 (git)
- **NEW**: True multi-monitor support
+- **NEW**: Vertical stack resizing
+- **NEW**: Mouse warping
+- **NEW**: Floating window rules
+- **NEW**: Ctrl key as modifier
+- **NEW**: Focus window on creation
+- **NEW**: Copy config to `/usr/local/share/sxwmrc`
+- **CHANGE**: Renamed `focus_previous` to `focus_prev`
+- **CHANGE**: Invalid sample config
+- **CHANGE**: Parser `$HOME` searching order. XDG Compliance
+- **FIXED**: Improved parsing now supporting commands with `"` and `'`
+- **FIXED**: (mouse warping) Switching to master doesn't automatically shift cursor to it
+- **FIXED**: `ctrl` and `shift` key works as a modifier
+- **FIXED**: Fixed build error (#64).
+- **FIXED**: Removed debug logs
+- **FIXED**: Fixed new window getting interrupted by mouse
+- **FIXED**: Fixed `should_float` segfalt
- **FIXED**: Invisible windows of minimized programs
- **FIXED**: Zombie processes spawned from apps
-- **FIXED**: Invalid sample config
- **FIXED**: Undefined behaviour in `parse_col`
-#### v1.5
+#### v1.5 (current)
- **NEW**: Using XCursor instead of cursor font && new logo.
-- **FIXED**: Proper bind resetting on refresh config. && Multi-arg binds now work due to new and improved spawn function
- **CHANGE**: No longer using INIT_WORKSPACE macro, proper workspace handling. New sxwmrc
+- **FIXED**: Proper bind resetting on refresh config. && Multi-arg binds now work due to new and improved spawn function
#### v1.4
- **CHANGE**: Added motion throttle && master width general options
diff --git a/CONTRIBUTIONS.md b/CONTRIBUTIONS.md
new file mode 100644
index 0000000..9955680
--- /dev/null
+++ b/CONTRIBUTIONS.md
@@ -0,0 +1,90 @@
+# Contributing to sxwm
+
+Firstly, thanks for taking the time to contribute to sxwm! I appreciate your interest in improving the project.
+
+## Code Style and Formatting
+
+There is an included clangd formatting file with this inside, but it wont do everything for you.
+
+### Indentation
+Indentation must always be **tabs** not spaces.
+
+### Blocks
+- All blocks of C code must be encased with curly braces `{}`
+- Blocks must also be seperated, each statement on a new line
+- Statements must be formatted with a space between the keyword and the brackets
+
+**Example**:
+``` c
+if (x) {
+ y();
+}
+else {
+ z();
+}
+```
+
+### Comments
+Comments must be like this to keep the look consistent across the whole program.
+`/* this is a comment */`
+
+### Function Declarations
+They must look like this
+``` c
+void function_x(void)
+{
+}
+
+void function_y(int y)
+{
+}
+```
+
+### Variable Naming
+Variables and function names must be in `snake_case`
+``` c
+void function_a(void);
+void function_b(void);
+```
+``` c
+int some_variable = 2;
+float other_variable = 5;
+```
+
+## Build
+
+- Make sure `make` succeeds with no warnings on your system
+- Don't commit any build artifacts or backup files
+- Test your changes on **multiple monitors (Xephyr)**
+
+## File Layouts
+
+- Please try to not make a new C file or header unless it is necissary. Most of the codebase is kept in the `sxwm.c` file.
+
+## Submitting Changes
+
+- Open a pull request with a **clear report** of the change(s)
+- Keep commits having one purpose per commit
+- If you fix a bug, please describe how to reproduce it
+- If adding a feature, make sure it is consistent with sxwm’s minimalist philosophy
+- Please don't keep multiple changes in one PR. Open a new one for that
+
+## Documentation
+
+- If applicable, **update `sxwm.1`, `README.md` and `default_sxwmrc`**
+
+## Respect the Existing Structure
+
+- Before large changes, open an issue discussion
+- Please don’t change for style unless it improves clarity or fixes a problem
+
+## Testing
+
+- [x] Builds with no warnings
+- [x] Tested to work fully
+- [x] All changes are explained in the PR
+- [x] Configuration reload works (if relevant)
+
+---
+
+**Happy hacking!**
diff --git a/README.md b/README.md
index fa51a2f..a08fac6 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@
- **Live Config Reload**: Change your config and reload instantly with a keybind.
- **Easy Configuration**: Human-friendly `sxwmrc` file, no C required.
- **Master-Stack Layout**: DWM-inspired productive workflow.
-- **Mouse Support**: Move, swap, resize, and focus windows with the mouse.
+- **Mouse Support**: Move, swap, and resize windows with the mouse.
- **Zero Dependencies**: Only `libX11` and `Xinerama` required.
- **Lightweight**: Single C file, minimal headers, compiles in seconds.
- **Bar Friendly**: Works great with [sxbar](https://github.com/uint23/sxbar).
@@ -305,5 +305,5 @@ exec sxwm
---
<p align="center">
- <em>Contributions welcome! Open issues or submit PRs.</em>
+ <em>Contributions welcome, Please read CONTRIBUTIONS.md for more info!</em>
</p>
diff --git a/default_sxwmrc b/default_sxwmrc
index 35e6f6c..6efede7 100644
--- a/default_sxwmrc
+++ b/default_sxwmrc
@@ -8,9 +8,10 @@ gaps : 10
border_width : 1
master_width : 60 # Percentage of screen width
resize_master_amount : 1
+resize_stack_amt : 20
snap_distance : 5
motion_throttle : 60 # Set to screen refresh rate for smoothest motions
-should_float : st
+should_float : "pcmanfm"
new_win_focus : true
warp_cursor : true
diff --git a/src/defs.h b/src/defs.h
index c259738..0075c21 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -1,7 +1,7 @@
/* See LICENSE for more information on use */
#pragma once
#include <X11/Xlib.h>
-#define SXWM_VERSION "sxwm ver. 1.5"
+#define SXWM_VERSION "sxwm ver. 1.6"
#define SXWM_AUTHOR "(C) Abhinav Prasai 2025"
#define SXWM_LICINFO "See LICENSE for more info"
diff --git a/src/parser.c b/src/parser.c
index 8e598d0..3803f10 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -135,7 +135,7 @@ int parser(Config *cfg)
return -1;
}
- // Determine config file path
+ /* determine config file path */
const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home) {
snprintf(path, sizeof path, "%s/sxwmrc", xdg_config_home);
@@ -159,7 +159,7 @@ int parser(Config *cfg)
goto found;
}
- // Nothing found
+ /* Nothing found */
fprintf(stderr, "sxwmrc: no configuration file found\n");
return -1;
@@ -174,7 +174,7 @@ found:;
int lineno = 0;
int should_floatn = 0;
- // Initialize should_float matrix
+ /* Initialize should_float matrix */
for (int j = 0; j < 256; j++) {
cfg->should_float[j] = calloc(256, sizeof(char *));
if (!cfg->should_float[j]) {
@@ -278,11 +278,13 @@ found:;
/* store each comma separated value in a seperate row */
while (comma && should_floatn < 256) {
comma = strip(comma);
- if (*comma == '"')
+ if (*comma == '"') {
comma++;
+ }
char *end = comma + strlen(comma) - 1;
- if (*end == '"')
+ if (*end == '"') {
*end = '\0';
+ }
/* store each programs name in its own row at index 0 */
cfg->should_float[should_floatn][0] = strdup(comma);
@@ -446,4 +448,4 @@ const char **build_argv(const char *cmd)
wordfree(&p);
return argv;
-} \ No newline at end of file
+}
diff --git a/src/sxwm.c b/src/sxwm.c
index 1a5db14..579a393 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -157,8 +157,9 @@ Client *add_client(Window w, int ws)
}
else {
Client *tail = workspaces[ws];
- while (tail->next)
+ while (tail->next) {
tail = tail->next;
+ }
tail->next = c;
}
@@ -213,24 +214,27 @@ Client *add_client(Window w, int ws)
void change_workspace(int ws)
{
- if (ws >= NUM_WORKSPACES || ws == current_ws)
+ if (ws >= NUM_WORKSPACES || ws == current_ws) {
return;
+ }
in_ws_switch = True;
XGrabServer(dpy);
/* unmap those still marked mapped */
for (Client *c = workspaces[current_ws]; c; c = c->next) {
- if (c->mapped)
+ if (c->mapped) {
XUnmapWindow(dpy, c->win);
+ }
}
current_ws = ws;
/* map those still marked mapped */
for (Client *c = workspaces[current_ws]; c; c = c->next) {
- if (c->mapped)
+ if (c->mapped) {
XMapWindow(dpy, c->win);
+ }
}
tile();
@@ -265,7 +269,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,
@@ -277,6 +281,7 @@ void close_focused(void)
XFree(protos);
return;
}
+ }
XUnmapWindow(dpy, focused->win);
XFree(protos);
}
@@ -321,8 +326,9 @@ void focus_prev(void)
}
if (!prev) {
- while (p->next)
+ while (p->next) {
p = p->next;
+ }
focused = p;
}
else {
@@ -341,8 +347,9 @@ 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++) {
- 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)
+ 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;
+ }
}
return 0;
}
@@ -363,15 +370,18 @@ void grab_keys(void)
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)))
+ (b->type == TYPE_MWKSP && b->mods != (user_config.modkey | ShiftMask))) {
continue;
+ }
KeyCode kc = XKeysymToKeycode(dpy, b->keysym);
- if (!kc)
+ if (!kc) {
continue;
+ }
- for (size_t g = 0; g < sizeof guards / sizeof *guards; g++)
+ for (size_t g = 0; g < sizeof guards / sizeof *guards; g++) {
XGrabKey(dpy, kc, b->mods | guards[g], root, True, GrabModeAsync, GrabModeAsync);
+ }
}
}
@@ -519,11 +529,13 @@ void hdl_config_req(XEvent *xev)
XConfigureRequestEvent *e = &xev->xconfigurerequest;
Client *c = NULL;
- for (int ws = 0; ws < NUM_WORKSPACES && !c; ws++)
- for (c = workspaces[ws]; c; c = c->next)
+ for (int ws = 0; ws < NUM_WORKSPACES && !c; ws++) {
+ for (c = workspaces[ws]; c; c = c->next) {
if (c->win == e->window) {
break;
}
+ }
+ }
if (!c || c->floating || c->fullscreen) {
/* allow client to configure itself */
@@ -612,8 +624,9 @@ void hdl_keypress(XEvent *xev)
break;
case TYPE_FUNC:
- if (b->action.fn)
+ if (b->action.fn) {
b->action.fn();
+ }
break;
case TYPE_CWKSP:
change_workspace(b->action.ws);
@@ -638,10 +651,12 @@ void swap_clients(Client *a, Client *b)
Client **head = &workspaces[current_ws];
Client **pa = head, **pb = head;
- while (*pa && *pa != a)
+ while (*pa && *pa != a) {
pa = &(*pa)->next;
- while (*pb && *pb != b)
+ }
+ while (*pb && *pb != b) {
pb = &(*pb)->next;
+ }
if (!*pa || !*pb) {
return;
@@ -724,12 +739,14 @@ void hdl_map_req(XEvent *xev)
}
Client *c = add_client(w, current_ws);
- if (!c)
+ if (!c) {
return;
+ }
Window tr;
- if (!should_float && XGetTransientForHint(dpy, w, &tr))
+ if (!should_float && XGetTransientForHint(dpy, w, &tr)) {
should_float = True;
+ }
XSizeHints sh;
long sup;
if (!should_float && XGetWMNormalHints(dpy, w, &sh, &sup) && (sh.flags & PMinSize) && (sh.flags & PMaxSize) &&
@@ -758,10 +775,12 @@ void hdl_map_req(XEvent *xev)
/* map & borders */
update_net_client_list();
- if (!global_floating && !c->floating)
+ if (!global_floating && !c->floating) {
tile();
- else if (c->floating)
+ }
+ else if (c->floating) {
XRaiseWindow(dpy, w);
+ }
if (user_config.new_win_focus) {
focused = c;
@@ -773,10 +792,11 @@ void hdl_map_req(XEvent *xev)
}
XMapWindow(dpy, w);
- for (Client *c = workspaces[current_ws]; c; c = c->next)
- if (c->win == w)
+ for (Client *c = workspaces[current_ws]; c; c = c->next) {
+ if (c->win == w) {
c->mapped = True;
-
+ }
+ }
update_borders();
}
@@ -914,8 +934,9 @@ void update_struts(void)
Window root_ret, parent_ret, *children;
unsigned int nchildren;
- if (!XQueryTree(dpy, root, &root_ret, &parent_ret, &children, &nchildren))
+ if (!XQueryTree(dpy, root, &root_ret, &parent_ret, &children, &nchildren)) {
return;
+ }
for (unsigned int i = 0; i < nchildren; i++) {
Window w = children[i];
@@ -927,8 +948,9 @@ void update_struts(void)
if (XGetWindowProperty(dpy, w, atom_wm_window_type, 0, 4, False, XA_ATOM, &actual_type, &actual_format, &nitems,
&bytes_after, (unsigned char **)&types) != Success ||
- !types)
+ !types) {
continue;
+ }
Bool is_dock = False;
for (unsigned long j = 0; j < nitems; j++) {
@@ -938,8 +960,9 @@ void update_struts(void)
}
}
XFree(types);
- if (!is_dock)
+ if (!is_dock) {
continue;
+ }
long *str = NULL;
Atom actual;
@@ -982,8 +1005,9 @@ void init_defaults(void)
default_config.border_foc_col = parse_col("#c0cbff");
default_config.border_ufoc_col = parse_col("#555555");
default_config.border_swap_col = parse_col("#fff4c0");
- for (int i = 0; i < MAX_MONITORS; i++)
+ for (int i = 0; i < MAX_MONITORS; i++) {
default_config.master_width[i] = 50 / 100.0f;
+ }
default_config.motion_throttle = 60;
default_config.resize_master_amt = 5;
@@ -1078,8 +1102,9 @@ void move_to_workspace(int ws)
XUnmapWindow(dpy, focused->win);
/* remove from current list */
Client **pp = &workspaces[current_ws];
- while (*pp && *pp != focused)
+ while (*pp && *pp != focused) {
pp = &(*pp)->next;
+ }
if (*pp) {
*pp = focused->next;
}
@@ -1212,8 +1237,9 @@ void resize_master_sub(void)
void resize_stack_add(void)
{
- if (!focused || focused->floating || focused == workspaces[current_ws])
+ if (!focused || focused->floating || focused == workspaces[current_ws]) {
return;
+ }
int bw2 = 2 * user_config.border_width;
int raw_cur = (focused->custom_stack_height > 0) ? focused->custom_stack_height : (focused->h + bw2);
@@ -1225,8 +1251,9 @@ void resize_stack_add(void)
void resize_stack_sub(void)
{
- if (!focused || focused->floating || focused == workspaces[current_ws])
+ if (!focused || focused->floating || focused == workspaces[current_ws]) {
return;
+ }
int bw2 = 2 * user_config.border_width;
int raw_cur = (focused->custom_stack_height > 0) ? focused->custom_stack_height : (focused->h + bw2);
@@ -1490,14 +1517,18 @@ void tile(void)
Client *head = workspaces[current_ws];
int total = 0;
- for (Client *c = head; c; c = c->next)
- if (c->mapped && !c->floating && !c->fullscreen)
+ for (Client *c = head; c; c = c->next) {
+ if (c->mapped && !c->floating && !c->fullscreen) {
total++;
+ }
+ }
if (total == 1) {
- for (Client *c = head; c; c = c->next)
- if (!c->floating && c->fullscreen)
+ for (Client *c = head; c; c = c->next) {
+ if (!c->floating && c->fullscreen) {
return;
+ }
+ }
}
for (int m = 0; m < monsn; m++) {
@@ -1506,12 +1537,15 @@ void tile(void)
Client *stackers[MAXCLIENTS];
int N = 0;
- for (Client *c = head; c; c = c->next)
- if (c->mapped && !c->floating && !c->fullscreen && c->mon == m)
+ for (Client *c = head; c; c = c->next) {
+ if (c->mapped && !c->floating && !c->fullscreen && c->mon == m) {
stackers[N++] = c;
+ }
+ }
- if (N == 0)
+ if (N == 0) {
continue;
+ }
int gx = user_config.gaps, gy = user_config.gaps;
int tile_x = mon_x + gx, tile_y = mon_y + gy;
@@ -1543,30 +1577,38 @@ void tile(void)
int num_stack = N - 1;
int idx_focus = -1;
- for (int i = 1; i < N; i++)
- if (stackers[i] == focused)
+ for (int i = 1; i < N; i++) {
+ if (stackers[i] == focused) {
idx_focus = i;
+ }
+ }
Bool is_fixed[MAXCLIENTS] = {0};
int bw2 = 2 * user_config.border_width;
- for (int i = 1; i < N; i++)
- if (stackers[i]->custom_stack_height > 0)
+ for (int i = 1; i < N; i++) {
+ if (stackers[i]->custom_stack_height > 0) {
is_fixed[i] = True;
- if (idx_focus >= 1 && stackers[idx_focus]->custom_stack_height > 0)
+ }
+ }
+ if (idx_focus >= 1 && stackers[idx_focus]->custom_stack_height > 0) {
is_fixed[idx_focus] = True;
+ }
int total_fixed_heights = 0;
for (int i = 1; i < N; i++) {
- if (!is_fixed[i])
+ if (!is_fixed[i]) {
continue;
+ }
int h = stackers[i]->custom_stack_height > 0 ? stackers[i]->custom_stack_height : stackers[i]->h + bw2;
total_fixed_heights += h;
}
int auto_count = 0;
- for (int i = 1; i < N; i++)
- if (!is_fixed[i])
+ for (int i = 1; i < N; i++) {
+ if (!is_fixed[i]) {
auto_count++;
+ }
+ }
int total_vgaps = (num_stack - 1) * gy;
int remaining = tile_h - total_fixed_heights - total_vgaps;
@@ -1575,6 +1617,7 @@ void tile(void)
if (auto_count > 0) {
if (remaining >= auto_count * min_raw) {
+
int auto_h = remaining / auto_count, used = 0, count = 0;
for (int i = 1; i < N; i++) {
if (!is_fixed[i]) {
@@ -1583,17 +1626,20 @@ void tile(void)
used += auto_h;
}
}
- for (int i = 1; i < N; i++)
- if (is_fixed[i])
+ for (int i = 1; i < N; i++) {
+ if (is_fixed[i]) {
heights_final[i] = stackers[i]->custom_stack_height > 0 ? stackers[i]->custom_stack_height
: stackers[i]->h + bw2;
+ }
+ }
}
else {
- for (int i = 1; i < N; i++)
+ for (int i = 1; i < N; i++) {
heights_final[i] = is_fixed[i]
? (stackers[i]->custom_stack_height > 0 ? stackers[i]->custom_stack_height
: stackers[i]->h + bw2)
: min_raw;
+ }
}
}
else {
@@ -1607,7 +1653,7 @@ void tile(void)
int base_h =
stackers[i]->custom_stack_height > 0 ? stackers[i]->custom_stack_height : stackers[i]->h + bw2;
- // only grow the bottom window if it isn’t fixed
+ /* only grow the bottom window if it isn’t fixed */
if (i == N - 1 && remaining_slack > 0 && stackers[i]->custom_stack_height == 0) {
heights_final[i] = base_h + remaining_slack;
}
@@ -1618,12 +1664,13 @@ void tile(void)
}
int total_height = total_vgaps;
- for (int i = 1; i < N; i++)
+ for (int i = 1; i < N; i++) {
total_height += heights_final[i];
+ }
int overfill = total_height - tile_h;
if (overfill > 0) {
- // shrink from top down, excluding bottom
+ /* shrink from top down, excluding bottom */
for (int i = 1; i < N - 1 && overfill > 0; i++) {
int shrink = MIN(overfill, heights_final[i] - min_raw);
heights_final[i] -= shrink;
@@ -1631,10 +1678,11 @@ void tile(void)
}
}
- // if its not perfectly filled stretch bottom to absorb remainder
+ /* if its not perfectly filled stretch bottom to absorb remainder */
int actual_stack_height = total_vgaps;
- for (int i = 1; i < N; i++)
+ for (int i = 1; i < N; i++) {
actual_stack_height += heights_final[i];
+ }
int shortfall = tile_h - actual_stack_height;
if (shortfall > 0) {
@@ -1901,4 +1949,4 @@ int main(int ac, char **av)
printf("sxwm: starting...\n");
run();
return 0;
-} \ No newline at end of file
+}
diff --git a/sxwm.1 b/sxwm.1
index 646c7d4..323905d 100644
--- a/sxwm.1
+++ b/sxwm.1
@@ -1,4 +1,4 @@
-.TH SXWM 1 "May 2025" "sxwm 1.5" "User Commands"
+.TH sxwm 1 "June 2025" "sxwm 1.6" "User Commands"
.SH NAME
sxwm \- minimal, fast, and configurable tiling window manager for X11
@@ -15,7 +15,7 @@ Nine workspaces with full bar support.
Live configuration reload without restart.
Human-friendly configuration file requiring no recompilation.
DWM-style master-stack layout.
-Mouse support for moving, resizing, focusing, and swapping windows.
+Mouse support for moving, resizing, and swapping windows.
Depends only on libX11 and Xinerama.
Extremely lightweight (single C file).
Multi-monitor support via Xinerama.
@@ -73,6 +73,14 @@ Target updates per second for mouse drag operations (move, resize, swap). Defaul
.B should_float
Lets you change which windows should float by default when opening them. Default is st
+.TP
+.B new_win_focus
+Whether newly opened windows should automatically gain focus. Default is true.
+
+.TP
+.B warp_cursor
+If true, warps the mouse cursor to the center of newly focused windows. Default is true.
+
.SH KEYBINDINGS
Keybindings associate key combinations with actions, either running external commands or internal sxwm functions.
@@ -155,6 +163,14 @@ Increases the width allocated to the master area.
Decreases the width allocated to the master area.
.TP
+.B stack_increase
+Increases the height of stack window.
+
+.TP
+.B stack_decrease
+Decreases the height of stack window.
+
+.TP
.B toggle_floating
Toggles the floating state of the focused window.
@@ -210,6 +226,14 @@ Focus next or previous window.
Move window up or down in the master stack.
.TP
+.B MOD + Shift + h / l
+Increase or decrease master size.
+
+.TP
+.B MOD + Ctrl h / l
+Increase or decrease stack height.
+
+.TP
.B MOD + Space
Toggle floating mode for focused window.
diff --git a/sxwm.desktop b/sxwm.desktop
index f841c2b..ef08338 100644
--- a/sxwm.desktop
+++ b/sxwm.desktop
@@ -1,5 +1,5 @@
[Desktop Entry]
-Name=Sxwm
+Name=sxwm
Comment=Simple Xorg Window Manager
Exec=sxwm
TryExec=sxwm