dwm

dynamic window manager
git clone git://git.suckless.org/dwm
Log | Files | Refs | README | LICENSE

commit 33996500763b04119a6867dfa4040a4236c21a41
parent 272e15c4b7bdeeb258caadb7c62e70c49c12b16d
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Tue, 11 Jul 2006 16:14:22 +0200

added protocol killing stuff

Diffstat:
Mclient.c | 33++++++++++++++++++++++++++-------
Mcmd.c | 14++++++++++++++
Mevent.c | 50+++++++++++++++++++++++++++++++++-----------------
Mmenu.c | 2+-
Mwm.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mwm.h | 24+++++++++++++++++-------
6 files changed, 153 insertions(+), 36 deletions(-)

diff --git a/client.c b/client.c @@ -10,8 +10,8 @@ #include "util.h" #include "wm.h" -static void -update_client_name(Client *c) +void +update_name(Client *c) { XTextProperty name; int n; @@ -38,6 +38,20 @@ update_client_name(Client *c) } void +focus(Client *c) +{ + Client **l; + for(l=&stack; *l && *l != c; l=&(*l)->snext); + eassert(*l == c); + *l = c->snext; + c->snext = stack; + stack = c; + XRaiseWindow(dpy, c->win); + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XFlush(dpy); +} + +void manage(Window w, XWindowAttributes *wa) { Client *c, **l; @@ -59,7 +73,7 @@ manage(Window w, XWindowAttributes *wa) (c->size.flags & PMinSize && c->size.flags & PMaxSize && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height); - update_client_name(c); + update_name(c); twa.override_redirect = 1; twa.background_pixmap = ParentRelative; twa.event_mask = ExposureMask; @@ -73,9 +87,10 @@ manage(Window w, XWindowAttributes *wa) for(l=&clients; *l; l=&(*l)->next); c->next = *l; /* *l == nil */ *l = c; - XMapRaised(dpy, c->win); - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XFlush(dpy); + c->snext = stack; + stack = c; + XMapWindow(dpy, c->win); + focus(c); } static int @@ -98,12 +113,15 @@ unmanage(Client *c) for(l=&clients; *l && *l != c; l=&(*l)->next); eassert(*l == c); *l = c->next; + for(l=&stack; *l && *l != c; l=&(*l)->snext); + eassert(*l == c); + *l = c->snext; free(c); XFlush(dpy); XSetErrorHandler(error_handler); XUngrabServer(dpy); - /*flush_masked_events(EnterWindowMask); ? */ + flush_events(EnterWindowMask); } @@ -116,3 +134,4 @@ getclient(Window w) return c; return NULL; } + diff --git a/cmd.c b/cmd.c @@ -18,3 +18,17 @@ quit(char *arg) fputs("quit\n", stderr); running = False; } + +void +kill(char *arg) +{ + Client *c = stack; + + if(!c) + return; + if(c->proto & WM_PROTOCOL_DELWIN) + send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]); + else + XKillClient(dpy, c->win); +} + diff --git a/event.c b/event.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <X11/keysym.h> +#include <X11/Xatom.h> #include "wm.h" @@ -35,7 +36,7 @@ void (*handler[LASTEvent]) (XEvent *) = { }; unsigned int -flush_masked_events(long even_mask) +flush_events(long even_mask) { XEvent ev; unsigned int n = 0; @@ -91,25 +92,18 @@ destroynotify(XEvent *e) static void enternotify(XEvent *e) { -#if 0 XCrossingEvent *ev = &e->xcrossing; Client *c; if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) return; - if((c = client_of_win(ev->window))) { - Frame *f = c->sel; - Area *a = f->area; - if(a->mode == Colmax) - c = a->sel->client; - focus(c, False); - } + if((c = getclient(ev->window))) + focus(c); else if(ev->window == root) { sel_screen = True; - draw_frames(); + /*draw_frames();*/ } -#endif } static void @@ -137,9 +131,7 @@ expose(XEvent *e) static void keymapnotify(XEvent *e) { -#if 0 update_keys(); -#endif } static void @@ -164,16 +156,40 @@ maprequest(XEvent *e) static void propertynotify(XEvent *e) { -#if 0 XPropertyEvent *ev = &e->xproperty; + long msize; Client *c; if(ev->state == PropertyDelete) return; /* ignore */ - if((c = client_of_win(ev->window))) - prop_client(c, ev); -#endif + if(ev->atom == wm_atom[WMProtocols]) { + c->proto = win_proto(c->win); + return; + } + if((c = getclient(ev->window))) { + switch (ev->atom) { + default: break; + case XA_WM_TRANSIENT_FOR: + XGetTransientForHint(dpy, c->win, &c->trans); + break; + case XA_WM_NORMAL_HINTS: + if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) + || !c->size.flags) + c->size.flags = PSize; + if(c->size.flags & PMinSize && c->size.flags & PMaxSize + && c->size.min_width == c->size.max_width + && c->size.min_height == c->size.max_height) + c->fixedsize = True; + else + c->fixedsize = False; + break; + } + if(ev->atom == XA_WM_NAME || ev->atom == net_atom[NetWMName]) { + update_name(c); + /*draw_frame(c->sel);*/ + } + } } static void diff --git a/menu.c b/menu.c @@ -304,7 +304,7 @@ kpress(XKeyEvent * e) } break; default: - if((num == 1) && !iscntrl((int) buf[0])) { + if(num && !iscntrl((int) buf[0])) { buf[num] = 0; if(len > 0) strncat(text, buf, sizeof(text)); diff --git a/wm.c b/wm.c @@ -16,18 +16,18 @@ /* X structs */ Display *dpy; Window root, barwin; -Atom net_atom[NetLast]; +Atom wm_atom[WMLast], net_atom[NetLast]; Cursor cursor[CurLast]; XRectangle rect, barrect; Bool running = True; +Bool sel_screen; char *bartext, tag[256]; -int screen, sel_screen; +int screen; Brush brush = {0}; Client *clients = NULL; - -enum { WM_PROTOCOL_DELWIN = 1 }; +Client *stack = NULL; static Bool other_wm_running; static char version[] = "gridwm - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; @@ -62,6 +62,62 @@ scan_wins() XFree(wins); } +static int +win_property(Window w, Atom a, Atom t, long l, unsigned char **prop) +{ + Atom real; + int format; + unsigned long res, extra; + int status; + + status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format, + &res, &extra, prop); + + if(status != Success || *prop == 0) { + return 0; + } + if(res == 0) { + free((void *) *prop); + } + return res; +} + +int +win_proto(Window w) +{ + Atom *protocols; + long res; + int protos = 0; + int i; + + res = win_property(w, wm_atom[WMProtocols], XA_ATOM, 20L, + ((unsigned char **) &protocols)); + if(res <= 0) { + return protos; + } + for(i = 0; i < res; i++) { + if(protocols[i] == wm_atom[WMDelete]) + protos |= WM_PROTOCOL_DELWIN; + } + free((char *) protocols); + return protos; +} + +void +send_message(Window w, Atom a, long value) +{ + XEvent e; + + e.type = ClientMessage; + e.xclient.window = w; + e.xclient.message_type = a; + e.xclient.format = 32; + e.xclient.data.l[0] = value; + e.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, w, False, NoEventMask, &e); + XFlush(dpy); +} + /* * There's no way to check accesses to destroyed windows, thus * those cases are ignored (especially on UnmapNotify's). @@ -160,6 +216,8 @@ main(int argc, char *argv[]) x_error_handler = XSetErrorHandler(error_handler); /* init atoms */ + wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wm_atom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); net_atom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); net_atom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); diff --git a/wm.h b/wm.h @@ -9,7 +9,10 @@ #include <X11/Xutil.h> +#define WM_PROTOCOL_DELWIN 1 + /* atoms */ +enum { WMProtocols, WMDelete, WMLast }; enum { NetSupported, NetWMName, NetLast }; /* cursor */ @@ -25,6 +28,7 @@ struct Client { char name[256]; char tag[256]; unsigned int border; + int proto; Bool fixedsize; Window win; Window trans; @@ -44,18 +48,17 @@ struct Key { extern Display *dpy; extern Window root, barwin; -extern Atom net_atom[NetLast]; +extern Atom wm_atom[WMLast], net_atom[NetLast]; extern Cursor cursor[CurLast]; extern XRectangle rect, barrect; -extern Bool running; -extern Bool grid; +extern Bool running, sel_screen, grid; extern void (*handler[LASTEvent]) (XEvent *); -extern int screen, sel_screen; +extern int screen; extern char *bartext, tag[256]; extern Brush brush; -extern Client *clients; +extern Client *clients, *stack; /* bar.c */ extern void draw_bar(); @@ -66,8 +69,13 @@ extern void quit(char *arg); /* client.c */ extern void manage(Window w, XWindowAttributes *wa); -void unmanage(Client *c); -extern Client * getclient(Window w); +extern void unmanage(Client *c); +extern Client *getclient(Window w); +extern void focus(Client *c); +extern void update_name(Client *c); + +/* event.c */ +extern unsigned int flush_events(long even_mask); /* key.c */ extern void update_keys(); @@ -75,3 +83,5 @@ extern void keypress(XEvent *e); /* wm.c */ extern int error_handler(Display *dpy, XErrorEvent *error); +extern void send_message(Window w, Atom a, long value); +extern int win_proto(Window w);