Add client size hints support
This commit is contained in:
103
src/client.c
103
src/client.c
@@ -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);
|
||||
|
||||
23
src/layout.c
23
src/layout.c
@@ -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:
|
||||
|
||||
13
src/wmfs.h
13
src/wmfs.h
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user