From 1d68f0683a784420b5a6ec0b8f1622b6ccd5fcc7 Mon Sep 17 00:00:00 2001 From: okan Date: Tue, 10 Dec 2013 21:27:37 +0000 Subject: [PATCH 1/7] Redraw client border when unhiding; during a hide, we just unset the active flag but never redraw since it'll be in IconicState. Behaviour reported by sthen@ --- client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client.c b/client.c index 9834757..d6019f6 100644 --- a/client.c +++ b/client.c @@ -471,6 +471,7 @@ client_unhide(struct client_ctx *cc) cc->flags &= ~CLIENT_HIDDEN; cc->state = NormalState; xu_set_wm_state(cc->win, cc->state); + client_draw_border(cc); } void From 23a1abdd8ac7025ff55e287bd4437594618781d2 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 11 Dec 2013 14:09:21 +0000 Subject: [PATCH 2/7] Stash Class and WM Hints in client_ctx --- calmwm.h | 4 ++-- client.c | 37 ++++++++++++++++--------------------- group.c | 6 +++--- search.c | 4 ++-- 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/calmwm.h b/calmwm.h index 8ceba9e..9c613b9 100644 --- a/calmwm.h +++ b/calmwm.h @@ -177,8 +177,8 @@ struct client_ctx { char *label; char *matchname; struct group_ctx *group; - char *app_class; - char *app_name; + XClassHint ch; + XWMHints *wmh; }; TAILQ_HEAD(client_ctx_q, client_ctx); TAILQ_HEAD(cycle_entry_q, client_ctx); diff --git a/client.c b/client.c index d6019f6..d291bbc 100644 --- a/client.c +++ b/client.c @@ -58,9 +58,7 @@ struct client_ctx * client_init(Window win, struct screen_ctx *sc, int mapped) { struct client_ctx *cc; - XClassHint xch; XWindowAttributes wattr; - XWMHints *wmhints; int state; if (win == None) @@ -74,18 +72,16 @@ client_init(Window win, struct screen_ctx *sc, int mapped) cc->sc = sc; cc->win = win; - client_getsizehints(cc); - TAILQ_INIT(&cc->nameq); client_setname(cc); conf_client(cc); - if (XGetClassHint(X_Dpy, cc->win, &xch)) { - cc->app_name = xch.res_name; - cc->app_class = xch.res_class; - } + XGetClassHint(X_Dpy, cc->win, &cc->ch); + cc->wmh = XGetWMHints(X_Dpy, cc->win); client_getmwmhints(cc); + client_wm_protocols(cc); + client_getsizehints(cc); /* Saved pointer position */ cc->ptr.x = -1; @@ -98,22 +94,20 @@ client_init(Window win, struct screen_ctx *sc, int mapped) cc->geom.h = wattr.height; cc->colormap = wattr.colormap; - if ((wmhints = XGetWMHints(X_Dpy, cc->win)) != NULL) { - if (wmhints->flags & InputHint) { - if (wmhints->input == 1) + if (cc->wmh != NULL) { + if (cc->wmh->flags & InputHint) { + if (cc->wmh->input == 1) cc->flags |= CLIENT_INPUT; } } if (wattr.map_state != IsViewable) { client_placecalc(cc); client_move(cc); - if ((wmhints) && (wmhints->flags & StateHint)) { - cc->state = wmhints->initial_state; + if ((cc->wmh) && (cc->wmh->flags & StateHint)) { + cc->state = cc->wmh->initial_state; xu_set_wm_state(cc->win, cc->state); } } - if (wmhints) - XFree(wmhints); client_draw_border(cc); if (xu_get_wm_state(cc->win, &state) < 0) @@ -136,7 +130,6 @@ client_init(Window win, struct screen_ctx *sc, int mapped) xu_ewmh_net_client_list(sc); - client_wm_protocols(cc); xu_ewmh_restore_net_wm_state(cc); if (mapped) @@ -165,17 +158,19 @@ client_delete(struct client_ctx *cc) if (cc == client_current()) client_none(sc); - if (cc->app_name != NULL) - XFree(cc->app_name); - if (cc->app_class != NULL) - XFree(cc->app_class); - while ((wn = TAILQ_FIRST(&cc->nameq)) != NULL) { TAILQ_REMOVE(&cc->nameq, wn, entry); free(wn->name); 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); } diff --git a/group.c b/group.c index 2c62ae6..94d881a 100644 --- a/group.c +++ b/group.c @@ -371,7 +371,7 @@ group_autogroup(struct client_ctx *cc) int no = -1, both_match = 0; long *grpno; - if (cc->app_class == NULL || cc->app_name == NULL) + if (cc->ch.res_class == NULL || cc->ch.res_name == NULL) return; if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], @@ -385,9 +385,9 @@ group_autogroup(struct client_ctx *cc) XFree(grpno); } else { TAILQ_FOREACH(aw, &Conf.autogroupq, entry) { - if (strcmp(aw->class, cc->app_class) == 0) { + if (strcmp(aw->class, cc->ch.res_class) == 0) { if ((aw->name != NULL) && - (strcmp(aw->name, cc->app_name) == 0)) { + (strcmp(aw->name, cc->ch.res_name) == 0)) { no = aw->num; both_match = 1; } else if (aw->name == NULL && !both_match) diff --git a/search.c b/search.c index 483a51b..9e59d87 100644 --- a/search.c +++ b/search.c @@ -85,8 +85,8 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search) } /* Then if there is a match on the window class name. */ - if (tier < 0 && strsubmatch(search, cc->app_class, 0)) { - cc->matchname = cc->app_class; + if (tier < 0 && strsubmatch(search, cc->ch.res_class, 0)) { + cc->matchname = cc->ch.res_class; tier = 3; } From 0d9b1becff4661134895780e4d610521582dc288 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 11 Dec 2013 14:16:09 +0000 Subject: [PATCH 3/7] Remove extra work and simplify client state handling. --- calmwm.h | 5 ++--- client.c | 47 ++++++++++++++++++++++++++++++++++------------- xevents.c | 3 +-- xutil.c | 27 --------------------------- 4 files changed, 37 insertions(+), 45 deletions(-) diff --git a/calmwm.h b/calmwm.h index 9c613b9..d2db949 100644 --- a/calmwm.h +++ b/calmwm.h @@ -167,7 +167,6 @@ struct client_ctx { #define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED) #define CLIENT_MAXIMIZED (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED) int flags; - int state; int active; int stackingorder; struct winname_q nameq; @@ -374,6 +373,7 @@ void client_delete(struct client_ctx *); void client_draw_border(struct client_ctx *); struct client_ctx *client_find(Window); void client_freeze(struct client_ctx *); +long client_get_wm_state(struct client_ctx *); void client_getsizehints(struct client_ctx *); void client_hide(struct client_ctx *); void client_hmaximize(struct client_ctx *); @@ -389,6 +389,7 @@ void client_ptrwarp(struct client_ctx *); void client_raise(struct client_ctx *); void client_resize(struct client_ctx *, int); void client_send_delete(struct client_ctx *); +void client_set_wm_state(struct client_ctx *, long); void client_setactive(struct client_ctx *); void client_setname(struct client_ctx *); int client_snapcalc(int, int, int, int, int); @@ -509,7 +510,6 @@ void xev_loop(void); void xu_btn_grab(Window, int, u_int); void xu_btn_ungrab(Window); int xu_getprop(Window, Atom, Atom, long, unsigned char **); -int xu_get_wm_state(Window, int *); int xu_getstrprop(Window, Atom, char **); void xu_key_grab(Window, u_int, KeySym); void xu_key_ungrab(Window); @@ -518,7 +518,6 @@ int xu_ptr_grab(Window, u_int, Cursor); int xu_ptr_regrab(u_int, Cursor); void xu_ptr_setpos(Window, int, int); void xu_ptr_ungrab(void); -void xu_set_wm_state(Window win, int); void xu_xft_draw(struct screen_ctx *, const char *, int, int, int); int xu_xft_width(XftFont *, const char *, int); diff --git a/client.c b/client.c index d291bbc..6cbd0d5 100644 --- a/client.c +++ b/client.c @@ -68,7 +68,6 @@ client_init(Window win, struct screen_ctx *sc, int mapped) XGrabServer(X_Dpy); - cc->state = mapped ? NormalState : IconicState; cc->sc = sc; cc->win = win; @@ -103,16 +102,11 @@ client_init(Window win, struct screen_ctx *sc, int mapped) if (wattr.map_state != IsViewable) { client_placecalc(cc); client_move(cc); - if ((cc->wmh) && (cc->wmh->flags & StateHint)) { - cc->state = cc->wmh->initial_state; - xu_set_wm_state(cc->win, cc->state); - } + if ((cc->wmh) && (cc->wmh->flags & StateHint)) + client_set_wm_state(cc, cc->wmh->initial_state); } client_draw_border(cc); - if (xu_get_wm_state(cc->win, &state) < 0) - state = NormalState; - XSelectInput(X_Dpy, cc->win, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | KeyReleaseMask); @@ -123,6 +117,9 @@ client_init(Window win, struct screen_ctx *sc, int mapped) /* Notify client of its configuration. */ client_config(cc); + if ((state = client_get_wm_state(cc)) < 0) + state = NormalState; + (state == IconicState) ? client_hide(cc) : client_unhide(cc); TAILQ_INSERT_TAIL(&sc->mruq, cc, mru_entry); @@ -425,7 +422,10 @@ client_ptrwarp(struct client_ctx *cc) y = cc->geom.h / 2; } - (cc->state == IconicState) ? client_unhide(cc) : client_raise(cc); + if (cc->flags & CLIENT_HIDDEN) + client_unhide(cc); + else + client_raise(cc); xu_ptr_setpos(cc->win, x, y); } @@ -451,8 +451,7 @@ client_hide(struct client_ctx *cc) cc->active = 0; cc->flags |= CLIENT_HIDDEN; - cc->state = IconicState; - xu_set_wm_state(cc->win, cc->state); + client_set_wm_state(cc, IconicState); if (cc == client_current()) client_none(cc->sc); @@ -464,8 +463,7 @@ client_unhide(struct client_ctx *cc) XMapRaised(X_Dpy, cc->win); cc->flags &= ~CLIENT_HIDDEN; - cc->state = NormalState; - xu_set_wm_state(cc->win, cc->state); + client_set_wm_state(cc, NormalState); client_draw_border(cc); } @@ -982,3 +980,26 @@ client_vtile(struct client_ctx *cc) i++; } } + +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); +} + diff --git a/xevents.c b/xevents.c index f111c84..e2d8b67 100644 --- a/xevents.c +++ b/xevents.c @@ -99,8 +99,7 @@ xev_handle_unmapnotify(XEvent *ee) if ((cc = client_find(e->window)) != NULL) { if (e->send_event) { - cc->state = WithdrawnState; - xu_set_wm_state(cc->win, cc->state); + client_set_wm_state(cc, WithdrawnState); } else { if (!(cc->flags & CLIENT_HIDDEN)) client_delete(cc); diff --git a/xutil.c b/xutil.c index 73dfac0..3435274 100644 --- a/xutil.c +++ b/xutil.c @@ -157,33 +157,6 @@ xu_getstrprop(Window win, Atom atm, char **text) { return (nitems); } -int -xu_get_wm_state(Window win, int *state) -{ - long *p = NULL; - - if (xu_getprop(win, cwmh[WM_STATE], cwmh[WM_STATE], 2L, - (unsigned char **)&p) <= 0) - return (-1); - - *state = (int)*p; - XFree((char *)p); - - return (0); -} - -void -xu_set_wm_state(Window win, int state) -{ - long dat[2]; - - dat[0] = state; - dat[1] = None; - - XChangeProperty(X_Dpy, win, cwmh[WM_STATE], cwmh[WM_STATE], 32, - PropModeReplace, (unsigned char *)dat, 2); -} - /* Root Window Properties */ void xu_ewmh_net_supported(struct screen_ctx *sc) From 7e0749b0b1e62f490f37aeb65302cd38b1fb52be Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 11 Dec 2013 15:41:11 +0000 Subject: [PATCH 4/7] Add client wrapper for XWMHints to support XA_WM_HINTS in PropertyNotify events; based off a diff from Thomas Adam. --- calmwm.h | 1 + client.c | 18 +++++++++++------- xevents.c | 3 +++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/calmwm.h b/calmwm.h index d2db949..9dfe66a 100644 --- a/calmwm.h +++ b/calmwm.h @@ -398,6 +398,7 @@ void client_unhide(struct client_ctx *); void client_vmaximize(struct client_ctx *); void client_vtile(struct client_ctx *); void client_warp(struct client_ctx *); +void client_wm_hints(struct client_ctx *); void group_alltoggle(struct screen_ctx *); void group_autogroup(struct client_ctx *); diff --git a/client.c b/client.c index 6cbd0d5..51162aa 100644 --- a/client.c +++ b/client.c @@ -77,7 +77,7 @@ client_init(Window win, struct screen_ctx *sc, int mapped) conf_client(cc); XGetClassHint(X_Dpy, cc->win, &cc->ch); - cc->wmh = XGetWMHints(X_Dpy, cc->win); + client_wm_hints(cc); client_getmwmhints(cc); client_wm_protocols(cc); client_getsizehints(cc); @@ -93,12 +93,6 @@ client_init(Window win, struct screen_ctx *sc, int mapped) cc->geom.h = wattr.height; cc->colormap = wattr.colormap; - if (cc->wmh != NULL) { - if (cc->wmh->flags & InputHint) { - if (cc->wmh->input == 1) - cc->flags |= CLIENT_INPUT; - } - } if (wattr.map_state != IsViewable) { client_placecalc(cc); client_move(cc); @@ -509,6 +503,16 @@ 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; +} + void client_msg(struct client_ctx *cc, Atom proto) { diff --git a/xevents.c b/xevents.c index e2d8b67..60944d7 100644 --- a/xevents.c +++ b/xevents.c @@ -186,6 +186,9 @@ xev_handle_propertynotify(XEvent *ee) case XA_WM_NAME: client_setname(cc); break; + case XA_WM_HINTS: + client_wm_hints(cc); + break; case XA_WM_TRANSIENT_FOR: client_transient(cc); break; From 68f365cddbf9ae293d20b3088403aa9972854b29 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 11 Dec 2013 15:46:47 +0000 Subject: [PATCH 5/7] apply mwm hints later --- client.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client.c b/client.c index 51162aa..a6723cd 100644 --- a/client.c +++ b/client.c @@ -37,7 +37,7 @@ static void client_mtf(struct client_ctx *); static void client_none(struct screen_ctx *); static void client_placecalc(struct client_ctx *); static void client_wm_protocols(struct client_ctx *); -static void client_getmwmhints(struct client_ctx *); +static void client_mwm_hints(struct client_ctx *); static int client_inbound(struct client_ctx *, int, int); struct client_ctx *_curcc = NULL; @@ -78,9 +78,9 @@ client_init(Window win, struct screen_ctx *sc, int mapped) XGetClassHint(X_Dpy, cc->win, &cc->ch); client_wm_hints(cc); - client_getmwmhints(cc); client_wm_protocols(cc); client_getsizehints(cc); + client_mwm_hints(cc); /* Saved pointer position */ cc->ptr.x = -1; @@ -806,7 +806,7 @@ client_applysizehints(struct client_ctx *cc) } static void -client_getmwmhints(struct client_ctx *cc) +client_mwm_hints(struct client_ctx *cc) { struct mwm_hints *mwmh; From 09e07ddaafe617fccd7c7ac98004d300e1cd8cba Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 11 Dec 2013 17:23:31 +0000 Subject: [PATCH 6/7] since we are drawing in unhide, no need to during client setup --- client.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client.c b/client.c index a6723cd..135cef1 100644 --- a/client.c +++ b/client.c @@ -99,7 +99,6 @@ client_init(Window win, struct screen_ctx *sc, int mapped) if ((cc->wmh) && (cc->wmh->flags & StateHint)) client_set_wm_state(cc, cc->wmh->initial_state); } - client_draw_border(cc); XSelectInput(X_Dpy, cc->win, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | KeyReleaseMask); From e767ac9c6556d04c346b89e8d47d721c38cc366e Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 11 Dec 2013 22:14:23 +0000 Subject: [PATCH 7/7] we don't need to manage the save-set since we're not reparenting; left-over from pwin --- client.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/client.c b/client.c index 135cef1..a601805 100644 --- a/client.c +++ b/client.c @@ -103,8 +103,6 @@ client_init(Window win, struct screen_ctx *sc, int mapped) XSelectInput(X_Dpy, cc->win, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | KeyReleaseMask); - XAddToSaveSet(X_Dpy, cc->win); - client_transient(cc); /* Notify client of its configuration. */