summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile18
-rw-r--r--README.md182
-rw-r--r--src/config4
-rw-r--r--src/defs.h7
-rw-r--r--src/sxwm.c58
5 files changed, 242 insertions, 27 deletions
diff --git a/Makefile b/Makefile
index 64b0b60..b31c83d 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,7 @@ SRC_DIR = src
SRC = $(wildcard $(SRC_DIR)/*.c)
OBJ = $(SRC:.c=.o)
BIN = sxwm
+PREFIX = /usr/local
all: $(BIN)
@@ -15,7 +16,20 @@ $(BIN): $(OBJ)
$(SRC_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c -o $@ $<
-c:
+clean:
rm -f $(SRC_DIR)/*.o $(BIN)
-.PHONY: all c
+install: all
+ @echo "Installing $(BIN) to $(DESTDIR)$(PREFIX)/bin..."
+ @mkdir -p $(DESTDIR)$(PREFIX)/bin
+ @install -m 755 $(BIN) $(DESTDIR)$(PREFIX)/bin/$(BIN)
+ @echo "Installation complete."
+
+uninstall:
+ @echo "Uninstalling $(BIN) from $(DESTDIR)$(PREFIX)/bin..."
+ @rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN)
+ @echo "Uninstallation complete."
+
+clean-install: clean install
+
+.PHONY: all clean install uninstall clean-install
diff --git a/README.md b/README.md
index 22e10c8..a2d14ee 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,161 @@
-MIT License
-
-Copyright (c) Abhinav Prasai 2025
-
-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.
+# sxwm (*The (truly) Simple Xorg Window Manager*)
+Performance greater than DWM, and easier to config than i3wm
+
+<a href="https://user-images.githubusercontent.com/username/sxwm-screen1.jpg"><img src="https://user-images.githubusercontent.com/username/sxwm-screen1.jpg" width="45%" align="right"></a>
+
+Here we have a **minimal**, **tiling**, and **configurable** window manager.
+
+- **Tiling & Floating**: Seamlessly switch between layouts.
+- **Workspaces**: Workspaces work with your bar.
+- **Bars work too**: BAR BAR BAR?! Why not try [sxbar](https://github.com/uint23/sxbar)
+- **Lightweight**: Single C file plus a small header and config.
+- **Easy Config**: All settings in `config`.
+- **SUPER Fast**: Sometimes **2M** sometimes **4M**, idk but still destroys DWM
+- **BEST WM**: Basically DWM on roids (and without the elitism).
+
+<br>
+
+<a href="TODO"><img src="TODO" width="45%" align="right"></a>
+
+- **Master-Stack**: Use the DWM native and super productive layout.
+- **Keyboard-driven**: Full coverage via `MOD` + keys.
+- **Mouse Support**: Focus under cursor, move & resize with modifiers.
+- **Zero Dependencies**: Only requires `libX11`.
+- **Compiles on a Toaster**: As long as it has a decently modern compiler.
+
+<br clear="right">
+
+---
+
+## Default Configuration
+
+All options reside in `config` (which is just a header-file) with clear comments.
+Keybindings are also easy to understand and quick to implement.
+No more bindsym or... *\*shudders\** C code...
+```c
+CMD(terminal, "st");
+CMD(browser, "firefox");
+
+static const Binding binds[] =
+{
+/*————< MODIFIER(S) >< KEY >—————< FUNCTION >——*/
+
+/*———————< Here are your functions calls >————— — */
+
+ CALL(MOD|SHIFT, e, quit),
+ CALL(MOD|SHIFT, q, close_focused),
+
+ CALL(MOD, j, focus_next),
+ CALL(MOD, k, focus_prev),
+
+ CALL(MOD|SHIFT, j, move_master_next),
+ CALL(MOD|SHIFT, k, move_master_prev),
+
+ CALL(MOD, equal, inc_gaps),
+ CALL(MOD, minus, dec_gaps),
+
+ CALL(MOD, space, toggle_floating),
+ CALL(MOD|SHIFT, space, toggle_floating_global),
+ .....
+```
+
+---
+
+## Default Keybindings
+
+**Window Management**
+
+| Combo | Action |
+| ---------------------------- | ------------------------- |
+| `Mouse` | Focus under cursor |
+| `MOD` + `Left Mouse` | Move window by mouse |
+| `MOD` + `Right Mouse` | Resize window by mouse |
+| `MOD` + `j` / `k` | Focus next / previous |
+| `MOD` + `Shift` + `j` / `k` | Move in master stack |
+| `MOD` + `Space` | Toggle floating |
+| `MOD` + `Shift` + `Space` | Toggle all floating |
+| `MOD` + `=` / `-` | Inc/Dec gaps |
+| `MOD` + `f` | Fullscreen toggle |
+| `MOD` + `c` | Center window |
+| `MOD` + `q` | Close focused window |
+| `MOD` + `1-9` | Switch workspace 1–9 |
+| `MOD` + `Shift` + `1-9` | Move window to WS 1–9 |
+
+**Programs**
+
+| Combo | Action | Programs (by default) |
+| -------------------- | ---------- | --------- |
+| `MOD` + `Return` | Terminal | `st` |
+| `MOD` + `b` | Browser | `firefox` |
+
+---
+
+## 📦 Dependencies
+
+- `libX11` (Xorg client library)
+- GCC / Clang & Make
+
+---
+
+## 🧰 Makefile Targets
+
+Below are the available `make` targets for streamlining common tasks:
+
+| Target | Description |
+| ---------------- | ------------------------------------------------------------------- |
+| `make` or `make all` | Compile the source files into the `sxwm` binary. |
+| `make clean` | Remove object files (`*.o`) and build artifacts. |
+| `make install` | Install `sxwm` to `$(PREFIX)/bin` (default `/usr/local/bin`). |
+| `make uninstall` | Remove the installed binary from `$(PREFIX)/bin`. |
+| `make clean-install` | Runs `make clean` then `make install`. |
+
+> You can override the install directory by specifying `PREFIX` or `DESTDIR`, for example:
+> ```sh
+> make install PREFIX=$HOME/.local
+> ```
+
+---
+
+## 🚀 Installation
+
+1. **Clone repository**
+
+ ```bash
+ git clone https://github.com/username/sxwm.git
+ cd sxwm
+ ```
+
+2. **Build**
+
+ ```bash
+ make
+ ```
+
+3. **Install** (optional)
+
+ ```bash
+ sudo make install PREFIX=/usr/local
+ ```
+
+4. **Run**
+
+ Add to `~/.xinitrc`:
+ ```sh
+ exec sxwm
+ ```
+
+---
+
+## 🙏 Thanks & Inspiration
+
+- [dwm](https://dwm.suckless.org)
+- [i3](https://i3wm.org)
+- [sowm](https://github.com/dylanaraps/sowm)
+- [2bwm](https://github.com/venam/2bwm)
+- [tinywm](http://incise.org/tinywm.html)
+
+---
+
+<p align="center">
+ <em>Contributions welcome! Open issues or submit PRs.</em>
+</p>
diff --git a/src/config b/src/config
index 2c2fb8d..97e15bc 100644
--- a/src/config
+++ b/src/config
@@ -98,7 +98,6 @@
CMD(terminal, "st");
CMD(browser, "firefox");
-
/*
* ———————————————< Bindings >————————————————*
*
@@ -179,6 +178,8 @@ static const Binding binds[] =
CALL(MOD, space, toggle_floating),
CALL(MOD|SHIFT, space, toggle_floating_global),
+ CALL(MOD|SHIFT, f, toggle_fullscreen),
+
/*—————< Here are your executable functions >—————*/
BIND(MOD, Return, terminal),
@@ -212,4 +213,5 @@ static const Binding binds[] =
CALL(MOD, 9, change_ws9),
CALL(MOD|SHIFT, 9, moveto_ws9),
+
};
diff --git a/src/defs.h b/src/defs.h
index f8de140..58c2360 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -3,9 +3,12 @@
#ifndef DEFS_H
#define DEFS_H
-#include <stdint.h>
#include <X11/Xlib.h>
+#define uint unsigned int
+#define ulong unsigned long
+#define u_char unsigned char
+
#define SXWM_VERSION "sxwm ver. 0.1.5"
#define SXWM_AUTHOR "(C) Abhinav Prasai 2025"
#define SXWM_LICINFO "See LICENSE for more info"
@@ -83,7 +86,9 @@ typedef struct {
typedef struct Client{
Window win;
uint x, y, h, w;
+ uint orig_x, orig_y, orig_w, orig_h;
Bool floating;
+ Bool fullscreen;
struct Client *next;
} Client;
diff --git a/src/sxwm.c b/src/sxwm.c
index 98d7b4a..f89833a 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -59,6 +59,7 @@ static void spawn(const char **cmd);
static void tile(void);
static void toggle_floating(void);
static void toggle_floating_global(void);
+static void toggle_fullscreen(void);
static void update_borders(void);
static int xerr(Display *dpy, XErrorEvent *ee);
static void xev_case(XEvent *xev);
@@ -122,7 +123,8 @@ add_client(Window w)
c->y = wa.y;
c->w = wa.width;
c->h = wa.height;
- c->floating = 0;
+ c->floating = False;
+ c->fullscreen = False;
if (global_floating) {
XSetWindowBorder(dpy, c->win, border_foc_col);
@@ -504,6 +506,12 @@ move_to_workspace(uint ws)
if (!focused || ws >= NUM_WORKSPACES || ws == current_ws)
return;
+ if (focused->fullscreen) {
+ focused->fullscreen = False;
+ XMoveResizeWindow(dpy, focused->win, focused->orig_x, focused->orig_y, focused->orig_w, focused->orig_h);
+ XSetWindowBorderWidth(dpy, focused->win, BORDER_WIDTH);
+ }
+
/* remove from current list */
Client **pp = &workspaces[current_ws];
while (*pp && *pp != focused) pp = &(*pp)->next;
@@ -702,9 +710,13 @@ tile(void)
{
uint total_windows = 0;
Client *head = workspaces[current_ws];
- for (Client *c = head; c; c = c->next)
+ for (Client *c = head; c; c = c->next) {
+ if (c->fullscreen)
+ return;
+
if (!c->floating)
++total_windows;
+ }
if (total_windows == 0)
return;
@@ -777,7 +789,13 @@ static void
toggle_floating(void)
{
if (!focused) return;
+
focused->floating = !focused->floating;
+ if (focused->fullscreen) {
+ focused->fullscreen = False;
+ tile();
+ XSetWindowBorderWidth(dpy, focused->win, BORDER_WIDTH);
+ }
if (focused->floating) {
XWindowAttributes wa;
@@ -847,6 +865,41 @@ toggle_floating_global(void)
}
static void
+toggle_fullscreen(void)
+{
+ if (!focused)
+ return;
+
+ if (focused->floating)
+ focused->floating = False;
+
+ focused->fullscreen = !focused->fullscreen;
+
+ if (focused->fullscreen) {
+ XWindowAttributes wa;
+ XGetWindowAttributes(dpy, focused->win, &wa);
+ focused->orig_x = wa.x;
+ focused->orig_y = wa.y;
+ focused->orig_w = wa.width;
+ focused->orig_h = wa.height;
+
+ uint fs_x = 0;
+ uint fs_y = 0;
+ uint fs_w = scr_width;
+ uint fs_h = scr_height;
+
+ XSetWindowBorderWidth(dpy, focused->win, 0);
+ XMoveResizeWindow(dpy, focused->win, fs_x, fs_y, fs_w, fs_h);
+ XRaiseWindow(dpy, focused->win); // Ensure it's on top
+ } else {
+ XMoveResizeWindow(dpy, focused->win, focused->orig_x, focused->orig_y, focused->orig_w, focused->orig_h);
+ XSetWindowBorderWidth(dpy, focused->win, BORDER_WIDTH);
+ tile();
+ update_borders();
+ }
+}
+
+static void
update_borders(void)
{
for (Client *c = workspaces[current_ws]; c; c = c->next) {
@@ -889,6 +942,7 @@ change_workspace(uint ws)
static int
xerr(Display *dpy, XErrorEvent *ee)
{
+ /* TODO MAKE IT BETTER */
if (ee->error_code == BadWindow
|| ee->error_code == BadDrawable
|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)