You are not logged in.
Hi there... I'm glad that someone is still using catwm and liking it
I just saw these post this morning, I was skying the few last days
If I got the time I really want to rewrite the code with xcb... I tried a few month ago but the machine crashed hardly and I lost all the code
Offline
I've had another play with catwm today, shifted a couple of things around, and added different tiling modes. There's horizontal, vertical and toggle the focused app fullscreen. There's keyboard shortcuts for each mode and catwm will remember each workspaces mode for the session. Default is set in the config file.
Earlier I added room for conky piped to dzen so I added which tiling mode is used for each workspace to the display. The file this is read from should be set from the config file.
I've called it catwm-0.0.2 'cause it is different to pyknites' original work but 99% of it is his work so I hope that's ok. The files are small like catwm's footprint so here they are :
/edit
After spending a couple of hours here and there I've ended up with :
the option for normal catwm behaviour(like the dwm attach aside patch apparently) or where the new window becomes the master, set in the config file.
three tiling modes - horizontal, fullscreen and vertical - keyboard shortcuts for each and and catwm remembers the mode for each desktop for the session, default set in the config
a panel height setting in the config for running conky through dzen
I removed the writing to file bit as tiling and workspace changes are pretty stable now
I've updated the below files for how catwm is as I'm using it now.
Thanks for the fun little app pyknite
catwm-0.0.2.c
/* catwm-0.0.2.c
*
* ( o o ) Made by cat...
* ( =^= )
* ( ) ... for cat!
* ( )
* ( ))))))________________ Cute And Tiny Window Manager
* ______________________________________________________________________________
*
* Copyright (c) 2010, Rinaldini Julien, julien.rinaldini@heig-vd.ch
*
* 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/>.
*
* Some changes and additions by P. Newman 24.4.11
* - best not to email julien if you use this... :)
*/
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/XF86keysym.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#define TABLENGTH(X) (sizeof(X)/sizeof(*X))
typedef union {
const char** com;
const int i;
} Arg;
// Structs
struct key {
unsigned int mod;
KeySym keysym;
void (*function)(const Arg arg);
const Arg arg;
};
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;
client *head;
client *current;
};
// 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 decrease();
static void destroynotify(XEvent *e);
static void die(const char* e);
static unsigned long getcolor(const char* color);
static void grabkeys();
static void increase();
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 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 toggle_fullscreen();
static void switch_vertical();
static void switch_horizontal();
static void tile();
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 master_size;
static int mode;
static int sh;
static int sw;
static int screen;
static unsigned int win_focus;
static unsigned int win_unfocus;
static Window root;
static client *head;
static client *current;
static int holder; // for coming out of fullscreen mode back to what mode it was
// Events array
static void (*events[LASTEvent])(XEvent *e) = {
[KeyPress] = keypress,
[MapRequest] = maprequest,
[DestroyNotify] = destroynotify,
[ConfigureNotify] = configurenotify,
[ConfigureRequest] = configurerequest
};
// Desktop array
static desktop desktops[5];
/* ***************************** Window Management ******************************* */
void add_window(Window w) {
client *c,*t;
if(!(c = (client *)calloc(1,sizeof(client))))
die("Error calloc!");
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);
}
void swap_master() {
Window tmp;
if(head != NULL && current != NULL && current != head && mode != 1) {
tmp = head->win;
head->win = current->win;
current->win = tmp;
current = head;
save_desktop(current_desktop);
tile();
}
}
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) {
fprintf(stdout, "%s\n","move_up not gonna be used");
return;
}
tmp = current->win;
current->win = current->prev->win;
current->prev->win = tmp;
prev_win();
save_desktop(current_desktop);
tile();
}
void next_win() {
client *c;
if(current != NULL && head != NULL) {
if(current->next == NULL)
c = head;
else
c = current->next;
current = c;
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;
update_current();
}
}
void decrease() {
// if(master_size < 50) {
master_size -= 10;
tile();
// }
}
void increase() {
// if(master_size < sh-50) {
master_size += 10;
tile();
// }
}
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;
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);
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);
}
}
unsigned long getcolor(const char* color) {
XColor c;
Colormap map = DefaultColormap(dis,screen);
if(!XAllocNamedColor(dis,map,color,&c,&c))
die("Error parsing color!");
return c.pixel;
}
void update_current() {
client *c;
for(c=head;c;c=c->next)
if(current == c) {
// "Enable" current window
XSetWindowBorderWidth(dis,c->win,BORDER_WIDTH);
XSetWindowBorder(dis,c->win,win_focus);
XSetInputFocus(dis,c->win,RevertToParent,CurrentTime);
XRaiseWindow(dis,c->win);
}
else
XSetWindowBorder(dis,c->win,win_unfocus);
}
/* **************************** 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 == 5)
tmp = 0;
else
tmp++;
Arg a = {.i = tmp};
change_desktop(a);
}
void prev_desktop() {
int tmp = current_desktop;
if(tmp == 0)
tmp = 5;
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);
remove_window(current->win);
XUnmapWindow(dis,tmp->win);
current = current->next;
tile();
update_current();
}
void save_desktop(int i) {
desktops[i].master_size = master_size;
desktops[i].mode = mode;
desktops[i].head = head;
desktops[i].current = current;
}
void select_desktop(int i) {
head = desktops[i].head;
current = desktops[i].current;
master_size = desktops[i].master_size;
mode = desktops[i].mode;
current_desktop = i;
}
void tile() {
client *c;
int n = 0;
int x = 0;
// If only one window
if(head != NULL && head->next == NULL) {
XMoveResizeWindow(dis,head->win,0,0,sw-4,sh-4);
}
else if(head != NULL) {
switch(mode) {
case 0: /* Horizontal */
// Master window
XMoveResizeWindow(dis,head->win,0,0,sw-4,master_size - BORDER_WIDTH);
// Stack
for(c=head->next;c;c=c->next) ++n;
for(c=head->next;c;c=c->next) {
XMoveResizeWindow(dis,c->win,x,master_size + BORDER_WIDTH,(sw/n) - BORDER_WIDTH,sh-master_size - (2 * BORDER_WIDTH));
x += sw/n;
}
break;
case 1: /* Fullscreen */
for(c=head;c;c=c->next) {
XMoveResizeWindow(dis,c->win,0,0,sw,sh);
}
break;
case 2: /* Vertical */
// Master window
XMoveResizeWindow(dis,head->win,0,0,master_size - BORDER_WIDTH,sh - BORDER_WIDTH);
// Stack
for(c=head->next;c;c=c->next) ++n;
for(c=head->next;c;c=c->next) {
XMoveResizeWindow(dis,c->win,master_size + BORDER_WIDTH,x,sw-master_size-(2*BORDER_WIDTH),(sh/n) - BORDER_WIDTH);
x += sh/n;
}
break;
default:
break;
}
}
}
void toggle_fullscreen() {
if(mode != 1) {
holder = mode;
mode = 1;
}
else {
mode = holder;
}
tile();
update_current();
}
void switch_vertical() {
mode = 2;
master_size = sw * MASTER_SIZE;
tile();
update_current();
}
void switch_horizontal() {
mode = 0;
master_size = sh * MASTER_SIZE;
tile();
update_current();
}
/* ********************** Keyboard Management ********************** */
void grabkeys() {
int i;
KeyCode code;
// For each shortcuts
for(i=0;i<TABLENGTH(keys);++i) {
if((code = XKeysymToKeycode(dis,keys[i].keysym))) {
XGrabKey(dis,code,keys[i].mod,root,True,GrabModeAsync,GrabModeAsync);
}
}
}
void keypress(XEvent *e) {
int i;
XKeyEvent ke = e->xkey;
KeySym keysym = XKeycodeToKeysym(dis,ke.keycode,0);
for(i=0;i<TABLENGTH(keys);++i) {
if(keys[i].keysym == keysym && keys[i].mod == ke.state) {
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;
wc.width = ev->width;
wc.height = ev->height;
wc.border_width = ev->border_width;
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(dis, ev->window, ev->value_mask, &wc);
}
void destroynotify(XEvent *e) {
int i=0;
client *c;
XDestroyWindowEvent *ev = &e->xdestroywindow;
// Uber (and ugly) hack ;)
for(c=head;c;c=c->next)
if(ev->window == c->win)
i++;
// End of the hack
if(i == 0)
return;
remove_window(ev->window);
tile();
update_current();
}
void die(const char* e) {
fprintf(stdout,"catwm-0.0.4: %s\n",e);
exit(1);
}
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);
return;
}
add_window(ev->window);
XMapWindow(dis,ev->window);
tile();
update_current();
}
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);
fprintf(stdout, "catwm-0.0.2: Thanks for using!\n");
XCloseDisplay(dis);
die("forced 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);
fprintf(stdout,"catwm-0.0.2: You Quit : Thanks for using!\n");
}
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);
}
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);
// Shortcuts
grabkeys();
// Default stack
mode = DEFAULT_MODE;
// For exiting
bool_quit = 0;
// List of client
head = NULL;
current = NULL;
// Master size
if(mode == 0)
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].head = head;
desktops[i].current = current;
}
// Select first dekstop by default
const Arg arg = {.i = 0};
current_desktop = arg.i;
change_desktop(arg);
// To catch maprequest and destroynotify (if other wm running)
XSelectInput(dis,root,SubstructureNotifyMask|SubstructureRedirectMask);
fprintf(stdout,"\n\n catwm-0.0.2: We're up and running!\n");
}
void sigchld(int unused) {
// Again, thx to dwm ;)
if(signal(SIGCHLD, sigchld) == SIG_ERR)
die("Can't install SIGCHLD handler");
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);
}
}
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)))
die("Cannot open display!");
// Setup env
setup();
// Start wm
start();
// Close display
XCloseDisplay(dis);
return 0;
}
config.h
/* config.h for catwm-0.0.2.c
*
* ( o o ) Made by cat...
* ( =^= )
* ( ) ... for cat!
* ( )
* ( ))))))________________ Cute And Tiny Window Manager
* ______________________________________________________________________________
*
* Copyright (c) 2010, Rinaldini Julien, julien.rinaldini@heig-vd.ch
*
* 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/>.
*
* Some changes and additions by P. Newman 24.4.11
* - best not to email julien if you use this... :)
*/
#ifndef CONFIG_H
#define CONFIG_H
/* Mod (Mod1 == alt) and master size
and I added panel size and the windows key (Mod4 == Super)
added shortcuts for different tiling modes
added shortcuts for moving the window to the next workspace and back
*/
#define MOD1 Mod1Mask
#define MOD4 Mod4Mask
#define MASTER_SIZE 0.6
#define PANEL_HEIGHT 20
#define BORDER_WIDTH 4
#define ATTACH_ASIDE 1 /* 0=TRUE, 1=New window is master */
#define DEFAULT_MODE 2 /* 0 = Horizontal, 1 = Fullscreen, 2 = Vertical */
// Colors
#define FOCUS "#664422" // dkorange
#define UNFOCUS "#004050" // blueish
const char* dmenucmd[] = {"dmenu_run","-i","-nb","#664422","-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* mailcmd[] = {"thunderbird",NULL };
const char* voldowncmd[] = {"/home/pnewm/bin/voldown",NULL};
const char* volupcmd[] = {"/home/pnewm/bin/volup",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 struct key keys[] = {
// MOD KEY FUNCTION ARGS
{ MOD1, XK_h, increase, {NULL}},
{ MOD1, XK_l, decrease, {NULL}},
{ 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_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_m, toggle_fullscreen,{NULL}},
{ MOD1|ShiftMask, XK_v, switch_vertical,{NULL}},
{ MOD1|ShiftMask, XK_h, switch_horizontal,{NULL}},
// 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_h, spawn, {.com = thunarcmd}},
{ MOD4, XK_t, spawn, {.com = terminalcmd}},
{ MOD4, XK_v, spawn, {.com = vols_what}},
// Control + alt + shortcut
{ MOD1|ControlMask, XK_q, quit, {NULL}},
{ MOD1|ControlMask, XK_r, spawn, {.com = rebootcmd}},
{ MOD1|ControlMask, XK_s, spawn, {.com = shutdowncmd}},
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
Here's a Makefile for it
CFLAGS+= -Wall
LDADD+= -lX11
LDFLAGS=
EXEC=catwm-0.0.2
PREFIX?= /usr
BINDIR?= $(PREFIX)/bin
CC=gcc
all: $(EXEC)
catwm-0.0.2: catwm-0.0.2.o
$(CC) $(LDFLAGS) -Os -o $@ $+ $(LDADD)
install: all
install -Dm 755 catwm-0.0.2 $(DESTDIR)$(BINDIR)/catwm-0.0.2
clean:
rm -fv catwm-0.0.2 *.o
I pipe conky through dzen2 to get the statusbar at the bottom :
dzen_conky
out_to_x no
out_to_console yes
double_buffer yes
use_spacer left
update_interval 1
no_buffers yes
TEXT
^bg()^fg(\#003040)^pa(350) | Mem: ^fg(\#ffff00)${mem} ^fg(\#003040)| CPU ^fg(\#00ff00)${cpu cpu0}% ^fg(\#003040)|| Down: ^fg(\#6666ff)${downspeed eth0} ^fg(\#003040) | Swap ^fg(\#ff4444) ${swapperc}% ^fg(\#003040) | Temp ^fg(\#44ff44)${acpitemp}C ^fg(\#003040)| ^fg(\#565600)${uptime} ^fg(\#003040) | ^pa(1195) ${time %a %d / %m} ^pa(1300) ^fg(\#007777) ${time %I:%M %P }
and I use ~/.xinitrc to make it all work nice :
.xinitrc
xsetroot -cursor_name left_ptr &
feh --bg-scale '/home/pnewm/.fluxbox/backgrounds/tiles-dark.jpg'
urxvtd -q -f -o &
conky -c /home/pnewm/build/Catwm-0.0.2/dzen_conky | dzen2 -x %x -y 1038 -bg black -fn -*-arial-*-*-*-*-*-*-*-*-*-*-*-* -ta l &
exec /home/pnewm/build/CatWM-0.0.2/src/catwm-0.0.2
I don't know if anyone is still interested in this window manager but I like its' low resource use and configurability
Last edited by moetunes (2011-04-25 05:34:20)
You're just jealous because the voices only talk to me.
Offline
I myself use musca(manual tiler), but this is for sure my favorite automatic-tiling-wm!
The only thing i'm missing in catwm, is that there's no external config file... I know that this is by design, just like dwm, but I just really preffer to be able to update existing configured installs with aur helpers like packer, just like my other used aur apps, without having to mess around with the source and recompile afterwards... Yeah, of course I can make a patch with my config and write a script to patch and update, but nonetheless...
Just a feature-request, allthough i'm sure you disagree, but just in case
Also, another feature-request about having the option to have new windows appear in the master area instead of the stack, like dwm; catwm now works like dwm with the attachaside patch and it would be nice to have the option of using catwm with the normal dwm-like tiling mode also...
Just for fun, then here's a ps_mem.py memory and filesize comparison between catwm(pyknite's, haven't tried moetunes version yet!) and dwm and with musca thrown in additionally.
Memory:
Private + Shared = RAM used Program
176.0 KiB + 83.5 KiB = 259.5 KiB catwm
316.0 KiB + 247.0 KiB = 563.0 KiB dwm
404.0 KiB + 195.0 KiB = 599.0 KiB musca
Filesize:
Targets (1): catwm-git-20110422-1
Total Download Size: 0.00 MB
Total Installed Size: 0.02 MB
Targets (1): dwm-5.8.2-2
Total Download Size: 0.00 MB
Total Installed Size: 0.11 MB
Targets (1): musca-0.9.24-1
Total Download Size: 0.00 MB
Total Installed Size: 0.12 MB
Last edited by mhertz (2011-04-23 00:48:20)
Offline
I'm currently testing running automatic tiling instead of manual on one of my boxes, to see if I maybe will like that better, and so i'm changing between catwm and dwm.
I love catwm as an auto-tiler, but the reason i'm changing back and forth between catwm and dwm, is that catwm uses a little "strange" auto-tiling algo, which is the same as dwm's attachaside patch, which means that new windows gets opened and focused on the stack instead of on the master which unpatched dwm does, and I cannot really decide what is the best approach?
So, could some of you catwm users/devs please tell me why you prefer the "open new windows on the stack instead of master" tiling approach instead of the normal dwm one?
I think most other auto-tilers does the opposite of catwm i.e. like dwm, since it would imho make sence to have new windows opened as the biggest window i.e. master, but there's one case where I can see catwm's method to make sence, and that's when opening a browser first, so thats on master and biggest and then the rest terminals opened are just stacked on the stack, but that approach then needs me to always open my browser first which isn't maybe always the case?(yes, I know i can swap master, but nonetheless).
Any thoughts on this would be highly appreciated!
Edit: Btw, i'm using pyknite's original catwm version and not moetunes "fork", since pyknite's original version features _exactly_ what I need and not a thing more, just the way I like it! I have no need for the added extra features...
Last edited by mhertz (2011-04-23 13:27:03)
Offline
I'm currently testing running automatic tiling instead of manual on one of my boxes, to see if I maybe will like that better, and so i'm changing between catwm and dwm.
I love catwm as an auto-tiler, but the reason i'm changing back and forth between catwm and dwm, is that catwm uses a little "strange" auto-tiling algo, which is the same as dwm's attachaside patch, which means that new windows gets opened and focused on the stack instead of on the master which unpatched dwm does, and I cannot really decide what is the best approach?
So, could some of you catwm users/devs please tell me why you prefer the "open new windows on the stack instead of master" tiling approach instead of the normal dwm one?
I'm not a catwm user, but I do use the attachaside patch for dwm, which replicates this exact feature, as you noted. For me, I prefer this, because I often open my most important window first, and then I want the rest to be slaves. For instance, if I'm doing a homework assignment, I want all the PDFs I have to reference to be on the side, and I open them first because then I have to use my terminal (the same one that launched those PDFs) to edit my LaTeX file with vi.
Hope the feedback helps (I'm sure the reasons for preferring this type of behavior vary).
Last edited by Sara (2011-04-23 18:50:25)
Registed Linux User 483618
Offline
Thanks alot mate! That makes perfect sence to me also!
Much appreciated!
Offline
@ mhertz
If you want catwm to work like standard dwm then comment out the line
update_current();
in the swap_master function and at the end of the add_window function add the line
swap_master();
I've only given it a quick check here but it seems to work fine
You're just jealous because the voices only talk to me.
Offline
A tip for trying out configuration changes in wm's like catwm and dwm :
I login at tty1 and start catwm and do some changes and rebuild catwm then login at tty2 and run
startx -- :1
which starts another X session on tty8. I then put my changes through some tests to see if I keep them.
Hope that's useful
You're just jealous because the voices only talk to me.
Offline
Hey, that's a great tip(dwm-like tiling), man! Thanks alot mate!
However, i'm just gonna keep it like default, as im beginning to get used to this way of doing things...
catwm really rocks and the foot/work-print is unbelieable! Im really beginning to like this wm and am not changing back and forth with dwm any longer!
Still im undecided about what I like the best in case of musca(manual) and catwm(auto) though... I've always used manual tilers(ratpoison and then musca) and never really given the auto-tilers any chance...
Damn, I hate it- when I cannot decide between things! lol...
CU, Martin.
Edit: In the end I must say that I prefer manual tiling with musca still, but nonetheless, then kudos to pyknite and moetunes for making one heck of an awesome auto-tiler, and which seriously gives dwm a run for it's money(that is if you don't use floating windows, however...)
Last edited by mhertz (2011-04-23 23:14:10)
Offline
Here's a different add_window function that will always add a new window as the master. It also places the current master window at the top of the stack so it will be the master window again when that new window gets closed.
void add_window(Window w) {
client *c,*t;
if(!(c = (client *)calloc(1,sizeof(client))))
die("Error calloc!");
if(head == NULL) {
c->next = NULL;
c->prev = NULL;
c->win = w;
head = 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);
}
Last edited by moetunes (2011-04-24 20:38:02)
You're just jealous because the voices only talk to me.
Offline
Great contribution! NIce work, mate!
Offline
The original add_window function I posted above did a good job of rearranging windows but didn't order the stack so there were issues with window deletion, moving etc. So I replaced it with one that does the same thing but orders the stack this time...
You're just jealous because the voices only talk to me.
Offline
I updated post #152 to reflect what I've settled on using after this round of playing with catwm.
(thanks pyknite)
- 3 tiling modes
with the default set in the config file
with keyboard shortcuts to use them
catwm remembers which mode for each desktop for the session
- normal catwm tiling ( like dwm with the attach aside patch)
or where the new window becomes the master(like the defaults in dwm etc)
choice of which is set in the config file
- room to run a panel like dzen at the bottom
with the height set in the config file
- removed the write to file stuff as tiling and workspace changes are stable now
With such a small code base it is easy enough to try stuff out
You're just jealous because the voices only talk to me.
Offline
Thanks for your efforts moetunes! Your version sounds pretty sweet and I wanted to test it, but i'm getting this when running make:
[martin@arch catwm]$ make
gcc -Wall -c -o catwm-0.0.2.o catwm-0.0.2.c
gcc -Os -o catwm-0.0.2 catwm-0.0.2.o -lX11
/usr/lib/gcc/i686-pc-linux-gnu/4.6.0/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status
make: *** [catwm-0.0.2] Error 1
I think it's probably because when I copy/paste from those codeboxes and into vim, then the code gets garbled and isn't adjusted right...
If you want, then you could put the files on e.g. pastebin or something(or tarball on public dropbox etc, etc.).
However, I would recommend that you either fork it and put it on aur, or you contact pyknite and ask him for taking over the project and it's aur package...
Thanks again!
Offline
@mhertz
It works ok here pasting into leafpad so it might be something about your vim or you missed a bit of the file or who knows...
I'm not looking to take over the project I want to play with some c programming sometimes and this is a fun little app to play with since the codebase is small.
I don't think there'd be too many people using catwm as their daily wm and if too much is added to it it won't be cute and tiny anymore
On another note I'm still not ordering the stack properly when not using it like the original catwm (when ATTACH_ASIDE = 1) so if you try my changes be aware that catwm might crash when you move windows to other desktops...
You're just jealous because the voices only talk to me.
Offline
The pic in post #152 shows what happens when opening a file manager then a couple of text editors with the default catwm way of ordering the windows.
Doing the same thing with the new window being the master like default dwm does gives
I like it this way
You're just jealous because the voices only talk to me.
Offline
Hi again, mate!
Hmm, when I copy/pasted with vim, then I did it the unix way of marking the text without copying and then shift+insert into vim in insert mode, which I always do with everything else, but that failed during building the app...
Now after you mentioned leafpad, then I to test did install it and this time actually did a windows-like copy/paste into leafpad, and it also failed that time, but with another error; the copy/pasted text wasen't mangled in this way, but there where missing some TABs in the makefile, i.e. line 14, 17 and 20 should have replaced it's preliminary space with actual Tabs and then it would build... Also just a FYI to others interested in trying this nice WM out!
Anyway, I commend you on a job well done! It's a great version of catwm you've made there and the new features are very nice without bloating up the codebase with useless stuff!
Also the memory is the same as previous, as I checked it again with ps_mem.py; both the original and yours starts up at about 325kb and over some minutes goes further down alittle to about 290kb! Just simply awesome!
As I previously stated, then i'm prefering manual ratpoison-like tiling, and so isn't using catwm but musca, but I would seriously recommend other ppl which prefers auto-tiling to check out this little piece of awesomeness, and now with moetunes help, then it rocks even better than before!
Nice job again and thanks for a great contribution, mate!
CU, Martin.
Last edited by mhertz (2011-04-26 00:09:11)
Offline
I've been having another play with catwm and have removed the popup urxvtc 'cause I fixed a bad window error killing the wm and have fixed up the numlock being on stopping the keyboard shortcuts from working. It's still the lightest wm I've found
You're just jealous because the voices only talk to me.
Offline
Thanks moetunes!
I cannot see you have edited your catvm-0-02 source with these changes? Btw, it would be nice if you could place your code on github or some other place e.g. pastebin or whatever... Also, since when copy/pasting, then you need to add tabs in the makefile... Then you could just update it whenever you have the motivation...
Offline
I should find somewhere to host it as I'm going to keep playing with it and someone might find it useful.
I've just added follow mouse option to it with 17 new lines and it's settable in the config and I haven't been able to crash it in ages.
Cheers
You're just jealous because the voices only talk to me.
Offline
I've set up a github account so the files are accessible here :
github.
If there's interest I'll start a post about it 'cause I'll keep playing with it for a while yet
edit: I should say I've started calling it DMiniWM as it is no longer the cute and tiny window manager the original author left it as, though it is still tiny.
Last edited by moetunes (2011-08-20 08:33:59)
You're just jealous because the voices only talk to me.
Offline
I've set up a github account so the files are accessible here :
github.
If there's interest I'll start a post about it 'cause I'll keep playing with it for a while yetedit: I should say I've started calling it DMiniWM as it is no longer the cute and tiny window manager the original author left it as, though it is still tiny.
It's great to see that you've picked up on the wm. However, I do believe that you need to retain mention of catwm in your license, as it is a fork and still contains a lot of code from the original project.
Offline
'snip'
It's great to see that you've picked up on the wm. However, I do believe that you need to retain mention of catwm in your license, as it is a fork and still contains a lot of code from the original project.
Cheers for that
I'd appreciate an idea of the sort of references required as the whole framework is pyknites' but I can't say that he is still interested in it so I don't want to include his email address e.g. Or should I just still call it catwm ?
Last edited by moetunes (2011-08-20 10:05:53)
You're just jealous because the voices only talk to me.
Offline
I've added my xcb port of this - without keyboard shortcuts yet - to github if anyone wants to have a play with it.
You're just jealous because the voices only talk to me.
Offline