aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-03-06 10:02:03 +0800
committerPo Lu2022-03-06 10:02:03 +0800
commitdb2cb522e154ce97b7a780572d2cb99d82d291ca (patch)
tree0034636d6dcf9a776d4f47736d3ffddd8a800624
parentc9667e9b60fe0044ea4d5f000973a87a0c584033 (diff)
downloademacs-db2cb522e154ce97b7a780572d2cb99d82d291ca.tar.gz
emacs-db2cb522e154ce97b7a780572d2cb99d82d291ca.zip
Reduce non-toolkit scroll bar flicker
* src/xterm.c (x_scroll_bar_create): Initialize double buffer for scroll bar. (x_scroll_bar_set_handle) (x_scroll_bar_remove, x_scroll_bar_expose): Draw to back buffer instead. (x_scroll_bar_end_update): New function. (x_scroll_bar_clear): Fill the scroll bar with the background instead when double buffered. * src/xterm.h (struct scroll_bar): New field `x_drawable'.
-rw-r--r--src/xterm.c168
-rw-r--r--src/xterm.h5
2 files changed, 158 insertions, 15 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 89feece10eb..1d68d4e9393 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -765,6 +765,10 @@ static void x_initialize (void);
765static bool x_get_current_wm_state (struct frame *, Window, int *, bool *, bool *); 765static bool x_get_current_wm_state (struct frame *, Window, int *, bool *, bool *);
766static void x_update_opaque_region (struct frame *, XEvent *); 766static void x_update_opaque_region (struct frame *, XEvent *);
767 767
768#if !defined USE_TOOLKIT_SCROLL_BARS && defined HAVE_XDBE
769static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar *);
770#endif
771
768/* Flush display of frame F. */ 772/* Flush display of frame F. */
769 773
770static void 774static void
@@ -8547,6 +8551,9 @@ x_scroll_bar_create (struct window *w, int top, int left,
8547 XSetWindowAttributes a; 8551 XSetWindowAttributes a;
8548 unsigned long mask; 8552 unsigned long mask;
8549 Window window; 8553 Window window;
8554#ifdef HAVE_XDBE
8555 Drawable drawable;
8556#endif
8550 8557
8551 a.background_pixel = f->output_data.x->scroll_bar_background_pixel; 8558 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8552 if (a.background_pixel == -1) 8559 if (a.background_pixel == -1)
@@ -8575,6 +8582,21 @@ x_scroll_bar_create (struct window *w, int top, int left,
8575 CopyFromParent, 8582 CopyFromParent,
8576 /* Attributes. */ 8583 /* Attributes. */
8577 mask, &a); 8584 mask, &a);
8585#ifdef HAVE_XDBE
8586 if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
8587 {
8588 x_catch_errors (FRAME_X_DISPLAY (f));
8589 drawable = XdbeAllocateBackBufferName (FRAME_X_DISPLAY (f),
8590 window, XdbeCopied);
8591 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
8592 drawable = window;
8593 else
8594 XSetWindowBackgroundPixmap (FRAME_X_DISPLAY (f), window, None);
8595 x_uncatch_errors_after_check ();
8596 }
8597 else
8598 drawable = window;
8599#endif
8578 8600
8579#ifdef HAVE_XINPUT2 8601#ifdef HAVE_XINPUT2
8580 /* Ask for input extension button and motion events. This lets us 8602 /* Ask for input extension button and motion events. This lets us
@@ -8599,7 +8621,11 @@ x_scroll_bar_create (struct window *w, int top, int left,
8599 XISelectEvents (FRAME_X_DISPLAY (f), window, &mask, 1); 8621 XISelectEvents (FRAME_X_DISPLAY (f), window, &mask, 1);
8600 } 8622 }
8601#endif 8623#endif
8624
8602 bar->x_window = window; 8625 bar->x_window = window;
8626#ifdef HAVE_XDBE
8627 bar->x_drawable = drawable;
8628#endif
8603 } 8629 }
8604#endif /* not USE_TOOLKIT_SCROLL_BARS */ 8630#endif /* not USE_TOOLKIT_SCROLL_BARS */
8605 8631
@@ -8673,7 +8699,11 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
8673 bool rebuild) 8699 bool rebuild)
8674{ 8700{
8675 bool dragging = bar->dragging != -1; 8701 bool dragging = bar->dragging != -1;
8702#ifndef HAVE_XDBE
8676 Window w = bar->x_window; 8703 Window w = bar->x_window;
8704#else
8705 Drawable w = bar->x_drawable;
8706#endif
8677 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); 8707 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8678 GC gc = f->output_data.x->normal_gc; 8708 GC gc = f->output_data.x->normal_gc;
8679 8709
@@ -8723,10 +8753,22 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
8723 /* Draw the empty space above the handle. Note that we can't clear 8753 /* Draw the empty space above the handle. Note that we can't clear
8724 zero-height areas; that means "clear to end of window." */ 8754 zero-height areas; that means "clear to end of window." */
8725 if ((inside_width > 0) && (start > 0)) 8755 if ((inside_width > 0) && (start > 0))
8726 x_clear_area1 (FRAME_X_DISPLAY (f), w, 8756 {
8727 VERTICAL_SCROLL_BAR_LEFT_BORDER, 8757 if (f->output_data.x->scroll_bar_background_pixel != -1)
8728 VERTICAL_SCROLL_BAR_TOP_BORDER, 8758 XSetForeground (FRAME_X_DISPLAY (f), gc,
8729 inside_width, start, False); 8759 f->output_data.x->scroll_bar_background_pixel);
8760 else
8761 XSetForeground (FRAME_X_DISPLAY (f), gc,
8762 FRAME_BACKGROUND_PIXEL (f));
8763
8764 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8765 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8766 VERTICAL_SCROLL_BAR_TOP_BORDER,
8767 inside_width, start);
8768
8769 XSetForeground (FRAME_X_DISPLAY (f), gc,
8770 FRAME_FOREGROUND_PIXEL (f));
8771 }
8730 8772
8731 /* Change to proper foreground color if one is specified. */ 8773 /* Change to proper foreground color if one is specified. */
8732 if (f->output_data.x->scroll_bar_foreground_pixel != -1) 8774 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
@@ -8740,20 +8782,38 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
8740 VERTICAL_SCROLL_BAR_TOP_BORDER + start, 8782 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8741 inside_width, end - start); 8783 inside_width, end - start);
8742 8784
8743 /* Restore the foreground color of the GC if we changed it above. */
8744 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8745 XSetForeground (FRAME_X_DISPLAY (f), gc,
8746 FRAME_FOREGROUND_PIXEL (f));
8747 8785
8748 /* Draw the empty space below the handle. Note that we can't 8786 /* Draw the empty space below the handle. Note that we can't
8749 clear zero-height areas; that means "clear to end of window." */ 8787 clear zero-height areas; that means "clear to end of window." */
8750 if ((inside_width > 0) && (end < inside_height)) 8788 if ((inside_width > 0) && (end < inside_height))
8751 x_clear_area1 (FRAME_X_DISPLAY (f), w, 8789 {
8752 VERTICAL_SCROLL_BAR_LEFT_BORDER, 8790 if (f->output_data.x->scroll_bar_background_pixel != -1)
8753 VERTICAL_SCROLL_BAR_TOP_BORDER + end, 8791 XSetForeground (FRAME_X_DISPLAY (f), gc,
8754 inside_width, inside_height - end, False); 8792 f->output_data.x->scroll_bar_background_pixel);
8793 else
8794 XSetForeground (FRAME_X_DISPLAY (f), gc,
8795 FRAME_BACKGROUND_PIXEL (f));
8796
8797 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8798 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8799 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8800 inside_width, inside_height - end);
8801
8802 XSetForeground (FRAME_X_DISPLAY (f), gc,
8803 FRAME_FOREGROUND_PIXEL (f));
8804 }
8805
8806 /* Restore the foreground color of the GC if we changed it above. */
8807 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8808 XSetForeground (FRAME_X_DISPLAY (f), gc,
8809 FRAME_FOREGROUND_PIXEL (f));
8755 } 8810 }
8756 8811
8812#ifdef HAVE_XDBE
8813 if (!rebuild)
8814 x_scroll_bar_end_update (FRAME_DISPLAY_INFO (f), bar);
8815#endif
8816
8757 unblock_input (); 8817 unblock_input ();
8758} 8818}
8759 8819
@@ -8775,6 +8835,11 @@ x_scroll_bar_remove (struct scroll_bar *bar)
8775 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar)); 8835 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
8776#endif /* not USE_GTK */ 8836#endif /* not USE_GTK */
8777#else 8837#else
8838#ifdef HAVE_XDBE
8839 if (bar->x_window != bar->x_drawable)
8840 XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
8841 bar->x_drawable);
8842#endif
8778 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window); 8843 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
8779#endif 8844#endif
8780 8845
@@ -9195,12 +9260,39 @@ XTjudge_scroll_bars (struct frame *f)
9195static void 9260static void
9196x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event) 9261x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
9197{ 9262{
9263#ifndef HAVE_XDBE
9198 Window w = bar->x_window; 9264 Window w = bar->x_window;
9265#else
9266 Drawable w = bar->x_drawable;
9267#endif
9268
9199 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); 9269 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9200 GC gc = f->output_data.x->normal_gc; 9270 GC gc = f->output_data.x->normal_gc;
9201 9271
9202 block_input (); 9272 block_input ();
9203 9273
9274#ifdef HAVE_XDBE
9275 if (w != bar->x_window)
9276 {
9277 if (f->output_data.x->scroll_bar_background_pixel != -1)
9278 XSetForeground (FRAME_X_DISPLAY (f), gc,
9279 f->output_data.x->scroll_bar_background_pixel);
9280 else
9281 XSetForeground (FRAME_X_DISPLAY (f), gc,
9282 FRAME_BACKGROUND_PIXEL (f));
9283
9284 XFillRectangle (FRAME_X_DISPLAY (f),
9285 bar->x_drawable,
9286 gc, event->xexpose.x,
9287 event->xexpose.y,
9288 event->xexpose.width,
9289 event->xexpose.height);
9290
9291 XSetForeground (FRAME_X_DISPLAY (f), gc,
9292 FRAME_FOREGROUND_PIXEL (f));
9293 }
9294#endif
9295
9204 x_scroll_bar_set_handle (bar, bar->start, bar->end, true); 9296 x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
9205 9297
9206 /* Switch to scroll bar foreground color. */ 9298 /* Switch to scroll bar foreground color. */
@@ -9221,6 +9313,10 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
9221 XSetForeground (FRAME_X_DISPLAY (f), gc, 9313 XSetForeground (FRAME_X_DISPLAY (f), gc,
9222 FRAME_FOREGROUND_PIXEL (f)); 9314 FRAME_FOREGROUND_PIXEL (f));
9223 9315
9316#ifdef HAVE_XDBE
9317 x_scroll_bar_end_update (FRAME_DISPLAY_INFO (f), bar);
9318#endif
9319
9224 unblock_input (); 9320 unblock_input ();
9225 9321
9226} 9322}
@@ -9352,6 +9448,24 @@ x_scroll_bar_note_movement (struct scroll_bar *bar,
9352 } 9448 }
9353} 9449}
9354 9450
9451#ifdef HAVE_XDBE
9452static void
9453x_scroll_bar_end_update (struct x_display_info *dpyinfo,
9454 struct scroll_bar *bar)
9455{
9456 XdbeSwapInfo swap_info;
9457
9458 /* This means the scroll bar is double-buffered. */
9459 if (bar->x_drawable != bar->x_window)
9460 {
9461 memset (&swap_info, 0, sizeof swap_info);
9462 swap_info.swap_window = bar->x_window;
9463 swap_info.swap_action = XdbeCopied;
9464 XdbeSwapBuffers (dpyinfo->display, &swap_info, 1);
9465 }
9466}
9467#endif
9468
9355#endif /* !USE_TOOLKIT_SCROLL_BARS */ 9469#endif /* !USE_TOOLKIT_SCROLL_BARS */
9356 9470
9357/* Return information to the user about the current position of the mouse 9471/* Return information to the user about the current position of the mouse
@@ -9502,6 +9616,16 @@ x_scroll_bar_clear (struct frame *f)
9502{ 9616{
9503#ifndef USE_TOOLKIT_SCROLL_BARS 9617#ifndef USE_TOOLKIT_SCROLL_BARS
9504 Lisp_Object bar; 9618 Lisp_Object bar;
9619#ifdef HAVE_XDBE
9620 GC gc = f->output_data.x->normal_gc;
9621
9622 if (f->output_data.x->scroll_bar_background_pixel != -1)
9623 XSetForeground (FRAME_X_DISPLAY (f), gc,
9624 f->output_data.x->scroll_bar_background_pixel);
9625 else
9626 XSetForeground (FRAME_X_DISPLAY (f), gc,
9627 FRAME_BACKGROUND_PIXEL (f));
9628#endif
9505 9629
9506 /* We can have scroll bars even if this is 0, 9630 /* We can have scroll bars even if this is 0,
9507 if we just turned off scroll bar mode. 9631 if we just turned off scroll bar mode.
@@ -9509,9 +9633,23 @@ x_scroll_bar_clear (struct frame *f)
9509 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) 9633 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9510 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar); 9634 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9511 bar = XSCROLL_BAR (bar)->next) 9635 bar = XSCROLL_BAR (bar)->next)
9512 XClearArea (FRAME_X_DISPLAY (f), 9636 {
9513 XSCROLL_BAR (bar)->x_window, 9637#ifndef HAVE_XDBE
9514 0, 0, 0, 0, True); 9638 XClearArea (FRAME_X_DISPLAY (f),
9639 XSCROLL_BAR (bar)->x_window,
9640 0, 0, 0, 0, True);
9641#else
9642 XFillRectangle (FRAME_X_DISPLAY (f),
9643 XSCROLL_BAR (bar)->x_drawable,
9644 gc, 0, 0, XSCROLL_BAR (bar)->width,
9645 XSCROLL_BAR (bar)->height);
9646#endif
9647 }
9648
9649#ifdef HAVE_XDBE
9650 XSetForeground (FRAME_X_DISPLAY (f), gc,
9651 FRAME_FOREGROUND_PIXEL (f));
9652#endif
9515#endif /* not USE_TOOLKIT_SCROLL_BARS */ 9653#endif /* not USE_TOOLKIT_SCROLL_BARS */
9516} 9654}
9517 9655
diff --git a/src/xterm.h b/src/xterm.h
index 7f45e2f172e..dd510ae2576 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1081,6 +1081,11 @@ struct scroll_bar
1081 /* The X window representing this scroll bar. */ 1081 /* The X window representing this scroll bar. */
1082 Window x_window; 1082 Window x_window;
1083 1083
1084#if defined HAVE_XDBE && !defined USE_TOOLKIT_SCROLL_BARS
1085 /* The X drawable representing this scroll bar. */
1086 Drawable x_drawable;
1087#endif
1088
1084 /* The position and size of the scroll bar in pixels, relative to the 1089 /* The position and size of the scroll bar in pixels, relative to the
1085 frame. */ 1090 frame. */
1086 int top, left, width, height; 1091 int top, left, width, height;