2007-02-26 13:17:10 +03:00
|
|
|
/* 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
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
2007-04-06 09:36:17 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Heavily modified by Kris Maglione for use with wmii.
|
|
|
|
*/
|
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
#define IXP_NO_P9_
|
|
|
|
#define IXP_P9_STRUCTS
|
2008-10-17 03:05:17 +04:00
|
|
|
#include <fmt.h>
|
2008-10-17 02:54:03 +04:00
|
|
|
#include <ixp.h>
|
2008-08-25 20:47:56 +04:00
|
|
|
#include <stdarg.h>
|
2008-10-17 02:54:03 +04:00
|
|
|
#include <stdbool.h>
|
2007-02-26 13:17:10 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2010-05-22 06:52:47 +04:00
|
|
|
|
|
|
|
#include <stuff/clientutil.h>
|
|
|
|
#include <stuff/util.h>
|
2010-06-02 04:09:25 +04:00
|
|
|
#include <stuff/x.h>
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2010-05-23 04:28:39 +04:00
|
|
|
char version[] = "wmii9menu-"VERSION" "COPYRIGHT", ©1994 David Hogan, Arnold Robbins";
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
static Window* menuwin;
|
|
|
|
|
|
|
|
static CTuple cnorm;
|
|
|
|
static CTuple csel;
|
|
|
|
static Font* font;
|
|
|
|
|
|
|
|
static int wborder;
|
|
|
|
|
2010-10-08 00:31:41 +04:00
|
|
|
static char* initial = "";
|
|
|
|
static int cur;
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
static char** labels; /* list of labels and commands */
|
|
|
|
static char** commands;
|
|
|
|
static int numitems;
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2007-05-25 01:42:33 +04:00
|
|
|
void usage(void);
|
|
|
|
void run_menu(void);
|
2008-10-17 02:54:03 +04:00
|
|
|
void create_window(void);
|
|
|
|
void size_window(int, int);
|
2007-05-25 01:42:33 +04:00
|
|
|
void redraw(int, int);
|
|
|
|
void warpmouse(int, int);
|
2009-10-22 15:07:10 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
init_screens(void) {
|
|
|
|
Rectangle *rects;
|
|
|
|
Point p;
|
|
|
|
int i, n;
|
|
|
|
|
|
|
|
rects = xinerama_screens(&n);
|
|
|
|
p = querypointer(&scr.root);
|
|
|
|
for(i=0; i < n; i++) {
|
2010-06-02 04:09:25 +04:00
|
|
|
if(rect_haspoint_p(rects[i], p))
|
2009-10-22 15:07:10 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(i == n)
|
|
|
|
i = 0;
|
|
|
|
scr.rect = rects[i];
|
|
|
|
}
|
|
|
|
|
2007-02-26 13:17:10 +03:00
|
|
|
/* main --- crack arguments, set up X stuff, run the main menu loop */
|
|
|
|
|
|
|
|
int
|
2007-02-26 14:08:50 +03:00
|
|
|
main(int argc, char **argv)
|
2007-02-26 13:17:10 +03:00
|
|
|
{
|
2008-10-17 03:05:17 +04:00
|
|
|
static char *address;
|
2007-02-26 13:17:10 +03:00
|
|
|
char *cp;
|
2008-10-17 03:05:17 +04:00
|
|
|
int i;
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2008-10-17 03:05:17 +04:00
|
|
|
ARGBEGIN{
|
|
|
|
case 'v':
|
2010-06-06 13:07:24 +04:00
|
|
|
lprint(1, "%s\n", version);
|
2008-10-17 03:05:17 +04:00
|
|
|
return 0;
|
|
|
|
case 'a':
|
|
|
|
address = EARGF(usage());
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
initial = EARGF(usage());
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}ARGEND;
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2007-04-07 09:28:49 +04:00
|
|
|
if(argc == 0)
|
|
|
|
usage();
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
initdisplay();
|
2009-10-22 15:07:10 +04:00
|
|
|
xext_init();
|
|
|
|
init_screens();
|
2008-10-17 02:54:03 +04:00
|
|
|
create_window();
|
|
|
|
|
2007-04-07 09:28:49 +04:00
|
|
|
numitems = argc;
|
2008-02-03 23:06:26 +03:00
|
|
|
labels = emalloc(numitems * sizeof *labels);
|
|
|
|
commands = emalloc(numitems * sizeof *labels);
|
2007-04-07 09:28:49 +04:00
|
|
|
|
|
|
|
for(i = 0; i < numitems; i++) {
|
|
|
|
labels[i] = argv[i];
|
2010-10-08 00:31:41 +04:00
|
|
|
commands[i] = argv[i];
|
2007-04-07 09:28:49 +04:00
|
|
|
if((cp = strchr(labels[i], ':')) != nil) {
|
2007-02-26 13:17:10 +03:00
|
|
|
*cp++ = '\0';
|
2007-04-07 09:28:49 +04:00
|
|
|
commands[i] = cp;
|
2010-10-08 00:31:41 +04:00
|
|
|
}
|
2007-04-07 09:28:49 +04:00
|
|
|
if(strcmp(labels[i], initial) == 0)
|
|
|
|
cur = i;
|
2007-02-26 13:17:10 +03:00
|
|
|
}
|
|
|
|
|
2009-05-14 07:30:20 +04:00
|
|
|
client_init(address);
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2010-10-08 00:31:41 +04:00
|
|
|
wborder = strtol(readctl("/ctl", "border "), nil, 10);
|
|
|
|
client_readconfig(&cnorm, &csel, &font);
|
2007-02-26 13:17:10 +03:00
|
|
|
|
|
|
|
run_menu();
|
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
XCloseDisplay(display);
|
2007-07-03 13:13:01 +04:00
|
|
|
return 0;
|
2007-02-26 13:17:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-05-25 01:42:33 +04:00
|
|
|
usage(void)
|
2007-02-26 13:17:10 +03:00
|
|
|
{
|
2010-10-08 00:31:41 +04:00
|
|
|
lprint(2, "usage: %s [-a <address>] [-i <arg>] <menitem>[:<command>] ...\n", argv0);
|
|
|
|
lprint(2, " %s -v\n", argv0);
|
2007-02-26 13:17:10 +03:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
enum {
|
2010-10-08 00:31:41 +04:00
|
|
|
MouseMask = ButtonPressMask
|
|
|
|
| ButtonReleaseMask
|
|
|
|
| ButtonMotionMask
|
|
|
|
| PointerMotionMask,
|
|
|
|
MenuMask = MouseMask
|
|
|
|
| StructureNotifyMask
|
|
|
|
| ExposureMask
|
2008-10-17 02:54:03 +04:00
|
|
|
};
|
2007-07-03 13:13:01 +04:00
|
|
|
|
2007-02-26 13:17:10 +03:00
|
|
|
void
|
2007-05-25 01:42:33 +04:00
|
|
|
run_menu(void)
|
2007-02-26 13:17:10 +03:00
|
|
|
{
|
|
|
|
XEvent ev;
|
2008-10-17 02:54:03 +04:00
|
|
|
int i, old, wide, high;
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
high = labelh(font);
|
2010-10-08 00:31:41 +04:00
|
|
|
wide = 0;
|
2008-10-17 02:54:03 +04:00
|
|
|
for(i = 0; i < numitems; i++)
|
|
|
|
wide = max(wide, textwidth(font, labels[i]));
|
|
|
|
wide += font->height & ~1;
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2008-10-17 20:08:44 +04:00
|
|
|
size_window(wide, high);
|
2007-03-01 05:18:26 +03:00
|
|
|
warpmouse(wide, high);
|
|
|
|
|
2007-04-07 09:28:49 +04:00
|
|
|
for(;;) {
|
2008-10-17 02:54:03 +04:00
|
|
|
XNextEvent(display, &ev);
|
2007-02-26 13:17:10 +03:00
|
|
|
switch (ev.type) {
|
|
|
|
default:
|
2010-06-06 13:07:24 +04:00
|
|
|
lprint(2, "%s: unknown ev.type %d\n", argv0, ev.type);
|
2007-02-26 13:17:10 +03:00
|
|
|
break;
|
|
|
|
case ButtonRelease:
|
2008-10-17 02:54:03 +04:00
|
|
|
i = ev.xbutton.y / high;
|
2007-04-07 09:28:49 +04:00
|
|
|
if(ev.xbutton.x < 0 || ev.xbutton.x > wide)
|
2007-03-01 04:16:21 +03:00
|
|
|
return;
|
2007-04-07 09:28:49 +04:00
|
|
|
else if(i < 0 || i >= numitems)
|
2007-03-01 04:16:21 +03:00
|
|
|
return;
|
2007-02-26 14:08:50 +03:00
|
|
|
|
2010-06-06 13:07:24 +04:00
|
|
|
lprint(1, "%s\n", commands[i]);
|
2007-02-26 13:17:10 +03:00
|
|
|
return;
|
2007-02-26 14:08:50 +03:00
|
|
|
case ButtonPress:
|
2007-02-26 13:17:10 +03:00
|
|
|
case MotionNotify:
|
|
|
|
old = cur;
|
2008-10-17 02:54:03 +04:00
|
|
|
cur = ev.xbutton.y / high;
|
2007-04-07 09:28:49 +04:00
|
|
|
if(ev.xbutton.x < 0 || ev.xbutton.x > wide)
|
2007-03-01 04:16:21 +03:00
|
|
|
cur = ~0;
|
2007-04-07 09:28:49 +04:00
|
|
|
if(cur == old)
|
2007-02-26 13:17:10 +03:00
|
|
|
break;
|
2007-03-01 05:18:26 +03:00
|
|
|
redraw(high, wide);
|
2007-02-26 13:17:10 +03:00
|
|
|
break;
|
|
|
|
case Expose:
|
2007-03-01 05:18:26 +03:00
|
|
|
redraw(high, wide);
|
2007-02-26 13:17:10 +03:00
|
|
|
break;
|
2010-10-08 00:31:41 +04:00
|
|
|
case MapNotify:
|
2008-10-17 20:08:44 +04:00
|
|
|
case ConfigureNotify:
|
|
|
|
case MappingNotify:
|
2007-02-26 13:17:10 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-10-17 02:54:03 +04:00
|
|
|
create_window(void)
|
|
|
|
{
|
|
|
|
WinAttr wa = { 0 };
|
|
|
|
|
|
|
|
wa.override_redirect = true;
|
|
|
|
menuwin = createwindow(&scr.root, Rect(-1, -1, 0, 0),
|
|
|
|
scr.depth, InputOutput,
|
|
|
|
&wa, CWOverrideRedirect);
|
|
|
|
selectinput(menuwin, MenuMask);
|
|
|
|
mapwin(menuwin);
|
|
|
|
if(!grabpointer(menuwin, nil, 0, MouseMask))
|
|
|
|
fatal("Failed to grab the mouse\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
size_window(int wide, int high)
|
2007-02-26 13:17:10 +03:00
|
|
|
{
|
2008-10-17 20:08:44 +04:00
|
|
|
Rectangle r;
|
2008-10-17 02:54:03 +04:00
|
|
|
Point p;
|
|
|
|
int h;
|
|
|
|
|
2007-03-01 05:18:26 +03:00
|
|
|
h = high * numitems;
|
2008-10-17 20:08:44 +04:00
|
|
|
r = Rect(0, 0, wide, h);
|
2007-03-01 05:18:26 +03:00
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
p = querypointer(&scr.root);
|
|
|
|
p.x -= wide / 2;
|
2009-10-22 15:07:10 +04:00
|
|
|
p.x = max(p.x, scr.rect.min.x);
|
|
|
|
p.x = min(p.x, scr.rect.max.x - wide);
|
2008-10-17 02:54:03 +04:00
|
|
|
|
|
|
|
p.y -= cur * high + high / 2;
|
2009-10-22 15:07:10 +04:00
|
|
|
p.y = max(p.y, scr.rect.min.y);
|
|
|
|
p.y = min(p.y, scr.rect.max.y - h);
|
2008-10-17 02:54:03 +04:00
|
|
|
|
2008-10-17 20:08:44 +04:00
|
|
|
reshapewin(menuwin, rectaddpt(r, p));
|
2010-06-20 22:24:04 +04:00
|
|
|
setborder(menuwin, 1, &cnorm.border);
|
2007-02-26 13:17:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-03-01 05:18:26 +03:00
|
|
|
redraw(int high, int wide)
|
2007-02-26 13:17:10 +03:00
|
|
|
{
|
2008-10-17 02:54:03 +04:00
|
|
|
Rectangle r;
|
|
|
|
int i;
|
2007-02-26 13:17:10 +03:00
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
r = Rect(0, 0, wide, high);
|
2007-04-07 09:28:49 +04:00
|
|
|
for(i = 0; i < numitems; i++) {
|
2008-10-17 02:54:03 +04:00
|
|
|
r = rectsetorigin(r, Pt(0, i * high));
|
2010-10-08 00:31:41 +04:00
|
|
|
fillstring(menuwin, font, r, Center, labels[i], (cur == i ? &csel : &cnorm), 0);
|
2007-02-26 13:17:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-03-01 05:18:26 +03:00
|
|
|
warpmouse(int wide, int high)
|
2007-02-26 13:17:10 +03:00
|
|
|
{
|
2008-10-17 02:54:03 +04:00
|
|
|
Point p;
|
2007-02-26 13:17:10 +03:00
|
|
|
int offset;
|
|
|
|
|
|
|
|
/* move tip of pointer into middle of menu item */
|
2008-10-17 02:54:03 +04:00
|
|
|
offset = labelh(font) / 2;
|
2007-02-26 13:17:10 +03:00
|
|
|
offset += 6; /* fudge factor */
|
|
|
|
|
2008-10-17 02:54:03 +04:00
|
|
|
p = Pt(wide / 2, cur*high - high/2 + offset);
|
|
|
|
p = addpt(p, menuwin->r.min);
|
|
|
|
|
|
|
|
warppointer(p);
|
2007-02-26 13:17:10 +03:00
|
|
|
}
|
2008-10-17 02:54:03 +04:00
|
|
|
|