add embedding support with -w option
This commit is contained in:
		
				
					committed by
					
						
						Hiltjo Posthuma
					
				
			
			
				
	
			
			
			
						parent
						
							a97f550aa7
						
					
				
				
					commit
					a9a5c6cc2d
				
			
							
								
								
									
										5
									
								
								dmenu.1
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								dmenu.1
									
									
									
									
									
								
							@@ -20,6 +20,8 @@ dmenu \- dynamic menu
 | 
			
		||||
.IR color ]
 | 
			
		||||
.RB [ \-sf
 | 
			
		||||
.IR color ]
 | 
			
		||||
.RB [ \-w
 | 
			
		||||
.IR windowid ]
 | 
			
		||||
.P
 | 
			
		||||
.BR dmenu_run " ..."
 | 
			
		||||
.SH DESCRIPTION
 | 
			
		||||
@@ -75,6 +77,9 @@ defines the selected foreground color.
 | 
			
		||||
.TP
 | 
			
		||||
.B \-v
 | 
			
		||||
prints version information to stdout, then exits.
 | 
			
		||||
.TP
 | 
			
		||||
.BI \-w " windowid"
 | 
			
		||||
embed into windowid.
 | 
			
		||||
.SH USAGE
 | 
			
		||||
dmenu is completely controlled by the keyboard.  Items are selected using the
 | 
			
		||||
arrow keys, page up, page down, home, and end.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										65
									
								
								dmenu.c
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								dmenu.c
									
									
									
									
									
								
							@@ -34,8 +34,8 @@ struct item {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static char text[BUFSIZ] = "";
 | 
			
		||||
static char *embed;
 | 
			
		||||
static int bh, mw, mh;
 | 
			
		||||
static int sw, sh; /* X display screen geometry width, height */
 | 
			
		||||
static int inputw = 0, promptw;
 | 
			
		||||
static int lrpad; /* sum of left and right padding */
 | 
			
		||||
static size_t cursor;
 | 
			
		||||
@@ -46,7 +46,7 @@ static int mon = -1, screen;
 | 
			
		||||
 | 
			
		||||
static Atom clip, utf8;
 | 
			
		||||
static Display *dpy;
 | 
			
		||||
static Window root, win;
 | 
			
		||||
static Window root, parentwin, win;
 | 
			
		||||
static XIC xic;
 | 
			
		||||
 | 
			
		||||
static Drw *drw;
 | 
			
		||||
@@ -174,12 +174,31 @@ drawmenu(void)
 | 
			
		||||
	drw_map(drw, win, 0, 0, mw, mh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
grabfocus(void)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000  };
 | 
			
		||||
	Window focuswin;
 | 
			
		||||
	int i, revertwin;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 100; ++i) {
 | 
			
		||||
		XGetInputFocus(dpy, &focuswin, &revertwin);
 | 
			
		||||
		if (focuswin == win)
 | 
			
		||||
			return;
 | 
			
		||||
		XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
 | 
			
		||||
		nanosleep(&ts, NULL);
 | 
			
		||||
	}
 | 
			
		||||
	die("cannot grab focus");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
