X-Git-Url: https://jasonwoof.com/gitweb/?p=dwm.git;a=blobdiff_plain;f=client.c;h=69189dea1afb1b5c4e8f750c7447ceb52b1bb1b1;hp=7bb8459042a1447a385793cdff289b404765b89b;hb=849e631510ed6533ac930449804e477fe67a43c2;hpb=c0705eeb65733e8c5091e47d5bdc701a0779a949 diff --git a/client.c b/client.c index 7bb8459..69189de 100644 --- a/client.c +++ b/client.c @@ -2,36 +2,17 @@ * (C)opyright MMVI Anselm R. Garbe * See LICENSE file for license details. */ +#include "dwm.h" #include -#include #include #include #include -#include "dwm.h" - -static Rule rule[] = { - /* class instance tags floating */ - { "Firefox-bin", "Gecko", { [Twww] = "www" }, False }, -}; - -Client * -getnext(Client *c) -{ - for(; c && !c->tags[tsel]; c = c->next); - return c; -} - -void -ban(Client *c) -{ - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); - XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty); -} +/* static functions */ static void -resize_title(Client *c) +resizetitle(Client *c) { int i; @@ -47,84 +28,19 @@ resize_title(Client *c) XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th); } -void -settitle(Client *c) -{ - XTextProperty name; - int n; - char **list = NULL; - - name.nitems = 0; - c->name[0] = 0; - XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]); - if(!name.nitems) - XGetWMName(dpy, c->win, &name); - if(!name.nitems) - return; - if(name.encoding == XA_STRING) - strncpy(c->name, (char *)name.value, sizeof(c->name)); - else { - if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success - && n > 0 && *list) - { - strncpy(c->name, *list, sizeof(c->name)); - XFreeStringList(list); - } - } - XFree(name.value); - resize_title(c); -} - -void -setsize(Client *c) +static int +xerrordummy(Display *dsply, XErrorEvent *ee) { - XSizeHints size; - long msize; - if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) - size.flags = PSize; - c->flags = size.flags; - if(c->flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } - else - c->basew = c->baseh = 0; - if(c->flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } - else - c->incw = c->inch = 0; - if(c->flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } - else - c->maxw = c->maxh = 0; - if(c->flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } - else - c->minw = c->minh = 0; - if(c->flags & PWinGravity) - c->grav = size.win_gravity; - else - c->grav = NorthWestGravity; + return 0; } -void -higher(Client *c) -{ - XRaiseWindow(dpy, c->win); - XRaiseWindow(dpy, c->title); -} +/* extern functions */ void -lower(Client *c) +ban(Client *c) { - XLowerWindow(dpy, c->title); - XLowerWindow(dpy, c->win); + XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); + XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty); } void @@ -133,113 +49,64 @@ focus(Client *c) Client *old = sel; XEvent ev; - XFlush(dpy); sel = c; if(old && old != c) drawtitle(old); drawtitle(c); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XFlush(dpy); + XSync(dpy, False); while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); } -static void -init_tags(Client *c) +void +focusnext(Arg *arg) { - XClassHint ch; - static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0; - unsigned int i, j; - Bool matched = False; - - if(!len) { - c->tags[tsel] = tags[tsel]; + Client *c; + + if(!sel) return; - } - if(XGetClassHint(dpy, c->win, &ch)) { - if(ch.res_class && ch.res_name) { - for(i = 0; i < len; i++) - if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class)) - && !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance))) - { - for(j = 0; j < TLast; j++) - c->tags[j] = rule[i].tags[j]; - c->floating = rule[i].floating; - matched = True; - break; - } - } - if(ch.res_class) - XFree(ch.res_class); - if(ch.res_name) - XFree(ch.res_name); + if(!(c = getnext(sel->next))) + c = getnext(clients); + if(c) { + higher(c); + c->revert = sel; + focus(c); } - - if(!matched) - c->tags[tsel] = tags[tsel]; } void -manage(Window w, XWindowAttributes *wa) +focusprev(Arg *arg) { - Client *c, **l; - XSetWindowAttributes twa; - Window trans; - - c = emallocz(sizeof(Client)); - c->win = w; - c->tx = c->x = wa->x; - c->ty = c->y = wa->y; - if(c->y < bh) - c->ty = c->y += bh; - c->tw = c->w = wa->width; - c->h = wa->height; - c->th = bh; - c->border = 1; - c->proto = proto(c->win); - setsize(c); - XSelectInput(dpy, c->win, - StructureNotifyMask | PropertyChangeMask | EnterWindowMask); - XGetTransientForHint(dpy, c->win, &trans); - twa.override_redirect = 1; - twa.background_pixmap = ParentRelative; - twa.event_mask = ExposureMask; - - c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th, - 0, DefaultDepth(dpy, screen), CopyFromParent, - DefaultVisual(dpy, screen), - CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); - - settitle(c); - init_tags(c); - - for(l = &clients; *l; l = &(*l)->next); - c->next = *l; /* *l == nil */ - *l = c; - - XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask, - GrabModeAsync, GrabModeSync, None, None); - XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask, - GrabModeAsync, GrabModeSync, None, None); - XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, - GrabModeAsync, GrabModeSync, None, None); + Client *c; - if(!c->floating) - c->floating = trans - || ((c->maxw == c->minw) && (c->maxh == c->minh)); + if(!sel) + return; - arrange(NULL); - /* mapping the window now prevents flicker */ - if(c->tags[tsel]) { - XMapRaised(dpy, c->win); - XMapRaised(dpy, c->title); + if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) { + higher(c); focus(c); } - else { - ban(c); - XMapRaised(dpy, c->win); - XMapRaised(dpy, c->title); - } +} + +Client * +getclient(Window w) +{ + Client *c; + for(c = clients; c; c = c->next) + if(c->win == w) + return c; + return NULL; +} + +Client * +getctitle(Window w) +{ + Client *c; + for(c = clients; c; c = c->next) + if(c->title == w) + return c; + return NULL; } void @@ -297,6 +164,108 @@ gravitate(Client *c, Bool invert) c->y += dy; } +void +higher(Client *c) +{ + XRaiseWindow(dpy, c->win); + XRaiseWindow(dpy, c->title); +} + +void +killclient(Arg *arg) +{ + if(!sel) + return; + if(sel->proto & WM_PROTOCOL_DELWIN) + sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]); + else + XKillClient(dpy, sel->win); +} + +void +lower(Client *c) +{ + XLowerWindow(dpy, c->title); + XLowerWindow(dpy, c->win); +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c; + XSetWindowAttributes twa; + Window trans; + + c = emallocz(sizeof(Client)); + c->win = w; + c->tx = c->x = wa->x; + c->ty = c->y = wa->y; + if(c->y < bh) + c->ty = c->y += bh; + c->tw = c->w = wa->width; + c->h = wa->height; + c->th = bh; + c->border = 1; + c->proto = getproto(c->win); + setsize(c); + XSelectInput(dpy, c->win, + StructureNotifyMask | PropertyChangeMask | EnterWindowMask); + XGetTransientForHint(dpy, c->win, &trans); + twa.override_redirect = 1; + twa.background_pixmap = ParentRelative; + twa.event_mask = ExposureMask; + + c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th, + 0, DefaultDepth(dpy, screen), CopyFromParent, + DefaultVisual(dpy, screen), + CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); + + settitle(c); + settags(c); + + c->next = clients; + clients = c; + + XGrabButton(dpy, Button1, ControlMask, c->win, False, ButtonPressMask, + GrabModeAsync, GrabModeSync, None, None); + XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask, + GrabModeAsync, GrabModeSync, None, None); + XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask, + GrabModeAsync, GrabModeSync, None, None); + XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, + GrabModeAsync, GrabModeSync, None, None); + + if(!c->isfloat) + c->isfloat = trans + || ((c->maxw == c->minw) && (c->maxh == c->minh)); + + arrange(NULL); + /* mapping the window now prevents flicker */ + if(c->tags[tsel]) { + XMapRaised(dpy, c->win); + XMapRaised(dpy, c->title); + focus(c); + } + else { + ban(c); + XMapRaised(dpy, c->win); + XMapRaised(dpy, c->title); + XSync(dpy, False); + } +} + +void +maximize(Arg *arg) +{ + if(!sel) + return; + sel->x = sx; + sel->y = sy + bh; + sel->w = sw - 2 * sel->border; + sel->h = sh - 2 * sel->border - bh; + higher(sel); + resize(sel, False); +} void resize(Client *c, Bool inc) @@ -321,7 +290,7 @@ resize(Client *c, Bool inc) c->w = c->maxw; if(c->maxh && c->h > c->maxh) c->h = c->maxh; - resize_title(c); + resizetitle(c); XSetWindowBorderWidth(dpy, c->win, 1); XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); e.type = ConfigureNotify; @@ -335,13 +304,73 @@ resize(Client *c, Bool inc) e.above = None; e.override_redirect = False; XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e); - XFlush(dpy); + XSync(dpy, False); } -static int -dummy_xerror(Display *dsply, XErrorEvent *err) +void +setsize(Client *c) { - return 0; + XSizeHints size; + long msize; + if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) + size.flags = PSize; + c->flags = size.flags; + if(c->flags & PBaseSize) { + c->basew = size.base_width; + c->baseh = size.base_height; + } + else + c->basew = c->baseh = 0; + if(c->flags & PResizeInc) { + c->incw = size.width_inc; + c->inch = size.height_inc; + } + else + c->incw = c->inch = 0; + if(c->flags & PMaxSize) { + c->maxw = size.max_width; + c->maxh = size.max_height; + } + else + c->maxw = c->maxh = 0; + if(c->flags & PMinSize) { + c->minw = size.min_width; + c->minh = size.min_height; + } + else + c->minw = c->minh = 0; + if(c->flags & PWinGravity) + c->grav = size.win_gravity; + else + c->grav = NorthWestGravity; +} + +void +settitle(Client *c) +{ + XTextProperty name; + int n; + char **list = NULL; + + name.nitems = 0; + c->name[0] = 0; + XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]); + if(!name.nitems) + XGetWMName(dpy, c->win, &name); + if(!name.nitems) + return; + if(name.encoding == XA_STRING) + strncpy(c->name, (char *)name.value, sizeof(c->name)); + else { + if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success + && n > 0 && *list) + { + strncpy(c->name, *list, sizeof(c->name)); + XFreeStringList(list); + } + } + XFree(name.value); + resizetitle(c); } void @@ -350,7 +379,7 @@ unmanage(Client *c) Client **l; XGrabServer(dpy); - XSetErrorHandler(dummy_xerror); + XSetErrorHandler(xerrordummy); XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XDestroyWindow(dpy, c->title); @@ -365,7 +394,7 @@ unmanage(Client *c) free(c); - XFlush(dpy); + XSync(dpy, False); XSetErrorHandler(xerror); XUngrabServer(dpy); arrange(NULL); @@ -373,22 +402,24 @@ unmanage(Client *c) focus(sel); } -Client * -gettitle(Window w) +void +zoom(Arg *arg) { - Client *c; - for(c = clients; c; c = c->next) - if(c->title == w) - return c; - return NULL; -} + Client **l, *c; -Client * -getclient(Window w) -{ - Client *c; - for(c = clients; c; c = c->next) - if(c->win == w) - return c; - return NULL; + if(!sel) + return; + + if(sel == getnext(clients) && sel->next) { + if((c = getnext(sel->next))) + sel = c; + } + + for(l = &clients; *l && *l != sel; l = &(*l)->next); + *l = sel->next; + + sel->next = clients; /* pop */ + clients = sel; + arrange(NULL); + focus(sel); }