sowm

An itsy bitsy floating window manager (220~ sloc!).
git clone git://mfeller.io/sowm.git
Log | Files | Refs | README | LICENSE

commit 0ac53bd8b303502c3cc1d83e1808d1cc6688611d
parent cc230ed5033f903efb951f065ced5ecbc34b0fe2
Author: Dylan Araps <dylan.araps@gmail.com>
Date:   Fri, 11 Oct 2019 18:00:00 +0300

catwm: Add mouse support.

Diffstat:
Mcatwm.c | 127++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 84 insertions(+), 43 deletions(-)

diff --git a/catwm.c b/catwm.c @@ -40,6 +40,7 @@ #include <sys/wait.h> #define TABLENGTH(X) (sizeof(X)/sizeof(*X)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) typedef union { const char** com; @@ -56,11 +57,9 @@ struct key { typedef struct client client; struct client{ - // Prev and next client client *next; client *prev; - // The window Window win; }; @@ -74,9 +73,10 @@ struct desktop{ // Functions static void add_window(Window w); +static void buttonpress(XEvent *e); +static void buttonrelease(XEvent *e); 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 die(const char* e); @@ -84,6 +84,7 @@ static void grabkeys(); static void keypress(XEvent *e); static void kill_client(); static void maprequest(XEvent *e); +static void motionnotify(XEvent *e); static void next_win(); static void remove_window(Window w); static void save_desktop(int i); @@ -92,7 +93,8 @@ 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 init(); +static void update_current(); // Include configuration file (need struct key) #include "config.h" @@ -109,14 +111,18 @@ static int screen; static Window root; static client *head; static client *current; +static XWindowAttributes attr; +static XButtonEvent start; // Events array static void (*events[LASTEvent])(XEvent *e) = { - [KeyPress] = keypress, - [MapRequest] = maprequest, - [DestroyNotify] = destroynotify, - [ConfigureNotify] = configurenotify, - [ConfigureRequest] = configurerequest + [KeyPress] = keypress, + [MapRequest] = maprequest, + [DestroyNotify] = destroynotify, + [ConfigureRequest] = configurerequest, + [ButtonPress] = buttonpress, + [ButtonRelease] = buttonrelease, + [MotionNotify] = motionnotify }; // Desktop array @@ -168,13 +174,15 @@ void change_desktop(const Arg arg) { if(head != NULL) for(c=head;c;c=c->next) XMapWindow(dis,c->win); + + update_current(); } void client_to_desktop(const Arg arg) { client *tmp = current; int tmp2 = current_desktop; - if(arg.i == current_desktop || current == NULL) + if (arg.i == current_desktop || current == NULL) return; // Add client to desktop @@ -185,10 +193,8 @@ void client_to_desktop(const Arg arg) { // Remove client from current desktop select_desktop(tmp2); remove_window(current->win); -} -void configurenotify(XEvent *e) { - // Do nothing for the moment + update_current(); } void configurerequest(XEvent *e) { @@ -220,6 +226,18 @@ void destroynotify(XEvent *e) { return; remove_window(ev->window); + update_current(); +} + +void update_current() { + client *c; + + for(c=head;c;c=c->next) + if(current == c) { + XSetWindowBorderWidth(dis,c->win,1); + XSetInputFocus(dis,c->win,RevertToParent,CurrentTime); + XRaiseWindow(dis,c->win); + } } void die(const char* e) { @@ -251,6 +269,34 @@ void keypress(XEvent *e) { } } +void buttonpress(XEvent *e) { + XButtonEvent bu = e->xbutton; + + if (bu.subwindow != None) { + XGetWindowAttributes(dis, bu.subwindow, &attr); + start = bu; + } +} + +void motionnotify(XEvent *e) { + XButtonEvent bu = e->xbutton; + + if (start.subwindow != None) { + int xdiff = bu.x_root - start.x_root; + int ydiff = bu.y_root - start.y_root; + + XMoveResizeWindow(dis, start.subwindow, + attr.x + (start.button==1 ? xdiff : 0), + attr.y + (start.button==1 ? ydiff : 0), + MAX(1, attr.width + (start.button==3 ? xdiff : 0)), + MAX(1, attr.height + (start.button==3 ? ydiff : 0))); + } +} + +void buttonrelease(XEvent *e) { + start.subwindow = None; +} + void kill_client() { if(current != NULL) { //send delete signal to window @@ -279,6 +325,7 @@ void maprequest(XEvent *e) { add_window(ev->window); XMapWindow(dis,ev->window); + update_current(); } void next_win() { @@ -291,6 +338,7 @@ void next_win() { c = current->next; current = c; + update_current(); } } @@ -356,34 +404,22 @@ void send_kill_signal(Window w) { } 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); - sh = XDisplayHeight(dis,screen); + root = RootWindow(dis,screen); + sw = XDisplayWidth(dis,screen); + sh = XDisplayHeight(dis,screen); - // Shortcuts grabkeys(); - // Vertical stack - mode = 0; - - // For exiting + mode = 0; bool_quit = 0; + head = NULL; + current = NULL; - // List of client - head = NULL; - current = NULL; - - // Master size master_size = sw*MASTER_SIZE; - // Set up all desktop int i; for(i=0;i<TABLENGTH(desktops);++i) { desktops[i].master_size = master_size; @@ -392,27 +428,24 @@ void setup() { desktops[i].current = current; } - // Select first dekstop by default const Arg arg = {.i = 1}; current_desktop = arg.i; change_desktop(arg); - // To catch maprequest and destroynotify (if other wm running) XSelectInput(dis,root,SubstructureNotifyMask|SubstructureRedirectMask); } 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)); + if(dis) close(ConnectionNumber(dis)); setsid(); execvp((char*)arg.com[0],(char**)arg.com); @@ -421,14 +454,22 @@ void spawn(const Arg arg) { } } -void start() { +void init() { XEvent ev; - // Main loop, just dispatch events (thx to dwm ;) - while(!bool_quit && !XNextEvent(dis,&ev)) { - if(events[ev.type]) - events[ev.type](&ev); - } + XGrabKey(dis, XKeysymToKeycode(dis, XStringToKeysym("F1")), Mod4Mask, + DefaultRootWindow(dis), True, GrabModeAsync, GrabModeAsync); + + XGrabButton(dis, 1, Mod4Mask, DefaultRootWindow(dis), True, + ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None); + + XGrabButton(dis, 3, Mod4Mask, DefaultRootWindow(dis), True, + ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None); + + start.subwindow = None; + + while(!bool_quit && !XNextEvent(dis,&ev)) + if (events[ev.type]) events[ev.type](&ev); } int main(int argc, char **argv) { @@ -436,7 +477,7 @@ int main(int argc, char **argv) { die("Cannot open display!"); setup(); - start(); + init(); XCloseDisplay(dis); return 0;