From 9471c8095373df357d2a4185ca8de26290faa72c Mon Sep 17 00:00:00 2001 From: Ivan Kanakarakis Date: Fri, 25 Nov 2011 17:57:17 +0200 Subject: move everything to top level --- .gitignore | 5 + ChangeLog | 46 +++ Makefile | 21 ++ README | 103 ++++++ README.md | 1 - config.h.def | 123 +++++++ dminiwm.c | 1011 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/.gitignore | 5 - src/ChangeLog | 46 --- src/Makefile | 21 -- src/README | 103 ------ src/config.h.def | 123 ------- src/dminiwm.c | 1011 ------------------------------------------------------ 13 files changed, 1309 insertions(+), 1310 deletions(-) create mode 100644 .gitignore create mode 100644 ChangeLog create mode 100644 Makefile create mode 100644 README delete mode 120000 README.md create mode 100644 config.h.def create mode 100644 dminiwm.c delete mode 100644 src/.gitignore delete mode 100644 src/ChangeLog delete mode 100644 src/Makefile delete mode 100644 src/README delete mode 100644 src/config.h.def delete mode 100644 src/dminiwm.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f9cf82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +dminiwm +config.h +*.o +*.swp +*~ diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..c960952 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,46 @@ +21/11/11 + Fix for transient windows not being managed + +15/11/11 + Fix for when trying to swap master with only one window + +23/10/11 + Fine tuned the popup window management so notification windows aren't managed either + +15/10/11 + Added having applications start on specified desktop + +13/10/11 + Added ability to use grow_window/shrink_window in grid mode with 3 or 4 windows + +13/10/11 + Popup windows now aren't managed/added to the stack + +10/10/11 + Reapplied setting master_size relevant to default mode + +8/10/11 + For only one window or fullscreen mode there is no border + +8/10/11 + Fixed fullscreen mplayer + +8/10/11 + Removed useless gaps when in grid mode + +16/9/11 + Added back the option to have the panel at the top + Fine tuned the grid tiling mode + +13/9/11 + Added back horizontal tiling, follow mouse and follow window + +12/9/11 + Returned to catwm tiling methods - with the ability to resize the window at the top of the stack + +9/9/11 + Fine tuned the next/prev desktop and the destroy notify functions + + 8/9/11 + Have a proper destroy notify function now that removes destroyed windows from + the window manager stack for the desktop they were on. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..55332f9 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +CFLAGS+= -Wall +LDADD+= -lX11 +LDFLAGS= +EXEC=dminiwm + +PREFIX?= /usr/local +BINDIR?= $(PREFIX)/bin + +CC=gcc + +all: $(EXEC) + +dminiwm: dminiwm.o + $(CC) $(LDFLAGS) -Os -o $@ $+ $(LDADD) + +install: all + install -Dm 755 dminiwm $(DESTDIR)$(BINDIR)/dminiwm + +clean: + rm -fv dminiwm *.o + diff --git a/README b/README new file mode 100644 index 0000000..1580a73 --- /dev/null +++ b/README @@ -0,0 +1,103 @@ +##dminiwm +### it's minimal and dynamic + +I started this from catwm 31/12/10 ( https://bbs.archlinux.org/viewtopic.php?id=100215&p=1 ) + See dminiwm.c or config.h for thanks and licensing. +Screenshots and ramblings/updates at https://bbs.archlinux.org/viewtopic.php?id=126463 + + +###Summary +------- + + +**dminiwm** is a very minimal and lightweight dynamic tiling window manager. + I will try to stay under 1000 SLOC. + Currently under 900 lines with the config file included. + + +###Modes +----- + +It allows the "normal" method of tiling window managers(with the new window as the master) + and with the new window opened at the bottom of the stack(like dwm's attach_aside) + + *There's vertical tiling mode:* + + -------------- + | | W | + | |___| + | Master | | + | |___| + | | | + -------------- + + *Horizontal tiling mode:* + + ------------- + | | + | Master | + |-----------| + | W | | | + ------------- + + *Grid tiling mode:* + + ------------- + | | W | + | | | + |------|----| + | | | + ------------- + + *Fullscreen mode*(which you'll know when you see it) + + All accessible with keyboard shortcuts defined in the config.h file. + + * The window W at the top of the stack can be resized on a per desktop basis. + * Changing a tiling mode or window size on one desktop doesn't affect the other desktops. + + +###Recent Changes +-------------- + +15/10/11 + Added having applications open on specified desktop + + +###Status +------ + +There are more options in the config file than the original catwm. + + * Fixed the window manager crashing on a bad window error. + * Fixed the keyboard shortcuts not working if numlock was on. + * Added some functions. + * Added an option to focus the window the mouse just moved to. + * Fixed a window being destroyed on another desktop creating ghost windows. + * Added ability to resize the window on the top of the stack + * Added having applications open on specified desktop + + +###Installation +------------ + +Need Xlib, then: + + edit the config.h file to suit your needs + + $ make + # make install + $ make clean + + +###Bugs +---- + +[ * No bugs for the moment ;) (I mean, no importants bugs ;)] + + +###Todo +---- + + * when swithching desktops stop the mouse being in an unfocused window changing focus. + diff --git a/README.md b/README.md deleted file mode 120000 index 487a367..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -./src/README \ No newline at end of file diff --git a/config.h.def b/config.h.def new file mode 100644 index 0000000..fed94d4 --- /dev/null +++ b/config.h.def @@ -0,0 +1,123 @@ + /* config.h for dminiwm.c [ 0.1.7 ] + * + * Started from catwm 31/12/10 + * Bad window error checking and numlock checking used from + * 2wm at http://hg.suckless.org/2wm/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) + +/* Mod (Mod1 == alt) (Mod4 == Super/windows) */ +#define MOD1 Mod1Mask +#define MOD4 Mod4Mask +#define MASTER_SIZE 0.52 +#define TOP_PANEL 1 /* 1=Don't 0=Have the panel at the top instead of the bottom */ +#define PANEL_HEIGHT 18 /* 0 for no space for a panel */ +#define BORDER_WIDTH 2 +#define ATTACH_ASIDE 1 /* 0=TRUE, 1=New window is master */ +#define DEFAULT_MODE 0 /* 0=Vertical, 1=Fullscreen 2=Horizontal 3=grid*/ +#define FOLLOW_MOUSE 0 /* 1=Don't 0=Focus the window the mouse just entered */ +#define FOLLOW_WINDOW 0 /* 1=Don't 0=Follow the window when moved to a different desktop */ +#define DESKTOPS 6 /* Must edit DESKTOPCHANGE keys to suit */ + +// Colors +#define FOCUS "#664422" // dkorange +#define UNFOCUS "#004050" // blueish + +// Applications to a specific desktop +static const Convenience convenience[] = { \ + /* class desktop follow */ + { "Thunar", 2, 1 }, + //{ "Leafpad", 2, 1 }, + { "Firefox", 3, 0 }, + { "Links", 3, 1 }, + { "MPlayer", 4, 1 }, + { "Thunderbird", 5, 0 }, + { "Pysol", 6, 1 }, +}; + +const char* dmenucmd[] = {"dmenu_run","-i","-nb","#666622","-nf","white",NULL}; +const char* urxvtcmd[] = {"urxvtc",NULL}; +const char* terminalcmd[] = {"Terminal",NULL}; +const char* thunarcmd[] = {"thunar",NULL}; +const char* firefoxcmd[] = {"firefox",NULL}; +const char* webcmd[] = {"links","-g",NULL}; +const char* mailcmd[] = {"thunderbird",NULL }; +const char* voldowncmd[] = {"/home/pnewm/.bin/voldown",NULL}; +const char* volupcmd[] = {"/home/pnewm/.bin/volup",NULL}; +const char* prevoldowncmd[] = {"/home/pnewm/.bin/prevoldown",NULL}; +const char* prevolupcmd[] = {"/home/pnewm/.bin/prevolup",NULL}; +const char* vols_what[] = {"/home/pnewm/.bin/volumes_what",NULL}; +// for reboot and shutdown +const char* rebootcmd[] = {"sudo","reboot",NULL}; +const char* shutdowncmd[] = {"sudo","shutdown","-h","now",NULL}; + +// Avoid multiple paste +#define DESKTOPCHANGE(K,N) \ + { MOD1, K, change_desktop, {.i = N}}, \ + { MOD1|ShiftMask, K, client_to_desktop, {.i = N}}, + +// Shortcuts +static key keys[] = { + // MOD KEY FUNCTION ARGS + { MOD1, XK_h, resize_master, {.i = 10}}, + { MOD1, XK_l, resize_master, {.i = -10}}, + { MOD1, XK_c, kill_client, {NULL}}, + { MOD1, XK_j, next_win, {NULL}}, + { MOD1, XK_k, prev_win, {NULL}}, + { MOD1, XK_v, spawn, {.com = dmenucmd}}, + { MOD1, XK_p, resize_stack, {.i = 10}}, + { MOD1, XK_o, resize_stack, {.i = -10}}, + { MOD1, XK_Return, spawn, {.com = urxvtcmd}}, + { MOD1, XK_Up, spawn, {.com = volupcmd}}, + { MOD1, XK_Down, spawn, {.com = voldowncmd}}, +// alt + shift + shortcut + { MOD1|ShiftMask, XK_j, move_up, {NULL}}, + { MOD1|ShiftMask, XK_k, move_down, {NULL}}, + { MOD1|ShiftMask, XK_Return, swap_master, {NULL}}, + { MOD1|ShiftMask, XK_g, switch_grid, {NULL}}, + { MOD1|ShiftMask, XK_h, switch_horizontal, {NULL}}, + { MOD1|ShiftMask, XK_m, switch_fullscreen, {NULL}}, + { MOD1|ShiftMask, XK_v, switch_vertical, {NULL}}, +// Control + alt + shortcut + { MOD1|ControlMask, XK_q, quit, {NULL}}, + { MOD1|ControlMask, XK_r, spawn, {.com = rebootcmd}}, + { MOD1|ControlMask, XK_s, spawn, {.com = shutdowncmd}}, +// Window key + shortcut + { MOD4, XK_Right, next_desktop, {NULL}}, + { MOD4, XK_Left, prev_desktop, {NULL}}, + { MOD4, XK_e, spawn, {.com = mailcmd}}, + { MOD4, XK_f, spawn, {.com = firefoxcmd}}, + { MOD4, XK_w, spawn, {.com = webcmd}}, + { MOD4, XK_h, spawn, {.com = thunarcmd}}, + { MOD4, XK_t, spawn, {.com = terminalcmd}}, + { MOD4, XK_v, spawn, {.com = vols_what}}, + { MOD4, XK_Up, spawn, {.com = prevolupcmd}}, + { MOD4, XK_Down, spawn, {.com = prevoldowncmd}}, + DESKTOPCHANGE( XK_1, 0) + DESKTOPCHANGE( XK_2, 1) + DESKTOPCHANGE( XK_3, 2) + DESKTOPCHANGE( XK_4, 3) + DESKTOPCHANGE( XK_5, 4) + DESKTOPCHANGE( XK_6, 5) +}; + +#endif + diff --git a/dminiwm.c b/dminiwm.c new file mode 100644 index 0000000..1c1b0ff --- /dev/null +++ b/dminiwm.c @@ -0,0 +1,1011 @@ +/* dminiwm.c [ 0.1.7 ] +* +* I started this from catwm 31/12/10 +* Bad window error checking and numlock checking used from +* 2wm at http://hg.suckless.org/2wm/ +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TABLENGTH(X) (sizeof(X)/sizeof(*X)) + +typedef union { + const char** com; + const int i; +} Arg; + +// Structs +typedef struct { + unsigned int mod; + KeySym keysym; + void (*function)(const Arg arg); + const Arg arg; +} key; + +typedef struct client client; +struct client{ + // Prev and next client + client *next; + client *prev; + + // The window + Window win; +}; + +typedef struct desktop desktop; +struct desktop{ + int master_size; + int mode; + int growth; + client *head; + client *current; +}; + +typedef struct { + const char *class; + int preferredd; + int followwin; +} Convenience; + +typedef enum { + ATOM_NET_WM_WINDOW_TYPE, + ATOM_NET_WM_WINDOW_TYPE_UTILITY, + ATOM_NET_WM_WINDOW_TYPE_DOCK, + ATOM_NET_WM_WINDOW_TYPE_SPLASH, + ATOM_NET_WM_WINDOW_TYPE_DIALOG, + ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION, + ATOM_COUNT +} AtomType; + +typedef struct { + Atom *atom; + const char *name; +} AtomNode; + +Atom atoms[ATOM_COUNT]; + +static const AtomNode atomList[] = { + { &atoms[ATOM_NET_WM_WINDOW_TYPE], "_NET_WM_WINDOW_TYPE" }, + { &atoms[ATOM_NET_WM_WINDOW_TYPE_UTILITY], "_NET_WM_WINDOW_TYPE_UTILITY" }, + { &atoms[ATOM_NET_WM_WINDOW_TYPE_DOCK], "_NET_WM_WINDOW_TYPE_DOCK" }, + { &atoms[ATOM_NET_WM_WINDOW_TYPE_SPLASH], "_NET_WM_WINDOW_TYPE_SPLASH" }, + { &atoms[ATOM_NET_WM_WINDOW_TYPE_DIALOG], "_NET_WM_WINDOW_TYPE_DIALOG" }, + { &atoms[ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION], "_NET_WM_WINDOW_TYPE_NOTIFICATION"}, +}; + +// Functions +static void add_window(Window w); +static void change_desktop(const Arg arg); +static void client_to_desktop(const Arg arg); +static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); +static void destroynotify(XEvent *e); +static void enternotify(XEvent *e); +static void logger(const char* e); +static unsigned long getcolor(const char* color); +static void grabkeys(); +static void keypress(XEvent *e); +static void kill_client(); +static void maprequest(XEvent *e); +static void move_down(); +static void move_up(); +static void next_desktop(); +static void next_win(); +static void prev_desktop(); +static void prev_win(); +static void quit(); +static void remove_window(Window w); +static void resize_master(const Arg arg); +static void resize_stack(const Arg arg); +static void save_desktop(int i); +static void select_desktop(int i); +static void send_kill_signal(Window w); +static void setup(); +static void sigchld(int unused); +static void spawn(const Arg arg); +static void start(); +static void swap_master(); +static void tile(); +static void switch_fullscreen(); +static void switch_grid(); +static void switch_horizontal(); +static void switch_vertical(); +static void update_current(); + +// Include configuration file (need struct key) +#include "config.h" + +// Variable +static Display *dis; +static int bool_quit; +static int current_desktop; +static int growth; +static int master_size; +static int mode; +static int sh; +static int sw; +static int screen; +static int xerror(Display *dis, XErrorEvent *ee); +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int win_focus; +static unsigned int win_unfocus; +unsigned int numlockmask; /* dynamic key lock mask */ +static Window root; +static client *head; +static client *current; + +// Events array +static void (*events[LASTEvent])(XEvent *e) = { + [KeyPress] = keypress, + [MapRequest] = maprequest, + [EnterNotify] = enternotify, + [DestroyNotify] = destroynotify, + [ConfigureNotify] = configurenotify, + [ConfigureRequest] = configurerequest +}; + +// Desktop array +static desktop desktops[DESKTOPS]; + +/* ***************************** Window Management ******************************* */ +void add_window(Window w) { + client *c,*t; + + if(!(c = (client *)calloc(1,sizeof(client)))) { + logger("\033[0;31mError calloc!"); + exit(1); + } + + if(head == NULL) { + c->next = NULL; + c->prev = NULL; + c->win = w; + head = c; + } + else { + if(ATTACH_ASIDE == 0) { + for(t=head;t->next;t=t->next); + + c->next = NULL; + c->prev = t; + c->win = w; + + t->next = c; + } + else { + for(t=head;t->prev;t=t->prev); + + c->prev = NULL; + c->next = t; + c->win = w; + + t->prev = c; + + head = c; + } + } + + current = c; + save_desktop(current_desktop); + // for folow mouse + if(FOLLOW_MOUSE == 0) + XSelectInput(dis, c->win, EnterWindowMask); +} + +void remove_window(Window w) { + client *c; + + // CHANGE THIS UGLY CODE + for(c=head;c;c=c->next) { + + if(c->win == w) { + if(c->prev == NULL && c->next == NULL) { + free(head); + head = NULL; + current = NULL; + save_desktop(current_desktop); + return; + } + + if(c->prev == NULL) { + head = c->next; + c->next->prev = NULL; + current = c->next; + } + else if(c->next == NULL) { + c->prev->next = NULL; + current = c->prev; + } + else { + c->prev->next = c->next; + c->next->prev = c->prev; + current = c->prev; + } + + free(c); + save_desktop(current_desktop); + tile(); + update_current(); + return; + } + } +} + +void kill_client() { + if(current != NULL) { + //send delete signal to window + XEvent ke; + ke.type = ClientMessage; + ke.xclient.window = current->win; + ke.xclient.message_type = XInternAtom(dis, "WM_PROTOCOLS", True); + ke.xclient.format = 32; + ke.xclient.data.l[0] = XInternAtom(dis, "WM_DELETE_WINDOW", True); + ke.xclient.data.l[1] = CurrentTime; + XSendEvent(dis, current->win, False, NoEventMask, &ke); + send_kill_signal(current->win); + remove_window(current->win); + } +} + +void next_win() { + client *c; + + if(current != NULL && head != NULL) { + if(current->next == NULL) + c = head; + else + c = current->next; + + current = c; + if(mode == 1) + tile(); + update_current(); + } +} + +void prev_win() { + client *c; + + if(current != NULL && head != NULL) { + if(current->prev == NULL) + for(c=head;c->next;c=c->next); + else + c = current->prev; + + current = c; + if(mode == 1) + tile(); + update_current(); + } +} + +void move_down() { + Window tmp; + if(current == NULL || current->next == NULL || current->win == head->win || current->prev == NULL) + return; + + tmp = current->win; + current->win = current->next->win; + current->next->win = tmp; + //keep the moved window activated + next_win(); + save_desktop(current_desktop); + tile(); +} + +void move_up() { + Window tmp; + if(current == NULL || current->prev == head || current->win == head->win) { + return; + } + tmp = current->win; + current->win = current->prev->win; + current->prev->win = tmp; + prev_win(); + save_desktop(current_desktop); + tile(); +} + +void swap_master() { + Window tmp; + + if(head->next != NULL && current != NULL && mode != 1) { + if(current == head) { + tmp = head->next->win; + head->next->win = head->win; + head->win = tmp; + } else { + tmp = head->win; + head->win = current->win; + current->win = tmp; + current = head; + } + save_desktop(current_desktop); + tile(); + update_current(); + } +} + +/* **************************** Desktop Management ************************************* */ +void change_desktop(const Arg arg) { + client *c; + + if(arg.i == current_desktop) + return; + + // Save current "properties" + save_desktop(current_desktop); + + // Unmap all window + if(head != NULL) + for(c=head;c;c=c->next) + XUnmapWindow(dis,c->win); + + // Take "properties" from the new desktop + select_desktop(arg.i); + + // Map all windows + if(head != NULL) + for(c=head;c;c=c->next) + XMapWindow(dis,c->win); + + tile(); + update_current(); +} + +void next_desktop() { + int tmp = current_desktop; + if(tmp == TABLENGTH(desktops)-1) + tmp = 0; + else + tmp++; + + Arg a = {.i = tmp}; + change_desktop(a); +} + +void prev_desktop() { + int tmp = current_desktop; + if(tmp == 0) + tmp = TABLENGTH(desktops)-1; + else + tmp--; + + Arg a = {.i = tmp}; + change_desktop(a); +} + +void client_to_desktop(const Arg arg) { + client *tmp = current; + int tmp2 = current_desktop; + + if(arg.i == current_desktop || current == NULL) + return; + + // Add client to desktop + select_desktop(arg.i); + add_window(tmp->win); + save_desktop(arg.i); + + // Remove client from current desktop + select_desktop(tmp2); + XUnmapWindow(dis,tmp->win); + remove_window(tmp->win); + save_desktop(tmp2); + tile(); + update_current(); + if(FOLLOW_WINDOW == 0) + change_desktop(arg); +} + +void save_desktop(int i) { + desktops[i].master_size = master_size; + desktops[i].mode = mode; + desktops[i].growth = growth; + desktops[i].head = head; + desktops[i].current = current; +} + +void select_desktop(int i) { + master_size = desktops[i].master_size; + mode = desktops[i].mode; + growth = desktops[i].growth; + head = desktops[i].head; + current = desktops[i].current; + current_desktop = i; +} + +void tile() { + client *c; + int n = 0; + int x = 0; + int y = 0; + + // For a top panel + if(TOP_PANEL == 0) + y = PANEL_HEIGHT; + + // If only one window + if(head != NULL && head->next == NULL) { + XMoveResizeWindow(dis,head->win,0,y,sw+2*BORDER_WIDTH,sh+2*BORDER_WIDTH); + } + else if(head != NULL) { + switch(mode) { + case 0: /* Vertical */ + // Master window + XMoveResizeWindow(dis,head->win,0,y,master_size - BORDER_WIDTH,sh - BORDER_WIDTH); + + // Stack + for(c=head->next;c;c=c->next) ++n; + if(n == 1) growth = 0; + XMoveResizeWindow(dis,head->next->win,master_size + BORDER_WIDTH,y,sw-master_size-(2*BORDER_WIDTH),(sh/n)+growth - BORDER_WIDTH); + y += (sh/n)+growth; + for(c=head->next->next;c;c=c->next) { + XMoveResizeWindow(dis,c->win,master_size + BORDER_WIDTH,y,sw-master_size-(2*BORDER_WIDTH),(sh/n)-(growth/(n-1)) - BORDER_WIDTH); + y += (sh/n)-(growth/(n-1)); + } + break; + case 1: /* Fullscreen */ + for(c=head;c;c=c->next) { + XMoveResizeWindow(dis,c->win,0,y,sw+2*BORDER_WIDTH,sh+2*BORDER_WIDTH); + } + break; + case 2: /* Horizontal */ + // Master window + XMoveResizeWindow(dis,head->win,0,y,sw-BORDER_WIDTH,master_size - BORDER_WIDTH); + + // Stack + for(c=head->next;c;c=c->next) ++n; + if(n == 1) growth = 0; + XMoveResizeWindow(dis,head->next->win,0,y+master_size + BORDER_WIDTH,(sw/n)+growth-BORDER_WIDTH,sh-master_size-(2*BORDER_WIDTH)); + x = (sw/n)+growth; + for(c=head->next->next;c;c=c->next) { + XMoveResizeWindow(dis,c->win,x,y+master_size + BORDER_WIDTH,(sw/n)-(growth/(n-1)) - BORDER_WIDTH,sh-master_size-(2*BORDER_WIDTH)); + x += (sw/n)-(growth/(n-1)); + } + break; + case 3: { // Grid + int xpos = 0; + int wdt = 0; + int ht = 0; + + for(c=head;c;c=c->next) ++x; + + for(c=head;c;c=c->next) { + ++n; + if(x >= 7) { + wdt = (sw/3) - BORDER_WIDTH; + ht = (sh/3) - BORDER_WIDTH; + if((n == 1) || (n == 4) || (n == 7)) + xpos = 0; + if((n == 2) || (n == 5) || (n == 8)) + xpos = (sw/3) + BORDER_WIDTH; + if((n == 3) || (n == 6) || (n == 9)) + xpos = (2*(sw/3)) + BORDER_WIDTH; + if((n == 4) || (n == 7)) + y += (sh/3) + BORDER_WIDTH; + if((n == x) && (n == 7)) + wdt = sw - BORDER_WIDTH; + if((n == x) && (n == 8)) + wdt = 2*sw/3 - BORDER_WIDTH; + } else + if(x >= 5) { + wdt = (sw/3) - BORDER_WIDTH; + ht = (sh/2) - BORDER_WIDTH; + if((n == 1) || (n == 4)) + xpos = 0; + if((n == 2) || (n == 5)) + xpos = (sw/3) + BORDER_WIDTH; + if((n == 3) || (n == 6)) + xpos = (2*(sw/3)) + BORDER_WIDTH; + if(n == 4) + y += (sh/2); // + BORDER_WIDTH; + if((n == x) && (n == 5)) + wdt = 2*sw/3 - BORDER_WIDTH; + + } else { + if(x > 2) { + if((n == 1) || (n == 2)) + ht = (sh/2) + growth - BORDER_WIDTH; + if(n >= 3) + ht = (sh/2) - growth - 2*BORDER_WIDTH; + } + else + ht = sh - BORDER_WIDTH; + if((n == 1) || (n == 3)) { + xpos = 0; + wdt = master_size - BORDER_WIDTH; + } + if((n == 2) || (n == 4)) { + xpos = master_size+BORDER_WIDTH; + wdt = (sw - master_size) - 2*BORDER_WIDTH; + } + if(n == 3) + y += (sh/2) + growth + BORDER_WIDTH; + if((n == x) && (n == 3)) + wdt = sw - BORDER_WIDTH; + } + XMoveResizeWindow(dis,c->win,xpos,y,wdt,ht); + } + } + break; + default: + break; + } + } +} + +void update_current() { + client *c; + + for(c=head;c;c=c->next) { + if((head->next == NULL) || (mode == 1)) + XSetWindowBorderWidth(dis,c->win,0); + else + XSetWindowBorderWidth(dis,c->win,BORDER_WIDTH); + + if(current == c) { + // "Enable" current window + XSetWindowBorder(dis,c->win,win_focus); + XSetInputFocus(dis,c->win,RevertToParent,CurrentTime); + XRaiseWindow(dis,c->win); + } + else + XSetWindowBorder(dis,c->win,win_unfocus); + } + XSync(dis, False); +} + +void switch_vertical() { + if(mode != 0) { + mode = 0; + master_size = sw * MASTER_SIZE; + tile(); + update_current(); + } +} + +void switch_fullscreen() { + if(mode != 1) { + mode = 1; + tile(); + update_current(); + } +} + +void switch_horizontal() { + if(mode != 2) { + mode = 2; + master_size = sh * MASTER_SIZE; + tile(); + update_current(); + } +} + +void switch_grid() { + if(mode != 3) { + mode = 3; + master_size = sw * MASTER_SIZE; + tile(); + update_current(); + } +} + +void resize_master(const Arg arg) { + master_size += arg.i; + tile(); +} + +void resize_stack(const Arg arg) { + growth += arg.i; + tile(); +} + +/* ********************** Keyboard Management ********************** */ +void grabkeys() { + int i; + KeyCode code; + + XUngrabKey(dis, AnyKey, AnyModifier, root); + // For each shortcuts + for(i=0;ixkey; + + keysym = XKeycodeToKeysym(dis, (KeyCode)ev->keycode, 0); + for(i = 0; i < len; i++) { + if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)) { + if(keys[i].function) + keys[i].function(keys[i].arg); + } + } +} + +void configurenotify(XEvent *e) { + // Do nothing for the moment +} + +/* ********************** Signal Management ************************** */ +void configurerequest(XEvent *e) { + // Paste from DWM, thx again \o/ + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + wc.x = ev->x; + wc.y = ev->y; + if(ev->width < sw-BORDER_WIDTH) + wc.width = ev->width; + else + wc.width = sw-BORDER_WIDTH; + if(ev->height < sh-BORDER_WIDTH) + wc.height = ev->height; + else + wc.height = sh-BORDER_WIDTH; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dis, ev->window, ev->value_mask, &wc); + XSync(dis, False); +} + +void maprequest(XEvent *e) { + XMapRequestEvent *ev = &e->xmaprequest; + + // For fullscreen mplayer (and maybe some other program) + client *c; + + for(c=head;c;c=c->next) + if(ev->window == c->win) { + XMapWindow(dis,ev->window); + XMoveResizeWindow(dis,c->win,-BORDER_WIDTH,-BORDER_WIDTH,sw+BORDER_WIDTH,sh+BORDER_WIDTH); + return; + } + + Window trans = None; + if (XGetTransientForHint(dis, ev->window, &trans) && trans != None) { + add_window(ev->window); + XMapWindow(dis, ev->window); + XSetInputFocus(dis,ev->window,RevertToParent,CurrentTime); + XRaiseWindow(dis,ev->window); + return; + } + + unsigned long count, j, extra; + Atom realType; + int realFormat; + unsigned char *temp; + Atom *type; + + if(XGetWindowProperty(dis, ev->window, atoms[ATOM_NET_WM_WINDOW_TYPE], 0, 32, False, XA_ATOM, &realType, &realFormat, &count, &extra, &temp) == Success) { + if(count > 0) { + type = (unsigned long*)temp; + for(j=0; jwindow); + XMapWindow(dis, ev->window); + XSetInputFocus(dis,ev->window,RevertToParent,CurrentTime); + XRaiseWindow(dis,ev->window); + return; + } + } + } + if(temp) + XFree(temp); + } + + XClassHint ch = {0}; + static unsigned int len = sizeof convenience / sizeof convenience[0]; + int i = 0; + int tmp = current_desktop; + if(XGetClassHint(dis, ev->window, &ch)) + for(i=0;iwindow); + if(tmp == convenience[i].preferredd-1) { + XMapWindow(dis, ev->window); + tile(); + update_current(); + } else { + select_desktop(tmp); + } + if(convenience[i].followwin != 0) { + Arg a = {.i = convenience[i].preferredd-1}; + change_desktop(a); + } + if(ch.res_class) + XFree(ch.res_class); + if(ch.res_name) + XFree(ch.res_name); + return; + } + + add_window(ev->window); + XMapWindow(dis,ev->window); + tile(); + update_current(); +} + +void destroynotify(XEvent *e) { + int i = 0; + int j = 0; + int tmp = current_desktop; + client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + save_desktop(tmp); + for(j=0;jnext) + if(ev->window == c->win) + i++; + + if(i != 0) { + remove_window(ev->window); + select_desktop(tmp); + return; + } + + i = 0; + } + select_desktop(tmp); +} + +void enternotify(XEvent *e) { + client *c; + XCrossingEvent *ev = &e->xcrossing; + + if(FOLLOW_MOUSE == 0) { + if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + for(c=head;c;c=c->next) + if(ev->window == c->win) { + current = c; + update_current(); + return; + } + } +} + +void send_kill_signal(Window w) { + XEvent ke; + ke.type = ClientMessage; + ke.xclient.window = w; + ke.xclient.message_type = XInternAtom(dis, "WM_PROTOCOLS", True); + ke.xclient.format = 32; + ke.xclient.data.l[0] = XInternAtom(dis, "WM_DELETE_WINDOW", True); + ke.xclient.data.l[1] = CurrentTime; + XSendEvent(dis, w, False, NoEventMask, &ke); +} + +unsigned long getcolor(const char* color) { + XColor c; + Colormap map = DefaultColormap(dis,screen); + + if(!XAllocNamedColor(dis,map,color,&c,&c)) { + logger("\033[0;31mError parsing color!"); + exit(1); + } + return c.pixel; +} + +void quit() { + Window root_return, parent; + Window *children; + int i; + unsigned int nchildren; + XEvent ev; + + /* + * if a client refuses to terminate itself, + * we kill every window remaining the brutal way. + * Since we're stuck in the while(nchildren > 0) { ... } loop + * we can't exit through the main method. + * This all happens if MOD+q is pushed a second time. + */ + if(bool_quit == 1) { + XUngrabKey(dis, AnyKey, AnyModifier, root); + XDestroySubwindows(dis, root); + logger(" \033[0;33mThanks for using!"); + XCloseDisplay(dis); + logger("\033[0;31mforced shutdown"); + } + + bool_quit = 1; + XQueryTree(dis, root, &root_return, &parent, &children, &nchildren); + for(i = 0; i < nchildren; i++) { + send_kill_signal(children[i]); + } + //keep alive until all windows are killed + while(nchildren > 0) { + XQueryTree(dis, root, &root_return, &parent, &children, &nchildren); + XNextEvent(dis,&ev); + if(events[ev.type]) + events[ev.type](&ev); + } + + XUngrabKey(dis,AnyKey,AnyModifier,root); + logger("\033[0;34mYou Quit : Thanks for using!"); +} + +void logger(const char* e) { + fprintf(stdout,"\n\033[0;34m:: dminiwm : %s \033[0;m\n", e); +} + +void setup() { + // Install a signal + sigchld(0); + + // Screen and root window + screen = DefaultScreen(dis); + root = RootWindow(dis,screen); + + // Screen width and height + sw = XDisplayWidth(dis,screen) - BORDER_WIDTH; + sh = (XDisplayHeight(dis,screen) - PANEL_HEIGHT) - BORDER_WIDTH; + + // Colors + win_focus = getcolor(FOCUS); + win_unfocus = getcolor(UNFOCUS); + + // numlock workaround + int j, k; + XModifierKeymap *modmap; + numlockmask = 0; + modmap = XGetModifierMapping(dis); + for (k = 0; k < 8; k++) { + for (j = 0; j < modmap->max_keypermod; j++) { + if(modmap->modifiermap[k * modmap->max_keypermod + j] == XKeysymToKeycode(dis, XK_Num_Lock)) + numlockmask = (1 << k); + } + } + XFreeModifiermap(modmap); + + // Shortcuts + grabkeys(); + + // Default stack + mode = DEFAULT_MODE; + growth = 0; + + // For exiting + bool_quit = 0; + + // List of client + head = NULL; + current = NULL; + + // Master size + if(mode == 2) + master_size = sh*MASTER_SIZE; + else + master_size = sw*MASTER_SIZE; + + // Set up all desktop + int i; + for(i=0;ierror_code == BadWindow + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) + return 0; + logger("\033[0;31mBad Window Error!"); + return xerrorxlib(dis, ee); /* may call exit */ +} + +void start() { + XEvent ev; + + // Main loop, just dispatch events (thx to dwm ;) + while(!bool_quit && !XNextEvent(dis,&ev)) { + if(events[ev.type]) + events[ev.type](&ev); + } +} + + +int main(int argc, char **argv) { + // Open display + if(!(dis = XOpenDisplay(NULL))) { + logger("\033[0;31mCannot open display!"); + exit(1); + } + + // Setup env + setup(); + + // Start wm + start(); + + // Close display + XCloseDisplay(dis); + + return 0; +} diff --git a/src/.gitignore b/src/.gitignore deleted file mode 100644 index 7f9cf82..0000000 --- a/src/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -dminiwm -config.h -*.o -*.swp -*~ diff --git a/src/ChangeLog b/src/ChangeLog deleted file mode 100644 index c960952..0000000 --- a/src/ChangeLog +++ /dev/null @@ -1,46 +0,0 @@ -21/11/11 - Fix for transient windows not being managed - -15/11/11 - Fix for when trying to swap master with only one window - -23/10/11 - Fine tuned the popup window management so notification windows aren't managed either - -15/10/11 - Added having applications start on specified desktop - -13/10/11 - Added ability to use grow_window/shrink_window in grid mode with 3 or 4 windows - -13/10/11 - Popup windows now aren't managed/added to the stack - -10/10/11 - Reapplied setting master_size relevant to default mode - -8/10/11 - For only one window or fullscreen mode there is no border - -8/10/11 - Fixed fullscreen mplayer - -8/10/11 - Removed useless gaps when in grid mode - -16/9/11 - Added back the option to have the panel at the top - Fine tuned the grid tiling mode - -13/9/11 - Added back horizontal tiling, follow mouse and follow window - -12/9/11 - Returned to catwm tiling methods - with the ability to resize the window at the top of the stack - -9/9/11 - Fine tuned the next/prev desktop and the destroy notify functions - - 8/9/11 - Have a proper destroy notify function now that removes destroyed windows from - the window manager stack for the desktop they were on. \ No newline at end of file diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 55332f9..0000000 --- a/src/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -CFLAGS+= -Wall -LDADD+= -lX11 -LDFLAGS= -EXEC=dminiwm - -PREFIX?= /usr/local -BINDIR?= $(PREFIX)/bin - -CC=gcc - -all: $(EXEC) - -dminiwm: dminiwm.o - $(CC) $(LDFLAGS) -Os -o $@ $+ $(LDADD) - -install: all - install -Dm 755 dminiwm $(DESTDIR)$(BINDIR)/dminiwm - -clean: - rm -fv dminiwm *.o - diff --git a/src/README b/src/README deleted file mode 100644 index 1580a73..0000000 --- a/src/README +++ /dev/null @@ -1,103 +0,0 @@ -##dminiwm -### it's minimal and dynamic - -I started this from catwm 31/12/10 ( https://bbs.archlinux.org/viewtopic.php?id=100215&p=1 ) - See dminiwm.c or config.h for thanks and licensing. -Screenshots and ramblings/updates at https://bbs.archlinux.org/viewtopic.php?id=126463 - - -###Summary -------- - - -**dminiwm** is a very minimal and lightweight dynamic tiling window manager. - I will try to stay under 1000 SLOC. - Currently under 900 lines with the config file included. - - -###Modes ------ - -It allows the "normal" method of tiling window managers(with the new window as the master) - and with the new window opened at the bottom of the stack(like dwm's attach_aside) - - *There's vertical tiling mode:* - - -------------- - | | W | - | |___| - | Master | | - | |___| - | | | - -------------- - - *Horizontal tiling mode:* - - ------------- - | | - | Master | - |-----------| - | W | | | - ------------- - - *Grid tiling mode:* - - ------------- - | | W | - | | | - |------|----| - | | | - ------------- - - *Fullscreen mode*(which you'll know when you see it) - - All accessible with keyboard shortcuts defined in the config.h file. - - * The window W at the top of the stack can be resized on a per desktop basis. - * Changing a tiling mode or window size on one desktop doesn't affect the other desktops. - - -###Recent Changes --------------- - -15/10/11 - Added having applications open on specified desktop - - -###Status ------- - -There are more options in the config file than the original catwm. - - * Fixed the window manager crashing on a bad window error. - * Fixed the keyboard shortcuts not working if numlock was on. - * Added some functions. - * Added an option to focus the window the mouse just moved to. - * Fixed a window being destroyed on another desktop creating ghost windows. - * Added ability to resize the window on the top of the stack - * Added having applications open on specified desktop - - -###Installation ------------- - -Need Xlib, then: - - edit the config.h file to suit your needs - - $ make - # make install - $ make clean - - -###Bugs ----- - -[ * No bugs for the moment ;) (I mean, no importants bugs ;)] - - -###Todo ----- - - * when swithching desktops stop the mouse being in an unfocused window changing focus. - diff --git a/src/config.h.def b/src/config.h.def deleted file mode 100644 index fed94d4..0000000 --- a/src/config.h.def +++ /dev/null @@ -1,123 +0,0 @@ - /* config.h for dminiwm.c [ 0.1.7 ] - * - * Started from catwm 31/12/10 - * Bad window error checking and numlock checking used from - * 2wm at http://hg.suckless.org/2wm/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#ifndef CONFIG_H -#define CONFIG_H - -#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) - -/* Mod (Mod1 == alt) (Mod4 == Super/windows) */ -#define MOD1 Mod1Mask -#define MOD4 Mod4Mask -#define MASTER_SIZE 0.52 -#define TOP_PANEL 1 /* 1=Don't 0=Have the panel at the top instead of the bottom */ -#define PANEL_HEIGHT 18 /* 0 for no space for a panel */ -#define BORDER_WIDTH 2 -#define ATTACH_ASIDE 1 /* 0=TRUE, 1=New window is master */ -#define DEFAULT_MODE 0 /* 0=Vertical, 1=Fullscreen 2=Horizontal 3=grid*/ -#define FOLLOW_MOUSE 0 /* 1=Don't 0=Focus the window the mouse just entered */ -#define FOLLOW_WINDOW 0 /* 1=Don't 0=Follow the window when moved to a different desktop */ -#define DESKTOPS 6 /* Must edit DESKTOPCHANGE keys to suit */ - -// Colors -#define FOCUS "#664422" // dkorange -#define UNFOCUS "#004050" // blueish - -// Applications to a specific desktop -static const Convenience convenience[] = { \ - /* class desktop follow */ - { "Thunar", 2, 1 }, - //{ "Leafpad", 2, 1 }, - { "Firefox", 3, 0 }, - { "Links", 3, 1 }, - { "MPlayer", 4, 1 }, - { "Thunderbird", 5, 0 }, - { "Pysol", 6, 1 }, -}; - -const char* dmenucmd[] = {"dmenu_run","-i","-nb","#666622","-nf","white",NULL}; -const char* urxvtcmd[] = {"urxvtc",NULL}; -const char* terminalcmd[] = {"Terminal",NULL}; -const char* thunarcmd[] = {"thunar",NULL}; -const char* firefoxcmd[] = {"firefox",NULL}; -const char* webcmd[] = {"links","-g",NULL}; -const char* mailcmd[] = {"thunderbird",NULL }; -const char* voldowncmd[] = {"/home/pnewm/.bin/voldown",NULL}; -const char* volupcmd[] = {"/home/pnewm/.bin/volup",NULL}; -const char* prevoldowncmd[] = {"/home/pnewm/.bin/prevoldown",NULL}; -const char* prevolupcmd[] = {"/home/pnewm/.bin/prevolup",NULL}; -const char* vols_what[] = {"/home/pnewm/.bin/volumes_what",NULL}; -// for reboot and shutdown -const char* rebootcmd[] = {"sudo","reboot",NULL}; -const char* shutdowncmd[] = {"sudo","shutdown","-h","now",NULL}; - -// Avoid multiple paste -#define DESKTOPCHANGE(K,N) \ - { MOD1, K, change_desktop, {.i = N}}, \ - { MOD1|ShiftMask, K, client_to_desktop, {.i = N}}, - -// Shortcuts -static key keys[] = { - // MOD KEY FUNCTION ARGS - { MOD1, XK_h, resize_master, {.i = 10}}, - { MOD1, XK_l, resize_master, {.i = -10}}, - { MOD1, XK_c, kill_client, {NULL}}, - { MOD1, XK_j, next_win, {NULL}}, - { MOD1, XK_k, prev_win, {NULL}}, - { MOD1, XK_v, spawn, {.com = dmenucmd}}, - { MOD1, XK_p, resize_stack, {.i = 10}}, - { MOD1, XK_o, resize_stack, {.i = -10}}, - { MOD1, XK_Return, spawn, {.com = urxvtcmd}}, - { MOD1, XK_Up, spawn, {.com = volupcmd}}, - { MOD1, XK_Down, spawn, {.com = voldowncmd}}, -// alt + shift + shortcut - { MOD1|ShiftMask, XK_j, move_up, {NULL}}, - { MOD1|ShiftMask, XK_k, move_down, {NULL}}, - { MOD1|ShiftMask, XK_Return, swap_master, {NULL}}, - { MOD1|ShiftMask, XK_g, switch_grid, {NULL}}, - { MOD1|ShiftMask, XK_h, switch_horizontal, {NULL}}, - { MOD1|ShiftMask, XK_m, switch_fullscreen, {NULL}}, - { MOD1|ShiftMask, XK_v, switch_vertical, {NULL}}, -// Control + alt + shortcut - { MOD1|ControlMask, XK_q, quit, {NULL}}, - { MOD1|ControlMask, XK_r, spawn, {.com = rebootcmd}}, - { MOD1|ControlMask, XK_s, spawn, {.com = shutdowncmd}}, -// Window key + shortcut - { MOD4, XK_Right, next_desktop, {NULL}}, - { MOD4, XK_Left, prev_desktop, {NULL}}, - { MOD4, XK_e, spawn, {.com = mailcmd}}, - { MOD4, XK_f, spawn, {.com = firefoxcmd}}, - { MOD4, XK_w, spawn, {.com = webcmd}}, - { MOD4, XK_h, spawn, {.com = thunarcmd}}, - { MOD4, XK_t, spawn, {.com = terminalcmd}}, - { MOD4, XK_v, spawn, {.com = vols_what}}, - { MOD4, XK_Up, spawn, {.com = prevolupcmd}}, - { MOD4, XK_Down, spawn, {.com = prevoldowncmd}}, - DESKTOPCHANGE( XK_1, 0) - DESKTOPCHANGE( XK_2, 1) - DESKTOPCHANGE( XK_3, 2) - DESKTOPCHANGE( XK_4, 3) - DESKTOPCHANGE( XK_5, 4) - DESKTOPCHANGE( XK_6, 5) -}; - -#endif - diff --git a/src/dminiwm.c b/src/dminiwm.c deleted file mode 100644 index 1c1b0ff..0000000 --- a/src/dminiwm.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* dminiwm.c [ 0.1.7 ] -* -* I started this from catwm 31/12/10 -* Bad window error checking and numlock checking used from -* 2wm at http://hg.suckless.org/2wm/ -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TABLENGTH(X) (sizeof(X)/sizeof(*X)) - -typedef union { - const char** com; - const int i; -} Arg; - -// Structs -typedef struct { - unsigned int mod; - KeySym keysym; - void (*function)(const Arg arg); - const Arg arg; -} key; - -typedef struct client client; -struct client{ - // Prev and next client - client *next; - client *prev; - - // The window - Window win; -}; - -typedef struct desktop desktop; -struct desktop{ - int master_size; - int mode; - int growth; - client *head; - client *current; -}; - -typedef struct { - const char *class; - int preferredd; - int followwin; -} Convenience; - -typedef enum { - ATOM_NET_WM_WINDOW_TYPE, - ATOM_NET_WM_WINDOW_TYPE_UTILITY, - ATOM_NET_WM_WINDOW_TYPE_DOCK, - ATOM_NET_WM_WINDOW_TYPE_SPLASH, - ATOM_NET_WM_WINDOW_TYPE_DIALOG, - ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION, - ATOM_COUNT -} AtomType; - -typedef struct { - Atom *atom; - const char *name; -} AtomNode; - -Atom atoms[ATOM_COUNT]; - -static const AtomNode atomList[] = { - { &atoms[ATOM_NET_WM_WINDOW_TYPE], "_NET_WM_WINDOW_TYPE" }, - { &atoms[ATOM_NET_WM_WINDOW_TYPE_UTILITY], "_NET_WM_WINDOW_TYPE_UTILITY" }, - { &atoms[ATOM_NET_WM_WINDOW_TYPE_DOCK], "_NET_WM_WINDOW_TYPE_DOCK" }, - { &atoms[ATOM_NET_WM_WINDOW_TYPE_SPLASH], "_NET_WM_WINDOW_TYPE_SPLASH" }, - { &atoms[ATOM_NET_WM_WINDOW_TYPE_DIALOG], "_NET_WM_WINDOW_TYPE_DIALOG" }, - { &atoms[ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION], "_NET_WM_WINDOW_TYPE_NOTIFICATION"}, -}; - -// Functions -static void add_window(Window w); -static void change_desktop(const Arg arg); -static void client_to_desktop(const Arg arg); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static void destroynotify(XEvent *e); -static void enternotify(XEvent *e); -static void logger(const char* e); -static unsigned long getcolor(const char* color); -static void grabkeys(); -static void keypress(XEvent *e); -static void kill_client(); -static void maprequest(XEvent *e); -static void move_down(); -static void move_up(); -static void next_desktop(); -static void next_win(); -static void prev_desktop(); -static void prev_win(); -static void quit(); -static void remove_window(Window w); -static void resize_master(const Arg arg); -static void resize_stack(const Arg arg); -static void save_desktop(int i); -static void select_desktop(int i); -static void send_kill_signal(Window w); -static void setup(); -static void sigchld(int unused); -static void spawn(const Arg arg); -static void start(); -static void swap_master(); -static void tile(); -static void switch_fullscreen(); -static void switch_grid(); -static void switch_horizontal(); -static void switch_vertical(); -static void update_current(); - -// Include configuration file (need struct key) -#include "config.h" - -// Variable -static Display *dis; -static int bool_quit; -static int current_desktop; -static int growth; -static int master_size; -static int mode; -static int sh; -static int sw; -static int screen; -static int xerror(Display *dis, XErrorEvent *ee); -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int win_focus; -static unsigned int win_unfocus; -unsigned int numlockmask; /* dynamic key lock mask */ -static Window root; -static client *head; -static client *current; - -// Events array -static void (*events[LASTEvent])(XEvent *e) = { - [KeyPress] = keypress, - [MapRequest] = maprequest, - [EnterNotify] = enternotify, - [DestroyNotify] = destroynotify, - [ConfigureNotify] = configurenotify, - [ConfigureRequest] = configurerequest -}; - -// Desktop array -static desktop desktops[DESKTOPS]; - -/* ***************************** Window Management ******************************* */ -void add_window(Window w) { - client *c,*t; - - if(!(c = (client *)calloc(1,sizeof(client)))) { - logger("\033[0;31mError calloc!"); - exit(1); - } - - if(head == NULL) { - c->next = NULL; - c->prev = NULL; - c->win = w; - head = c; - } - else { - if(ATTACH_ASIDE == 0) { - for(t=head;t->next;t=t->next); - - c->next = NULL; - c->prev = t; - c->win = w; - - t->next = c; - } - else { - for(t=head;t->prev;t=t->prev); - - c->prev = NULL; - c->next = t; - c->win = w; - - t->prev = c; - - head = c; - } - } - - current = c; - save_desktop(current_desktop); - // for folow mouse - if(FOLLOW_MOUSE == 0) - XSelectInput(dis, c->win, EnterWindowMask); -} - -void remove_window(Window w) { - client *c; - - // CHANGE THIS UGLY CODE - for(c=head;c;c=c->next) { - - if(c->win == w) { - if(c->prev == NULL && c->next == NULL) { - free(head); - head = NULL; - current = NULL; - save_desktop(current_desktop); - return; - } - - if(c->prev == NULL) { - head = c->next; - c->next->prev = NULL; - current = c->next; - } - else if(c->next == NULL) { - c->prev->next = NULL; - current = c->prev; - } - else { - c->prev->next = c->next; - c->next->prev = c->prev; - current = c->prev; - } - - free(c); - save_desktop(current_desktop); - tile(); - update_current(); - return; - } - } -} - -void kill_client() { - if(current != NULL) { - //send delete signal to window - XEvent ke; - ke.type = ClientMessage; - ke.xclient.window = current->win; - ke.xclient.message_type = XInternAtom(dis, "WM_PROTOCOLS", True); - ke.xclient.format = 32; - ke.xclient.data.l[0] = XInternAtom(dis, "WM_DELETE_WINDOW", True); - ke.xclient.data.l[1] = CurrentTime; - XSendEvent(dis, current->win, False, NoEventMask, &ke); - send_kill_signal(current->win); - remove_window(current->win); - } -} - -void next_win() { - client *c; - - if(current != NULL && head != NULL) { - if(current->next == NULL) - c = head; - else - c = current->next; - - current = c; - if(mode == 1) - tile(); - update_current(); - } -} - -void prev_win() { - client *c; - - if(current != NULL && head != NULL) { - if(current->prev == NULL) - for(c=head;c->next;c=c->next); - else - c = current->prev; - - current = c; - if(mode == 1) - tile(); - update_current(); - } -} - -void move_down() { - Window tmp; - if(current == NULL || current->next == NULL || current->win == head->win || current->prev == NULL) - return; - - tmp = current->win; - current->win = current->next->win; - current->next->win = tmp; - //keep the moved window activated - next_win(); - save_desktop(current_desktop); - tile(); -} - -void move_up() { - Window tmp; - if(current == NULL || current->prev == head || current->win == head->win) { - return; - } - tmp = current->win; - current->win = current->prev->win; - current->prev->win = tmp; - prev_win(); - save_desktop(current_desktop); - tile(); -} - -void swap_master() { - Window tmp; - - if(head->next != NULL && current != NULL && mode != 1) { - if(current == head) { - tmp = head->next->win; - head->next->win = head->win; - head->win = tmp; - } else { - tmp = head->win; - head->win = current->win; - current->win = tmp; - current = head; - } - save_desktop(current_desktop); - tile(); - update_current(); - } -} - -/* **************************** Desktop Management ************************************* */ -void change_desktop(const Arg arg) { - client *c; - - if(arg.i == current_desktop) - return; - - // Save current "properties" - save_desktop(current_desktop); - - // Unmap all window - if(head != NULL) - for(c=head;c;c=c->next) - XUnmapWindow(dis,c->win); - - // Take "properties" from the new desktop - select_desktop(arg.i); - - // Map all windows - if(head != NULL) - for(c=head;c;c=c->next) - XMapWindow(dis,c->win); - - tile(); - update_current(); -} - -void next_desktop() { - int tmp = current_desktop; - if(tmp == TABLENGTH(desktops)-1) - tmp = 0; - else - tmp++; - - Arg a = {.i = tmp}; - change_desktop(a); -} - -void prev_desktop() { - int tmp = current_desktop; - if(tmp == 0) - tmp = TABLENGTH(desktops)-1; - else - tmp--; - - Arg a = {.i = tmp}; - change_desktop(a); -} - -void client_to_desktop(const Arg arg) { - client *tmp = current; - int tmp2 = current_desktop; - - if(arg.i == current_desktop || current == NULL) - return; - - // Add client to desktop - select_desktop(arg.i); - add_window(tmp->win); - save_desktop(arg.i); - - // Remove client from current desktop - select_desktop(tmp2); - XUnmapWindow(dis,tmp->win); - remove_window(tmp->win); - save_desktop(tmp2); - tile(); - update_current(); - if(FOLLOW_WINDOW == 0) - change_desktop(arg); -} - -void save_desktop(int i) { - desktops[i].master_size = master_size; - desktops[i].mode = mode; - desktops[i].growth = growth; - desktops[i].head = head; - desktops[i].current = current; -} - -void select_desktop(int i) { - master_size = desktops[i].master_size; - mode = desktops[i].mode; - growth = desktops[i].growth; - head = desktops[i].head; - current = desktops[i].current; - current_desktop = i; -} - -void tile() { - client *c; - int n = 0; - int x = 0; - int y = 0; - - // For a top panel - if(TOP_PANEL == 0) - y = PANEL_HEIGHT; - - // If only one window - if(head != NULL && head->next == NULL) { - XMoveResizeWindow(dis,head->win,0,y,sw+2*BORDER_WIDTH,sh+2*BORDER_WIDTH); - } - else if(head != NULL) { - switch(mode) { - case 0: /* Vertical */ - // Master window - XMoveResizeWindow(dis,head->win,0,y,master_size - BORDER_WIDTH,sh - BORDER_WIDTH); - - // Stack - for(c=head->next;c;c=c->next) ++n; - if(n == 1) growth = 0; - XMoveResizeWindow(dis,head->next->win,master_size + BORDER_WIDTH,y,sw-master_size-(2*BORDER_WIDTH),(sh/n)+growth - BORDER_WIDTH); - y += (sh/n)+growth; - for(c=head->next->next;c;c=c->next) { - XMoveResizeWindow(dis,c->win,master_size + BORDER_WIDTH,y,sw-master_size-(2*BORDER_WIDTH),(sh/n)-(growth/(n-1)) - BORDER_WIDTH); - y += (sh/n)-(growth/(n-1)); - } - break; - case 1: /* Fullscreen */ - for(c=head;c;c=c->next) { - XMoveResizeWindow(dis,c->win,0,y,sw+2*BORDER_WIDTH,sh+2*BORDER_WIDTH); - } - break; - case 2: /* Horizontal */ - // Master window - XMoveResizeWindow(dis,head->win,0,y,sw-BORDER_WIDTH,master_size - BORDER_WIDTH); - - // Stack - for(c=head->next;c;c=c->next) ++n; - if(n == 1) growth = 0; - XMoveResizeWindow(dis,head->next->win,0,y+master_size + BORDER_WIDTH,(sw/n)+growth-BORDER_WIDTH,sh-master_size-(2*BORDER_WIDTH)); - x = (sw/n)+growth; - for(c=head->next->next;c;c=c->next) { - XMoveResizeWindow(dis,c->win,x,y+master_size + BORDER_WIDTH,(sw/n)-(growth/(n-1)) - BORDER_WIDTH,sh-master_size-(2*BORDER_WIDTH)); - x += (sw/n)-(growth/(n-1)); - } - break; - case 3: { // Grid - int xpos = 0; - int wdt = 0; - int ht = 0; - - for(c=head;c;c=c->next) ++x; - - for(c=head;c;c=c->next) { - ++n; - if(x >= 7) { - wdt = (sw/3) - BORDER_WIDTH; - ht = (sh/3) - BORDER_WIDTH; - if((n == 1) || (n == 4) || (n == 7)) - xpos = 0; - if((n == 2) || (n == 5) || (n == 8)) - xpos = (sw/3) + BORDER_WIDTH; - if((n == 3) || (n == 6) || (n == 9)) - xpos = (2*(sw/3)) + BORDER_WIDTH; - if((n == 4) || (n == 7)) - y += (sh/3) + BORDER_WIDTH; - if((n == x) && (n == 7)) - wdt = sw - BORDER_WIDTH; - if((n == x) && (n == 8)) - wdt = 2*sw/3 - BORDER_WIDTH; - } else - if(x >= 5) { - wdt = (sw/3) - BORDER_WIDTH; - ht = (sh/2) - BORDER_WIDTH; - if((n == 1) || (n == 4)) - xpos = 0; - if((n == 2) || (n == 5)) - xpos = (sw/3) + BORDER_WIDTH; - if((n == 3) || (n == 6)) - xpos = (2*(sw/3)) + BORDER_WIDTH; - if(n == 4) - y += (sh/2); // + BORDER_WIDTH; - if((n == x) && (n == 5)) - wdt = 2*sw/3 - BORDER_WIDTH; - - } else { - if(x > 2) { - if((n == 1) || (n == 2)) - ht = (sh/2) + growth - BORDER_WIDTH; - if(n >= 3) - ht = (sh/2) - growth - 2*BORDER_WIDTH; - } - else - ht = sh - BORDER_WIDTH; - if((n == 1) || (n == 3)) { - xpos = 0; - wdt = master_size - BORDER_WIDTH; - } - if((n == 2) || (n == 4)) { - xpos = master_size+BORDER_WIDTH; - wdt = (sw - master_size) - 2*BORDER_WIDTH; - } - if(n == 3) - y += (sh/2) + growth + BORDER_WIDTH; - if((n == x) && (n == 3)) - wdt = sw - BORDER_WIDTH; - } - XMoveResizeWindow(dis,c->win,xpos,y,wdt,ht); - } - } - break; - default: - break; - } - } -} - -void update_current() { - client *c; - - for(c=head;c;c=c->next) { - if((head->next == NULL) || (mode == 1)) - XSetWindowBorderWidth(dis,c->win,0); - else - XSetWindowBorderWidth(dis,c->win,BORDER_WIDTH); - - if(current == c) { - // "Enable" current window - XSetWindowBorder(dis,c->win,win_focus); - XSetInputFocus(dis,c->win,RevertToParent,CurrentTime); - XRaiseWindow(dis,c->win); - } - else - XSetWindowBorder(dis,c->win,win_unfocus); - } - XSync(dis, False); -} - -void switch_vertical() { - if(mode != 0) { - mode = 0; - master_size = sw * MASTER_SIZE; - tile(); - update_current(); - } -} - -void switch_fullscreen() { - if(mode != 1) { - mode = 1; - tile(); - update_current(); - } -} - -void switch_horizontal() { - if(mode != 2) { - mode = 2; - master_size = sh * MASTER_SIZE; - tile(); - update_current(); - } -} - -void switch_grid() { - if(mode != 3) { - mode = 3; - master_size = sw * MASTER_SIZE; - tile(); - update_current(); - } -} - -void resize_master(const Arg arg) { - master_size += arg.i; - tile(); -} - -void resize_stack(const Arg arg) { - growth += arg.i; - tile(); -} - -/* ********************** Keyboard Management ********************** */ -void grabkeys() { - int i; - KeyCode code; - - XUngrabKey(dis, AnyKey, AnyModifier, root); - // For each shortcuts - for(i=0;ixkey; - - keysym = XKeycodeToKeysym(dis, (KeyCode)ev->keycode, 0); - for(i = 0; i < len; i++) { - if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)) { - if(keys[i].function) - keys[i].function(keys[i].arg); - } - } -} - -void configurenotify(XEvent *e) { - // Do nothing for the moment -} - -/* ********************** Signal Management ************************** */ -void configurerequest(XEvent *e) { - // Paste from DWM, thx again \o/ - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - wc.x = ev->x; - wc.y = ev->y; - if(ev->width < sw-BORDER_WIDTH) - wc.width = ev->width; - else - wc.width = sw-BORDER_WIDTH; - if(ev->height < sh-BORDER_WIDTH) - wc.height = ev->height; - else - wc.height = sh-BORDER_WIDTH; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dis, ev->window, ev->value_mask, &wc); - XSync(dis, False); -} - -void maprequest(XEvent *e) { - XMapRequestEvent *ev = &e->xmaprequest; - - // For fullscreen mplayer (and maybe some other program) - client *c; - - for(c=head;c;c=c->next) - if(ev->window == c->win) { - XMapWindow(dis,ev->window); - XMoveResizeWindow(dis,c->win,-BORDER_WIDTH,-BORDER_WIDTH,sw+BORDER_WIDTH,sh+BORDER_WIDTH); - return; - } - - Window trans = None; - if (XGetTransientForHint(dis, ev->window, &trans) && trans != None) { - add_window(ev->window); - XMapWindow(dis, ev->window); - XSetInputFocus(dis,ev->window,RevertToParent,CurrentTime); - XRaiseWindow(dis,ev->window); - return; - } - - unsigned long count, j, extra; - Atom realType; - int realFormat; - unsigned char *temp; - Atom *type; - - if(XGetWindowProperty(dis, ev->window, atoms[ATOM_NET_WM_WINDOW_TYPE], 0, 32, False, XA_ATOM, &realType, &realFormat, &count, &extra, &temp) == Success) { - if(count > 0) { - type = (unsigned long*)temp; - for(j=0; jwindow); - XMapWindow(dis, ev->window); - XSetInputFocus(dis,ev->window,RevertToParent,CurrentTime); - XRaiseWindow(dis,ev->window); - return; - } - } - } - if(temp) - XFree(temp); - } - - XClassHint ch = {0}; - static unsigned int len = sizeof convenience / sizeof convenience[0]; - int i = 0; - int tmp = current_desktop; - if(XGetClassHint(dis, ev->window, &ch)) - for(i=0;iwindow); - if(tmp == convenience[i].preferredd-1) { - XMapWindow(dis, ev->window); - tile(); - update_current(); - } else { - select_desktop(tmp); - } - if(convenience[i].followwin != 0) { - Arg a = {.i = convenience[i].preferredd-1}; - change_desktop(a); - } - if(ch.res_class) - XFree(ch.res_class); - if(ch.res_name) - XFree(ch.res_name); - return; - } - - add_window(ev->window); - XMapWindow(dis,ev->window); - tile(); - update_current(); -} - -void destroynotify(XEvent *e) { - int i = 0; - int j = 0; - int tmp = current_desktop; - client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - save_desktop(tmp); - for(j=0;jnext) - if(ev->window == c->win) - i++; - - if(i != 0) { - remove_window(ev->window); - select_desktop(tmp); - return; - } - - i = 0; - } - select_desktop(tmp); -} - -void enternotify(XEvent *e) { - client *c; - XCrossingEvent *ev = &e->xcrossing; - - if(FOLLOW_MOUSE == 0) { - if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - for(c=head;c;c=c->next) - if(ev->window == c->win) { - current = c; - update_current(); - return; - } - } -} - -void send_kill_signal(Window w) { - XEvent ke; - ke.type = ClientMessage; - ke.xclient.window = w; - ke.xclient.message_type = XInternAtom(dis, "WM_PROTOCOLS", True); - ke.xclient.format = 32; - ke.xclient.data.l[0] = XInternAtom(dis, "WM_DELETE_WINDOW", True); - ke.xclient.data.l[1] = CurrentTime; - XSendEvent(dis, w, False, NoEventMask, &ke); -} - -unsigned long getcolor(const char* color) { - XColor c; - Colormap map = DefaultColormap(dis,screen); - - if(!XAllocNamedColor(dis,map,color,&c,&c)) { - logger("\033[0;31mError parsing color!"); - exit(1); - } - return c.pixel; -} - -void quit() { - Window root_return, parent; - Window *children; - int i; - unsigned int nchildren; - XEvent ev; - - /* - * if a client refuses to terminate itself, - * we kill every window remaining the brutal way. - * Since we're stuck in the while(nchildren > 0) { ... } loop - * we can't exit through the main method. - * This all happens if MOD+q is pushed a second time. - */ - if(bool_quit == 1) { - XUngrabKey(dis, AnyKey, AnyModifier, root); - XDestroySubwindows(dis, root); - logger(" \033[0;33mThanks for using!"); - XCloseDisplay(dis); - logger("\033[0;31mforced shutdown"); - } - - bool_quit = 1; - XQueryTree(dis, root, &root_return, &parent, &children, &nchildren); - for(i = 0; i < nchildren; i++) { - send_kill_signal(children[i]); - } - //keep alive until all windows are killed - while(nchildren > 0) { - XQueryTree(dis, root, &root_return, &parent, &children, &nchildren); - XNextEvent(dis,&ev); - if(events[ev.type]) - events[ev.type](&ev); - } - - XUngrabKey(dis,AnyKey,AnyModifier,root); - logger("\033[0;34mYou Quit : Thanks for using!"); -} - -void logger(const char* e) { - fprintf(stdout,"\n\033[0;34m:: dminiwm : %s \033[0;m\n", e); -} - -void setup() { - // Install a signal - sigchld(0); - - // Screen and root window - screen = DefaultScreen(dis); - root = RootWindow(dis,screen); - - // Screen width and height - sw = XDisplayWidth(dis,screen) - BORDER_WIDTH; - sh = (XDisplayHeight(dis,screen) - PANEL_HEIGHT) - BORDER_WIDTH; - - // Colors - win_focus = getcolor(FOCUS); - win_unfocus = getcolor(UNFOCUS); - - // numlock workaround - int j, k; - XModifierKeymap *modmap; - numlockmask = 0; - modmap = XGetModifierMapping(dis); - for (k = 0; k < 8; k++) { - for (j = 0; j < modmap->max_keypermod; j++) { - if(modmap->modifiermap[k * modmap->max_keypermod + j] == XKeysymToKeycode(dis, XK_Num_Lock)) - numlockmask = (1 << k); - } - } - XFreeModifiermap(modmap); - - // Shortcuts - grabkeys(); - - // Default stack - mode = DEFAULT_MODE; - growth = 0; - - // For exiting - bool_quit = 0; - - // List of client - head = NULL; - current = NULL; - - // Master size - if(mode == 2) - master_size = sh*MASTER_SIZE; - else - master_size = sw*MASTER_SIZE; - - // Set up all desktop - int i; - for(i=0;ierror_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - logger("\033[0;31mBad Window Error!"); - return xerrorxlib(dis, ee); /* may call exit */ -} - -void start() { - XEvent ev; - - // Main loop, just dispatch events (thx to dwm ;) - while(!bool_quit && !XNextEvent(dis,&ev)) { - if(events[ev.type]) - events[ev.type](&ev); - } -} - - -int main(int argc, char **argv) { - // Open display - if(!(dis = XOpenDisplay(NULL))) { - logger("\033[0;31mCannot open display!"); - exit(1); - } - - // Setup env - setup(); - - // Start wm - start(); - - // Close display - XCloseDisplay(dis); - - return 0; -} -- cgit v1.3.1 From 6581ec93a2f07a441229f513bdb312e174814d77 Mon Sep 17 00:00:00 2001 From: Ivan Kanakarakis Date: Fri, 25 Nov 2011 18:10:04 +0200 Subject: format readme to markdown --- README | 103 -------------------------------------------------------------- README.md | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 103 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index 1580a73..0000000 --- a/README +++ /dev/null @@ -1,103 +0,0 @@ -##dminiwm -### it's minimal and dynamic - -I started this from catwm 31/12/10 ( https://bbs.archlinux.org/viewtopic.php?id=100215&p=1 ) - See dminiwm.c or config.h for thanks and licensing. -Screenshots and ramblings/updates at https://bbs.archlinux.org/viewtopic.php?id=126463 - - -###Summary -------- - - -**dminiwm** is a very minimal and lightweight dynamic tiling window manager. - I will try to stay under 1000 SLOC. - Currently under 900 lines with the config file included. - - -###Modes ------ - -It allows the "normal" method of tiling window managers(with the new window as the master) - and with the new window opened at the bottom of the stack(like dwm's attach_aside) - - *There's vertical tiling mode:* - - -------------- - | | W | - | |___| - | Master | | - | |___| - | | | - -------------- - - *Horizontal tiling mode:* - - ------------- - | | - | Master | - |-----------| - | W | | | - ------------- - - *Grid tiling mode:* - - ------------- - | | W | - | | | - |------|----| - | | | - ------------- - - *Fullscreen mode*(which you'll know when you see it) - - All accessible with keyboard shortcuts defined in the config.h file. - - * The window W at the top of the stack can be resized on a per desktop basis. - * Changing a tiling mode or window size on one desktop doesn't affect the other desktops. - - -###Recent Changes --------------- - -15/10/11 - Added having applications open on specified desktop - - -###Status ------- - -There are more options in the config file than the original catwm. - - * Fixed the window manager crashing on a bad window error. - * Fixed the keyboard shortcuts not working if numlock was on. - * Added some functions. - * Added an option to focus the window the mouse just moved to. - * Fixed a window being destroyed on another desktop creating ghost windows. - * Added ability to resize the window on the top of the stack - * Added having applications open on specified desktop - - -###Installation ------------- - -Need Xlib, then: - - edit the config.h file to suit your needs - - $ make - # make install - $ make clean - - -###Bugs ----- - -[ * No bugs for the moment ;) (I mean, no importants bugs ;)] - - -###Todo ----- - - * when swithching desktops stop the mouse being in an unfocused window changing focus. - diff --git a/README.md b/README.md new file mode 100644 index 0000000..1580a73 --- /dev/null +++ b/README.md @@ -0,0 +1,103 @@ +##dminiwm +### it's minimal and dynamic + +I started this from catwm 31/12/10 ( https://bbs.archlinux.org/viewtopic.php?id=100215&p=1 ) + See dminiwm.c or config.h for thanks and licensing. +Screenshots and ramblings/updates at https://bbs.archlinux.org/viewtopic.php?id=126463 + + +###Summary +------- + + +**dminiwm** is a very minimal and lightweight dynamic tiling window manager. + I will try to stay under 1000 SLOC. + Currently under 900 lines with the config file included. + + +###Modes +----- + +It allows the "normal" method of tiling window managers(with the new window as the master) + and with the new window opened at the bottom of the stack(like dwm's attach_aside) + + *There's vertical tiling mode:* + + -------------- + | | W | + | |___| + | Master | | + | |___| + | | | + -------------- + + *Horizontal tiling mode:* + + ------------- + | | + | Master | + |-----------| + | W | | | + ------------- + + *Grid tiling mode:* + + ------------- + | | W | + | | | + |------|----| + | | | + ------------- + + *Fullscreen mode*(which you'll know when you see it) + + All accessible with keyboard shortcuts defined in the config.h file. + + * The window W at the top of the stack can be resized on a per desktop basis. + * Changing a tiling mode or window size on one desktop doesn't affect the other desktops. + + +###Recent Changes +-------------- + +15/10/11 + Added having applications open on specified desktop + + +###Status +------ + +There are more options in the config file than the original catwm. + + * Fixed the window manager crashing on a bad window error. + * Fixed the keyboard shortcuts not working if numlock was on. + * Added some functions. + * Added an option to focus the window the mouse just moved to. + * Fixed a window being destroyed on another desktop creating ghost windows. + * Added ability to resize the window on the top of the stack + * Added having applications open on specified desktop + + +###Installation +------------ + +Need Xlib, then: + + edit the config.h file to suit your needs + + $ make + # make install + $ make clean + + +###Bugs +---- + +[ * No bugs for the moment ;) (I mean, no importants bugs ;)] + + +###Todo +---- + + * when swithching desktops stop the mouse being in an unfocused window changing focus. + -- cgit v1.3.1 From 69ccb7ab008e18177902eed8324f8465b0f2f6d0 Mon Sep 17 00:00:00 2001 From: Ivan Kanakarakis Date: Fri, 25 Nov 2011 18:10:29 +0200 Subject: rework and update readme --- README.md | 94 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 1580a73..c3e1d90 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,32 @@ -##dminiwm -### it's minimal and dynamic +dminiwm +======= -I started this from catwm 31/12/10 ( https://bbs.archlinux.org/viewtopic.php?id=100215&p=1 ) - See dminiwm.c or config.h for thanks and licensing. -Screenshots and ramblings/updates at https://bbs.archlinux.org/viewtopic.php?id=126463 +### ~ it's minimal and dynamic +I started this from [catwm][cwm] 31/12/10 ([ArchLinux forums][cwmf]) +Credits and licensing included in `dminiwm.c` and/or `config.h.def`. +For screenshots and ramblings/updates check [the topic on ArchLinux forums][dmnf] -###Summary -------- + [cwm]: https://github.com/pyknite/catwm + [cwmf]: https://bbs.archlinux.org/viewtopic.php?id=100215&p=1 + [dmnf]: https://bbs.archlinux.org/viewtopic.php?id=126463 +Summary +------- **dminiwm** is a very minimal and lightweight dynamic tiling window manager. - I will try to stay under 1000 SLOC. - Currently under 900 lines with the config file included. - +I will try to stay under 1000 SLOC. +Currently under 900 lines with the config file included. -###Modes +Modes ----- It allows the "normal" method of tiling window managers(with the new window as the master) and with the new window opened at the bottom of the stack(like dwm's attach_aside) - *There's vertical tiling mode:* +--- + +*There's vertical tiling mode:* -------------- | | W | @@ -31,7 +36,9 @@ It allows the "normal" method of tiling window managers(with the new window as t | | | -------------- - *Horizontal tiling mode:* +--- + +*Horizontal tiling mode:* ------------- | | @@ -39,7 +46,9 @@ It allows the "normal" method of tiling window managers(with the new window as t |-----------| | W | | | ------------- - + +--- + *Grid tiling mode:* ------------- @@ -49,54 +58,71 @@ It allows the "normal" method of tiling window managers(with the new window as t | | | ------------- - *Fullscreen mode*(which you'll know when you see it) +--- + + *Fullscreen mode* (you'll know when you see it) + + ------------- + | | + | | + | | + | | + ------------- + +--- + +All accessible with keyboard shortcuts defined in the config.h file. - All accessible with keyboard shortcuts defined in the config.h file. - * The window W at the top of the stack can be resized on a per desktop basis. * Changing a tiling mode or window size on one desktop doesn't affect the other desktops. -###Recent Changes +Recent Changes -------------- 15/10/11 Added having applications open on specified desktop - -###Status +Status ------ There are more options in the config file than the original catwm. - * Fixed the window manager crashing on a bad window error. - * Fixed the keyboard shortcuts not working if numlock was on. - * Added some functions. - * Added an option to focus the window the mouse just moved to. - * Fixed a window being destroyed on another desktop creating ghost windows. - * Added ability to resize the window on the top of the stack - * Added having applications open on specified desktop + * Fixed the window manager crashing on a bad window error. + * Fixed the keyboard shortcuts not working if numlock was on. + * Added some functions. + * Added an option to focus the window the mouse just moved to. + * Fixed a window being destroyed on another desktop creating ghost windows. + * Added ability to resize the window on the top of the stack + * Added having applications open on specified desktop -###Installation +Installation ------------ -Need Xlib, then: +You need Xlib, then, +copy the `config.h.deh` file as `config.h` and edit to suit your needs. +Build and install the project. - edit the config.h file to suit your needs + $ cp config.h.def config.h + $ $EDITOR config.h # optional $ make # make install $ make clean - -###Bugs +Bugs ---- -[ * No bugs for the moment ;) (I mean, no importants bugs ;)] +No bugs for the moment ;) (I mean, no importants bugs) + +For any issues report at [the topic on ArchLinux forums][dmnf], +or [fill an issue][bug] on [GitHub][ghp] + [bug]: https://github.com/moetunes/dminimalwm/issues + [ghp]: https://github.com/moetunes/dminimalwm -###Todo +Todo ---- * when swithching desktops stop the mouse being in an unfocused window changing focus. -- cgit v1.3.1