diff options
| author | Po Lu | 2022-10-16 14:02:31 +0800 |
|---|---|---|
| committer | Po Lu | 2022-10-16 14:02:31 +0800 |
| commit | da6778d1ce55843cd52da7db66bcb518c441e46e (patch) | |
| tree | 47dda753ed3a9a4d115306d0a382c2e28e3aa20d | |
| parent | 0ff389c0c17b0b2938e79640e86b594344f20e55 (diff) | |
| download | emacs-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.c | 9 | ||||
| -rw-r--r-- | src/xterm.c | 117 | ||||
| -rw-r--r-- | src/xterm.h | 21 |
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 | ||
| 17037 | static void | 17051 | static void |
| 17038 | flush_dirty_back_buffer_on (struct frame *f) | 17052 | x_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 |
| 17050 | void | 17068 | void |
| @@ -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. */ |