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