Hi list,I've implemented embedder support, i.e. the host part, for st. This allows clients to embed into the st window and is useful if you start X applications from the terminal. For example:
$ surf -e $WINDOWIDThe behavior is similar to Plan 9 where applications can take over windows.. as far as this is possible in X ;).
The attached patch is against git master and I intent to put it into the wiki unless someone things it's worth for mainline.
Cheers Jochen
diff --git a/x.c b/x.c index bc3ad5a..ebe4b6a 100644 --- a/x.c +++ b/x.c @@ -66,6 +66,10 @@ static void ttysend(const Arg *); /* XEMBED messages */ #define XEMBED_FOCUS_IN 4 #define XEMBED_FOCUS_OUT 5 +#define XEMBED_EMBEDDED_NOTIFY 0 +#define XEMBED_WINDOW_ACTIVATE 1 +#define XEMBED_FOCUS_CURRENT 0 + /* macros */ #define IS_SET(flag) ((win.mode & (flag)) != 0) @@ -179,6 +183,9 @@ static void mousesel(XEvent *, int); static void mousereport(XEvent *); static char *kmap(KeySym, uint); static int match(uint, uint); +static void createnotify(XEvent *e); +static void destroynotify(XEvent *e); +static void sendxembed(long msg, long detail, long d1, long d2); static void run(void); static void usage(void); @@ -207,6 +214,8 @@ static void (*handler[LASTEvent])(XEvent *) = { */ [PropertyNotify] = propnotify, [SelectionRequest] = selrequest, + [CreateNotify] = createnotify, + [DestroyNotify] = destroynotify, }; /* Globals */ @@ -214,6 +223,7 @@ static DC dc; static XWindow xw; static XSelection xsel; static TermWindow win; +static Window embed; /* Font Ring Cache */ enum { @@ -706,6 +716,55 @@ cresize(int width, int height) ttyresize(win.tw, win.th); } +void +createnotify(XEvent *e) +{ + XWindowChanges wc; + + if (embed || e->xcreatewindow.override_redirect) + return; + + embed = e->xcreatewindow.window; + + XReparentWindow(xw.dpy, embed, xw.win, 0, 0); + XSelectInput(xw.dpy, embed, PropertyChangeMask | StructureNotifyMask | EnterWindowMask); + + XMapWindow(xw.dpy, embed); + sendxembed(XEMBED_EMBEDDED_NOTIFY, 0, xw.win, 0); + + wc.width = win.w; + wc.height = win.h; + XConfigureWindow(xw.dpy, embed, CWWidth | CWHeight, &wc); + + XSetInputFocus(xw.dpy, embed, RevertToParent, CurrentTime); +} + +void +destroynotify(XEvent *e) +{ + visibility(e); + if (embed == e->xdestroywindow.window) { + focus(e); + } +} + +void +sendxembed(long msg, long detail, long d1, long d2) +{ + XEvent e = { 0 }; + + e.xclient.window = embed; + e.xclient.type = ClientMessage; + e.xclient.message_type = xw.xembed; + e.xclient.format = 32; + e.xclient.data.l[0] = CurrentTime; + e.xclient.data.l[1] = msg; + e.xclient.data.l[2] = detail; + e.xclient.data.l[3] = d1; + e.xclient.data.l[4] = d2; + XSendEvent(xw.dpy, embed, False, NoEventMask, &e); +} + void xresize(int col, int row) { @@ -1097,7 +1156,8 @@ xinit(int cols, int rows) xw.attrs.bit_gravity = NorthWestGravity; xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask + | SubstructureNotifyMask | SubstructureRedirectMask; xw.attrs.colormap = xw.cmap; if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) @@ -1625,6 +1685,11 @@ visibility(XEvent *ev) void unmap(XEvent *ev) { + if (embed == ev->xunmap.window) { + embed = 0; + XRaiseWindow(xw.dpy, xw.win); + XSetInputFocus(xw.dpy, xw.win, RevertToParent, CurrentTime); + } win.mode &= ~MODE_VISIBLE; } @@ -1678,6 +1743,13 @@ focus(XEvent *ev) { XFocusChangeEvent *e = &ev->xfocus; + if (embed && ev->type == FocusIn) { + XRaiseWindow(xw.dpy, embed); + XSetInputFocus(xw.dpy, embed, RevertToParent, CurrentTime); + sendxembed(XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0); + sendxembed(XEMBED_WINDOW_ACTIVATE, 0, 0, 0); + } + if (e->mode == NotifyGrab) return; @@ -1808,9 +1880,17 @@ cmessage(XEvent *e) void resize(XEvent *e) { + XWindowChanges wc; + if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) return; + if (embed) { + wc.width = e->xconfigure.width; + wc.height = e->xconfigure.height; + XConfigureWindow(xw.dpy, embed, CWWidth | CWHeight, &wc); + } + cresize(e->xconfigure.width, e->xconfigure.height); }
signature.asc
Description: PGP signature