catwm: Add mouse support.

This commit is contained in:
Dylan Araps 2019-10-11 18:00:00 +03:00
parent cc230ed503
commit 0ac53bd8b3

127
catwm.c
View File

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