commit 352170eec845cb8fdf1c4ae92a9108eb5ebd0509
parent e76c4c0637a0a57adc562ccad7a80fcecee8f22d
Author: bakkeby <bakkeby@gmail.com>
Date: Tue, 7 Jan 2020 08:05:00 +0100
Adding st embedder patch
Diffstat:
7 files changed, 117 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
@@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
### Changelog:
+2020-01-07 - Added st embedder patch
+
2019-10-16 - Introduced [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer)
2019-09-17 - Added relativeborder, fix-keyboard-input, iso14755, visualbell, right-click-to-plumb, boxdraw and keyboard-select patches
@@ -81,6 +83,10 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
- [scrollback](https://st.suckless.org/patches/scrollback/)
- allows you scroll back through terminal output using keyboard shortcuts or mousewheel
+ - st-embedder
+ - this patch allows clients to embed into the st window and can be useful if you tend to start X applications from the terminal
+ - the behavior is similar to Plan 9 where applications can take over windows
+
- [spoiler](https://st.suckless.org/patches/spoiler/)
- use inverted defaultbg/fg for selection when bg/fg are the same
diff --git a/patch/st_embedder_x.c b/patch/st_embedder_x.c
@@ -0,0 +1,50 @@
+static Window embed;
+
+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);
+}
diff --git a/patch/st_embedder_x.h b/patch/st_embedder_x.h
@@ -0,0 +1,7 @@
+#define XEMBED_EMBEDDED_NOTIFY 0
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_FOCUS_CURRENT 0
+
+static void createnotify(XEvent *e);
+static void destroynotify(XEvent *e);
+static void sendxembed(long msg, long detail, long d1, long d2);
+\ No newline at end of file
diff --git a/patch/x_include.c b/patch/x_include.c
@@ -17,6 +17,9 @@
#if RIGHTCLICKTOPLUMB_PATCH
#include "rightclicktoplumb_x.c"
#endif
+#if ST_EMBEDDER_PATCH
+#include "st_embedder_x.c"
+#endif
#if VISUALBELL_2_PATCH || VISUALBELL_3_PATCH
#include "visualbell.c"
#endif
diff --git a/patch/x_include.h b/patch/x_include.h
@@ -14,6 +14,9 @@
#if RIGHTCLICKTOPLUMB_PATCH
#include "rightclicktoplumb_x.h"
#endif
+#if ST_EMBEDDER_PATCH
+#include "st_embedder_x.h"
+#endif
#if VISUALBELL_2_PATCH || VISUALBELL_3_PATCH
#include "visualbell.h"
#endif
diff --git a/patches.h b/patches.h
@@ -136,6 +136,16 @@
*/
#define SCROLLBACK_MOUSE_ALTSCREEN_PATCH 0
+/* This patch allows clients to embed into the st window and is useful if you tend to
+ * start X applications from the terminal. For example:
+ *
+ * $ surf -e $WINDOWID
+ *
+ * The behavior is similar to Plan 9 where applications can take over windows.
+ * URL TBC
+ */
+#define ST_EMBEDDER_PATCH 0
+
/* Use inverted defaultbg/fg for selection when bg/fg are the same.
* https://st.suckless.org/patches/spoiler/
*/
diff --git a/x.c b/x.c
@@ -227,6 +227,10 @@ static void (*handler[LASTEvent])(XEvent *) = {
*/
[PropertyNotify] = propnotify,
[SelectionRequest] = selrequest,
+ #if ST_EMBEDDER_PATCH
+ [CreateNotify] = createnotify,
+ [DestroyNotify] = destroynotify,
+ #endif // ST_EMBEDDER_PATCH
};
/* Globals */
@@ -1189,7 +1193,11 @@ xinit(int cols, int rows)
| KeyReleaseMask
#endif // FIXIME_PATCH
| ExposureMask | VisibilityChangeMask | StructureNotifyMask
- | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
+ | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask
+ #if ST_EMBEDDER_PATCH
+ | SubstructureNotifyMask | SubstructureRedirectMask
+ #endif // ST_EMBEDDER_PATCH
+ ;
xw.attrs.colormap = xw.cmap;
#if !ALPHA_PATCH
@@ -1889,6 +1897,13 @@ visibility(XEvent *ev)
void
unmap(XEvent *ev)
{
+ #if ST_EMBEDDER_PATCH
+ if (embed == ev->xunmap.window) {
+ embed = 0;
+ XRaiseWindow(xw.dpy, xw.win);
+ XSetInputFocus(xw.dpy, xw.win, RevertToParent, CurrentTime);
+ }
+ #endif // ST_EMBEDDER_PATCH
win.mode &= ~MODE_VISIBLE;
}
@@ -1960,6 +1975,15 @@ focus(XEvent *ev)
{
XFocusChangeEvent *e = &ev->xfocus;
+ #if ST_EMBEDDER_PATCH
+ 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);
+ }
+ #endif // ST_EMBEDDER_PATCH
+
if (e->mode == NotifyGrab)
return;
@@ -2108,9 +2132,21 @@ cmessage(XEvent *e)
void
resize(XEvent *e)
{
+ #if ST_EMBEDDER_PATCH
+ XWindowChanges wc;
+ #endif // ST_EMBEDDER_PATCH
+
if (e->xconfigure.width == win.w && e->xconfigure.height == win.h)
return;
+ #if ST_EMBEDDER_PATCH
+ if (embed) {
+ wc.width = e->xconfigure.width;
+ wc.height = e->xconfigure.height;
+ XConfigureWindow(xw.dpy, embed, CWWidth | CWHeight, &wc);
+ }
+ #endif // ST_EMBEDDER_PATCH
+
cresize(e->xconfigure.width, e->xconfigure.height);
}