added mouse-based resizals

This commit is contained in:
Anselm R. Garbe 2006-07-11 21:24:10 +02:00
parent 5ed16faecb
commit b9da4b082e
7 changed files with 181 additions and 19 deletions

View file

@ -3,7 +3,7 @@
include config.mk 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} WMOBJ = ${WMSRC:.c=.o}
MENSRC = menu.c draw.c util.c MENSRC = menu.c draw.c util.c
MENOBJ = ${MENSRC:.c=.o} MENOBJ = ${MENSRC:.c=.o}

10
README
View file

@ -5,14 +5,6 @@ gridwm is an extremly fast, small, and automatic X11 window manager. It
arranges all windows in a grid. 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 Requirements
------------ ------------
In order to build gridwm you need the Xlib header files. In order to build gridwm you need the Xlib header files.
@ -46,6 +38,6 @@ This will start gridwm on display :1 of the host foo.bar.
Configuration Configuration
------------- -------------
The configuration of gridwm is done by customizing the config.h source file. To 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. status command definition in wm.c.

View file

@ -10,6 +10,8 @@
#include "util.h" #include "util.h"
#include "wm.h" #include "wm.h"
#define CLIENT_MASK (StructureNotifyMask | PropertyChangeMask | EnterWindowMask)
void void
update_name(Client *c) update_name(Client *c)
{ {
@ -70,7 +72,7 @@ manage(Window w, XWindowAttributes *wa)
c->r[RFloat].height = wa->height; c->r[RFloat].height = wa->height;
c->border = wa->border_width; c->border = wa->border_width;
XSetWindowBorderWidth(dpy, c->win, 0); XSetWindowBorderWidth(dpy, c->win, 0);
XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | EnterWindowMask); XSelectInput(dpy, c->win, CLIENT_MASK);
XGetTransientForHint(dpy, c->win, &c->trans); XGetTransientForHint(dpy, c->win, &c->trans);
if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags) if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags)
c->size.flags = PSize; c->size.flags = PSize;
@ -95,9 +97,34 @@ manage(Window w, XWindowAttributes *wa)
c->snext = stack; c->snext = stack;
stack = c; stack = c;
XMapWindow(dpy, c->win); XMapWindow(dpy, c->win);
XGrabButton(dpy, AnyButton, Mod1Mask, c->win, False, ButtonPressMask,
GrabModeAsync, GrabModeSync, None, None);
focus(c); 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 static int
dummy_error_handler(Display *dpy, XErrorEvent *error) dummy_error_handler(Display *dpy, XErrorEvent *error)
{ {
@ -112,6 +139,7 @@ unmanage(Client *c)
XGrabServer(dpy); XGrabServer(dpy);
XSetErrorHandler(dummy_error_handler); XSetErrorHandler(dummy_error_handler);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XUnmapWindow(dpy, c->win); XUnmapWindow(dpy, c->win);
XDestroyWindow(dpy, c->title); XDestroyWindow(dpy, c->title);
@ -126,7 +154,7 @@ unmanage(Client *c)
XFlush(dpy); XFlush(dpy);
XSetErrorHandler(error_handler); XSetErrorHandler(error_handler);
XUngrabServer(dpy); XUngrabServer(dpy);
flush_events(EnterWindowMask); discard_events(EnterWindowMask);
if(stack) if(stack)
focus(stack); focus(stack);
} }

30
event.c
View file

@ -12,6 +12,7 @@
#include "wm.h" #include "wm.h"
/* local functions */ /* local functions */
static void buttonpress(XEvent *e);
static void configurerequest(XEvent *e); static void configurerequest(XEvent *e);
static void destroynotify(XEvent *e); static void destroynotify(XEvent *e);
static void enternotify(XEvent *e); static void enternotify(XEvent *e);
@ -23,6 +24,7 @@ static void propertynotify(XEvent *e);
static void unmapnotify(XEvent *e); static void unmapnotify(XEvent *e);
void (*handler[LASTEvent]) (XEvent *) = { void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress,
[ConfigureRequest] = configurerequest, [ConfigureRequest] = configurerequest,
[DestroyNotify] = destroynotify, [DestroyNotify] = destroynotify,
[EnterNotify] = enternotify, [EnterNotify] = enternotify,
@ -36,7 +38,7 @@ void (*handler[LASTEvent]) (XEvent *) = {
}; };
unsigned int unsigned int
flush_events(long even_mask) discard_events(long even_mask)
{ {
XEvent ev; XEvent ev;
unsigned int n = 0; unsigned int n = 0;
@ -44,6 +46,29 @@ flush_events(long even_mask)
return n; 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 static void
configurerequest(XEvent *e) configurerequest(XEvent *e)
{ {
@ -51,9 +76,8 @@ configurerequest(XEvent *e)
XWindowChanges wc; XWindowChanges wc;
Client *c; Client *c;
c = getclient(ev->window);
ev->value_mask &= ~CWSibling; ev->value_mask &= ~CWSibling;
if(c) { if((c = getclient(ev->window))) {
if(ev->value_mask & CWX) if(ev->value_mask & CWX)
c->r[RFloat].x = ev->x; c->r[RFloat].x = ev->x;
if(ev->value_mask & CWY) if(ev->value_mask & CWY)

View file

100
mouse.c Normal file
View file

@ -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;
}
}
}

26
wm.h
View file

@ -11,6 +11,22 @@
#define WM_PROTOCOL_DELWIN 1 #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 */ /* atoms */
enum { WMProtocols, WMDelete, WMLast }; enum { WMProtocols, WMDelete, WMLast };
enum { NetSupported, NetWMName, NetLast }; enum { NetSupported, NetWMName, NetLast };
@ -21,9 +37,6 @@ enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
/* rects */ /* rects */
enum { RFloat, RGrid, RLast }; enum { RFloat, RGrid, RLast };
typedef struct Client Client;
typedef struct Key Key;
struct Client { struct Client {
char name[256]; char name[256];
char tag[256]; char tag[256];
@ -75,14 +88,19 @@ extern Client *getclient(Window w);
extern void focus(Client *c); extern void focus(Client *c);
extern void update_name(Client *c); extern void update_name(Client *c);
extern void draw_client(Client *c); extern void draw_client(Client *c);
extern void resize(Client *c);
/* event.c */ /* event.c */
extern unsigned int flush_events(long even_mask); extern unsigned int discard_events(long even_mask);
/* key.c */ /* key.c */
extern void update_keys(); extern void update_keys();
extern void keypress(XEvent *e); extern void keypress(XEvent *e);
/* mouse.c */
extern void mresize(Client *c);
extern void mmove(Client *c);
/* wm.c */ /* wm.c */
extern int error_handler(Display *dpy, XErrorEvent *error); extern int error_handler(Display *dpy, XErrorEvent *error);
extern void send_message(Window w, Atom a, long value); extern void send_message(Window w, Atom a, long value);