diff options
Diffstat (limited to 'client.c')
-rw-r--r-- | client.c | 373 |
1 files changed, 147 insertions, 226 deletions
diff --git a/client.c b/client.c index 2384f59..821da25 100644 --- a/client.c +++ b/client.c @@ -31,34 +31,31 @@ #include "calmwm.h" -static struct client_ctx *client_next(struct client_ctx *); -static struct client_ctx *client_prev(struct client_ctx *); -static void client_placecalc(struct client_ctx *); -static void client_wm_protocols(struct client_ctx *); +static void client_class_hint(struct client_ctx *); +static void client_placement(struct client_ctx *); static void client_mwm_hints(struct client_ctx *); +static void client_wm_protocols(struct client_ctx *); struct client_ctx * -client_init(Window win, struct screen_ctx *sc, int active) +client_init(Window win, struct screen_ctx *sc) { struct client_ctx *cc; XWindowAttributes wattr; int mapped; - Window rwin, cwin; - int x, y, wx, wy; - unsigned int mask; + long state; if (win == None) - return(NULL); + return NULL; if (!XGetWindowAttributes(X_Dpy, win, &wattr)) - return(NULL); + return NULL; if (sc == NULL) { if ((sc = screen_find(wattr.root)) == NULL) - return(NULL); + return NULL; mapped = 1; } else { if (wattr.override_redirect || wattr.map_state != IsViewable) - return(NULL); + return NULL; mapped = wattr.map_state != IsUnmapped; } @@ -67,12 +64,15 @@ client_init(Window win, struct screen_ctx *sc, int active) cc = xmalloc(sizeof(*cc)); cc->sc = sc; cc->win = win; + cc->name = NULL; cc->label = NULL; cc->gc = NULL; + cc->res_class = NULL; + cc->res_name = NULL; cc->flags = 0; cc->stackingorder = 0; + cc->initial_state = 0; memset(&cc->hint, 0, sizeof(cc->hint)); - memset(&cc->ch, 0, sizeof(cc->ch)); TAILQ_INIT(&cc->nameq); cc->geom.x = wattr.x; @@ -83,13 +83,13 @@ client_init(Window win, struct screen_ctx *sc, int active) cc->obwidth = wattr.border_width; cc->bwidth = Conf.bwidth; - client_setname(cc); + client_set_name(cc); conf_client(cc); - XGetClassHint(X_Dpy, cc->win, &cc->ch); client_wm_hints(cc); + client_class_hint(cc); client_wm_protocols(cc); - client_getsizehints(cc); + client_get_sizehints(cc); client_transient(cc); client_mwm_hints(cc); @@ -101,18 +101,14 @@ client_init(Window win, struct screen_ctx *sc, int active) cc->ptr.y = cc->geom.h / 2; if (wattr.map_state != IsViewable) { - client_placecalc(cc); + client_placement(cc); client_resize(cc, 0); - if ((cc->wmh) && (cc->wmh->flags & StateHint)) - client_set_wm_state(cc, cc->wmh->initial_state); - } else { - if ((active == 0) && (XQueryPointer(X_Dpy, cc->win, &rwin, - &cwin, &x, &y, &wx, &wy, &mask)) && (cwin != None)) - active = 1; + if (cc->initial_state) + xu_set_wm_state(cc->win, cc->initial_state); } - XSelectInput(X_Dpy, cc->win, ColormapChangeMask | EnterWindowMask | - PropertyChangeMask | KeyReleaseMask); + XSelectInput(X_Dpy, cc->win, + EnterWindowMask | PropertyChangeMask | KeyReleaseMask); XAddToSaveSet(X_Dpy, cc->win); @@ -125,7 +121,8 @@ client_init(Window win, struct screen_ctx *sc, int active) xu_ewmh_net_client_list_stacking(sc); xu_ewmh_restore_net_wm_state(cc); - if (client_get_wm_state(cc) == IconicState) + xu_get_wm_state(cc->win, &state); + if (state == IconicState) client_hide(cc); else client_show(cc); @@ -148,10 +145,29 @@ out: XSync(X_Dpy, False); XUngrabServer(X_Dpy); - if (active) - client_setactive(cc); + return cc; +} + +struct client_ctx * +client_current(struct screen_ctx *sc) +{ + struct screen_ctx *_sc; + struct client_ctx *cc; - return(cc); + if (sc) { + TAILQ_FOREACH(cc, &sc->clientq, entry) { + if (cc->flags & CLIENT_ACTIVE) + return cc; + } + } else { + TAILQ_FOREACH(_sc, &Screenq, entry) { + TAILQ_FOREACH(cc, &_sc->clientq, entry) { + if (cc->flags & CLIENT_ACTIVE) + return cc; + } + } + } + return NULL; } struct client_ctx * @@ -163,10 +179,30 @@ client_find(Window win) TAILQ_FOREACH(sc, &Screenq, entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) { if (cc->win == win) - return(cc); + return cc; } } - return(NULL); + return NULL; +} + +struct client_ctx * +client_next(struct client_ctx *cc) +{ + struct screen_ctx *sc = cc->sc; + struct client_ctx *newcc; + + return(((newcc = TAILQ_NEXT(cc, entry)) != NULL) ? + newcc : TAILQ_FIRST(&sc->clientq)); +} + +struct client_ctx * +client_prev(struct client_ctx *cc) +{ + struct screen_ctx *sc = cc->sc; + struct client_ctx *newcc; + + return(((newcc = TAILQ_PREV(cc, client_q, entry)) != NULL) ? + newcc : TAILQ_LAST(&sc->clientq, client_q)); } void @@ -189,18 +225,15 @@ client_remove(struct client_ctx *cc) free(wn); } - if (cc->ch.res_class) - XFree(cc->ch.res_class); - if (cc->ch.res_name) - XFree(cc->ch.res_name); - if (cc->wmh) - XFree(cc->wmh); - + free(cc->name); + free(cc->label); + free(cc->res_class); + free(cc->res_name); free(cc); } void -client_setactive(struct client_ctx *cc) +client_set_active(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; struct client_ctx *oldcc; @@ -216,7 +249,7 @@ client_setactive(struct client_ctx *cc) RevertToPointerRoot, CurrentTime); } if (cc->flags & CLIENT_WM_TAKE_FOCUS) - client_msg(cc, cwmh[WM_TAKE_FOCUS], Last_Event_Time); + xu_send_clientmsg(cc->win, cwmh[WM_TAKE_FOCUS], Last_Event_Time); if ((oldcc = client_current(sc)) != NULL) { oldcc->flags &= ~CLIENT_ACTIVE; @@ -234,28 +267,6 @@ client_setactive(struct client_ctx *cc) xu_ewmh_net_active_window(sc, cc->win); } -struct client_ctx * -client_current(struct screen_ctx *sc) -{ - struct screen_ctx *_sc; - struct client_ctx *cc; - - if (sc) { - TAILQ_FOREACH(cc, &sc->clientq, entry) { - if (cc->flags & CLIENT_ACTIVE) - return(cc); - } - } else { - TAILQ_FOREACH(_sc, &Screenq, entry) { - TAILQ_FOREACH(cc, &_sc->clientq, entry) { - if (cc->flags & CLIENT_ACTIVE) - return(cc); - } - } - } - return(NULL); -} - void client_toggle_freeze(struct client_ctx *cc) { @@ -316,7 +327,7 @@ client_toggle_fullscreen(struct client_ctx *cc) area = screen_area(sc, cc->geom.x + cc->geom.w / 2, - cc->geom.y + cc->geom.h / 2, CWM_NOGAP); + cc->geom.y + cc->geom.h / 2, 0); cc->bwidth = 0; cc->geom = area; @@ -354,7 +365,7 @@ client_toggle_maximize(struct client_ctx *cc) area = screen_area(sc, cc->geom.x + cc->geom.w / 2, - cc->geom.y + cc->geom.h / 2, CWM_GAP); + cc->geom.y + cc->geom.h / 2, 1); cc->geom.x = area.x; cc->geom.y = area.y; @@ -388,7 +399,7 @@ client_toggle_vmaximize(struct client_ctx *cc) area = screen_area(sc, cc->geom.x + cc->geom.w / 2, - cc->geom.y + cc->geom.h / 2, CWM_GAP); + cc->geom.y + cc->geom.h / 2, 1); cc->geom.y = area.y; cc->geom.h = area.h - (cc->bwidth * 2); @@ -420,7 +431,7 @@ client_toggle_hmaximize(struct client_ctx *cc) area = screen_area(sc, cc->geom.x + cc->geom.w / 2, - cc->geom.y + cc->geom.h / 2, CWM_GAP); + cc->geom.y + cc->geom.h / 2, 1); cc->geom.x = area.x; cc->geom.w = area.w - (cc->bwidth * 2); @@ -491,7 +502,7 @@ void client_ptr_inbound(struct client_ctx *cc, int getpos) { if (getpos) - xu_ptr_getpos(cc->win, &cc->ptr.x, &cc->ptr.y); + xu_ptr_get(cc->win, &cc->ptr.x, &cc->ptr.y); if (cc->ptr.x < 0) cc->ptr.x = 0; @@ -502,21 +513,21 @@ client_ptr_inbound(struct client_ctx *cc, int getpos) else if (cc->ptr.y > cc->geom.h - 1) cc->ptr.y = cc->geom.h - 1; - client_ptrwarp(cc); + client_ptr_warp(cc); } void -client_ptrwarp(struct client_ctx *cc) +client_ptr_warp(struct client_ctx *cc) { - xu_ptr_setpos(cc->win, cc->ptr.x, cc->ptr.y); + xu_ptr_set(cc->win, cc->ptr.x, cc->ptr.y); } void -client_ptrsave(struct client_ctx *cc) +client_ptr_save(struct client_ctx *cc) { int x, y; - xu_ptr_getpos(cc->win, &x, &y); + xu_ptr_get(cc->win, &x, &y); if (client_inbound(cc, x, y)) { cc->ptr.x = x; cc->ptr.y = y; @@ -536,7 +547,7 @@ client_hide(struct client_ctx *cc) xu_ewmh_net_active_window(cc->sc, None); } cc->flags |= CLIENT_HIDDEN; - client_set_wm_state(cc, IconicState); + xu_set_wm_state(cc->win, IconicState); } void @@ -545,7 +556,7 @@ client_show(struct client_ctx *cc) XMapRaised(X_Dpy, cc->win); cc->flags &= ~CLIENT_HIDDEN; - client_set_wm_state(cc, NormalState); + xu_set_wm_state(cc->win, NormalState); client_draw_border(cc); } @@ -585,6 +596,23 @@ client_draw_border(struct client_ctx *cc) } static void +client_class_hint(struct client_ctx *cc) +{ + XClassHint ch; + + if (XGetClassHint(X_Dpy, cc->win, &ch)) { + if (ch.res_class) { + cc->res_class = xstrdup(ch.res_class); + XFree(ch.res_class); + } + if (ch.res_name) { + cc->res_name = xstrdup(ch.res_name); + XFree(ch.res_name); + } + } +} + +static void client_wm_protocols(struct client_ctx *cc) { Atom *p; @@ -604,149 +632,62 @@ client_wm_protocols(struct client_ctx *cc) void client_wm_hints(struct client_ctx *cc) { - if ((cc->wmh = XGetWMHints(X_Dpy, cc->win)) == NULL) - return; - - if ((cc->wmh->flags & InputHint) && (cc->wmh->input)) - cc->flags |= CLIENT_INPUT; - - if ((cc->wmh->flags & XUrgencyHint)) - client_urgency(cc); -} - -void -client_msg(struct client_ctx *cc, Atom proto, Time ts) -{ - XClientMessageEvent cm; - - (void)memset(&cm, 0, sizeof(cm)); - cm.type = ClientMessage; - cm.window = cc->win; - cm.message_type = cwmh[WM_PROTOCOLS]; - cm.format = 32; - cm.data.l[0] = proto; - cm.data.l[1] = ts; - - XSendEvent(X_Dpy, cc->win, False, NoEventMask, (XEvent *)&cm); + XWMHints *wmh; + + if ((wmh = XGetWMHints(X_Dpy, cc->win)) != NULL) { + if ((wmh->flags & InputHint) && (wmh->input)) + cc->flags |= CLIENT_INPUT; + if ((wmh->flags & XUrgencyHint)) + client_urgency(cc); + if ((wmh->flags & StateHint)) + cc->initial_state = wmh->initial_state; + XFree(wmh); + } } void client_close(struct client_ctx *cc) { if (cc->flags & CLIENT_WM_DELETE_WINDOW) - client_msg(cc, cwmh[WM_DELETE_WINDOW], CurrentTime); + xu_send_clientmsg(cc->win, cwmh[WM_DELETE_WINDOW], CurrentTime); else XKillClient(X_Dpy, cc->win); } void -client_setname(struct client_ctx *cc) +client_set_name(struct client_ctx *cc) { - struct winname *wn; - char *newname; + struct winname *wn, *wnnxt; int i = 0; - if (!xu_getstrprop(cc->win, ewmh[_NET_WM_NAME], &newname)) - if (!xu_getstrprop(cc->win, XA_WM_NAME, &newname)) - newname = xstrdup(""); + free(cc->name); + if (!xu_get_strprop(cc->win, ewmh[_NET_WM_NAME], &cc->name)) + if (!xu_get_strprop(cc->win, XA_WM_NAME, &cc->name)) + cc->name = xstrdup(""); - TAILQ_FOREACH(wn, &cc->nameq, entry) { - if (strcmp(wn->name, newname) == 0) { - /* Move to the last since we got a hit. */ + TAILQ_FOREACH_SAFE(wn, &cc->nameq, entry, wnnxt) { + if (strcmp(wn->name, cc->name) == 0) { TAILQ_REMOVE(&cc->nameq, wn, entry); - TAILQ_INSERT_TAIL(&cc->nameq, wn, entry); - goto match; + free(wn->name); + free(wn); } + i++; } wn = xmalloc(sizeof(*wn)); - wn->name = newname; + wn->name = xstrdup(cc->name); TAILQ_INSERT_TAIL(&cc->nameq, wn, entry); -match: - cc->name = wn->name; - /* Do some garbage collection. */ - TAILQ_FOREACH(wn, &cc->nameq, entry) - i++; - if (i > Conf.nameqlen) { + /* Garbage collection. */ + if ((i + 1) > Conf.nameqlen) { wn = TAILQ_FIRST(&cc->nameq); TAILQ_REMOVE(&cc->nameq, wn, entry); free(wn->name); free(wn); - i--; } } -void -client_cycle(struct screen_ctx *sc, int flags) -{ - struct client_ctx *newcc, *oldcc, *prevcc; - int again = 1; - - if (TAILQ_EMPTY(&sc->clientq)) - return; - - prevcc = TAILQ_FIRST(&sc->clientq); - oldcc = client_current(sc); - if (oldcc == NULL) - oldcc = (flags & CWM_CYCLE_REVERSE) ? - TAILQ_LAST(&sc->clientq, client_q) : - TAILQ_FIRST(&sc->clientq); - - newcc = oldcc; - while (again) { - again = 0; - - newcc = (flags & CWM_CYCLE_REVERSE) ? client_prev(newcc) : - client_next(newcc); - - /* Only cycle visible and non-ignored windows. */ - if ((newcc->flags & (CLIENT_SKIP_CYCLE)) || - ((flags & CWM_CYCLE_INGROUP) && - (newcc->gc != oldcc->gc))) - again = 1; - - /* Is oldcc the only non-hidden window? */ - if (newcc == oldcc) { - if (again) - return; /* No windows visible. */ - break; - } - } - - /* Reset when cycling mod is released. XXX I hate this hack */ - sc->cycling = 1; - client_ptrsave(oldcc); - client_raise(prevcc); - client_raise(newcc); - if (!client_inbound(newcc, newcc->ptr.x, newcc->ptr.y)) { - newcc->ptr.x = newcc->geom.w / 2; - newcc->ptr.y = newcc->geom.h / 2; - } - client_ptrwarp(newcc); -} - -static struct client_ctx * -client_next(struct client_ctx *cc) -{ - struct screen_ctx *sc = cc->sc; - struct client_ctx *newcc; - - return(((newcc = TAILQ_NEXT(cc, entry)) != NULL) ? - newcc : TAILQ_FIRST(&sc->clientq)); -} - -static struct client_ctx * -client_prev(struct client_ctx *cc) -{ - struct screen_ctx *sc = cc->sc; - struct client_ctx *newcc; - - return(((newcc = TAILQ_PREV(cc, client_q, entry)) != NULL) ? - newcc : TAILQ_LAST(&sc->clientq, client_q)); -} - static void -client_placecalc(struct client_ctx *cc) +client_placement(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; @@ -769,8 +710,8 @@ client_placecalc(struct client_ctx *cc) struct geom area; int xmouse, ymouse, xslack, yslack; - xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse); - area = screen_area(sc, xmouse, ymouse, CWM_GAP); + xu_ptr_get(sc->rootwin, &xmouse, &ymouse); + area = screen_area(sc, xmouse, ymouse, 1); xmouse = MAX(MAX(xmouse, area.x) - cc->geom.w / 2, area.x); ymouse = MAX(MAX(ymouse, area.y) - cc->geom.h / 2, area.y); @@ -803,7 +744,7 @@ client_mtf(struct client_ctx *cc) } void -client_getsizehints(struct client_ctx *cc) +client_get_sizehints(struct client_ctx *cc) { long tmp; XSizeHints size; @@ -851,7 +792,7 @@ client_getsizehints(struct client_ctx *cc) } void -client_applysizehints(struct client_ctx *cc) +client_apply_sizehints(struct client_ctx *cc) { Bool baseismin; @@ -902,7 +843,7 @@ client_mwm_hints(struct client_ctx *cc) { struct mwm_hints *mwmh; - if (xu_getprop(cc->win, cwmh[_MOTIF_WM_HINTS], + if (xu_get_prop(cc->win, cwmh[_MOTIF_WM_HINTS], cwmh[_MOTIF_WM_HINTS], MWM_HINTS_ELEMENTS, (unsigned char **)&mwmh) == MWM_HINTS_ELEMENTS) { if (mwmh->flags & MWM_FLAGS_DECORATIONS && @@ -952,15 +893,15 @@ client_snapcalc(int n0, int n1, int e0, int e1, int snapdist) /* possible to snap in both directions */ if (s0 != 0 && s1 != 0) if (abs(s0) < abs(s1)) - return(s0); + return s0; else - return(s1); + return s1; else if (s0 != 0) - return(s0); + return s0; else if (s1 != 0) - return(s1); + return s1; else - return(0); + return 0; } void @@ -974,7 +915,7 @@ client_htile(struct client_ctx *cc) i = n = 0; area = screen_area(sc, cc->geom.x + cc->geom.w / 2, - cc->geom.y + cc->geom.h / 2, CWM_GAP); + cc->geom.y + cc->geom.h / 2, 1); TAILQ_FOREACH(ci, &sc->clientq, entry) { if (ci->gc != cc->gc) @@ -999,9 +940,10 @@ client_htile(struct client_ctx *cc) cc->geom.x = area.x; cc->geom.y = area.y; cc->geom.w = area.w - (cc->bwidth * 2); - cc->geom.h = (area.h - (cc->bwidth * 2)) / 2; + if (Conf.htile > 0) + cc->geom.h = ((area.h - (cc->bwidth * 2)) * Conf.htile) / 100; client_resize(cc, 1); - client_ptrwarp(cc); + client_ptr_warp(cc); mh = cc->geom.h + (cc->bwidth * 2); x = area.x; @@ -1042,7 +984,7 @@ client_vtile(struct client_ctx *cc) i = n = 0; area = screen_area(sc, cc->geom.x + cc->geom.w / 2, - cc->geom.y + cc->geom.h / 2, CWM_GAP); + cc->geom.y + cc->geom.h / 2, 1); TAILQ_FOREACH(ci, &sc->clientq, entry) { if (ci->gc != cc->gc) @@ -1066,10 +1008,11 @@ client_vtile(struct client_ctx *cc) cc->flags &= ~CLIENT_VMAXIMIZED; cc->geom.x = area.x; cc->geom.y = area.y; - cc->geom.w = (area.w - (cc->bwidth * 2)) / 2; + if (Conf.vtile > 0) + cc->geom.w = ((area.w - (cc->bwidth * 2)) * Conf.vtile) / 100; cc->geom.h = area.h - (cc->bwidth * 2); client_resize(cc, 1); - client_ptrwarp(cc); + client_ptr_warp(cc); mw = cc->geom.w + (cc->bwidth * 2); y = area.y; @@ -1098,25 +1041,3 @@ client_vtile(struct client_ctx *cc) client_resize(ci, 1); } } - -long -client_get_wm_state(struct client_ctx *cc) -{ - long *p, state = -1; - - if (xu_getprop(cc->win, cwmh[WM_STATE], cwmh[WM_STATE], 2L, - (unsigned char **)&p) > 0) { - state = *p; - XFree(p); - } - return(state); -} - -void -client_set_wm_state(struct client_ctx *cc, long state) -{ - long data[] = { state, None }; - - XChangeProperty(X_Dpy, cc->win, cwmh[WM_STATE], cwmh[WM_STATE], 32, - PropModeReplace, (unsigned char *)data, 2); -} |