Some new packages. Reworked mbase a bit.
This commit is contained in:
parent
e44cdda61c
commit
1adcf76846
|
@ -1 +0,0 @@
|
||||||
../community-mod/rolling/hummingbird-git
|
|
|
@ -0,0 +1 @@
|
||||||
|
../community-mod/stable/picom
|
|
@ -1 +0,0 @@
|
||||||
../community-mod/rolling/picom-git
|
|
|
@ -0,0 +1 @@
|
||||||
|
../community-mod/stable/shadow
|
|
@ -1 +0,0 @@
|
||||||
../community-mod/rolling/shadow-git
|
|
|
@ -0,0 +1 @@
|
||||||
|
../community-mod/stable/shellcheck-bin
|
|
@ -1 +0,0 @@
|
||||||
../community-mod/rolling/shellcheck-bin-git
|
|
|
@ -0,0 +1 @@
|
||||||
|
../community-mod/stable/shinit
|
|
@ -1 +0,0 @@
|
||||||
../community-mod/stable/slock
|
|
|
@ -0,0 +1 @@
|
||||||
|
../ports/slock-mod
|
|
@ -1 +0,0 @@
|
||||||
../community-mod/rolling/ssu-git
|
|
|
@ -0,0 +1 @@
|
||||||
|
../community-mod/stable/sxhkd
|
|
@ -1 +0,0 @@
|
||||||
../community-mod/rolling/sxhkd-git
|
|
|
@ -0,0 +1 @@
|
||||||
|
../community-mod/stable/sxiv
|
|
@ -1 +0,0 @@
|
||||||
../community-mod/rolling/sxiv-git
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
cmake -B build \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DBACKTRACE=OFF \
|
||||||
|
-DUSE_HOME_DIR=1 \
|
||||||
|
-DLOCALIZE=OFF \
|
||||||
|
-DSOUND=ON \
|
||||||
|
-DTILES=ON
|
||||||
|
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
install -Dm755 build/src/cataclysm-tiles "$1/usr/share/cataclysm-dda/cataclysm-tiles"
|
||||||
|
install -Dm755 cataclysm-launcher "$1/usr/share/cataclysm-dda/cataclysm-launcher"
|
||||||
|
cp -r data "$1/usr/share/cataclysm-dda"
|
||||||
|
cp -r gfx "$1/usr/share/cataclysm-dda"
|
||||||
|
install -d "$1/usr/bin"
|
||||||
|
ln -s /usr/share/cataclysm-dda/cataclysm-launcher "$1/usr/bin/cataclysm-dda"
|
|
@ -0,0 +1,10 @@
|
||||||
|
bzip2
|
||||||
|
cmake make
|
||||||
|
freetype-harfbuzz
|
||||||
|
#libexecinfo
|
||||||
|
libpng
|
||||||
|
sdl2
|
||||||
|
sdl2-image
|
||||||
|
sdl2-mixer
|
||||||
|
sdl2-ttf
|
||||||
|
zlib
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
||||||
|
git+https://github.com/CleverRaven/Cataclysm-DDA
|
|
@ -0,0 +1 @@
|
||||||
|
git 1
|
|
@ -1,7 +0,0 @@
|
||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
./configure
|
|
||||||
|
|
||||||
install -Dm644 ctags.1 "$1/usr/share/man/man1/ctags.1"
|
|
||||||
install -Dm644 readtags.h "$1/usr/include/readtags.h"
|
|
||||||
install -Dm755 ctags "$1/usr/bin/ctags"
|
|
|
@ -1,11 +0,0 @@
|
||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
./configure \
|
|
||||||
--prefix=/usr \
|
|
||||||
--enable-single-host
|
|
||||||
|
|
||||||
make
|
|
||||||
#make modules
|
|
||||||
make check
|
|
||||||
make doc
|
|
||||||
make DESTDIR="$1" install
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
make
|
||||||
|
make PREFIX=/usr DESTDIR="$1" install
|
|
@ -0,0 +1,5 @@
|
||||||
|
curl
|
||||||
|
libseccomp
|
||||||
|
libxml2
|
||||||
|
xz
|
||||||
|
zlib
|
|
@ -0,0 +1,17 @@
|
||||||
|
/var/db/kiss/installed/rdrview/version
|
||||||
|
/var/db/kiss/installed/rdrview/sources
|
||||||
|
/var/db/kiss/installed/rdrview/manifest
|
||||||
|
/var/db/kiss/installed/rdrview/depends
|
||||||
|
/var/db/kiss/installed/rdrview/build
|
||||||
|
/var/db/kiss/installed/rdrview/
|
||||||
|
/var/db/kiss/installed/
|
||||||
|
/var/db/kiss/
|
||||||
|
/var/db/
|
||||||
|
/var/
|
||||||
|
/usr/share/man/man1/rdrview.1
|
||||||
|
/usr/share/man/man1/
|
||||||
|
/usr/share/man/
|
||||||
|
/usr/share/
|
||||||
|
/usr/bin/rdrview
|
||||||
|
/usr/bin/
|
||||||
|
/usr/
|
|
@ -0,0 +1 @@
|
||||||
|
git+https://github.com/eafer/rdrview
|
|
@ -0,0 +1 @@
|
||||||
|
git 1
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
for file in dpms.diff ctrlclear.diff
|
||||||
|
do
|
||||||
|
patch < $file
|
||||||
|
done
|
||||||
|
|
||||||
|
sed 's/005577/EAEAEA/' config.def.h > cfg
|
||||||
|
sed 's/clear = 0/clear = 1/' cfg > cfg2
|
||||||
|
mv cfg2 config.def.h
|
||||||
|
|
||||||
|
make
|
||||||
|
make DESTDIR="$1" PREFIX=/usr install
|
|
@ -0,0 +1,3 @@
|
||||||
|
b53849dbc60109a987d7a49b8da197305c29307fd74c12dc18af0d3044392e6a
|
||||||
|
12af3ae1522d2423fb55d462896e1392797fd4073006a30a99d1b679535dbadf
|
||||||
|
0e3182fa18c4e98ea108a035bd6181eaedacaf2af62133c230fb6012cbfd667d
|
|
@ -0,0 +1,3 @@
|
||||||
|
libX11
|
||||||
|
libXext
|
||||||
|
libXrandr
|
|
@ -0,0 +1,27 @@
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 6fba2b6..933152b 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = {
|
||||||
|
/* time in seconds before the monitor shuts down */
|
||||||
|
static const int monitortime = 5;
|
||||||
|
+
|
||||||
|
+/* allow control key to trigger fail on clear */
|
||||||
|
+static const int controlkeyclear = 0;
|
||||||
|
|
||||||
|
diff --git a/slock.c b/slock.c
|
||||||
|
index 4d7f06f..15552ef 100644
|
||||||
|
--- a/slock.c
|
||||||
|
+++ b/slock.c
|
||||||
|
@@ -180,8 +180,9 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
|
||||||
|
passwd[len--] = '\0';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
- if (num && !iscntrl((int)buf[0]) &&
|
||||||
|
- (len + num < sizeof(passwd))) {
|
||||||
|
+ if (controlkeyclear && iscntrl((int)buf[0]))
|
||||||
|
+ continue;
|
||||||
|
+ if (num && (len + num < sizeof(passwd))) {
|
||||||
|
memcpy(passwd + len, buf, num);
|
||||||
|
len += num;
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 9855e21..d01bd38 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = {
|
||||||
|
|
||||||
|
/* treat a cleared input like a wrong password (color) */
|
||||||
|
static const int failonclear = 1;
|
||||||
|
+
|
||||||
|
+/* time in seconds before the monitor shuts down */
|
||||||
|
+static const int monitortime = 5;
|
||||||
|
diff --git a/slock.c b/slock.c
|
||||||
|
index d2f0886..f65a43b 100644
|
||||||
|
--- a/slock.c
|
||||||
|
+++ b/slock.c
|
||||||
|
@@ -15,6 +15,7 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
+#include <X11/extensions/dpms.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
@@ -306,6 +307,7 @@ main(int argc, char **argv) {
|
||||||
|
const char *hash;
|
||||||
|
Display *dpy;
|
||||||
|
int s, nlocks, nscreens;
|
||||||
|
+ CARD16 standby, suspend, off;
|
||||||
|
|
||||||
|
ARGBEGIN {
|
||||||
|
case 'v':
|
||||||
|
@@ -366,6 +368,20 @@ main(int argc, char **argv) {
|
||||||
|
if (nlocks != nscreens)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
+ /* DPMS magic to disable the monitor */
|
||||||
|
+ if (!DPMSCapable(dpy))
|
||||||
|
+ die("slock: DPMSCapable failed\n");
|
||||||
|
+ if (!DPMSEnable(dpy))
|
||||||
|
+ die("slock: DPMSEnable failed\n");
|
||||||
|
+ if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off))
|
||||||
|
+ die("slock: DPMSGetTimeouts failed\n");
|
||||||
|
+ if (!standby || !suspend || !off)
|
||||||
|
+ die("slock: at least one DPMS variable is zero\n");
|
||||||
|
+ if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime))
|
||||||
|
+ die("slock: DPMSSetTimeouts failed\n");
|
||||||
|
+
|
||||||
|
+ XSync(dpy, 0);
|
||||||
|
+
|
||||||
|
/* run post-lock command */
|
||||||
|
if (argc > 0) {
|
||||||
|
switch (fork()) {
|
||||||
|
@@ -383,5 +399,9 @@ main(int argc, char **argv) {
|
||||||
|
/* everything is now blank. Wait for the correct password */
|
||||||
|
readpw(dpy, &rr, locks, nscreens, hash);
|
||||||
|
|
||||||
|
+ /* reset DPMS values to inital ones */
|
||||||
|
+ DPMSSetTimeouts(dpy, standby, suspend, off);
|
||||||
|
+ XSync(dpy, 0);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
https://dl.suckless.org/tools/slock-1.4.tar.gz
|
||||||
|
patches/dpms.diff
|
||||||
|
patches/ctrlclear.diff
|
|
@ -0,0 +1 @@
|
||||||
|
1.4 1
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
./configure \
|
||||||
|
--prefix=/usr
|
||||||
|
|
||||||
|
make
|
||||||
|
install -Dm755 snarf "$1/usr/bin/snarf"
|
||||||
|
install -Dm644 snarf.1 "$1/usr/share/man/man1/snarf.1"
|
|
@ -0,0 +1 @@
|
||||||
|
d7ab0559247b618197f906657182b7d1d15b8ebc5a620d84c10a09b2a74e9e94
|
|
@ -0,0 +1 @@
|
||||||
|
http://deb.debian.org/debian/pool/main/s/snarf/snarf_7.0.orig.tar.gz
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,232 @@
|
||||||
|
.TH 9MENU 1 "Apr 16 2020"
|
||||||
|
.SH NAME
|
||||||
|
9menu \- create a menu to run commands
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B 9menu
|
||||||
|
[
|
||||||
|
.BI \-bg " background-color"
|
||||||
|
] [
|
||||||
|
.BI \-display " displayname"
|
||||||
|
] [
|
||||||
|
.BI \-file " name"
|
||||||
|
] [
|
||||||
|
.BI \-fg " foreground-color"
|
||||||
|
] [
|
||||||
|
.BI \-font " fname"
|
||||||
|
] [
|
||||||
|
.BI \-geometry " geom"
|
||||||
|
] [
|
||||||
|
.B \-iconic
|
||||||
|
] [
|
||||||
|
.BI \-label " name"
|
||||||
|
] [
|
||||||
|
.B \-path
|
||||||
|
] [
|
||||||
|
.B \-popdown
|
||||||
|
] [
|
||||||
|
.B \-popup
|
||||||
|
] [
|
||||||
|
.BI \-shell " prog"
|
||||||
|
] [
|
||||||
|
.B \-teleport
|
||||||
|
] [
|
||||||
|
.B \-version
|
||||||
|
] [
|
||||||
|
.B \-warp
|
||||||
|
]
|
||||||
|
.IR menuitem [: command ]
|
||||||
|
\&...
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.I 9menu
|
||||||
|
is a simple program that accepts a list of menu item and command
|
||||||
|
pairs on the command line.
|
||||||
|
It creates a window that consists of nothing but a menu.
|
||||||
|
When a particular item is selected, the corresponding command is executed.
|
||||||
|
.PP
|
||||||
|
Either
|
||||||
|
.B Button1
|
||||||
|
or
|
||||||
|
.B Button3
|
||||||
|
may be used to select an item.
|
||||||
|
Alternatively, the UP-ARROW and DOWN-ARROW cursor keys may be used to
|
||||||
|
highlight different items, with ENTER used to select the
|
||||||
|
highlighted item.
|
||||||
|
.PP
|
||||||
|
Menu items and commands are separated by a colon. The colon and command
|
||||||
|
are optional. If they are missing, then the menu item is assumed to be
|
||||||
|
a command that can be executed directly.
|
||||||
|
.PP
|
||||||
|
A menu item consisting of the word
|
||||||
|
.B exit
|
||||||
|
causes
|
||||||
|
.I 9menu
|
||||||
|
to exit when it is selected.
|
||||||
|
Otherwise, to stop
|
||||||
|
.I 9menu ,
|
||||||
|
delete it using the window manager.
|
||||||
|
The
|
||||||
|
.B exit
|
||||||
|
menu item can be anywhere in the list, although by convention it is last.
|
||||||
|
If a command is supplied along with the
|
||||||
|
.B exit
|
||||||
|
item, that command is executed before
|
||||||
|
.I 9menu
|
||||||
|
exits.
|
||||||
|
.PP
|
||||||
|
If a menu item's command starts with the word
|
||||||
|
.BR exec ,
|
||||||
|
.I 9menu
|
||||||
|
ceases operating after launching it.
|
||||||
|
.PP
|
||||||
|
.I 9menu
|
||||||
|
accepts the following command line options,
|
||||||
|
listed alphabetically:
|
||||||
|
.TP
|
||||||
|
.BI \-bg " background-color"
|
||||||
|
Set the background color to
|
||||||
|
.IR background-color .
|
||||||
|
By default, the background color is white.
|
||||||
|
.TP
|
||||||
|
.BI \-display " displayname"
|
||||||
|
Use the X display
|
||||||
|
.IR displayname ,
|
||||||
|
instead of the default display.
|
||||||
|
.TP
|
||||||
|
.BI \-file " filename"
|
||||||
|
Read items to display from
|
||||||
|
.IR filename ,
|
||||||
|
in addition to any other command line arguments. This is intended for use
|
||||||
|
with
|
||||||
|
.B #!
|
||||||
|
in scripts.
|
||||||
|
A
|
||||||
|
.I filename
|
||||||
|
of
|
||||||
|
.B -
|
||||||
|
causes
|
||||||
|
.I 9menu
|
||||||
|
to read items from standard input.
|
||||||
|
.TP
|
||||||
|
.BI \-fg " foreground-color"
|
||||||
|
Set the foreground color to
|
||||||
|
.IR foreground-color .
|
||||||
|
By default, the foreground color is black.
|
||||||
|
.TP
|
||||||
|
.BI \-font " fname"
|
||||||
|
Use the font
|
||||||
|
.IR fname ,
|
||||||
|
instead of one of the default fonts built into
|
||||||
|
.IR 9wm .
|
||||||
|
.TP
|
||||||
|
.BI \-geometry " geom"
|
||||||
|
Use
|
||||||
|
.I geom
|
||||||
|
(a geometry in standard X format) as the geometry of the menu.
|
||||||
|
This is most useful for specifying the initial location of the menu.
|
||||||
|
Note that
|
||||||
|
.I 9menu
|
||||||
|
overrides the size part of the geometry specification. The window is
|
||||||
|
always just large enough to hold the menu.
|
||||||
|
.TP
|
||||||
|
.B \-iconic
|
||||||
|
Start up in the iconified state.
|
||||||
|
.TP
|
||||||
|
.BI \-label " name"
|
||||||
|
Change both the window and icon labels of the window to
|
||||||
|
.IR name .
|
||||||
|
The default label is the last component of the path used to run
|
||||||
|
.IR 9menu ,
|
||||||
|
typically,
|
||||||
|
.BR 9menu .
|
||||||
|
.TP
|
||||||
|
.B \-path
|
||||||
|
Append the current directory to the command search path.
|
||||||
|
.TP
|
||||||
|
.B \-popdown
|
||||||
|
Once an item is selected, the menu window automatically iconifies itself.
|
||||||
|
.TP
|
||||||
|
.B \-popup
|
||||||
|
Act like a pop-up menu. Once a menu item is selected,
|
||||||
|
.I 9menu
|
||||||
|
exits.
|
||||||
|
This option overrides
|
||||||
|
.BR \-popdown .
|
||||||
|
.TP
|
||||||
|
.BI \-shell " prog"
|
||||||
|
Use
|
||||||
|
.I prog
|
||||||
|
as the shell to run commands, instead of
|
||||||
|
.BR /bin/sh .
|
||||||
|
A popular alternative shell is
|
||||||
|
.IR rc (1).
|
||||||
|
If the shell cannot be executed,
|
||||||
|
.I 9menu
|
||||||
|
then
|
||||||
|
.I silently
|
||||||
|
falls back to using
|
||||||
|
.BR /bin/sh .
|
||||||
|
.TP
|
||||||
|
.B \-teleport
|
||||||
|
Move the menu to where the mouse is when the menu is uniconified.
|
||||||
|
This option is particularly useful when combined with
|
||||||
|
.BR \-popdown .
|
||||||
|
.TP
|
||||||
|
.B \-version
|
||||||
|
This option prints the version of
|
||||||
|
.I 9menu
|
||||||
|
on the standard output, and then exits with an exit value of zero.
|
||||||
|
.TP
|
||||||
|
.B \-warp
|
||||||
|
Warp the mouse to the menu when the menu is uniconified.
|
||||||
|
After the selection is made, restore the mouse to where it was.
|
||||||
|
This option is particularly useful when combined with
|
||||||
|
.BR \-popdown .
|
||||||
|
.SH EXAMPLES
|
||||||
|
.ft B
|
||||||
|
.nf
|
||||||
|
9menu \-label Remotes xterm 'acme:ssh acme xterm' 'herman:ssh herman 9term' &
|
||||||
|
.sp
|
||||||
|
9menu \-label 'X progs' gv xdvi xeyes xneko exit &
|
||||||
|
.ft
|
||||||
|
.fi
|
||||||
|
.SH SEE ALSO
|
||||||
|
.IR sam (1),
|
||||||
|
.IR 9term (1),
|
||||||
|
.IR 9wm (1),
|
||||||
|
.IR rc (1).
|
||||||
|
.PP
|
||||||
|
.IR "The Plan 9 Programmer's Manual" .
|
||||||
|
.SH VERSION
|
||||||
|
This man page documents
|
||||||
|
.I 9menu
|
||||||
|
version 1.10.
|
||||||
|
.PP
|
||||||
|
Source code is available from
|
||||||
|
.BR ftp://ftp.freefriends.org/arnold/Source/9menu.shar.gz .
|
||||||
|
.PP
|
||||||
|
The code with full history is also available via Git from
|
||||||
|
.BR http://github.com/arnoldrobbins/9menu .
|
||||||
|
.SH BUGS
|
||||||
|
This program has grown to have too many options.
|
||||||
|
.SH AUTHORS
|
||||||
|
The initial idea for this program was by Arnold Robbins, after having
|
||||||
|
worked with John Mackin's GWM Blit emulation.
|
||||||
|
Matty Farrow wrote a version using libXg, from which some ideas were borrowed.
|
||||||
|
This code was written by David Hogan and Arnold Robbins.
|
||||||
|
Rich Salz motivated the
|
||||||
|
.B \-shell
|
||||||
|
option.
|
||||||
|
Christopher Platt motivated the
|
||||||
|
.B \-teleport
|
||||||
|
option.
|
||||||
|
John O'Donnell supplied the basic code for the
|
||||||
|
.B \-fg
|
||||||
|
and
|
||||||
|
.B \-bg
|
||||||
|
options.
|
||||||
|
Peter Seebach provided the base code for the
|
||||||
|
.B \-file
|
||||||
|
and
|
||||||
|
.B \-path
|
||||||
|
options.
|
||||||
|
Matthias Bauer made it work with the keyboard.
|
|
@ -0,0 +1,832 @@
|
||||||
|
/*
|
||||||
|
* 9menu.c
|
||||||
|
*
|
||||||
|
* This program puts up a window that is just a menu, and executes
|
||||||
|
* commands that correspond to the items selected.
|
||||||
|
*
|
||||||
|
* Initial idea: Arnold Robbins
|
||||||
|
* Version using libXg: Matty Farrow (some ideas borrowed)
|
||||||
|
* This code by: David Hogan and Arnold Robbins
|
||||||
|
*
|
||||||
|
* Copyright (c), Arnold Robbins and David Hogan
|
||||||
|
*
|
||||||
|
* Arnold Robbins
|
||||||
|
* arnold@skeeve.com
|
||||||
|
* October, 1994
|
||||||
|
*
|
||||||
|
* Code added to cause pop-up (unIconify) to move menu to mouse.
|
||||||
|
* Christopher Platt
|
||||||
|
* platt@coos.dartmouth.edu
|
||||||
|
* May, 1995
|
||||||
|
*
|
||||||
|
* Said code moved to -teleport option, and -warp option added.
|
||||||
|
* Arnold Robbins
|
||||||
|
* June, 1995
|
||||||
|
*
|
||||||
|
* Code added to allow -fg and -bg colors.
|
||||||
|
* John M. O'Donnell
|
||||||
|
* odonnell@stpaul.lampf.lanl.gov
|
||||||
|
* April, 1997
|
||||||
|
*
|
||||||
|
* Code added for -file and -path options.
|
||||||
|
* Peter Seebach
|
||||||
|
* seebs@plethora.net
|
||||||
|
* October, 2001
|
||||||
|
*
|
||||||
|
* Code added to allow up and down arrow keys to go up
|
||||||
|
* and down menu and RETURN to select an item.
|
||||||
|
* Matthias Bauer
|
||||||
|
* bauerm@immd1.informatik.uni-erlangen.de
|
||||||
|
* June, 2003
|
||||||
|
*
|
||||||
|
* spawn() changed to do exec directly if -popup, based on
|
||||||
|
* suggestion from
|
||||||
|
* Andrew Stribblehill
|
||||||
|
* a.d.stribblehill@durham.ac.uk
|
||||||
|
* June, 2004
|
||||||
|
*
|
||||||
|
* Allow "-" to mean read info from stdin.
|
||||||
|
* suggestion from
|
||||||
|
* Peter Bailey, by way of
|
||||||
|
* Andrew Stribblehill
|
||||||
|
* a.d.stribblehill@durham.ac.uk
|
||||||
|
* August, 2005
|
||||||
|
*
|
||||||
|
* Fix compile warnings (getcwd and getting a key sym).
|
||||||
|
* Arnold Robbins
|
||||||
|
* January, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <X11/X.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xproto.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/keysymdef.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
|
||||||
|
char version[] = "9menu version 1.10";
|
||||||
|
|
||||||
|
Display *dpy; /* lovely X stuff */
|
||||||
|
int screen;
|
||||||
|
Window root;
|
||||||
|
Window menuwin;
|
||||||
|
GC gc;
|
||||||
|
unsigned long black;
|
||||||
|
unsigned long white;
|
||||||
|
char *fgcname = NULL;
|
||||||
|
char *bgcname = NULL;
|
||||||
|
Colormap defcmap;
|
||||||
|
XColor color;
|
||||||
|
XFontStruct *font;
|
||||||
|
Atom wm_protocols;
|
||||||
|
Atom wm_delete_window;
|
||||||
|
int g_argc; /* for XSetWMProperties to use */
|
||||||
|
char **g_argv;
|
||||||
|
int f_argc; /* for labels read from files */
|
||||||
|
char **f_argv;
|
||||||
|
char *geometry = "";
|
||||||
|
int savex, savey;
|
||||||
|
Window savewindow;
|
||||||
|
|
||||||
|
char *fontlist[] = { /* default font list if no -font */
|
||||||
|
"pelm.latin1.9",
|
||||||
|
"lucm.latin1.9",
|
||||||
|
"blit",
|
||||||
|
"9x15bold",
|
||||||
|
"9x15",
|
||||||
|
"lucidasanstypewriter-12",
|
||||||
|
"fixed",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the 9menu icon, for garish window managers */
|
||||||
|
#define nine_menu_width 40
|
||||||
|
#define nine_menu_height 40
|
||||||
|
static unsigned char nine_menu_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00,
|
||||||
|
0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00,
|
||||||
|
0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04,
|
||||||
|
0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff,
|
||||||
|
0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00,
|
||||||
|
0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00,
|
||||||
|
0x80, 0xe0, 0x01, 0x04, 0x00, 0x80, 0xe0, 0x00, 0xfc, 0xff, 0xff, 0xe0,
|
||||||
|
0x01, 0xfc, 0xff, 0xff, 0x20, 0x03, 0x04, 0x00, 0x80, 0x00, 0x06, 0x04,
|
||||||
|
0x00, 0x80, 0x00, 0x0c, 0xfc, 0xff, 0xff, 0x00, 0x08, 0xfc, 0xff, 0xff,
|
||||||
|
0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00,
|
||||||
|
0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00,
|
||||||
|
0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00,
|
||||||
|
0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04,
|
||||||
|
0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff,
|
||||||
|
0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00,
|
||||||
|
0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
|
/* Modify this to your liking */
|
||||||
|
#define CONFIG_MENU_UP_KEY XK_Up
|
||||||
|
#define CONFIG_MENU_DOWN_KEY XK_Down
|
||||||
|
#define CONFIG_MENU_SELECT_KEY XK_Return
|
||||||
|
|
||||||
|
char *progname; /* my name */
|
||||||
|
char *displayname; /* X display */
|
||||||
|
char *fontname; /* font */
|
||||||
|
char *labelname; /* window and icon name */
|
||||||
|
char *filename; /* file to read options or labels from */
|
||||||
|
bool popup = false; /* true if we're a popup window */
|
||||||
|
bool popdown = false; /* autohide after running a command */
|
||||||
|
bool iconic = false; /* start iconified */
|
||||||
|
bool teleport = false; /* teleport the menu */
|
||||||
|
bool warp = false; /* warp the mouse */
|
||||||
|
|
||||||
|
char **labels; /* list of labels and commands */
|
||||||
|
char **commands;
|
||||||
|
int numitems;
|
||||||
|
|
||||||
|
char *shell = "/bin/sh"; /* default shell */
|
||||||
|
|
||||||
|
extern void usage(), run_menu(), spawn(char *com), ask_wm_for_delete();
|
||||||
|
extern void reap(int sig), set_wm_hints(int wide, int high);
|
||||||
|
extern void redraw(int cur, int high, int wide);
|
||||||
|
extern void teleportmenu(int cur, int wide, int high);
|
||||||
|
extern void warpmouse(int cur, int wide, int high);
|
||||||
|
extern void restoremouse();
|
||||||
|
extern void memory(char *msg);
|
||||||
|
extern int args(int argc, char **argv);
|
||||||
|
|
||||||
|
/* memory --- print the out of memory message and die */
|
||||||
|
|
||||||
|
void
|
||||||
|
memory(char *s)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: couldn't allocate memory for %s: %s\n", progname, s, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* args --- go through the argument list, set options */
|
||||||
|
|
||||||
|
int
|
||||||
|
args(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (argc == 0 || argv == NULL || argv[0][0] == '\0')
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (i = 0; i < argc && argv[i] != NULL; i++) {
|
||||||
|
if (strcmp(argv[i], "-display") == 0) {
|
||||||
|
displayname = argv[i+1];
|
||||||
|
i++;
|
||||||
|
} else if (strcmp(argv[i], "-file") == 0) {
|
||||||
|
filename = argv[i+1];
|
||||||
|
i++;
|
||||||
|
} else if (strcmp(argv[i], "-font") == 0) {
|
||||||
|
fontname = argv[i+1];
|
||||||
|
i++;
|
||||||
|
} else if (strcmp(argv[i], "-geometry") == 0) {
|
||||||
|
geometry = argv[i+1];
|
||||||
|
i++;
|
||||||
|
} else if (strcmp(argv[i], "-label") == 0) {
|
||||||
|
labelname = argv[i+1];
|
||||||
|
i++;
|
||||||
|
} else if (strcmp(argv[i], "-shell") == 0) {
|
||||||
|
shell = argv[i+1];
|
||||||
|
i++;
|
||||||
|
} else if (strcmp(argv[i], "-popup") == 0)
|
||||||
|
popup = true;
|
||||||
|
else if (strcmp(argv[i], "-popdown") == 0)
|
||||||
|
popdown = true;
|
||||||
|
else if (strcmp(argv[i], "-fg") == 0)
|
||||||
|
fgcname = argv[++i];
|
||||||
|
else if (strcmp(argv[i], "-bg") == 0)
|
||||||
|
bgcname = argv[++i];
|
||||||
|
else if (strcmp(argv[i], "-iconic") == 0)
|
||||||
|
iconic = true;
|
||||||
|
else if (strcmp(argv[i], "-path") == 0) {
|
||||||
|
char pathbuf[MAXPATHLEN];
|
||||||
|
char *s, *t;
|
||||||
|
|
||||||
|
s = getenv("PATH");
|
||||||
|
if (s != NULL) {
|
||||||
|
/* append current dir to PATH */
|
||||||
|
char *cp = getcwd(pathbuf, MAXPATHLEN);
|
||||||
|
t = malloc(strlen(s) + strlen(pathbuf) + 7);
|
||||||
|
sprintf(t, "PATH=%s:%s", pathbuf, s);
|
||||||
|
putenv(t);
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[i], "-teleport") == 0)
|
||||||
|
teleport = true;
|
||||||
|
else if (strcmp(argv[i], "-warp") == 0)
|
||||||
|
warp = true;
|
||||||
|
else if (strcmp(argv[i], "-version") == 0) {
|
||||||
|
printf("%s\n", version);
|
||||||
|
exit(0);
|
||||||
|
} else if (argv[i][0] == '-')
|
||||||
|
usage();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main --- crack arguments, set up X stuff, run the main menu loop */
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
char *cp;
|
||||||
|
XGCValues gv;
|
||||||
|
unsigned long mask;
|
||||||
|
int nlabels = 0;
|
||||||
|
|
||||||
|
g_argc = argc;
|
||||||
|
g_argv = argv;
|
||||||
|
|
||||||
|
/* set default label name */
|
||||||
|
if ((cp = strrchr(argv[0], '/')) == NULL)
|
||||||
|
labelname = argv[0];
|
||||||
|
else
|
||||||
|
labelname = ++cp;
|
||||||
|
|
||||||
|
++argv;
|
||||||
|
--argc;
|
||||||
|
|
||||||
|
/* and program name for diagnostics */
|
||||||
|
progname = labelname;
|
||||||
|
|
||||||
|
i = args(argc, argv);
|
||||||
|
|
||||||
|
numitems = argc - i;
|
||||||
|
|
||||||
|
if (numitems <= 0 && filename == NULL)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (filename) {
|
||||||
|
/* Read options and labels from file */
|
||||||
|
char fbuf[1024];
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (strcmp(filename, "-") == 0) {
|
||||||
|
fp = stdin;
|
||||||
|
} else {
|
||||||
|
fp = fopen(filename, "r");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr, "%s: couldn't open '%s': %s\n", progname,
|
||||||
|
filename, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(fbuf, sizeof fbuf, fp)) {
|
||||||
|
char *s = fbuf;
|
||||||
|
strtok(s, "\n");
|
||||||
|
if (s[0] == '-') {
|
||||||
|
char *temp[3];
|
||||||
|
temp[0] = s;
|
||||||
|
temp[1] = strchr(s, ' ');
|
||||||
|
if (temp[1]) {
|
||||||
|
*(temp[1]++) = '\0';
|
||||||
|
s = malloc(strlen(temp[1]) + 1);
|
||||||
|
if (s == NULL)
|
||||||
|
memory("temporary argument");
|
||||||
|
strcpy(s, temp[1]);
|
||||||
|
temp[1] = s;
|
||||||
|
}
|
||||||
|
temp[2] = 0;
|
||||||
|
args(temp[1] ? 2 : 1, temp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (s[0] == '#')
|
||||||
|
continue;
|
||||||
|
/* allow - in menu items to be escaped */
|
||||||
|
if (s[0] == '\\')
|
||||||
|
++s;
|
||||||
|
/* allocate space */
|
||||||
|
if (f_argc < nlabels + 1) {
|
||||||
|
int k;
|
||||||
|
char **temp = malloc(sizeof(char *) * (f_argc + 5));
|
||||||
|
if (temp == 0)
|
||||||
|
memory("temporary item");
|
||||||
|
|
||||||
|
for (k = 0; k < nlabels; k++)
|
||||||
|
temp[k] = f_argv[k];
|
||||||
|
|
||||||
|
free(f_argv);
|
||||||
|
f_argv = temp;
|
||||||
|
f_argc += 5;
|
||||||
|
}
|
||||||
|
f_argv[nlabels] = malloc(strlen(s) + 1);
|
||||||
|
if (f_argv[nlabels] == NULL)
|
||||||
|
memory("temporary text");
|
||||||
|
strcpy(f_argv[nlabels], s);
|
||||||
|
++nlabels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
labels = (char **) malloc((numitems + nlabels) * sizeof(char *));
|
||||||
|
commands = (char **) malloc((numitems + nlabels) * sizeof(char *));
|
||||||
|
if (commands == NULL || labels == NULL)
|
||||||
|
memory("command and label arrays");
|
||||||
|
|
||||||
|
for (j = 0; j < numitems; j++) {
|
||||||
|
labels[j] = argv[i + j];
|
||||||
|
if ((cp = strchr(labels[j], ':')) != NULL) {
|
||||||
|
*cp++ = '\0';
|
||||||
|
commands[j] = cp;
|
||||||
|
} else
|
||||||
|
commands[j] = labels[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we no longer need i (our offset into argv) so we recycle it,
|
||||||
|
* while keeping the old value of j!
|
||||||
|
*/
|
||||||
|
for (i = 0; i < nlabels; i++) {
|
||||||
|
labels[j] = f_argv[i];
|
||||||
|
if ((cp = strchr(labels[j], ':')) != NULL) {
|
||||||
|
*cp++ = '\0';
|
||||||
|
commands[j] = cp;
|
||||||
|
} else
|
||||||
|
commands[j] = labels[j];
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And now we merge the totals */
|
||||||
|
numitems += nlabels;
|
||||||
|
|
||||||
|
dpy = XOpenDisplay(displayname);
|
||||||
|
if (dpy == NULL) {
|
||||||
|
fprintf(stderr, "%s: cannot open display", progname);
|
||||||
|
if (displayname != NULL)
|
||||||
|
fprintf(stderr, " %s", displayname);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
screen = DefaultScreen(dpy);
|
||||||
|
root = RootWindow(dpy, screen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This used to be
|
||||||
|
* black = BlackPixel(dpy, screen);
|
||||||
|
* white = WhitePixel(dpy, screen);
|
||||||
|
*/
|
||||||
|
defcmap = DefaultColormap(dpy, screen);
|
||||||
|
if (fgcname == NULL
|
||||||
|
|| XParseColor(dpy, defcmap, fgcname, &color) == 0
|
||||||
|
|| XAllocColor(dpy, defcmap, &color) == 0)
|
||||||
|
black = BlackPixel(dpy, screen);
|
||||||
|
else
|
||||||
|
black = color.pixel;
|
||||||
|
|
||||||
|
if (bgcname == NULL
|
||||||
|
|| XParseColor(dpy, defcmap, bgcname, &color) == 0
|
||||||
|
|| XAllocColor(dpy, defcmap, &color) == 0)
|
||||||
|
white = WhitePixel(dpy, screen);
|
||||||
|
else
|
||||||
|
white = color.pixel;
|
||||||
|
|
||||||
|
/* try user's font first */
|
||||||
|
if (fontname != NULL) {
|
||||||
|
font = XLoadQueryFont(dpy, fontname);
|
||||||
|
if (font == NULL)
|
||||||
|
fprintf(stderr, "%s: warning: can't load font %s\n",
|
||||||
|
progname, fontname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if no user font, try one of our default fonts */
|
||||||
|
if (font == NULL) {
|
||||||
|
for (i = 0; fontlist[i] != NULL; i++) {
|
||||||
|
font = XLoadQueryFont(dpy, fontlist[i]);
|
||||||
|
if (font != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (font == NULL) {
|
||||||
|
fprintf(stderr, "%s: fatal: cannot load a font\n", progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
gv.foreground = black^white;
|
||||||
|
gv.background = white;
|
||||||
|
gv.font = font->fid;
|
||||||
|
gv.function = GXxor;
|
||||||
|
gv.line_width = 0;
|
||||||
|
mask = GCForeground | GCBackground | GCFunction | GCFont | GCLineWidth;
|
||||||
|
gc = XCreateGC(dpy, root, mask, &gv);
|
||||||
|
|
||||||
|
signal(SIGCHLD, reap);
|
||||||
|
|
||||||
|
run_menu();
|
||||||
|
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* spawn --- run a command */
|
||||||
|
|
||||||
|
void
|
||||||
|
spawn(char *com)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
static char *sh_base = NULL;
|
||||||
|
|
||||||
|
if (sh_base == NULL) {
|
||||||
|
sh_base = strrchr(shell, '/');
|
||||||
|
if (sh_base != NULL)
|
||||||
|
sh_base++;
|
||||||
|
else
|
||||||
|
sh_base = shell;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since -popup means run command and exit, just
|
||||||
|
* fall straight into exec code. Thus only fork
|
||||||
|
* if not popup.
|
||||||
|
*/
|
||||||
|
if (! popup) {
|
||||||
|
if (strncmp(com, "exec ", 5) != 0) {
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
fprintf(stderr, "%s: can't fork: %s\n", progname, strerror(errno));
|
||||||
|
return;
|
||||||
|
} else if (pid > 0)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
com += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(ConnectionNumber(dpy));
|
||||||
|
execl(shell, sh_base, "-c", com, NULL);
|
||||||
|
execl("/bin/sh", "sh", "-c", com, NULL);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reap --- collect dead children */
|
||||||
|
|
||||||
|
void
|
||||||
|
reap(int sig)
|
||||||
|
{
|
||||||
|
(void) wait((int *) NULL);
|
||||||
|
signal(sig, reap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* usage --- print a usage message and die */
|
||||||
|
|
||||||
|
void
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [-display displayname] [-font fname] ", progname);
|
||||||
|
fprintf(stderr, "[-file filename] [-path]");
|
||||||
|
fprintf(stderr, "[-geometry geom] [-shell shell] [-label name] ");
|
||||||
|
fprintf(stderr, "[-popup] [-popdown] [-iconic] [-teleport] ");
|
||||||
|
fprintf(stderr, "[-warp] [-version] menitem:command ...\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* run_menu --- put up the window, execute selected commands */
|
||||||
|
|
||||||
|
void
|
||||||
|
run_menu()
|
||||||
|
{
|
||||||
|
XEvent ev;
|
||||||
|
XClientMessageEvent *cmsg;
|
||||||
|
KeySym key;
|
||||||
|
int i, cur, old, wide, high, ico, dx, dy;
|
||||||
|
|
||||||
|
dx = 0;
|
||||||
|
for (i = 0; i < numitems; i++) {
|
||||||
|
wide = XTextWidth(font, labels[i], strlen(labels[i])) + 4;
|
||||||
|
if (wide > dx)
|
||||||
|
dx = wide;
|
||||||
|
}
|
||||||
|
wide = dx;
|
||||||
|
|
||||||
|
old = cur = -1;
|
||||||
|
|
||||||
|
high = font->ascent + font->descent + 1;
|
||||||
|
dy = numitems * high;
|
||||||
|
|
||||||
|
set_wm_hints(wide, dy);
|
||||||
|
|
||||||
|
ask_wm_for_delete();
|
||||||
|
|
||||||
|
#define MenuMask (ButtonPressMask|ButtonReleaseMask\
|
||||||
|
|LeaveWindowMask|PointerMotionMask|ButtonMotionMask\
|
||||||
|
|ExposureMask|StructureNotifyMask|KeyPressMask)
|
||||||
|
|
||||||
|
XSelectInput(dpy, menuwin, MenuMask);
|
||||||
|
|
||||||
|
XMapWindow(dpy, menuwin);
|
||||||
|
|
||||||
|
ico = 1; /* warp to first item */
|
||||||
|
i = 0; /* save menu Item position */
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
XNextEvent(dpy, &ev);
|
||||||
|
switch (ev.type) {
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: unknown ev.type %d\n",
|
||||||
|
progname, ev.type);
|
||||||
|
break;
|
||||||
|
case ButtonRelease:
|
||||||
|
/* allow button 1 or button 3 */
|
||||||
|
if (ev.xbutton.button == Button2)
|
||||||
|
break;
|
||||||
|
i = ev.xbutton.y/high;
|
||||||
|
if (ev.xbutton.x < 0 || ev.xbutton.x > wide)
|
||||||
|
break;
|
||||||
|
else if (i < 0 || i >= numitems)
|
||||||
|
break;
|
||||||
|
if (warp)
|
||||||
|
restoremouse();
|
||||||
|
if (strcmp(labels[i], "exit") == 0) {
|
||||||
|
if (commands[i] != labels[i]) {
|
||||||
|
spawn(commands[i]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spawn(commands[i]);
|
||||||
|
if (popup)
|
||||||
|
return;
|
||||||
|
if (cur >= 0 && cur < numitems)
|
||||||
|
XFillRectangle(dpy, menuwin, gc, 0, cur*high, wide, high);
|
||||||
|
if (popdown)
|
||||||
|
XIconifyWindow(dpy, menuwin, screen);
|
||||||
|
cur = -1;
|
||||||
|
break;
|
||||||
|
case ButtonPress:
|
||||||
|
case MotionNotify:
|
||||||
|
old = cur;
|
||||||
|
cur = ev.xbutton.y/high;
|
||||||
|
if (ev.xbutton.x < 0 || ev.xbutton.x > wide)
|
||||||
|
cur = -1;
|
||||||
|
else if (cur < 0 || cur >= numitems)
|
||||||
|
cur = -1;
|
||||||
|
if (cur == old)
|
||||||
|
break;
|
||||||
|
if (old >= 0 && old < numitems)
|
||||||
|
XFillRectangle(dpy, menuwin, gc, 0, old*high, wide, high);
|
||||||
|
if (cur >= 0 && cur < numitems)
|
||||||
|
XFillRectangle(dpy, menuwin, gc, 0, cur*high, wide, high);
|
||||||
|
break;
|
||||||
|
case KeyPress:
|
||||||
|
/* http://stackoverflow.com/questions/9838385/replace-of-xkeycodetokeysym */
|
||||||
|
key = XkbKeycodeToKeysym(dpy, ev.xkey.keycode, 0,
|
||||||
|
ev.xkey.state & ShiftMask ? 1 : 0);
|
||||||
|
if (key != CONFIG_MENU_UP_KEY
|
||||||
|
&& key != CONFIG_MENU_DOWN_KEY
|
||||||
|
&& key != CONFIG_MENU_SELECT_KEY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* adjust i so mapping will work */
|
||||||
|
if (key == CONFIG_MENU_UP_KEY) {
|
||||||
|
old = cur;
|
||||||
|
cur--;
|
||||||
|
i--;
|
||||||
|
} else if (key == CONFIG_MENU_DOWN_KEY) {
|
||||||
|
old = cur;
|
||||||
|
cur++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cur < 0)
|
||||||
|
cur += numitems;
|
||||||
|
|
||||||
|
cur %= numitems;
|
||||||
|
|
||||||
|
if (key == CONFIG_MENU_UP_KEY || key == CONFIG_MENU_DOWN_KEY) {
|
||||||
|
if (cur == old)
|
||||||
|
break;
|
||||||
|
if (old >= 0 && old < numitems && cur != -1)
|
||||||
|
XFillRectangle(dpy, menuwin, gc, 0, old*high, wide, high);
|
||||||
|
if (cur >= 0 && cur < numitems && cur != -1)
|
||||||
|
XFillRectangle(dpy, menuwin, gc, 0, cur*high, wide, high);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (warp)
|
||||||
|
restoremouse();
|
||||||
|
if (key == CONFIG_MENU_SELECT_KEY) {
|
||||||
|
if (strcmp(labels[cur], "exit") == 0) {
|
||||||
|
if (commands[cur] != labels[cur]) {
|
||||||
|
spawn(commands[cur]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spawn(commands[cur]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (popup)
|
||||||
|
return;
|
||||||
|
if (popdown)
|
||||||
|
XIconifyWindow(dpy, menuwin, screen);
|
||||||
|
break;
|
||||||
|
case LeaveNotify:
|
||||||
|
cur = old = -1;
|
||||||
|
XClearWindow(dpy, menuwin);
|
||||||
|
redraw(cur, high, wide);
|
||||||
|
break;
|
||||||
|
case ReparentNotify:
|
||||||
|
case ConfigureNotify:
|
||||||
|
/*
|
||||||
|
* ignore these, they come from XMoveWindow
|
||||||
|
* and are enabled by Struct..
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case UnmapNotify:
|
||||||
|
ico = 1;
|
||||||
|
XClearWindow(dpy, menuwin);
|
||||||
|
break;
|
||||||
|
case MapNotify:
|
||||||
|
if (ico) {
|
||||||
|
if (teleport)
|
||||||
|
teleportmenu(i, wide, high);
|
||||||
|
else if (warp)
|
||||||
|
warpmouse(i, wide, high);
|
||||||
|
}
|
||||||
|
XClearWindow(dpy, menuwin);
|
||||||
|
redraw(cur = i, high, wide);
|
||||||
|
ico = 0;
|
||||||
|
break;
|
||||||
|
case Expose:
|
||||||
|
XClearWindow(dpy, menuwin);
|
||||||
|
redraw(cur, high, wide);
|
||||||
|
break;
|
||||||
|
case ClientMessage:
|
||||||
|
cmsg = &ev.xclient;
|
||||||
|
if (cmsg->message_type == wm_protocols
|
||||||
|
&& cmsg->data.l[0] == wm_delete_window)
|
||||||
|
return;
|
||||||
|
case MappingNotify: /* why do we get this? */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set_wm_hints --- set all the window manager hints */
|
||||||
|
|
||||||
|
void
|
||||||
|
set_wm_hints(int wide, int high)
|
||||||
|
{
|
||||||
|
Pixmap iconpixmap;
|
||||||
|
XWMHints *wmhints;
|
||||||
|
XSizeHints *sizehints;
|
||||||
|
XClassHint *classhints;
|
||||||
|
XTextProperty wname, iname;
|
||||||
|
|
||||||
|
if ((sizehints = XAllocSizeHints()) == NULL)
|
||||||
|
memory("size hints");
|
||||||
|
|
||||||
|
if ((wmhints = XAllocWMHints()) == NULL)
|
||||||
|
memory("window manager hints");
|
||||||
|
|
||||||
|
if ((classhints = XAllocClassHint()) == NULL)
|
||||||
|
memory("class hints");
|
||||||
|
|
||||||
|
/* fill in hints in order to parse geometry spec */
|
||||||
|
sizehints->width = sizehints->min_width = sizehints->max_width = wide;
|
||||||
|
sizehints->height = sizehints->min_height = sizehints->max_height = high;
|
||||||
|
sizehints->flags = USSize|PSize|PMinSize|PMaxSize;
|
||||||
|
if (XWMGeometry(dpy, screen, geometry, "", 1, sizehints,
|
||||||
|
&sizehints->x, &sizehints->y,
|
||||||
|
&sizehints->width, &sizehints->height,
|
||||||
|
&sizehints->win_gravity) & (XValue|YValue))
|
||||||
|
sizehints->flags |= USPosition;
|
||||||
|
|
||||||
|
/* override -geometry for size of window */
|
||||||
|
sizehints->width = sizehints->min_width = sizehints->max_width = wide;
|
||||||
|
sizehints->height = sizehints->min_height = sizehints->max_height = high;
|
||||||
|
|
||||||
|
if (XStringListToTextProperty(& labelname, 1, & wname) == 0)
|
||||||
|
memory("window name structure");
|
||||||
|
|
||||||
|
if (XStringListToTextProperty(& labelname, 1, & iname) == 0)
|
||||||
|
memory("icon name structure");
|
||||||
|
|
||||||
|
menuwin = XCreateSimpleWindow(dpy, root, sizehints->x, sizehints->y,
|
||||||
|
sizehints->width, sizehints->height, 1, black, white);
|
||||||
|
|
||||||
|
iconpixmap = XCreateBitmapFromData(dpy, menuwin,
|
||||||
|
nine_menu_bits,
|
||||||
|
nine_menu_width,
|
||||||
|
nine_menu_height);
|
||||||
|
|
||||||
|
wmhints->icon_pixmap = iconpixmap;
|
||||||
|
wmhints->input = False; /* no keyboard input */
|
||||||
|
if (iconic)
|
||||||
|
wmhints->initial_state = IconicState;
|
||||||
|
else
|
||||||
|
wmhints->initial_state = NormalState;
|
||||||
|
|
||||||
|
wmhints->flags = IconPixmapHint | StateHint | InputHint;
|
||||||
|
|
||||||
|
classhints->res_name = progname;
|
||||||
|
classhints->res_class = "9menu";
|
||||||
|
|
||||||
|
#ifdef SET_PROPERTIES_MANUALLY
|
||||||
|
/*
|
||||||
|
* For some reason, XSetWMProperties (see below) is failing
|
||||||
|
* John O'Donnell replaces it with the following commands
|
||||||
|
* (this leaves out XSetWMClientMachine,
|
||||||
|
* and also environment variable checking from ClassHint)
|
||||||
|
*/
|
||||||
|
XSetWMName(dpy, menuwin, &wname);
|
||||||
|
XSetWMIconName(dpy, menuwin, &iname);
|
||||||
|
XSetCommand(dpy, menuwin, g_argv, g_argc);
|
||||||
|
XSetWMHints(dpy, menuwin, wmhints);
|
||||||
|
XSetClassHint(dpy, menuwin, classhints);
|
||||||
|
XSetWMNormalHints(dpy, menuwin, sizehints);
|
||||||
|
#else
|
||||||
|
XSetWMProperties(dpy, menuwin, & wname, & iname,
|
||||||
|
g_argv, g_argc, sizehints, wmhints, classhints);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ask_wm_for_delete --- jump through hoops to ask WM to delete us */
|
||||||
|
|
||||||
|
void
|
||||||
|
ask_wm_for_delete()
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
|
||||||
|
wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
||||||
|
status = XSetWMProtocols(dpy, menuwin, & wm_delete_window, 1);
|
||||||
|
|
||||||
|
if (status != True)
|
||||||
|
fprintf(stderr, "%s: could not ask for clean delete\n",
|
||||||
|
progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* redraw --- actually redraw the menu */
|
||||||
|
|
||||||
|
void
|
||||||
|
redraw(int cur, int high, int wide)
|
||||||
|
{
|
||||||
|
int tx, ty, i;
|
||||||
|
|
||||||
|
for (i = 0; i < numitems; i++) {
|
||||||
|
tx = (wide - XTextWidth(font, labels[i], strlen(labels[i]))) / 2;
|
||||||
|
ty = i*high + font->ascent + 1;
|
||||||
|
XDrawString(dpy, menuwin, gc, tx, ty, labels[i], strlen(labels[i]));
|
||||||
|
}
|
||||||
|
if (cur >= 0 && cur < numitems)
|
||||||
|
XFillRectangle(dpy, menuwin, gc, 0, cur*high, wide, high);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* teleportmenu --- move the menu to the right place */
|
||||||
|
|
||||||
|
void
|
||||||
|
teleportmenu(int cur, int wide, int high)
|
||||||
|
{
|
||||||
|
int x, y, dummy;
|
||||||
|
Window wdummy;
|
||||||
|
|
||||||
|
if (XQueryPointer(dpy, menuwin, &wdummy, &wdummy, &x, &y,
|
||||||
|
&dummy, &dummy, &dummy))
|
||||||
|
XMoveWindow(dpy, menuwin, x-wide/2, y-cur*high-high/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* warpmouse --- bring the mouse to the menu */
|
||||||
|
|
||||||
|
void
|
||||||
|
warpmouse(int cur, int wide, int high)
|
||||||
|
{
|
||||||
|
int dummy;
|
||||||
|
Window wdummy;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
/* move tip of pointer into middle of menu item */
|
||||||
|
offset = (font->ascent + font->descent + 1) / 2;
|
||||||
|
offset += 6; /* fudge factor */
|
||||||
|
|
||||||
|
if (XQueryPointer(dpy, menuwin, &wdummy, &wdummy, &savex, &savey,
|
||||||
|
&dummy, &dummy, &dummy))
|
||||||
|
XWarpPointer(dpy, None, menuwin, 0, 0, 0, 0,
|
||||||
|
wide/2, cur*high-high/2+offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restoremouse --- put the mouse back where it was */
|
||||||
|
|
||||||
|
void
|
||||||
|
restoremouse()
|
||||||
|
{
|
||||||
|
XWarpPointer(dpy, menuwin, root, 0, 0, 0, 0,
|
||||||
|
savex, savey);
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
INCLUDES = -I$(TOP)
|
||||||
|
DEPLIBS = $(DEPXLIBONLY)
|
||||||
|
LOCAL_LIBRARIES = $(XLIBONLY)
|
||||||
|
DEFINES = -DSHAPE #-DDEBUG -DDEBUG_EV
|
||||||
|
SRCS = 9menu.c
|
||||||
|
OBJS = 9menu.o
|
||||||
|
|
||||||
|
ComplexProgramTarget(9menu)
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Makefile for 9menu.
|
||||||
|
#
|
||||||
|
# Edit to taste
|
||||||
|
#
|
||||||
|
# Arnold Robbins
|
||||||
|
# arnold@skeeve.atl.ga.us
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -g -O
|
||||||
|
LIBS = -lX11
|
||||||
|
|
||||||
|
9menu: 9menu.c
|
||||||
|
$(CC) $(CFLAGS) 9menu.c $(LIBS) -o 9menu
|
|
@ -0,0 +1,40 @@
|
||||||
|
Thu Mar 19 23:51:38 IST 2015
|
||||||
|
|
||||||
|
This is 9menu, a simple program that allows you to create X menus from the
|
||||||
|
shell, where each menu item will run a command. 9menu is intended for use
|
||||||
|
with 9wm, but can be used with any other window manager.
|
||||||
|
|
||||||
|
The idea of a command line menu generator is from xmenu, but xmenu was
|
||||||
|
exclusively a pop-up menu, not what I wanted.
|
||||||
|
|
||||||
|
The files are:
|
||||||
|
|
||||||
|
README --- this file
|
||||||
|
9menu.1 --- man page for 9menu
|
||||||
|
9menu.c --- source code
|
||||||
|
Imakefile --- a contributed Imakefile,
|
||||||
|
from Bengt Kleberg <bengt@softwell.se>
|
||||||
|
Makefile.noimake --- a simple makefile.
|
||||||
|
|
||||||
|
Licence
|
||||||
|
=======
|
||||||
|
|
||||||
|
9menu is free software, and is Copyright (c) 1994 by David Hogan and
|
||||||
|
Arnold Robbins. Permission is granted to all sentient beings to use
|
||||||
|
this software, to make copies of it, and to distribute those copies,
|
||||||
|
provided that:
|
||||||
|
|
||||||
|
(1) the copyright and licence notices are left intact
|
||||||
|
(2) the recipients are aware that it is free software
|
||||||
|
(3) any unapproved changes in functionality are either
|
||||||
|
(i) only distributed as patches
|
||||||
|
or (ii) distributed as a new program which is not called 9menu
|
||||||
|
and whose documentation gives credit where it is due
|
||||||
|
(4) the authors are not held responsible for any defects
|
||||||
|
or shortcomings in the software, or damages caused by it.
|
||||||
|
|
||||||
|
There is no warranty for this software. Have a nice day.
|
||||||
|
|
||||||
|
--
|
||||||
|
Arnold Robbins
|
||||||
|
arnold@skeeve.com
|
|
@ -0,0 +1 @@
|
||||||
|
7 1
|
Loading…
Reference in New Issue