From 9ff88dfc5b148ac616959569165d947c7c388374 Mon Sep 17 00:00:00 2001
From: Po Lu <luangruo@yahoo.com>
Date: Sat, 5 Feb 2022 09:41:01 +0800
Subject: [PATCH] Implement _NET_WM_PING protocol

* src/xfns.c (append_wm_protocols): New function.
(x_window): Call `append_wm_protocols' after window creation.
* src/xterm.c (handle_one_xevent): Handle _NET_WM_PING client
messages.
(x_term_init): Intern _NET_WM_PING atom.
* src/xterm.h (struct x_display_info): New field
`Xatom_net_wm_ping'.
---
 src/xfns.c  | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/xterm.c | 16 ++++++++++++++++
 src/xterm.h |  2 +-
 3 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/src/xfns.c b/src/xfns.c
index 4b10f5035a7..9bbefd79a02 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2355,6 +2355,55 @@ hack_wm_protocols (struct frame *f, Widget widget)
 }
 #endif
 
+static void
+append_wm_protocols (struct x_display_info *dpyinfo,
+		     struct frame *f)
+{
+  unsigned char *existing = NULL;
+  int format = 0;
+  unsigned long nitems = 0;
+  Atom type;
+  Atom *existing_protocols;
+  Atom protos[10];
+  int num_protos = 0;
+  bool found_wm_ping = false;
+  unsigned long bytes_after;
+
+  block_input ();
+  if ((XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+			   dpyinfo->Xatom_wm_protocols,
+			   0, 100, False, XA_ATOM, &type, &format, &nitems,
+			   &bytes_after, &existing) == Success)
+      && format == 32 && type == XA_ATOM)
+    {
+      existing_protocols = (Atom *) existing;
+
+      while (nitems)
+	{
+	  nitems--;
+
+	  if (existing_protocols[nitems]
+	      == dpyinfo->Xatom_net_wm_ping)
+	    found_wm_ping = true;
+	}
+    }
+
+  if (existing)
+    XFree (existing);
+
+  if (!found_wm_ping)
+    protos[num_protos++] = dpyinfo->Xatom_net_wm_ping;
+
+  if (num_protos)
+    XChangeProperty (dpyinfo->display,
+		     FRAME_OUTER_WINDOW (f),
+		     dpyinfo->Xatom_wm_protocols,
+		     XA_ATOM, 32, PropModeAppend,
+		     (unsigned char *) protos,
+		     num_protos);
+  unblock_input ();
+}
+
 
 
 /* Support routines for XIC (X Input Context).  */
@@ -3630,6 +3679,7 @@ x_window (struct frame *f, long window_prompting)
 	       &f->output_data.x->wm_hints);
 
   hack_wm_protocols (f, shell_widget);
+  append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
 
 #ifdef X_TOOLKIT_EDITRES
   XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
@@ -3750,6 +3800,8 @@ x_window (struct frame *f)
   }
 #endif
 
+  append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
+
 #ifdef HAVE_XINPUT2
   if (FRAME_DISPLAY_INFO (f)->supports_xi2)
     setup_xi_event_mask (f);
@@ -3790,6 +3842,7 @@ x_window (struct frame *f)
 		     FRAME_X_VISUAL (f),
                      attribute_mask, &attributes);
   initial_set_up_x_back_buffer (f);
+  append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
 
 #ifdef HAVE_X_I18N
   if (use_xim)
diff --git a/src/xterm.c b/src/xterm.c
index deaa5b5961c..34a85aa7456 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -9071,6 +9071,21 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		goto done;
               }
 
+
+	    if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_ping
+		&& event->xclient.format == 32)
+	      {
+		XEvent send_event = *event;
+
+		send_event.xclient.window = dpyinfo->root_window;
+		XSendEvent (dpyinfo->display, dpyinfo->root_window, False,
+			    SubstructureRedirectMask | SubstructureNotifyMask,
+			    &send_event);
+
+		*finish = X_EVENT_DROP;
+		goto done;
+	      }
+
 	    goto done;
           }
 
@@ -15914,6 +15929,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
       ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
       ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
       ATOM_REFS_INIT ("_NET_WM_OPAQUE_REGION", Xatom_net_wm_opaque_region)
+      ATOM_REFS_INIT ("_NET_WM_PING", Xatom_net_wm_ping)
 #ifdef HAVE_XKB
       ATOM_REFS_INIT ("Meta", Xatom_Meta)
       ATOM_REFS_INIT ("Super", Xatom_Super)
diff --git a/src/xterm.h b/src/xterm.h
index 02270d69360..99d339e1f94 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -498,7 +498,7 @@ struct x_display_info
     Xatom_net_wm_state_sticky, Xatom_net_wm_state_above, Xatom_net_wm_state_below,
     Xatom_net_wm_state_hidden, Xatom_net_wm_state_skip_taskbar,
     Xatom_net_frame_extents, Xatom_net_current_desktop, Xatom_net_workarea,
-    Xatom_net_wm_opaque_region;
+    Xatom_net_wm_opaque_region, Xatom_net_wm_ping;
 
   /* XSettings atoms and windows.  */
   Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
-- 
2.39.5