catwm: Add mouse support.

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

107
catwm.c
View File

@ -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
[ConfigureRequest] = configurerequest,
[ButtonPress] = buttonpress,
[ButtonRelease] = buttonrelease,
[MotionNotify] = motionnotify
};
// Desktop array
@ -168,6 +174,8 @@ 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) {
@ -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);
// Shortcuts
grabkeys();
// Vertical stack
mode = 0;
// For exiting
bool_quit = 0;
// 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;