diff options
author | Jochen Sprickerhof <suckless@jochen.sprickerhof.de> | 2024-02-01 06:16:04 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2024-02-03 16:09:35 +0300 |
commit | 1b61390375255529635d627397d3f759357d8613 (patch) | |
tree | 348e77c7d028702e5fe795422a63519c18e2d2c1 | |
parent | a6d484d8723d493bc09a5122128aaea729adaa80 (diff) | |
download | st-fork-1b61390375255529635d627397d3f759357d8613.tar.gz |
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 $WINDOWID
The 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
Source: https://lists.suckless.org/hackers/2001/17072.html
-rw-r--r-- | x.c | 82 |
1 files changed, 81 insertions, 1 deletions
@@ -69,6 +69,10 @@ void kscrolldown(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) @@ -188,6 +192,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); @@ -216,6 +223,8 @@ static void (*handler[LASTEvent])(XEvent *) = { */ [PropertyNotify] = propnotify, [SelectionRequest] = selrequest, + [CreateNotify] = createnotify, + [DestroyNotify] = destroynotify, }; /* Globals */ @@ -223,6 +232,7 @@ static DC dc; static XWindow xw; static XSelection xsel; static TermWindow win; +static Window embed; /* Font Ring Cache */ enum { @@ -750,6 +760,55 @@ cresize(int width, int height) } 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) { win.tw = col * win.cw; @@ -1170,7 +1229,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)))) @@ -1720,6 +1780,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; } @@ -1772,6 +1837,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; @@ -1910,9 +1982,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); } |