mirror of
https://github.com/dylanaraps/sowm.git
synced 2025-05-19 09:30:24 -07:00
catwm: Add mouse support.
This commit is contained in:
parent
cc230ed503
commit
0ac53bd8b3
109
catwm.c
109
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
|
||||
[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);
|
||||
|
||||
// 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user