emacs-devel
[Top][All Lists]
Advanced

[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 *);
> 
> 
> 

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]