aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-10-16 14:02:31 +0800
committerPo Lu2022-10-16 14:02:31 +0800
commitda6778d1ce55843cd52da7db66bcb518c441e46e (patch)
tree47dda753ed3a9a4d115306d0a382c2e28e3aa20d
parent0ff389c0c17b0b2938e79640e86b594344f20e55 (diff)
downloademacs-da6778d1ce55843cd52da7db66bcb518c441e46e.tar.gz
emacs-da6778d1ce55843cd52da7db66bcb518c441e46e.zip
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.
-rw-r--r--src/dispnew.c9
-rw-r--r--src/xterm.c117
-rw-r--r--src/xterm.h21
3 files changed, 102 insertions, 45 deletions
diff --git a/src/dispnew.c b/src/dispnew.c
index 2568ba1086a..5a9ba8909e3 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3152,10 +3152,19 @@ redraw_frame (struct frame *f)
3152 update_begin (f); 3152 update_begin (f);
3153 if (FRAME_MSDOS_P (f)) 3153 if (FRAME_MSDOS_P (f))
3154 FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f)); 3154 FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f));
3155
3156 if (FRAME_WINDOW_P (f))
3157 /* Garbage the frame now. Otherwise, platforms that support
3158 double buffering will display the blank contents of the frame
3159 even though the frame should be redrawn at some point in the
3160 future. */
3161 SET_FRAME_GARBAGED (f);
3162
3155 clear_frame (f); 3163 clear_frame (f);
3156 clear_current_matrices (f); 3164 clear_current_matrices (f);
3157 update_end (f); 3165 update_end (f);
3158 fset_redisplay (f); 3166 fset_redisplay (f);
3167
3159 /* Mark all windows as inaccurate, so that every window will have 3168 /* Mark all windows as inaccurate, so that every window will have
3160 its redisplay done. */ 3169 its redisplay done. */
3161 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0); 3170 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
diff --git a/src/xterm.c b/src/xterm.c
index d35af7a8de2..ee6db62bb94 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -7044,6 +7044,13 @@ x_update_begin (struct frame *f)
7044#else 7044#else
7045 /* Nothing to do. */ 7045 /* Nothing to do. */
7046#endif 7046#endif
7047
7048#ifdef HAVE_XDBE
7049 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7050 /* The frame is no longer complete, as it is in the midst of an
7051 update. */
7052 FRAME_X_COMPLETE_P (f) = false;
7053#endif
7047} 7054}
7048 7055
7049/* Draw a vertical window border from (x,y0) to (x,y1) */ 7056/* Draw a vertical window border from (x,y0) to (x,y1) */
@@ -7190,6 +7197,10 @@ x_flip_and_flush (struct frame *f)
7190#ifdef HAVE_XDBE 7197#ifdef HAVE_XDBE
7191 if (FRAME_X_NEED_BUFFER_FLIP (f)) 7198 if (FRAME_X_NEED_BUFFER_FLIP (f))
7192 show_back_buffer (f); 7199 show_back_buffer (f);
7200
7201 /* The frame is complete again as its contents were just
7202 flushed. */
7203 FRAME_X_COMPLETE_P (f) = true;
7193#endif 7204#endif
7194 x_flush (f); 7205 x_flush (f);
7195 unblock_input (); 7206 unblock_input ();
@@ -7240,6 +7251,9 @@ XTframe_up_to_date (struct frame *f)
7240 if (!buffer_flipping_blocked_p () 7251 if (!buffer_flipping_blocked_p ()
7241 && FRAME_X_NEED_BUFFER_FLIP (f)) 7252 && FRAME_X_NEED_BUFFER_FLIP (f))
7242 show_back_buffer (f); 7253 show_back_buffer (f);
7254
7255 /* The frame is now complete, as its contents have been drawn. */
7256 FRAME_X_COMPLETE_P (f) = true;
7243#endif 7257#endif
7244 7258
7245#ifdef HAVE_XSYNC 7259#ifdef HAVE_XSYNC
@@ -10806,6 +10820,7 @@ x_clear_frame (struct frame *f)
10806 /* We have to clear the scroll bars. If we have changed colors or 10820 /* We have to clear the scroll bars. If we have changed colors or
10807 something like that, then they should be notified. */ 10821 something like that, then they should be notified. */
10808 x_scroll_bar_clear (f); 10822 x_scroll_bar_clear (f);
10823
10809 unblock_input (); 10824 unblock_input ();
10810} 10825}
10811 10826
@@ -10857,7 +10872,7 @@ x_show_hourglass (struct frame *f)
10857 (xcb_window_t) x->hourglass_window, 10872 (xcb_window_t) x->hourglass_window,
10858 parent, 0, 0, FRAME_PIXEL_WIDTH (f), 10873 parent, 0, 0, FRAME_PIXEL_WIDTH (f),
10859 FRAME_PIXEL_HEIGHT (f), 0, 10874 FRAME_PIXEL_HEIGHT (f), 0,
10860 XCB_WINDOW_CLASS_INPUT_OUTPUT, 10875 XCB_WINDOW_CLASS_INPUT_ONLY,
10861 XCB_COPY_FROM_PARENT, XCB_CW_CURSOR, 10876 XCB_COPY_FROM_PARENT, XCB_CW_CURSOR,
10862 &cursor); 10877 &cursor);
10863#endif 10878#endif
@@ -17033,18 +17048,21 @@ x_net_wm_state (struct frame *f, Window window)
17033 17048
17034/* Flip back buffers on F if it has undrawn content. */ 17049/* Flip back buffers on F if it has undrawn content. */
17035 17050
17036#ifdef HAVE_XDBE
17037static void 17051static void
17038flush_dirty_back_buffer_on (struct frame *f) 17052x_flush_dirty_back_buffer_on (struct frame *f)
17039{ 17053{
17040 block_input (); 17054#ifdef HAVE_XDBE
17041 if (!FRAME_GARBAGED_P (f) 17055 if (FRAME_GARBAGED_P (f)
17042 && !buffer_flipping_blocked_p () 17056 || buffer_flipping_blocked_p ()
17043 && FRAME_X_NEED_BUFFER_FLIP (f)) 17057 /* If the frame is not already up to date, do not flush buffers
17044 show_back_buffer (f); 17058 on input, as that will result in flicker. */
17045 unblock_input (); 17059 || !FRAME_X_COMPLETE_P (f)
17046} 17060 || !FRAME_X_NEED_BUFFER_FLIP (f))
17061 return;
17062
17063 show_back_buffer (f);
17047#endif 17064#endif
17065}
17048 17066
17049#ifdef HAVE_GTK3 17067#ifdef HAVE_GTK3
17050void 17068void
@@ -17824,7 +17842,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17824 Time gen_help_time UNINIT; 17842 Time gen_help_time UNINIT;
17825#endif 17843#endif
17826 ptrdiff_t nbytes = 0; 17844 ptrdiff_t nbytes = 0;
17827 struct frame *any, *f = NULL; 17845 struct frame *any, *f = NULL, *mouse_frame;
17828 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight; 17846 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
17829 /* This holds the state XLookupString needs to implement dead keys 17847 /* This holds the state XLookupString needs to implement dead keys
17830 and other tricks known as "compose processing". _X Window System_ 17848 and other tricks known as "compose processing". _X Window System_
@@ -19148,9 +19166,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19148 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window)) 19166 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
19149 ) 19167 )
19150 { 19168 {
19151 clear_mouse_face (hlinfo); 19169 mouse_frame = hlinfo->mouse_face_mouse_frame;
19152 hlinfo->mouse_face_hidden = true; 19170
19153 } 19171 clear_mouse_face (hlinfo);
19172 hlinfo->mouse_face_hidden = true;
19173
19174 if (mouse_frame)
19175 x_flush_dirty_back_buffer_on (mouse_frame);
19176 }
19154 19177
19155#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS 19178#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
19156 if (f == 0) 19179 if (f == 0)
@@ -19630,6 +19653,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19630 { 19653 {
19631 clear_mouse_face (hlinfo); 19654 clear_mouse_face (hlinfo);
19632 hlinfo->mouse_face_mouse_frame = 0; 19655 hlinfo->mouse_face_mouse_frame = 0;
19656 x_flush_dirty_back_buffer_on (xvw->frame);
19633 } 19657 }
19634 19658
19635 if (any_help_event_p) 19659 if (any_help_event_p)
@@ -19783,6 +19807,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19783 certainly no longer on any text in the frame. */ 19807 certainly no longer on any text in the frame. */
19784 clear_mouse_face (hlinfo); 19808 clear_mouse_face (hlinfo);
19785 hlinfo->mouse_face_mouse_frame = 0; 19809 hlinfo->mouse_face_mouse_frame = 0;
19810 x_flush_dirty_back_buffer_on (f);
19786 } 19811 }
19787 19812
19788 /* Generate a nil HELP_EVENT to cancel a help-echo. 19813 /* Generate a nil HELP_EVENT to cancel a help-echo.
@@ -19840,7 +19865,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19840 help_echo_string = Qnil; 19865 help_echo_string = Qnil;
19841 19866
19842 if (hlinfo->mouse_face_hidden) 19867 if (hlinfo->mouse_face_hidden)
19843 { 19868 {
19844 hlinfo->mouse_face_hidden = false; 19869 hlinfo->mouse_face_hidden = false;
19845 clear_mouse_face (hlinfo); 19870 clear_mouse_face (hlinfo);
19846 } 19871 }
@@ -20171,6 +20196,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20171 if (!NILP (help_echo_string) 20196 if (!NILP (help_echo_string)
20172 || !NILP (previous_help_echo_string)) 20197 || !NILP (previous_help_echo_string))
20173 do_help = 1; 20198 do_help = 1;
20199
20200 if (f)
20201 x_flush_dirty_back_buffer_on (f);
20174 goto OTHER; 20202 goto OTHER;
20175 } 20203 }
20176 20204
@@ -20837,9 +20865,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20837 tab_bar_p = EQ (window, f->tab_bar_window); 20865 tab_bar_p = EQ (window, f->tab_bar_window);
20838 20866
20839 if (tab_bar_p) 20867 if (tab_bar_p)
20840 tab_bar_arg = handle_tab_bar_click 20868 {
20841 (f, x, y, event->xbutton.type == ButtonPress, 20869 tab_bar_arg = handle_tab_bar_click
20842 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state)); 20870 (f, x, y, event->xbutton.type == ButtonPress,
20871 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
20872 x_flush_dirty_back_buffer_on (f);
20873 }
20843 } 20874 }
20844 20875
20845#if ! defined (USE_GTK) 20876#if ! defined (USE_GTK)
@@ -20857,9 +20888,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20857 || f->last_tool_bar_item != -1)); 20888 || f->last_tool_bar_item != -1));
20858 20889
20859 if (tool_bar_p && event->xbutton.button < 4) 20890 if (tool_bar_p && event->xbutton.button < 4)
20860 handle_tool_bar_click 20891 {
20861 (f, x, y, event->xbutton.type == ButtonPress, 20892 handle_tool_bar_click
20862 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state)); 20893 (f, x, y, event->xbutton.type == ButtonPress,
20894 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
20895 x_flush_dirty_back_buffer_on (f);
20896 }
20863 } 20897 }
20864#endif /* !USE_GTK */ 20898#endif /* !USE_GTK */
20865 20899
@@ -21398,6 +21432,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21398 certainly no longer on any text in the frame. */ 21432 certainly no longer on any text in the frame. */
21399 clear_mouse_face (hlinfo); 21433 clear_mouse_face (hlinfo);
21400 hlinfo->mouse_face_mouse_frame = 0; 21434 hlinfo->mouse_face_mouse_frame = 0;
21435 x_flush_dirty_back_buffer_on (f);
21401 } 21436 }
21402 21437
21403 /* Generate a nil HELP_EVENT to cancel a help-echo. 21438 /* Generate a nil HELP_EVENT to cancel a help-echo.
@@ -22073,6 +22108,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22073 22108
22074 do_help = 1; 22109 do_help = 1;
22075 } 22110 }
22111
22112 if (f)
22113 x_flush_dirty_back_buffer_on (f);
22076 goto XI_OTHER; 22114 goto XI_OTHER;
22077 } 22115 }
22078 22116
@@ -22592,9 +22630,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22592 tab_bar_p = EQ (window, f->tab_bar_window); 22630 tab_bar_p = EQ (window, f->tab_bar_window);
22593 22631
22594 if (tab_bar_p) 22632 if (tab_bar_p)
22595 tab_bar_arg = handle_tab_bar_click 22633 {
22596 (f, x, y, xev->evtype == XI_ButtonPress, 22634 tab_bar_arg = handle_tab_bar_click
22597 x_x_to_emacs_modifiers (dpyinfo, bv.state)); 22635 (f, x, y, xev->evtype == XI_ButtonPress,
22636 x_x_to_emacs_modifiers (dpyinfo, bv.state));
22637 x_flush_dirty_back_buffer_on (f);
22638 }
22598 } 22639 }
22599 22640
22600#if ! defined (USE_GTK) 22641#if ! defined (USE_GTK)
@@ -22619,10 +22660,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22619 || f->last_tool_bar_item != -1)); 22660 || f->last_tool_bar_item != -1));
22620 22661
22621 if (tool_bar_p && xev->detail < 4) 22662 if (tool_bar_p && xev->detail < 4)
22622 handle_tool_bar_click_with_device 22663 {
22623 (f, x, y, xev->evtype == XI_ButtonPress, 22664 handle_tool_bar_click_with_device
22624 x_x_to_emacs_modifiers (dpyinfo, bv.state), 22665 (f, x, y, xev->evtype == XI_ButtonPress,
22625 source ? source->name : Qt); 22666 x_x_to_emacs_modifiers (dpyinfo, bv.state),
22667 source ? source->name : Qt);
22668 x_flush_dirty_back_buffer_on (f);
22669 }
22626 } 22670 }
22627#endif /* !USE_GTK */ 22671#endif /* !USE_GTK */
22628 22672
@@ -22919,8 +22963,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22919 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window)) 22963 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
22920 ) 22964 )
22921 { 22965 {
22966 mouse_frame = hlinfo->mouse_face_mouse_frame;
22967
22922 clear_mouse_face (hlinfo); 22968 clear_mouse_face (hlinfo);
22923 hlinfo->mouse_face_hidden = true; 22969 hlinfo->mouse_face_hidden = true;
22970
22971 if (mouse_frame)
22972 x_flush_dirty_back_buffer_on (mouse_frame);
22924 } 22973 }
22925 22974
22926 if (f != 0) 22975 if (f != 0)
@@ -24084,18 +24133,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
24084 count++; 24133 count++;
24085 } 24134 }
24086 24135
24087 /* Sometimes event processing draws to either F or ANY outside
24088 redisplay. To ensure that these changes become visible, draw
24089 them here. */
24090
24091#ifdef HAVE_XDBE
24092 if (f)
24093 flush_dirty_back_buffer_on (f);
24094
24095 if (any && any != f)
24096 flush_dirty_back_buffer_on (any);
24097#endif
24098
24099 SAFE_FREE (); 24136 SAFE_FREE ();
24100 return count; 24137 return count;
24101} 24138}
diff --git a/src/xterm.h b/src/xterm.h
index b68a234faa5..55fd193a29f 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -916,11 +916,6 @@ struct x_output
916 Picture picture; 916 Picture picture;
917#endif 917#endif
918 918
919 /* Flag that indicates whether we've modified the back buffer and
920 need to publish our modifications to the front buffer at a
921 convenient time. */
922 bool need_buffer_flip;
923
924 /* The X window used for the bitmap icon; 919 /* The X window used for the bitmap icon;
925 or 0 if we don't have a bitmap icon. */ 920 or 0 if we don't have a bitmap icon. */
926 Window icon_desc; 921 Window icon_desc;
@@ -1091,6 +1086,18 @@ struct x_output
1091 and inactive states. */ 1086 and inactive states. */
1092 bool_bf alpha_identical_p : 1; 1087 bool_bf alpha_identical_p : 1;
1093 1088
1089#ifdef HAVE_XDBE
1090 /* Flag that indicates whether we've modified the back buffer and
1091 need to publish our modifications to the front buffer at a
1092 convenient time. */
1093 bool_bf need_buffer_flip : 1;
1094
1095 /* Flag that indicates whether or not the frame contents are
1096 complete and can be safely flushed while handling async
1097 input. */
1098 bool_bf complete : 1;
1099#endif
1100
1094#ifdef HAVE_X_I18N 1101#ifdef HAVE_X_I18N
1095 /* Input context (currently, this means Compose key handler setup). */ 1102 /* Input context (currently, this means Compose key handler setup). */
1096 XIC xic; 1103 XIC xic;
@@ -1248,6 +1255,10 @@ extern void x_mark_frame_dirty (struct frame *f);
1248 1255
1249/* Return the need-buffer-flip flag for frame F. */ 1256/* Return the need-buffer-flip flag for frame F. */
1250#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip) 1257#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip)
1258
1259/* Return whether or not the frame F has been completely drawn. Used
1260 while handling async input. */
1261#define FRAME_X_COMPLETE_P(f) ((f)->output_data.x->complete)
1251#endif 1262#endif
1252 1263
1253/* Return the outermost X window associated with the frame F. */ 1264/* Return the outermost X window associated with the frame F. */