From 7f425613a75d7566309e8b60cdc01fd26c597302 Mon Sep 17 00:00:00 2001
From: Po Lu <luangruo@yahoo.com>
Date: Wed, 9 Feb 2022 18:47:07 +0800
Subject: [PATCH] Add support for _NET_WM_USER_TIME_WINDOW

* src/xterm.c (x_make_frame_visible):
(x_display_set_last_user_time): Use and set user time window if
the WM supports it.
(x_term_init): Intern new atom.

* src/xterm.h (struct x_display_info): New atom
`_NET_WM_USER_TIME_WINDOW'.
(struct x_output): New field `user_time_window'.
---
 src/xterm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-------
 src/xterm.h |  8 +++++++-
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index 38b50bcd3b7..e6d7d5d133f 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -2220,24 +2220,29 @@ static void x_check_font (struct frame *, struct font *);
 void
 x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time)
 {
+#ifndef USE_GTK
   struct frame *focus_frame = dpyinfo->x_focus_frame;
+#endif
 
 #ifdef ENABLE_CHECKING
   eassert (t <= X_ULONG_MAX);
 #endif
   dpyinfo->last_user_time = time;
 
+#ifndef USE_GTK
   if (focus_frame)
     {
       while (FRAME_PARENT_FRAME (focus_frame))
 	focus_frame = FRAME_PARENT_FRAME (focus_frame);
 
-      XChangeProperty (dpyinfo->display,
-		       FRAME_OUTER_WINDOW (dpyinfo->x_focus_frame),
-		       dpyinfo->Xatom_net_wm_user_time,
-		       XA_CARDINAL, 32, PropModeReplace,
-		       (unsigned char *) &time, 1);
+      if (FRAME_X_OUTPUT (focus_frame)->user_time_window != None)
+	XChangeProperty (dpyinfo->display,
+			 FRAME_X_OUTPUT (focus_frame)->user_time_window,
+			 dpyinfo->Xatom_net_wm_user_time,
+			 XA_CARDINAL, 32, PropModeReplace,
+			 (unsigned char *) &time, 1);
     }
+#endif
 }
 
 
@@ -14481,6 +14486,9 @@ void
 x_make_frame_visible (struct frame *f)
 {
   struct x_display_info *dpyinfo;
+#ifndef USE_GTK
+  struct x_output *output;
+#endif
 
   if (FRAME_PARENT_FRAME (f))
     {
@@ -14518,16 +14526,44 @@ x_make_frame_visible (struct frame *f)
 	  && ! f->output_data.x->asked_for_visible)
 	x_set_offset (f, f->left_pos, f->top_pos, 0);
 
+#ifndef USE_GTK
+      output = FRAME_X_OUTPUT (f);
+
+      if (output->user_time_window == None)
+	{
+	  XSetWindowAttributes attrs;
+	  memset (&attrs, 0, sizeof attrs);
+
+	  output->user_time_window
+	    = FRAME_OUTER_WINDOW (f);
+
+	  if (x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time_window))
+	    {
+	      output->user_time_window
+		= XCreateWindow (dpyinfo->display, FRAME_X_WINDOW (f),
+				 -1, -1, 1, 1, 0, 0, InputOnly,
+				 CopyFromParent, 0, &attrs);
+
+	      XChangeProperty (dpyinfo->display,
+			       FRAME_OUTER_WINDOW (f),
+			       dpyinfo->Xatom_net_wm_user_time_window,
+			       XA_WINDOW, 32, PropModeReplace,
+			       (unsigned char *) &output->user_time_window,
+			       1);
+	    }
+	}
+
       if (dpyinfo->last_user_time)
 	XChangeProperty (dpyinfo->display,
-			 FRAME_OUTER_WINDOW (f),
+			 output->user_time_window,
 			 dpyinfo->Xatom_net_wm_user_time,
 			 XA_CARDINAL, 32, PropModeReplace,
 			 (unsigned char *) &dpyinfo->last_user_time, 1);
       else
 	XDeleteProperty (dpyinfo->display,
-			 FRAME_OUTER_WINDOW (f),
+			 output->user_time_window,
 			 dpyinfo->Xatom_net_wm_user_time);
+#endif
 
       f->output_data.x->asked_for_visible = true;
 
@@ -16133,6 +16169,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
       ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", Xatom_net_wm_sync_request_counter)
       ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn)
       ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time)
+      ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window)
       /* Session management */
       ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
       ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
diff --git a/src/xterm.h b/src/xterm.h
index 9aa7021c4dc..afd6a1757c5 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -506,7 +506,7 @@ struct x_display_info
     Xatom_net_frame_extents, Xatom_net_current_desktop, Xatom_net_workarea,
     Xatom_net_wm_opaque_region, Xatom_net_wm_ping, Xatom_net_wm_sync_request,
     Xatom_net_wm_sync_request_counter, Xatom_net_wm_frame_drawn,
-    Xatom_net_wm_user_time;
+    Xatom_net_wm_user_time, Xatom_net_wm_user_time_window;
 
   /* XSettings atoms and windows.  */
   Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
@@ -677,6 +677,12 @@ struct x_output
   Widget menubar_widget;
 #endif
 
+#ifndef USE_GTK
+  /* A window used to store the user time property.  May be None or
+     the frame's outer window.  */
+  Window user_time_window;
+#endif
+
 #ifdef USE_GTK
   /* The widget of this screen.  This is the window of a top widget.  */
   GtkWidget *widget;
-- 
2.39.5