Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Fluxbox show "(on $HOSTNAME)" if X11 forwarded program

I solved my problem from last time! I wrote a patch for Fluxbox to add the "(on $CLIENT)" message to titlebars of X11-forwarded client windows. See the source, and the debian/ for building a dpkg on my cgit instance (master branch).

Just in case that ever goes away (and somehow this blog doesn't), here's the source:

Author: bgstack15
Date: 2022-11-09
Version: fluxbox 1.4.0
Source: original
Summary: Add "(on $CLIENT)" to titlebar for forwarded windows
Message: 
Inspired by xfwm4's ability to display the remote host running an X11 window. This fails on xfe which somehow lacks the WM_CLIENT_MACHINE property.
--- a/src/Xutil.cc
+++ b/src/Xutil.cc
@@ -43,6 +43,51 @@ using std::endl;

 namespace Xutil {

+FbTk::FbString getWMClientMachine(Window window) {
+
+    if (window == None)
+        return FbTk::FbString("");
+
+    Display *display = FbTk::App::instance()->display();
+
+    XTextProperty text_prop;
+    text_prop.value = 0;
+    char **list = 0;
+    int num = 0;
+    _FB_USES_NLS;
+    FbTk::FbString name;
+
+    if (XGetWMClientMachine(display, window, &text_prop)) {
+        if (text_prop.value && text_prop.nitems > 0) {
+            if (text_prop.encoding != XA_STRING) {
+
+                text_prop.nitems = strlen((char *) text_prop.value);
+                XmbTextPropertyToTextList(display, &text_prop, &list, &num);
+
+                if (num > 0 && list != 0)
+                    name = FbTk::FbStringUtil::LocaleStrToFb(static_cast<char *>(*list));
+                else
+                    name = text_prop.value ? FbTk::FbStringUtil::XStrToFb((char *)text_prop.value) : "";
+
+                if (list)
+                    XFreeStringList(list);
+
+            } else
+                name = text_prop.value ? FbTk::FbStringUtil::XStrToFb((char *)text_prop.value) : "";
+
+            XFree(text_prop.value);
+
+        } else { // default name
+            name = _FB_XTEXT(Window, Unnamed, "Unnamed", "Default name for a window without a WM_NAME");
+        }
+    } else {
+        // default name
+        name = _FB_XTEXT(Window, Unnamed, "Unnamed", "Default name for a window without a WM_NAME");
+    }
+
+    return name;
+}
+
 FbTk::FbString getWMName(Window window) {

     if (window == None)
--- a/src/Xutil.hh
+++ b/src/Xutil.hh
@@ -28,6 +28,7 @@

 namespace Xutil {

+FbTk::FbString getWMClientMachine(Window window);
 FbTk::FbString getWMName(Window window);

 FbTk::FbString getWMClassName(Window win);
--- a/src/WinClient.cc
+++ b/src/WinClient.cc
@@ -49,6 +49,7 @@
 #else
   #include <string.h>
 #endif
+#include<unistd.h>

 using std::string;
 using std::list;
@@ -217,6 +218,10 @@ bool WinClient::getAttrib(XWindowAttribu
     return XGetWindowAttributes(display(), window(), &attr);
 }

+bool WinClient::getWMClientMachine(XTextProperty &textprop) const {
+    return XGetWMClientMachine(display(), window(), &textprop);
+}
+
 bool WinClient::getWMName(XTextProperty &textprop) const {
     return XGetWMName(display(), window(), &textprop);
 }
@@ -319,7 +324,14 @@ void WinClient::updateTitle() {
     if (m_title_override)
         return;

-    m_title.setLogical(FbTk::FbString(Xutil::getWMName(window()), 0, 512));
+    FbTk::FbString fullname = FbTk::FbString(Xutil::getWMName(window()), 0, 512);
+    FbTk::FbString clientmachine = FbTk::FbString(Xutil::getWMClientMachine(window()), 0, 512);
+    char *host = new char[512]; gethostname(host, 512);
+    FbTk::FbString hostname = FbTk::FbString(host);
+    if (clientmachine != "Unnamed" && clientmachine != "" && clientmachine != hostname) {
+        fullname += " (on " + clientmachine + ")";
+    }
+    m_title.setLogical(fullname);
     m_title_update_timer.start();
 }

@@ -328,7 +340,14 @@ void WinClient::emitTitleSig() {
 }

 void WinClient::setTitle(const FbTk::FbString &title) {
-    m_title.setLogical(title);
+    FbTk::FbString fullname = title;
+    FbTk::FbString clientmachine = FbTk::FbString(Xutil::getWMClientMachine(window()), 0, 512);
+    char *host = new char[512]; gethostname(host, 512);
+    FbTk::FbString hostname = FbTk::FbString(host);
+    if (clientmachine != "Unnamed" && clientmachine != "" && clientmachine != hostname) {
+        fullname += " (on " + clientmachine + ")";
+    }
+    m_title.setLogical(fullname);
     m_title_override = true;
     m_title_update_timer.start();
 }
--- a/src/WinClient.hh
+++ b/src/WinClient.hh
@@ -91,6 +91,7 @@ public:
     //

     bool getAttrib(XWindowAttributes &attr) const;
+    bool getWMClientMachine(XTextProperty &textprop) const;
     bool getWMName(XTextProperty &textprop) const;
     bool getWMIconName(XTextProperty &textprop) const;
     std::string getWMRole() const;

And here's the readme:

Readme for fluxbox

Overview

This is for my customized dpkg of Fluxbox which exists quite happily in vanilla form in Debian Sid.

fluxbox upstream

I modified the debian/ from snapshot.debian.org/package/fluxbox/

This set of overlay patches probably will not be maintained, so user beware! That being said, upstream is frozen so you won't get behind here either.

Reason for being in stackrpms

I wrote exactly one patch: debian/patches/add-clientmachine-if-forwarded.patch Also by using the custom package here I can incorporate all the useful patches added in what appears to be a neo-upstream on github which has neat patches like toolbar: allow labeled general action buttons and document iconified title deco which are not present in the Debian Fluxbox 1.3.5 release.

I chose Fluxbox as my daily driver desktop environment/window manager because it is stable. And it is stable, with a few minor flaws!

So this one patch I wrote adds to the titlebar of a forwarded window "(on $CLIENT)" which was inspired by Xfwm4.

Improvements

  • Add a configurable option for "Show (on $CLIENT)" so users can decide if they like it.
  • Some programs do not properly maintain WM_CLIENT_MACHINE X property, like xfe(1) so that could be misleading.
  • Maybe store local hostname on the Display, like Xfwm4 so we do not need to keep calling gethostname()
  • Find way to rearrange the iconbar window entries (issue #94 in original repo) which was also requested in one of the github forks (luebking/fluxbox#1 with comments:

If you however mean to drag around the icon, that's probably not too hard to do in src/Icon{Button,barTool}*

Alternatives

Just use the native package fluxbox for the given distro.

Github indicates a large number of forks exist of the source. Almost all of them do not provide substantive improvements.

Dependencies

Exact same as native package fluxbox.

References

Every link in this document. Official upstream link?: http://git.fluxbox.org/fluxbox.git/

Differences from upstream

Only one d/p/series and d/p/add-clientmachine-if-forwarded.patch

Comments