added mouse-based resizals

new_dwm
Anselm R. Garbe 19 years ago
parent 5ed16faecb
commit b9da4b082e

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

@ -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 @@ 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.

@ -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 @@ 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;
@ -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)
{
@ -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);
@ -126,7 +154,7 @@ unmanage(Client *c)
XFlush(dpy);
XSetErrorHandler(error_handler);
XUngrabServer(dpy);
flush_events(EnterWindowMask);
discard_events(EnterWindowMask);
if(stack)
focus(stack);
}

@ -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 @@ void (*handler[LASTEvent]) (XEvent *) = {
};
unsigned int
flush_events(long even_mask)
discard_events(long even_mask)
{
XEvent ev;
unsigned int n = 0;
@ -44,6 +46,29 @@ flush_events(long even_mask)
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)
{
@ -51,9 +76,8 @@ configurerequest(XEvent *e)
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)

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

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

Loading…
Cancel
Save