]> git.eshelyaron.com Git - emacs.git/commitdiff
End Resize flickering by copying surface rather than just clearing
authorJeff Walsh <jawalsh@localhost.localdomain>
Mon, 13 Jan 2020 05:17:50 +0000 (16:17 +1100)
committerJeff Walsh <fejfighter@gmail.com>
Sun, 22 Nov 2020 03:46:56 +0000 (14:46 +1100)
* src/pgtkterm.h (struct pgtk_output): store desired sizes

* src/pgtkterm.c (FRAME_CR_SURFACE_DESIRED_HEIGHT)
(FRAME_CR_SURFACE_DESIRED_WIDTH, size_allocate, configure_event)
(pgtk_cr_update_surface_desired_size): add "desired" size for handling
surface change

* src/gtkutil.c (xg_frame_resized, xg_create_frame_widgets): remove
surface destroy, turn off double buffer call

src/gtkutil.c
src/pgtkterm.c
src/pgtkterm.h

index 394d81ace609e8ec77b836bd7b47333ea05df3e5..8cdbe3e4ad5e063b8719c85dd44985aaf323c4e1 100644 (file)
@@ -1053,9 +1053,6 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
       change_frame_size (f, width, height, 0, 1, 0, 1);
       SET_FRAME_GARBAGED (f);
       cancel_mouse_face (f);
-#ifdef HAVE_PGTK
-      pgtk_cr_destroy_surface (f);
-#endif
     }
 }
 
@@ -1449,7 +1446,10 @@ xg_create_frame_widgets (struct frame *f)
      FIXME: gtk_widget_set_double_buffered is deprecated and might stop
      working in the future.  We need to migrate away from combining
      X and GTK+ drawing to a pure GTK+ build.  */
+
+#ifndef HAVE_PGTK
   gtk_widget_set_double_buffered (wfixed, FALSE);
+#endif
 
 #if ! GTK_CHECK_VERSION (3, 22, 0)
   gtk_window_set_wmclass (GTK_WINDOW (wtop),
index 67ff37863322fcfb95829cfb4f9bb8ef1f552a33..74eb08d33014a7da95befcc9dfdf69babcb1ef44 100644 (file)
@@ -22,6 +22,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    interpretation of even the system includes. */
 #include <config.h>
 
+#include <cairo.h>
 #include <fcntl.h>
 #include <math.h>
 #include <pthread.h>
@@ -63,6 +64,11 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 
 #define FRAME_CR_CONTEXT(f)    ((f)->output_data.pgtk->cr_context)
 #define FRAME_CR_SURFACE(f)    ((f)->output_data.pgtk->cr_surface)
+#define FRAME_CR_SURFACE_DESIRED_WIDTH(f)              \
+  ((f)->output_data.pgtk->cr_surface_desired_width)
+#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
+  ((f)->output_data.pgtk->cr_surface_desired_height)
+
 
 struct pgtk_display_info *x_display_list; /* Chain of existing displays */
 extern Lisp_Object tip_frame;
@@ -4851,6 +4857,7 @@ static void size_allocate(GtkWidget *widget, GtkAllocation *alloc, gpointer *use
   if (f) {
     PGTK_TRACE("%dx%d", alloc->width, alloc->height);
     xg_frame_resized(f, alloc->width, alloc->height);
+    pgtk_cr_update_surface_desired_size(f, alloc->width, alloc->height);
   }
 }
 
@@ -5274,6 +5281,7 @@ static gboolean configure_event(GtkWidget *widget, GdkEvent *event, gpointer *us
   if (f && widget == FRAME_GTK_OUTER_WIDGET (f)) {
     PGTK_TRACE("%dx%d", event->configure.width, event->configure.height);
     xg_frame_resized(f, event->configure.width, event->configure.height);
+    pgtk_cr_update_surface_desired_size(f, event->configure.width, event->configure.height);
   }
   return TRUE;
 }
@@ -6574,6 +6582,40 @@ If set to a non-float value, there will be no wait at all.  */);
 
 }
 
+
+void
+pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height)
+{
+  PGTK_TRACE("pgtk_cr_update_surface_desired_size");
+
+  if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width
+      || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height)
+    {
+      cairo_surface_t *old_surface = FRAME_CR_SURFACE(f);
+      cairo_t *cr = NULL;
+      cairo_t *old_cr = FRAME_CR_CONTEXT(f);
+      FRAME_CR_SURFACE(f) = gdk_window_create_similar_surface(gtk_widget_get_window(FRAME_GTK_WIDGET(f)),
+                                                             CAIRO_CONTENT_COLOR_ALPHA,
+                                                             width,
+                                                             height);
+
+      if (old_surface){
+       cr = cairo_create(FRAME_CR_SURFACE(f));
+       cairo_set_source_surface (cr, old_surface, 0, 0);
+
+       cairo_paint(cr);
+       FRAME_CR_CONTEXT (f) = cr;
+
+        cairo_destroy(old_cr);
+       cairo_surface_destroy (old_surface);
+      }
+      gtk_widget_queue_draw(FRAME_GTK_WIDGET(f));
+      FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width;
+      FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height;
+    }
+}
+
+
 cairo_t *
 pgtk_begin_cr_clip (struct frame *f)
 {
index 694a85bac2e637ce57282905d7867fe56876ea2a..d441e16106e07188cf559fe0b0136d1d022585e5 100644 (file)
@@ -366,6 +366,7 @@ struct pgtk_output
 #ifdef USE_CAIRO
   /* Cairo drawing context.  */
   cairo_t *cr_context;
+  int cr_surface_desired_width, cr_surface_desired_height;
   /* Cairo surface for double buffering */
   cairo_surface_t *cr_surface;
   cairo_surface_t *cr_surface_visible_bell;
@@ -568,6 +569,7 @@ extern int pgtk_select (int nfds, fd_set *readfds, fd_set *writefds,
                        sigset_t *sigmask);
 
 /* Cairo related functions implemented in pgtkterm.c */
+extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int);
 extern cairo_t *pgtk_begin_cr_clip (struct frame *f);
 extern void pgtk_end_cr_clip (struct frame *f);
 extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc);