浏览代码

Refactored code, changed resources and config.h

master
phillbush 4 年前
父节点
当前提交
fd530f3f68
共有 3 个文件被更改,包括 162 次插入140 次删除
  1. +20
    -11
      config.h
  2. +4
    -4
      xmenu.1
  3. +138
    -125
      xmenu.c

+ 20
- 11
config.h 查看文件

@@ -1,11 +1,20 @@
static const char *font = "monospace:size=9"; /* font */
static const char *background = "#FFFFFF"; static const char *font = "monospace:size=9"; /* for regular items */
static const char *foreground = "#2E3436"; /* colors */
static const char *selbackground = "#3584E4"; static const char *background_color = "#FFFFFF";
static const char *selforeground = "#FFFFFF"; static const char *foreground_color = "#2E3436";
static const char *separator = "#CDC7C2"; static const char *selbackground_color = "#3584E4";
static const char *border = "#E6E6E6"; static const char *selforeground_color = "#FFFFFF";
static int width = 130; static const char *separator_color = "#CDC7C2";
static int itemborder = 4; static const char *border_color = "#E6E6E6";
static int menuborder = 1; /* sizes in pixels */
static int separatorsize = 1; static int width_pixels = 130; /* minimum width of a menu */
static int padding_pixels = 4; /* padding around label in a item */
static int border_pixels = 1; /* menu border */
static int separator_pixels = 3; /* space around separator */

/* geometry of the right-pointing isoceles triangle for submenus */
static const int triangle_width = 3;
static const int triangle_height = 7;

+ 4
- 4
xmenu.1 查看文件

@@ -94,13 +94,13 @@ The color of the separator between itens in the menu.
.B xmenu.width .B xmenu.width
The minimum width, in pixels, of the items in the menu. The minimum width, in pixels, of the items in the menu.
.TP .TP
.B xmenu.itemborder .B xmenu.padding
The size in pixels of the border around the label text in items in the menu. The size in pixels of the padding around the label text in items in the menu.
.TP .TP
.B xmenu.menuborder .B xmenu.borderWidth
The size in pixels of the border around the menu. The size in pixels of the border around the menu.
.TP .TP
.B xmenu.separatorsize .B xmenu.separatorWidth
The size in pixels of the item separator. The size in pixels of the item separator.


.SH EXAMPLES .SH EXAMPLES


+ 138
- 125
xmenu.c 查看文件

