[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master da6778d1ce: Fix multiple sources of flicker under X
From: |
Po Lu |
Subject: |
master da6778d1ce: Fix multiple sources of flicker under X |
Date: |
Sun, 16 Oct 2022 02:05:14 -0400 (EDT) |
branch: master
commit da6778d1ce55843cd52da7db66bcb518c441e46e
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Fix multiple sources of flicker under X
Fix three kinds of flicker. The first is if you do:
(while t (sit-for 1) (redraw-display))
and press a key, the frame will turn blank until you C-g. The
second is where handling async input happens in the middle of
drawing and causes a buffer flip to happen. The third is where
unmapping the hourglass window causes exposures.
* src/dispnew.c (redraw_frame): Garbage the frame if it is a
window system frame.
* src/xterm.c (x_update_begin): Clear complete flag.
(x_flip_and_flush, XTframe_up_to_date): Set complete flag.
(x_show_hourglass): Fix hourglass window class.
(flush_dirty_back_buffer_on): Rename to
x_flush_dirty_back_buffer_on.
(x_flush_dirty_back_buffer_on): Check if the frame is complete
before trying to flip.
(handle_one_xevent): Flush frames in a more detailed fashion.
* src/xterm.h (struct x_output): New flag `complete'.
(FRAME_X_COMPLETE_P): New macro.
---
src/dispnew.c | 9 +++++
src/xterm.c | 117 ++++++++++++++++++++++++++++++++++++++--------------------
src/xterm.h | 21 ++++++++---
3 files changed, 102 insertions(+), 45 deletions(-)
diff --git a/src/dispnew.c b/src/dispnew.c
index 2568ba1086..5a9ba8909e 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3152,10 +3152,19 @@ redraw_frame (struct frame *f)
update_begin (f);
if (FRAME_MSDOS_P (f))
FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f));
+
+ if (FRAME_WINDOW_P (f))
+ /* Garbage the frame now. Otherwise, platforms that support
+ double buffering will display the blank contents of the frame
+ even though the frame should be redrawn at some point in the
+ future. */
+ SET_FRAME_GARBAGED (f);
+
clear_frame (f);
clear_current_matrices (f);
update_end (f);
fset_redisplay (f);
+
/* Mark all windows as inaccurate, so that every window will have
its redisplay done. */
mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
diff --git a/src/xterm.c b/src/xterm.c
index d35af7a8de..ee6db62bb9 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -7044,6 +7044,13 @@ x_update_begin (struct frame *f)
#else
/* Nothing to do. */
#endif
+
+#ifdef HAVE_XDBE
+ if (FRAME_X_DOUBLE_BUFFERED_P (f))
+ /* The frame is no longer complete, as it is in the midst of an
+ update. */
+ FRAME_X_COMPLETE_P (f) = false;
+#endif
}
/* Draw a vertical window border from (x,y0) to (x,y1) */
@@ -7190,6 +7197,10 @@ x_flip_and_flush (struct frame *f)
#ifdef HAVE_XDBE
if (FRAME_X_NEED_BUFFER_FLIP (f))
show_back_buffer (f);
+
+ /* The frame is complete again as its contents were just
+ flushed. */
+ FRAME_X_COMPLETE_P (f) = true;
#endif
x_flush (f);
unblock_input ();
@@ -7240,6 +7251,9 @@ XTframe_up_to_date (struct frame *f)
if (!buffer_flipping_blocked_p ()
&& FRAME_X_NEED_BUFFER_FLIP (f))
show_back_buffer (f);
+
+ /* The frame is now complete, as its contents have been drawn. */
+ FRAME_X_COMPLETE_P (f) = true;
#endif
#ifdef HAVE_XSYNC
@@ -10806,6 +10820,7 @@ x_clear_frame (struct frame *f)
/* We have to clear the scroll bars. If we have changed colors or
something like that, then they should be notified. */
x_scroll_bar_clear (f);
+
unblock_input ();
}
@@ -10857,7 +10872,7 @@ x_show_hourglass (struct frame *f)
(xcb_window_t) x->hourglass_window,
parent, 0, 0, FRAME_PIXEL_WIDTH (f),
FRAME_PIXEL_HEIGHT (f), 0,
- XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ XCB_WINDOW_CLASS_INPUT_ONLY,
XCB_COPY_FROM_PARENT, XCB_CW_CURSOR,
&cursor);
#endif
@@ -17033,18 +17048,21 @@ x_net_wm_state (struct frame *f, Window window)
/* Flip back buffers on F if it has undrawn content. */
-#ifdef HAVE_XDBE
static void
-flush_dirty_back_buffer_on (struct frame *f)
+x_flush_dirty_back_buffer_on (struct frame *f)
{
- block_input ();
- if (!FRAME_GARBAGED_P (f)
- && !buffer_flipping_blocked_p ()
- && FRAME_X_NEED_BUFFER_FLIP (f))
- show_back_buffer (f);
- unblock_input ();
-}
+#ifdef HAVE_XDBE
+ if (FRAME_GARBAGED_P (f)
+ || buffer_flipping_blocked_p ()
+ /* If the frame is not already up to date, do not flush buffers
+ on input, as that will result in flicker. */
+ || !FRAME_X_COMPLETE_P (f)
+ || !FRAME_X_NEED_BUFFER_FLIP (f))
+ return;
+
+ show_back_buffer (f);
#endif
+}
#ifdef HAVE_GTK3
void
@@ -17824,7 +17842,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
Time gen_help_time UNINIT;
#endif
ptrdiff_t nbytes = 0;
- struct frame *any, *f = NULL;
+ struct frame *any, *f = NULL, *mouse_frame;
Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
/* This holds the state XLookupString needs to implement dead keys
and other tricks known as "compose processing". _X Window System_
@@ -19148,9 +19166,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
)
{
- clear_mouse_face (hlinfo);
- hlinfo->mouse_face_hidden = true;
- }
+ mouse_frame = hlinfo->mouse_face_mouse_frame;
+
+ clear_mouse_face (hlinfo);
+ hlinfo->mouse_face_hidden = true;
+
+ if (mouse_frame)
+ x_flush_dirty_back_buffer_on (mouse_frame);
+ }
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
if (f == 0)
@@ -19630,6 +19653,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
clear_mouse_face (hlinfo);
hlinfo->mouse_face_mouse_frame = 0;
+ x_flush_dirty_back_buffer_on (xvw->frame);
}
if (any_help_event_p)
@@ -19783,6 +19807,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
certainly no longer on any text in the frame. */
clear_mouse_face (hlinfo);
hlinfo->mouse_face_mouse_frame = 0;
+ x_flush_dirty_back_buffer_on (f);
}
/* Generate a nil HELP_EVENT to cancel a help-echo.
@@ -19840,7 +19865,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
help_echo_string = Qnil;
if (hlinfo->mouse_face_hidden)
- {
+ {
hlinfo->mouse_face_hidden = false;
clear_mouse_face (hlinfo);
}
@@ -20171,6 +20196,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!NILP (help_echo_string)
|| !NILP (previous_help_echo_string))
do_help = 1;
+
+ if (f)
+ x_flush_dirty_back_buffer_on (f);
goto OTHER;
}
@@ -20837,9 +20865,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
- tab_bar_arg = handle_tab_bar_click
- (f, x, y, event->xbutton.type == ButtonPress,
- x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
+ {
+ tab_bar_arg = handle_tab_bar_click
+ (f, x, y, event->xbutton.type == ButtonPress,
+ x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
+ x_flush_dirty_back_buffer_on (f);
+ }
}
#if ! defined (USE_GTK)
@@ -20857,9 +20888,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| f->last_tool_bar_item != -1));
if (tool_bar_p && event->xbutton.button < 4)
- handle_tool_bar_click
- (f, x, y, event->xbutton.type == ButtonPress,
- x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
+ {
+ handle_tool_bar_click
+ (f, x, y, event->xbutton.type == ButtonPress,
+ x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
+ x_flush_dirty_back_buffer_on (f);
+ }
}
#endif /* !USE_GTK */
@@ -21398,6 +21432,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
certainly no longer on any text in the frame. */
clear_mouse_face (hlinfo);
hlinfo->mouse_face_mouse_frame = 0;
+ x_flush_dirty_back_buffer_on (f);
}
/* Generate a nil HELP_EVENT to cancel a help-echo.
@@ -22073,6 +22108,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
do_help = 1;
}
+
+ if (f)
+ x_flush_dirty_back_buffer_on (f);
goto XI_OTHER;
}
@@ -22592,9 +22630,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
- tab_bar_arg = handle_tab_bar_click
- (f, x, y, xev->evtype == XI_ButtonPress,
- x_x_to_emacs_modifiers (dpyinfo, bv.state));
+ {
+ tab_bar_arg = handle_tab_bar_click
+ (f, x, y, xev->evtype == XI_ButtonPress,
+ x_x_to_emacs_modifiers (dpyinfo, bv.state));
+ x_flush_dirty_back_buffer_on (f);
+ }
}
#if ! defined (USE_GTK)
@@ -22619,10 +22660,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| f->last_tool_bar_item != -1));
if (tool_bar_p && xev->detail < 4)
- handle_tool_bar_click_with_device
- (f, x, y, xev->evtype == XI_ButtonPress,
- x_x_to_emacs_modifiers (dpyinfo, bv.state),
- source ? source->name : Qt);
+ {
+ handle_tool_bar_click_with_device
+ (f, x, y, xev->evtype == XI_ButtonPress,
+ x_x_to_emacs_modifiers (dpyinfo, bv.state),
+ source ? source->name : Qt);
+ x_flush_dirty_back_buffer_on (f);
+ }
}
#endif /* !USE_GTK */
@@ -22919,8 +22963,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
)
{
+ mouse_frame = hlinfo->mouse_face_mouse_frame;
+
clear_mouse_face (hlinfo);
hlinfo->mouse_face_hidden = true;
+
+ if (mouse_frame)
+ x_flush_dirty_back_buffer_on (mouse_frame);
}
if (f != 0)
@@ -24084,18 +24133,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
count++;
}
- /* Sometimes event processing draws to either F or ANY outside
- redisplay. To ensure that these changes become visible, draw
- them here. */
-
-#ifdef HAVE_XDBE
- if (f)
- flush_dirty_back_buffer_on (f);
-
- if (any && any != f)
- flush_dirty_back_buffer_on (any);
-#endif
-
SAFE_FREE ();
return count;
}
diff --git a/src/xterm.h b/src/xterm.h
index b68a234faa..55fd193a29 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -916,11 +916,6 @@ struct x_output
Picture picture;
#endif
- /* Flag that indicates whether we've modified the back buffer and
- need to publish our modifications to the front buffer at a
- convenient time. */
- bool need_buffer_flip;
-
/* The X window used for the bitmap icon;
or 0 if we don't have a bitmap icon. */
Window icon_desc;
@@ -1091,6 +1086,18 @@ struct x_output
and inactive states. */
bool_bf alpha_identical_p : 1;
+#ifdef HAVE_XDBE
+ /* Flag that indicates whether we've modified the back buffer and
+ need to publish our modifications to the front buffer at a
+ convenient time. */
+ bool_bf need_buffer_flip : 1;
+
+ /* Flag that indicates whether or not the frame contents are
+ complete and can be safely flushed while handling async
+ input. */
+ bool_bf complete : 1;
+#endif
+
#ifdef HAVE_X_I18N
/* Input context (currently, this means Compose key handler setup). */
XIC xic;
@@ -1248,6 +1255,10 @@ extern void x_mark_frame_dirty (struct frame *f);
/* Return the need-buffer-flip flag for frame F. */
#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip)
+
+/* Return whether or not the frame F has been completely drawn. Used
+ while handling async input. */
+#define FRAME_X_COMPLETE_P(f) ((f)->output_data.x->complete)
#endif
/* Return the outermost X window associated with the frame F. */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master da6778d1ce: Fix multiple sources of flicker under X,
Po Lu <=