grabkeyboard(void)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000  };
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	if (embed)
 | 
			
		||||
		return;
 | 
			
		||||
	/* try to grab keyboard, we may have to wait for another process to ungrab */
 | 
			
		||||
	for (i = 0; i < 1000; i++) {
 | 
			
		||||
		if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
 | 
			
		||||
@@ -497,6 +516,11 @@ run(void)
 | 
			
		||||
			if (ev.xexpose.count == 0)
 | 
			
		||||
				drw_map(drw, win, 0, 0, mw, mh);
 | 
			
		||||
			break;
 | 
			
		||||
		case FocusIn:
 | 
			
		||||
			/* regrab focus from parent window */
 | 
			
		||||
			if (ev.xfocus.window != win)
 | 
			
		||||
				grabfocus();
 | 
			
		||||
			break;
 | 
			
		||||
		case KeyPress:
 | 
			
		||||
			keypress(&ev.xkey);
 | 
			
		||||
			break;
 | 
			
		||||
@@ -539,7 +563,7 @@ setup(void)
 | 
			
		||||
	lines = MAX(lines, 0);
 | 
			
		||||
	mh = (lines + 1) * bh;
 | 
			
		||||
#ifdef XINERAMA
 | 
			
		||||
	if ((info = XineramaQueryScreens(dpy, &n))) {
 | 
			
		||||
	if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
 | 
			
		||||
		XGetInputFocus(dpy, &w, &di);
 | 
			
		||||
		if (mon >= 0 && mon < n)
 | 
			
		||||
			i = mon;
 | 
			
		||||
@@ -570,9 +594,12 @@ setup(void)
 | 
			
		||||
	} else
 | 
			
		||||
#endif
 | 
			
		||||
	{
 | 
			
		||||
		if (!XGetWindowAttributes(dpy, parentwin, &wa))
 | 
			
		||||
			die("could not get embedding window attributes: 0x%lx",
 | 
			
		||||
			    parentwin);
 | 
			
		||||
		x = 0;
 | 
			
		||||
		y = topbar ? 0 : sh - mh;
 | 
			
		||||
		mw = sw;
 | 
			
		||||
		y = topbar ? 0 : wa.height - mh;
 | 
			
		||||
		mw = wa.width;
 | 
			
		||||
	}
 | 
			
		||||
	promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
 | 
			
		||||
	inputw = MIN(inputw, mw/3);
 | 
			
		||||
@@ -582,9 +609,8 @@ setup(void)
 | 
			
		||||
	swa.override_redirect = True;
 | 
			
		||||
	swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
 | 
			
		||||
	swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
 | 
			
		||||
	win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
 | 
			
		||||
	                    DefaultDepth(dpy, screen), CopyFromParent,
 | 
			
		||||
	                    DefaultVisual(dpy, screen),
 | 
			
		||||
	win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
 | 
			
		||||
	                    CopyFromParent, CopyFromParent, CopyFromParent,
 | 
			
		||||
	                    CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
 | 
			
		||||
 | 
			
		||||
	/* open input methods */
 | 
			
		||||
@@ -593,6 +619,15 @@ setup(void)
 | 
			
		||||
	                XNClientWindow, win, XNFocusWindow, win, NULL);
 | 
			
		||||
 | 
			
		||||
	XMapRaised(dpy, win);
 | 
			
		||||
	if (embed) {
 | 
			
		||||
		XSelectInput(dpy, parentwin, FocusChangeMask);
 | 
			
		||||
		if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
 | 
			
		||||
			for (i = 0; i < du && dws[i] != win; ++i)
 | 
			
		||||
				XSelectInput(dpy, dws[i], FocusChangeMask);
 | 
			
		||||
			XFree(dws);
 | 
			
		||||
		}
 | 
			
		||||
		grabfocus();
 | 
			
		||||
	}
 | 
			
		||||
	drw_resize(drw, mw, mh);
 | 
			
		||||
	drawmenu();
 | 
			
		||||
}
 | 
			
		||||
@@ -601,13 +636,14 @@ static void
 | 
			
		||||
usage(void)
 | 
			
		||||
{
 | 
			
		||||
	fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
 | 
			
		||||
	      "             [-nb color] [-nf color] [-sb color] [-sf color]\n", stderr);
 | 
			
		||||
	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
 | 
			
		||||
	exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	XWindowAttributes wa;
 | 
			
		||||
	int i, fast = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 1; i < argc; i++)
 | 
			
		||||
@@ -641,6 +677,8 @@ main(int argc, char *argv[])
 | 
			
		||||
			colors[SchemeSel][ColBg] = argv[++i];
 | 
			
		||||
		else if (!strcmp(argv[i], "-sf"))  /* selected foreground color */
 | 
			
		||||
			colors[SchemeSel][ColFg] = argv[++i];
 | 
			
		||||
		else if (!strcmp(argv[i], "-w"))   /* embedding window id */
 | 
			
		||||
			embed = argv[++i];
 | 
			
		||||
		else
 | 
			
		||||
			usage();
 | 
			
		||||
 | 
			
		||||
@@ -650,9 +688,12 @@ main(int argc, char *argv[])
 | 
			
		||||
		die("cannot open display");
 | 
			
		||||
	screen = DefaultScreen(dpy);
 | 
			
		||||
	root = RootWindow(dpy, screen);
 | 
			
		||||
	sw = DisplayWidth(dpy, screen);
 | 
			
		||||
	sh = DisplayHeight(dpy, screen);
 | 
			
		||||
	drw = drw_create(dpy, screen, root, sw, sh);
 | 
			
		||||
	if (!embed || !(parentwin = strtol(embed, NULL, 0)))
 | 
			
		||||
		parentwin = root;
 | 
			
		||||
	if (!XGetWindowAttributes(dpy, parentwin, &wa))
 | 
			
		||||
		die("could not get embedding window attributes: 0x%lx",
 | 
			
		||||
		    parentwin);
 | 
			
		||||
	drw = drw_create(dpy, screen, root, wa.width, wa.height);
 | 
			
		||||
	if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
 | 
			
		||||
		die("no fonts could be loaded.");
 | 
			
		||||
	lrpad = drw->fonts->h;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user