diff --git a/src/client.c b/src/client.c index 39c9bc6..1ae6e72 100644 --- a/src/client.c +++ b/src/client.c @@ -972,12 +972,14 @@ client_new(Window w, XWindowAttributes *wa, bool scan) client_apply_rule(c); } + ewmh_manage_state_sticky(c); + /* * Conf option set per client, for possibility * to config only one client */ c->border = c->theme->client_border_width; - if(!(c->tbarw = c->theme->client_titlebar_width)) + if(!(c->tbarw = c->theme->client_titlebar_width) || (c->flags & CLIENT_STICKY)) c->tbarw = c->border; c->ncol = c->theme->client_n; @@ -1199,6 +1201,25 @@ client_moveresize(struct client *c, struct geo *g) client_configure(c); } +void +client_place_at_mouse(struct client *c) +{ + int x, y; + + Window w; + int d, u; + + XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (uint *)&u); + + if(x < c->screen->ugeo.x) + x = 0; + if(y < c->screen->ugeo.y) + y = 0; + + c->geo.x = ((x + c->geo.w) > c->screen->ugeo.w ? c->screen->ugeo.w - c->geo.w : x); + c->geo.y = ((y + c->geo.h) > c->screen->ugeo.h ? c->screen->ugeo.h - c->geo.h : y); +} + void client_maximize(struct client *c) { diff --git a/src/client.h b/src/client.h index eb10c95..0535aae 100644 --- a/src/client.h +++ b/src/client.h @@ -44,6 +44,7 @@ void client_geo_hints(struct geo *g, int *s); void client_get_sizeh(struct client *c); bool client_winsize(struct client *c, struct geo *geo); void client_moveresize(struct client *c, struct geo *g); +void client_place_at_mouse(struct client *c); void client_maximize(struct client *c); void client_fac_resize(struct client *c, enum position p, int fac); void client_fac_adjust(struct client *c); @@ -211,4 +212,13 @@ client_get_larger(struct tag *t, bool ignoring_tag) return lc; } +static inline void +clients_layout_refresh(void) +{ + struct client *c; + + SLIST_FOREACH(c, &W->h.client, next) + layout_fix_hole(c); +} + #endif /* CLIENT_H */ diff --git a/src/config.h b/src/config.h index 9b83688..17e8754 100644 --- a/src/config.h +++ b/src/config.h @@ -88,6 +88,9 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] = { "status" , uicb_status }, { "status_surface", uicb_status_surface }, + /* Infobar */ + { "infobar_toggle_hide", uicb_infobar_toggle_hide }, + /* Mouse */ { "mouse_resize", uicb_mouse_resize }, { "mouse_move", uicb_mouse_move }, diff --git a/src/ewmh.c b/src/ewmh.c index e2472ea..417a09f 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -227,6 +227,38 @@ ewmh_manage_state(long data[], struct client *c) layout_fix_hole(c); } } + +} + +void +ewmh_manage_state_sticky(struct client *c) +{ + Atom *atom, rf; + int f; + unsigned long n, il, i; + unsigned char *data = NULL; + + if(XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_state], 0L, 0x7FFFFFFFL, false, + XA_ATOM, &rf, &f, &n, &il, &data) == Success && n) + { + atom = (Atom*)data; + + for(i = 0; i < n; ++i) + { + /* manage _NET_WM_STATE_STICKY */ + if(atom[i] == W->net_atom[net_wm_state_sticky]) + { + c->flags |= CLIENT_STICKY; + c->flags |= CLIENT_FREE; + + client_place_at_mouse(c); + + break; + } + } + + XFree(data); + } } void diff --git a/src/ewmh.h b/src/ewmh.h index 28535fe..9f8c958 100644 --- a/src/ewmh.h +++ b/src/ewmh.h @@ -124,6 +124,7 @@ void ewmh_get_client_list(void); long ewmh_get_xembed_state(Window win); void ewmh_update_wmfs_props(void); void ewmh_manage_state(long data[], struct client *c); +void ewmh_manage_state_sticky(struct client *c); void ewmh_manage_window_type(struct client *c); bool ewmh_manage_window_type_desktop(Window win); diff --git a/src/infobar.c b/src/infobar.c index 453033a..091d47c 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -515,8 +515,48 @@ infobar_free(struct screen *s) } } +void +uicb_infobar_toggle_hide(Uicb iname) +{ + struct infobar *i; + if (iname) + i = infobar_gb_name(iname); + else + i = SLIST_FIRST(&W->screen->infobars); + if(i->pos == BarHide) + { + i->pos = i->opos; + if(infobar_placement(i, i->pos)) + { + barwin_map(i->bar); + barwin_map_subwin(i->bar); + barwin_refresh_color(i->bar); + infobar_refresh(i); + } + } + else + { + i->opos = i->pos; + i->pos = BarHide; + barwin_unmap_subwin(i->bar); + barwin_unmap(i->bar); + + switch(i->opos) + { + case BarTop: + i->screen->ugeo.y -= i->geo.h; + case BarBottom: + i->screen->ugeo.h += i->geo.h; + case BarHide: + default: + break; + } + } + + clients_layout_refresh(); +} diff --git a/src/infobar.h b/src/infobar.h index 9e9c82f..a61e803 100644 --- a/src/infobar.h +++ b/src/infobar.h @@ -88,4 +88,6 @@ infobar_gb_name(const char *name) return SLIST_FIRST(&s->infobars); } +void uicb_infobar_toggle_hide(Uicb iname); + #endif /* INFOBAR_H */ diff --git a/src/layout.c b/src/layout.c index b73cea6..3d92dae 100644 --- a/src/layout.c +++ b/src/layout.c @@ -631,7 +631,7 @@ layout_client(struct client *c) return; } - if(c->flags & CLIENT_FREE) + if(c->flags & (CLIENT_FREE | CLIENT_STICKY)) { layout_split_arrange_closed(c); c->flags ^= CLIENT_TILED; diff --git a/src/wmfs.h b/src/wmfs.h index 1e6a4b4..6479387 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -151,7 +151,7 @@ struct infobar struct screen *screen; struct theme *theme; struct status_ctx statusctx; - enum barpos pos; + enum barpos opos, pos; char *elemorder; char *name; TAILQ_HEAD(esub, element) elements; @@ -217,6 +217,7 @@ struct client #define CLIENT_TILED 0x2000 #define CLIENT_MOUSE 0x4000 #define CLIENT_IGNORE_TAG 0x8000 +#define CLIENT_STICKY 0x10000 Flags flags; Window win, frame, tmp; SLIST_ENTRY(client) next; /* Global list */