x: fix XIM handling
Do not try to set specific IM method, let the user specify it with XMODIFIERS. If the requested method is not available or opening fails, fallback to the default input handler and register a handler on the new IM server availability signal. Do the same when the input server is closed and (re)started.
This commit is contained in:
		
				
					committed by
					
						 Hiltjo Posthuma
						Hiltjo Posthuma
					
				
			
			
				
	
			
			
			
						parent
						
							cd785755f2
						
					
				
				
					commit
					26cdfebf31
				
			
							
								
								
									
										60
									
								
								x.c
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								x.c
									
									
									
									
									
								
							| @@ -146,9 +146,10 @@ static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); | ||||
| static void xdrawglyph(Glyph, int, int); | ||||
| static void xclear(int, int, int, int); | ||||
| static int xgeommasktogravity(int); | ||||
| static void ximopen(Display *); | ||||
| static int ximopen(Display *); | ||||
| static void ximinstantiate(Display *, XPointer, XPointer); | ||||
| static void ximdestroy(XIM, XPointer, XPointer); | ||||
| static int xicdestroy(XIC, XPointer, XPointer); | ||||
| static void xinit(int, int); | ||||
| static void cresize(int, int); | ||||
| static void xresize(int, int); | ||||
| @@ -1025,34 +1026,41 @@ xunloadfonts(void) | ||||
| 	xunloadfont(&dc.ibfont); | ||||
| } | ||||
|  | ||||
| void | ||||
| int | ||||
| ximopen(Display *dpy) | ||||
| { | ||||
| 	XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy }; | ||||
| 	XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; | ||||
| 	XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; | ||||
|  | ||||
| 	if ((xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { | ||||
| 		XSetLocaleModifiers("@im=local"); | ||||
| 		if ((xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { | ||||
| 			XSetLocaleModifiers("@im="); | ||||
| 			if ((xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) | ||||
| 				die("XOpenIM failed. Could not open input device.\n"); | ||||
| 		} | ||||
| 	} | ||||
| 	if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &destroy, NULL) != NULL) | ||||
| 		die("XSetIMValues failed. Could not set input method value.\n"); | ||||
| 	xw.xic = XCreateIC(xw.ime.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, | ||||
| 	                   XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL); | ||||
| 	if (xw.xic == NULL) | ||||
| 		die("XCreateIC failed. Could not obtain input method.\n"); | ||||
| 	xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); | ||||
| 	if (xw.ime.xim == NULL) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) | ||||
| 		fprintf(stderr, "XSetIMValues: " | ||||
| 		                "Could not set XNDestroyCallback.\n"); | ||||
|  | ||||
| 	xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, | ||||
| 	                                      NULL); | ||||
|  | ||||
| 	if (xw.ime.xic == NULL) { | ||||
| 		xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, | ||||
| 		                       XIMPreeditNothing | XIMStatusNothing, | ||||
| 		                       XNClientWindow, xw.win, | ||||
| 		                       XNFocusWindow, xw.win, | ||||
| 		                       XNDestroyCallback, &icdestroy, | ||||
| 		                       NULL); | ||||
| 	} | ||||
| 	if (xw.ime.xic == NULL) | ||||
| 		fprintf(stderr, "XCreateIC: Could not create input context.\n"); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| void | ||||
| ximinstantiate(Display *dpy, XPointer client, XPointer call) | ||||
| { | ||||
| 	ximopen(dpy); | ||||
| 	if (ximopen(dpy)) | ||||
| 		XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, | ||||
| 		                                 ximinstantiate, NULL); | ||||
| } | ||||
| @@ -1061,12 +1069,18 @@ void | ||||
| ximdestroy(XIM xim, XPointer client, XPointer call) | ||||
| { | ||||
| 	xw.ime.xim = NULL; | ||||
| 	xw.ime.xic = NULL; | ||||
| 	XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, | ||||
| 	                               ximinstantiate, NULL); | ||||
| 	XFree(xw.ime.spotlist); | ||||
| } | ||||
|  | ||||
| int | ||||
| xicdestroy(XIC xim, XPointer client, XPointer call) | ||||
| { | ||||
| 	xw.ime.xic = NULL; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| void | ||||
| xinit(int cols, int rows) | ||||
| { | ||||
| @@ -1132,7 +1146,10 @@ xinit(int cols, int rows) | ||||
| 	xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); | ||||
|  | ||||
| 	/* input methods */ | ||||
| 	ximopen(xw.dpy); | ||||
| 	if (!ximopen(xw.dpy)) { | ||||
| 		XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, | ||||
| 	                                       ximinstantiate, NULL); | ||||
| 	} | ||||
|  | ||||
| 	/* white cursor, black outline */ | ||||
| 	cursor = XCreateFontCursor(xw.dpy, mouseshape); | ||||
| @@ -1765,7 +1782,10 @@ kpress(XEvent *ev) | ||||
| 	if (IS_SET(MODE_KBDLOCK)) | ||||
| 		return; | ||||
|  | ||||
| 	if (xw.ime.xic) | ||||
| 		len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); | ||||
| 	else | ||||
| 		len = XLookupString(e, buf, sizeof buf, &ksym, NULL); | ||||
| 	/* 1. shortcuts */ | ||||
| 	for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { | ||||
| 		if (ksym == bp->keysym && match(bp->mod, e->state)) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user