On Sat, 3 Sep 2011 22:38:34 +0200, Aurélien Aptel <aurelien.ap...@gmail.com> 
wrote:
> Hi,
> 
> I currently have no *nix computer at hand to test your patch. This
> behaviour was introduced to make focus work inside tabbed. It has the
> side effect your describing. I didn't find the right way to know
> whether the window has *keyboard* focus or not when it's embed.
> I you manage to make it work in every case I'll apply your patch.

According to the documentation[^1], the embedding application is supposed to
send a ClientMessage XEvent with major opcodes of XEMBED_FOCUS_IN and
XEMBED_FOCUS_OUT. I've attached a patch that should add detection of these
events to st. Unfortunately, I'm unable to properly test them with tabbed
because it seems tabbed doesn't send any XEMBED_FOCUS_OUT events. The
current effect in tabbed is that the cursor is always shown, which seems an
acceptable state until tabbed can be improved.

[^1]: http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html

I should add that I don't really know C, so you should probably look the
patch over with extra care. :)
diff -r 1c8e6796c6fe st.c
--- a/st.c	Sun Aug 14 17:15:19 2011 +0200
+++ b/st.c	Sun Sep 04 01:47:36 2011 +0100
@@ -37,6 +37,10 @@
 	"st-" VERSION ", (c) 2010-2011 st engineers\n" \
 	"usage: st [-t title] [-c class] [-w windowid] [-v] [-e command...]\n"
 
+/* XEMBED messages */
+#define XEMBED_FOCUS_IN  4
+#define XEMBED_FOCUS_OUT 5
+
 /* Arbitrary sizes */
 #define ESC_TITLE_SIZ 256
 #define ESC_BUF_SIZ   256
@@ -219,6 +223,7 @@
 static void unmap(XEvent *);
 static char* kmap(KeySym, unsigned int state);
 static void kpress(XEvent *);
+static void cmessage(XEvent *);
 static void resize(XEvent *);
 static void focus(XEvent *);
 static void brelease(XEvent *);
@@ -239,12 +244,11 @@
 
 static void (*handler[LASTEvent])(XEvent *) = {
 	[KeyPress] = kpress,
+	[ClientMessage] = cmessage,
 	[ConfigureNotify] = resize,
 	[VisibilityNotify] = visibility,
 	[UnmapNotify] = unmap,
 	[Expose] = expose,
-	[EnterNotify] = focus,
-	[LeaveNotify] = focus,
 	[FocusIn] = focus,
 	[FocusOut] = focus,
 	[MotionNotify] = bmotion,
@@ -266,6 +270,7 @@
 static char *opt_title = NULL;
 static char *opt_embed = NULL;
 static char *opt_class = NULL;
+static Atom xembedatom;
 
 int
 utf8decode(char *s, long *u) {
@@ -1668,6 +1673,8 @@
 		&(XColor){.red = 0xffff, .green = 0xffff, .blue = 0xffff},
 		&(XColor){.red = 0x0000, .green = 0x0000, .blue = 0x0000});
 
+	xembedatom = XInternAtom(xw.dpy, "_XEMBED", False);
+
 	XStoreName(xw.dpy, xw.win, opt_title ? opt_title : "st");
 	XMapWindow(xw.dpy, xw.win);
 	xhints();
@@ -1824,7 +1831,7 @@
 
 void
 focus(XEvent *ev) {
-	if(ev->type == FocusIn || ev->type == EnterNotify) {
+	if(ev->type == FocusIn) {
 		xw.state |= WIN_FOCUSED;
 		xseturgency(0);
 	} else
@@ -1895,6 +1902,19 @@
 }
 
 void
+cmessage(XEvent *e) {
+	if (e->xclient.message_type == xembedatom && e->xclient.format == 32) {
+		if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) {
+			xw.state |= WIN_FOCUSED;
+			xseturgency(0);
+		} else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) {
+			xw.state &= ~WIN_FOCUSED;
+		}
+		draw();
+	}
+}
+
+void
 resize(XEvent *e) {
 	int col, row;
 	

Reply via email to