Add client size hints support

This commit is contained in:
Martin Duquesnoy
2011-10-06 23:41:38 +02:00
parent 39380848a0
commit ad5c4101ee
3 changed files with 130 additions and 9 deletions

View File

@@ -295,6 +295,69 @@ uicb_client_close(Uicb cmd)
client_close(W->client);
}
static void
client_get_sizeh(struct client *c)
{
long msize;
XSizeHints size;
memset(c->sizeh, 0, SHLAST);
if(!XGetWMNormalHints(W->dpy, c->win, &size, &msize) || !size.flags)
size.flags = PSize;
/* base */
if(size.flags & PBaseSize)
{
c->sizeh[BASEW] = size.base_width;
c->sizeh[BASEH] = size.base_height;
}
else if(size.flags & PMinSize)
{
c->sizeh[BASEW] = size.min_width;
c->sizeh[BASEH] = size.min_height;
}
/* inc */
if(size.flags & PResizeInc)
{
c->sizeh[INCW] = size.width_inc;
c->sizeh[INCH] = size.height_inc;
}
/* max */
if(size.flags & PMaxSize)
{
c->sizeh[MAXW] = size.max_width;
c->sizeh[MAXH] = size.max_height;
}
/* min */
if(size.flags & PMinSize)
{
c->sizeh[MINW] = (size.min_width ? size.min_width : 1);
c->sizeh[MINH] = (size.min_height ? size.min_height: 1);
}
else if(size.flags & PBaseSize)
{
c->sizeh[MINW] = (size.base_width ? size.base_width : 1);
c->sizeh[MINH] = (size.base_height ? size.base_height : 1);
}
/* aspect */
if(size.flags & PAspect)
{
c->sizeh[MINAX] = size.min_aspect.x;
c->sizeh[MAXAX] = size.max_aspect.x;
c->sizeh[MINAY] = size.min_aspect.y;
c->sizeh[MAXAY] = size.max_aspect.y;
}
if(c->sizeh[MAXW] && c->sizeh[MINW] && c->sizeh[MAXH] && c->sizeh[MINH]
&& c->sizeh[MAXW] == c->sizeh[MINW] && c->sizeh[MAXH] == c->sizeh[MINH])
c->flags |= CLIENT_HINT_FLAG;
}
struct client*
client_new(Window w, XWindowAttributes *wa)
{
@@ -314,6 +377,7 @@ client_new(Window w, XWindowAttributes *wa)
c->tgeo = c->wgeo = c->geo;
/* Set tag */
client_get_sizeh(c);
tag_client(W->screen->seltag, c);
/* X window attributes */
@@ -335,6 +399,43 @@ client_new(Window w, XWindowAttributes *wa)
return c;
}
static void
client_geo_hints(struct geo *g, int *s)
{
/* base */
g->w -= s[BASEW];
g->h -= s[BASEH];
/* aspect */
if((s[MINAY] | s[MAXAY] | s[MINAX] | s[MAXAX]) > 0)
{
if(g->w * s[MAXAY] > g->h * s[MAXAX])
g->w = g->h * s[MAXAX] / s[MAXAY];
else if(g->w * s[MINAY] < g->h * s[MINAX])
g->h = g->w * s[MINAY] / s[MINAX];
}
/* incremental */
if(s[INCW])
g->w -= g->w % s[INCW];
if(s[INCH])
g->h -= g->h % s[INCH];
/* base dimension */
g->w += s[BASEW];
g->h += s[BASEH];
if(s[MINW] > 0 && g->w < s[MINW])
g->w = s[MINW];
if(s[MINH] > 0 && g->h < s[MINH])
g->h = s[MINH];
if(s[MAXW] > 0 && g->w > s[MAXW])
g->w = s[MAXW];
if(s[MAXH] > 0 && g->h > s[MAXH])
g->h = s[MAXH];
}
void
client_moveresize(struct client *c, struct geo *g)
{
@@ -348,6 +449,8 @@ client_moveresize(struct client *c, struct geo *g)
c->wgeo.w = g->w - (bord << 1);
c->wgeo.h = g->h - (bord << 1);
client_geo_hints(&c->wgeo, (int*)c->sizeh);
XMoveResizeWindow(W->dpy, c->win,
c->wgeo.x, c->wgeo.y,
c->wgeo.w, c->wgeo.h);

View File

@@ -93,6 +93,15 @@ layout_split_check_row_dir(struct client *c, struct client *g, enum position p)
* '-.__ _.' ~
* ````` ~
*/
#define _ARRANGE_SINGLE_PARENT(p) \
do { \
if((c = client_next_with_pos(ghost, p))) \
if(GEO_CHECK2(ghost->geo, c->geo, p)) \
{ \
layout_split_arrange_size(&ghost->geo, c, p); \
return; \
} \
} while(/* CONSTCOND */ 0);
void
layout_split_arrange_closed(struct client *ghost)
{
@@ -110,15 +119,11 @@ layout_split_arrange_closed(struct client *ghost)
* | | C | -> C -> | |v v v|
* |_____|_____| -> -> |_____|_____|
*/
for(p = Right; p < Center; ++p) /* Check every direction */
{
if((c = client_next_with_pos(ghost, p)))
if(GEO_CHECK2(ghost->geo, c->geo, p))
{
layout_split_arrange_size(&ghost->geo, c, p);
return;
}
}
_ARRANGE_SINGLE_PARENT(Right);
_ARRANGE_SINGLE_PARENT(Left);
_ARRANGE_SINGLE_PARENT(Top);
_ARRANGE_SINGLE_PARENT(Bottom);
/* Check row parents for full resize
* Example case:

View File

@@ -49,6 +49,17 @@ enum position
PositionLast
};
enum size_hints
{
BASEW, BASEH,
INCW, INCH,
MAXW, MAXH,
MINW, MINH,
MINAX, MINAY,
MAXAX, MAXAY,
SHLAST
};
/*
* Structures
*/
@@ -122,7 +133,9 @@ struct client
struct screen *screen;
struct barwin *titlebar;
struct geo geo, tgeo, wgeo;
int sizeh[SHLAST];
char *title;
#define CLIENT_HINT_FLAG 0x01
Flags flags;
Window win;
SLIST_ENTRY(client) next; /* Global list */