wmii/cmd/x11/wmii9menu.c

285 lines
5.6 KiB
C
Raw Normal View History

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
*/
/*
* Heavily modified by Kris Maglione for use with wmii.
*/
#define IXP_NO_P9_
#define IXP_P9_STRUCTS
2008-10-17 03:05:17 +04:00
#include <fmt.h>
#include <ixp.h>
2008-08-25 20:47:56 +04:00
#include <stdarg.h>
#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
char version[] = "wmii9menu-"VERSION" "COPYRIGHT", ©1994 David Hogan, Arnold Robbins";
2007-02-26 13:17:10 +03: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
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);
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);
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))
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
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
initdisplay();
xext_init();
init_screens();
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();
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);
}
enum {
2010-10-08 00:31:41 +04:00
MouseMask = ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
| PointerMotionMask,
MenuMask = MouseMask
| StructureNotifyMask
| ExposureMask
};
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;
int i, old, wide, high;
2007-02-26 13:17:10 +03:00
high = labelh(font);
2010-10-08 00:31:41 +04:00
wide = 0;
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);
warpmouse(wide, high);
2007-04-07 09:28:49 +04:00
for(;;) {
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:
i = ev.xbutton.y / high;
2007-04-07 09:28:49 +04:00
if(ev.xbutton.x < 0 || ev.xbutton.x > wide)
return;
2007-04-07 09:28:49 +04:00
else if(i < 0 || i >= numitems)
return;
2010-06-06 13:07:24 +04:00
lprint(1, "%s\n", commands[i]);
2007-02-26 13:17:10 +03:00
return;
case ButtonPress:
2007-02-26 13:17:10 +03:00
case MotionNotify:
old = cur;
cur = ev.xbutton.y / high;
2007-04-07 09:28:49 +04:00
if(ev.xbutton.x < 0 || ev.xbutton.x > wide)
cur = ~0;
2007-04-07 09:28:49 +04:00
if(cur == old)
2007-02-26 13:17:10 +03:00
break;
redraw(high, wide);
2007-02-26 13:17:10 +03:00
break;
case Expose:
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
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;
Point p;
int h;
h = high * numitems;
2008-10-17 20:08:44 +04:00
r = Rect(0, 0, wide, h);
p = querypointer(&scr.root);
p.x -= wide / 2;
p.x = max(p.x, scr.rect.min.x);
p.x = min(p.x, scr.rect.max.x - wide);
p.y -= cur * high + high / 2;
p.y = max(p.y, scr.rect.min.y);
p.y = min(p.y, scr.rect.max.y - h);
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
redraw(int high, int wide)
2007-02-26 13:17:10 +03:00
{
Rectangle r;
int i;
2007-02-26 13:17:10 +03:00
r = Rect(0, 0, wide, high);
2007-04-07 09:28:49 +04:00
for(i = 0; i < numitems; i++) {
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
warpmouse(int wide, int high)
2007-02-26 13:17:10 +03:00
{
Point p;
2007-02-26 13:17:10 +03:00
int offset;
/* move tip of pointer into middle of menu item */
offset = labelh(font) / 2;
2007-02-26 13:17:10 +03:00
offset += 6; /* fudge factor */
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
}