From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: =?UTF-8?Q?Cl=c3=a9ment_Pit--Claudel?= Newsgroups: gmane.emacs.devel Subject: Re: RFC: flicker-free double-buffered Emacs under X11 Date: Thu, 20 Oct 2016 23:56:54 -0400 Message-ID: <9744eb17-ea8f-3cad-0e62-a49cbfab73ab@gmail.com> References: <9e8ad090-a6a0-c807-95ae-7ec7c3f391cb@dancol.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="vUlXPuSt3TTfbDjCfC39Q1EIheVnJWoVx" X-Trace: blaine.gmane.org 1477022364 21233 195.159.176.226 (21 Oct 2016 03:59:24 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Fri, 21 Oct 2016 03:59:24 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0 To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Oct 21 05:59:18 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bxQz8-0003g2-7U for ged-emacs-devel@m.gmane.org; Fri, 21 Oct 2016 05:59:10 +0200 Original-Received: from localhost ([::1]:58511 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bxQzA-00029x-G5 for ged-emacs-devel@m.gmane.org; Thu, 20 Oct 2016 23:59:12 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:35513) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bxQxA-00018B-OG for emacs-devel@gnu.org; Thu, 20 Oct 2016 23:57:13 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bxQx5-00014c-V1 for emacs-devel@gnu.org; Thu, 20 Oct 2016 23:57:08 -0400 Original-Received: from mout.kundenserver.de ([212.227.126.131]:59444) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1bxQx5-00014P-Cm for emacs-devel@gnu.org; Thu, 20 Oct 2016 23:57:03 -0400 Original-Received: from [18.189.6.80] ([18.189.6.80]) by mrelayeu.kundenserver.de (mreue001) with ESMTPSA (Nemesis) id 0MceGG-1cF6MP0lZA-00HgtS for ; Fri, 21 Oct 2016 05:57:01 +0200 In-Reply-To: <9e8ad090-a6a0-c807-95ae-7ec7c3f391cb@dancol.org> X-Provags-ID: V03:K0:w9mi9e7N+am4wVt7sL3hgb4e11djd7laEcr6BUbDVjZnGbywIqC vU/oBZgu1Eg4ss33UrVq+Yislf+icg1IiE9wTuZvdvGuw2nB7NoReaKPcrvMgZKTVIl9sGv yeli7i+Nlb3bBZRJK1dmiocawwTsjQEHV9+pWF2m2+URmo4cJwxN5JlM61a3walyJAPs2qW 3JncCYA9vUcv+AWRbv5EA== X-UI-Out-Filterresults: notjunk:1;V01:K0:T34xaMebTAs=:b+IO7VkHxiR6flSfYpS4G4 Nk72rAuq71XNY1bjjq+A1K8lrvINSxRttcXqHFW6T9IVtn7CstkF0UwcOSmLnDzcbq3+wCGUa tUajQOAh0EyzvyYFIUlYDdw8WYWEb6xRlexrbLyjkuPZF5sWCihAk8B+MQuvakVIPM6j4ZxBl wJ9A09FzQPfAVikRxVKFZccgrUg8a/atq0jjPXkiXdBvxDk0dQwF/Zivxeith08X5iiVum9Dg oO6XC323XrkwJKolMtTS/bdyESGmD1MNYp/vcVcaSm5XwpS0O9zaiUDRr6+lsfx/fo8rZ0Tcd 9WuFi5jLTzTYOuS9khn18Zr0OcrCnxg8ESO/Wni2SffeJzlrXqWJLDhJXFLs+Vgwaa0sXuTaH 193SHJaLqTSP57HJRO2U75n1UiZjndKTcfFRVECnAXOOUvJRxm/GxTELdXMP/10gXOJ0cfdtx GUcFOmpEJQc2roMg4kQQT8vFS6CFQJs8pPVKGrMowGMrb1G8xec4f5QUQ89glSRbt7k9RSylo cPby/imkPp75GWkKexHIPWrv7UOWdp6CEPtgdS0qAb3vjgBVNdNPEicD8HNO4wQ72amyzJ9Pv pT4cx+wBj6KcyKIP+J6AZostO4ssVnHNDQif4v+gEHyVaMolpr92vE/TNQX8NprMJjiVX5xlx rHU7tLUoX/te1IwjCKdH1k4XOu9Fp1dTH3R9F6/ZZEGBbjnm280yGGMjYr7myGHYmZt0= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 212.227.126.131 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:208568 Archived-At: This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --vUlXPuSt3TTfbDjCfC39Q1EIheVnJWoVx Content-Type: multipart/mixed; boundary="fbDHfRkGooq6K3UtdiOssBskgVXCPAf2j"; protected-headers="v1" From: =?UTF-8?Q?Cl=c3=a9ment_Pit--Claudel?= To: emacs-devel@gnu.org Message-ID: <9744eb17-ea8f-3cad-0e62-a49cbfab73ab@gmail.com> Subject: Re: RFC: flicker-free double-buffered Emacs under X11 References: <9e8ad090-a6a0-c807-95ae-7ec7c3f391cb@dancol.org> In-Reply-To: <9e8ad090-a6a0-c807-95ae-7ec7c3f391cb@dancol.org> --fbDHfRkGooq6K3UtdiOssBskgVXCPAf2j Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable 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 wi= ndows, running a process in the background, and isearch) seemed fixed :) Congrats on this very nice patch :) Cl=C3=A9ment. 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. >=20 > The patch also stops flickering that occurs when using the "solid resiz= ing" feature of some window managers --- i.e., when the WM redraws window= s as the user drags their edges, as opposed to displaying some kind of bo= unding-box in lieu of the actual window contents. >=20 > I've tried to avoid changing the logic in the single-buffered case (whi= ch we still support), and I've also tried to avoid touching Cairo renderi= ng. This patch should work with any toolkit --- I've tested GTK+3 and no = toolkit at all. >=20 > A few notes: >=20 > * We do a buffer flip at the end of redisplay instead of in x_update_en= d() so the user never sees the completely-cleared state that we enter imm= ediately after clear_garbaged_frames(). x_update_end() does do a buffer f= lip if it's called outside redisplay. I've added a new terminal hook to s= upport this hack. >=20 > * The DBE documentation claims that XClearWindow and XClearArea clear b= oth the front and back buffers. It's a lie. In my experiments, these func= tions clear only the front buffer. >=20 > * XFT stops drawing after we give XftCreateDraw a DBE back-buffer and t= he size of that back buffer changes. To work around this problem, we disc= ard any caches XftDraw object we might have to a frame after that frame c= hanges size. I haven't noticed any performance problems. >=20 > commit 15fdd8f63533201f05627ede634a8f5ae4757d7e > Author: Daniel Colascione > Date: Thu Oct 20 16:50:54 2016 -0700 >=20 > Add double-buffered output support to Emacs >=20 > 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) >=20 > +### Use Xdbe (-lXdbe) if available > +HAVE_XDBE=3Dno > +if test "${HAVE_X11}" =3D "yes"; then > + AC_CHECK_HEADER(X11/extensions/Xdbe.h, > + [AC_CHECK_LIB(Xext, XdbeAllocateBackBufferName, HAVE_XDBE=3Dyes)],= > + [], > + [#include > + ]) > + if test $HAVE_XDBE =3D yes; then > + XDBE_LIBS=3D-lXext > + fi > + if test $HAVE_XDBE =3D yes; then > + AC_DEFINE(HAVE_XDBE, 1, [Define to 1 if you have the Xdbe extensio= n.]) > + 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= =2E > HAVE_LIBXML2=3Dno > 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 =3D > XFIXES_LIBS =3D @XFIXES_LIBS@ > XFIXES_CFLAGS =3D @XFIXES_CFLAGS@ >=20 > +XDBE_LIBS =3D @XDBE_LIBS@ > +XDBE_CFLAGS =3D @XDBE_CFLAGS@ > + > ## widget.o if USE_X_TOOLKIT, otherwise empty. > WIDGET_OBJ=3D@WIDGET_OBJ@ >=20 > @@ -372,7 +375,7 @@ ALL_CFLAGS=3D > $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ > $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAG= S) \ > $(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 =3D > $(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_LI= BS) \ > $(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_Obje= ct arg, Lisp_Object result) > } >=20 > void > +font_flush_frame_caches (struct frame *f) > +{ > + struct font_driver_list *list; > + > + for (list =3D f->font_driver_list; list; list =3D 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] =3D 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); > }; >=20 >=20 > @@ -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_prop= erties[]); > + > +extern void font_flush_frame_caches (struct frame *f); >=20 > #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 foreg= round, unsigned long backgr > if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color)) > break; > xgcv.foreground =3D color.pixel; > - new->gcs[i - 1] =3D XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WIND= OW (f), > + new->gcs[i - 1] =3D XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAW= ABLE (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 =3D y - bitmap.top + i; > if (++n[0] =3D=3D 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] =3D 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, G= C *gcs, struct font *font, > pp[n[idx]].y =3D y - bitmap.top + i; > if (++(n[idx]) =3D=3D size) > { > - XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), > + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWAB= LE (f), > idx =3D=3D 6 ? gc_fore : gcs[idx], pp, size, > CoordModeOrigin); > n[idx] =3D 0; > @@ -180,10 +180,10 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore,= GC *gcs, struct font *font, > { > for (i =3D 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 fo= nt *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 . */ > #include "emacsgtkfixed.h" > #endif >=20 > +#ifdef HAVE_XDBE > +#include > +#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) =3D GTK_WIDGET_TO_X_WIN (wfixed); > + set_up_x_back_buffer (f); >=20 > /* 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); >=20 > +#ifdef HAVE_XDBE > + if (FRAME_X_WINDOW (f) !=3D FRAME_X_DRAWABLE (f)) > + { > + XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f), > + FRAME_X_DRAWABLE (f)); > + FRAME_X_DRAWABLE (f) =3D 0; > + } > +#endif > + > gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); > FRAME_X_WINDOW (f) =3D 0; /* Set to avoid XDestroyWindow in xter= m.c */ > FRAME_GTK_OUTER_WIDGET (f) =3D 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 *b= its, unsigned int width, unsi >=20 > #ifdef HAVE_X_WINDOWS > Pixmap bitmap; > - bitmap =3D XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDO= W (f), > + bitmap =3D XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWA= BLE (f), > bits, width, height); > if (! bitmap) > return -1; > @@ -327,7 +327,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Ob= ject file) >=20 > filename =3D SSDATA (found); >=20 > - result =3D XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),= > + result =3D XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f= ), > filename, &width, &height, &bitmap, &xhot, &yhot); > if (result !=3D 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 =3D FRAME_X_DISPLAY (f); > - Window window =3D FRAME_X_WINDOW (f); > + Drawable drawable =3D FRAME_X_DRAWABLE (f); > Screen *screen =3D FRAME_X_SCREEN (f); >=20 > 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 =3D xmalloc ((*ximg)->bytes_per_line * height); >=20 > /* Allocate a pixmap of the same size. */ > - *pixmap =3D XCreatePixmap (display, window, width, height, depth); > + *pixmap =3D XCreatePixmap (display, drawable, width, height, depth);= > if (*pixmap =3D=3D 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 =3D > (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, c= onst char **bits) > xpm_init_color_cache (f, &attrs); > #endif >=20 > - rc =3D XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW = (f), > + rc =3D XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABL= E (f), > (char **) bits, &bitmap, &mask, &attrs); > if (rc !=3D XpmSuccess) > { > @@ -3758,7 +3758,7 @@ xpm_load (struct frame *f, struct image *img) > #ifdef HAVE_X_WINDOWS > if (rc =3D=3D XpmSuccess) > { > - img->pixmap =3D XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WIND= OW (f), > + img->pixmap =3D XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAW= ABLE (f), > img->ximg->width, img->ximg->height, > img->ximg->depth); > if (img->pixmap =3D=3D NO_PIXMAP) > @@ -3768,7 +3768,7 @@ xpm_load (struct frame *f, struct image *img) > } > else if (img->mask_img) > { > - img->mask =3D XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW= (f), > + img->mask =3D XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DR= AWABLE (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 =3D XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WIND= OW (f), > + img->pixmap =3D XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAW= ABLE (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 =3D FRAME_X_WINDOW (f); > + printnum1 =3D FRAME_X_DRAWABLE (f); > printnum2 =3D img->pixmap; > window_and_pixmap_id > =3D make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, print= num2); > 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 >=20 > 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); >=20 > /* 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, in= t gy, NativeRectangle *rect) >=20 > /* 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 =3D 0; > } >=20 > + FOR_EACH_FRAME (tail, frame) > + { > + struct frame *f =3D 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 =3D hdc; > #endif > s->display =3D FRAME_X_DISPLAY (s->f); > - s->window =3D FRAME_X_WINDOW (s->f); > + s->window =3D FRAME_X_DRAWABLE (s->f); > s->char2b =3D char2b; > s->hl =3D hl; > s->row =3D 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, X= GCValues *xgcv) > { > GC gc; > block_input (); > - gc =3D XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgc= v); > + gc =3D XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), mask, x= gcv); > 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 . */ > #include "gtkutil.h" > #endif >=20 > +#ifdef HAVE_XDBE > +#include > +#endif > + > #ifdef USE_X_TOOLKIT > #include >=20 > @@ -2483,6 +2487,29 @@ xic_set_xfontset (struct frame *f, const char *b= ase_fontname) >=20 >=20 > =0C > + > +void > +set_up_x_back_buffer (struct frame* f) > +{ > + FRAME_X_DRAWABLE (f) =3D 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) =3D XdbeAllocateBackBufferName ( > + FRAME_X_DISPLAY (f), > + FRAME_X_WINDOW (f), > + XdbeCopied); > + if (x_had_errors_p (FRAME_X_DISPLAY (f))) > + FRAME_X_DRAWABLE (f) =3D FRAME_X_WINDOW (f); > + x_uncatch_errors_after_check (); > + } > +#endif > +} > + > #ifdef USE_X_TOOLKIT >=20 > /* 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); >=20 > FRAME_X_WINDOW (f) =3D XtWindow (frame_widget); > - > + set_up_x_back_buffer (f); > validate_x_resource_name (); >=20 > class_hints.res_name =3D 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); >=20 > #ifdef HAVE_X_I18N > if (use_xim) > @@ -2938,7 +2966,7 @@ x_make_gc (struct frame *f) > gc_values.line_width =3D 0; /* Means 1 using fast algorithm. */ > f->output_data.x->normal_gc > =3D XCreateGC (FRAME_X_DISPLAY (f), > - FRAME_X_WINDOW (f), > + FRAME_X_DRAWABLE (f), > GCLineWidth | GCForeground | GCBackground, > &gc_values); >=20 > @@ -2947,7 +2975,7 @@ x_make_gc (struct frame *f) > gc_values.background =3D FRAME_FOREGROUND_PIXEL (f); > f->output_data.x->reverse_gc > =3D XCreateGC (FRAME_X_DISPLAY (f), > - FRAME_X_WINDOW (f), > + FRAME_X_DRAWABLE (f), > GCForeground | GCBackground | GCLineWidth, > &gc_values); >=20 > @@ -2956,7 +2984,7 @@ x_make_gc (struct frame *f) > gc_values.background =3D f->output_data.x->cursor_pixel; > gc_values.fill_style =3D FillOpaqueStippled; > f->output_data.x->cursor_gc > - =3D XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), > + =3D 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 *dpyinf= o, 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, i= nt to, int x, int y, > { > if (s->padding_p) > for (i =3D 0; i < len; i++) > - XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s-= >f), > + XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWAB= LE (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 =3D 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, i= nt to, int x, int y, > { > if (s->padding_p) > for (i =3D 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 =3D 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=3D 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; > } >=20 > +static void > +xftfont_flush_frame_caches (struct frame *f) > +{ > + if (FRAME_X_WINDOW (f) !=3D 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 =3D 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 =3D xftfont_flush_frame_caches; >=20 > 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 . */ > #include > #endif >=20 > +#ifdef HAVE_XDBE > +#include > +#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 =3D 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, in= t 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, in= t 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) !=3D 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 > } >=20 > @@ -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 curs= or_on_p, > /* End update of frame F. This function is installed as a hook in > update_end. */ >=20 > +#if defined (HAVE_XDBE) > +static void > +show_back_buffer (struct frame *f) > +{ > + if (FRAME_X_WINDOW (f) !=3D FRAME_X_DRAWABLE (f)) > + { > + XdbeSwapInfo swap_info; > + memset (&swap_info, 0, sizeof (swap_info)); > + swap_info.swap_window =3D FRAME_X_WINDOW (f); > + swap_info.swap_action =3D 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 +=3D FRAME_MENU_BAR_HEIGHT (f); > surface =3D 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) =3D true; > + else > + show_back_buffer (f); > +#endif >=20 > #ifndef XFlush > block_input (); > @@ -1229,6 +1258,17 @@ x_update_end (struct frame *f) > #endif > } >=20 > +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) =3D false; > + } > +#endif > +} >=20 > /* 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 gl= yph_row *row, struct draw_fring > #else /* not USE_CAIRO */ > if (p->which) > { > - Window window =3D FRAME_X_WINDOW (f); > + Drawable drawable =3D FRAME_X_DRAWABLE (f); > char *bits; > Pixmap pixmap, clipmask =3D (Pixmap) 0; > int depth =3D DefaultDepthOfScreen (FRAME_X_SCREEN (f)); > @@ -1367,7 +1407,7 @@ x_draw_fringe_bitmap (struct window *w, struct gl= yph_row *row, struct draw_fring >=20 > /* Draw the bitmap. I believe these small pixmaps can be cached= > by the server. */ > - pixmap =3D XCreatePixmapFromBitmapData (display, window, bits, p= ->wd, p->h, > + pixmap =3D 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 gl= yph_row *row, struct draw_fring > XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrig= in, &gcv); > } >=20 > - 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); >=20 > @@ -2565,7 +2605,7 @@ x_setup_relief_color (struct frame *f, struct rel= ief *relief, double factor, > { > xgcv.stipple =3D dpyinfo->gray; > mask |=3D GCStipple; > - relief->gc =3D XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);= > + relief->gc =3D 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 =3D FRAME_X_DISPLAY (f); > - Window window =3D FRAME_X_WINDOW (f); > + Drawable drawable =3D FRAME_X_DRAWABLE (f); > int i; > GC gc; >=20 > @@ -2715,12 +2755,12 @@ x_draw_relief_rect (struct frame *f, > if (top_p) > { > if (width =3D=3D 1) > - XDrawLine (dpy, window, gc, > + XDrawLine (dpy, drawable, gc, > left_x + left_p, top_y, > right_x + !right_p, top_y); >=20 > for (i =3D 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 =3D=3D 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, botto= m_y); >=20 > - 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); >=20 > for (i =3D (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); >=20 > /* 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, botto= m_y); > } >=20 > /* 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 =3D 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 =3D 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_DRAWAB= LE (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) !=3D 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 > } >=20 > @@ -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 =3D true; > + font_flush_frame_caches (f); > SET_FRAME_GARBAGED (f); > } > else > @@ -8437,7 +8484,10 @@ handle_one_xevent (struct x_display_info *dpyinf= o, > { > if (FRAME_PIXEL_HEIGHT (f) !=3D configureEvent.xconfigur= e.height > || FRAME_PIXEL_WIDTH (f) !=3D configureEvent.xconfig= ure.width) > - SET_FRAME_GARBAGED (f); > + { > + font_flush_frame_caches (f); > + SET_FRAME_GARBAGED (f); > + } > FRAME_PIXEL_HEIGHT (f) =3D configureEvent.xconfigure.hei= ght; > FRAME_PIXEL_WIDTH (f) =3D configureEvent.xconfigure.widt= h; > } > @@ -8463,7 +8513,8 @@ handle_one_xevent (struct x_display_info *dpyinfo= , > || configureEvent.xconfigure.height !=3D FRAME_PIXEL_HEI= GHT (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 gl= yph_row *row) > if (dpyinfo->scratch_cursor_gc) > XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv); > else > - dpyinfo->scratch_cursor_gc =3D XCreateGC (dpy, FRAME_X_WINDOW (f),= > + dpyinfo->scratch_cursor_gc =3D XCreateGC (dpy, FRAME_X_DRAWABLE (f= ), > GCForeground, &xgcv); > gc =3D dpyinfo->scratch_cursor_gc; >=20 > @@ -8937,7 +8988,7 @@ x_draw_bar_cursor (struct window *w, struct glyph= _row *row, int width, enum text > else > { > Display *dpy =3D FRAME_X_DISPLAY (f); > - Window window =3D FRAME_X_WINDOW (f); > + Drawable drawable =3D FRAME_X_DRAWABLE (f); > GC gc =3D FRAME_DISPLAY_INFO (f)->scratch_cursor_gc; > unsigned long mask =3D GCForeground | GCBackground | GCGraphicsE= xposures; > struct face *face =3D 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 =3D XCreateGC (dpy, window, mask, &xgcv); > + gc =3D XCreateGC (dpy, drawable, mask, &xgcv); > FRAME_DISPLAY_INFO (f)->scratch_cursor_gc =3D gc; > } >=20 > @@ -11271,7 +11322,14 @@ x_free_frame_resources (struct frame *f) > #endif /* USE_GTK */ >=20 > if (FRAME_X_WINDOW (f)) > - XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); > + { > +#ifdef HAVE_XDBE > + if (FRAME_X_WINDOW (f) !=3D 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 */ >=20 > unload_color (f, FRAME_FOREGROUND_PIXEL (f)); > @@ -12111,7 +12169,17 @@ x_term_init (Lisp_Object display_name, char *x= rm_option, char *resource_name) > } > else > dpyinfo->cmap =3D XCreateColormap (dpyinfo->display, dpyinfo->root= _window, > - dpyinfo->visual, AllocNone); > + dpyinfo->visual, AllocNone); > + > +#ifdef HAVE_XDBE > + dpyinfo->supports_xdbe =3D false; > + { > + int xdbe_major; > + int xdbe_minor; > + if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_min= or)) > + dpyinfo->supports_xdbe =3D true; > + } > +#endif >=20 > #ifdef HAVE_XFT > { > @@ -12590,6 +12658,7 @@ x_create_terminal (struct x_display_info *dpyin= fo) > terminal->toggle_invisible_pointer_hook =3D XTtoggle_invisible_point= er; > terminal->update_begin_hook =3D x_update_begin; > terminal->update_end_hook =3D x_update_end; > + terminal->redisplay_end_hook =3D x_redisplay_end; > terminal->read_socket_hook =3D XTread_socket; > terminal->frame_up_to_date_hook =3D XTframe_up_to_date; > terminal->mouse_position_hook =3D 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 > }; >=20 > #ifdef HAVE_X_I18N > @@ -527,6 +531,17 @@ struct x_output > and the X window has not yet been created. */ > Window window_desc; >=20 > +#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) >=20 > +/* 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_f= lip) > +#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); >=20 > +extern void set_up_x_back_buffer (struct frame* f); > + > /* Defined in xselect.c. */ >=20 > extern void x_handle_property_notify (const XPropertyEvent *); >=20 >=20 >=20 --fbDHfRkGooq6K3UtdiOssBskgVXCPAf2j-- --vUlXPuSt3TTfbDjCfC39Q1EIheVnJWoVx Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJYCZIGAAoJEPqg+cTm90wjQeUP/AwQw4Rqg8yqlVv47LHcS02+ bWCyBBM3G/rxoPiCVhcEoT6ecR9nOkKT8mIBH/AC/15abodx+8LiNs5pVLojDUfW BH4uk0sKZfy/DANoiVMorG3pVCmRTMjxrRxzEFPKgD5+WcjHQ0y1vlR72eUK+pfR rbcrq0RRwn84vKJPqjwR2/BAKmxvVR3V4UU5CxTGdnpGcTSb+Cd82+G8IGUJnv+l fkiHMami7FIztEdMjb/s85XZsPxUcMAMnVqoM+7/xyoqqy2Icv+3LTutYsxArVOa gn1q97tlEVcSCZMlD1uFcS4zHDQCZW8svUhx49VSvri1uVUkRh2d3dZEC3YeZT5U 3O/e9CnIVB78Z1xqZXHKMUIc4VX1Mv82xzpYiXTuKYfEFMEvKdAs/0Y340S8niA3 7va9EXFWnk/eZOd0HKnGAbFzdB958ke4TqhXUnzcR7W/Nf2xEs7bhf6cqorY/tpC s4KYtMJ1rwbTd0iJCbDXjUz7j9wlMwTxExeCDsR6ytRCtLH4DPlJn6WiZKSOoXsw 8hn+ZEpsH9ZNgPEXn4f0aghIa81J/fbIG2aif62B+t3yLtlgVcHgGeZXxllVWpOh o1Qxdp5cwwoQV4dgXT37s/gZmebnKZGPIrp+OeMSJBJV714xacB2eKDszXhmquOR lboNabM1pe/Ra1Y6rPLr =r5qz -----END PGP SIGNATURE----- --vUlXPuSt3TTfbDjCfC39Q1EIheVnJWoVx--