add embedding support with -w option
							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; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue