dwm-meillo
changeset 18:1efa34c6e1b6
added mouse-based resizals
author | Anselm R. Garbe <garbeam@wmii.de> |
---|---|
date | Tue, 11 Jul 2006 21:24:10 +0200 |
parents | aaf520f53110 |
children | b5510d0c6d43 |
files | Makefile README client.c event.c kb.c mouse.c wm.h |
diffstat | 8 files changed, 236 insertions(+), 74 deletions(-) [+] |
line diff
1.1 --- a/Makefile Tue Jul 11 18:59:09 2006 +0200 1.2 +++ b/Makefile Tue Jul 11 21:24:10 2006 +0200 1.3 @@ -3,7 +3,7 @@ 1.4 1.5 include config.mk 1.6 1.7 -WMSRC = bar.c client.c cmd.c draw.c event.c key.c util.c wm.c 1.8 +WMSRC = bar.c client.c cmd.c draw.c event.c kb.c mouse.c util.c wm.c 1.9 WMOBJ = ${WMSRC:.c=.o} 1.10 MENSRC = menu.c draw.c util.c 1.11 MENOBJ = ${MENSRC:.c=.o}
2.1 --- a/README Tue Jul 11 18:59:09 2006 +0200 2.2 +++ b/README Tue Jul 11 21:24:10 2006 +0200 2.3 @@ -5,14 +5,6 @@ 2.4 arranges all windows in a grid. 2.5 2.6 2.7 -Configuration 2.8 -------------- 2.9 -You have to edit the source code for configuration, this WM is intended to 2.10 -provide sane defaults, if something doesn't fits your needs, edit config.h and 2.11 -maybe key.c. To change the status output edit that status variable definition 2.12 -in wm.c. 2.13 - 2.14 - 2.15 Requirements 2.16 ------------ 2.17 In order to build gridwm you need the Xlib header files. 2.18 @@ -46,6 +38,6 @@ 2.19 Configuration 2.20 ------------- 2.21 The configuration of gridwm is done by customizing the config.h source file. To 2.22 -customize the key bindings edit key.c. To change the status output, edit the 2.23 +customize the key bindings edit kb.c. To change the status output, edit the 2.24 status command definition in wm.c. 2.25
3.1 --- a/client.c Tue Jul 11 18:59:09 2006 +0200 3.2 +++ b/client.c Tue Jul 11 21:24:10 2006 +0200 3.3 @@ -10,6 +10,8 @@ 3.4 #include "util.h" 3.5 #include "wm.h" 3.6 3.7 +#define CLIENT_MASK (StructureNotifyMask | PropertyChangeMask | EnterWindowMask) 3.8 + 3.9 void 3.10 update_name(Client *c) 3.11 { 3.12 @@ -70,7 +72,7 @@ 3.13 c->r[RFloat].height = wa->height; 3.14 c->border = wa->border_width; 3.15 XSetWindowBorderWidth(dpy, c->win, 0); 3.16 - XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | EnterWindowMask); 3.17 + XSelectInput(dpy, c->win, CLIENT_MASK); 3.18 XGetTransientForHint(dpy, c->win, &c->trans); 3.19 if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags) 3.20 c->size.flags = PSize; 3.21 @@ -95,9 +97,34 @@ 3.22 c->snext = stack; 3.23 stack = c; 3.24 XMapWindow(dpy, c->win); 3.25 + XGrabButton(dpy, AnyButton, Mod1Mask, c->win, False, ButtonPressMask, 3.26 + GrabModeAsync, GrabModeSync, None, None); 3.27 focus(c); 3.28 } 3.29 3.30 +void 3.31 +resize(Client *c) 3.32 +{ 3.33 + XConfigureEvent e; 3.34 + 3.35 + XMoveResizeWindow(dpy, c->win, c->r[RFloat].x, c->r[RFloat].y, 3.36 + c->r[RFloat].width, c->r[RFloat].height); 3.37 + e.type = ConfigureNotify; 3.38 + e.event = c->win; 3.39 + e.window = c->win; 3.40 + e.x = c->r[RFloat].x; 3.41 + e.y = c->r[RFloat].y; 3.42 + e.width = c->r[RFloat].width; 3.43 + e.height = c->r[RFloat].height; 3.44 + e.border_width = c->border; 3.45 + e.above = None; 3.46 + e.override_redirect = False; 3.47 + XSelectInput(dpy, c->win, CLIENT_MASK & ~StructureNotifyMask); 3.48 + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e); 3.49 + XSelectInput(dpy, c->win, CLIENT_MASK); 3.50 + XFlush(dpy); 3.51 +} 3.52 + 3.53 static int 3.54 dummy_error_handler(Display *dpy, XErrorEvent *error) 3.55 { 3.56 @@ -112,6 +139,7 @@ 3.57 XGrabServer(dpy); 3.58 XSetErrorHandler(dummy_error_handler); 3.59 3.60 + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); 3.61 XUnmapWindow(dpy, c->win); 3.62 XDestroyWindow(dpy, c->title); 3.63 3.64 @@ -126,7 +154,7 @@ 3.65 XFlush(dpy); 3.66 XSetErrorHandler(error_handler); 3.67 XUngrabServer(dpy); 3.68 - flush_events(EnterWindowMask); 3.69 + discard_events(EnterWindowMask); 3.70 if(stack) 3.71 focus(stack); 3.72 }
4.1 --- a/event.c Tue Jul 11 18:59:09 2006 +0200 4.2 +++ b/event.c Tue Jul 11 21:24:10 2006 +0200 4.3 @@ -12,6 +12,7 @@ 4.4 #include "wm.h" 4.5 4.6 /* local functions */ 4.7 +static void buttonpress(XEvent *e); 4.8 static void configurerequest(XEvent *e); 4.9 static void destroynotify(XEvent *e); 4.10 static void enternotify(XEvent *e); 4.11 @@ -23,6 +24,7 @@ 4.12 static void unmapnotify(XEvent *e); 4.13 4.14 void (*handler[LASTEvent]) (XEvent *) = { 4.15 + [ButtonPress] = buttonpress, 4.16 [ConfigureRequest] = configurerequest, 4.17 [DestroyNotify] = destroynotify, 4.18 [EnterNotify] = enternotify, 4.19 @@ -36,7 +38,7 @@ 4.20 }; 4.21 4.22 unsigned int 4.23 -flush_events(long even_mask) 4.24 +discard_events(long even_mask) 4.25 { 4.26 XEvent ev; 4.27 unsigned int n = 0; 4.28 @@ -45,15 +47,37 @@ 4.29 } 4.30 4.31 static void 4.32 +buttonpress(XEvent *e) 4.33 +{ 4.34 + XButtonPressedEvent *ev = &e->xbutton; 4.35 + Client *c; 4.36 + 4.37 + if((c = getclient(ev->window))) { 4.38 + switch(ev->button) { 4.39 + default: 4.40 + break; 4.41 + case Button1: 4.42 + mmove(c); 4.43 + break; 4.44 + case Button2: 4.45 + XLowerWindow(dpy, c->win); 4.46 + break; 4.47 + case Button3: 4.48 + mresize(c); 4.49 + break; 4.50 + } 4.51 + } 4.52 +} 4.53 + 4.54 +static void 4.55 configurerequest(XEvent *e) 4.56 { 4.57 XConfigureRequestEvent *ev = &e->xconfigurerequest; 4.58 XWindowChanges wc; 4.59 Client *c; 4.60 4.61 - c = getclient(ev->window); 4.62 ev->value_mask &= ~CWSibling; 4.63 - if(c) { 4.64 + if((c = getclient(ev->window))) { 4.65 if(ev->value_mask & CWX) 4.66 c->r[RFloat].x = ev->x; 4.67 if(ev->value_mask & CWY)
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/kb.c Tue Jul 11 21:24:10 2006 +0200 5.3 @@ -0,0 +1,55 @@ 5.4 +/* 5.5 + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> 5.6 + * See LICENSE file for license details. 5.7 + */ 5.8 + 5.9 +#include "wm.h" 5.10 + 5.11 +#include <X11/keysym.h> 5.12 + 5.13 +static const char *term[] = { 5.14 + "xterm", "-u8", "-bg", "black", "-fg", "white", "-fn", 5.15 + "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*", 0 5.16 +}; 5.17 + 5.18 +static const char *proglist[] = { 5.19 + "sh", "-c", "exec `ls -lL /bin /sbin /usr/bin /usr/local/bin 2>/dev/null | awk 'NF>2 && $1 ~ /^[^d].*x/ {print $NF}' | sort | uniq | gridmenu`", 0 5.20 +}; 5.21 + 5.22 +static Key key[] = { 5.23 + { Mod1Mask, XK_Return, run, term }, 5.24 + { Mod1Mask, XK_p, run, proglist }, 5.25 + { Mod1Mask | ShiftMask, XK_c, kill, NULL}, 5.26 + { Mod1Mask | ShiftMask, XK_q, quit, NULL}, 5.27 +}; 5.28 + 5.29 +void 5.30 +update_keys() 5.31 +{ 5.32 + unsigned int i, len; 5.33 + KeyCode code; 5.34 + 5.35 + len = sizeof(key) / sizeof(key[0]); 5.36 + for(i = 0; i < len; i++) { 5.37 + code = XKeysymToKeycode(dpy, key[i].keysym); 5.38 + XUngrabKey(dpy, code, key[i].mod, root); 5.39 + XGrabKey(dpy, code, key[i].mod, root, True, GrabModeAsync, GrabModeAsync); 5.40 + } 5.41 +} 5.42 + 5.43 +void 5.44 +keypress(XEvent *e) 5.45 +{ 5.46 + XKeyEvent *ev = &e->xkey; 5.47 + unsigned int i, len; 5.48 + KeySym keysym; 5.49 + 5.50 + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); 5.51 + len = sizeof(key) / sizeof(key[0]); 5.52 + for(i = 0; i < len; i++) 5.53 + if((keysym == key[i].keysym) && (key[i].mod == ev->state)) { 5.54 + if(key[i].func) 5.55 + key[i].func(key[i].aux); 5.56 + return; 5.57 + } 5.58 +}
6.1 --- a/key.c Tue Jul 11 18:59:09 2006 +0200 6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 6.3 @@ -1,55 +0,0 @@ 6.4 -/* 6.5 - * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> 6.6 - * See LICENSE file for license details. 6.7 - */ 6.8 - 6.9 -#include "wm.h" 6.10 - 6.11 -#include <X11/keysym.h> 6.12 - 6.13 -static const char *term[] = { 6.14 - "xterm", "-u8", "-bg", "black", "-fg", "white", "-fn", 6.15 - "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*", 0 6.16 -}; 6.17 - 6.18 -static const char *proglist[] = { 6.19 - "sh", "-c", "exec `ls -lL /bin /sbin /usr/bin /usr/local/bin 2>/dev/null | awk 'NF>2 && $1 ~ /^[^d].*x/ {print $NF}' | sort | uniq | gridmenu`", 0 6.20 -}; 6.21 - 6.22 -static Key key[] = { 6.23 - { Mod1Mask, XK_Return, run, term }, 6.24 - { Mod1Mask, XK_p, run, proglist }, 6.25 - { Mod1Mask | ShiftMask, XK_c, kill, NULL}, 6.26 - { Mod1Mask | ShiftMask, XK_q, quit, NULL}, 6.27 -}; 6.28 - 6.29 -void 6.30 -update_keys() 6.31 -{ 6.32 - unsigned int i, len; 6.33 - KeyCode code; 6.34 - 6.35 - len = sizeof(key) / sizeof(key[0]); 6.36 - for(i = 0; i < len; i++) { 6.37 - code = XKeysymToKeycode(dpy, key[i].keysym); 6.38 - XUngrabKey(dpy, code, key[i].mod, root); 6.39 - XGrabKey(dpy, code, key[i].mod, root, True, GrabModeAsync, GrabModeAsync); 6.40 - } 6.41 -} 6.42 - 6.43 -void 6.44 -keypress(XEvent *e) 6.45 -{ 6.46 - XKeyEvent *ev = &e->xkey; 6.47 - unsigned int i, len; 6.48 - KeySym keysym; 6.49 - 6.50 - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); 6.51 - len = sizeof(key) / sizeof(key[0]); 6.52 - for(i = 0; i < len; i++) 6.53 - if((keysym == key[i].keysym) && (key[i].mod == ev->state)) { 6.54 - if(key[i].func) 6.55 - key[i].func(key[i].aux); 6.56 - return; 6.57 - } 6.58 -}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/mouse.c Tue Jul 11 21:24:10 2006 +0200 7.3 @@ -0,0 +1,100 @@ 7.4 +/* 7.5 + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> 7.6 + * (C)opyright MMVI Kris Maglione <fbsdaemon@gmail.com> 7.7 + * See LICENSE file for license details. 7.8 + */ 7.9 + 7.10 +#include <stdlib.h> 7.11 +#include <string.h> 7.12 +#include <unistd.h> 7.13 + 7.14 +#include "wm.h" 7.15 + 7.16 +#define ButtonMask (ButtonPressMask | ButtonReleaseMask) 7.17 +#define MouseMask (ButtonMask | PointerMotionMask) 7.18 + 7.19 +static void 7.20 +mmatch(Client *c, int x1, int y1, int x2, int y2) 7.21 +{ 7.22 + c->r[RFloat].width = abs(x1 - x2); 7.23 + c->r[RFloat].height = abs(y1 - y2); 7.24 + c->r[RFloat].width -= 7.25 + (c->r[RFloat].width - c->size.base_width) % c->size.width_inc; 7.26 + c->r[RFloat].height -= 7.27 + (c->r[RFloat].height - c->size.base_height) % c->size.height_inc; 7.28 + if(c->size.min_width && c->r[RFloat].width < c->size.min_width) 7.29 + c->r[RFloat].width = c->size.min_width; 7.30 + if(c->size.min_height && c->r[RFloat].height < c->size.min_height) 7.31 + c->r[RFloat].height = c->size.min_height; 7.32 + if(c->size.max_width && c->r[RFloat].width > c->size.max_width) 7.33 + c->r[RFloat].width = c->size.max_width; 7.34 + if(c->size.max_height && c->r[RFloat].height > c->size.max_height) 7.35 + c->r[RFloat].height = c->size.max_height; 7.36 + c->r[RFloat].x = (x1 <= x2) ? x1 : x1 - c->r[RFloat].width; 7.37 + c->r[RFloat].y = (y1 <= y2) ? y1 : y1 - c->r[RFloat].height; 7.38 +} 7.39 + 7.40 +void 7.41 +mresize(Client *c) 7.42 +{ 7.43 + XEvent ev; 7.44 + int old_cx, old_cy; 7.45 + 7.46 + old_cx = c->r[RFloat].x; 7.47 + old_cy = c->r[RFloat].y; 7.48 + if(XGrabPointer(dpy, c->win, False, MouseMask, GrabModeAsync, GrabModeAsync, 7.49 + None, cursor[CurResize], CurrentTime) != GrabSuccess) 7.50 + return; 7.51 + XGrabServer(dpy); 7.52 + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, 7.53 + c->r[RFloat].width, c->r[RFloat].height); 7.54 + for(;;) { 7.55 + XMaskEvent(dpy, MouseMask, &ev); 7.56 + switch(ev.type) { 7.57 + default: break; 7.58 + case MotionNotify: 7.59 + XUngrabServer(dpy); 7.60 + mmatch(c, old_cx, old_cy, ev.xmotion.x, ev.xmotion.y); 7.61 + resize(c); 7.62 + XGrabServer(dpy); 7.63 + break; 7.64 + case ButtonRelease: 7.65 + XUngrabPointer(dpy, CurrentTime); 7.66 + return; 7.67 + } 7.68 + } 7.69 +} 7.70 + 7.71 +void 7.72 +mmove(Client *c) 7.73 +{ 7.74 + XEvent ev; 7.75 + int x1, y1, old_cx, old_cy, di; 7.76 + unsigned int dui; 7.77 + Window dummy; 7.78 + 7.79 + old_cx = c->r[RFloat].x; 7.80 + old_cy = c->r[RFloat].y; 7.81 + if(XGrabPointer(dpy, c->win, False, MouseMask, GrabModeAsync, GrabModeAsync, 7.82 + None, cursor[CurMove], CurrentTime) != GrabSuccess) 7.83 + return; 7.84 + XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); 7.85 + XGrabServer(dpy); 7.86 + for(;;) { 7.87 + XMaskEvent(dpy, MouseMask, &ev); 7.88 + switch (ev.type) { 7.89 + default: break; 7.90 + case MotionNotify: 7.91 + XUngrabServer(dpy); 7.92 + c->r[RFloat].x = old_cx + (ev.xmotion.x - x1); 7.93 + c->r[RFloat].y = old_cy + (ev.xmotion.y - y1); 7.94 + resize(c); 7.95 + XGrabServer(dpy); 7.96 + break; 7.97 + case ButtonRelease: 7.98 + XUngrabServer(dpy); 7.99 + XUngrabPointer(dpy, CurrentTime); 7.100 + return; 7.101 + } 7.102 + } 7.103 +}
8.1 --- a/wm.h Tue Jul 11 18:59:09 2006 +0200 8.2 +++ b/wm.h Tue Jul 11 21:24:10 2006 +0200 8.3 @@ -11,6 +11,22 @@ 8.4 8.5 #define WM_PROTOCOL_DELWIN 1 8.6 8.7 +typedef struct Client Client; 8.8 +typedef struct Key Key; 8.9 +typedef enum Align Align; 8.10 + 8.11 +enum Align { 8.12 + NORTH = 0x01, 8.13 + EAST = 0x02, 8.14 + SOUTH = 0x04, 8.15 + WEST = 0x08, 8.16 + NEAST = NORTH | EAST, 8.17 + NWEST = NORTH | WEST, 8.18 + SEAST = SOUTH | EAST, 8.19 + SWEST = SOUTH | WEST, 8.20 + CENTER = NEAST | SWEST 8.21 +}; 8.22 + 8.23 /* atoms */ 8.24 enum { WMProtocols, WMDelete, WMLast }; 8.25 enum { NetSupported, NetWMName, NetLast }; 8.26 @@ -21,9 +37,6 @@ 8.27 /* rects */ 8.28 enum { RFloat, RGrid, RLast }; 8.29 8.30 -typedef struct Client Client; 8.31 -typedef struct Key Key; 8.32 - 8.33 struct Client { 8.34 char name[256]; 8.35 char tag[256]; 8.36 @@ -75,14 +88,19 @@ 8.37 extern void focus(Client *c); 8.38 extern void update_name(Client *c); 8.39 extern void draw_client(Client *c); 8.40 +extern void resize(Client *c); 8.41 8.42 /* event.c */ 8.43 -extern unsigned int flush_events(long even_mask); 8.44 +extern unsigned int discard_events(long even_mask); 8.45 8.46 /* key.c */ 8.47 extern void update_keys(); 8.48 extern void keypress(XEvent *e); 8.49 8.50 +/* mouse.c */ 8.51 +extern void mresize(Client *c); 8.52 +extern void mmove(Client *c); 8.53 + 8.54 /* wm.c */ 8.55 extern int error_handler(Display *dpy, XErrorEvent *error); 8.56 extern void send_message(Window w, Atom a, long value);