emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 9e420cd893: Add support for basic syncing with the window manager


From: Po Lu
Subject: master 9e420cd893: Add support for basic syncing with the window manager on resize
Date: Sat, 5 Feb 2022 08:47:53 -0500 (EST)

branch: master
commit 9e420cd893f5507b9d7d3888c3a6d709aa45e6ff
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Add support for basic syncing with the window manager on resize
    
    This is handled by GTK 3, so the code is disabled on that
    specific build.  On other builds, this eliminates any unexposed
    part of a frame from showing up after a resize when
    `frame-resize-pixelwise' is t.
    
    * configure.ac: Check for the X Synchronization Extension if
    present.
    * src/Makefile.in (EMACS_CFLAGS):
    (LIBES): Add XSYNC_LIBS and XSYNC_CFLAGS.
    
    * src/xfns.c (append_wm_protocols): Declare
    `_NET_WM_SYNC_REQUEST' support if appropriate.
    (x_window): Adjust location of call to `append_wm_protocols' on
    Xt version to prevent it from being overwritten.
    (Fx_create_frame): Create basic counter.
    * src/xterm.c (XTframe_up_to_date): Set counter value to the one
    asked for by the window manager.
    (handle_one_xevent): Handle _NET_WM_SYNC_REQUEST.
    (x_free_frame_resources): Free frame counter if present.
    (x_term_init): Test for XSync and set fields accordingly.
    * src/xterm.h (struct x_display_info): New fields for XSync
    support and new atoms.
    (struct x_output): New fields for counter status.
    (FRAME_X_BASIC_COUNTER): New macro.
---
 configure.ac    | 16 ++++++++++++++++
 src/Makefile.in |  7 +++++--
 src/xfns.c      | 33 +++++++++++++++++++++++++++++++-
 src/xterm.c     | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/xterm.h     | 29 ++++++++++++++++++++++++----
 5 files changed, 136 insertions(+), 8 deletions(-)

diff --git a/configure.ac b/configure.ac
index 2ad5f2312c..6f469cf0f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4490,6 +4490,22 @@ fi
 AC_SUBST(XINPUT_CFLAGS)
 AC_SUBST(XINPUT_LIBS)
 
+XSYNC_LIBS=
+XSYNC_CFLAGS=
+HAVE_XSYNC=no
+if test "${HAVE_X11}" = "yes"; then
+   AC_CHECK_HEADER(X11/extensions/sync.h,
+     AC_CHECK_LIB(Xext, XSyncQueryExtension, HAVE_XSYNC=yes),
+     [], [#include <X11/Xlib.h>])
+
+  if test "${HAVE_XSYNC}" = "yes"; then
+    AC_DEFINE(HAVE_XSYNC, 1, [Define to 1 if the X Synchronization Extension 
is available.])
+    XSYNC_LIBS="-lXext"
+  fi
+fi
+AC_SUBST(XSYNC_LIBS)
+AC_SUBST(XSYNC_CFLAGS)
+
 ### Use Xdbe (-lXdbe) if available
 HAVE_XDBE=no
 if test "${HAVE_X11}" = "yes"; then
diff --git a/src/Makefile.in b/src/Makefile.in
index 706beb453b..186e06735c 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -264,6 +264,9 @@ XFIXES_CFLAGS = @XFIXES_CFLAGS@
 XINPUT_LIBS = @XINPUT_LIBS@
 XINPUT_CFLAGS = @XINPUT_CFLAGS@
 
+XSYNC_LIBS = @XSYNC_LIBS@
+XSYNC_CFLAGS = @XSYNC_CFLAGS@
+
 XDBE_LIBS = @XDBE_LIBS@
 XDBE_CFLAGS = @XDBE_CFLAGS@
 
@@ -396,7 +399,7 @@ EMACS_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
   $(XINPUT_CFLAGS) $(WEBP_CFLAGS) $(WEBKIT_CFLAGS) $(LCMS2_CFLAGS) \
   $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
   $(HARFBUZZ_CFLAGS) $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
-  $(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) \
+  $(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) $(XSYNC_CFLAGS) \
   $(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
   $(WERROR_CFLAGS) $(HAIKU_CFLAGS)
 ALL_CFLAGS = $(EMACS_CFLAGS) $(WARN_CFLAGS) $(CFLAGS)
@@ -548,7 +551,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(PGTK_LIBS) 
$(LIBX_BASE) $(LIBIMAGE
    $(WEBKIT_LIBS) \
    $(LIB_EACCESS) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
    $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
-   $(XDBE_LIBS) \
+   $(XDBE_LIBS) $(XSYNC_LIBS) \
    $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
    $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
    $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(HARFBUZZ_LIBS) $(LIBOTF_LIBS) 
$(M17N_FLT_LIBS) \
diff --git a/src/xfns.c b/src/xfns.c
index 4719c5dac7..bfb61c1205 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2367,6 +2367,9 @@ append_wm_protocols (struct x_display_info *dpyinfo,
   Atom protos[10];
   int num_protos = 0;
   bool found_wm_ping = false;
+#if !defined HAVE_GTK3 && defined HAVE_XSYNC
+  bool found_wm_sync_request = false;
+#endif
   unsigned long bytes_after;
 
   block_input ();
@@ -2385,6 +2388,11 @@ append_wm_protocols (struct x_display_info *dpyinfo,
          if (existing_protocols[nitems]
              == dpyinfo->Xatom_net_wm_ping)
            found_wm_ping = true;
+#if !defined HAVE_GTK3 && defined HAVE_XSYNC
+         else if (existing_protocols[nitems]
+                  == dpyinfo->Xatom_net_wm_sync_request)
+           found_wm_sync_request = true;
+#endif
        }
     }
 
@@ -2393,6 +2401,10 @@ append_wm_protocols (struct x_display_info *dpyinfo,
 
   if (!found_wm_ping)
     protos[num_protos++] = dpyinfo->Xatom_net_wm_ping;
+#if !defined HAVE_GTK3 && defined HAVE_XSYNC
+  if (!found_wm_sync_request)
+    protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request;
+#endif
 
   if (num_protos)
     XChangeProperty (dpyinfo->display,
@@ -3842,7 +3854,6 @@ 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)
@@ -3891,6 +3902,8 @@ x_window (struct frame *f)
     XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
   }
 
+  append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
+
   /* x_set_name normally ignores requests to set the name if the
      requested name is the same as the current name.  This is the one
      place where that assumption isn't correct; f->name is set, but
@@ -4795,6 +4808,24 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
                       (unsigned char *) &dpyinfo->client_leader_window, 1);
     }
 
+#ifdef HAVE_XSYNC
+  if (dpyinfo->xsync_supported_p)
+    {
+#ifndef HAVE_GTK3
+      XSyncValue initial_value;
+
+      XSyncIntToValue (&initial_value, 0);
+      FRAME_X_BASIC_COUNTER (f) = XSyncCreateCounter (FRAME_X_DISPLAY (f),
+                                                     initial_value);
+
+      XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                      dpyinfo->Xatom_net_wm_sync_request_counter,
+                      XA_CARDINAL, 32, PropModeReplace,
+                      (unsigned char *) &FRAME_X_BASIC_COUNTER (f), 1);
+#endif
+    }
+#endif
+
   unblock_input ();
 
   /* Works iff frame has been already mapped.  */
diff --git a/src/xterm.c b/src/xterm.c
index 34a85aa745..4b4eae53be 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -122,6 +122,10 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include <X11/extensions/Xrandr.h>
 #endif
 
+#ifdef HAVE_XSYNC
+#include <X11/extensions/sync.h>
+#endif
+
 /* Load sys/types.h if not already loaded.
    In some systems loading it twice is suicidal.  */
 #ifndef makedev
@@ -1849,6 +1853,17 @@ XTframe_up_to_date (struct frame *f)
   FRAME_MOUSE_UPDATE (f);
   if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f))
     show_back_buffer (f);
+
+#ifdef HAVE_XSYNC
+  if (FRAME_X_OUTPUT (f)->sync_end_pending_p
+      && FRAME_X_BASIC_COUNTER (f))
+    {
+      XSyncSetCounter (FRAME_X_DISPLAY (f),
+                      FRAME_X_BASIC_COUNTER (f),
+                      FRAME_X_OUTPUT (f)->pending_basic_counter_value);
+      FRAME_X_OUTPUT (f)->sync_end_pending_p = false;
+    }
+#endif
   unblock_input ();
 }
 
@@ -9086,6 +9101,26 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                goto done;
              }
 
+#if defined HAVE_XSYNC && !defined HAVE_GTK3
+           if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_sync_request
+               && event->xclient.format == 32)
+             {
+               struct frame *f
+                 = x_top_window_to_frame (dpyinfo,
+                                          event->xclient.window);
+
+               if (f)
+                 {
+                   XSyncIntsToValue (&FRAME_X_OUTPUT 
(f)->pending_basic_counter_value,
+                                     event->xclient.data.l[2], 
event->xclient.data.l[3]);
+                   FRAME_X_OUTPUT (f)->sync_end_pending_p = true;
+
+                   *finish = X_EVENT_DROP;
+                   goto done;
+                 }
+             }
+#endif
+
            goto done;
           }
 
@@ -14745,9 +14780,15 @@ x_free_frame_resources (struct frame *f)
 
       tear_down_x_back_buffer (f);
       if (FRAME_X_WINDOW (f))
-          XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+       XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* !USE_X_TOOLKIT */
 
+#ifdef HAVE_XSYNC
+      if (FRAME_X_BASIC_COUNTER (f))
+       XSyncDestroyCounter (FRAME_X_DISPLAY (f),
+                            FRAME_X_BASIC_COUNTER (f));
+#endif
+
       unload_color (f, FRAME_FOREGROUND_PIXEL (f));
       unload_color (f, FRAME_BACKGROUND_PIXEL (f));
       unload_color (f, f->output_data.x->cursor_pixel);
@@ -15628,6 +15669,19 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
     }
 #endif
 
+#ifdef HAVE_XSYNC
+  int xsync_event_base, xsync_error_base;
+  dpyinfo->xsync_supported_p
+    = XSyncQueryExtension (dpyinfo->display,
+                          &xsync_event_base,
+                          &xsync_error_base);
+
+  if (dpyinfo->xsync_supported_p)
+    dpyinfo->xsync_supported_p = XSyncInitialize (dpyinfo->display,
+                                                 &dpyinfo->xsync_major,
+                                                 &dpyinfo->xsync_minor);
+#endif
+
   /* See if a private colormap is requested.  */
   if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
     {
@@ -15887,6 +15941,7 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
       ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
       ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
       ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
+      ATOM_REFS_INIT ("XATOM_COUNTER", Xatom_XEMBED_INFO)
       ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
       /* For properties of font.  */
       ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
@@ -15921,6 +15976,8 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
       ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
       ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
       ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
+      ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request)
+      ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", 
Xatom_net_wm_sync_request_counter)
       /* 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 99d339e1f9..25ea257b51 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -99,6 +99,10 @@ typedef GtkWidget *xt_or_gtk_widget;
 #include <X11/XKBlib.h>
 #endif
 
+#ifdef HAVE_XSYNC
+#include <X11/extensions/sync.h>
+#endif
+
 #include "dispextern.h"
 #include "termhooks.h"
 
@@ -366,9 +370,9 @@ struct x_display_info
 
   /* More atoms, which are selection types.  */
   Atom Xatom_CLIPBOARD, Xatom_TIMESTAMP, Xatom_TEXT, Xatom_DELETE,
-  Xatom_COMPOUND_TEXT, Xatom_UTF8_STRING,
-  Xatom_MULTIPLE, Xatom_INCR, Xatom_EMACS_TMP, Xatom_TARGETS, Xatom_NULL,
-  Xatom_ATOM, Xatom_ATOM_PAIR, Xatom_CLIPBOARD_MANAGER;
+    Xatom_COMPOUND_TEXT, Xatom_UTF8_STRING,
+    Xatom_MULTIPLE, Xatom_INCR, Xatom_EMACS_TMP, Xatom_TARGETS, Xatom_NULL,
+    Xatom_ATOM, Xatom_ATOM_PAIR, Xatom_CLIPBOARD_MANAGER, Xatom_COUNTER;
 
   /* More atoms for font properties.  The last three are private
      properties, see the comments in src/fontset.h.  */
@@ -498,7 +502,8 @@ 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_ping;
+    Xatom_net_wm_opaque_region, Xatom_net_wm_ping, Xatom_net_wm_sync_request,
+    Xatom_net_wm_sync_request_counter;
 
   /* XSettings atoms and windows.  */
   Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
@@ -565,6 +570,12 @@ struct x_display_info
   int xfixes_major;
   int xfixes_minor;
 #endif
+
+#ifdef HAVE_XSYNC
+  bool xsync_supported_p;
+  int xsync_major;
+  int xsync_minor;
+#endif
 };
 
 #ifdef HAVE_X_I18N
@@ -801,6 +812,13 @@ struct x_output
   XFontSet xic_xfs;
 #endif
 
+#ifdef HAVE_XSYNC
+  XSyncCounter basic_frame_counter;
+  XSyncValue pending_basic_counter_value;
+
+  bool_bf sync_end_pending_p;
+#endif
+
   /* Relief GCs, colors etc.  */
   struct relief
   {
@@ -963,6 +981,9 @@ extern void x_mark_frame_dirty (struct frame *f);
        || (FRAME_DISPLAY_INFO (f)->xrender_major > (major))))
 #endif
 
+#ifdef HAVE_XSYNC
+#define FRAME_X_BASIC_COUNTER(f) FRAME_X_OUTPUT (f)->basic_frame_counter
+#endif
 
 /* This is the Colormap which frame F uses.  */
 #define FRAME_X_COLORMAP(f) FRAME_DISPLAY_INFO (f)->cmap



reply via email to

[Prev in Thread] Current Thread [Next in Thread]