@@ -25,7 +25,8 @@ enum {ColorFG, ColorBG, ColorLast};
struct DC { struct DC {
XftColor normal[ColorLast]; XftColor normal[ColorLast];
XftColor selected[ColorLast]; XftColor selected[ColorLast];
XftColor decoration[ColorLast]; XftColor border;
XftColor separator;


Drawable d; Drawable d;
GC gc; GC gc;
@@ -33,7 +34,7 @@ struct DC {
}; };


/* menu geometry structure */ /* menu geometry structure */
struct Geometry { struct MenuGeometry {
int itemb; /* item border */ int itemb; /* item border */
int itemw; /* item width */ int itemw; /* item width */
int itemh; /* item height */ int itemh; /* item height */
@@ -80,6 +81,8 @@ static void setupgeom(void);
static struct Item *allocitem(const char *label, const char *output); static struct Item *allocitem(const char *label, const char *output);
static struct Menu *allocmenu(struct Menu *parent, struct Item *list, unsigned level); static struct Menu *allocmenu(struct Menu *parent, struct Item *list, unsigned level);
static void getmenuitem(Window win, int y, struct Menu **menu_ret, struct Item **item_ret); static void getmenuitem(Window win, int y, struct Menu **menu_ret, struct Item **item_ret);
static void drawseparator(struct Menu *menu, struct Item *item);
static void drawitem(struct Menu *menu, struct Item *item, XftColor *color);
static void drawmenu(void); static void drawmenu(void);
static void calcscreengeom(void); static void calcscreengeom(void);
static void calcmenu(struct Menu *menu); static void calcmenu(struct Menu *menu);
@@ -99,16 +102,14 @@ static Visual *visual;
static Window rootwin; static Window rootwin;
static int screen; static int screen;
static struct DC dc; static struct DC dc;
static struct ScreenGeometry screengeom;


/* menu variables */ /* menu variables */
static struct Menu *rootmenu = NULL; static struct Menu *rootmenu = NULL;
static struct Menu *currmenu = NULL; static struct Menu *currmenu = NULL;
static char **menutitle; static char **menutitle;
static int menutitlecount; static int menutitlecount;

static struct MenuGeometry geom;
/* geometry variables */
static struct Geometry geom;
static struct ScreenGeometry screengeom;


#include "config.h" #include "config.h"


@@ -154,10 +155,6 @@ main(int argc, char *argv[])
grabpointer(); grabpointer();
grabkeyboard(); grabkeyboard();


/* map root menu */
setcurrmenu(rootmenu);
XMapWindow(dpy, rootmenu->win);

/* run event loop */ /* run event loop */
run(); run();


@@ -171,44 +168,44 @@ getresources(void)
{ {
char *xrm; char *xrm;
long n; long n;
char *type;
XrmDatabase xdb;
XrmValue xval;


XrmInitialize(); XrmInitialize();
if ((xrm = XResourceManagerString(dpy))) { if ((xrm = XResourceManagerString(dpy)) == NULL)
char *type; return;
XrmDatabase xdb; xdb = XrmGetStringDatabase(xrm);
XrmValue xval; if (XrmGetResource(xdb, "xmenu.borderWidth", "*", &type, &xval) == True)

if ((n = strtol(xval.addr, NULL, 10)) > 0)
xdb = XrmGetStringDatabase(xrm); border_pixels = n;

if (XrmGetResource(xdb, "xmenu.separatorWidth", "*", &type, &xval) == True)
if (XrmGetResource(xdb, "xmenu.menuborder", "*", &type, &xval) == True) if ((n = strtol(xval.addr, NULL, 10)) > 0)
if ((n = strtol(xval.addr, NULL, 10)) > 0) separator_pixels = n;
menuborder = n; if (XrmGetResource(xdb, "xmenu.padding", "*", &type, &xval) == True)
if (XrmGetResource(xdb, "xmenu.separatorsize", "*", &type, &xval) == True) if ((n = strtol(xval.addr, NULL, 10)) > 0)
if ((n = strtol(xval.addr, NULL, 10)) > 0) padding_pixels = n;
separatorsize = n; if (XrmGetResource(xdb, "xmenu.width", "*", &type, &xval) == True)
if (XrmGetResource(xdb, "xmenu.itemborder", "*", &type, &xval) == True) if ((n = strtol(xval.addr, NULL, 10)) > 0)
if ((n = strtol(xval.addr, NULL, 10)) > 0) width_pixels = n;
itemborder = n; if (XrmGetResource(xdb, "xmenu.background", "*", &type, &xval) == True)
if (XrmGetResource(xdb, "xmenu.width", "*", &type, &xval) == True) background_color = strdup(xval.addr);
if ((n = strtol(xval.addr, NULL, 10)) > 0) if (XrmGetResource(xdb, "xmenu.foreground", "*", &type, &xval) == True)
width = n; foreground_color = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.background", "*", &type, &xval) == True) if (XrmGetResource(xdb, "xmenu.selbackground", "*", &type, &xval) == True)
background = strdup(xval.addr); selbackground_color = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.foreground", "*", &type, &xval) == True) if (XrmGetResource(xdb, "xmenu.selforeground", "*", &type, &xval) == True)
foreground = strdup(xval.addr); selforeground_color = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.selbackground", "*", &type, &xval) == True) if (XrmGetResource(xdb, "xmenu.separator", "*", &type, &xval) == True)
selbackground = strdup(xval.addr); separator_color = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.selforeground", "*", &type, &xval) == True) if (XrmGetResource(xdb, "xmenu.border", "*", &type, &xval) == True)
selforeground = strdup(xval.addr); border_color = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.separator", "*", &type, &xval) == True) if (XrmGetResource(xdb, "xmenu.font", "*", &type, &xval) == True)
separator = strdup(xval.addr); font = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.border", "*", &type, &xval) == True) XrmDestroyDatabase(xdb);
border = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.font", "*", &type, &xval) == True)
font = strdup(xval.addr);

XrmDestroyDatabase(xdb);
}
} }


/* get color from color string */ /* get color from color string */
@@ -224,18 +221,18 @@ static void
setupdc(void) setupdc(void)
{ {
/* get color pixels */ /* get color pixels */
getcolor(background, &dc.normal[ColorBG]); getcolor(background_color, &dc.normal[ColorBG]);
getcolor(foreground, &dc.normal[ColorFG]); getcolor(foreground_color, &dc.normal[ColorFG]);
getcolor(selbackground, &dc.selected[ColorBG]); getcolor(selbackground_color, &dc.selected[ColorBG]);
getcolor(selforeground, &dc.selected[ColorFG]); getcolor(selforeground_color, &dc.selected[ColorFG]);
getcolor(separator, &dc.decoration[ColorBG]); getcolor(separator_color, &dc.separator);
getcolor(border, &dc.decoration[ColorFG]); getcolor(border_color, &dc.border);


/* try to get font */ /* try to get font */
if ((dc.font = XftFontOpenName(dpy, screen, font)) == NULL) if ((dc.font = XftFontOpenName(dpy, screen, font)) == NULL)
errx(1, "cannot load font"); errx(1, "cannot load font");


/* create GC */ /* create common GC */
dc.gc = XCreateGC(dpy, rootwin, 0, NULL); dc.gc = XCreateGC(dpy, rootwin, 0, NULL);
} }


@@ -243,11 +240,11 @@ setupdc(void)
static void static void
setupgeom(void) setupgeom(void)
{ {
geom.itemb = itemborder; geom.itemb = padding_pixels;
geom.itemh = dc.font->height + itemborder * 2; geom.itemh = dc.font->height + padding_pixels * 2;
geom.itemw = width; geom.itemw = width_pixels;
geom.border = menuborder; geom.border = border_pixels;
geom.separator = separatorsize; geom.separator = separator_pixels;
} }


/* allocate an item */ /* allocate an item */
@@ -299,13 +296,15 @@ allocmenu(struct Menu *parent, struct Item *list, unsigned level)
menu->level = level; menu->level = level;


swa.override_redirect = True; swa.override_redirect = True;
swa.background_pixel = dc.decoration[ColorBG].pixel; swa.background_pixel = dc.normal[ColorBG].pixel;
swa.border_pixel = dc.decoration[ColorFG].pixel; swa.border_pixel = dc.border.pixel;
swa.save_under = True; /* pop-up windows should save_under*/
swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask
| PointerMotionMask | LeaveWindowMask; | PointerMotionMask | LeaveWindowMask;
menu->win = XCreateWindow(dpy, rootwin, 0, 0, geom.itemw, geom.itemh, geom.border, menu->win = XCreateWindow(dpy, rootwin, 0, 0, geom.itemw, geom.itemh, geom.border,
CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWEventMask, CWOverrideRedirect | CWBackPixel |
CWBorderPixel | CWEventMask | CWSaveUnder,
&swa); &swa);


return menu; return menu;
@@ -573,6 +572,7 @@ setcurrmenu(struct Menu *currmenu_new)
/* if there was no currmenu, skip calculations */ /* if there was no currmenu, skip calculations */
if (currmenu == NULL) { if (currmenu == NULL) {
currmenu = currmenu_new; currmenu = currmenu_new;
XMapWindow(dpy, currmenu->win);
return; return;
} }


@@ -607,9 +607,49 @@ setcurrmenu(struct Menu *currmenu_new)
item = NULL; item = NULL;
for (menu = currmenu; menu != lcamenu; menu = menu->parent) { for (menu = currmenu; menu != lcamenu; menu = menu->parent) {
XMapWindow(dpy, menu->win); XMapWindow(dpy, menu->win);
if (item != NULL) }
menu->selected = item; }
item = menu->caller; /* draw separator item */
static void
drawseparator(struct Menu *menu, struct Item *item)
{
int linex, liney, linew;

linex = dc.font->height;
liney = item->y + item->h/2;
linew = menu->w - dc.font->height;

XSetForeground(dpy, dc.gc, dc.separator.pixel);
XDrawLine(dpy, menu->pixmap, dc.gc, linex, liney, linew, liney);
}

/* draw regular item */
static void
drawitem(struct Menu *menu, struct Item *item, XftColor *color)
{
int x, y;

x = 0 + dc.font->height;
y = item->y + dc.font->height + geom.itemb / 2;
XSetForeground(dpy, dc.gc, color[ColorFG].pixel);
XftDrawStringUtf8(menu->draw, &color[ColorFG], dc.font,
x, y, item->label, item->labellen);

/* draw triangle, if item contains a submenu */
if (item->submenu != NULL) {
x = menu->w - dc.font->height + geom.itemb - 1;
y = item->y + geom.itemh/2 - triangle_height/2 - 1;

XPoint triangle[] = {
{x, y},
{x + triangle_width, y + triangle_height/2},
{x, y + triangle_height},
{x, y}
};

XFillPolygon(dpy, menu->pixmap, dc.gc, triangle, LEN(triangle),
Convex, CoordModeOrigin);
} }
} }


@@ -623,52 +663,26 @@ drawmenu(void)
for (menu = currmenu; menu != NULL; menu = menu->parent) { for (menu = currmenu; menu != NULL; menu = menu->parent) {
for (item = menu->list; item != NULL; item = item->next) { for (item = menu->list; item != NULL; item = item->next) {
XftColor *color; XftColor *color;
int labelx, labely;


/* determine item color */ /* determine item color */
if (item == menu->selected) if (item == menu->selected && item->label != NULL)
color = dc.selected; color = dc.selected;
else else
color = dc.normal; color = dc.normal;


/* continue if item is a separator */
if (item->label == NULL)
continue;

/* draw item box */ /* draw item box */
XSetForeground(dpy, dc.gc, color[ColorBG].pixel); XSetForeground(dpy, dc.gc, color[ColorBG].pixel);
XDrawRectangle(dpy, menu->pixmap, dc.gc, 0, item->y,
menu->w, item->h);
XFillRectangle(dpy, menu->pixmap, dc.gc, 0, item->y, XFillRectangle(dpy, menu->pixmap, dc.gc, 0, item->y,
menu->w, item->h); menu->w, item->h);


/* draw item label */ if (item->label == NULL) /* item is a separator */
labelx = 0 + dc.font->height; drawseparator(menu, item);
labely = item->y + dc.font->height + geom.itemb / 2; else /* item is a regular item */
XSetForeground(dpy, dc.gc, color[ColorFG].pixel); drawitem(menu, item, color);
XftDrawStringUtf8(menu->draw, &color[ColorFG], dc.font,
labelx, labely, item->label,
item->labellen);

/* draw triangle, if item contains a submenu */
if (item->submenu != NULL) {
int trianglex = menu->w - dc.font->height + geom.itemb - 1;
int triangley = item->y + (3 * item->h)/8 -1;

XPoint triangle[] = {
{trianglex, triangley},
{trianglex + item->h/8 + 1, item->y + item->h/2},
{trianglex, triangley + item->h/4 + 2},
{trianglex, triangley}
};

XFillPolygon(dpy, menu->pixmap, dc.gc, triangle, LEN(triangle),
Convex, CoordModeOrigin);
}

XCopyArea(dpy, menu->pixmap, menu->win, dc.gc, 0, item->y,
menu->w, item->h, 0, item->y);
} }

XCopyArea(dpy, menu->pixmap, menu->win, dc.gc, 0, 0,
menu->w, menu->h, 0, 0);
} }
} }


