From 3b5c03eeb2bc559767555fbb5b9916721ce9f853 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 1 Aug 2022 09:56:12 +0800 Subject: [PATCH] Make frame synchronization a frame parameter * doc/lispref/frames.texi (Management Parameters): Document `use-frame-synchronization'. * etc/NEWS: Update entry. * src/frame.c (frame_parms): New frame parameter `use-frame-synchronization'. (syms_of_frame): New defsym. * src/haikufns.c (haiku_frame_parm_handlers): * src/nsfns.m (ns_frame_parm_handlers): * src/pgtkfns.c (pgtk_frame_parm_handlers): * src/w32fns.c (w32_frame_parm_handlers): Update frame param handlers correctly. * src/xfns.c (x_set_use_frame_synchronization): New function. (Fx_create_frame): Set default value of said parameter. (x_frame_parm_handlers): Add handler. * src/xterm.c (x_sync_wait_for_frame_drawn_event): Clear parameter if sync fails. --- doc/lispref/frames.texi | 12 +++++++++++- etc/NEWS | 3 +++ src/frame.c | 6 ++++-- src/haikufns.c | 1 + src/nsfns.m | 1 + src/pgtkfns.c | 1 + src/w32fns.c | 1 + src/xfns.c | 33 +++++++++++++++++++++++++++------ src/xterm.c | 3 +++ 9 files changed, 52 insertions(+), 9 deletions(-) diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index ed56fa777d2..e5dec4f8072 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -2180,10 +2180,20 @@ If non-@code{nil}, the frame is visible on all virtual desktops on systems with virtual desktops. @vindex shaded@r{, a frame parameter} -@item sticky +@item shaded If non-@code{nil}, tell the window manager to display the frame in a way that its contents are hidden, leaving only the title bar. +@vindex use-frame-synchronization@r{, a frame parameter} +@item use-frame-synchronization +If non-@code{nil}, synchronize the frame redisplay with the refresh +rate of the monitor to avoid graphics tearing. At present, this is +only implemented on the X window system inside no-toolkit and X +toolkit builds, does not work correctly with toolkit scroll bars, and +requires a compositing manager supporting the relevant display +synchronization protocols. The @code{synchronizeResize} X resource +must also be set to the string @code{"extended"}. + @vindex inhibit-double-buffering@r{, a frame parameter} @item inhibit-double-buffering If non-@code{nil}, the frame is drawn to the screen without double diff --git a/etc/NEWS b/etc/NEWS index ba05b491761..963aa22c680 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -620,6 +620,9 @@ requires an X compositing manager supporting the extended frame synchronization protocol (see https://fishsoup.net/misc/wm-spec-synchronization.html). +This behavior can be toggled on and off via the frame parameter +'use-frame-synchronization'. + +++ ** New frame parameter 'alpha-background' and X resource "alphaBackground". This controls the opacity of the text background when running on a diff --git a/src/frame.c b/src/frame.c index a39e1c4944f..25d71e0769f 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3916,9 +3916,10 @@ static const struct frame_parm_table frame_parms[] = {"z-group", SYMBOL_INDEX (Qz_group)}, {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)}, {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)}, - {"alpha-background", SYMBOL_INDEX (Qalpha_background)}, + {"alpha-background", SYMBOL_INDEX (Qalpha_background)}, + {"use-frame-synchronization", SYMBOL_INDEX (Quse_frame_synchronization)}, #ifdef HAVE_X_WINDOWS - {"shaded", SYMBOL_INDEX (Qshaded)}, + {"shaded", SYMBOL_INDEX (Qshaded)}, #endif #ifdef NS_IMPL_COCOA {"ns-appearance", SYMBOL_INDEX (Qns_appearance)}, @@ -6195,6 +6196,7 @@ syms_of_frame (void) DEFSYM (Qtop_only, "top-only"); DEFSYM (Qiconify_top_level, "iconify-top-level"); DEFSYM (Qmake_invisible, "make-invisible"); + DEFSYM (Quse_frame_synchronization, "use-frame-synchronization"); { int i; diff --git a/src/haikufns.c b/src/haikufns.c index f3667ac2f9d..055a33e2c1e 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -3128,6 +3128,7 @@ frame_parm_handler haiku_frame_parm_handlers[] = haiku_set_override_redirect, gui_set_no_special_glyphs, gui_set_alpha_background, + NULL, }; void diff --git a/src/nsfns.m b/src/nsfns.m index 433df059610..1d3dcd31243 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -1057,6 +1057,7 @@ frame_parm_handler ns_frame_parm_handlers[] = 0, /* x_set_override_redirect */ gui_set_no_special_glyphs, gui_set_alpha_background, + NULL, #ifdef NS_IMPL_COCOA ns_set_appearance, ns_set_transparent_titlebar, diff --git a/src/pgtkfns.c b/src/pgtkfns.c index d998c3d938c..beaf28f69d9 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -991,6 +991,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] = pgtk_set_override_redirect, gui_set_no_special_glyphs, pgtk_set_alpha_background, + NULL, }; diff --git a/src/w32fns.c b/src/w32fns.c index 5e42a1df6ff..28d13a68d45 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -10508,6 +10508,7 @@ frame_parm_handler w32_frame_parm_handlers[] = 0, /* x_set_override_redirect */ gui_set_no_special_glyphs, gui_set_alpha_background, + 0, /* x_set_use_frame_synchronization */ }; void diff --git a/src/xfns.c b/src/xfns.c index 1ae615fad44..c149eaeca3b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2431,6 +2431,28 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval) } } +static void +x_set_use_frame_synchronization (struct frame *f, Lisp_Object arg, + Lisp_Object oldval) +{ +#if !defined USE_GTK && defined HAVE_XSYNC + struct x_display_info *dpyinfo; + + dpyinfo = FRAME_DISPLAY_INFO (f); + + if (!NILP (arg) && FRAME_X_EXTENDED_COUNTER (f)) + FRAME_X_OUTPUT (f)->use_vsync_p + = x_wm_supports (f, dpyinfo->Xatom_net_wm_frame_drawn); + else + FRAME_X_OUTPUT (f)->use_vsync_p = false; + + store_frame_param (f, Quse_frame_synchronization, + FRAME_X_OUTPUT (f)->use_vsync_p ? Qt : Qnil); +#else + store_frame_param (f, Quse_frame_synchronization, Qnil); +#endif +} + /* Record in frame F the specified or default value according to ALIST of the parameter named PROP (a Lisp symbol). If no value is @@ -5150,17 +5172,15 @@ This function is an internal primitive--use `make-frame' instead. */) ((STRINGP (value) && !strcmp (SSDATA (value), "extended")) ? 2 : 1)); #endif - -#ifndef USE_GTK - if (FRAME_X_EXTENDED_COUNTER (f)) - FRAME_X_OUTPUT (f)->use_vsync_p - = x_wm_supports (f, dpyinfo->Xatom_net_wm_frame_drawn); -#endif } #endif unblock_input (); + /* Set whether or not frame synchronization is enabled. */ + gui_default_parameter (f, parms, Quse_frame_synchronization, Qt, + NULL, NULL, RES_TYPE_BOOLEAN); + /* Works iff frame has been already mapped. */ gui_default_parameter (f, parms, Qskip_taskbar, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); @@ -9775,6 +9795,7 @@ frame_parm_handler x_frame_parm_handlers[] = x_set_override_redirect, gui_set_no_special_glyphs, x_set_alpha_background, + x_set_use_frame_synchronization, x_set_shaded, }; diff --git a/src/xterm.c b/src/xterm.c index d7d4cb418f3..986973eb788 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -6689,6 +6689,9 @@ x_sync_wait_for_frame_drawn_event (struct frame *f) fprintf (stderr, "Warning: compositing manager spent more than 1 second " "drawing a frame. Frame synchronization has been disabled\n"); FRAME_X_OUTPUT (f)->use_vsync_p = false; + + /* Also change the frame parameter to reflect the new state. */ + store_frame_param (f, Quse_frame_synchronization, Qnil); } FRAME_X_WAITING_FOR_DRAW (f) = false; -- 2.39.2