mirror of git://git.suckless.org/dwm
added mouse-based resizals
This commit is contained in:
parent
5ed16faecb
commit
b9da4b082e
2
Makefile
2
Makefile
|
@ -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
10
README
|
@ -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.
|
||||||
|
|
||||||
|
|
32
client.c
32
client.c
|
@ -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
30
event.c
|
@ -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)
|
||||||
|
|
|
@ -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
26
wm.h
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue