frame: Add frame buttons support: 3 buttons at the top-right of the client for multiple usage

This commit is contained in:
Martin Duquesnoy 2008-11-10 04:06:14 +01:00
parent f0a78fd027
commit 5ba931d1d6
8 changed files with 129 additions and 84 deletions

View File

@ -165,7 +165,6 @@ client_focus(Client *c)
if(sel && sel != c)
{
sel->colors.frame = conf.client.bordernormal;
sel->colors.titlebar = conf.titlebar.fg_normal;
sel->colors.resizecorner = conf.client.resizecorner_normal;
frame_update(sel);
mouse_grabbuttons(sel, False);
@ -176,7 +175,6 @@ client_focus(Client *c)
if(c)
{
c->colors.frame = conf.client.borderfocus;
c->colors.titlebar = conf.titlebar.fg_focus;
c->colors.resizecorner = conf.client.resizecorner_focus;
frame_update(c);
mouse_grabbuttons(c, True);
@ -242,6 +240,21 @@ client_focus(Client *c)
return c;
}
/** Get a client->button[button_number] with a window
* \param b Button type
* \param w Window
* \return The client
*/
Client* client_gb_button(ButtonType b, Window w)
{
Client *c;
for(c = clients; c && c->button[b] != w; c = c->next);
return c;
}
/* }}} */
/** Get a client name
@ -333,13 +346,12 @@ client_manage(Window w, XWindowAttributes *wa)
c = emalloc(1, sizeof(Client));
c->win = w;
c->geo.x = wa->x;
c->geo.y = wa->y + sgeo.y + conf.titlebar.height;
c->geo.y = wa->y + sgeo.y;
c->geo.width = wa->width;
c->geo.height = wa->height;
c->tag = seltag;
frame_create(c);
XSelectInput(dpy, c->win, PropertyChangeMask | StructureNotifyMask);
mouse_grabbuttons(c, False);
client_size_hints(c);
@ -498,7 +510,6 @@ client_size_hints(Client *c)
c->maxay = size.max_aspect.y;
}
else
c->minax = c->maxax = c->minay = c->maxay = 0;
c->hint = (c->maxw && c->minw && c->maxh && c->minh
&& c->maxw == c->minw && c->maxh == c->minh);

View File

@ -206,10 +206,9 @@ init_conf(void)
static cfg_opt_t titlebar_opts[] =
{
CFG_INT("height", 0, CFGF_NONE),
CFG_STR("fg_focus", "#FFFFFF", CFGF_NONE),
CFG_STR("fg_normal", "#FFFFFF", CFGF_NONE),
CFG_SEC("mouse", mouse_button_opts, CFGF_MULTI),
CFG_INT("height", 0, CFGF_NONE),
CFG_STR("fg", "#FFFFFF", CFGF_NONE),
CFG_SEC("mouse", mouse_button_opts, CFGF_MULTI),
CFG_END()
};
@ -399,8 +398,7 @@ init_conf(void)
/* titlebar (in client) */
cfgtmp = cfg_getsec(cfg_client, "titlebar");
conf.titlebar.height = cfg_getint(cfgtmp, "height");
conf.titlebar.fg_focus = var_to_str(cfg_getstr(cfgtmp, "fg_focus"));
conf.titlebar.fg_normal = var_to_str(cfg_getstr(cfgtmp, "fg_normal"));
conf.titlebar.fg = var_to_str(cfg_getstr(cfgtmp, "fg"));
conf.titlebar.nmouse = cfg_size(cfgtmp, "mouse");
conf.titlebar.mouse = emalloc(conf.titlebar.nmouse, sizeof(MouseBinding));
@ -451,7 +449,8 @@ init_conf(void)
/* tag */
/* if there is no tag in the conf or more than
* MAXTAG (32) print an error and create only one. */
* MAXTAG (32) print an error and create only one.
*/
conf.colors.tagselfg = strdup(var_to_str(cfg_getstr(cfg_tags, "sel_fg")));
conf.colors.tagselbg = getcolor(var_to_str(cfg_getstr(cfg_tags, "sel_bg")));
conf.tagbordwidth = cfg_getint(cfg_tags, "border_width");

View File

@ -42,7 +42,7 @@ buttonpress(XButtonEvent *ev)
int i;
char s[6];
/* Frame & titlebar */
/* Titlebar */
if((c = client_gb_titlebar(ev->window)))
for(i = 0; i < conf.titlebar.nmouse; ++i)
if(ev->button == conf.titlebar.mouse[i].button)
@ -145,11 +145,18 @@ configurerequest(XConfigureRequestEvent *ev)
if(ev->value_mask & CWHeight)
geo.height = ev->height;
if(geo.x != c->geo.x || geo.y != c->geo.y
|| geo.width != c->geo.width || geo.height != c->geo.height)
if(geo.x != c->geo.x
|| geo.y != c->geo.y
|| geo.width != c->geo.width
|| geo.height != c->geo.height)
{
/*
* Adjust the client's future geo to
* set the correct position of the frame
*/
geo.x += BORDH;
geo.y += TBARH;
/* Resize */
client_moveresize(c, geo, True);
}
else
@ -197,9 +204,9 @@ enternotify(XCrossingEvent *ev)
return;
if((c = client_gb_win(ev->window))
|| (c = client_gb_frame(ev->window))
|| (c = client_gb_titlebar(ev->window))
|| (c = client_gb_resize(ev->window)))
|| (c = client_gb_titlebar(ev->window)))
client_focus(c);
else
client_focus(NULL);
@ -218,9 +225,8 @@ expose(XExposeEvent *ev)
&& (ev->window == infobar->bar->win))
infobar_draw();
for(c = clients; c; c = c->next)
if(ev->window == c->titlebar)
frame_update(c);
if((c = client_gb_titlebar(ev->window)))
frame_update(c);
return;
}

