frame: Add frame buttons support: 3 buttons at the top-right of the client for multiple usage
This commit is contained in:
parent
f0a78fd027
commit
5ba931d1d6
21
src/client.c
21
src/client.c
@ -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);
|
||||
|
||||
13
src/config.c
13
src/config.c
@ -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");
|
||||
|
||||
22
src/event.c
22
src/event.c
@ -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;
|
||||
}
|
||||
|
||||
104
src/frame.c
104
src/frame.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
20
src/wmfs.h
20
src/wmfs.h
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user