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
127
catwm.c
127
catwm.c
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user