added mouse-based resizals
Anselm R. Garbe garbeam@wmii.de
Tue, 11 Jul 2006 21:24:10 +0200
M
Makefile
→
Makefile
@@ -3,7 +3,7 @@ # (C)opyright MMVI Anselm R. Garbe
include config.mk -WMSRC = bar.c client.c cmd.c draw.c event.c key.c util.c wm.c +WMSRC = bar.c client.c cmd.c draw.c event.c kb.c mouse.c util.c wm.c WMOBJ = ${WMSRC:.c=.o} MENSRC = menu.c draw.c util.c MENOBJ = ${MENSRC:.c=.o}
M
README
→
README
@@ -5,14 +5,6 @@ gridwm is an extremly fast, small, and automatic X11 window manager. It
arranges all windows in a grid. -Configuration -------------- -You have to edit the source code for configuration, this WM is intended to -provide sane defaults, if something doesn't fits your needs, edit config.h and -maybe key.c. To change the status output edit that status variable definition -in wm.c. - - Requirements ------------ In order to build gridwm you need the Xlib header files.@@ -46,6 +38,6 @@
Configuration ------------- The configuration of gridwm is done by customizing the config.h source file. To -customize the key bindings edit key.c. To change the status output, edit the +customize the key bindings edit kb.c. To change the status output, edit the status command definition in wm.c.
M
client.c
→
client.c
@@ -10,6 +10,8 @@
#include "util.h" #include "wm.h" +#define CLIENT_MASK (StructureNotifyMask | PropertyChangeMask | EnterWindowMask) + void update_name(Client *c) {@@ -70,7 +72,7 @@ c->r[RFloat].width = wa->width;
c->r[RFloat].height = wa->height; c->border = wa->border_width; XSetWindowBorderWidth(dpy, c->win, 0); - XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | EnterWindowMask); + XSelectInput(dpy, c->win, CLIENT_MASK); XGetTransientForHint(dpy, c->win, &c->trans); if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags) c->size.flags = PSize;@@ -95,9 +97,34 @@ *l = c;
c->snext = stack; stack = c; XMapWindow(dpy, c->win); + XGrabButton(dpy, AnyButton, Mod1Mask, c->win, False, ButtonPressMask, + GrabModeAsync, GrabModeSync, None, None); focus(c); } +void +resize(Client *c) +{ + XConfigureEvent e; + + XMoveResizeWindow(dpy, c->win, c->r[RFloat].x, c->r[RFloat].y, + c->r[RFloat].width, c->r[RFloat].height); + e.type = ConfigureNotify; + e.event = c->win; + e.window = c->win; + e.x = c->r[RFloat].x; + e.y = c->r[RFloat].y; + e.width = c->r[RFloat].width; + e.height = c->r[RFloat].height; + e.border_width = c->border; + e.above = None; + e.override_redirect = False; + XSelectInput(dpy, c->win, CLIENT_MASK & ~StructureNotifyMask); + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e); + XSelectInput(dpy, c->win, CLIENT_MASK); + XFlush(dpy); +} + static int dummy_error_handler(Display *dpy, XErrorEvent *error) {@@ -112,6 +139,7 @@
XGrabServer(dpy); XSetErrorHandler(dummy_error_handler); + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUnmapWindow(dpy, c->win); XDestroyWindow(dpy, c->title);@@ -126,7 +154,7 @@
XFlush(dpy); XSetErrorHandler(error_handler); XUngrabServer(dpy); - flush_events(EnterWindowMask); + discard_events(EnterWindowMask); if(stack) focus(stack); }
M
event.c
→
event.c
@@ -12,6 +12,7 @@
#include "wm.h" /* local functions */ +static void buttonpress(XEvent *e); static void configurerequest(XEvent *e); static void destroynotify(XEvent *e); static void enternotify(XEvent *e);@@ -23,6 +24,7 @@ static void propertynotify(XEvent *e);
static void unmapnotify(XEvent *e); void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, [ConfigureRequest] = configurerequest, [DestroyNotify] = destroynotify, [EnterNotify] = enternotify,@@ -36,7 +38,7 @@ [UnmapNotify] = unmapnotify
}; unsigned int -flush_events(long even_mask) +discard_events(long even_mask) { XEvent ev; unsigned int n = 0;@@ -45,15 +47,37 @@ return n;
} static void +buttonpress(XEvent *e) +{ + XButtonPressedEvent *ev = &e->xbutton; + Client *c; + + if((c = getclient(ev->window))) { + switch(ev->button) { + default: + break; + case Button1: + mmove(c); + break; + case Button2: + XLowerWindow(dpy, c->win); + break; + case Button3: + mresize(c); + break; + } + } +} + +static void configurerequest(XEvent *e) { XConfigureRequestEvent *ev = &e->xconfigurerequest; XWindowChanges wc; Client *c; - c = getclient(ev->window); ev->value_mask &= ~CWSibling; - if(c) { + if((c = getclient(ev->window))) { if(ev->value_mask & CWX) c->r[RFloat].x = ev->x; if(ev->value_mask & CWY)
A
mouse.c
@@ -0,0 +1,100 @@
+/* + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> + * (C)opyright MMVI Kris Maglione <fbsdaemon@gmail.com> + * See LICENSE file for license details. + */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "wm.h" + +#define ButtonMask (ButtonPressMask | ButtonReleaseMask) +#define MouseMask (ButtonMask | PointerMotionMask) + +static void +mmatch(Client *c, int x1, int y1, int x2, int y2) +{ + c->r[RFloat].width = abs(x1 - x2); + c->r[RFloat].height = abs(y1 - y2); + c->r[RFloat].width -= + (c->r[RFloat].width - c->size.base_width) % c->size.width_inc; + c->r[RFloat].height -= + (c->r[RFloat].height - c->size.base_height) % c->size.height_inc; + if(c->size.min_width && c->r[RFloat].width < c->size.min_width) + c->r[RFloat].width = c->size.min_width; + if(c->size.min_height && c->r[RFloat].height < c->size.min_height) + c->r[RFloat].height = c->size.min_height; + if(c->size.max_width && c->r[RFloat].width > c->size.max_width) + c->r[RFloat].width = c->size.max_width; + if(c->size.max_height && c->r[RFloat].height > c->size.max_height) + c->r[RFloat].height = c->size.max_height; + c->r[RFloat].x = (x1 <= x2) ? x1 : x1 - c->r[RFloat].width; + c->r[RFloat].y = (y1 <= y2) ? y1 : y1 - c->r[RFloat].height; +} + +void +mresize(Client *c) +{ + XEvent ev; + int old_cx, old_cy; + + old_cx = c->r[RFloat].x; + old_cy = c->r[RFloat].y; + if(XGrabPointer(dpy, c->win, False, MouseMask, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize], CurrentTime) != GrabSuccess) + return; + XGrabServer(dpy); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, + c->r[RFloat].width, c->r[RFloat].height); + for(;;) { + XMaskEvent(dpy, MouseMask, &ev); + switch(ev.type) { + default: break; + case MotionNotify: + XUngrabServer(dpy); + mmatch(c, old_cx, old_cy, ev.xmotion.x, ev.xmotion.y); + resize(c); + XGrabServer(dpy); + break; + case ButtonRelease: + XUngrabPointer(dpy, CurrentTime); + return; + } + } +} + +void +mmove(Client *c) +{ + XEvent ev; + int x1, y1, old_cx, old_cy, di; + unsigned int dui; + Window dummy; + + old_cx = c->r[RFloat].x; + old_cy = c->r[RFloat].y; + if(XGrabPointer(dpy, c->win, False, MouseMask, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove], CurrentTime) != GrabSuccess) + return; + XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); + XGrabServer(dpy); + for(;;) { + XMaskEvent(dpy, MouseMask, &ev); + switch (ev.type) { + default: break; + case MotionNotify: + XUngrabServer(dpy); + c->r[RFloat].x = old_cx + (ev.xmotion.x - x1); + c->r[RFloat].y = old_cy + (ev.xmotion.y - y1); + resize(c); + XGrabServer(dpy); + break; + case ButtonRelease: + XUngrabServer(dpy); + XUngrabPointer(dpy, CurrentTime); + return; + } + } +}
M
wm.h
→
wm.h
@@ -11,6 +11,22 @@ #include <X11/Xutil.h>
#define WM_PROTOCOL_DELWIN 1 +typedef struct Client Client; +typedef struct Key Key; +typedef enum Align Align; + +enum Align { + NORTH = 0x01, + EAST = 0x02, + SOUTH = 0x04, + WEST = 0x08, + NEAST = NORTH | EAST, + NWEST = NORTH | WEST, + SEAST = SOUTH | EAST, + SWEST = SOUTH | WEST, + CENTER = NEAST | SWEST +}; + /* atoms */ enum { WMProtocols, WMDelete, WMLast }; enum { NetSupported, NetWMName, NetLast };@@ -20,9 +36,6 @@ enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
/* rects */ enum { RFloat, RGrid, RLast }; - -typedef struct Client Client; -typedef struct Key Key; struct Client { char name[256];@@ -75,13 +88,18 @@ extern Client *getclient(Window w);
extern void focus(Client *c); extern void update_name(Client *c); extern void draw_client(Client *c); +extern void resize(Client *c); /* event.c */ -extern unsigned int flush_events(long even_mask); +extern unsigned int discard_events(long even_mask); /* key.c */ extern void update_keys(); extern void keypress(XEvent *e); + +/* mouse.c */ +extern void mresize(Client *c); +extern void mmove(Client *c); /* wm.c */ extern int error_handler(Display *dpy, XErrorEvent *error);