@@ -723,6 +737,8 @@ run(void)
KeySym ksym; KeySym ksym;
XEvent ev; XEvent ev;


setcurrmenu(rootmenu);

while (!XNextEvent(dpy, &ev)) { while (!XNextEvent(dpy, &ev)) {
switch(ev.type) { switch(ev.type) {
case Expose: case Expose:
@@ -731,38 +747,34 @@ run(void)
break; break;
case MotionNotify: case MotionNotify:
getmenuitem(ev.xbutton.window, ev.xbutton.y, &menu, &item); getmenuitem(ev.xbutton.window, ev.xbutton.y, &menu, &item);
if (menu != NULL && item != NULL) { if (menu == NULL || item == NULL)
if (previtem != item) { break;
if (item->submenu != NULL) if (previtem != item) {
setcurrmenu(item->submenu); menu->selected = item;
else if (item->submenu != NULL)
setcurrmenu(menu); setcurrmenu(item->submenu);
previtem = item; else
drawmenu(); setcurrmenu(menu);
} else if (menu->selected != item) { previtem = item;
menu->selected = item; drawmenu();
drawmenu();
}
} }
break; break;
case ButtonRelease: case ButtonRelease:
getmenuitem(ev.xbutton.window, ev.xbutton.y, &menu, &item); getmenuitem(ev.xbutton.window, ev.xbutton.y, &menu, &item);
if (menu != NULL && item != NULL) { if (menu == NULL || item == NULL)
selectitem:
if (item->label == NULL)
break; /* ignore separators */
if (item->submenu != NULL) {
setcurrmenu(item->submenu);
} else {
printf("%s\n", item->output);
return;
}
currmenu->selected = currmenu->list;
drawmenu();
break; break;
selectitem:
if (item->label == NULL)
break; /* ignore separators */
if (item->submenu != NULL) {
setcurrmenu(item->submenu);
} else { } else {
printf("%s\n", item->output);
return; return;
} }
currmenu->selected = currmenu->list;
drawmenu();
break;
case ButtonPress: case ButtonPress:
getmenuitem(ev.xbutton.window, ev.xbutton.y, &menu, &item); getmenuitem(ev.xbutton.window, ev.xbutton.y, &menu, &item);
if (menu == NULL || item == NULL) if (menu == NULL || item == NULL)
@@ -798,6 +810,7 @@ selectitem:
drawmenu(); drawmenu();
break; break;
case LeaveNotify: case LeaveNotify:
previtem = NULL;
currmenu->selected = NULL; currmenu->selected = NULL;
drawmenu(); drawmenu();
break; break;
@@ -805,7 +818,7 @@ selectitem:
} }
} }


/* recursivelly free a pixmap */ /* recursivelly free pixmaps and destroy windows */
static void static void
freewindow(struct Menu *menu) freewindow(struct Menu *menu)
{ {
@@ -830,8 +843,8 @@ cleanup(void)
XftColorFree(dpy, visual, colormap, &dc.normal[ColorFG]); XftColorFree(dpy, visual, colormap, &dc.normal[ColorFG]);
XftColorFree(dpy, visual, colormap, &dc.selected[ColorBG]); XftColorFree(dpy, visual, colormap, &dc.selected[ColorBG]);
XftColorFree(dpy, visual, colormap, &dc.selected[ColorFG]); XftColorFree(dpy, visual, colormap, &dc.selected[ColorFG]);
XftColorFree(dpy, visual, colormap, &dc.decoration[ColorBG]); XftColorFree(dpy, visual, colormap, &dc.separator);
XftColorFree(dpy, visual, colormap, &dc.decoration[ColorFG]); XftColorFree(dpy, visual, colormap, &dc.border);


XFreeGC(dpy, dc.gc); XFreeGC(dpy, dc.gc);
XCloseDisplay(dpy); XCloseDisplay(dpy);


||||||
x
 
000:0
正在加载...
取消
保存