[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: RFC: flicker-free double-buffered Emacs under X11
From: |
Clément Pit--Claudel |
Subject: |
Re: RFC: flicker-free double-buffered Emacs under X11 |
Date: |
Thu, 20 Oct 2016 23:56:54 -0400 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0 |
Hi Daniel,
This is brillant! I applied the patch and everything seems to work great: all
of the cases in which I usually see flickering (I tried resizing windows,
running a process in the background, and isearch) seemed fixed :)
Congrats on this very nice patch :)
Clément.
On 2016-10-20 21:32, Daniel Colascione wrote:
> This patch teaches Emacs how to use the X11 DOUBLE-BUFFER extension to avoid
> showing the user incomplete drawing results. Without this patch, I can make
> Emacs flicker like crazy by running isearch for a piece of text unique in a
> buffer and holding down C-s. With this patch, Emacs does not flicker no
> matter what I do to it.
>
> The patch also stops flickering that occurs when using the "solid resizing"
> feature of some window managers --- i.e., when the WM redraws windows as the
> user drags their edges, as opposed to displaying some kind of bounding-box in
> lieu of the actual window contents.
>
> I've tried to avoid changing the logic in the single-buffered case (which we
> still support), and I've also tried to avoid touching Cairo rendering. This
> patch should work with any toolkit --- I've tested GTK+3 and no toolkit at
> all.
>
> A few notes:
>
> * We do a buffer flip at the end of redisplay instead of in x_update_end() so
> the user never sees the completely-cleared state that we enter immediately
> after clear_garbaged_frames(). x_update_end() does do a buffer flip if it's
> called outside redisplay. I've added a new terminal hook to support this hack.
>
> * The DBE documentation claims that XClearWindow and XClearArea clear both
> the front and back buffers. It's a lie. In my experiments, these functions
> clear only the front buffer.
>
> * XFT stops drawing after we give XftCreateDraw a DBE back-buffer and the
> size of that back buffer changes. To work around this problem, we discard any
> caches XftDraw object we might have to a frame after that frame changes size.
> I haven't noticed any performance problems.
>
> commit 15fdd8f63533201f05627ede634a8f5ae4757d7e
> Author: Daniel Colascione <address@hidden>
> Date: Thu Oct 20 16:50:54 2016 -0700
>
> Add double-buffered output support to Emacs
>
> diff --git a/configure.ac b/configure.ac
> index cd11b10..4716b43 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -3712,6 +3712,24 @@ AC_DEFUN
> AC_SUBST(XFIXES_CFLAGS)
> AC_SUBST(XFIXES_LIBS)
>
> +### Use Xdbe (-lXdbe) if available
> +HAVE_XDBE=no
> +if test "${HAVE_X11}" = "yes"; then
> + AC_CHECK_HEADER(X11/extensions/Xdbe.h,
> + [AC_CHECK_LIB(Xext, XdbeAllocateBackBufferName, HAVE_XDBE=yes)],
> + [],
> + [#include <X11/Xlib.h>
> + ])
> + if test $HAVE_XDBE = yes; then
> + XDBE_LIBS=-lXext
> + fi
> + if test $HAVE_XDBE = yes; then
> + AC_DEFINE(HAVE_XDBE, 1, [Define to 1 if you have the Xdbe extension.])
> + fi
> +fi
> +AC_SUBST(XDBE_CFLAGS)
> +AC_SUBST(XDBE_LIBS)
> +
> ### Use libxml (-lxml2) if available
> ### mingw32 doesn't use -lxml2, since it loads the library dynamically.
> HAVE_LIBXML2=no
> diff --git a/src/Makefile.in b/src/Makefile.in
> index 89f7a92..dc0bfff 100644
> --- a/src/Makefile.in
> +++ b/src/Makefile.in
> @@ -254,6 +254,9 @@ XINERAMA_CFLAGS =
> XFIXES_LIBS = @XFIXES_LIBS@
> XFIXES_CFLAGS = @XFIXES_CFLAGS@
>
> +XDBE_LIBS = @XDBE_LIBS@
> +XDBE_CFLAGS = @XDBE_CFLAGS@
> +
> ## widget.o if USE_X_TOOLKIT, otherwise empty.
> address@hidden@
>
> @@ -372,7 +375,7 @@ ALL_CFLAGS=
> $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
> $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
> $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
> - $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
> + $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \
> $(WEBKIT_CFLAGS) \
> $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
> $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
> @@ -489,6 +492,7 @@ LIBES =
> $(WEBKIT_LIBS) \
> $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
> $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
> + $(XDBE_LIBS) \
> $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
> $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
> $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
> diff --git a/src/dispnew.c b/src/dispnew.c
> index 70d4de0..8f81cee 100644
> --- a/src/dispnew.c
> +++ b/src/dispnew.c
> @@ -2999,6 +2999,7 @@ redraw_frame (struct frame *f)
> {
> /* Error if F has no glyphs. */
> eassert (f->glyphs_initialized_p);
> + font_flush_frame_caches (f);
> update_begin (f);
> if (FRAME_MSDOS_P (f))
> FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f));
> diff --git a/src/font.c b/src/font.c
> index f8e6794..033995e 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)
> }
>
> void
> +font_flush_frame_caches (struct frame *f)
> +{
> + struct font_driver_list *list;
> +
> + for (list = f->font_driver_list; list; list = list->next)
> + if (list->on && list->driver->flush_frame_caches)
> + list->driver->flush_frame_caches (f);
> +}
> +
> +void
> syms_of_font (void)
> {
> sort_shift_bits[FONT_TYPE_INDEX] = 0;
> diff --git a/src/font.h b/src/font.h
> index cf47729..961e9c4 100644
> --- a/src/font.h
> +++ b/src/font.h
> @@ -763,6 +763,12 @@ struct font_driver
> Return non-nil if the driver support rendering of combining
> characters for FONT according to Unicode combining class. */
> Lisp_Object (*combining_capability) (struct font *font);
> +
> + /* Optional
> +
> + Called when frame F is redrawn from scratch. Font engines may
> + invalidate certain caches in this case. */
> + void (*flush_frame_caches) (struct frame *f);
> };
>
>
> @@ -862,7 +868,9 @@ extern void *font_get_frame_data (struct frame *f,
> Lisp_Object);
> extern void font_filter_properties (Lisp_Object font,
> Lisp_Object alist,
> const char *const boolean_properties[],
> - const char *const non_boolean_properties[]);
> + const char *const
> non_boolean_properties[]);
> +
> +extern void font_flush_frame_caches (struct frame *f);
>
> #ifdef HAVE_FREETYPE
> extern struct font_driver ftfont_driver;
> diff --git a/src/ftxfont.c b/src/ftxfont.c
> index f49d44f..bfdeb40 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
> if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
> break;
> xgcv.foreground = color.pixel;
> - new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> GCForeground, &xgcv);
> }
> unblock_input ();
> @@ -139,14 +139,14 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC
> *gcs, struct font *font,
> p[n[0]].y = y - bitmap.top + i;
> if (++n[0] == size)
> {
> - XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> gc_fore, p, size, CoordModeOrigin);
> n[0] = 0;
> }
> }
> }
> if (flush && n[0] > 0)
> - XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> gc_fore, p, n[0], CoordModeOrigin);
> }
> else
> @@ -168,7 +168,7 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC
> *gcs, struct font *font,
> pp[n[idx]].y = y - bitmap.top + i;
> if (++(n[idx]) == size)
> {
> - XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> idx == 6 ? gc_fore : gcs[idx], pp, size,
> CoordModeOrigin);
> n[idx] = 0;
> @@ -180,10 +180,10 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC
> *gcs, struct font *font,
> {
> for (i = 0; i < 6; i++)
> if (n[i] > 0)
> - XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
> if (n[6] > 0)
> - XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> gc_fore, p + 0x600, n[6], CoordModeOrigin);
> }
> }
> @@ -203,7 +203,7 @@ ftxfont_draw_background (struct frame *f, struct font
> *font, GC gc, int x, int y
> XGetGCValues (FRAME_X_DISPLAY (f), gc,
> GCForeground | GCBackground, &xgcv);
> XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
> - XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
> + XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
> x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
> XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
> }
> diff --git a/src/gtkutil.c b/src/gtkutil.c
> index 88e6d30..f81940b 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/>. */
> #include "emacsgtkfixed.h"
> #endif
>
> +#ifdef HAVE_XDBE
> +#include <X11/extensions/Xdbe.h>
> +#endif
> +
> #ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
> #define gtk_widget_set_has_window(w, b) \
> (gtk_fixed_set_has_window (GTK_FIXED (w), b))
> @@ -1233,6 +1237,7 @@ xg_create_frame_widgets (struct frame *f)
> by callers of this function. */
> gtk_widget_realize (wfixed);
> FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed);
> + set_up_x_back_buffer (f);
>
> /* Since GTK clears its window by filling with the background color,
> we must keep X and GTK background in sync. */
> @@ -1296,6 +1301,15 @@ xg_free_frame_widgets (struct frame *f)
> if (tbinfo)
> xfree (tbinfo);
>
> +#ifdef HAVE_XDBE
> + if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
> + {
> + XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
> + FRAME_X_DRAWABLE (f));
> + FRAME_X_DRAWABLE (f) = 0;
> + }
> +#endif
> +
> gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
> FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
> FRAME_GTK_OUTER_WIDGET (f) = 0;
> diff --git a/src/image.c b/src/image.c
> index 9bd2455..1303a93 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
>
> #ifdef HAVE_X_WINDOWS
> Pixmap bitmap;
> - bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> bits, width, height);
> if (! bitmap)
> return -1;
> @@ -327,7 +327,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object
> file)
>
> filename = SSDATA (found);
>
> - result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> filename, &width, &height, &bitmap, &xhot, &yhot);
> if (result != BitmapSuccess)
> return -1;
> @@ -1952,7 +1952,7 @@ x_create_x_image_and_pixmap (struct frame *f, int
> width, int height, int depth,
> {
> #ifdef HAVE_X_WINDOWS
> Display *display = FRAME_X_DISPLAY (f);
> - Window window = FRAME_X_WINDOW (f);
> + Drawable drawable = FRAME_X_DRAWABLE (f);
> Screen *screen = FRAME_X_SCREEN (f);
>
> eassert (input_blocked_p ());
> @@ -1981,7 +1981,7 @@ x_create_x_image_and_pixmap (struct frame *f, int
> width, int height, int depth,
> (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height);
>
> /* Allocate a pixmap of the same size. */
> - *pixmap = XCreatePixmap (display, window, width, height, depth);
> + *pixmap = XCreatePixmap (display, drawable, width, height, depth);
> if (*pixmap == NO_PIXMAP)
> {
> x_destroy_x_image (*ximg);
> @@ -2742,7 +2742,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct
> image *img, char *data,
> img->pixmap =
> (x_check_image_size (0, img->width, img->height)
> ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
> - FRAME_X_WINDOW (f),
> + FRAME_X_DRAWABLE (f),
> data,
> img->width, img->height,
> fg, bg,
> @@ -3520,7 +3520,7 @@ x_create_bitmap_from_xpm_data (struct frame *f, const
> char **bits)
> xpm_init_color_cache (f, &attrs);
> #endif
>
> - rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> (char **) bits, &bitmap, &mask, &attrs);
> if (rc != XpmSuccess)
> {
> @@ -3758,7 +3758,7 @@ xpm_load (struct frame *f, struct image *img)
> #ifdef HAVE_X_WINDOWS
> if (rc == XpmSuccess)
> {
> - img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> img->ximg->width, img->ximg->height,
> img->ximg->depth);
> if (img->pixmap == NO_PIXMAP)
> @@ -3768,7 +3768,7 @@ xpm_load (struct frame *f, struct image *img)
> }
> else if (img->mask_img)
> {
> - img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE
> (f),
> img->mask_img->width,
> img->mask_img->height,
> img->mask_img->depth);
> @@ -9541,7 +9541,7 @@ gs_load (struct frame *f, struct image *img)
> {
> /* Only W32 version did BLOCK_INPUT here. ++kfs */
> block_input ();
> - img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> img->width, img->height,
> DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
> unblock_input ();
> @@ -9557,7 +9557,7 @@ gs_load (struct frame *f, struct image *img)
> if successful. We do not record_unwind_protect here because
> other places in redisplay like calling window scroll functions
> don't either. Let the Lisp loader use `unwind-protect' instead. */
> - printnum1 = FRAME_X_WINDOW (f);
> + printnum1 = FRAME_X_DRAWABLE (f);
> printnum2 = img->pixmap;
> window_and_pixmap_id
> = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
> diff --git a/src/termhooks.h b/src/termhooks.h
> index ff74d99..c8d7fae 100644
> --- a/src/termhooks.h
> +++ b/src/termhooks.h
> @@ -477,6 +477,7 @@ struct terminal
>
> void (*update_begin_hook) (struct frame *);
> void (*update_end_hook) (struct frame *);
> + void (*redisplay_end_hook) (struct frame *);
> void (*set_terminal_window_hook) (struct frame *, int);
>
> /* Multi-frame and mouse support hooks. */
> diff --git a/src/xdisp.c b/src/xdisp.c
> index 3af5ea4..04f0ca1 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)
>
> /* Visible feedback for debugging. */
> #if false && defined HAVE_X_WINDOWS
> - XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> f->output_data.x->normal_gc,
> gx, gy, width, height);
> #endif
> @@ -14211,6 +14211,13 @@ redisplay_internal (void)
> windows_or_buffers_changed = 0;
> }
>
> + FOR_EACH_FRAME (tail, frame)
> + {
> + struct frame *f = XFRAME (frame);
> + if (FRAME_TERMINAL (f)->redisplay_end_hook)
> + (*FRAME_TERMINAL (f)->redisplay_end_hook) (f);
> + }
> +
> /* Start SIGIO interrupts coming again. Having them off during the
> code above makes it less likely one will discard output, but not
> impossible, since there might be stuff in the system buffer here.
> @@ -24608,7 +24615,7 @@ init_glyph_string (struct glyph_string *s,
> s->hdc = hdc;
> #endif
> s->display = FRAME_X_DISPLAY (s->f);
> - s->window = FRAME_X_WINDOW (s->f);
> + s->window = FRAME_X_DRAWABLE (s->f);
> s->char2b = char2b;
> s->hl = hl;
> s->row = row;
> diff --git a/src/xfaces.c b/src/xfaces.c
> index 5837f35..accb98b 100644
> --- a/src/xfaces.c
> +++ b/src/xfaces.c
> @@ -495,7 +495,7 @@ x_create_gc (struct frame *f, unsigned long mask,
> XGCValues *xgcv)
> {
> GC gc;
> block_input ();
> - gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgcv);
> + gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), mask, xgcv);
> unblock_input ();
> IF_DEBUG (++ngcs);
> return gc;
> diff --git a/src/xfns.c b/src/xfns.c
> index 8571d0e..2098036 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/>. */
> #include "gtkutil.h"
> #endif
>
> +#ifdef HAVE_XDBE
> +#include <X11/extensions/Xdbe.h>
> +#endif
> +
> #ifdef USE_X_TOOLKIT
> #include <X11/Shell.h>
>
> @@ -2483,6 +2487,29 @@ xic_set_xfontset (struct frame *f, const char
> *base_fontname)
>
>
>
> +
> +void
> +set_up_x_back_buffer (struct frame* f)
> +{
> + FRAME_X_DRAWABLE (f) = FRAME_X_WINDOW (f);
> +#ifdef HAVE_XDBE
> + if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
> + {
> + /* If allocating a back buffer fails, just use single-buffered
> + rendering. */
> + x_sync (f);
> + x_catch_errors (FRAME_X_DISPLAY (f));
> + FRAME_X_DRAWABLE (f) = XdbeAllocateBackBufferName (
> + FRAME_X_DISPLAY (f),
> + FRAME_X_WINDOW (f),
> + XdbeCopied);
> + if (x_had_errors_p (FRAME_X_DISPLAY (f)))
> + FRAME_X_DRAWABLE (f) = FRAME_X_WINDOW (f);
> + x_uncatch_errors_after_check ();
> + }
> +#endif
> +}
> +
> #ifdef USE_X_TOOLKIT
>
> /* Create and set up the X widget for frame F. */
> @@ -2638,7 +2665,7 @@ x_window (struct frame *f, long window_prompting)
> f->output_data.x->parent_desc, 0, 0);
>
> FRAME_X_WINDOW (f) = XtWindow (frame_widget);
> -
> + set_up_x_back_buffer (f);
> validate_x_resource_name ();
>
> class_hints.res_name = SSDATA (Vx_resource_name);
> @@ -2784,7 +2811,8 @@ x_window (struct frame *f)
> CopyFromParent, /* depth */
> InputOutput, /* class */
> FRAME_X_VISUAL (f),
> - attribute_mask, &attributes);
> + attribute_mask, &attributes);
> + set_up_x_back_buffer (f);
>
> #ifdef HAVE_X_I18N
> if (use_xim)
> @@ -2938,7 +2966,7 @@ x_make_gc (struct frame *f)
> gc_values.line_width = 0; /* Means 1 using fast algorithm. */
> f->output_data.x->normal_gc
> = XCreateGC (FRAME_X_DISPLAY (f),
> - FRAME_X_WINDOW (f),
> + FRAME_X_DRAWABLE (f),
> GCLineWidth | GCForeground | GCBackground,
> &gc_values);
>
> @@ -2947,7 +2975,7 @@ x_make_gc (struct frame *f)
> gc_values.background = FRAME_FOREGROUND_PIXEL (f);
> f->output_data.x->reverse_gc
> = XCreateGC (FRAME_X_DISPLAY (f),
> - FRAME_X_WINDOW (f),
> + FRAME_X_DRAWABLE (f),
> GCForeground | GCBackground | GCLineWidth,
> &gc_values);
>
> @@ -2956,7 +2984,7 @@ x_make_gc (struct frame *f)
> gc_values.background = f->output_data.x->cursor_pixel;
> gc_values.fill_style = FillOpaqueStippled;
> f->output_data.x->cursor_gc
> - = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> (GCForeground | GCBackground
> | GCFillStyle | GCLineWidth),
> &gc_values);
> @@ -5636,7 +5664,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
> Lisp_Object parms)
> /* Border. */
> f->border_width,
> CopyFromParent, InputOutput, CopyFromParent,
> - mask, &attrs);
> + mask, &attrs);
> + set_up_x_back_buffer (f);
> XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
> FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
> XA_ATOM, 32, PropModeReplace,
> diff --git a/src/xfont.c b/src/xfont.c
> index 45b0e0a..c2b7317 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,
> {
> if (s->padding_p)
> for (i = 0; i < len; i++)
> - XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
> + XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE
> (s->f),
> gc, x + i, y, str + i, 1);
> else
> - XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
> + XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE
> (s->f),
> gc, x, y, str, len);
> }
> else
> {
> if (s->padding_p)
> for (i = 0; i < len; i++)
> - XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
> + XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
> gc, x + i, y, str + i, 1);
> else
> - XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
> + XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
> gc, x, y, str, len);
> }
> unblock_input ();
> @@ -1083,20 +1083,20 @@ xfont_draw (struct glyph_string *s, int from, int to,
> int x, int y,
> {
> if (s->padding_p)
> for (i = 0; i < len; i++)
> - XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
> + XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE
> (s->f),
> gc, x + i, y, s->char2b + from + i, 1);
> else
> - XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
> + XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
> gc, x, y, s->char2b + from, len);
> }
> else
> {
> if (s->padding_p)
> for (i = 0; i < len; i++)
> - XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
> + XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
> gc, x + i, y, s->char2b + from + i, 1);
> else
> - XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
> + XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
> gc, x, y, s->char2b + from, len);
> }
> unblock_input ();
> diff --git a/src/xftfont.c b/src/xftfont.c
> index 34c6f7d..447adf6 100644
> --- a/src/xftfont.c
> +++ b/src/xftfont.c
> @@ -586,7 +586,7 @@ xftfont_get_xft_draw (struct frame *f)
> {
> block_input ();
> xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
> - FRAME_X_WINDOW (f),
> + FRAME_X_DRAWABLE (f),
> FRAME_X_VISUAL (f),
> FRAME_X_COLORMAP (f));
> unblock_input ();
> @@ -695,6 +695,13 @@ xftfont_end_for_frame (struct frame *f)
> return 0;
> }
>
> +static void
> +xftfont_flush_frame_caches (struct frame *f)
> +{
> + if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
> + xftfont_end_for_frame (f);
> +}
> +
> static bool
> xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
> Lisp_Object entity)
> @@ -777,6 +784,9 @@ This is needed with some fonts to correct vertical
> overlap of glyphs. */);
> #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
> xftfont_driver.shape = xftfont_shape;
> #endif
> + // When using X double buffering, the XftDraw structure we
> + // build seems to be useless once a frame is resized, so
> + xftfont_driver.flush_frame_caches = xftfont_flush_frame_caches;
>
> register_font_driver (&xftfont_driver, NULL);
> }
> diff --git a/src/xterm.c b/src/xterm.c
> index 7476694..7116784 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/>. */
> #include <X11/extensions/Xrender.h>
> #endif
>
> +#ifdef HAVE_XDBE
> +#include <X11/extensions/Xdbe.h>
> +#endif
> +
> /* Load sys/types.h if not already loaded.
> In some systems loading it twice is suicidal. */
> #ifndef makedev
> @@ -360,7 +364,7 @@ x_begin_cr_clip (struct frame *f, GC gc)
> {
> cairo_surface_t *surface;
> surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
> - FRAME_X_WINDOW (f),
> + FRAME_X_DRAWABLE (f),
> FRAME_DISPLAY_INFO
> (f)->visual,
> FRAME_PIXEL_WIDTH (f),
> FRAME_PIXEL_HEIGHT (f));
> @@ -722,7 +726,7 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y,
> int width, int height)
> cairo_fill (cr);
> x_end_cr_clip (f);
> #else
> - XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> gc, x, y, width, height);
> #endif
> }
> @@ -740,7 +744,7 @@ x_draw_rectangle (struct frame *f, GC gc, int x, int y,
> int width, int height)
> cairo_stroke (cr);
> x_end_cr_clip (f);
> #else
> - XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> gc, x, y, width, height);
> #endif
> }
> @@ -756,7 +760,10 @@ x_clear_window (struct frame *f)
> cairo_paint (cr);
> x_end_cr_clip (f);
> #else
> - XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
> + if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
> + x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
> + else
> + XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
> #endif
> }
>
> @@ -1067,7 +1074,7 @@ x_draw_vertical_window_border (struct window *w, int x,
> int y0, int y1)
> #ifdef USE_CAIRO
> x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
> #else
> - XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
> f->output_data.x->normal_gc, x, y0, x, y1);
> #endif
> }
> @@ -1179,6 +1186,21 @@ x_update_window_end (struct window *w, bool
> cursor_on_p,
> /* End update of frame F. This function is installed as a hook in
> update_end. */
>
> +#if defined (HAVE_XDBE)
> +static void
> +show_back_buffer (struct frame *f)
> +{
> + if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
> + {
> + XdbeSwapInfo swap_info;
> + memset (&swap_info, 0, sizeof (swap_info));
> + swap_info.swap_window = FRAME_X_WINDOW (f);
> + swap_info.swap_action = XdbeCopied;
> + XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
> + }
> +}
> +#endif
> +
> static void
> x_update_end (struct frame *f)
> {
> @@ -1207,7 +1229,7 @@ x_update_end (struct frame *f)
> if (! FRAME_EXTERNAL_MENU_BAR (f))
> height += FRAME_MENU_BAR_HEIGHT (f);
> surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
> - FRAME_X_WINDOW (f),
> + FRAME_X_DRAWABLE (f),
> FRAME_DISPLAY_INFO
> (f)->visual,
> width,
> height);
> @@ -1220,7 +1242,14 @@ x_update_end (struct frame *f)
> cairo_destroy (cr);
> unblock_input ();
> }
> -#endif /* USE_CAIRO */
> +#endif
> +
> +#ifdef HAVE_XDBE
> + if (redisplaying_p)
> + FRAME_X_NEED_BUFFER_FLIP (f) = true;
> + else
> + show_back_buffer (f);
> +#endif
>
> #ifndef XFlush
> block_input ();
> @@ -1229,6 +1258,17 @@ x_update_end (struct frame *f)
> #endif
> }
>
> +static void
> +x_redisplay_end (struct frame *f)
> +{
> +#ifdef HAVE_XDBE
> + if (FRAME_X_NEED_BUFFER_FLIP (f))
> + {
> + show_back_buffer (f);
> + FRAME_X_NEED_BUFFER_FLIP (f) = false;
> + }
> +#endif
> +}
>
> /* This function is called from various places in xdisp.c
> whenever a complete update has been performed. */
> @@ -1354,7 +1394,7 @@ x_draw_fringe_bitmap (struct window *w, struct
> glyph_row *row, struct draw_fring
> #else /* not USE_CAIRO */
> if (p->which)
> {
> - Window window = FRAME_X_WINDOW (f);
> + Drawable drawable = FRAME_X_DRAWABLE (f);
> char *bits;
> Pixmap pixmap, clipmask = (Pixmap) 0;
> int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
> @@ -1367,7 +1407,7 @@ x_draw_fringe_bitmap (struct window *w, struct
> glyph_row *row, struct draw_fring
>
> /* Draw the bitmap. I believe these small pixmaps can be cached
> by the server. */
> - pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd,
> p->h,
> + pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd,
> p->h,
> (p->cursor_p
> ? (p->overlay_p ? face->background
> : f->output_data.x->cursor_pixel)
> @@ -1386,7 +1426,7 @@ x_draw_fringe_bitmap (struct window *w, struct
> glyph_row *row, struct draw_fring
> XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin,
> &gcv);
> }
>
> - XCopyArea (display, pixmap, window, gc, 0, 0,
> + XCopyArea (display, pixmap, drawable, gc, 0, 0,
> p->wd, p->h, p->x, p->y);
> XFreePixmap (display, pixmap);
>
> @@ -2565,7 +2605,7 @@ x_setup_relief_color (struct frame *f, struct relief
> *relief, double factor,
> {
> xgcv.stipple = dpyinfo->gray;
> mask |= GCStipple;
> - relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
> + relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
> }
> else
> XChangeGC (dpy, relief->gc, mask, &xgcv);
> @@ -2696,7 +2736,7 @@ x_draw_relief_rect (struct frame *f,
> x_reset_clip_rectangles (f, bottom_right_gc);
> #else
> Display *dpy = FRAME_X_DISPLAY (f);
> - Window window = FRAME_X_WINDOW (f);
> + Drawable drawable = FRAME_X_DRAWABLE (f);
> int i;
> GC gc;
>
> @@ -2715,12 +2755,12 @@ x_draw_relief_rect (struct frame *f,
> if (top_p)
> {
> if (width == 1)
> - XDrawLine (dpy, window, gc,
> + XDrawLine (dpy, drawable, gc,
> left_x + left_p, top_y,
> right_x + !right_p, top_y);
>
> for (i = 1; i < width; ++i)
> - XDrawLine (dpy, window, gc,
> + XDrawLine (dpy, drawable, gc,
> left_x + i * left_p, top_y + i,
> right_x + 1 - i * right_p, top_y + i);
> }
> @@ -2729,13 +2769,13 @@ x_draw_relief_rect (struct frame *f,
> if (left_p)
> {
> if (width == 1)
> - XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
> + XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
>
> - XClearArea (dpy, window, left_x, top_y, 1, 1, False);
> - XClearArea (dpy, window, left_x, bottom_y, 1, 1, False);
> + x_clear_area(f, left_x, top_y, 1, 1);
> + x_clear_area(f, left_x, bottom_y, 1, 1);
>
> for (i = (width > 1 ? 1 : 0); i < width; ++i)
> - XDrawLine (dpy, window, gc,
> + XDrawLine (dpy, drawable, gc,
> left_x + i, top_y + (i + 1) * top_p,
> left_x + i, bottom_y + 1 - (i + 1) * bot_p);
> }
> @@ -2751,23 +2791,23 @@ x_draw_relief_rect (struct frame *f,
> {
> /* Outermost top line. */
> if (top_p)
> - XDrawLine (dpy, window, gc,
> + XDrawLine (dpy, drawable, gc,
> left_x + left_p, top_y,
> right_x + !right_p, top_y);
>
> /* Outermost left line. */
> if (left_p)
> - XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
> + XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
> }
>
> /* Bottom. */
> if (bot_p)
> {
> - XDrawLine (dpy, window, gc,
> + XDrawLine (dpy, drawable, gc,
> left_x + left_p, bottom_y,
> right_x + !right_p, bottom_y);
> for (i = 1; i < width; ++i)
> - XDrawLine (dpy, window, gc,
> + XDrawLine (dpy, drawable, gc,
> left_x + i * left_p, bottom_y - i,
> right_x + 1 - i * right_p, bottom_y - i);
> }
> @@ -2775,10 +2815,10 @@ x_draw_relief_rect (struct frame *f,
> /* Right. */
> if (right_p)
> {
> - XClearArea (dpy, window, right_x, top_y, 1, 1, False);
> - XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
> + x_clear_area(f, right_x, top_y, 1, 1);
> + x_clear_area(f, right_x, bottom_y, 1, 1);
> for (i = 0; i < width; ++i)
> - XDrawLine (dpy, window, gc,
> + XDrawLine (dpy, drawable, gc,
> right_x - i, top_y + (i + 1) * top_p,
> right_x - i, bottom_y + 1 - (i + 1) * bot_p);
> }
> @@ -3741,7 +3781,7 @@ x_shift_glyphs_for_insert (struct frame *f, int x, int
> y, int width, int height,
> /* Never called on a GUI frame, see
> http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html
> */
> - XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
> + XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
> f->output_data.x->normal_gc,
> x, y, width, height,
> x + shift_by, y);
> @@ -3782,8 +3822,14 @@ x_clear_area (struct frame *f, int x, int y, int
> width, int height)
> cairo_fill (cr);
> x_end_cr_clip (f);
> #else
> - x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> - x, y, width, height, False);
> + if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
> + XFillRectangle (FRAME_X_DISPLAY (f),
> + FRAME_X_DRAWABLE (f),
> + f->output_data.x->reverse_gc,
> + x, y, width, height);
> + else
> + x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
> + x, y, width, height, False);
> #endif
> }
>
> @@ -4109,7 +4155,7 @@ x_scroll_run (struct window *w, struct run *run)
> SET_FRAME_GARBAGED (f);
> #else
> XCopyArea (FRAME_X_DISPLAY (f),
> - FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
> + FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
> f->output_data.x->normal_gc,
> x, from_y,
> width, height,
> @@ -7769,6 +7815,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
> SET_FRAME_VISIBLE (f, 1);
> SET_FRAME_ICONIFIED (f, false);
> f->output_data.x->has_been_visible = true;
> + font_flush_frame_caches (f);
> SET_FRAME_GARBAGED (f);
> }
> else
> @@ -8437,7 +8484,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
> {
> if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
> || FRAME_PIXEL_WIDTH (f) !=
> configureEvent.xconfigure.width)
> - SET_FRAME_GARBAGED (f);
> + {
> + font_flush_frame_caches (f);
> + SET_FRAME_GARBAGED (f);
> + }
> FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
> FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
> }
> @@ -8463,7 +8513,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
> || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
> {
> change_frame_size (f, width, height, false, true, false, true);
> - x_clear_under_internal_border (f);
> + x_clear_under_internal_border (f);
> + font_flush_frame_caches (f);
> SET_FRAME_GARBAGED (f);
> cancel_mouse_face (f);
> }
> @@ -8880,7 +8931,7 @@ x_draw_hollow_cursor (struct window *w, struct
> glyph_row *row)
> if (dpyinfo->scratch_cursor_gc)
> XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
> else
> - dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
> + dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
> GCForeground, &xgcv);
> gc = dpyinfo->scratch_cursor_gc;
>
> @@ -8937,7 +8988,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row
> *row, int width, enum text
> else
> {
> Display *dpy = FRAME_X_DISPLAY (f);
> - Window window = FRAME_X_WINDOW (f);
> + Drawable drawable = FRAME_X_DRAWABLE (f);
> GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
> unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
> struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
> @@ -8958,7 +9009,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row
> *row, int width, enum text
> XChangeGC (dpy, gc, mask, &xgcv);
> else
> {
> - gc = XCreateGC (dpy, window, mask, &xgcv);
> + gc = XCreateGC (dpy, drawable, mask, &xgcv);
> FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
> }
>
> @@ -11271,7 +11322,14 @@ x_free_frame_resources (struct frame *f)
> #endif /* USE_GTK */
>
> if (FRAME_X_WINDOW (f))
> - XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
> + {
> +#ifdef HAVE_XDBE
> + if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
> + XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
> + FRAME_X_DRAWABLE (f));
> +#endif
> + XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
> + }
> #endif /* !USE_X_TOOLKIT */
>
> unload_color (f, FRAME_FOREGROUND_PIXEL (f));
> @@ -12111,7 +12169,17 @@ x_term_init (Lisp_Object display_name, char
> *xrm_option, char *resource_name)
> }
> else
> dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
> - dpyinfo->visual, AllocNone);
> + dpyinfo->visual, AllocNone);
> +
> +#ifdef HAVE_XDBE
> + dpyinfo->supports_xdbe = false;
> + {
> + int xdbe_major;
> + int xdbe_minor;
> + if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
> + dpyinfo->supports_xdbe = true;
> + }
> +#endif
>
> #ifdef HAVE_XFT
> {
> @@ -12590,6 +12658,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
> terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
> terminal->update_begin_hook = x_update_begin;
> terminal->update_end_hook = x_update_end;
> + terminal->redisplay_end_hook = x_redisplay_end;
> terminal->read_socket_hook = XTread_socket;
> terminal->frame_up_to_date_hook = XTframe_up_to_date;
> terminal->mouse_position_hook = XTmouse_position;
> diff --git a/src/xterm.h b/src/xterm.h
> index 675a484..cb1aa1d 100644
> --- a/src/xterm.h
> +++ b/src/xterm.h
> @@ -475,6 +475,10 @@ struct x_display_info
> #ifdef USE_XCB
> xcb_connection_t *xcb_connection;
> #endif
> +
> +#ifdef HAVE_XDBE
> + bool supports_xdbe;
> +#endif
> };
>
> #ifdef HAVE_X_I18N
> @@ -527,6 +531,17 @@ struct x_output
> and the X window has not yet been created. */
> Window window_desc;
>
> +#ifdef HAVE_XDBE
> + /* The drawable to which we're rendering. In the single-buffered
> + base, the window itself. In the double-buffered case, the
> + window's back buffer. */
> + Drawable draw_desc;
> +
> + /* Set to true when we need a buffer flip. We do a buffer flip only
> + at the end of redisplay in order to minimize flicker. */
> + bool need_buffer_flip;
> +#endif
> +
> /* The X window used for the bitmap icon;
> or 0 if we don't have a bitmap icon. */
> Window icon_desc;
> @@ -737,6 +752,18 @@ enum
> /* Return the X window used for displaying data in frame F. */
> #define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc)
>
> +/* Return the drawable used for rendering to frame F. */
> +#ifdef HAVE_XDBE
> +#define FRAME_X_DRAWABLE(f) ((f)->output_data.x->draw_desc)
> +#else
> +#define FRAME_X_DRAWABLE(f) (0,(FRAME_X_WINDOW (f)))
> +#endif
> +
> +/* Return the need-buffer-flip flag for frame F. */
> +#ifdef HAVE_XDBE
> +#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip)
> +#endif
> +
> /* Return the outermost X window associated with the frame F. */
> #ifdef USE_X_TOOLKIT
> #define FRAME_OUTER_WINDOW(f) ((f)->output_data.x->widget ? \
> @@ -1140,6 +1167,8 @@ extern bool x_wm_supports (struct frame *, Atom);
> extern void x_wait_for_event (struct frame *, int);
> extern void x_clear_under_internal_border (struct frame *f);
>
> +extern void set_up_x_back_buffer (struct frame* f);
> +
> /* Defined in xselect.c. */
>
> extern void x_handle_property_notify (const XPropertyEvent *);
>
>
>
signature.asc
Description: OpenPGP digital signature
Re: RFC: flicker-free double-buffered Emacs under X11,
Clément Pit--Claudel <=
Re: RFC: flicker-free double-buffered Emacs under X11, Eli Zaretskii, 2016/10/21
- Re: RFC: flicker-free double-buffered Emacs under X11, Daniel Colascione, 2016/10/21
- Re: RFC: flicker-free double-buffered Emacs under X11, Eli Zaretskii, 2016/10/21
- Re: RFC: flicker-free double-buffered Emacs under X11, Daniel Colascione, 2016/10/21
- Re: RFC: flicker-free double-buffered Emacs under X11, Eli Zaretskii, 2016/10/21
- Re: RFC: flicker-free double-buffered Emacs under X11, Daniel Colascione, 2016/10/23
- Re: RFC: flicker-free double-buffered Emacs under X11, Eli Zaretskii, 2016/10/24
- Re: RFC: flicker-free double-buffered Emacs under X11, Ken Raeburn, 2016/10/24
- Re: RFC: flicker-free double-buffered Emacs under X11, dancol, 2016/10/27
- Re: RFC: flicker-free double-buffered Emacs under X11, Eli Zaretskii, 2016/10/27