View File

@ -40,6 +40,7 @@ void
frame_create(Client *c)
{
XSetWindowAttributes at;
int i;
at.background_pixel = conf.client.bordernormal;
at.background_pixmap = ParentRelative;
@ -54,41 +55,48 @@ frame_create(Client *c)
c->frame_geo.height = FRAMEH(c->geo.height);
c->colors.frame = conf.client.bordernormal;
c->colors.resizecorner = conf.client.resizecorner_normal;
c->colors.titlebar = conf.titlebar.fg_normal;
/* Create frame window */
c->frame = XCreateWindow(dpy, root,
c->frame_geo.x,
c->frame_geo.y,
c->frame_geo.width,
c->frame_geo.height, 0,
CopyFromParent, InputOutput, CopyFromParent,
CWOverrideRedirect|CWBackPixmap|CWEventMask, &at);
CWIN(c->frame, root,
c->frame_geo.x,
c->frame_geo.y,
c->frame_geo.width,
c->frame_geo.height, 0,
CWOverrideRedirect|CWBackPixmap|CWEventMask, c->colors.frame, &at);
/* Create titlebar window */
c->titlebar = XCreateWindow(dpy, c->frame, 0, 0,
c->frame_geo.width,
TBARH + BORDH, 0,
CopyFromParent, InputOutput, CopyFromParent,
CWEventMask|CWBackPixel, &at);
if(TBARH)
CWIN(c->titlebar, c->frame, 0, 0,
c->frame_geo.width,
TBARH + BORDH,
0, CWEventMask|CWBackPixel,
c->colors.frame, &at);
/* Titlebar buttons */
at.event_mask &= ~EnterWindowMask; /* <- Delete the EnterWindow mask */
if(CTBAR)
for(i = 0; i < LastButton; ++i)
{
CWIN(c->button[i], c->frame,
BUTX(i), 2,
BUTHW, BUTHW,
1, CWEventMask|CWBackPixel,
c->colors.frame, &at);
XSetWindowBorder(dpy, c->button[i], getcolor(conf.titlebar.fg));
}
/* Create resize area */
at.cursor = cursor[CurResize];
c->resize = XCreateWindow(dpy, c->frame,
c->frame_geo.width - RESHW,
c->frame_geo.height - RESHW,
RESHW, RESHW, 0, CopyFromParent,
InputOutput, CopyFromParent,
CWEventMask|CWBackPixel|CWCursor, &at);
/* Color it */
XSetWindowBackground(dpy, c->resize, c->colors.resizecorner);
XSetWindowBackground(dpy, c->titlebar, c->colors.frame);
XSetWindowBackground(dpy, c->frame, c->colors.frame);
if(BORDH)
CWIN(c->resize, c->frame,
c->frame_geo.width - RESHW,
c->frame_geo.height - RESHW,
RESHW,
RESHW, 0,
CWEventMask|CWBackPixel|CWCursor, c->colors.resizecorner, &at);
/* Reparent window with the frame */
XReparentWindow(dpy, c->win, c->frame, BORDH, BORDH + TBARH);
return;
}
@ -111,10 +119,12 @@ frame_moveresize(Client *c, XRectangle geo)
c->frame_geo.width,
c->frame_geo.height);
/* Titlebar */
XResizeWindow(dpy, c->titlebar, c->frame_geo.width, TBARH + BORDH);
if(TBARH)
XResizeWindow(dpy, c->titlebar, c->frame_geo.width, TBARH + BORDH);
/* Resize area */
XMoveWindow(dpy, c->resize, c->frame_geo.width - RESHW, c->frame_geo.height - RESHW);
if(BORDH)
XMoveWindow(dpy, c->resize, c->frame_geo.width - RESHW, c->frame_geo.height - RESHW);
return;
}
@ -125,27 +135,33 @@ frame_moveresize(Client *c, XRectangle geo)
void
frame_update(Client *c)
{
int px, py;
int i;
XSetWindowBackground(dpy, c->frame, c->colors.frame);
XSetWindowBackground(dpy, c->titlebar, c->colors.frame);
XSetWindowBackground(dpy, c->resize, c->colors.resizecorner);
XClearWindow(dpy, c->frame);
XClearWindow(dpy, c->titlebar);
XClearWindow(dpy, c->resize);
/* Draw the client title \in the titlebar *logeek* */
if((conf.titlebar.height + BORDH + 1) > font->height)
if(CTBAR)
for(i = 0; i < LastButton; ++i)
{
XSetWindowBackground(dpy, c->button[i], c->colors.frame);
XClearWindow(dpy, c->button[i]);
}
if(BORDH)
{
/* x position of the text (center) */
px = (c->frame_geo.width / 2) - (textw(c->title) / 2);
/* y position of the text (center too) */
py = (font->height - (font->descent )) + (((TBARH + BORDH) - font->height) / 2);
draw_text(c->titlebar, px, py, c->colors.titlebar, c->colors.frame, 0, c->title);
XSetWindowBackground(dpy, c->resize, c->colors.resizecorner);
XClearWindow(dpy, c->resize);
}
if(TBARH)
{
XSetWindowBackground(dpy, c->titlebar, c->colors.frame);
XClearWindow(dpy, c->titlebar);
}
XSetWindowBackground(dpy, c->frame, c->colors.frame);
XClearWindow(dpy, c->frame);
if((TBARH + BORDH + 1) > font->height)
draw_text(c->titlebar,
(c->frame_geo.width / 2) - (textw(c->title) / 2),
(font->height - (font->descent )) + (((TBARH + BORDH) - font->height) / 2),
conf.titlebar.fg, c->colors.frame, 0, c->title);
return;
}

