This commit is contained in:
commit
77e564b9de
|
@ -0,0 +1,21 @@
|
|||
MIT/X Consortium License
|
||||
|
||||
© 2020 phillbush
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,29 @@
|
|||
include config.mk
|
||||
|
||||
SRCS = ${PROG}.c
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
all: ${PROG}
|
||||
|
||||
${PROG}: ${OBJS}
|
||||
${CC} -o $@ ${OBJS} ${LDFLAGS}
|
||||
|
||||
${OBJS}: config.h ${PROG}.h
|
||||
|
||||
.c.o:
|
||||
${CC} ${CFLAGS} -c $<
|
||||
|
||||
clean:
|
||||
-rm ${OBJS} ${PROG}
|
||||
|
||||
install: all
|
||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
install -m 755 ${PROG} ${DESTDIR}${PREFIX}/bin/${PROG}
|
||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||
install -m 644 ${PROG}.1 ${DESTDIR}${MANPREFIX}/man1/${PROG}.1
|
||||
|
||||
uninstall:
|
||||
rm -f ${DESTDIR}${PREFIX}/bin/${PROG}
|
||||
rm -f ${DESTDIR}${MANPREFIX}/man1/${PROG}.1
|
||||
|
||||
.PHONY: all clean install uninstall
|
|
@ -0,0 +1,77 @@
|
|||
<p align="center">
|
||||
<img src="/demo.gif", title="demo"/>
|
||||
</p>
|
||||
|
||||
# XMenu
|
||||
|
||||
XMenu is a menu utility for X.
|
||||
XMenu receives a menu specification in stdin, shows a menu for the user
|
||||
to select one of the options, and outputs the option selected to stdout.
|
||||
XMenu can be controlled both via mouse and via keyboard.
|
||||
|
||||
In order to generate a menu of applications based on .desktop entries,
|
||||
as specified by XDG, checkout [xdg-xmenu](https://github.com/OliverLew/xdg-xmenu)
|
||||
by [OliverLew](https://github.com/OliverLew).
|
||||
|
||||
Check out my other project, [xclickroot](https://github.com/phillbush/xclickroot) for an application that can
|
||||
spawn xmenu by right clicking on the root window (i.e. on the desktop).
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
XMenu comes with the following features:
|
||||
|
||||
* XMenu reads something in and prints something out, the UNIX way.
|
||||
* Submenus (some menu entries can spawn another menu).
|
||||
* Separators (menu entries can be separated by a line).
|
||||
* Icons (menu entries can be preceded by an icon image).
|
||||
* X resources support (you don't need to recompile xmenu for configuring it).
|
||||
|
||||
|
||||
## Files
|
||||
|
||||
The files are:
|
||||
|
||||
* `./README`: This file.
|
||||
* `./Makefile`: The makefile.
|
||||
* `./config.h`: The hardcoded default configuration for XMenu.
|
||||
* `./config.mk`: The setup for the makefile.
|
||||
* `./demo.gif`: A gif demonstrating how XMenu works.
|
||||
* `./xmenu.1`: The manual file (man page) for XMenu.
|
||||
* `./xmenu.c`: The source code of XMenu.
|
||||
* `./xmenu.sh`: A sample script illustrating how to use XMenu.
|
||||
* `./icons/`: Icons for the sample script
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
First, edit `./config.mk` to match your local setup.
|
||||
|
||||
In order to build XMenu you need the `Imlib2`, `Xlib` and `Xft` header files.
|
||||
The default configuration for XMenu is specified in the file `config.h`,
|
||||
you can edit it, but most configuration can be changed at runtime via
|
||||
X resources. Enter the following command to build XMenu. This command
|
||||
creates the binary file `./xmenu`.
|
||||
|
||||
make
|
||||
|
||||
By default, XMenu is installed into the `/usr/local` prefix. Enter the
|
||||
following command to install XMenu (if necessary as root). This command
|
||||
installs the binary file `./xmenu` into the `${PREFIX}/bin/` directory, and
|
||||
the manual file `./xmenu.1` into `${MANPREFIX}/man1/` directory.
|
||||
|
||||
make install
|
||||
|
||||
|
||||
## Running XMenu
|
||||
|
||||
XMenu receives as input a menu specification where each line is a menu
|
||||
entry. Each line can be indented with tabs to represent nested menus.
|
||||
Each line is made out of a label and a command separated by any number
|
||||
of tabs. Lines without labels are menu separators.
|
||||
|
||||
See the script `./xmenu.sh` for an example of how to use XMenu to draw a
|
||||
simple menu with submenus and separators. The file `./demo.gif` shows how
|
||||
the menu generated by that script looks like.
|
||||
|
||||
Read the [manual](https://github.com/phillbush/xmenu/wiki) for more information on running XMenu.
|
|
@ -0,0 +1,57 @@
|
|||
Static ; struct Config config = {
|
||||
/* font, separate different fonts with comma */
|
||||
.font ="FiraCode Nerd Font:style=Light:size=8:antialias=true:autohint=true","Chiron Sans HK Light:style=Light:size=8","Noto Color Emoji:style=Regular",
|
||||
|
||||
/* colors */
|
||||
.background_color = "#282a36",
|
||||
.foreground_color = "#f8f8f2",
|
||||
.selbackground_color = "#ff5555",
|
||||
.selforeground_color = "#282a36",
|
||||
.separator_color = "#bbbbbb",
|
||||
.border_color = "#bbbbbb",
|
||||
/* sizes in pixels */
|
||||
.width_pixels = 15, /* minimum width of a menu */
|
||||
.height_pixels = 25, /* height of a single menu item */
|
||||
.border_pixels = 1, /* menu border */
|
||||
.separator_pixels = 3, /* space around separator */
|
||||
.gap_pixels = 5, /* gap between menus */
|
||||
|
||||
/*
|
||||
* The variables below cannot be set by X resources.
|
||||
* Their values must be less than .height_pixels.
|
||||
*/
|
||||
|
||||
/* geometry of the right-pointing isoceles triangle for submenus */
|
||||
.triangle_width = 3,
|
||||
.triangle_height = 7,
|
||||
|
||||
/* the icon size is equal to .height_pixels - .iconpadding * 2 */
|
||||
.iconpadding = 2,
|
||||
|
||||
/* area around the icon, the triangle and the separator */
|
||||
.horzpadding = 8,
|
||||
};
|
||||
|
||||
/*
|
||||
* KEYBINDINGS
|
||||
*
|
||||
* Look at your /usr/include/X11/keysymdef.h (or the equivalent file
|
||||
* in your system) for a list of key symbol constants, and change the
|
||||
* macros below accordingly. All key symbol constants begin with the
|
||||
* prefix XK_.
|
||||
*
|
||||
* For example, to use vim-like key bindings, set KEYSYMLEFT to XK_h,
|
||||
* KEYSYMDOWN to XK_j, KEYSYMUP to XK_k, etc.
|
||||
*
|
||||
* Note that the regular keys like ArrowUp, ArrowDown, Tab, Home, etc
|
||||
* will ALWAYS work, so you do not need to set them.
|
||||
*
|
||||
* If you do not want to set a key binding, keep it with the value of
|
||||
* XK_VoidSymbol
|
||||
*/
|
||||
#define KSYMFIRST XK_VoidSymbol /* select first item */
|
||||
#define KSYMLAST XK_VoidSymbol /* select last item */
|
||||
#define KSYMUP XK_VoidSymbol /* select previous item */
|
||||
#define KSYMDOWN XK_VoidSymbol /* select next item */
|
||||
#define KSYMLEFT XK_VoidSymbol /* close current menu */
|
||||
#define KSYMRIGHT XK_VoidSymbol /* enter selected item */
|
|
@ -0,0 +1,28 @@
|
|||
# program name
|
||||
PROG = xmenu
|
||||
|
||||
# paths
|
||||
PREFIX = /usr/local
|
||||
MANPREFIX = ${PREFIX}/share/man
|
||||
|
||||
LOCALINC = /usr/local/include
|
||||
LOCALLIB = /usr/local/lib
|
||||
|
||||
X11INC = /usr/X11R6/include
|
||||
X11LIB = /usr/X11R6/lib
|
||||
|
||||
FREETYPEINC = /usr/include/freetype2
|
||||
# OpenBSD (uncomment)
|
||||
#FREETYPEINC = ${X11INC}/freetype2
|
||||
|
||||
# includes and libs
|
||||
INCS = -I${LOCALINC} -I${X11INC} -I${FREETYPEINC}
|
||||
LIBS = -L${LOCALLIB} -L${X11LIB} -lfontconfig -lXft -lX11 -lXinerama -lImlib2
|
||||
|
||||
# flags
|
||||
CPPFLAGS =
|
||||
CFLAGS = -Wall -Wextra ${INCS} ${CPPFLAGS}
|
||||
LDFLAGS = ${LIBS}
|
||||
|
||||
# compiler and linker
|
||||
CC = cc
|
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
|
@ -0,0 +1,200 @@
|
|||
.TH XMENU 1
|
||||
.SH NAME
|
||||
xmenu \- menu utility for X
|
||||
.SH SYNOPSIS
|
||||
.B xmenu
|
||||
.RB [ \-irw ]
|
||||
.RB [ -p
|
||||
.IR position ]
|
||||
.RI [ title ]
|
||||
.SH DESCRIPTION
|
||||
.B xmenu
|
||||
is a menu for X,
|
||||
it reads a list of newline-separated items from stdin,
|
||||
shows a menu for the user to select one of the items,
|
||||
and outputs the item selected to stdout.
|
||||
.PP
|
||||
The options are as follows:
|
||||
.TP
|
||||
.B -i
|
||||
Disable icons.
|
||||
This makes xmenu loading faster when not using icons.
|
||||
.TP
|
||||
.BI -p " position"
|
||||
Set the position to spawn xmenu.
|
||||
Without this option, xmenu spawns next to the cursor.
|
||||
.I position
|
||||
is a string of the form
|
||||
.BR INTxINT[:MONITOR] ,
|
||||
where the first INT is the x position and the second INT is the y position.
|
||||
The monitor part between brackets is optional.
|
||||
.B MONITOR
|
||||
can be a number from 0 to the number of monitors minus 1;
|
||||
or it can be a string like
|
||||
.B current
|
||||
or
|
||||
.BR cursor .
|
||||
If present, the monitor specifies that the position is relative to the upper left corner
|
||||
of that monitor.
|
||||
If
|
||||
.B monitor
|
||||
is
|
||||
.B current
|
||||
or
|
||||
.BR cursor ,
|
||||
the monitor to be used is that where the cursor is in.
|
||||
For example,
|
||||
.B -p 0x0:cursor
|
||||
specifies that
|
||||
.B xmenu
|
||||
must spawn at the position 0x0 of the monitor where the cursor is in.
|
||||
And
|
||||
.B -p 100x500:0
|
||||
specifies that
|
||||
.B xmenu
|
||||
must spawn at the position 100x500 of the monitor 0.
|
||||
.TP
|
||||
.B -r
|
||||
If this option is set, the right mouse button is disabled;
|
||||
so pressing it will not trigger any menu item.
|
||||
.TP
|
||||
.B -w
|
||||
Asks the window manager to draw a border around the menus.
|
||||
This option may be buggy in some window managers,
|
||||
specially tiled ones that do not respect window hints.
|
||||
.PP
|
||||
Each item read from stdin has the following format:
|
||||
.IP
|
||||
.EX
|
||||
ITEM := [TABS] [[IMAGE TABS] LABEL [TABS OUTPUT]] NEWLINE
|
||||
.EE
|
||||
.PP
|
||||
That means that each item is composed by
|
||||
tabs, followed by an optional image specification, followed by tabs
|
||||
followed by a label, followed by more tabs, followed by an output,
|
||||
and ended by a newline. Brackets group optional elements.
|
||||
.IP
|
||||
The initial tabs indicate the menu hierarchy:
|
||||
items indented with a tab is shown in a submenu of the preceding item not indented.
|
||||
An item without initial tabs is a top-level item.
|
||||
.IP
|
||||
The image is a string of the form "IMG:/path/to/image.png".
|
||||
It specifies a image to be shown as icon at the left of the entry.
|
||||
.IP
|
||||
The label is the string that will be shown as a item in the menu.
|
||||
An item without label is considered a separator and is drawn as a thin line in the menu
|
||||
separating the item above from the item below.
|
||||
.IP
|
||||
The output is the string that will be output after selecting the item.
|
||||
If an item does not have an output, its label is used as its output.
|
||||
.IP
|
||||
The newline terminates the item specification.
|
||||
.PP
|
||||
If the argument
|
||||
.I title
|
||||
is given, the title of the menu window is set to it.
|
||||
.SH USAGE
|
||||
.B xmenu
|
||||
is controlled by the mouse,
|
||||
but can also be controlled by the keyboard.
|
||||
Items can be selected using the arrow keys,
|
||||
Tab (with and without Shift),
|
||||
Home, End,
|
||||
Enter and Esc, and 1-9 keys.
|
||||
.TP
|
||||
.BR Home
|
||||
Select the first item in the menu.
|
||||
.TP
|
||||
.BR End
|
||||
Select the last item in the menu.
|
||||
.TP
|
||||
.BR Down ", " Tab
|
||||
Cycle through the items in the regular direction.
|
||||
.TP
|
||||
.BR Up ", " Shift-Tab
|
||||
Cycle through the items in the reverse direction.
|
||||
.TP
|
||||
.BR Right ", " Enter
|
||||
Select the highlighted item.
|
||||
.TP
|
||||
.B Left
|
||||
Go to the menu above.
|
||||
.TP
|
||||
.B Esc
|
||||
Go to the menu above or exit xmenu.
|
||||
.PP
|
||||
Additional key bindings can be set at compile time by changing the
|
||||
.B config.h
|
||||
file.
|
||||
.SH RESOURCES
|
||||
.B
|
||||
xmenu
|
||||
understands the following X resources.
|
||||
.TP
|
||||
.B xmenu.font
|
||||
The font in which the labels should be drawn.
|
||||
Multiple fonts can be added as fallback fonts;
|
||||
they must be separated by a comma.
|
||||
.TP
|
||||
.B xmenu.background
|
||||
The background color of non-selected items in the menu.
|
||||
.TP
|
||||
.B xmenu.foreground
|
||||
The color of the label text of non-selected items in the menu.
|
||||
.TP
|
||||
.B xmenu.selbackground
|
||||
The background color of selected items in the menu.
|
||||
.TP
|
||||
.B xmenu.selforeground
|
||||
The color of the label text of selected items in the menu.
|
||||
.TP
|
||||
.B xmenu.border
|
||||
The color of the border around the menu.
|
||||
.TP
|
||||
.B xmenu.separator
|
||||
The color of the separator between items in the menu.
|
||||
.TP
|
||||
.B xmenu.gap
|
||||
The gap, in pixels, between the menus.
|
||||
.TP
|
||||
.B xmenu.width
|
||||
The minimum width, in pixels, of the items in the menu.
|
||||
.TP
|
||||
.B xmenu.height
|
||||
The size in pixels of the height of a single menu item.
|
||||
.TP
|
||||
.B xmenu.borderWidth
|
||||
The size in pixels of the border around the menu.
|
||||
.TP
|
||||
.B xmenu.separatorWidth
|
||||
The size in pixels of the item separator.
|
||||
|
||||
.SH EXAMPLES
|
||||
The following script illustrates the use of
|
||||
.BR xmenu .
|
||||
The output is redirected to
|
||||
.IR sh (1),
|
||||
creating a command to be run by the shell.
|
||||
.IP
|
||||
.EX
|
||||
#!/bin/sh
|
||||
|
||||
cat <<EOF | xmenu | sh &
|
||||
Applications
|
||||
IMG:./web.png Web Browser firefox
|
||||
IMG:./gimp.png Image editor gimp
|
||||
Terminal (xterm) xterm
|
||||
Terminal (urxvt) urxvt
|
||||
Terminal (st) st
|
||||
|
||||
Shutdown poweroff
|
||||
Reboot reboot
|
||||
EOF
|
||||
.EE
|
||||
.PP
|
||||
For example, by selecting \(lqApplications\(rq, a new menu will appear.
|
||||
Selecting \(lqWeb Browser\(rq in the new menu opens firefox.
|
||||
.SH SEE ALSO
|
||||
.IR dmenu (1),
|
||||
.IR 9menu (1),
|
||||
.IR thingmenu (1)
|
|
@ -0,0 +1,90 @@
|
|||
#define PROGNAME "xmenu"
|
||||
|
||||
/* enum for keyboard menu navigation */
|
||||
enum { ITEMPREV, ITEMNEXT, ITEMFIRST, ITEMLAST };
|
||||
|
||||
/* macros */
|
||||
#define LEN(x) (sizeof (x) / sizeof (x[0]))
|
||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||||
#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b))
|
||||
|
||||
/* color enum */
|
||||
enum {ColorFG, ColorBG, ColorLast};
|
||||
|
||||
/* EWMH atoms */
|
||||
enum {NetWMName, NetWMWindowType, NetWMWindowTypePopupMenu, NetLast};
|
||||
|
||||
/* configuration structure */
|
||||
struct Config {
|
||||
/* the values below are set by config.h */
|
||||
const char *font;
|
||||
const char *background_color;
|
||||
const char *foreground_color;
|
||||
const char *selbackground_color;
|
||||
const char *selforeground_color;
|
||||
const char *separator_color;
|
||||
const char *border_color;
|
||||
int width_pixels;
|
||||
int height_pixels;
|
||||
int border_pixels;
|
||||
int separator_pixels;
|
||||
int gap_pixels;
|
||||
int triangle_width;
|
||||
int triangle_height;
|
||||
int iconpadding;
|
||||
int horzpadding;
|
||||
|
||||
/* the values below are set by options */
|
||||
int monitor;
|
||||
int posx, posy; /* rootmenu position */
|
||||
|
||||
/* the value below is computed by xmenu */
|
||||
int iconsize;
|
||||
};
|
||||
|
||||
/* draw context structure */
|
||||
struct DC {
|
||||
XftColor normal[ColorLast];
|
||||
XftColor selected[ColorLast];
|
||||
XftColor border;
|
||||
XftColor separator;
|
||||
|
||||
GC gc;
|
||||
|
||||
FcPattern *pattern;
|
||||
XftFont **fonts;
|
||||
size_t nfonts;
|
||||
};
|
||||
|
||||
/* menu item structure */
|
||||
struct Item {
|
||||
char *label; /* string to be drawed on menu */
|
||||
char *output; /* string to be outputed when item is clicked */
|
||||
char *file; /* filename of the icon */
|
||||
int y; /* item y position relative to menu */
|
||||
int h; /* item height */
|
||||
struct Item *prev; /* previous item */
|
||||
struct Item *next; /* next item */
|
||||
struct Menu *submenu; /* submenu spawned by clicking on item */
|
||||
Drawable sel, unsel; /* pixmap for selected and unselected item */
|
||||
Imlib_Image icon;
|
||||
};
|
||||
|
||||
/* monitor geometry structure */
|
||||
struct Monitor {
|
||||
int x, y, w, h; /* monitor geometry */
|
||||
};
|
||||
|
||||
/* menu structure */
|
||||
struct Menu {
|
||||
struct Menu *parent; /* parent menu */
|
||||
struct Item *caller; /* item that spawned the menu */
|
||||
struct Item *list; /* list of items contained by the menu */
|
||||
struct Item *selected; /* item currently selected in the menu */
|
||||
int x, y, w, h; /* menu geometry */
|
||||
int hasicon; /* whether the menu has item with icons */
|
||||
int drawn; /* whether the menu was already drawn */
|
||||
unsigned level; /* menu level relative to root */
|
||||
Window win; /* menu window to map on the screen */
|
||||
};
|
Loading…
Reference in New Issue