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:
M | catwm.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;