View File

@ -198,7 +198,7 @@ nexttiled(Client *c)
}
/** Set the mwfact
* \param cmd Mwfact
* \param cmd Mwfact (string)
*/
void
uicb_set_mwfact(uicb_t cmd)
@ -218,7 +218,7 @@ uicb_set_mwfact(uicb_t cmd)
}
/** Set the nmaster
* \param cmd nmaster
* \param cmd Nmaster (string)
*/
void
uicb_set_nmaster(uicb_t cmd)
@ -324,7 +324,7 @@ multi_tile(Position type)
if(type == Top)
mastergeo.y = (n <= nmaster) ? sgeo.y : sgeo.y + (sgeo.height - mwfact) - border;
mastergeo.width = (sgeo.width / nmaster) - BORDH;
mastergeo.height = (n <= nmaster) ? sgeo.height - BORDH : mwfact;
mastergeo.height = (n <= nmaster) ? sgeo.height - border : mwfact;
}
else
{
@ -346,7 +346,7 @@ multi_tile(Position type)
for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++i)
{
/* Set client property, 'don't care */
/* Set client property */
c->max = c->lmax = False;
c->tile = True;
c->ogeo.x = c->geo.x; c->ogeo.y = c->geo.y;

View File

@ -51,9 +51,12 @@ enum { CurNormal, CurResize, CurMove, CurLast };
enum { WMState, WMProtocols, WMName, WMDelete, WMLast };
enum { NetSupported, NetWMName, NetLast };
typedef enum { Top = 0, Bottom, Right, Left, Center, PositionLast } Position;
typedef enum { CloseButton = 0, MaxButton = 1, FreeButton = 2, LastButton } ButtonType;
/* BarWindow Structure
* (titlebar, topbar..) */
/*
* BarWindow Structure
* (titlebar, topbar..)
*/
typedef struct
{
Window win;
@ -85,14 +88,12 @@ struct Client
Window win;
Window frame;
Window resize, titlebar;
Window button[LastButton];
struct
{
uint frame;
uint resizecorner;
char *titlebar;
} colors;
/* Border */
int border;
/* Client Layout Information */
Bool max, tile, free, hide;
Bool hint, lmax, havetbar;
@ -157,8 +158,10 @@ typedef struct
int tagbordwidth;
struct
{
/* Only the colors will be use for text
* are 'char*' (for xprint -> XftColorAllocName) */
/*
* Only the colors will be use for text
* are 'char*' (for xprint -> XftColorAllocName)
*/
uint bar;
char *text;
char *tagselfg;
@ -187,8 +190,7 @@ typedef struct
struct
{
int height;
char *fg_focus;
char *fg_normal;
char *fg;
MouseBinding *mouse;
int nmouse;
} titlebar;

View File

@ -59,18 +59,29 @@
#define MouseMask (ButtonMask | PointerMotionMask)
#define KeyMask (KeyPressMask | KeyReleaseMask)
#define CWIN(win, parent, x, y, w, h, b, mask, col, at) \
win = XCreateWindow(dpy, parent, x, y, w, h, b, CopyFromParent, \
InputOutput, CopyFromParent, mask, at); \
XSetWindowBackground(dpy, win, col);
#define MAXH DisplayHeight(dpy, screen)
#define MAXW DisplayWidth(dpy, screen)
#define FRAMEW(w) w + conf.client.borderheight * 2
#define FRAMEH(h) h + (conf.client.borderheight * 2) + conf.titlebar.height
#define BORDH conf.client.borderheight
#define TBARH conf.titlebar.height
#define RESHW 15
#define FRAMEW(w) w + BORDH * 2
#define FRAMEH(h) h + (BORDH * 2) + TBARH
/* To checking if wmfs can create and use the titlebar buttons */
#define CTBAR TBARH - BORDH > 1
#define BUTHW (BORDH + TBARH) - 6
#define BUTX(b) (b + 0.5) * BUTHW + BORDH + 1
#define RESHW 5 * BORDH
#define CHECK(x) if(!x) return
#define ITOA(p ,n) sprintf(p, "%d", n)
#define debug(p) fprintf(stderr, "debug: %d\n", p)
#define deb(p) fprintf(stderr, "debug: %d\n", p)
#define PAD 8
/* bar.c */
@ -106,6 +117,7 @@ Client* client_gb_win(Window w);
Client* client_gb_frame(Window w);
Client* client_gb_titlebar(Window w);
Client* client_gb_resize(Window w);
Client* client_gb_button(ButtonType b, Window w);
/* }}} */
void client_get_name(Client *c);
void client_hide(Client *c);

5
wmfsrc
View File

@ -81,9 +81,8 @@ client
titlebar
{
height = 11
fg_normal = "#B4B4B4"
fg_focus = "#D4D4D4"
height = 11
fg = "#D4D4D4"
mouse { button = "1" func = "client_raise" }
mouse { button = "1" func = "mouse_move" }