tadded mouse-based resizals - dwm - [fork] customized build of dwm, the dynamic window manager
 (HTM) git clone git://src.adamsgaard.dk/dwm
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit b9da4b082eb658b4142b61c149212f414f7653b6
 (DIR) parent 5ed16faecb94b551ea00ea940e8d719211576de8
 (HTM) Author: Anselm R. Garbe <garbeam@wmii.de>
       Date:   Tue, 11 Jul 2006 21:24:10 +0200
       
       added mouse-based resizals
       
       Diffstat:
         M Makefile                            |       2 +-
         M README                              |      10 +---------
         M client.c                            |      32 +++++++++++++++++++++++++++++--
         M event.c                             |      30 +++++++++++++++++++++++++++---
         R key.c -> kb.c                       |       0 
         A mouse.c                             |     100 +++++++++++++++++++++++++++++++
         M wm.h                                |      26 ++++++++++++++++++++++----
       
       7 files changed, 181 insertions(+), 19 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       t@@ -3,7 +3,7 @@
        
        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}
 (DIR) diff --git a/README b/README
       t@@ -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.
       t@@ -46,6 +38,6 @@ This will start gridwm on display :1 of the host foo.bar.
        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.
        
 (DIR) diff --git a/client.c b/client.c
       t@@ -10,6 +10,8 @@
        #include "util.h"
        #include "wm.h"
        
       +#define CLIENT_MASK                (StructureNotifyMask | PropertyChangeMask | EnterWindowMask)
       +
        void
        update_name(Client *c)
        {
       t@@ -70,7 +72,7 @@ manage(Window w, XWindowAttributes *wa)
                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;
       t@@ -95,9 +97,34 @@ manage(Window w, XWindowAttributes *wa)
                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)
        {
       t@@ -112,6 +139,7 @@ unmanage(Client *c)
                XGrabServer(dpy);
                XSetErrorHandler(dummy_error_handler);
        
       +        XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
                XUnmapWindow(dpy, c->win);
                XDestroyWindow(dpy, c->title);
        
       t@@ -126,7 +154,7 @@ unmanage(Client *c)
                XFlush(dpy);
                XSetErrorHandler(error_handler);
                XUngrabServer(dpy);
       -        flush_events(EnterWindowMask);
       +        discard_events(EnterWindowMask);
                if(stack)
                        focus(stack);
        }
 (DIR) diff --git a/event.c b/event.c
       t@@ -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);
       t@@ -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,
       t@@ -36,7 +38,7 @@ void (*handler[LASTEvent]) (XEvent *) = {
        };
        
        unsigned int
       -flush_events(long even_mask)
       +discard_events(long even_mask)
        {
                XEvent ev;
                unsigned int n = 0;
       t@@ -45,15 +47,37 @@ flush_events(long even_mask)
        }
        
        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)
 (DIR) diff --git a/key.c b/kb.c
 (DIR) diff --git a/mouse.c b/mouse.c
       t@@ -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;
       +                }
       +        }
       +}
 (DIR) diff --git a/wm.h b/wm.h
       t@@ -11,6 +11,22 @@
        
        #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 };
       t@@ -21,9 +37,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];
                char tag[256];
       t@@ -75,14 +88,19 @@ 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);
        extern void send_message(Window w, Atom a, long value);