mirror of
https://git.suckless.org/dwm
synced 2024-12-27 03:16:32 +00:00
added mouse-based resizals
This commit is contained in:
parent
5ed16faecb
commit
b9da4b082e
7 changed files with 181 additions and 19 deletions
2
Makefile
2
Makefile
|
@ -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}
|
||||
|
|
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.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
|
32
client.c
32
client.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);
|
||||
}
|
||||
|
|
30
event.c
30
event.c
|
@ -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)
|
||||
|
|
100
mouse.c
Normal file
100
mouse.c
Normal 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
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…
Reference in a new issue