aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Colascione2016-10-20 20:34:36 -0700
committerDaniel Colascione2016-10-28 19:21:39 -0700
commitc29071587c64efb30792bd72248d3c791abd9337 (patch)
treea38c726630104997b7d63cbba56056ed1f8d19fa /src
parentf5543ffcf5b2974fa8fc6cf007e9109fa8e9051e (diff)
downloademacs-c29071587c64efb30792bd72248d3c791abd9337.tar.gz
emacs-c29071587c64efb30792bd72248d3c791abd9337.zip
Add double-buffering support to reduce flicker
* src/dispextern.h (struct glyph_string): Remove window member (block_buffer_flips, unblock_buffer_flips) (buffer_flipping_blocked_p): Declare. * src/xterm.h (struct x_display_info): New member supports_xdbe. (struct x_output): New members draw_desc and need_buffer_flip. (FRAME_X_DRAWABLE, FRAME_X_RAW_DRAWABLE) (FRAME_X_DOUBLE_BUFFERED_P) (FRAME_X_NEED_BUFFER_FLIP): New macros. (set_up_x_back_buffer, tear_down_x_back_buffer) (initial_set_up_x_back_buffer): Declare. * src/xterm.c: Include Xdbe.h. (x_begin_cr_clip, x_fill_rectangle, x_draw_rectangle) (x_draw_vertical_window_border, x_update_end) (x_setup_relief_color, x_draw_relief_rect) (x_draw_fringe_bitmap, x_shift_glyphs_for_insert) (x_scroll_run, x_draw_hollow_cursor, x_draw_bar_cursor): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW; rename local variables appropriately; substitute calls to XClearArea with x_clear_area, which DTRT for double buffering. (x_clear_window, x_clear_area): In double-buffering mode, use rect-drawing X functions instead of XClearWindow and XClearArea, which always operate on the front buffer. (show_back_buffer): New function. (XTframe_up_to_date): Call show_back_buffer when done. (x_clear_frame, x_clear_frame_area): Remove obsolete calls to gtk_widget_queue_draw to refresh scroll bars; scroll bars are now independent X windows. (handle_one_xevent): Call font_drop_xrender_surfaces when XftDraw might need regenerating; perform buffer flip when responding to Expose events; issue front-buffer clearing commands as stopgap while we wait for redisplay. Call flush_dirty_back_buffers. (x_make_frame_visible): Un-bitrot comment; move XSETFRAME earlier in function. (x_free_frame_resources): Call tear_down_x_back_buffer when destroying frame. (x_term_init): Attempt to initialize double buffer extension. (x_flip_and_flush): New function. (x_redisplay_interface): Point to x_flip_and_flush instead of x_flip directly. (flush_dirty_back_buffers): New function. (x_create_terminal): Register buffer_flipping_unblocked_hook. * src/xftfont.c (xftfont_drop_xrender_surfaces): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW. (xftfont_draw): Call x_mark_frame_dirty. (xftfont_drop_xrender_surfaces): New function. (syms_of_xftfont): Register it. * src/xfont.c (xfont_draw): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW. * src/xfns.c: Include Xdbe.h. (x_set_inhibit_double_buffering, set_up_x_back_buffer) (Fx_double_buffered_p): New functions. (x_window): Call initial_set_up_x_back_buffer. (x_make_gc): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW. (Fx_create_frame): Configure `inhibit-double-buffering' frame parameter. (x_create_tip_frame): Call initial_set_up_x_back_buffer. (x_frame_parm_handlers): Register x_set_inhibit_double_buffering. (syms_of_xfns): Register Sx_double_buffered_p. (x_mark_frame_dirty): Define. * src/xfaces.c (x_create_gc): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW. * src/xdisp.c (remember_mouse_glyph, init_glyph_string): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW. (redisplay_internal): Restart redisplay if a frame is garbaged during updating; explain why. Block buffer flips during redisplay. (redisplay_preserve_echo_area): Block buffer flip during call to redisplay_internal. (buffer_flip_blocked_depth): New variable. (block_buffer_flips, unblock_buffer_flips) (buffer_flipping_blocked_p): New functions. (init_glyph_string): Stop setting window member of struct glyph_string. * src/w32fns.c (w32_frame_parm_handlers): Add placeholder for x_set_inhibit_double_buffering. * src/termhooks.h (struct terminal): Add buffer_flipping_unblocked_hook. * src/nsfns.m (ns_frame_parm_handlers): Add placeholder for x_set_inhibit_double_buffering. * src/image.c (x_create_bitmap_from_data) (x_create_bitmap_from_file, x_create_x_image_and_pixmap) (Create_Pixmap_From_Bitmap_Data) (x_create_bitmap_from_xpm_data, xpm_load, gs_load): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW; rename local variables appropriately. * src/gtkutil.c: Include Xdbe.h. (xg_get_widget_from_map): Forward declare. (xg_clear_under_internal_border): Remove obsolete calls to refresh scroll bars. (xg_create_frame_widgets): Call initial_set_up_x_back_buffer. (xg_free_frame_widgets): Call tear_down_x_back_buffer; reset FRAME_X_DRAWABLE as well as FRAME_X_WINDOW and for the same reason. (xg_set_background_color): Set scroll bar background colors. (xg_finish_scroll_bar_creation): New function with common logic of xg_create_scroll_bar, xg_create_horizontal_scroll_bar. Force scroll bars to be real X11 windows. (xg_create_scroll_bar, xg_create_horizontal_scroll_bar): Call xg_finish_scroll_bar_creation. (xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos): Remove obsolete calls to refresh scroll bars; fix comments. * src/ftxfont.c (ftxfont_get_gcs, ftxfont_draw_bitmap, (ftxfont_draw_background): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW. * src/frame.c (frame_parms): Add table entry for new `inhibit-double-buffering' frame parameter (syms_of_frame): Register Qinhibit_double_buffering. * src/font.h (struct font_driver): Add new `flush_frame_caches' hook. (font_drop_xrender_surfaces): Declare. * src/font.c (font_drop_xrender_surfaces): New function. * src/Makefile.in (XDBE_LIBS, XDBE_CFLAGS): Substitute. * etc/NEWS: Mention use of double buffering * doc/lispref/frames.texi (Management Parameters): Document `inhibit-double-buffering' frame parameters. (Visibility of Frames): Document `x-double-buffered-p'. * configure.ac: Check for the X double buffer extension
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in6
-rw-r--r--src/dispextern.h5
-rw-r--r--src/font.c10
-rw-r--r--src/font.h11
-rw-r--r--src/frame.c2
-rw-r--r--src/ftxfont.c14
-rw-r--r--src/gtkutil.c167
-rw-r--r--src/image.c20
-rw-r--r--src/nsfns.m1
-rw-r--r--src/termhooks.h5
-rw-r--r--src/w32fns.c1
-rw-r--r--src/xdisp.c69
-rw-r--r--src/xfaces.c2
-rw-r--r--src/xfns.c128
-rw-r--r--src/xfont.c16
-rw-r--r--src/xftfont.c31
-rw-r--r--src/xterm.c288
-rw-r--r--src/xterm.h35
18 files changed, 595 insertions, 216 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 89f7a921faa..dc0bfff9b33 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -254,6 +254,9 @@ XINERAMA_CFLAGS = @XINERAMA_CFLAGS@
254XFIXES_LIBS = @XFIXES_LIBS@ 254XFIXES_LIBS = @XFIXES_LIBS@
255XFIXES_CFLAGS = @XFIXES_CFLAGS@ 255XFIXES_CFLAGS = @XFIXES_CFLAGS@
256 256
257XDBE_LIBS = @XDBE_LIBS@
258XDBE_CFLAGS = @XDBE_CFLAGS@
259
257## widget.o if USE_X_TOOLKIT, otherwise empty. 260## widget.o if USE_X_TOOLKIT, otherwise empty.
258WIDGET_OBJ=@WIDGET_OBJ@ 261WIDGET_OBJ=@WIDGET_OBJ@
259 262
@@ -372,7 +375,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
372 $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ 375 $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
373 $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ 376 $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
374 $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ 377 $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
375 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ 378 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \
376 $(WEBKIT_CFLAGS) \ 379 $(WEBKIT_CFLAGS) \
377 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ 380 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
378 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ 381 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
@@ -489,6 +492,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
489 $(WEBKIT_LIBS) \ 492 $(WEBKIT_LIBS) \
490 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ 493 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
491 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ 494 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
495 $(XDBE_LIBS) \
492 $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ 496 $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
493 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 497 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
494 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ 498 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
diff --git a/src/dispextern.h b/src/dispextern.h
index 79bc9353ec5..f27279975ac 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1276,7 +1276,6 @@ struct glyph_string
1276 1276
1277 /* X display and window for convenience. */ 1277 /* X display and window for convenience. */
1278 Display *display; 1278 Display *display;
1279 Window window;
1280 1279
1281 /* The glyph row for which this string was built. It determines the 1280 /* The glyph row for which this string was built. It determines the
1282 y-origin and height of the string. */ 1281 y-origin and height of the string. */
@@ -3357,6 +3356,10 @@ void x_cr_init_fringe (struct redisplay_interface *);
3357 3356
3358extern unsigned row_hash (struct glyph_row *); 3357extern unsigned row_hash (struct glyph_row *);
3359 3358
3359extern void block_buffer_flips(void);
3360extern void unblock_buffer_flips(void);
3361extern bool buffer_flipping_blocked_p(void);
3362
3360/* Defined in image.c */ 3363/* Defined in image.c */
3361 3364
3362#ifdef HAVE_WINDOW_SYSTEM 3365#ifdef HAVE_WINDOW_SYSTEM
diff --git a/src/font.c b/src/font.c
index f8e6794cbb1..ce632335256 100644
--- a/src/font.c
+++ b/src/font.c
@@ -5275,6 +5275,16 @@ font_deferred_log (const char *action, Lisp_Object arg, Lisp_Object result)
5275} 5275}
5276 5276
5277void 5277void
5278font_drop_xrender_surfaces (struct frame *f)
5279{
5280 struct font_driver_list *list;
5281
5282 for (list = f->font_driver_list; list; list = list->next)
5283 if (list->on && list->driver->drop_xrender_surfaces)
5284 list->driver->drop_xrender_surfaces (f);
5285}
5286
5287void
5278syms_of_font (void) 5288syms_of_font (void)
5279{ 5289{
5280 sort_shift_bits[FONT_TYPE_INDEX] = 0; 5290 sort_shift_bits[FONT_TYPE_INDEX] = 0;
diff --git a/src/font.h b/src/font.h
index cf477290d06..c14823bc1eb 100644
--- a/src/font.h
+++ b/src/font.h
@@ -763,6 +763,13 @@ struct font_driver
763 Return non-nil if the driver support rendering of combining 763 Return non-nil if the driver support rendering of combining
764 characters for FONT according to Unicode combining class. */ 764 characters for FONT according to Unicode combining class. */
765 Lisp_Object (*combining_capability) (struct font *font); 765 Lisp_Object (*combining_capability) (struct font *font);
766
767 /* Optional
768
769 Called when frame F is double-buffered and its size changes; Xft
770 relies on this hook to throw away its old XftDraw (which won't
771 work after the size change) and get a new one. */
772 void (*drop_xrender_surfaces) (struct frame *f);
766}; 773};
767 774
768 775
@@ -862,7 +869,9 @@ extern void *font_get_frame_data (struct frame *f, Lisp_Object);
862extern void font_filter_properties (Lisp_Object font, 869extern void font_filter_properties (Lisp_Object font,
863 Lisp_Object alist, 870 Lisp_Object alist,
864 const char *const boolean_properties[], 871 const char *const boolean_properties[],
865 const char *const non_boolean_properties[]); 872 const char *const non_boolean_properties[]);
873
874extern void font_drop_xrender_surfaces (struct frame *f);
866 875
867#ifdef HAVE_FREETYPE 876#ifdef HAVE_FREETYPE
868extern struct font_driver ftfont_driver; 877extern struct font_driver ftfont_driver;
diff --git a/src/frame.c b/src/frame.c
index f3a548cbce7..3a2d009d325 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3128,6 +3128,7 @@ static const struct frame_parm_table frame_parms[] =
3128 {"alpha", SYMBOL_INDEX (Qalpha)}, 3128 {"alpha", SYMBOL_INDEX (Qalpha)},
3129 {"sticky", SYMBOL_INDEX (Qsticky)}, 3129 {"sticky", SYMBOL_INDEX (Qsticky)},
3130 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)}, 3130 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
3131 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
3131}; 3132};
3132 3133
3133#ifdef HAVE_WINDOW_SYSTEM 3134#ifdef HAVE_WINDOW_SYSTEM
@@ -5044,6 +5045,7 @@ syms_of_frame (void)
5044 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars"); 5045 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
5045 DEFSYM (Qvisibility, "visibility"); 5046 DEFSYM (Qvisibility, "visibility");
5046 DEFSYM (Qwait_for_wm, "wait-for-wm"); 5047 DEFSYM (Qwait_for_wm, "wait-for-wm");
5048 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
5047 5049
5048 { 5050 {
5049 int i; 5051 int i;
diff --git a/src/ftxfont.c b/src/ftxfont.c
index f49d44ffc20..bfdeb4051b9 100644
--- a/src/ftxfont.c
+++ b/src/ftxfont.c
@@ -95,7 +95,7 @@ ftxfont_get_gcs (struct frame *f, unsigned long foreground, unsigned long backgr
95 if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color)) 95 if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
96 break; 96 break;
97 xgcv.foreground = color.pixel; 97 xgcv.foreground = color.pixel;
98 new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 98 new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
99 GCForeground, &xgcv); 99 GCForeground, &xgcv);
100 } 100 }
101 unblock_input (); 101 unblock_input ();
@@ -139,14 +139,14 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
139 p[n[0]].y = y - bitmap.top + i; 139 p[n[0]].y = y - bitmap.top + i;
140 if (++n[0] == size) 140 if (++n[0] == size)
141 { 141 {
142 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 142 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
143 gc_fore, p, size, CoordModeOrigin); 143 gc_fore, p, size, CoordModeOrigin);
144 n[0] = 0; 144 n[0] = 0;
145 } 145 }
146 } 146 }
147 } 147 }
148 if (flush && n[0] > 0) 148 if (flush && n[0] > 0)
149 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 149 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
150 gc_fore, p, n[0], CoordModeOrigin); 150 gc_fore, p, n[0], CoordModeOrigin);
151 } 151 }
152 else 152 else
@@ -168,7 +168,7 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
168 pp[n[idx]].y = y - bitmap.top + i; 168 pp[n[idx]].y = y - bitmap.top + i;
169 if (++(n[idx]) == size) 169 if (++(n[idx]) == size)
170 { 170 {
171 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 171 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
172 idx == 6 ? gc_fore : gcs[idx], pp, size, 172 idx == 6 ? gc_fore : gcs[idx], pp, size,
173 CoordModeOrigin); 173 CoordModeOrigin);
174 n[idx] = 0; 174 n[idx] = 0;
@@ -180,10 +180,10 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
180 { 180 {
181 for (i = 0; i < 6; i++) 181 for (i = 0; i < 6; i++)
182 if (n[i] > 0) 182 if (n[i] > 0)
183 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 183 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
184 gcs[i], p + 0x100 * i, n[i], CoordModeOrigin); 184 gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
185 if (n[6] > 0) 185 if (n[6] > 0)
186 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 186 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
187 gc_fore, p + 0x600, n[6], CoordModeOrigin); 187 gc_fore, p + 0x600, n[6], CoordModeOrigin);
188 } 188 }
189 } 189 }
@@ -203,7 +203,7 @@ ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y
203 XGetGCValues (FRAME_X_DISPLAY (f), gc, 203 XGetGCValues (FRAME_X_DISPLAY (f), gc,
204 GCForeground | GCBackground, &xgcv); 204 GCForeground | GCBackground, &xgcv);
205 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background); 205 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
206 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, 206 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
207 x, y - FONT_BASE (font), width, FONT_HEIGHT (font)); 207 x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
208 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground); 208 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
209} 209}
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 88e6d30bd9a..986eca85587 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -48,6 +48,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
48#include "emacsgtkfixed.h" 48#include "emacsgtkfixed.h"
49#endif 49#endif
50 50
51#ifdef HAVE_XDBE
52#include <X11/extensions/Xdbe.h>
53#endif
54
51#ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW 55#ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
52#define gtk_widget_set_has_window(w, b) \ 56#define gtk_widget_set_has_window(w, b) \
53 (gtk_fixed_set_has_window (GTK_FIXED (w), b)) 57 (gtk_fixed_set_has_window (GTK_FIXED (w), b))
@@ -143,6 +147,8 @@ struct xg_frame_tb_info
143 GtkTextDirection dir; 147 GtkTextDirection dir;
144}; 148};
145 149
150static GtkWidget * xg_get_widget_from_map (ptrdiff_t idx);
151
146 152
147/*********************************************************************** 153/***********************************************************************
148 Display handling functions 154 Display handling functions
@@ -815,12 +821,6 @@ xg_clear_under_internal_border (struct frame *f)
815{ 821{
816 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) 822 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
817 { 823 {
818#ifndef USE_CAIRO
819 GtkWidget *wfixed = f->output_data.x->edit_widget;
820
821 gtk_widget_queue_draw (wfixed);
822 gdk_window_process_all_updates ();
823#endif
824 x_clear_area (f, 0, 0, 824 x_clear_area (f, 0, 0,
825 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); 825 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
826 826
@@ -1233,6 +1233,7 @@ xg_create_frame_widgets (struct frame *f)
1233 by callers of this function. */ 1233 by callers of this function. */
1234 gtk_widget_realize (wfixed); 1234 gtk_widget_realize (wfixed);
1235 FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed); 1235 FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed);
1236 initial_set_up_x_back_buffer (f);
1236 1237
1237 /* Since GTK clears its window by filling with the background color, 1238 /* Since GTK clears its window by filling with the background color,
1238 we must keep X and GTK background in sync. */ 1239 we must keep X and GTK background in sync. */
@@ -1296,8 +1297,11 @@ xg_free_frame_widgets (struct frame *f)
1296 if (tbinfo) 1297 if (tbinfo)
1297 xfree (tbinfo); 1298 xfree (tbinfo);
1298 1299
1300 /* x_free_frame_resources should have taken care of it */
1301 eassert (!FRAME_X_DOUBLE_BUFFERED_P (f));
1299 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); 1302 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
1300 FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */ 1303 FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
1304 FRAME_X_RAW_DRAWABLE (f) = 0;
1301 FRAME_GTK_OUTER_WIDGET (f) = 0; 1305 FRAME_GTK_OUTER_WIDGET (f) = 0;
1302#ifdef USE_GTK_TOOLTIP 1306#ifdef USE_GTK_TOOLTIP
1303 if (x->ttip_lbl) 1307 if (x->ttip_lbl)
@@ -1440,6 +1444,18 @@ xg_set_background_color (struct frame *f, unsigned long bg)
1440 { 1444 {
1441 block_input (); 1445 block_input ();
1442 xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f)); 1446 xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f));
1447
1448 Lisp_Object bar;
1449 for (bar = FRAME_SCROLL_BARS (f);
1450 !NILP (bar);
1451 bar = XSCROLL_BAR (bar)->next)
1452 {
1453 GtkWidget *scrollbar =
1454 xg_get_widget_from_map (XSCROLL_BAR (bar)->x_window);
1455 GtkWidget *webox = gtk_widget_get_parent (scrollbar);
1456 xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f));
1457 }
1458
1443 unblock_input (); 1459 unblock_input ();
1444 } 1460 }
1445} 1461}
@@ -2265,7 +2281,6 @@ xg_mark_data (void)
2265 } 2281 }
2266} 2282}
2267 2283
2268
2269/* Callback called when a menu item is destroyed. Used to free data. 2284/* Callback called when a menu item is destroyed. Used to free data.
2270 W is the widget that is being destroyed (not used). 2285 W is the widget that is being destroyed (not used).
2271 CLIENT_DATA points to the xg_menu_item_cb_data associated with the W. */ 2286 CLIENT_DATA points to the xg_menu_item_cb_data associated with the W. */
@@ -3569,44 +3584,23 @@ xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data)
3569 xg_remove_widget_from_map (id); 3584 xg_remove_widget_from_map (id);
3570} 3585}
3571 3586
3572/* Create a scroll bar widget for frame F. Store the scroll bar 3587static void
3573 in BAR. 3588xg_finish_scroll_bar_creation (struct frame *f,
3574 SCROLL_CALLBACK is the callback to invoke when the value of the 3589 GtkWidget *wscroll,
3575 bar changes. 3590 struct scroll_bar *bar,
3576 END_CALLBACK is the callback to invoke when scrolling ends. 3591 GCallback scroll_callback,
3577 SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used 3592 GCallback end_callback,
3578 to set resources for the widget. */ 3593 const char *scroll_bar_name)
3579
3580void
3581xg_create_scroll_bar (struct frame *f,
3582 struct scroll_bar *bar,
3583 GCallback scroll_callback,
3584 GCallback end_callback,
3585 const char *scroll_bar_name)
3586{ 3594{
3587 GtkWidget *wscroll; 3595 GtkWidget *webox = gtk_event_box_new ();
3588 GtkWidget *webox;
3589 intptr_t scroll_id;
3590#ifdef HAVE_GTK3
3591 GtkAdjustment *vadj;
3592#else
3593 GtkObject *vadj;
3594#endif
3595 3596
3596 /* Page, step increment values are not so important here, they
3597 will be corrected in x_set_toolkit_scroll_bar_thumb. */
3598 vadj = gtk_adjustment_new (XG_SB_MIN, XG_SB_MIN, XG_SB_MAX,
3599 0.1, 0.1, 0.1);
3600
3601 wscroll = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (vadj));
3602 webox = gtk_event_box_new ();
3603 gtk_widget_set_name (wscroll, scroll_bar_name); 3597 gtk_widget_set_name (wscroll, scroll_bar_name);
3604#ifndef HAVE_GTK3 3598#ifndef HAVE_GTK3
3605 gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); 3599 gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
3606#endif 3600#endif
3607 g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f); 3601 g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
3608 3602
3609 scroll_id = xg_store_widget_in_map (wscroll); 3603 ptrdiff_t scroll_id = xg_store_widget_in_map (wscroll);
3610 3604
3611 g_signal_connect (G_OBJECT (wscroll), 3605 g_signal_connect (G_OBJECT (wscroll),
3612 "destroy", 3606 "destroy",
@@ -3630,11 +3624,52 @@ xg_create_scroll_bar (struct frame *f,
3630 gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); 3624 gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1);
3631 gtk_container_add (GTK_CONTAINER (webox), wscroll); 3625 gtk_container_add (GTK_CONTAINER (webox), wscroll);
3632 3626
3627 xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f));
3628
3629 /* N.B. The event box doesn't become a real X11 window until we ask
3630 for its XID via GTK_WIDGET_TO_X_WIN. If the event box is not a
3631 real X window, it and its scroll-bar child try to draw on the
3632 Emacs main window, which we draw over using Xlib. */
3633 gtk_widget_realize (webox);
3634 GTK_WIDGET_TO_X_WIN (webox);
3633 3635
3634 /* Set the cursor to an arrow. */ 3636 /* Set the cursor to an arrow. */
3635 xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); 3637 xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
3636 3638
3637 bar->x_window = scroll_id; 3639 bar->x_window = scroll_id;
3640}
3641
3642/* Create a scroll bar widget for frame F. Store the scroll bar
3643 in BAR.
3644 SCROLL_CALLBACK is the callback to invoke when the value of the
3645 bar changes.
3646 END_CALLBACK is the callback to invoke when scrolling ends.
3647 SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used
3648 to set resources for the widget. */
3649
3650void
3651xg_create_scroll_bar (struct frame *f,
3652 struct scroll_bar *bar,
3653 GCallback scroll_callback,
3654 GCallback end_callback,
3655 const char *scroll_bar_name)
3656{
3657 GtkWidget *wscroll;
3658#ifdef HAVE_GTK3
3659 GtkAdjustment *vadj;
3660#else
3661 GtkObject *vadj;
3662#endif
3663
3664 /* Page, step increment values are not so important here, they
3665 will be corrected in x_set_toolkit_scroll_bar_thumb. */
3666 vadj = gtk_adjustment_new (XG_SB_MIN, XG_SB_MIN, XG_SB_MAX,
3667 0.1, 0.1, 0.1);
3668
3669 wscroll = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (vadj));
3670
3671 xg_finish_scroll_bar_creation (f, wscroll, bar, scroll_callback,
3672 end_callback, scroll_bar_name);
3638 bar->horizontal = 0; 3673 bar->horizontal = 0;
3639} 3674}
3640 3675
@@ -3652,8 +3687,6 @@ xg_create_horizontal_scroll_bar (struct frame *f,
3652 const char *scroll_bar_name) 3687 const char *scroll_bar_name)
3653{ 3688{
3654 GtkWidget *wscroll; 3689 GtkWidget *wscroll;
3655 GtkWidget *webox;
3656 intptr_t scroll_id;
3657#ifdef HAVE_GTK3 3690#ifdef HAVE_GTK3
3658 GtkAdjustment *hadj; 3691 GtkAdjustment *hadj;
3659#else 3692#else
@@ -3666,42 +3699,9 @@ xg_create_horizontal_scroll_bar (struct frame *f,
3666 0.1, 0.1, 0.1); 3699 0.1, 0.1, 0.1);
3667 3700
3668 wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj)); 3701 wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj));
3669 webox = gtk_event_box_new ();
3670 gtk_widget_set_name (wscroll, scroll_bar_name);
3671#ifndef HAVE_GTK3
3672 gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
3673#endif
3674 g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
3675
3676 scroll_id = xg_store_widget_in_map (wscroll);
3677
3678 g_signal_connect (G_OBJECT (wscroll),
3679 "destroy",
3680 G_CALLBACK (xg_gtk_scroll_destroy),
3681 (gpointer) scroll_id);
3682 g_signal_connect (G_OBJECT (wscroll),
3683 "change-value",
3684 scroll_callback,
3685 (gpointer) bar);
3686 g_signal_connect (G_OBJECT (wscroll),
3687 "button-release-event",
3688 end_callback,
3689 (gpointer) bar);
3690
3691 /* The scroll bar widget does not draw on a window of its own. Instead
3692 it draws on the parent window, in this case the edit widget. So
3693 whenever the edit widget is cleared, the scroll bar needs to redraw
3694 also, which causes flicker. Put an event box between the edit widget
3695 and the scroll bar, so the scroll bar instead draws itself on the
3696 event box window. */
3697 gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1);
3698 gtk_container_add (GTK_CONTAINER (webox), wscroll);
3699 3702
3700 3703 xg_finish_scroll_bar_creation (f, wscroll, bar, scroll_callback,
3701 /* Set the cursor to an arrow. */ 3704 end_callback, scroll_bar_name);
3702 xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
3703
3704 bar->x_window = scroll_id;
3705 bar->horizontal = 1; 3705 bar->horizontal = 1;
3706} 3706}
3707 3707
@@ -3770,16 +3770,10 @@ xg_update_scrollbar_pos (struct frame *f,
3770 gtk_widget_show_all (wparent); 3770 gtk_widget_show_all (wparent);
3771 gtk_widget_set_size_request (wscroll, width, height); 3771 gtk_widget_set_size_request (wscroll, width, height);
3772 } 3772 }
3773#ifndef USE_CAIRO
3774 gtk_widget_queue_draw (wfixed);
3775 gdk_window_process_all_updates ();
3776#endif
3777 if (oldx != -1 && oldw > 0 && oldh > 0) 3773 if (oldx != -1 && oldw > 0 && oldh > 0)
3778 { 3774 {
3779 /* Clear under old scroll bar position. This must be done after 3775 /* Clear under old scroll bar position. */
3780 the gtk_widget_queue_draw and gdk_window_process_all_updates 3776 oldw += (scale - 1) * oldw;
3781 above. */
3782 oldw += (scale - 1) * oldw;
3783 oldx -= (scale - 1) * oldw; 3777 oldx -= (scale - 1) * oldw;
3784 x_clear_area (f, oldx, oldy, oldw, oldh); 3778 x_clear_area (f, oldx, oldy, oldw, oldh);
3785 } 3779 }
@@ -3841,14 +3835,9 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
3841 gtk_widget_show_all (wparent); 3835 gtk_widget_show_all (wparent);
3842 gtk_widget_set_size_request (wscroll, width, height); 3836 gtk_widget_set_size_request (wscroll, width, height);
3843 } 3837 }
3844 gtk_widget_queue_draw (wfixed);
3845 gdk_window_process_all_updates ();
3846 if (oldx != -1 && oldw > 0 && oldh > 0) 3838 if (oldx != -1 && oldw > 0 && oldh > 0)
3847 /* Clear under old scroll bar position. This must be done after 3839 /* Clear under old scroll bar position. */
3848 the gtk_widget_queue_draw and gdk_window_process_all_updates 3840 x_clear_area (f, oldx, oldy, oldw, oldh);
3849 above. */
3850 x_clear_area (f,
3851 oldx, oldy, oldw, oldh);
3852 3841
3853 /* GTK does not redraw until the main loop is entered again, but 3842 /* GTK does not redraw until the main loop is entered again, but
3854 if there are no X events pending we will not enter it. So we sync 3843 if there are no X events pending we will not enter it. So we sync
diff --git a/src/image.c b/src/image.c
index 9bd245585c6..1303a931263 100644
--- a/src/image.c
+++ b/src/image.c
@@ -220,7 +220,7 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi
220 220
221#ifdef HAVE_X_WINDOWS 221#ifdef HAVE_X_WINDOWS
222 Pixmap bitmap; 222 Pixmap bitmap;
223 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 223 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
224 bits, width, height); 224 bits, width, height);
225 if (! bitmap) 225 if (! bitmap)
226 return -1; 226 return -1;
@@ -327,7 +327,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
327 327
328 filename = SSDATA (found); 328 filename = SSDATA (found);
329 329
330 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 330 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
331 filename, &width, &height, &bitmap, &xhot, &yhot); 331 filename, &width, &height, &bitmap, &xhot, &yhot);
332 if (result != BitmapSuccess) 332 if (result != BitmapSuccess)
333 return -1; 333 return -1;
@@ -1952,7 +1952,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
1952{ 1952{
1953#ifdef HAVE_X_WINDOWS 1953#ifdef HAVE_X_WINDOWS
1954 Display *display = FRAME_X_DISPLAY (f); 1954 Display *display = FRAME_X_DISPLAY (f);
1955 Window window = FRAME_X_WINDOW (f); 1955 Drawable drawable = FRAME_X_DRAWABLE (f);
1956 Screen *screen = FRAME_X_SCREEN (f); 1956 Screen *screen = FRAME_X_SCREEN (f);
1957 1957
1958 eassert (input_blocked_p ()); 1958 eassert (input_blocked_p ());
@@ -1981,7 +1981,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
1981 (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height); 1981 (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height);
1982 1982
1983 /* Allocate a pixmap of the same size. */ 1983 /* Allocate a pixmap of the same size. */
1984 *pixmap = XCreatePixmap (display, window, width, height, depth); 1984 *pixmap = XCreatePixmap (display, drawable, width, height, depth);
1985 if (*pixmap == NO_PIXMAP) 1985 if (*pixmap == NO_PIXMAP)
1986 { 1986 {
1987 x_destroy_x_image (*ximg); 1987 x_destroy_x_image (*ximg);
@@ -2742,7 +2742,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
2742 img->pixmap = 2742 img->pixmap =
2743 (x_check_image_size (0, img->width, img->height) 2743 (x_check_image_size (0, img->width, img->height)
2744 ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), 2744 ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
2745 FRAME_X_WINDOW (f), 2745 FRAME_X_DRAWABLE (f),
2746 data, 2746 data,
2747 img->width, img->height, 2747 img->width, img->height,
2748 fg, bg, 2748 fg, bg,
@@ -3520,7 +3520,7 @@ x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
3520 xpm_init_color_cache (f, &attrs); 3520 xpm_init_color_cache (f, &attrs);
3521#endif 3521#endif
3522 3522
3523 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3523 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
3524 (char **) bits, &bitmap, &mask, &attrs); 3524 (char **) bits, &bitmap, &mask, &attrs);
3525 if (rc != XpmSuccess) 3525 if (rc != XpmSuccess)
3526 { 3526 {
@@ -3758,7 +3758,7 @@ xpm_load (struct frame *f, struct image *img)
3758#ifdef HAVE_X_WINDOWS 3758#ifdef HAVE_X_WINDOWS
3759 if (rc == XpmSuccess) 3759 if (rc == XpmSuccess)
3760 { 3760 {
3761 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3761 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
3762 img->ximg->width, img->ximg->height, 3762 img->ximg->width, img->ximg->height,
3763 img->ximg->depth); 3763 img->ximg->depth);
3764 if (img->pixmap == NO_PIXMAP) 3764 if (img->pixmap == NO_PIXMAP)
@@ -3768,7 +3768,7 @@ xpm_load (struct frame *f, struct image *img)
3768 } 3768 }
3769 else if (img->mask_img) 3769 else if (img->mask_img)
3770 { 3770 {
3771 img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3771 img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
3772 img->mask_img->width, 3772 img->mask_img->width,
3773 img->mask_img->height, 3773 img->mask_img->height,
3774 img->mask_img->depth); 3774 img->mask_img->depth);
@@ -9541,7 +9541,7 @@ gs_load (struct frame *f, struct image *img)
9541 { 9541 {
9542 /* Only W32 version did BLOCK_INPUT here. ++kfs */ 9542 /* Only W32 version did BLOCK_INPUT here. ++kfs */
9543 block_input (); 9543 block_input ();
9544 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 9544 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
9545 img->width, img->height, 9545 img->width, img->height,
9546 DefaultDepthOfScreen (FRAME_X_SCREEN (f))); 9546 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9547 unblock_input (); 9547 unblock_input ();
@@ -9557,7 +9557,7 @@ gs_load (struct frame *f, struct image *img)
9557 if successful. We do not record_unwind_protect here because 9557 if successful. We do not record_unwind_protect here because
9558 other places in redisplay like calling window scroll functions 9558 other places in redisplay like calling window scroll functions
9559 don't either. Let the Lisp loader use `unwind-protect' instead. */ 9559 don't either. Let the Lisp loader use `unwind-protect' instead. */
9560 printnum1 = FRAME_X_WINDOW (f); 9560 printnum1 = FRAME_X_DRAWABLE (f);
9561 printnum2 = img->pixmap; 9561 printnum2 = img->pixmap;
9562 window_and_pixmap_id 9562 window_and_pixmap_id
9563 = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2); 9563 = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
diff --git a/src/nsfns.m b/src/nsfns.m
index ce2622c8062..b8264608b34 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -971,6 +971,7 @@ frame_parm_handler ns_frame_parm_handlers[] =
971 x_set_alpha, 971 x_set_alpha,
972 0, /* x_set_sticky */ 972 0, /* x_set_sticky */
973 0, /* x_set_tool_bar_position */ 973 0, /* x_set_tool_bar_position */
974 0, /* x_set_inhibit_double_buffering */
974}; 975};
975 976
976 977
diff --git a/src/termhooks.h b/src/termhooks.h
index ff74d99b7c1..03416cb8842 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -631,6 +631,11 @@ struct terminal
631 /* Called when a frame's display becomes entirely up to date. */ 631 /* Called when a frame's display becomes entirely up to date. */
632 void (*frame_up_to_date_hook) (struct frame *); 632 void (*frame_up_to_date_hook) (struct frame *);
633 633
634 /* Called when buffer flipping becomes unblocked after having
635 previously been blocked. Redisplay always blocks buffer flips
636 while it runs. */
637 void (*buffer_flipping_unblocked_hook) (struct frame *);
638
634 639
635 /* Called to delete the device-specific portions of a frame that is 640 /* Called to delete the device-specific portions of a frame that is
636 on this terminal device. */ 641 on this terminal device. */
diff --git a/src/w32fns.c b/src/w32fns.c
index 2b07bb20e42..1d83b02d629 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -9757,6 +9757,7 @@ frame_parm_handler w32_frame_parm_handlers[] =
9757 x_set_alpha, 9757 x_set_alpha,
9758 0, /* x_set_sticky */ 9758 0, /* x_set_sticky */
9759 0, /* x_set_tool_bar_position */ 9759 0, /* x_set_tool_bar_position */
9760 0, /* x_set_inhibit_double_buffering */
9760}; 9761};
9761 9762
9762void 9763void
diff --git a/src/xdisp.c b/src/xdisp.c
index 1a27c4c3c96..6e8af8aaf0a 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2501,7 +2501,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2501 2501
2502 /* Visible feedback for debugging. */ 2502 /* Visible feedback for debugging. */
2503#if false && defined HAVE_X_WINDOWS 2503#if false && defined HAVE_X_WINDOWS
2504 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 2504 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2505 f->output_data.x->normal_gc, 2505 f->output_data.x->normal_gc,
2506 gx, gy, width, height); 2506 gx, gy, width, height);
2507#endif 2507#endif
@@ -11349,7 +11349,7 @@ clear_garbaged_frames (void)
11349 fset_redisplay (f); 11349 fset_redisplay (f);
11350 f->garbaged = false; 11350 f->garbaged = false;
11351 f->resized_p = false; 11351 f->resized_p = false;
11352 } 11352 }
11353 } 11353 }
11354 11354
11355 frame_garbaged = false; 11355 frame_garbaged = false;
@@ -13573,6 +13573,7 @@ redisplay_internal (void)
13573 count = SPECPDL_INDEX (); 13573 count = SPECPDL_INDEX ();
13574 record_unwind_protect_void (unwind_redisplay); 13574 record_unwind_protect_void (unwind_redisplay);
13575 redisplaying_p = true; 13575 redisplaying_p = true;
13576 block_buffer_flips ();
13576 specbind (Qinhibit_free_realized_faces, Qnil); 13577 specbind (Qinhibit_free_realized_faces, Qnil);
13577 13578
13578 /* Record this function, so it appears on the profiler's backtraces. */ 13579 /* Record this function, so it appears on the profiler's backtraces. */
@@ -14070,7 +14071,23 @@ redisplay_internal (void)
14070 use them in update_frame will segfault. 14071 use them in update_frame will segfault.
14071 Therefore, we must redisplay this frame. */ 14072 Therefore, we must redisplay this frame. */
14072 if (!f_redisplay_flag && f->redisplay) 14073 if (!f_redisplay_flag && f->redisplay)
14073 goto retry_frame; 14074 goto retry_frame;
14075
14076 /* In some case (e.g., window resize), we notice
14077 only during window updating that the window
14078 content changed unpredictably (e.g., a GTK
14079 scrollbar moved) and that our previous estimation
14080 of the frame content was garbage. We have to
14081 start over. These cases should be rare, so going
14082 all the way back to the top of redisplay should
14083 be good enough.
14084
14085 Why FRAME_WINDOW_P? See
14086 https://lists.gnu.org/archive/html/emacs-devel/2016-10/msg00957.html
14087
14088 */
14089 if (FRAME_GARBAGED_P (f) && FRAME_WINDOW_P (f))
14090 goto retry;
14074 14091
14075 /* Prevent various kinds of signals during display 14092 /* Prevent various kinds of signals during display
14076 update. stdio is not robust about handling 14093 update. stdio is not robust about handling
@@ -14297,6 +14314,11 @@ redisplay_internal (void)
14297 RESUME_POLLING; 14314 RESUME_POLLING;
14298} 14315}
14299 14316
14317static void
14318unwind_redisplay_preserve_echo_area (void)
14319{
14320 unblock_buffer_flips ();
14321}
14300 14322
14301/* Redisplay, but leave alone any recent echo area message unless 14323/* Redisplay, but leave alone any recent echo area message unless
14302 another message has been requested in its place. 14324 another message has been requested in its place.
@@ -14314,6 +14336,12 @@ redisplay_preserve_echo_area (int from_where)
14314{ 14336{
14315 TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where)); 14337 TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where));
14316 14338
14339 block_input ();
14340 ptrdiff_t count = SPECPDL_INDEX ();
14341 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
14342 block_buffer_flips ();
14343 unblock_input ();
14344
14317 if (!NILP (echo_area_buffer[1])) 14345 if (!NILP (echo_area_buffer[1]))
14318 { 14346 {
14319 /* We have a previously displayed message, but no current 14347 /* We have a previously displayed message, but no current
@@ -14326,6 +14354,7 @@ redisplay_preserve_echo_area (int from_where)
14326 redisplay_internal (); 14354 redisplay_internal ();
14327 14355
14328 flush_frame (SELECTED_FRAME ()); 14356 flush_frame (SELECTED_FRAME ());
14357 unbind_to (count, Qnil);
14329} 14358}
14330 14359
14331 14360
@@ -14335,6 +14364,7 @@ static void
14335unwind_redisplay (void) 14364unwind_redisplay (void)
14336{ 14365{
14337 redisplaying_p = false; 14366 redisplaying_p = false;
14367 unblock_buffer_flips ();
14338} 14368}
14339 14369
14340 14370
@@ -14444,6 +14474,38 @@ disp_char_vector (struct Lisp_Char_Table *dp, int c)
14444 return val; 14474 return val;
14445} 14475}
14446 14476
14477static int buffer_flip_blocked_depth;
14478
14479void
14480block_buffer_flips(void)
14481{
14482 eassert (buffer_flip_blocked_depth >= 0);
14483 buffer_flip_blocked_depth++;
14484}
14485
14486void
14487unblock_buffer_flips(void)
14488{
14489 eassert (buffer_flip_blocked_depth > 0);
14490 if (--buffer_flip_blocked_depth == 0)
14491 {
14492 Lisp_Object tail, frame;
14493 block_input ();
14494 FOR_EACH_FRAME (tail, frame)
14495 {
14496 struct frame *f = XFRAME (frame);
14497 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
14498 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
14499 }
14500 unblock_input ();
14501 }
14502}
14503
14504bool
14505buffer_flipping_blocked_p (void)
14506{
14507 return buffer_flip_blocked_depth > 0;
14508}
14447 14509
14448 14510
14449/*********************************************************************** 14511/***********************************************************************
@@ -24626,7 +24688,6 @@ init_glyph_string (struct glyph_string *s,
24626 s->hdc = hdc; 24688 s->hdc = hdc;
24627#endif 24689#endif
24628 s->display = FRAME_X_DISPLAY (s->f); 24690 s->display = FRAME_X_DISPLAY (s->f);
24629 s->window = FRAME_X_WINDOW (s->f);
24630 s->char2b = char2b; 24691 s->char2b = char2b;
24631 s->hl = hl; 24692 s->hl = hl;
24632 s->row = row; 24693 s->row = row;
diff --git a/src/xfaces.c b/src/xfaces.c
index 5837f35d7b6..accb98bf4c7 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -495,7 +495,7 @@ x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv)
495{ 495{
496 GC gc; 496 GC gc;
497 block_input (); 497 block_input ();
498 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgcv); 498 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), mask, xgcv);
499 unblock_input (); 499 unblock_input ();
500 IF_DEBUG (++ngcs); 500 IF_DEBUG (++ngcs);
501 return gc; 501 return gc;
diff --git a/src/xfns.c b/src/xfns.c
index 8571d0e20ab..3438c8ef5b4 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -53,6 +53,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
53#include "gtkutil.h" 53#include "gtkutil.h"
54#endif 54#endif
55 55
56#ifdef HAVE_XDBE
57#include <X11/extensions/Xdbe.h>
58#endif
59
56#ifdef USE_X_TOOLKIT 60#ifdef USE_X_TOOLKIT
57#include <X11/Shell.h> 61#include <X11/Shell.h>
58 62
@@ -114,6 +118,7 @@ static int dpyinfo_refcount;
114#endif 118#endif
115 119
116static struct x_display_info *x_display_info_for_name (Lisp_Object); 120static struct x_display_info *x_display_info_for_name (Lisp_Object);
121static void set_up_x_back_buffer (struct frame *f);
117 122
118/* Let the user specify an X display with a Lisp object. 123/* Let the user specify an X display with a Lisp object.
119 OBJECT may be nil, a frame or a terminal object. 124 OBJECT may be nil, a frame or a terminal object.
@@ -701,6 +706,35 @@ x_set_tool_bar_position (struct frame *f,
701 wrong_choice (choice, new_value); 706 wrong_choice (choice, new_value);
702} 707}
703 708
709static void
710x_set_inhibit_double_buffering (struct frame *f,
711 Lisp_Object new_value,
712 Lisp_Object old_value)
713{
714 block_input ();
715 if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value))
716 {
717 bool want_double_buffering = NILP (new_value);
718 bool was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
719 /* font_drop_xrender_surfaces in xftfont does something only if
720 we're double-buffered, so call font_drop_xrender_surfaces before
721 and after any potential change. One of the calls will end up
722 being a no-op. */
723 if (want_double_buffering != was_double_buffered)
724 font_drop_xrender_surfaces (f);
725 if (FRAME_X_DOUBLE_BUFFERED_P (f) && !want_double_buffering)
726 tear_down_x_back_buffer (f);
727 else if (!FRAME_X_DOUBLE_BUFFERED_P (f) && want_double_buffering)
728 set_up_x_back_buffer (f);
729 if (FRAME_X_DOUBLE_BUFFERED_P (f) != was_double_buffered)
730 {
731 SET_FRAME_GARBAGED (f);
732 font_drop_xrender_surfaces (f);
733 }
734 }
735 unblock_input ();
736}
737
704#ifdef USE_GTK 738#ifdef USE_GTK
705 739
706/* Set icon from FILE for frame F. By using GTK functions the icon 740/* Set icon from FILE for frame F. By using GTK functions the icon
@@ -2483,6 +2517,72 @@ xic_set_xfontset (struct frame *f, const char *base_fontname)
2483 2517
2484 2518
2485 2519
2520
2521void
2522x_mark_frame_dirty (struct frame *f)
2523{
2524 if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f))
2525 FRAME_X_NEED_BUFFER_FLIP (f) = true;
2526}
2527
2528static void
2529set_up_x_back_buffer (struct frame *f)
2530{
2531#ifdef HAVE_XDBE
2532 block_input ();
2533 if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
2534 {
2535 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2536 if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
2537 {
2538 /* If allocating a back buffer fails, either because the
2539 server ran out of memory or we don't have the right kind
2540 of visual, just use single-buffered rendering. */
2541 x_catch_errors (FRAME_X_DISPLAY (f));
2542 FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName (
2543 FRAME_X_DISPLAY (f),
2544 FRAME_X_WINDOW (f),
2545 XdbeCopied);
2546 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
2547 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2548 x_uncatch_errors_after_check ();
2549 }
2550 }
2551 unblock_input ();
2552#endif
2553}
2554
2555void
2556tear_down_x_back_buffer (struct frame *f)
2557{
2558#ifdef HAVE_XDBE
2559 block_input ();
2560 if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
2561 {
2562 if (FRAME_X_DOUBLE_BUFFERED_P (f))
2563 {
2564 XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
2565 FRAME_X_DRAWABLE (f));
2566 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2567 }
2568 }
2569 unblock_input ();
2570#endif
2571}
2572
2573/* Set up double buffering if the frame parameters don't prohibit
2574 it. */
2575void
2576initial_set_up_x_back_buffer (struct frame *f)
2577{
2578 block_input ();
2579 eassert (FRAME_X_WINDOW (f));
2580 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2581 if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
2582 set_up_x_back_buffer (f);
2583 unblock_input ();
2584}
2585
2486#ifdef USE_X_TOOLKIT 2586#ifdef USE_X_TOOLKIT
2487 2587
2488/* Create and set up the X widget for frame F. */ 2588/* Create and set up the X widget for frame F. */
@@ -2638,7 +2738,7 @@ x_window (struct frame *f, long window_prompting)
2638 f->output_data.x->parent_desc, 0, 0); 2738 f->output_data.x->parent_desc, 0, 0);
2639 2739
2640 FRAME_X_WINDOW (f) = XtWindow (frame_widget); 2740 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2641 2741 initial_set_up_x_back_buffer (f);
2642 validate_x_resource_name (); 2742 validate_x_resource_name ();
2643 2743
2644 class_hints.res_name = SSDATA (Vx_resource_name); 2744 class_hints.res_name = SSDATA (Vx_resource_name);
@@ -2784,7 +2884,8 @@ x_window (struct frame *f)
2784 CopyFromParent, /* depth */ 2884 CopyFromParent, /* depth */
2785 InputOutput, /* class */ 2885 InputOutput, /* class */
2786 FRAME_X_VISUAL (f), 2886 FRAME_X_VISUAL (f),
2787 attribute_mask, &attributes); 2887 attribute_mask, &attributes);
2888 initial_set_up_x_back_buffer (f);
2788 2889
2789#ifdef HAVE_X_I18N 2890#ifdef HAVE_X_I18N
2790 if (use_xim) 2891 if (use_xim)
@@ -2938,7 +3039,7 @@ x_make_gc (struct frame *f)
2938 gc_values.line_width = 0; /* Means 1 using fast algorithm. */ 3039 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
2939 f->output_data.x->normal_gc 3040 f->output_data.x->normal_gc
2940 = XCreateGC (FRAME_X_DISPLAY (f), 3041 = XCreateGC (FRAME_X_DISPLAY (f),
2941 FRAME_X_WINDOW (f), 3042 FRAME_X_DRAWABLE (f),
2942 GCLineWidth | GCForeground | GCBackground, 3043 GCLineWidth | GCForeground | GCBackground,
2943 &gc_values); 3044 &gc_values);
2944 3045
@@ -2947,7 +3048,7 @@ x_make_gc (struct frame *f)
2947 gc_values.background = FRAME_FOREGROUND_PIXEL (f); 3048 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
2948 f->output_data.x->reverse_gc 3049 f->output_data.x->reverse_gc
2949 = XCreateGC (FRAME_X_DISPLAY (f), 3050 = XCreateGC (FRAME_X_DISPLAY (f),
2950 FRAME_X_WINDOW (f), 3051 FRAME_X_DRAWABLE (f),
2951 GCForeground | GCBackground | GCLineWidth, 3052 GCForeground | GCBackground | GCLineWidth,
2952 &gc_values); 3053 &gc_values);
2953 3054
@@ -2956,7 +3057,7 @@ x_make_gc (struct frame *f)
2956 gc_values.background = f->output_data.x->cursor_pixel; 3057 gc_values.background = f->output_data.x->cursor_pixel;
2957 gc_values.fill_style = FillOpaqueStippled; 3058 gc_values.fill_style = FillOpaqueStippled;
2958 f->output_data.x->cursor_gc 3059 f->output_data.x->cursor_gc
2959 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3060 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2960 (GCForeground | GCBackground 3061 (GCForeground | GCBackground
2961 | GCFillStyle | GCLineWidth), 3062 | GCFillStyle | GCLineWidth),
2962 &gc_values); 3063 &gc_values);
@@ -3463,6 +3564,9 @@ This function is an internal primitive--use `make-frame' instead. */)
3463 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); 3564 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3464 x_default_parameter (f, parms, Qtool_bar_position, 3565 x_default_parameter (f, parms, Qtool_bar_position,
3465 FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); 3566 FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
3567 x_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
3568 "inhibitDoubleBuffering", "InhibitDoubleBuffering",
3569 RES_TYPE_BOOLEAN);
3466 3570
3467 /* Compute the size of the X window. */ 3571 /* Compute the size of the X window. */
3468 window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height); 3572 window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
@@ -5636,7 +5740,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
5636 /* Border. */ 5740 /* Border. */
5637 f->border_width, 5741 f->border_width,
5638 CopyFromParent, InputOutput, CopyFromParent, 5742 CopyFromParent, InputOutput, CopyFromParent,
5639 mask, &attrs); 5743 mask, &attrs);
5744 initial_set_up_x_back_buffer (f);
5640 XChangeProperty (FRAME_X_DISPLAY (f), tip_window, 5745 XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
5641 FRAME_DISPLAY_INFO (f)->Xatom_net_window_type, 5746 FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
5642 XA_ATOM, 32, PropModeReplace, 5747 XA_ATOM, 32, PropModeReplace,
@@ -6213,6 +6318,15 @@ Value is t if tooltip was open, nil otherwise. */)
6213 return x_hide_tip (!tooltip_reuse_hidden_frame); 6318 return x_hide_tip (!tooltip_reuse_hidden_frame);
6214} 6319}
6215 6320
6321DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
6322 0, 1, 0,
6323 doc: /* Return t if FRAME is being double buffered. */)
6324 (Lisp_Object frame)
6325{
6326 struct frame *f = decode_live_frame (frame);
6327 return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
6328}
6329
6216 6330
6217/*********************************************************************** 6331/***********************************************************************
6218 File selection dialog 6332 File selection dialog
@@ -6864,6 +6978,7 @@ frame_parm_handler x_frame_parm_handlers[] =
6864 x_set_alpha, 6978 x_set_alpha,
6865 x_set_sticky, 6979 x_set_sticky,
6866 x_set_tool_bar_position, 6980 x_set_tool_bar_position,
6981 x_set_inhibit_double_buffering,
6867}; 6982};
6868 6983
6869void 6984void
@@ -7080,6 +7195,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
7080 7195
7081 defsubr (&Sx_show_tip); 7196 defsubr (&Sx_show_tip);
7082 defsubr (&Sx_hide_tip); 7197 defsubr (&Sx_hide_tip);
7198 defsubr (&Sx_double_buffered_p);
7083 tip_timer = Qnil; 7199 tip_timer = Qnil;
7084 staticpro (&tip_timer); 7200 staticpro (&tip_timer);
7085 tip_frame = Qnil; 7201 tip_frame = Qnil;
diff --git a/src/xfont.c b/src/xfont.c
index 45b0e0a5f53..c2b73173968 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -1057,20 +1057,20 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
1057 { 1057 {
1058 if (s->padding_p) 1058 if (s->padding_p)
1059 for (i = 0; i < len; i++) 1059 for (i = 0; i < len; i++)
1060 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), 1060 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1061 gc, x + i, y, str + i, 1); 1061 gc, x + i, y, str + i, 1);
1062 else 1062 else
1063 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), 1063 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1064 gc, x, y, str, len); 1064 gc, x, y, str, len);
1065 } 1065 }
1066 else 1066 else
1067 { 1067 {
1068 if (s->padding_p) 1068 if (s->padding_p)
1069 for (i = 0; i < len; i++) 1069 for (i = 0; i < len; i++)
1070 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), 1070 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1071 gc, x + i, y, str + i, 1); 1071 gc, x + i, y, str + i, 1);
1072 else 1072 else
1073 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), 1073 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1074 gc, x, y, str, len); 1074 gc, x, y, str, len);
1075 } 1075 }
1076 unblock_input (); 1076 unblock_input ();
@@ -1083,20 +1083,20 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
1083 { 1083 {
1084 if (s->padding_p) 1084 if (s->padding_p)
1085 for (i = 0; i < len; i++) 1085 for (i = 0; i < len; i++)
1086 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), 1086 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1087 gc, x + i, y, s->char2b + from + i, 1); 1087 gc, x + i, y, s->char2b + from + i, 1);
1088 else 1088 else
1089 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), 1089 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1090 gc, x, y, s->char2b + from, len); 1090 gc, x, y, s->char2b + from, len);
1091 } 1091 }
1092 else 1092 else
1093 { 1093 {
1094 if (s->padding_p) 1094 if (s->padding_p)
1095 for (i = 0; i < len; i++) 1095 for (i = 0; i < len; i++)
1096 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), 1096 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1097 gc, x + i, y, s->char2b + from + i, 1); 1097 gc, x + i, y, s->char2b + from + i, 1);
1098 else 1098 else
1099 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), 1099 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1100 gc, x, y, s->char2b + from, len); 1100 gc, x, y, s->char2b + from, len);
1101 } 1101 }
1102 unblock_input (); 1102 unblock_input ();
diff --git a/src/xftfont.c b/src/xftfont.c
index 34c6f7d3e42..861ad80da5c 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -586,7 +586,7 @@ xftfont_get_xft_draw (struct frame *f)
586 { 586 {
587 block_input (); 587 block_input ();
588 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f), 588 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
589 FRAME_X_WINDOW (f), 589 FRAME_X_DRAWABLE (f),
590 FRAME_X_VISUAL (f), 590 FRAME_X_VISUAL (f),
591 FRAME_X_COLORMAP (f)); 591 FRAME_X_COLORMAP (f));
592 unblock_input (); 592 unblock_input ();
@@ -600,6 +600,8 @@ static int
600xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, 600xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
601 bool with_background) 601 bool with_background)
602{ 602{
603 block_input ();
604
603 struct frame *f = s->f; 605 struct frame *f = s->f;
604 struct face *face = s->face; 606 struct face *face = s->face;
605 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font; 607 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
@@ -614,7 +616,6 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
614 xftface_info = (struct xftface_info *) face->extra; 616 xftface_info = (struct xftface_info *) face->extra;
615 xftfont_get_colors (f, face, s->gc, xftface_info, 617 xftfont_get_colors (f, face, s->gc, xftface_info,
616 &fg, with_background ? &bg : NULL); 618 &fg, with_background ? &bg : NULL);
617 block_input ();
618 if (s->num_clips > 0) 619 if (s->num_clips > 0)
619 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips); 620 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
620 else 621 else
@@ -652,9 +653,12 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
652 x + i, y, code + i, 1); 653 x + i, y, code + i, 1);
653 else 654 else
654 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont, 655 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
655 x, y, code, len); 656 x, y, code, len);
657 /* Need to explicitly mark the frame dirty because we didn't call
658 FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
659 XftDraw structure. */
660 x_mark_frame_dirty (f);
656 unblock_input (); 661 unblock_input ();
657
658 return len; 662 return len;
659} 663}
660 664
@@ -678,13 +682,10 @@ xftfont_shape (Lisp_Object lgstring)
678static int 682static int
679xftfont_end_for_frame (struct frame *f) 683xftfont_end_for_frame (struct frame *f)
680{ 684{
685 block_input ();
681 XftDraw *xft_draw; 686 XftDraw *xft_draw;
682 687
683 /* Don't do anything if display is dead */
684 if (FRAME_X_DISPLAY (f) == NULL) return 0;
685
686 xft_draw = font_get_frame_data (f, Qxft); 688 xft_draw = font_get_frame_data (f, Qxft);
687
688 if (xft_draw) 689 if (xft_draw)
689 { 690 {
690 block_input (); 691 block_input ();
@@ -692,9 +693,19 @@ xftfont_end_for_frame (struct frame *f)
692 unblock_input (); 693 unblock_input ();
693 font_put_frame_data (f, Qxft, NULL); 694 font_put_frame_data (f, Qxft, NULL);
694 } 695 }
696 unblock_input ();
695 return 0; 697 return 0;
696} 698}
697 699
700static void
701xftfont_drop_xrender_surfaces (struct frame *f)
702{
703 block_input ();
704 if (FRAME_X_DOUBLE_BUFFERED_P (f))
705 xftfont_end_for_frame (f);
706 unblock_input ();
707}
708
698static bool 709static bool
699xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object, 710xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
700 Lisp_Object entity) 711 Lisp_Object entity)
@@ -777,6 +788,10 @@ This is needed with some fonts to correct vertical overlap of glyphs. */);
777#if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF) 788#if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
778 xftfont_driver.shape = xftfont_shape; 789 xftfont_driver.shape = xftfont_shape;
779#endif 790#endif
791 /* When using X double buffering, the XftDraw structure we build
792 seems to be useless once a frame is resized, so recreate it on
793 ConfigureNotify and in some other cases. */
794 xftfont_driver.drop_xrender_surfaces = xftfont_drop_xrender_surfaces;
780 795
781 register_font_driver (&xftfont_driver, NULL); 796 register_font_driver (&xftfont_driver, NULL);
782} 797}
diff --git a/src/xterm.c b/src/xterm.c
index 747669446f5..f0dd0ca1dc1 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -45,6 +45,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
45#include <X11/extensions/Xrender.h> 45#include <X11/extensions/Xrender.h>
46#endif 46#endif
47 47
48#ifdef HAVE_XDBE
49#include <X11/extensions/Xdbe.h>
50#endif
51
48/* Load sys/types.h if not already loaded. 52/* Load sys/types.h if not already loaded.
49 In some systems loading it twice is suicidal. */ 53 In some systems loading it twice is suicidal. */
50#ifndef makedev 54#ifndef makedev
@@ -360,7 +364,7 @@ x_begin_cr_clip (struct frame *f, GC gc)
360 { 364 {
361 cairo_surface_t *surface; 365 cairo_surface_t *surface;
362 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f), 366 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
363 FRAME_X_WINDOW (f), 367 FRAME_X_DRAWABLE (f),
364 FRAME_DISPLAY_INFO (f)->visual, 368 FRAME_DISPLAY_INFO (f)->visual,
365 FRAME_PIXEL_WIDTH (f), 369 FRAME_PIXEL_WIDTH (f),
366 FRAME_PIXEL_HEIGHT (f)); 370 FRAME_PIXEL_HEIGHT (f));
@@ -722,7 +726,7 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
722 cairo_fill (cr); 726 cairo_fill (cr);
723 x_end_cr_clip (f); 727 x_end_cr_clip (f);
724#else 728#else
725 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 729 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
726 gc, x, y, width, height); 730 gc, x, y, width, height);
727#endif 731#endif
728} 732}
@@ -740,7 +744,7 @@ x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
740 cairo_stroke (cr); 744 cairo_stroke (cr);
741 x_end_cr_clip (f); 745 x_end_cr_clip (f);
742#else 746#else
743 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 747 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
744 gc, x, y, width, height); 748 gc, x, y, width, height);
745#endif 749#endif
746} 750}
@@ -756,7 +760,10 @@ x_clear_window (struct frame *f)
756 cairo_paint (cr); 760 cairo_paint (cr);
757 x_end_cr_clip (f); 761 x_end_cr_clip (f);
758#else 762#else
759 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); 763 if (FRAME_X_DOUBLE_BUFFERED_P (f))
764 x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
765 else
766 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
760#endif 767#endif
761} 768}
762 769
@@ -1067,7 +1074,7 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
1067#ifdef USE_CAIRO 1074#ifdef USE_CAIRO
1068 x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0); 1075 x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
1069#else 1076#else
1070 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 1077 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
1071 f->output_data.x->normal_gc, x, y0, x, y1); 1078 f->output_data.x->normal_gc, x, y0, x, y1);
1072#endif 1079#endif
1073} 1080}
@@ -1175,6 +1182,41 @@ x_update_window_end (struct window *w, bool cursor_on_p,
1175 } 1182 }
1176} 1183}
1177 1184
1185/* Show the frame back buffer. If frame is double-buffered,
1186 atomically publish to the user's screen graphics updates made since
1187 the last call to show_back_buffer. */
1188static void
1189show_back_buffer (struct frame *f)
1190{
1191 block_input ();
1192 if (FRAME_X_DOUBLE_BUFFERED_P (f))
1193 {
1194#ifdef HAVE_XDBE
1195 XdbeSwapInfo swap_info;
1196 memset (&swap_info, 0, sizeof (swap_info));
1197 swap_info.swap_window = FRAME_X_WINDOW (f);
1198 swap_info.swap_action = XdbeCopied;
1199 XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
1200#else
1201 eassert (!"should have back-buffer only with XDBE");
1202#endif
1203 }
1204 FRAME_X_NEED_BUFFER_FLIP (f) = false;
1205 unblock_input ();
1206}
1207
1208/* Updates back buffer and flushes changes to display. Called from
1209 minibuf read code. Note that we display the back buffer even if
1210 buffer flipping is blocked. */
1211static void
1212x_flip_and_flush (struct frame *f)
1213{
1214 block_input ();
1215 if (FRAME_X_NEED_BUFFER_FLIP (f))
1216 show_back_buffer (f);
1217 x_flush (f);
1218 unblock_input ();
1219}
1178 1220
1179/* End update of frame F. This function is installed as a hook in 1221/* End update of frame F. This function is installed as a hook in
1180 update_end. */ 1222 update_end. */
@@ -1207,7 +1249,7 @@ x_update_end (struct frame *f)
1207 if (! FRAME_EXTERNAL_MENU_BAR (f)) 1249 if (! FRAME_EXTERNAL_MENU_BAR (f))
1208 height += FRAME_MENU_BAR_HEIGHT (f); 1250 height += FRAME_MENU_BAR_HEIGHT (f);
1209 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f), 1251 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
1210 FRAME_X_WINDOW (f), 1252 FRAME_X_DRAWABLE (f),
1211 FRAME_DISPLAY_INFO (f)->visual, 1253 FRAME_DISPLAY_INFO (f)->visual,
1212 width, 1254 width,
1213 height); 1255 height);
@@ -1220,7 +1262,7 @@ x_update_end (struct frame *f)
1220 cairo_destroy (cr); 1262 cairo_destroy (cr);
1221 unblock_input (); 1263 unblock_input ();
1222 } 1264 }
1223#endif /* USE_CAIRO */ 1265#endif
1224 1266
1225#ifndef XFlush 1267#ifndef XFlush
1226 block_input (); 1268 block_input ();
@@ -1229,17 +1271,26 @@ x_update_end (struct frame *f)
1229#endif 1271#endif
1230} 1272}
1231 1273
1232
1233/* This function is called from various places in xdisp.c 1274/* This function is called from various places in xdisp.c
1234 whenever a complete update has been performed. */ 1275 whenever a complete update has been performed. */
1235 1276
1236static void 1277static void
1237XTframe_up_to_date (struct frame *f) 1278XTframe_up_to_date (struct frame *f)
1238{ 1279{
1239 if (FRAME_X_P (f)) 1280 eassert (FRAME_X_P (f));
1240 FRAME_MOUSE_UPDATE (f); 1281 block_input ();
1282 FRAME_MOUSE_UPDATE (f);
1283 if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f))
1284 show_back_buffer (f);
1285 unblock_input ();
1241} 1286}
1242 1287
1288static void
1289XTbuffer_flipping_unblocked_hook (struct frame *f)
1290{
1291 if (FRAME_X_NEED_BUFFER_FLIP (f))
1292 show_back_buffer (f);
1293}
1243 1294
1244/* Clear under internal border if any (GTK has its own version). */ 1295/* Clear under internal border if any (GTK has its own version). */
1245#ifndef USE_GTK 1296#ifndef USE_GTK
@@ -1354,7 +1405,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
1354#else /* not USE_CAIRO */ 1405#else /* not USE_CAIRO */
1355 if (p->which) 1406 if (p->which)
1356 { 1407 {
1357 Window window = FRAME_X_WINDOW (f); 1408 Drawable drawable = FRAME_X_DRAWABLE (f);
1358 char *bits; 1409 char *bits;
1359 Pixmap pixmap, clipmask = (Pixmap) 0; 1410 Pixmap pixmap, clipmask = (Pixmap) 0;
1360 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f)); 1411 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
@@ -1367,7 +1418,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
1367 1418
1368 /* Draw the bitmap. I believe these small pixmaps can be cached 1419 /* Draw the bitmap. I believe these small pixmaps can be cached
1369 by the server. */ 1420 by the server. */
1370 pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h, 1421 pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h,
1371 (p->cursor_p 1422 (p->cursor_p
1372 ? (p->overlay_p ? face->background 1423 ? (p->overlay_p ? face->background
1373 : f->output_data.x->cursor_pixel) 1424 : f->output_data.x->cursor_pixel)
@@ -1386,7 +1437,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
1386 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv); 1437 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
1387 } 1438 }
1388 1439
1389 XCopyArea (display, pixmap, window, gc, 0, 0, 1440 XCopyArea (display, pixmap, drawable, gc, 0, 0,
1390 p->wd, p->h, p->x, p->y); 1441 p->wd, p->h, p->x, p->y);
1391 XFreePixmap (display, pixmap); 1442 XFreePixmap (display, pixmap);
1392 1443
@@ -1487,7 +1538,7 @@ x_set_cursor_gc (struct glyph_string *s)
1487 mask, &xgcv); 1538 mask, &xgcv);
1488 else 1539 else
1489 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc 1540 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
1490 = XCreateGC (s->display, s->window, mask, &xgcv); 1541 = XCreateGC (s->display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
1491 1542
1492 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc; 1543 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1493 } 1544 }
@@ -1534,7 +1585,7 @@ x_set_mouse_face_gc (struct glyph_string *s)
1534 mask, &xgcv); 1585 mask, &xgcv);
1535 else 1586 else
1536 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc 1587 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
1537 = XCreateGC (s->display, s->window, mask, &xgcv); 1588 = XCreateGC (s->display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
1538 1589
1539 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc; 1590 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1540 1591
@@ -2565,7 +2616,7 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
2565 { 2616 {
2566 xgcv.stipple = dpyinfo->gray; 2617 xgcv.stipple = dpyinfo->gray;
2567 mask |= GCStipple; 2618 mask |= GCStipple;
2568 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv); 2619 relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
2569 } 2620 }
2570 else 2621 else
2571 XChangeGC (dpy, relief->gc, mask, &xgcv); 2622 XChangeGC (dpy, relief->gc, mask, &xgcv);
@@ -2696,7 +2747,7 @@ x_draw_relief_rect (struct frame *f,
2696 x_reset_clip_rectangles (f, bottom_right_gc); 2747 x_reset_clip_rectangles (f, bottom_right_gc);
2697#else 2748#else
2698 Display *dpy = FRAME_X_DISPLAY (f); 2749 Display *dpy = FRAME_X_DISPLAY (f);
2699 Window window = FRAME_X_WINDOW (f); 2750 Drawable drawable = FRAME_X_DRAWABLE (f);
2700 int i; 2751 int i;
2701 GC gc; 2752 GC gc;
2702 2753
@@ -2715,12 +2766,12 @@ x_draw_relief_rect (struct frame *f,
2715 if (top_p) 2766 if (top_p)
2716 { 2767 {
2717 if (width == 1) 2768 if (width == 1)
2718 XDrawLine (dpy, window, gc, 2769 XDrawLine (dpy, drawable, gc,
2719 left_x + left_p, top_y, 2770 left_x + left_p, top_y,
2720 right_x + !right_p, top_y); 2771 right_x + !right_p, top_y);
2721 2772
2722 for (i = 1; i < width; ++i) 2773 for (i = 1; i < width; ++i)
2723 XDrawLine (dpy, window, gc, 2774 XDrawLine (dpy, drawable, gc,
2724 left_x + i * left_p, top_y + i, 2775 left_x + i * left_p, top_y + i,
2725 right_x + 1 - i * right_p, top_y + i); 2776 right_x + 1 - i * right_p, top_y + i);
2726 } 2777 }
@@ -2729,13 +2780,13 @@ x_draw_relief_rect (struct frame *f,
2729 if (left_p) 2780 if (left_p)
2730 { 2781 {
2731 if (width == 1) 2782 if (width == 1)
2732 XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y); 2783 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
2733 2784
2734 XClearArea (dpy, window, left_x, top_y, 1, 1, False); 2785 x_clear_area(f, left_x, top_y, 1, 1);
2735 XClearArea (dpy, window, left_x, bottom_y, 1, 1, False); 2786 x_clear_area(f, left_x, bottom_y, 1, 1);
2736 2787
2737 for (i = (width > 1 ? 1 : 0); i < width; ++i) 2788 for (i = (width > 1 ? 1 : 0); i < width; ++i)
2738 XDrawLine (dpy, window, gc, 2789 XDrawLine (dpy, drawable, gc,
2739 left_x + i, top_y + (i + 1) * top_p, 2790 left_x + i, top_y + (i + 1) * top_p,
2740 left_x + i, bottom_y + 1 - (i + 1) * bot_p); 2791 left_x + i, bottom_y + 1 - (i + 1) * bot_p);
2741 } 2792 }
@@ -2751,23 +2802,23 @@ x_draw_relief_rect (struct frame *f,
2751 { 2802 {
2752 /* Outermost top line. */ 2803 /* Outermost top line. */
2753 if (top_p) 2804 if (top_p)
2754 XDrawLine (dpy, window, gc, 2805 XDrawLine (dpy, drawable, gc,
2755 left_x + left_p, top_y, 2806 left_x + left_p, top_y,
2756 right_x + !right_p, top_y); 2807 right_x + !right_p, top_y);
2757 2808
2758 /* Outermost left line. */ 2809 /* Outermost left line. */
2759 if (left_p) 2810 if (left_p)
2760 XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y); 2811 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
2761 } 2812 }
2762 2813
2763 /* Bottom. */ 2814 /* Bottom. */
2764 if (bot_p) 2815 if (bot_p)
2765 { 2816 {
2766 XDrawLine (dpy, window, gc, 2817 XDrawLine (dpy, drawable, gc,
2767 left_x + left_p, bottom_y, 2818 left_x + left_p, bottom_y,
2768 right_x + !right_p, bottom_y); 2819 right_x + !right_p, bottom_y);
2769 for (i = 1; i < width; ++i) 2820 for (i = 1; i < width; ++i)
2770 XDrawLine (dpy, window, gc, 2821 XDrawLine (dpy, drawable, gc,
2771 left_x + i * left_p, bottom_y - i, 2822 left_x + i * left_p, bottom_y - i,
2772 right_x + 1 - i * right_p, bottom_y - i); 2823 right_x + 1 - i * right_p, bottom_y - i);
2773 } 2824 }
@@ -2775,10 +2826,10 @@ x_draw_relief_rect (struct frame *f,
2775 /* Right. */ 2826 /* Right. */
2776 if (right_p) 2827 if (right_p)
2777 { 2828 {
2778 XClearArea (dpy, window, right_x, top_y, 1, 1, False); 2829 x_clear_area(f, right_x, top_y, 1, 1);
2779 XClearArea (dpy, window, right_x, bottom_y, 1, 1, False); 2830 x_clear_area(f, right_x, bottom_y, 1, 1);
2780 for (i = 0; i < width; ++i) 2831 for (i = 0; i < width; ++i)
2781 XDrawLine (dpy, window, gc, 2832 XDrawLine (dpy, drawable, gc,
2782 right_x - i, top_y + (i + 1) * top_p, 2833 right_x - i, top_y + (i + 1) * top_p,
2783 right_x - i, bottom_y + 1 - (i + 1) * bot_p); 2834 right_x - i, bottom_y + 1 - (i + 1) * bot_p);
2784 } 2835 }
@@ -2930,7 +2981,8 @@ x_draw_image_foreground (struct glyph_string *s)
2930 image_rect.width = s->slice.width; 2981 image_rect.width = s->slice.width;
2931 image_rect.height = s->slice.height; 2982 image_rect.height = s->slice.height;
2932 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) 2983 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2933 XCopyArea (s->display, s->img->pixmap, s->window, s->gc, 2984 XCopyArea (s->display, s->img->pixmap,
2985 FRAME_X_DRAWABLE (s->f), s->gc,
2934 s->slice.x + r.x - x, s->slice.y + r.y - y, 2986 s->slice.x + r.x - x, s->slice.y + r.y - y,
2935 r.width, r.height, r.x, r.y); 2987 r.width, r.height, r.x, r.y);
2936 } 2988 }
@@ -2944,7 +2996,8 @@ x_draw_image_foreground (struct glyph_string *s)
2944 image_rect.width = s->slice.width; 2996 image_rect.width = s->slice.width;
2945 image_rect.height = s->slice.height; 2997 image_rect.height = s->slice.height;
2946 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) 2998 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2947 XCopyArea (s->display, s->img->pixmap, s->window, s->gc, 2999 XCopyArea (s->display, s->img->pixmap,
3000 FRAME_X_DRAWABLE (s->f), s->gc,
2948 s->slice.x + r.x - x, s->slice.y + r.y - y, 3001 s->slice.x + r.x - x, s->slice.y + r.y - y,
2949 r.width, r.height, r.x, r.y); 3002 r.width, r.height, r.x, r.y);
2950 3003
@@ -3184,7 +3237,7 @@ x_draw_image_glyph_string (struct glyph_string *s)
3184 int depth = DefaultDepthOfScreen (screen); 3237 int depth = DefaultDepthOfScreen (screen);
3185 3238
3186 /* Create a pixmap as large as the glyph string. */ 3239 /* Create a pixmap as large as the glyph string. */
3187 pixmap = XCreatePixmap (s->display, s->window, 3240 pixmap = XCreatePixmap (s->display, FRAME_X_DRAWABLE (s->f),
3188 s->background_width, 3241 s->background_width,
3189 s->height, depth); 3242 s->height, depth);
3190 3243
@@ -3259,7 +3312,7 @@ x_draw_image_glyph_string (struct glyph_string *s)
3259 { 3312 {
3260 x_draw_image_foreground_1 (s, pixmap); 3313 x_draw_image_foreground_1 (s, pixmap);
3261 x_set_glyph_string_clipping (s); 3314 x_set_glyph_string_clipping (s);
3262 XCopyArea (s->display, pixmap, s->window, s->gc, 3315 XCopyArea (s->display, pixmap, FRAME_X_DRAWABLE (s->f), s->gc,
3263 0, 0, s->background_width, s->height, s->x, s->y); 3316 0, 0, s->background_width, s->height, s->x, s->y);
3264 XFreePixmap (s->display, pixmap); 3317 XFreePixmap (s->display, pixmap);
3265 } 3318 }
@@ -3438,7 +3491,7 @@ x_draw_underwave (struct glyph_string *s)
3438 3491
3439 while (x1 <= xmax) 3492 while (x1 <= xmax)
3440 { 3493 {
3441 XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2); 3494 XDrawLine (s->display, FRAME_X_DRAWABLE (s->f), s->gc, x1, y1, x2, y2);
3442 x1 = x2, y1 = y2; 3495 x1 = x2, y1 = y2;
3443 x2 += dx, y2 = y0 + odd*dy; 3496 x2 += dx, y2 = y0 + odd*dy;
3444 odd = !odd; 3497 odd = !odd;
@@ -3741,7 +3794,7 @@ x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height,
3741/* Never called on a GUI frame, see 3794/* Never called on a GUI frame, see
3742 http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html 3795 http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html
3743*/ 3796*/
3744 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), 3797 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
3745 f->output_data.x->normal_gc, 3798 f->output_data.x->normal_gc,
3746 x, y, width, height, 3799 x, y, width, height,
3747 x + shift_by, y); 3800 x + shift_by, y);
@@ -3782,8 +3835,14 @@ x_clear_area (struct frame *f, int x, int y, int width, int height)
3782 cairo_fill (cr); 3835 cairo_fill (cr);
3783 x_end_cr_clip (f); 3836 x_end_cr_clip (f);
3784#else 3837#else
3785 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3838 if (FRAME_X_DOUBLE_BUFFERED_P (f))
3786 x, y, width, height, False); 3839 XFillRectangle (FRAME_X_DISPLAY (f),
3840 FRAME_X_DRAWABLE (f),
3841 f->output_data.x->reverse_gc,
3842 x, y, width, height);
3843 else
3844 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3845 x, y, width, height, False);
3787#endif 3846#endif
3788} 3847}
3789 3848
@@ -3799,19 +3858,13 @@ x_clear_frame (struct frame *f)
3799 3858
3800 block_input (); 3859 block_input ();
3801 3860
3861 font_drop_xrender_surfaces (f);
3802 x_clear_window (f); 3862 x_clear_window (f);
3803 3863
3804 /* We have to clear the scroll bars. If we have changed colors or 3864 /* We have to clear the scroll bars. If we have changed colors or
3805 something like that, then they should be notified. */ 3865 something like that, then they should be notified. */
3806 x_scroll_bar_clear (f); 3866 x_scroll_bar_clear (f);
3807 3867
3808#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3809 /* Make sure scroll bars are redrawn. As they aren't redrawn by
3810 redisplay, do it here. */
3811 if (FRAME_GTK_WIDGET (f))
3812 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
3813#endif
3814
3815 XFlush (FRAME_X_DISPLAY (f)); 3868 XFlush (FRAME_X_DISPLAY (f));
3816 3869
3817 unblock_input (); 3870 unblock_input ();
@@ -4109,7 +4162,7 @@ x_scroll_run (struct window *w, struct run *run)
4109 SET_FRAME_GARBAGED (f); 4162 SET_FRAME_GARBAGED (f);
4110#else 4163#else
4111 XCopyArea (FRAME_X_DISPLAY (f), 4164 XCopyArea (FRAME_X_DISPLAY (f),
4112 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), 4165 FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
4113 f->output_data.x->normal_gc, 4166 f->output_data.x->normal_gc,
4114 x, from_y, 4167 x, from_y,
4115 width, height, 4168 width, height,
@@ -7448,6 +7501,26 @@ x_net_wm_state (struct frame *f, Window window)
7448/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/ 7501/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
7449} 7502}
7450 7503
7504/* Flip back buffers on any frames with undrawn content. */
7505static void
7506flush_dirty_back_buffers (void)
7507{
7508 block_input ();
7509 Lisp_Object tail, frame;
7510 FOR_EACH_FRAME (tail, frame)
7511 {
7512 struct frame *f = XFRAME (frame);
7513 if (FRAME_LIVE_P (f) &&
7514 FRAME_X_P (f) &&
7515 FRAME_X_WINDOW (f) &&
7516 !FRAME_GARBAGED_P (f) &&
7517 !buffer_flipping_blocked_p () &&
7518 FRAME_X_NEED_BUFFER_FLIP (f))
7519 show_back_buffer (f);
7520 }
7521 unblock_input ();
7522}
7523
7451/* Handles the XEvent EVENT on display DPYINFO. 7524/* Handles the XEvent EVENT on display DPYINFO.
7452 7525
7453 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. 7526 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
@@ -7766,23 +7839,49 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7766 { 7839 {
7767 if (!FRAME_VISIBLE_P (f)) 7840 if (!FRAME_VISIBLE_P (f))
7768 { 7841 {
7842 block_input ();
7769 SET_FRAME_VISIBLE (f, 1); 7843 SET_FRAME_VISIBLE (f, 1);
7770 SET_FRAME_ICONIFIED (f, false); 7844 SET_FRAME_ICONIFIED (f, false);
7845 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7846 font_drop_xrender_surfaces (f);
7771 f->output_data.x->has_been_visible = true; 7847 f->output_data.x->has_been_visible = true;
7772 SET_FRAME_GARBAGED (f); 7848 SET_FRAME_GARBAGED (f);
7849 unblock_input ();
7773 } 7850 }
7774 else 7851 else if (FRAME_GARBAGED_P (f))
7775 { 7852 {
7776#ifdef USE_GTK 7853#ifdef USE_GTK
7777 /* This seems to be needed for GTK 2.6 and later, see 7854 /* Go around the back buffer and manually clear the
7778 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */ 7855 window the first time we show it. This way, we avoid
7779 x_clear_area (f, 7856 showing users the sanity-defying horror of whatever
7780 event->xexpose.x, event->xexpose.y, 7857 GtkWindow is rendering beneath us. We've garbaged
7781 event->xexpose.width, event->xexpose.height); 7858 the frame, so we'll redraw the whole thing on next
7859 redisplay anyway. Yuck. */
7860 x_clear_area1 (
7861 FRAME_X_DISPLAY (f),
7862 FRAME_X_WINDOW (f),
7863 event->xexpose.x, event->xexpose.y,
7864 event->xexpose.width, event->xexpose.height,
7865 0);
7782#endif 7866#endif
7783 expose_frame (f, event->xexpose.x, event->xexpose.y, 7867 }
7868
7869
7870 if (!FRAME_GARBAGED_P (f))
7871 {
7872#ifdef USE_GTK
7873 /* This seems to be needed for GTK 2.6 and later, see
7874 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
7875 x_clear_area (f,
7876 event->xexpose.x, event->xexpose.y,
7877 event->xexpose.width, event->xexpose.height);
7878#endif
7879 expose_frame (f, event->xexpose.x, event->xexpose.y,
7784 event->xexpose.width, event->xexpose.height); 7880 event->xexpose.width, event->xexpose.height);
7785 } 7881 }
7882
7883 if (!FRAME_GARBAGED_P (f))
7884 show_back_buffer (f);
7786 } 7885 }
7787 else 7886 else
7788 { 7887 {
@@ -7822,10 +7921,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7822 available. */ 7921 available. */
7823 f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable); 7922 f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
7824 if (f) 7923 if (f)
7825 expose_frame (f, event->xgraphicsexpose.x, 7924 {
7826 event->xgraphicsexpose.y, 7925 expose_frame (f, event->xgraphicsexpose.x,
7827 event->xgraphicsexpose.width, 7926 event->xgraphicsexpose.y,
7828 event->xgraphicsexpose.height); 7927 event->xgraphicsexpose.width,
7928 event->xgraphicsexpose.height);
7929 show_back_buffer (f);
7930 }
7829#ifdef USE_X_TOOLKIT 7931#ifdef USE_X_TOOLKIT
7830 else 7932 else
7831 goto OTHER; 7933 goto OTHER;
@@ -8410,7 +8512,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8410 else 8512 else
8411 configureEvent = next_event; 8513 configureEvent = next_event;
8412 } 8514 }
8515
8413 f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window); 8516 f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
8517 /* Unfortunately, we need to call font_drop_xrender_surfaces for
8518 _all_ ConfigureNotify events, otherwise we miss some and
8519 flicker. Don't try to optimize these calls by looking only
8520 for size changes: that's not sufficient. We miss some
8521 surface invalidations and flicker. */
8522 block_input ();
8523 if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
8524 font_drop_xrender_surfaces (f);
8525 unblock_input ();
8414#ifdef USE_CAIRO 8526#ifdef USE_CAIRO
8415 if (f) x_cr_destroy_surface (f); 8527 if (f) x_cr_destroy_surface (f);
8416#endif 8528#endif
@@ -8419,6 +8531,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8419 && (f = any) 8531 && (f = any)
8420 && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)) 8532 && configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
8421 { 8533 {
8534 block_input ();
8535 if (FRAME_X_DOUBLE_BUFFERED_P (f))
8536 font_drop_xrender_surfaces (f);
8537 unblock_input ();
8422 xg_frame_resized (f, configureEvent.xconfigure.width, 8538 xg_frame_resized (f, configureEvent.xconfigure.width,
8423 configureEvent.xconfigure.height); 8539 configureEvent.xconfigure.height);
8424#ifdef USE_CAIRO 8540#ifdef USE_CAIRO
@@ -8429,7 +8545,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8429#endif 8545#endif
8430 if (f) 8546 if (f)
8431 { 8547 {
8432 x_net_wm_state (f, configureEvent.xconfigure.window); 8548
8549 x_net_wm_state (f, configureEvent.xconfigure.window);
8433 8550
8434#ifdef USE_X_TOOLKIT 8551#ifdef USE_X_TOOLKIT
8435 /* Tip frames are pure X window, set size for them. */ 8552 /* Tip frames are pure X window, set size for them. */
@@ -8437,7 +8554,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8437 { 8554 {
8438 if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height 8555 if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
8439 || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width) 8556 || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
8440 SET_FRAME_GARBAGED (f); 8557 {
8558 SET_FRAME_GARBAGED (f);
8559 }
8441 FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height; 8560 FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
8442 FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width; 8561 FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
8443 } 8562 }
@@ -8463,8 +8582,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8463 || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f)) 8582 || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
8464 { 8583 {
8465 change_frame_size (f, width, height, false, true, false, true); 8584 change_frame_size (f, width, height, false, true, false, true);
8466 x_clear_under_internal_border (f); 8585 x_clear_under_internal_border (f);
8467 SET_FRAME_GARBAGED (f); 8586 SET_FRAME_GARBAGED (f);
8468 cancel_mouse_face (f); 8587 cancel_mouse_face (f);
8469 } 8588 }
8470#endif /* not USE_GTK */ 8589#endif /* not USE_GTK */
@@ -8688,6 +8807,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8688 count++; 8807 count++;
8689 } 8808 }
8690 8809
8810 /* Sometimes event processing draws to the frame outside redisplay.
8811 To ensure that these changes become visible, draw them here. */
8812 flush_dirty_back_buffers ();
8691 SAFE_FREE (); 8813 SAFE_FREE ();
8692 return count; 8814 return count;
8693} 8815}
@@ -8880,7 +9002,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
8880 if (dpyinfo->scratch_cursor_gc) 9002 if (dpyinfo->scratch_cursor_gc)
8881 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv); 9003 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8882 else 9004 else
8883 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f), 9005 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
8884 GCForeground, &xgcv); 9006 GCForeground, &xgcv);
8885 gc = dpyinfo->scratch_cursor_gc; 9007 gc = dpyinfo->scratch_cursor_gc;
8886 9008
@@ -8937,7 +9059,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
8937 else 9059 else
8938 { 9060 {
8939 Display *dpy = FRAME_X_DISPLAY (f); 9061 Display *dpy = FRAME_X_DISPLAY (f);
8940 Window window = FRAME_X_WINDOW (f); 9062 Drawable drawable = FRAME_X_DRAWABLE (f);
8941 GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc; 9063 GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
8942 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures; 9064 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
8943 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id); 9065 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
@@ -8958,7 +9080,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
8958 XChangeGC (dpy, gc, mask, &xgcv); 9080 XChangeGC (dpy, gc, mask, &xgcv);
8959 else 9081 else
8960 { 9082 {
8961 gc = XCreateGC (dpy, window, mask, &xgcv); 9083 gc = XCreateGC (dpy, drawable, mask, &xgcv);
8962 FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc; 9084 FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
8963 } 9085 }
8964 9086
@@ -9028,11 +9150,6 @@ static void
9028x_clear_frame_area (struct frame *f, int x, int y, int width, int height) 9150x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
9029{ 9151{
9030 x_clear_area (f, x, y, width, height); 9152 x_clear_area (f, x, y, width, height);
9031#ifdef USE_GTK
9032 /* Must queue a redraw, because scroll bars might have been cleared. */
9033 if (FRAME_GTK_WIDGET (f))
9034 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
9035#endif
9036} 9153}
9037 9154
9038 9155
@@ -10889,9 +11006,9 @@ x_make_frame_visible (struct frame *f)
10889 11006
10890 if (! FRAME_VISIBLE_P (f)) 11007 if (! FRAME_VISIBLE_P (f))
10891 { 11008 {
10892 /* We test FRAME_GARBAGED_P here to make sure we don't 11009 /* We test asked_for_visible here to make sure we don't
10893 call x_set_offset a second time 11010 call x_set_offset a second time
10894 if we get to x_make_frame_visible a second time 11011 if we get to x_make_frame_visible a second time
10895 before the window gets really visible. */ 11012 before the window gets really visible. */
10896 if (! FRAME_ICONIFIED_P (f) 11013 if (! FRAME_ICONIFIED_P (f)
10897 && ! FRAME_X_EMBEDDED_P (f) 11014 && ! FRAME_X_EMBEDDED_P (f)
@@ -10935,6 +11052,8 @@ x_make_frame_visible (struct frame *f)
10935 will set it when they are handled. */ 11052 will set it when they are handled. */
10936 bool previously_visible = f->output_data.x->has_been_visible; 11053 bool previously_visible = f->output_data.x->has_been_visible;
10937 11054
11055 XSETFRAME (frame, f);
11056
10938 original_left = f->left_pos; 11057 original_left = f->left_pos;
10939 original_top = f->top_pos; 11058 original_top = f->top_pos;
10940 11059
@@ -10981,8 +11100,6 @@ x_make_frame_visible (struct frame *f)
10981 unblock_input (); 11100 unblock_input ();
10982 } 11101 }
10983 11102
10984 XSETFRAME (frame, f);
10985
10986 /* Process X events until a MapNotify event has been seen. */ 11103 /* Process X events until a MapNotify event has been seen. */
10987 while (!FRAME_VISIBLE_P (f)) 11104 while (!FRAME_VISIBLE_P (f))
10988 { 11105 {
@@ -11227,6 +11344,7 @@ x_free_frame_resources (struct frame *f)
11227 font-driver (e.g. xft) access a window while finishing a 11344 font-driver (e.g. xft) access a window while finishing a
11228 face. */ 11345 face. */
11229 free_frame_faces (f); 11346 free_frame_faces (f);
11347 tear_down_x_back_buffer (f);
11230 11348
11231 if (f->output_data.x->icon_desc) 11349 if (f->output_data.x->icon_desc)
11232 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc); 11350 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
@@ -11258,7 +11376,7 @@ x_free_frame_resources (struct frame *f)
11258 /* Tooltips don't have widgets, only a simple X window, even if 11376 /* Tooltips don't have widgets, only a simple X window, even if
11259 we are using a toolkit. */ 11377 we are using a toolkit. */
11260 else if (FRAME_X_WINDOW (f)) 11378 else if (FRAME_X_WINDOW (f))
11261 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); 11379 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11262 11380
11263 free_frame_menubar (f); 11381 free_frame_menubar (f);
11264 11382
@@ -11270,8 +11388,9 @@ x_free_frame_resources (struct frame *f)
11270 xg_free_frame_widgets (f); 11388 xg_free_frame_widgets (f);
11271#endif /* USE_GTK */ 11389#endif /* USE_GTK */
11272 11390
11391 tear_down_x_back_buffer (f);
11273 if (FRAME_X_WINDOW (f)) 11392 if (FRAME_X_WINDOW (f))
11274 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); 11393 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11275#endif /* !USE_X_TOOLKIT */ 11394#endif /* !USE_X_TOOLKIT */
11276 11395
11277 unload_color (f, FRAME_FOREGROUND_PIXEL (f)); 11396 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
@@ -12111,7 +12230,15 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
12111 } 12230 }
12112 else 12231 else
12113 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window, 12232 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
12114 dpyinfo->visual, AllocNone); 12233 dpyinfo->visual, AllocNone);
12234
12235#ifdef HAVE_XDBE
12236 dpyinfo->supports_xdbe = false;
12237 int xdbe_major;
12238 int xdbe_minor;
12239 if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
12240 dpyinfo->supports_xdbe = true;
12241#endif
12115 12242
12116#ifdef HAVE_XFT 12243#ifdef HAVE_XFT
12117 { 12244 {
@@ -12462,7 +12589,7 @@ static struct redisplay_interface x_redisplay_interface =
12462 x_after_update_window_line, 12589 x_after_update_window_line,
12463 x_update_window_begin, 12590 x_update_window_begin,
12464 x_update_window_end, 12591 x_update_window_end,
12465 x_flush, 12592 x_flip_and_flush,
12466 x_clear_window_mouse_face, 12593 x_clear_window_mouse_face,
12467 x_get_glyph_overhangs, 12594 x_get_glyph_overhangs,
12468 x_fix_overlapping_area, 12595 x_fix_overlapping_area,
@@ -12592,6 +12719,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
12592 terminal->update_end_hook = x_update_end; 12719 terminal->update_end_hook = x_update_end;
12593 terminal->read_socket_hook = XTread_socket; 12720 terminal->read_socket_hook = XTread_socket;
12594 terminal->frame_up_to_date_hook = XTframe_up_to_date; 12721 terminal->frame_up_to_date_hook = XTframe_up_to_date;
12722 terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
12595 terminal->mouse_position_hook = XTmouse_position; 12723 terminal->mouse_position_hook = XTmouse_position;
12596 terminal->frame_rehighlight_hook = XTframe_rehighlight; 12724 terminal->frame_rehighlight_hook = XTframe_rehighlight;
12597 terminal->frame_raise_lower_hook = XTframe_raise_lower; 12725 terminal->frame_raise_lower_hook = XTframe_raise_lower;
diff --git a/src/xterm.h b/src/xterm.h
index 675a48443dc..01d7efc6dc8 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -475,6 +475,10 @@ struct x_display_info
475#ifdef USE_XCB 475#ifdef USE_XCB
476 xcb_connection_t *xcb_connection; 476 xcb_connection_t *xcb_connection;
477#endif 477#endif
478
479#ifdef HAVE_XDBE
480 bool supports_xdbe;
481#endif
478}; 482};
479 483
480#ifdef HAVE_X_I18N 484#ifdef HAVE_X_I18N
@@ -527,6 +531,16 @@ struct x_output
527 and the X window has not yet been created. */ 531 and the X window has not yet been created. */
528 Window window_desc; 532 Window window_desc;
529 533
534 /* The drawable to which we're rendering. In the single-buffered
535 base, the window itself. In the double-buffered case, the
536 window's back buffer. */
537 Drawable draw_desc;
538
539 /* Flag that indicates whether we've modified the back buffer and
540 need to publish our modifications to the front buffer at a
541 convenient time. */
542 bool need_buffer_flip;
543
530 /* The X window used for the bitmap icon; 544 /* The X window used for the bitmap icon;
531 or 0 if we don't have a bitmap icon. */ 545 or 0 if we don't have a bitmap icon. */
532 Window icon_desc; 546 Window icon_desc;
@@ -737,6 +751,24 @@ enum
737/* Return the X window used for displaying data in frame F. */ 751/* Return the X window used for displaying data in frame F. */
738#define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc) 752#define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc)
739 753
754/* Return the drawable used for rendering to frame F. */
755#define FRAME_X_RAW_DRAWABLE(f) ((f)->output_data.x->draw_desc)
756
757extern void x_mark_frame_dirty (struct frame *f);
758
759/* Return the drawable used for rendering to frame F and mark the
760 frame as needing a buffer flip later. There's no easy way to run
761 code after any drawing command, but we can run code whenever
762 someone asks for the handle necessary to draw. */
763#define FRAME_X_DRAWABLE(f) \
764 (x_mark_frame_dirty((f)), FRAME_X_RAW_DRAWABLE ((f)))
765
766#define FRAME_X_DOUBLE_BUFFERED_P(f) \
767 (FRAME_X_WINDOW (f) != FRAME_X_RAW_DRAWABLE (f))
768
769/* Return the need-buffer-flip flag for frame F. */
770#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip)
771
740/* Return the outermost X window associated with the frame F. */ 772/* Return the outermost X window associated with the frame F. */
741#ifdef USE_X_TOOLKIT 773#ifdef USE_X_TOOLKIT
742#define FRAME_OUTER_WINDOW(f) ((f)->output_data.x->widget ? \ 774#define FRAME_OUTER_WINDOW(f) ((f)->output_data.x->widget ? \
@@ -1140,6 +1172,9 @@ extern bool x_wm_supports (struct frame *, Atom);
1140extern void x_wait_for_event (struct frame *, int); 1172extern void x_wait_for_event (struct frame *, int);
1141extern void x_clear_under_internal_border (struct frame *f); 1173extern void x_clear_under_internal_border (struct frame *f);
1142 1174
1175extern void tear_down_x_back_buffer (struct frame *f);
1176extern void initial_set_up_x_back_buffer (struct frame *f);
1177
1143/* Defined in xselect.c. */ 1178/* Defined in xselect.c. */
1144 1179
1145extern void x_handle_property_notify (const XPropertyEvent *); 1180extern void x_handle_property_notify (const XPropertyEvent *);