  } Arg;
  
  void die(const char *, ...);
-+void redrawcursor(void);
++void redrawcursor(int);
  void redraw(void);
  void draw(void);
  

+	if (!XkbQueryExtension(xw.dpy, &xkb_opcode, &xkb_event_base, &xkb_error_base, &xkb_major, &xkb_minor)) {
+		die("Xkb server extension is not available (or incompatible)\n");
+	}
+	if (!XkbSelectEventDetails(xw.dpy, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask)) {
+		die("Xkb subscribe to events gone wrong\n");
+	}
+
 	ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd);
 	cresize(w, h);
 
@@ -2280,6 +2297,27 @@ run(void)
 			if (XFilterEvent(&ev, None))
 				continue;
 			if (LASTEvent <= ev.type) {
+				if (xkb_event_base == ev.type) {
+					// NOTE: keep cursor unchanged for other background windows
+					// INFO: xkb events are broadcasted regardless of kbd focus
+					if (!(IS_SET(MODE_FOCUSED)))
+						continue;
+					if (XkbStateNotify != ((XkbAnyEvent *)&ev)->xkb_type) {
+						fprintf(stderr, "Xkb unexpected event\n");
+						continue;
+					}
+					// MAYBE:ENH: map color to lang code "en" instead of index
+					//   SEE: libkbdd.c:569: _kbdd_group_names_initialize
+					int grp = ((XkbStateNotifyEvent*)&ev)->group;
+					// DEBUG: fprintf(stderr, "Xkb lang group[0-3]: %d\n", grp);
+					if (grp < 0 || grp > 3) {
+						fprintf(stderr, "Xkb invalid lang group: %d\n", grp);
+						continue;
+					}
+					defaultcs = xkbbasecolor + grp;
+					redrawcursor();
+					continue;
+				}
 				if (rr_event_base + RRNotify == ev.type &&

index a1e7d23..27a1a57 100644
--- i/st.c
+++ w/st.c
@@ -2755,6 +2755,24 @@ draw(void)
 		xximspot(term.ocx, term.ocy);
 }
 
+void
+redrawcursor(int grp)
+{
+	// DEBUG: fprintf(stderr, "Xkb lang group[0-3]: %d\n", grp);
+	if (grp < 0 || grp > 3)
+		die("Xkb unlikely invalid lang group: %d\n", grp);
+	if (defaultcs == xkbbasecolor + grp)
+		return;  // NOTE: prevent unnecessary redraw
+	// MAYBE:ENH: map color to lang code "en" instead of index
+	//   SEE: libkbdd.c:569: _kbdd_group_names_initialize
+	defaultcs = xkbbasecolor + grp;
+	if (!xstartdraw())
+		return;
+	xdrawcursor(term.c.x, term.c.y, term.line[term.c.y][term.c.x],
