diff options
| author | Po Lu | 2022-03-06 10:02:03 +0800 |
|---|---|---|
| committer | Po Lu | 2022-03-06 10:02:03 +0800 |
| commit | db2cb522e154ce97b7a780572d2cb99d82d291ca (patch) | |
| tree | 0034636d6dcf9a776d4f47736d3ffddd8a800624 | |
| parent | c9667e9b60fe0044ea4d5f000973a87a0c584033 (diff) | |
| download | emacs-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.c | 168 | ||||
| -rw-r--r-- | src/xterm.h | 5 |
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); | |||
| 765 | static bool x_get_current_wm_state (struct frame *, Window, int *, bool *, bool *); | 765 | static bool x_get_current_wm_state (struct frame *, Window, int *, bool *, bool *); |
| 766 | static void x_update_opaque_region (struct frame *, XEvent *); | 766 | static void x_update_opaque_region (struct frame *, XEvent *); |
| 767 | 767 | ||
| 768 | #if !defined USE_TOOLKIT_SCROLL_BARS && defined HAVE_XDBE | ||
| 769 | static 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 | ||
| 770 | static void | 774 | static 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) | |||
| 9195 | static void | 9260 | static void |
| 9196 | x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event) | 9261 | x_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 | ||
| 9452 | static void | ||
| 9453 | x_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; |