aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Kanakarakis <ivan.kanak@gmail.com>2011-11-25 17:57:17 +0200
committerIvan Kanakarakis <ivan.kanak@gmail.com>2011-11-25 18:52:19 +0200
commit9471c8095373df357d2a4185ca8de26290faa72c (patch)
treecfaff9428e4325d55a01fc41902c13de612feae8 /src
parent544de8a8e3d2940043b982454fa80340a7461f21 (diff)
move everything to top level
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore5
-rw-r--r--src/ChangeLog46
-rw-r--r--src/Makefile21
-rw-r--r--src/README103
-rw-r--r--src/config.h.def123
-rw-r--r--src/dminiwm.c1011
6 files changed, 0 insertions, 1309 deletions
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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <X11/Xlib.h>
-#include <X11/keysym.h>
-//#include <X11/XF86keysym.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <string.h>
-
-#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;i<TABLENGTH(keys);++i) {
- code = XKeysymToKeycode(dis,keys[i].keysym);
- XGrabKey(dis, code, keys[i].mod, root, True, GrabModeAsync, GrabModeAsync);
- XGrabKey(dis, code, keys[i].mod | LockMask, root, True, GrabModeAsync, GrabModeAsync);
- XGrabKey(dis, code, keys[i].mod | numlockmask, root, True, GrabModeAsync, GrabModeAsync);
- XGrabKey(dis, code, keys[i].mod | numlockmask | LockMask, root, True, GrabModeAsync, GrabModeAsync);
- }
-}
-
-void keypress(XEvent *e) {
- static unsigned int len = sizeof keys / sizeof keys[0];
- unsigned int i;
- KeySym keysym;
- XKeyEvent *ev = &e->xkey;
-
- 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; j<count; j++) {
- if((type[j] == atoms[ATOM_NET_WM_WINDOW_TYPE_UTILITY]) ||
- (type[j] == atoms[ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION]) ||
- (type[j] == atoms[ATOM_NET_WM_WINDOW_TYPE_SPLASH]) ||
- (type[j] == atoms[ATOM_NET_WM_WINDOW_TYPE_DIALOG]) ||
- (type[j] == atoms[ATOM_NET_WM_WINDOW_TYPE_DOCK])) {
- add_window(ev->window);
- 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;i<len;i++)
- if(strcmp(ch.res_class, convenience[i].class) == 0) {
- save_desktop(tmp);
- select_desktop(convenience[i].preferredd-1);
- add_window(ev->window);
- 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;j<TABLENGTH(desktops);++j) {
- select_desktop(j);
- for(c=head;c;c=c->next)
- 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;i<TABLENGTH(desktops);++i) {
- desktops[i].master_size = master_size;
- desktops[i].mode = mode;
- desktops[i].growth = growth;
- desktops[i].head = head;
- desktops[i].current = current;
- }
-
- // Select first dekstop by default
- const Arg arg = {.i = 0};
- current_desktop = arg.i;
- change_desktop(arg);
- // Set up atoms for dialog/notification windows
- int x;
- for(x = 0; x < ATOM_COUNT; x++)
- *atomList[x].atom = XInternAtom(dis, atomList[x].name, False);
- // To catch maprequest and destroynotify (if other wm running)
- XSelectInput(dis,root,SubstructureNotifyMask|SubstructureRedirectMask);
- XSetErrorHandler(xerror);
- logger("\033[0;32mWe're up and running!");
-}
-
-void sigchld(int unused) {
- // Again, thx to dwm ;)
- if(signal(SIGCHLD, sigchld) == SIG_ERR) {
- logger("\033[0;31mCan't install SIGCHLD handler");
- exit(1);
- }
- while(0 < waitpid(-1, NULL, WNOHANG));
-}
-
-void spawn(const Arg arg) {
- if(fork() == 0) {
- if(fork() == 0) {
- if(dis)
- close(ConnectionNumber(dis));
-
- setsid();
- execvp((char*)arg.com[0],(char**)arg.com);
- }
- exit(0);
- }
-}
-
-/* There's no way to check accesses to destroyed windows, thus those cases are ignored (especially on UnmapNotify's). Other types of errors call Xlibs default error handler, which may call exit. */
-int xerror(Display *dis, XErrorEvent *ee) {
- if(ee->error_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;
-}