diff options
| author | Daniel Colascione | 2016-10-20 20:34:36 -0700 |
|---|---|---|
| committer | Daniel Colascione | 2016-10-28 19:21:39 -0700 |
| commit | c29071587c64efb30792bd72248d3c791abd9337 (patch) | |
| tree | a38c726630104997b7d63cbba56056ed1f8d19fa /src | |
| parent | f5543ffcf5b2974fa8fc6cf007e9109fa8e9051e (diff) | |
| download | emacs-c29071587c64efb30792bd72248d3c791abd9337.tar.gz emacs-c29071587c64efb30792bd72248d3c791abd9337.zip | |
Add double-buffering support to reduce flicker
* src/dispextern.h (struct glyph_string): Remove window member
(block_buffer_flips, unblock_buffer_flips)
(buffer_flipping_blocked_p): Declare.
* src/xterm.h (struct x_display_info): New member supports_xdbe.
(struct x_output): New members draw_desc and need_buffer_flip.
(FRAME_X_DRAWABLE, FRAME_X_RAW_DRAWABLE)
(FRAME_X_DOUBLE_BUFFERED_P)
(FRAME_X_NEED_BUFFER_FLIP): New macros.
(set_up_x_back_buffer, tear_down_x_back_buffer)
(initial_set_up_x_back_buffer): Declare.
* src/xterm.c: Include Xdbe.h.
(x_begin_cr_clip, x_fill_rectangle, x_draw_rectangle)
(x_draw_vertical_window_border, x_update_end)
(x_setup_relief_color, x_draw_relief_rect)
(x_draw_fringe_bitmap, x_shift_glyphs_for_insert)
(x_scroll_run, x_draw_hollow_cursor, x_draw_bar_cursor): Use
FRAME_X_DRAWABLE instead of FRAME_X_WINDOW; rename local
variables appropriately; substitute calls to XClearArea with
x_clear_area, which DTRT for double buffering.
(x_clear_window, x_clear_area): In double-buffering mode, use
rect-drawing X functions instead of XClearWindow and
XClearArea, which always operate on the front buffer.
(show_back_buffer): New function.
(XTframe_up_to_date): Call show_back_buffer when done.
(x_clear_frame, x_clear_frame_area): Remove obsolete calls to
gtk_widget_queue_draw to refresh scroll bars; scroll bars are
now independent X windows.
(handle_one_xevent): Call font_drop_xrender_surfaces when
XftDraw might need regenerating; perform buffer flip when
responding to Expose events; issue front-buffer clearing
commands as stopgap while we wait for redisplay.
Call flush_dirty_back_buffers.
(x_make_frame_visible): Un-bitrot comment; move XSETFRAME
earlier in function.
(x_free_frame_resources): Call tear_down_x_back_buffer when
destroying frame.
(x_term_init): Attempt to initialize double buffer extension.
(x_flip_and_flush): New function.
(x_redisplay_interface): Point to x_flip_and_flush instead of
x_flip directly.
(flush_dirty_back_buffers): New function.
(x_create_terminal): Register buffer_flipping_unblocked_hook.
* src/xftfont.c (xftfont_drop_xrender_surfaces): Use
FRAME_X_DRAWABLE instead of FRAME_X_WINDOW.
(xftfont_draw): Call x_mark_frame_dirty.
(xftfont_drop_xrender_surfaces): New function.
(syms_of_xftfont): Register it.
* src/xfont.c (xfont_draw): Use FRAME_X_DRAWABLE instead of
FRAME_X_WINDOW.
* src/xfns.c: Include Xdbe.h.
(x_set_inhibit_double_buffering, set_up_x_back_buffer)
(Fx_double_buffered_p): New functions.
(x_window): Call initial_set_up_x_back_buffer.
(x_make_gc): Use FRAME_X_DRAWABLE instead of FRAME_X_WINDOW.
(Fx_create_frame): Configure `inhibit-double-buffering'
frame parameter.
(x_create_tip_frame): Call initial_set_up_x_back_buffer.
(x_frame_parm_handlers): Register
x_set_inhibit_double_buffering.
(syms_of_xfns): Register Sx_double_buffered_p.
(x_mark_frame_dirty): Define.
* src/xfaces.c (x_create_gc): Use FRAME_X_DRAWABLE instead of
FRAME_X_WINDOW.
* src/xdisp.c (remember_mouse_glyph, init_glyph_string): Use
FRAME_X_DRAWABLE instead of FRAME_X_WINDOW.
(redisplay_internal): Restart redisplay if a frame is garbaged
during updating; explain why. Block buffer flips
during redisplay.
(redisplay_preserve_echo_area): Block buffer flip during call
to redisplay_internal.
(buffer_flip_blocked_depth): New variable.
(block_buffer_flips, unblock_buffer_flips)
(buffer_flipping_blocked_p): New functions.
(init_glyph_string): Stop setting window member of struct
glyph_string.
* src/w32fns.c (w32_frame_parm_handlers): Add placeholder for
x_set_inhibit_double_buffering.
* src/termhooks.h (struct terminal): Add
buffer_flipping_unblocked_hook.
* src/nsfns.m (ns_frame_parm_handlers): Add placeholder for
x_set_inhibit_double_buffering.
* src/image.c (x_create_bitmap_from_data)
(x_create_bitmap_from_file, x_create_x_image_and_pixmap)
(Create_Pixmap_From_Bitmap_Data)
(x_create_bitmap_from_xpm_data, xpm_load, gs_load): Use
FRAME_X_DRAWABLE instead of FRAME_X_WINDOW; rename local
variables appropriately.
* src/gtkutil.c: Include Xdbe.h.
(xg_get_widget_from_map): Forward declare.
(xg_clear_under_internal_border): Remove obsolete calls to
refresh scroll bars.
(xg_create_frame_widgets): Call initial_set_up_x_back_buffer.
(xg_free_frame_widgets): Call tear_down_x_back_buffer; reset
FRAME_X_DRAWABLE as well as FRAME_X_WINDOW and for the
same reason.
(xg_set_background_color): Set scroll bar background colors.
(xg_finish_scroll_bar_creation): New function with common
logic of xg_create_scroll_bar, xg_create_horizontal_scroll_bar. Force
scroll bars to be real X11 windows.
(xg_create_scroll_bar, xg_create_horizontal_scroll_bar): Call
xg_finish_scroll_bar_creation.
(xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos):
Remove obsolete calls to refresh scroll bars; fix comments.
* src/ftxfont.c (ftxfont_get_gcs, ftxfont_draw_bitmap,
(ftxfont_draw_background): Use FRAME_X_DRAWABLE instead of
FRAME_X_WINDOW.
* src/frame.c (frame_parms): Add table entry for new
`inhibit-double-buffering' frame parameter
(syms_of_frame): Register Qinhibit_double_buffering.
* src/font.h (struct font_driver): Add new `flush_frame_caches' hook.
(font_drop_xrender_surfaces): Declare.
* src/font.c (font_drop_xrender_surfaces): New function.
* src/Makefile.in (XDBE_LIBS, XDBE_CFLAGS): Substitute.
* etc/NEWS: Mention use of double buffering
* doc/lispref/frames.texi (Management Parameters): Document
`inhibit-double-buffering' frame parameters.
(Visibility of Frames): Document `x-double-buffered-p'.
* configure.ac: Check for the X double buffer extension
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.in | 6 | ||||
| -rw-r--r-- | src/dispextern.h | 5 | ||||
| -rw-r--r-- | src/font.c | 10 | ||||
| -rw-r--r-- | src/font.h | 11 | ||||
| -rw-r--r-- | src/frame.c | 2 | ||||
| -rw-r--r-- | src/ftxfont.c | 14 | ||||
| -rw-r--r-- | src/gtkutil.c | 167 | ||||
| -rw-r--r-- | src/image.c | 20 | ||||
| -rw-r--r-- | src/nsfns.m | 1 | ||||
| -rw-r--r-- | src/termhooks.h | 5 | ||||
| -rw-r--r-- | src/w32fns.c | 1 | ||||
| -rw-r--r-- | src/xdisp.c | 69 | ||||
| -rw-r--r-- | src/xfaces.c | 2 | ||||
| -rw-r--r-- | src/xfns.c | 128 | ||||
| -rw-r--r-- | src/xfont.c | 16 | ||||
| -rw-r--r-- | src/xftfont.c | 31 | ||||
| -rw-r--r-- | src/xterm.c | 288 | ||||
| -rw-r--r-- | src/xterm.h | 35 |
18 files changed, 595 insertions, 216 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 89f7a921faa..dc0bfff9b33 100644 --- a/src/Makefile.in +++ b/src/Makefile.in | |||
| @@ -254,6 +254,9 @@ XINERAMA_CFLAGS = @XINERAMA_CFLAGS@ | |||
| 254 | XFIXES_LIBS = @XFIXES_LIBS@ | 254 | XFIXES_LIBS = @XFIXES_LIBS@ |
| 255 | XFIXES_CFLAGS = @XFIXES_CFLAGS@ | 255 | XFIXES_CFLAGS = @XFIXES_CFLAGS@ |
| 256 | 256 | ||
| 257 | XDBE_LIBS = @XDBE_LIBS@ | ||
| 258 | XDBE_CFLAGS = @XDBE_CFLAGS@ | ||
| 259 | |||
| 257 | ## widget.o if USE_X_TOOLKIT, otherwise empty. | 260 | ## widget.o if USE_X_TOOLKIT, otherwise empty. |
| 258 | WIDGET_OBJ=@WIDGET_OBJ@ | 261 | WIDGET_OBJ=@WIDGET_OBJ@ |
| 259 | 262 | ||
| @@ -372,7 +375,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ | |||
| 372 | $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ | 375 | $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ |
| 373 | $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ | 376 | $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ |
| 374 | $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ | 377 | $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ |
| 375 | $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ | 378 | $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \ |
| 376 | $(WEBKIT_CFLAGS) \ | 379 | $(WEBKIT_CFLAGS) \ |
| 377 | $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ | 380 | $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ |
| 378 | $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ | 381 | $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ |
| @@ -489,6 +492,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ | |||
| 489 | $(WEBKIT_LIBS) \ | 492 | $(WEBKIT_LIBS) \ |
| 490 | $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ | 493 | $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ |
| 491 | $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ | 494 | $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ |
| 495 | $(XDBE_LIBS) \ | ||
| 492 | $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ | 496 | $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ |
| 493 | $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ | 497 | $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ |
| 494 | $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ | 498 | $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ |
diff --git a/src/dispextern.h b/src/dispextern.h index 79bc9353ec5..f27279975ac 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1276,7 +1276,6 @@ struct glyph_string | |||
| 1276 | 1276 | ||
| 1277 | /* X display and window for convenience. */ | 1277 | /* X display and window for convenience. */ |
| 1278 | Display *display; | 1278 | Display *display; |
| 1279 | Window window; | ||
| 1280 | 1279 | ||
| 1281 | /* The glyph row for which this string was built. It determines the | 1280 | /* The glyph row for which this string was built. It determines the |
| 1282 | y-origin and height of the string. */ | 1281 | y-origin and height of the string. */ |
| @@ -3357,6 +3356,10 @@ void x_cr_init_fringe (struct redisplay_interface *); | |||
| 3357 | 3356 | ||
| 3358 | extern unsigned row_hash (struct glyph_row *); | 3357 | extern unsigned row_hash (struct glyph_row *); |
| 3359 | 3358 | ||
| 3359 | extern void block_buffer_flips(void); | ||
| 3360 | extern void unblock_buffer_flips(void); | ||
| 3361 | extern bool buffer_flipping_blocked_p(void); | ||
| 3362 | |||
| 3360 | /* Defined in image.c */ | 3363 | /* Defined in image.c */ |
| 3361 | 3364 | ||
| 3362 | #ifdef HAVE_WINDOW_SYSTEM | 3365 | #ifdef HAVE_WINDOW_SYSTEM |
diff --git a/src/font.c b/src/font.c index f8e6794cbb1..ce632335256 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) | |||
| 5275 | } | 5275 | } |
| 5276 | 5276 | ||
| 5277 | void | 5277 | void |
| 5278 | font_drop_xrender_surfaces (struct frame *f) | ||
| 5279 | { | ||
| 5280 | struct font_driver_list *list; | ||
| 5281 | |||
| 5282 | for (list = f->font_driver_list; list; list = list->next) | ||
| 5283 | if (list->on && list->driver->drop_xrender_surfaces) | ||
| 5284 | list->driver->drop_xrender_surfaces (f); | ||
| 5285 | } | ||
| 5286 | |||
| 5287 | void | ||
| 5278 | syms_of_font (void) | 5288 | syms_of_font (void) |
| 5279 | { | 5289 | { |
| 5280 | sort_shift_bits[FONT_TYPE_INDEX] = 0; | 5290 | sort_shift_bits[FONT_TYPE_INDEX] = 0; |
diff --git a/src/font.h b/src/font.h index cf477290d06..c14823bc1eb 100644 --- a/src/font.h +++ b/src/font.h | |||
| @@ -763,6 +763,13 @@ struct font_driver | |||
| 763 | Return non-nil if the driver support rendering of combining | 763 | Return non-nil if the driver support rendering of combining |
| 764 | characters for FONT according to Unicode combining class. */ | 764 | characters for FONT according to Unicode combining class. */ |
| 765 | Lisp_Object (*combining_capability) (struct font *font); | 765 | Lisp_Object (*combining_capability) (struct font *font); |
| 766 | |||
| 767 | /* Optional | ||
| 768 | |||
| 769 | Called when frame F is double-buffered and its size changes; Xft | ||
| 770 | relies on this hook to throw away its old XftDraw (which won't | ||
| 771 | work after the size change) and get a new one. */ | ||
| 772 | void (*drop_xrender_surfaces) (struct frame *f); | ||
| 766 | }; | 773 | }; |
| 767 | 774 | ||
| 768 | 775 | ||
| @@ -862,7 +869,9 @@ extern void *font_get_frame_data (struct frame *f, Lisp_Object); | |||
| 862 | extern void font_filter_properties (Lisp_Object font, | 869 | extern void font_filter_properties (Lisp_Object font, |
| 863 | Lisp_Object alist, | 870 | Lisp_Object alist, |
| 864 | const char *const boolean_properties[], | 871 | const char *const boolean_properties[], |
| 865 | const char *const non_boolean_properties[]); | 872 | const char *const non_boolean_properties[]); |
| 873 | |||
| 874 | extern void font_drop_xrender_surfaces (struct frame *f); | ||
| 866 | 875 | ||
| 867 | #ifdef HAVE_FREETYPE | 876 | #ifdef HAVE_FREETYPE |
| 868 | extern struct font_driver ftfont_driver; | 877 | extern struct font_driver ftfont_driver; |
diff --git a/src/frame.c b/src/frame.c index f3a548cbce7..3a2d009d325 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -3128,6 +3128,7 @@ static const struct frame_parm_table frame_parms[] = | |||
| 3128 | {"alpha", SYMBOL_INDEX (Qalpha)}, | 3128 | {"alpha", SYMBOL_INDEX (Qalpha)}, |
| 3129 | {"sticky", SYMBOL_INDEX (Qsticky)}, | 3129 | {"sticky", SYMBOL_INDEX (Qsticky)}, |
| 3130 | {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)}, | 3130 | {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)}, |
| 3131 | {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)}, | ||
| 3131 | }; | 3132 | }; |
| 3132 | 3133 | ||
| 3133 | #ifdef HAVE_WINDOW_SYSTEM | 3134 | #ifdef HAVE_WINDOW_SYSTEM |
| @@ -5044,6 +5045,7 @@ syms_of_frame (void) | |||
| 5044 | DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars"); | 5045 | DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars"); |
| 5045 | DEFSYM (Qvisibility, "visibility"); | 5046 | DEFSYM (Qvisibility, "visibility"); |
| 5046 | DEFSYM (Qwait_for_wm, "wait-for-wm"); | 5047 | DEFSYM (Qwait_for_wm, "wait-for-wm"); |
| 5048 | DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering"); | ||
| 5047 | 5049 | ||
| 5048 | { | 5050 | { |
| 5049 | int i; | 5051 | int i; |
diff --git a/src/ftxfont.c b/src/ftxfont.c index f49d44ffc20..bfdeb4051b9 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 | |||
| 95 | if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color)) | 95 | if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color)) |
| 96 | break; | 96 | break; |
| 97 | xgcv.foreground = color.pixel; | 97 | xgcv.foreground = color.pixel; |
| 98 | new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 98 | new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 99 | GCForeground, &xgcv); | 99 | GCForeground, &xgcv); |
| 100 | } | 100 | } |
| 101 | unblock_input (); | 101 | unblock_input (); |
| @@ -139,14 +139,14 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font, | |||
| 139 | p[n[0]].y = y - bitmap.top + i; | 139 | p[n[0]].y = y - bitmap.top + i; |
| 140 | if (++n[0] == size) | 140 | if (++n[0] == size) |
| 141 | { | 141 | { |
| 142 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 142 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 143 | gc_fore, p, size, CoordModeOrigin); | 143 | gc_fore, p, size, CoordModeOrigin); |
| 144 | n[0] = 0; | 144 | n[0] = 0; |
| 145 | } | 145 | } |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | if (flush && n[0] > 0) | 148 | if (flush && n[0] > 0) |
| 149 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 149 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 150 | gc_fore, p, n[0], CoordModeOrigin); | 150 | gc_fore, p, n[0], CoordModeOrigin); |
| 151 | } | 151 | } |
| 152 | else | 152 | else |
| @@ -168,7 +168,7 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font, | |||
| 168 | pp[n[idx]].y = y - bitmap.top + i; | 168 | pp[n[idx]].y = y - bitmap.top + i; |
| 169 | if (++(n[idx]) == size) | 169 | if (++(n[idx]) == size) |
| 170 | { | 170 | { |
| 171 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 171 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 172 | idx == 6 ? gc_fore : gcs[idx], pp, size, | 172 | idx == 6 ? gc_fore : gcs[idx], pp, size, |
| 173 | CoordModeOrigin); | 173 | CoordModeOrigin); |
| 174 | n[idx] = 0; | 174 | n[idx] = 0; |
| @@ -180,10 +180,10 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font, | |||
| 180 | { | 180 | { |
| 181 | for (i = 0; i < 6; i++) | 181 | for (i = 0; i < 6; i++) |
| 182 | if (n[i] > 0) | 182 | if (n[i] > 0) |
| 183 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 183 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 184 | gcs[i], p + 0x100 * i, n[i], CoordModeOrigin); | 184 | gcs[i], p + 0x100 * i, n[i], CoordModeOrigin); |
| 185 | if (n[6] > 0) | 185 | if (n[6] > 0) |
| 186 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 186 | XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 187 | gc_fore, p + 0x600, n[6], CoordModeOrigin); | 187 | gc_fore, p + 0x600, n[6], CoordModeOrigin); |
| 188 | } | 188 | } |
| 189 | } | 189 | } |
| @@ -203,7 +203,7 @@ ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y | |||
| 203 | XGetGCValues (FRAME_X_DISPLAY (f), gc, | 203 | XGetGCValues (FRAME_X_DISPLAY (f), gc, |
| 204 | GCForeground | GCBackground, &xgcv); | 204 | GCForeground | GCBackground, &xgcv); |
| 205 | XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background); | 205 | XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background); |
| 206 | XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | 206 | XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc, |
| 207 | x, y - FONT_BASE (font), width, FONT_HEIGHT (font)); | 207 | x, y - FONT_BASE (font), width, FONT_HEIGHT (font)); |
| 208 | XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground); | 208 | XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground); |
| 209 | } | 209 | } |
diff --git a/src/gtkutil.c b/src/gtkutil.c index 88e6d30bd9a..986eca85587 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/>. */ | |||
| 48 | #include "emacsgtkfixed.h" | 48 | #include "emacsgtkfixed.h" |
| 49 | #endif | 49 | #endif |
| 50 | 50 | ||
| 51 | #ifdef HAVE_XDBE | ||
| 52 | #include <X11/extensions/Xdbe.h> | ||
| 53 | #endif | ||
| 54 | |||
| 51 | #ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW | 55 | #ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW |
| 52 | #define gtk_widget_set_has_window(w, b) \ | 56 | #define gtk_widget_set_has_window(w, b) \ |
| 53 | (gtk_fixed_set_has_window (GTK_FIXED (w), b)) | 57 | (gtk_fixed_set_has_window (GTK_FIXED (w), b)) |
| @@ -143,6 +147,8 @@ struct xg_frame_tb_info | |||
| 143 | GtkTextDirection dir; | 147 | GtkTextDirection dir; |
| 144 | }; | 148 | }; |
| 145 | 149 | ||
| 150 | static GtkWidget * xg_get_widget_from_map (ptrdiff_t idx); | ||
| 151 | |||
| 146 | 152 | ||
| 147 | /*********************************************************************** | 153 | /*********************************************************************** |
| 148 | Display handling functions | 154 | Display handling functions |
| @@ -815,12 +821,6 @@ xg_clear_under_internal_border (struct frame *f) | |||
| 815 | { | 821 | { |
| 816 | if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) | 822 | if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) |
| 817 | { | 823 | { |
| 818 | #ifndef USE_CAIRO | ||
| 819 | GtkWidget *wfixed = f->output_data.x->edit_widget; | ||
| 820 | |||
| 821 | gtk_widget_queue_draw (wfixed); | ||
| 822 | gdk_window_process_all_updates (); | ||
| 823 | #endif | ||
| 824 | x_clear_area (f, 0, 0, | 824 | x_clear_area (f, 0, 0, |
| 825 | FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); | 825 | FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); |
| 826 | 826 | ||
| @@ -1233,6 +1233,7 @@ xg_create_frame_widgets (struct frame *f) | |||
| 1233 | by callers of this function. */ | 1233 | by callers of this function. */ |
| 1234 | gtk_widget_realize (wfixed); | 1234 | gtk_widget_realize (wfixed); |
| 1235 | FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed); | 1235 | FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed); |
| 1236 | initial_set_up_x_back_buffer (f); | ||
| 1236 | 1237 | ||
| 1237 | /* Since GTK clears its window by filling with the background color, | 1238 | /* Since GTK clears its window by filling with the background color, |
| 1238 | we must keep X and GTK background in sync. */ | 1239 | we must keep X and GTK background in sync. */ |
| @@ -1296,8 +1297,11 @@ xg_free_frame_widgets (struct frame *f) | |||
| 1296 | if (tbinfo) | 1297 | if (tbinfo) |
| 1297 | xfree (tbinfo); | 1298 | xfree (tbinfo); |
| 1298 | 1299 | ||
| 1300 | /* x_free_frame_resources should have taken care of it */ | ||
| 1301 | eassert (!FRAME_X_DOUBLE_BUFFERED_P (f)); | ||
| 1299 | gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); | 1302 | gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); |
| 1300 | FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */ | 1303 | FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */ |
| 1304 | FRAME_X_RAW_DRAWABLE (f) = 0; | ||
| 1301 | FRAME_GTK_OUTER_WIDGET (f) = 0; | 1305 | FRAME_GTK_OUTER_WIDGET (f) = 0; |
| 1302 | #ifdef USE_GTK_TOOLTIP | 1306 | #ifdef USE_GTK_TOOLTIP |
| 1303 | if (x->ttip_lbl) | 1307 | if (x->ttip_lbl) |
| @@ -1440,6 +1444,18 @@ xg_set_background_color (struct frame *f, unsigned long bg) | |||
| 1440 | { | 1444 | { |
| 1441 | block_input (); | 1445 | block_input (); |
| 1442 | xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f)); | 1446 | xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f)); |
| 1447 | |||
| 1448 | Lisp_Object bar; | ||
| 1449 | for (bar = FRAME_SCROLL_BARS (f); | ||
| 1450 | !NILP (bar); | ||
| 1451 | bar = XSCROLL_BAR (bar)->next) | ||
| 1452 | { | ||
| 1453 | GtkWidget *scrollbar = | ||
| 1454 | xg_get_widget_from_map (XSCROLL_BAR (bar)->x_window); | ||
| 1455 | GtkWidget *webox = gtk_widget_get_parent (scrollbar); | ||
| 1456 | xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f)); | ||
| 1457 | } | ||
| 1458 | |||
| 1443 | unblock_input (); | 1459 | unblock_input (); |
| 1444 | } | 1460 | } |
| 1445 | } | 1461 | } |
| @@ -2265,7 +2281,6 @@ xg_mark_data (void) | |||
| 2265 | } | 2281 | } |
| 2266 | } | 2282 | } |
| 2267 | 2283 | ||
| 2268 | |||
| 2269 | /* Callback called when a menu item is destroyed. Used to free data. | 2284 | /* Callback called when a menu item is destroyed. Used to free data. |
| 2270 | W is the widget that is being destroyed (not used). | 2285 | W is the widget that is being destroyed (not used). |
| 2271 | CLIENT_DATA points to the xg_menu_item_cb_data associated with the W. */ | 2286 | CLIENT_DATA points to the xg_menu_item_cb_data associated with the W. */ |
| @@ -3569,44 +3584,23 @@ xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data) | |||
| 3569 | xg_remove_widget_from_map (id); | 3584 | xg_remove_widget_from_map (id); |
| 3570 | } | 3585 | } |
| 3571 | 3586 | ||
| 3572 | /* Create a scroll bar widget for frame F. Store the scroll bar | 3587 | static void |
| 3573 | in BAR. | 3588 | xg_finish_scroll_bar_creation (struct frame *f, |
| 3574 | SCROLL_CALLBACK is the callback to invoke when the value of the | 3589 | GtkWidget *wscroll, |
| 3575 | bar changes. | 3590 | struct scroll_bar *bar, |
| 3576 | END_CALLBACK is the callback to invoke when scrolling ends. | 3591 | GCallback scroll_callback, |
| 3577 | SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used | 3592 | GCallback end_callback, |
| 3578 | to set resources for the widget. */ | 3593 | const char *scroll_bar_name) |
| 3579 | |||
| 3580 | void | ||
| 3581 | xg_create_scroll_bar (struct frame *f, | ||
| 3582 | struct scroll_bar *bar, | ||
| 3583 | GCallback scroll_callback, | ||
| 3584 | GCallback end_callback, | ||
| 3585 | const char *scroll_bar_name) | ||
| 3586 | { | 3594 | { |
| 3587 | GtkWidget *wscroll; | 3595 | GtkWidget *webox = gtk_event_box_new (); |
| 3588 | GtkWidget *webox; | ||
| 3589 | intptr_t scroll_id; | ||
| 3590 | #ifdef HAVE_GTK3 | ||
| 3591 | GtkAdjustment *vadj; | ||
| 3592 | #else | ||
| 3593 | GtkObject *vadj; | ||
| 3594 | #endif | ||
| 3595 | 3596 | ||
| 3596 | /* Page, step increment values are not so important here, they | ||
| 3597 | will be corrected in x_set_toolkit_scroll_bar_thumb. */ | ||
| 3598 | vadj = gtk_adjustment_new (XG_SB_MIN, XG_SB_MIN, XG_SB_MAX, | ||
| 3599 | 0.1, 0.1, 0.1); | ||
| 3600 | |||
| 3601 | wscroll = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (vadj)); | ||
| 3602 | webox = gtk_event_box_new (); | ||
| 3603 | gtk_widget_set_name (wscroll, scroll_bar_name); | 3597 | gtk_widget_set_name (wscroll, scroll_bar_name); |
| 3604 | #ifndef HAVE_GTK3 | 3598 | #ifndef HAVE_GTK3 |
| 3605 | gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); | 3599 | gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); |
| 3606 | #endif | 3600 | #endif |
| 3607 | g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f); | 3601 | g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f); |
| 3608 | 3602 | ||
| 3609 | scroll_id = xg_store_widget_in_map (wscroll); | 3603 | ptrdiff_t scroll_id = xg_store_widget_in_map (wscroll); |
| 3610 | 3604 | ||
| 3611 | g_signal_connect (G_OBJECT (wscroll), | 3605 | g_signal_connect (G_OBJECT (wscroll), |
| 3612 | "destroy", | 3606 | "destroy", |
| @@ -3630,11 +3624,52 @@ xg_create_scroll_bar (struct frame *f, | |||
| 3630 | gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); | 3624 | gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); |
| 3631 | gtk_container_add (GTK_CONTAINER (webox), wscroll); | 3625 | gtk_container_add (GTK_CONTAINER (webox), wscroll); |
| 3632 | 3626 | ||
| 3627 | xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f)); | ||
| 3628 | |||
| 3629 | /* N.B. The event box doesn't become a real X11 window until we ask | ||
| 3630 | for its XID via GTK_WIDGET_TO_X_WIN. If the event box is not a | ||
| 3631 | real X window, it and its scroll-bar child try to draw on the | ||
| 3632 | Emacs main window, which we draw over using Xlib. */ | ||
| 3633 | gtk_widget_realize (webox); | ||
| 3634 | GTK_WIDGET_TO_X_WIN (webox); | ||
| 3633 | 3635 | ||
| 3634 | /* Set the cursor to an arrow. */ | 3636 | /* Set the cursor to an arrow. */ |
| 3635 | xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); | 3637 | xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); |
| 3636 | 3638 | ||
| 3637 | bar->x_window = scroll_id; | 3639 | bar->x_window = scroll_id; |
| 3640 | } | ||
| 3641 | |||
| 3642 | /* Create a scroll bar widget for frame F. Store the scroll bar | ||
| 3643 | in BAR. | ||
| 3644 | SCROLL_CALLBACK is the callback to invoke when the value of the | ||
| 3645 | bar changes. | ||
| 3646 | END_CALLBACK is the callback to invoke when scrolling ends. | ||
| 3647 | SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used | ||
| 3648 | to set resources for the widget. */ | ||
| 3649 | |||
| 3650 | void | ||
| 3651 | xg_create_scroll_bar (struct frame *f, | ||
| 3652 | struct scroll_bar *bar, | ||
| 3653 | GCallback scroll_callback, | ||
| 3654 | GCallback end_callback, | ||
| 3655 | const char *scroll_bar_name) | ||
| 3656 | { | ||
| 3657 | GtkWidget *wscroll; | ||
| 3658 | #ifdef HAVE_GTK3 | ||
| 3659 | GtkAdjustment *vadj; | ||
| 3660 | #else | ||
| 3661 | GtkObject *vadj; | ||
| 3662 | #endif | ||
| 3663 | |||
| 3664 | /* Page, step increment values are not so important here, they | ||
| 3665 | will be corrected in x_set_toolkit_scroll_bar_thumb. */ | ||
| 3666 | vadj = gtk_adjustment_new (XG_SB_MIN, XG_SB_MIN, XG_SB_MAX, | ||
| 3667 | 0.1, 0.1, 0.1); | ||
| 3668 | |||
| 3669 | wscroll = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (vadj)); | ||
| 3670 | |||
| 3671 | xg_finish_scroll_bar_creation (f, wscroll, bar, scroll_callback, | ||
| 3672 | end_callback, scroll_bar_name); | ||
| 3638 | bar->horizontal = 0; | 3673 | bar->horizontal = 0; |
| 3639 | } | 3674 | } |
| 3640 | 3675 | ||
| @@ -3652,8 +3687,6 @@ xg_create_horizontal_scroll_bar (struct frame *f, | |||
| 3652 | const char *scroll_bar_name) | 3687 | const char *scroll_bar_name) |
| 3653 | { | 3688 | { |
| 3654 | GtkWidget *wscroll; | 3689 | GtkWidget *wscroll; |
| 3655 | GtkWidget *webox; | ||
| 3656 | intptr_t scroll_id; | ||
| 3657 | #ifdef HAVE_GTK3 | 3690 | #ifdef HAVE_GTK3 |
| 3658 | GtkAdjustment *hadj; | 3691 | GtkAdjustment *hadj; |
| 3659 | #else | 3692 | #else |
| @@ -3666,42 +3699,9 @@ xg_create_horizontal_scroll_bar (struct frame *f, | |||
| 3666 | 0.1, 0.1, 0.1); | 3699 | 0.1, 0.1, 0.1); |
| 3667 | 3700 | ||
| 3668 | wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj)); | 3701 | wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj)); |
| 3669 | webox = gtk_event_box_new (); | ||
| 3670 | gtk_widget_set_name (wscroll, scroll_bar_name); | ||
| 3671 | #ifndef HAVE_GTK3 | ||
| 3672 | gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); | ||
| 3673 | #endif | ||
| 3674 | g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f); | ||
| 3675 | |||
| 3676 | scroll_id = xg_store_widget_in_map (wscroll); | ||
| 3677 | |||
| 3678 | g_signal_connect (G_OBJECT (wscroll), | ||
| 3679 | "destroy", | ||
| 3680 | G_CALLBACK (xg_gtk_scroll_destroy), | ||
| 3681 | (gpointer) scroll_id); | ||
| 3682 | g_signal_connect (G_OBJECT (wscroll), | ||
| 3683 | "change-value", | ||
| 3684 | scroll_callback, | ||
| 3685 | (gpointer) bar); | ||
| 3686 | g_signal_connect (G_OBJECT (wscroll), | ||
| 3687 | "button-release-event", | ||
| 3688 | end_callback, | ||
| 3689 | (gpointer) bar); | ||
| 3690 | |||
| 3691 | /* The scroll bar widget does not draw on a window of its own. Instead | ||
| 3692 | it draws on the parent window, in this case the edit widget. So | ||
| 3693 | whenever the edit widget is cleared, the scroll bar needs to redraw | ||
| 3694 | also, which causes flicker. Put an event box between the edit widget | ||
| 3695 | and the scroll bar, so the scroll bar instead draws itself on the | ||
| 3696 | event box window. */ | ||
| 3697 | gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); | ||
| 3698 | gtk_container_add (GTK_CONTAINER (webox), wscroll); | ||
| 3699 | 3702 | ||
| 3700 | 3703 | xg_finish_scroll_bar_creation (f, wscroll, bar, scroll_callback, | |
| 3701 | /* Set the cursor to an arrow. */ | 3704 | end_callback, scroll_bar_name); |
| 3702 | xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); | ||
| 3703 | |||
| 3704 | bar->x_window = scroll_id; | ||
| 3705 | bar->horizontal = 1; | 3705 | bar->horizontal = 1; |
| 3706 | } | 3706 | } |
| 3707 | 3707 | ||
| @@ -3770,16 +3770,10 @@ xg_update_scrollbar_pos (struct frame *f, | |||
| 3770 | gtk_widget_show_all (wparent); | 3770 | gtk_widget_show_all (wparent); |
| 3771 | gtk_widget_set_size_request (wscroll, width, height); | 3771 | gtk_widget_set_size_request (wscroll, width, height); |
| 3772 | } | 3772 | } |
| 3773 | #ifndef USE_CAIRO | ||
| 3774 | gtk_widget_queue_draw (wfixed); | ||
| 3775 | gdk_window_process_all_updates (); | ||
| 3776 | #endif | ||
| 3777 | if (oldx != -1 && oldw > 0 && oldh > 0) | 3773 | if (oldx != -1 && oldw > 0 && oldh > 0) |
| 3778 | { | 3774 | { |
| 3779 | /* Clear under old scroll bar position. This must be done after | 3775 | /* Clear under old scroll bar position. */ |
| 3780 | the gtk_widget_queue_draw and gdk_window_process_all_updates | 3776 | oldw += (scale - 1) * oldw; |
| 3781 | above. */ | ||
| 3782 | oldw += (scale - 1) * oldw; | ||
| 3783 | oldx -= (scale - 1) * oldw; | 3777 | oldx -= (scale - 1) * oldw; |
| 3784 | x_clear_area (f, oldx, oldy, oldw, oldh); | 3778 | x_clear_area (f, oldx, oldy, oldw, oldh); |
| 3785 | } | 3779 | } |
| @@ -3841,14 +3835,9 @@ xg_update_horizontal_scrollbar_pos (struct frame *f, | |||
| 3841 | gtk_widget_show_all (wparent); | 3835 | gtk_widget_show_all (wparent); |
| 3842 | gtk_widget_set_size_request (wscroll, width, height); | 3836 | gtk_widget_set_size_request (wscroll, width, height); |
| 3843 | } | 3837 | } |
| 3844 | gtk_widget_queue_draw (wfixed); | ||
| 3845 | gdk_window_process_all_updates (); | ||
| 3846 | if (oldx != -1 && oldw > 0 && oldh > 0) | 3838 | if (oldx != -1 && oldw > 0 && oldh > 0) |
| 3847 | /* Clear under old scroll bar position. This must be done after | 3839 | /* Clear under old scroll bar position. */ |
| 3848 | the gtk_widget_queue_draw and gdk_window_process_all_updates | 3840 | x_clear_area (f, oldx, oldy, oldw, oldh); |
| 3849 | above. */ | ||
| 3850 | x_clear_area (f, | ||
| 3851 | oldx, oldy, oldw, oldh); | ||
| 3852 | 3841 | ||
| 3853 | /* GTK does not redraw until the main loop is entered again, but | 3842 | /* GTK does not redraw until the main loop is entered again, but |
| 3854 | if there are no X events pending we will not enter it. So we sync | 3843 | if there are no X events pending we will not enter it. So we sync |
diff --git a/src/image.c b/src/image.c index 9bd245585c6..1303a931263 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 | |||
| 220 | 220 | ||
| 221 | #ifdef HAVE_X_WINDOWS | 221 | #ifdef HAVE_X_WINDOWS |
| 222 | Pixmap bitmap; | 222 | Pixmap bitmap; |
| 223 | bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 223 | bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 224 | bits, width, height); | 224 | bits, width, height); |
| 225 | if (! bitmap) | 225 | if (! bitmap) |
| 226 | return -1; | 226 | return -1; |
| @@ -327,7 +327,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 327 | 327 | ||
| 328 | filename = SSDATA (found); | 328 | filename = SSDATA (found); |
| 329 | 329 | ||
| 330 | result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 330 | result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 331 | filename, &width, &height, &bitmap, &xhot, &yhot); | 331 | filename, &width, &height, &bitmap, &xhot, &yhot); |
| 332 | if (result != BitmapSuccess) | 332 | if (result != BitmapSuccess) |
| 333 | return -1; | 333 | return -1; |
| @@ -1952,7 +1952,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | |||
| 1952 | { | 1952 | { |
| 1953 | #ifdef HAVE_X_WINDOWS | 1953 | #ifdef HAVE_X_WINDOWS |
| 1954 | Display *display = FRAME_X_DISPLAY (f); | 1954 | Display *display = FRAME_X_DISPLAY (f); |
| 1955 | Window window = FRAME_X_WINDOW (f); | 1955 | Drawable drawable = FRAME_X_DRAWABLE (f); |
| 1956 | Screen *screen = FRAME_X_SCREEN (f); | 1956 | Screen *screen = FRAME_X_SCREEN (f); |
| 1957 | 1957 | ||
| 1958 | eassert (input_blocked_p ()); | 1958 | eassert (input_blocked_p ()); |
| @@ -1981,7 +1981,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | |||
| 1981 | (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height); | 1981 | (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height); |
| 1982 | 1982 | ||
| 1983 | /* Allocate a pixmap of the same size. */ | 1983 | /* Allocate a pixmap of the same size. */ |
| 1984 | *pixmap = XCreatePixmap (display, window, width, height, depth); | 1984 | *pixmap = XCreatePixmap (display, drawable, width, height, depth); |
| 1985 | if (*pixmap == NO_PIXMAP) | 1985 | if (*pixmap == NO_PIXMAP) |
| 1986 | { | 1986 | { |
| 1987 | x_destroy_x_image (*ximg); | 1987 | x_destroy_x_image (*ximg); |
| @@ -2742,7 +2742,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data, | |||
| 2742 | img->pixmap = | 2742 | img->pixmap = |
| 2743 | (x_check_image_size (0, img->width, img->height) | 2743 | (x_check_image_size (0, img->width, img->height) |
| 2744 | ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), | 2744 | ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), |
| 2745 | FRAME_X_WINDOW (f), | 2745 | FRAME_X_DRAWABLE (f), |
| 2746 | data, | 2746 | data, |
| 2747 | img->width, img->height, | 2747 | img->width, img->height, |
| 2748 | fg, bg, | 2748 | fg, bg, |
| @@ -3520,7 +3520,7 @@ x_create_bitmap_from_xpm_data (struct frame *f, const char **bits) | |||
| 3520 | xpm_init_color_cache (f, &attrs); | 3520 | xpm_init_color_cache (f, &attrs); |
| 3521 | #endif | 3521 | #endif |
| 3522 | 3522 | ||
| 3523 | rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 3523 | rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 3524 | (char **) bits, &bitmap, &mask, &attrs); | 3524 | (char **) bits, &bitmap, &mask, &attrs); |
| 3525 | if (rc != XpmSuccess) | 3525 | if (rc != XpmSuccess) |
| 3526 | { | 3526 | { |
| @@ -3758,7 +3758,7 @@ xpm_load (struct frame *f, struct image *img) | |||
| 3758 | #ifdef HAVE_X_WINDOWS | 3758 | #ifdef HAVE_X_WINDOWS |
| 3759 | if (rc == XpmSuccess) | 3759 | if (rc == XpmSuccess) |
| 3760 | { | 3760 | { |
| 3761 | img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 3761 | img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 3762 | img->ximg->width, img->ximg->height, | 3762 | img->ximg->width, img->ximg->height, |
| 3763 | img->ximg->depth); | 3763 | img->ximg->depth); |
| 3764 | if (img->pixmap == NO_PIXMAP) | 3764 | if (img->pixmap == NO_PIXMAP) |
| @@ -3768,7 +3768,7 @@ xpm_load (struct frame *f, struct image *img) | |||
| 3768 | } | 3768 | } |
| 3769 | else if (img->mask_img) | 3769 | else if (img->mask_img) |
| 3770 | { | 3770 | { |
| 3771 | img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 3771 | img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 3772 | img->mask_img->width, | 3772 | img->mask_img->width, |
| 3773 | img->mask_img->height, | 3773 | img->mask_img->height, |
| 3774 | img->mask_img->depth); | 3774 | img->mask_img->depth); |
| @@ -9541,7 +9541,7 @@ gs_load (struct frame *f, struct image *img) | |||
| 9541 | { | 9541 | { |
| 9542 | /* Only W32 version did BLOCK_INPUT here. ++kfs */ | 9542 | /* Only W32 version did BLOCK_INPUT here. ++kfs */ |
| 9543 | block_input (); | 9543 | block_input (); |
| 9544 | img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 9544 | img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 9545 | img->width, img->height, | 9545 | img->width, img->height, |
| 9546 | DefaultDepthOfScreen (FRAME_X_SCREEN (f))); | 9546 | DefaultDepthOfScreen (FRAME_X_SCREEN (f))); |
| 9547 | unblock_input (); | 9547 | unblock_input (); |
| @@ -9557,7 +9557,7 @@ gs_load (struct frame *f, struct image *img) | |||
| 9557 | if successful. We do not record_unwind_protect here because | 9557 | if successful. We do not record_unwind_protect here because |
| 9558 | other places in redisplay like calling window scroll functions | 9558 | other places in redisplay like calling window scroll functions |
| 9559 | don't either. Let the Lisp loader use `unwind-protect' instead. */ | 9559 | don't either. Let the Lisp loader use `unwind-protect' instead. */ |
| 9560 | printnum1 = FRAME_X_WINDOW (f); | 9560 | printnum1 = FRAME_X_DRAWABLE (f); |
| 9561 | printnum2 = img->pixmap; | 9561 | printnum2 = img->pixmap; |
| 9562 | window_and_pixmap_id | 9562 | window_and_pixmap_id |
| 9563 | = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2); | 9563 | = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2); |
diff --git a/src/nsfns.m b/src/nsfns.m index ce2622c8062..b8264608b34 100644 --- a/src/nsfns.m +++ b/src/nsfns.m | |||
| @@ -971,6 +971,7 @@ frame_parm_handler ns_frame_parm_handlers[] = | |||
| 971 | x_set_alpha, | 971 | x_set_alpha, |
| 972 | 0, /* x_set_sticky */ | 972 | 0, /* x_set_sticky */ |
| 973 | 0, /* x_set_tool_bar_position */ | 973 | 0, /* x_set_tool_bar_position */ |
| 974 | 0, /* x_set_inhibit_double_buffering */ | ||
| 974 | }; | 975 | }; |
| 975 | 976 | ||
| 976 | 977 | ||
diff --git a/src/termhooks.h b/src/termhooks.h index ff74d99b7c1..03416cb8842 100644 --- a/src/termhooks.h +++ b/src/termhooks.h | |||
| @@ -631,6 +631,11 @@ struct terminal | |||
| 631 | /* Called when a frame's display becomes entirely up to date. */ | 631 | /* Called when a frame's display becomes entirely up to date. */ |
| 632 | void (*frame_up_to_date_hook) (struct frame *); | 632 | void (*frame_up_to_date_hook) (struct frame *); |
| 633 | 633 | ||
| 634 | /* Called when buffer flipping becomes unblocked after having | ||
| 635 | previously been blocked. Redisplay always blocks buffer flips | ||
| 636 | while it runs. */ | ||
| 637 | void (*buffer_flipping_unblocked_hook) (struct frame *); | ||
| 638 | |||
| 634 | 639 | ||
| 635 | /* Called to delete the device-specific portions of a frame that is | 640 | /* Called to delete the device-specific portions of a frame that is |
| 636 | on this terminal device. */ | 641 | on this terminal device. */ |
diff --git a/src/w32fns.c b/src/w32fns.c index 2b07bb20e42..1d83b02d629 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -9757,6 +9757,7 @@ frame_parm_handler w32_frame_parm_handlers[] = | |||
| 9757 | x_set_alpha, | 9757 | x_set_alpha, |
| 9758 | 0, /* x_set_sticky */ | 9758 | 0, /* x_set_sticky */ |
| 9759 | 0, /* x_set_tool_bar_position */ | 9759 | 0, /* x_set_tool_bar_position */ |
| 9760 | 0, /* x_set_inhibit_double_buffering */ | ||
| 9760 | }; | 9761 | }; |
| 9761 | 9762 | ||
| 9762 | void | 9763 | void |
diff --git a/src/xdisp.c b/src/xdisp.c index 1a27c4c3c96..6e8af8aaf0a 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) | |||
| 2501 | 2501 | ||
| 2502 | /* Visible feedback for debugging. */ | 2502 | /* Visible feedback for debugging. */ |
| 2503 | #if false && defined HAVE_X_WINDOWS | 2503 | #if false && defined HAVE_X_WINDOWS |
| 2504 | XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 2504 | XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 2505 | f->output_data.x->normal_gc, | 2505 | f->output_data.x->normal_gc, |
| 2506 | gx, gy, width, height); | 2506 | gx, gy, width, height); |
| 2507 | #endif | 2507 | #endif |
| @@ -11349,7 +11349,7 @@ clear_garbaged_frames (void) | |||
| 11349 | fset_redisplay (f); | 11349 | fset_redisplay (f); |
| 11350 | f->garbaged = false; | 11350 | f->garbaged = false; |
| 11351 | f->resized_p = false; | 11351 | f->resized_p = false; |
| 11352 | } | 11352 | } |
| 11353 | } | 11353 | } |
| 11354 | 11354 | ||
| 11355 | frame_garbaged = false; | 11355 | frame_garbaged = false; |
| @@ -13573,6 +13573,7 @@ redisplay_internal (void) | |||
| 13573 | count = SPECPDL_INDEX (); | 13573 | count = SPECPDL_INDEX (); |
| 13574 | record_unwind_protect_void (unwind_redisplay); | 13574 | record_unwind_protect_void (unwind_redisplay); |
| 13575 | redisplaying_p = true; | 13575 | redisplaying_p = true; |
| 13576 | block_buffer_flips (); | ||
| 13576 | specbind (Qinhibit_free_realized_faces, Qnil); | 13577 | specbind (Qinhibit_free_realized_faces, Qnil); |
| 13577 | 13578 | ||
| 13578 | /* Record this function, so it appears on the profiler's backtraces. */ | 13579 | /* Record this function, so it appears on the profiler's backtraces. */ |
| @@ -14070,7 +14071,23 @@ redisplay_internal (void) | |||
| 14070 | use them in update_frame will segfault. | 14071 | use them in update_frame will segfault. |
| 14071 | Therefore, we must redisplay this frame. */ | 14072 | Therefore, we must redisplay this frame. */ |
| 14072 | if (!f_redisplay_flag && f->redisplay) | 14073 | if (!f_redisplay_flag && f->redisplay) |
| 14073 | goto retry_frame; | 14074 | goto retry_frame; |
| 14075 | |||
| 14076 | /* In some case (e.g., window resize), we notice | ||
| 14077 | only during window updating that the window | ||
| 14078 | content changed unpredictably (e.g., a GTK | ||
| 14079 | scrollbar moved) and that our previous estimation | ||
| 14080 | of the frame content was garbage. We have to | ||
| 14081 | start over. These cases should be rare, so going | ||
| 14082 | all the way back to the top of redisplay should | ||
| 14083 | be good enough. | ||
| 14084 | |||
| 14085 | Why FRAME_WINDOW_P? See | ||
| 14086 | https://lists.gnu.org/archive/html/emacs-devel/2016-10/msg00957.html | ||
| 14087 | |||
| 14088 | */ | ||
| 14089 | if (FRAME_GARBAGED_P (f) && FRAME_WINDOW_P (f)) | ||
| 14090 | goto retry; | ||
| 14074 | 14091 | ||
| 14075 | /* Prevent various kinds of signals during display | 14092 | /* Prevent various kinds of signals during display |
| 14076 | update. stdio is not robust about handling | 14093 | update. stdio is not robust about handling |
| @@ -14297,6 +14314,11 @@ redisplay_internal (void) | |||
| 14297 | RESUME_POLLING; | 14314 | RESUME_POLLING; |
| 14298 | } | 14315 | } |
| 14299 | 14316 | ||
| 14317 | static void | ||
| 14318 | unwind_redisplay_preserve_echo_area (void) | ||
| 14319 | { | ||
| 14320 | unblock_buffer_flips (); | ||
| 14321 | } | ||
| 14300 | 14322 | ||
| 14301 | /* Redisplay, but leave alone any recent echo area message unless | 14323 | /* Redisplay, but leave alone any recent echo area message unless |
| 14302 | another message has been requested in its place. | 14324 | another message has been requested in its place. |
| @@ -14314,6 +14336,12 @@ redisplay_preserve_echo_area (int from_where) | |||
| 14314 | { | 14336 | { |
| 14315 | TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where)); | 14337 | TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where)); |
| 14316 | 14338 | ||
| 14339 | block_input (); | ||
| 14340 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 14341 | record_unwind_protect_void (unwind_redisplay_preserve_echo_area); | ||
| 14342 | block_buffer_flips (); | ||
| 14343 | unblock_input (); | ||
| 14344 | |||
| 14317 | if (!NILP (echo_area_buffer[1])) | 14345 | if (!NILP (echo_area_buffer[1])) |
| 14318 | { | 14346 | { |
| 14319 | /* We have a previously displayed message, but no current | 14347 | /* We have a previously displayed message, but no current |
| @@ -14326,6 +14354,7 @@ redisplay_preserve_echo_area (int from_where) | |||
| 14326 | redisplay_internal (); | 14354 | redisplay_internal (); |
| 14327 | 14355 | ||
| 14328 | flush_frame (SELECTED_FRAME ()); | 14356 | flush_frame (SELECTED_FRAME ()); |
| 14357 | unbind_to (count, Qnil); | ||
| 14329 | } | 14358 | } |
| 14330 | 14359 | ||
| 14331 | 14360 | ||
| @@ -14335,6 +14364,7 @@ static void | |||
| 14335 | unwind_redisplay (void) | 14364 | unwind_redisplay (void) |
| 14336 | { | 14365 | { |
| 14337 | redisplaying_p = false; | 14366 | redisplaying_p = false; |
| 14367 | unblock_buffer_flips (); | ||
| 14338 | } | 14368 | } |
| 14339 | 14369 | ||
| 14340 | 14370 | ||
| @@ -14444,6 +14474,38 @@ disp_char_vector (struct Lisp_Char_Table *dp, int c) | |||
| 14444 | return val; | 14474 | return val; |
| 14445 | } | 14475 | } |
| 14446 | 14476 | ||
| 14477 | static int buffer_flip_blocked_depth; | ||
| 14478 | |||
| 14479 | void | ||
| 14480 | block_buffer_flips(void) | ||
| 14481 | { | ||
| 14482 | eassert (buffer_flip_blocked_depth >= 0); | ||
| 14483 | buffer_flip_blocked_depth++; | ||
| 14484 | } | ||
| 14485 | |||
| 14486 | void | ||
| 14487 | unblock_buffer_flips(void) | ||
| 14488 | { | ||
| 14489 | eassert (buffer_flip_blocked_depth > 0); | ||
| 14490 | if (--buffer_flip_blocked_depth == 0) | ||
| 14491 | { | ||
| 14492 | Lisp_Object tail, frame; | ||
| 14493 | block_input (); | ||
| 14494 | FOR_EACH_FRAME (tail, frame) | ||
| 14495 | { | ||
| 14496 | struct frame *f = XFRAME (frame); | ||
| 14497 | if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) | ||
| 14498 | (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f); | ||
| 14499 | } | ||
| 14500 | unblock_input (); | ||
| 14501 | } | ||
| 14502 | } | ||
| 14503 | |||
| 14504 | bool | ||
| 14505 | buffer_flipping_blocked_p (void) | ||
| 14506 | { | ||
| 14507 | return buffer_flip_blocked_depth > 0; | ||
| 14508 | } | ||
| 14447 | 14509 | ||
| 14448 | 14510 | ||
| 14449 | /*********************************************************************** | 14511 | /*********************************************************************** |
| @@ -24626,7 +24688,6 @@ init_glyph_string (struct glyph_string *s, | |||
| 24626 | s->hdc = hdc; | 24688 | s->hdc = hdc; |
| 24627 | #endif | 24689 | #endif |
| 24628 | s->display = FRAME_X_DISPLAY (s->f); | 24690 | s->display = FRAME_X_DISPLAY (s->f); |
| 24629 | s->window = FRAME_X_WINDOW (s->f); | ||
| 24630 | s->char2b = char2b; | 24691 | s->char2b = char2b; |
| 24631 | s->hl = hl; | 24692 | s->hl = hl; |
| 24632 | s->row = row; | 24693 | s->row = row; |
diff --git a/src/xfaces.c b/src/xfaces.c index 5837f35d7b6..accb98bf4c7 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -495,7 +495,7 @@ x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv) | |||
| 495 | { | 495 | { |
| 496 | GC gc; | 496 | GC gc; |
| 497 | block_input (); | 497 | block_input (); |
| 498 | gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgcv); | 498 | gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), mask, xgcv); |
| 499 | unblock_input (); | 499 | unblock_input (); |
| 500 | IF_DEBUG (++ngcs); | 500 | IF_DEBUG (++ngcs); |
| 501 | return gc; | 501 | return gc; |
diff --git a/src/xfns.c b/src/xfns.c index 8571d0e20ab..3438c8ef5b4 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/>. */ | |||
| 53 | #include "gtkutil.h" | 53 | #include "gtkutil.h" |
| 54 | #endif | 54 | #endif |
| 55 | 55 | ||
| 56 | #ifdef HAVE_XDBE | ||
| 57 | #include <X11/extensions/Xdbe.h> | ||
| 58 | #endif | ||
| 59 | |||
| 56 | #ifdef USE_X_TOOLKIT | 60 | #ifdef USE_X_TOOLKIT |
| 57 | #include <X11/Shell.h> | 61 | #include <X11/Shell.h> |
| 58 | 62 | ||
| @@ -114,6 +118,7 @@ static int dpyinfo_refcount; | |||
| 114 | #endif | 118 | #endif |
| 115 | 119 | ||
| 116 | static struct x_display_info *x_display_info_for_name (Lisp_Object); | 120 | static struct x_display_info *x_display_info_for_name (Lisp_Object); |
| 121 | static void set_up_x_back_buffer (struct frame *f); | ||
| 117 | 122 | ||
| 118 | /* Let the user specify an X display with a Lisp object. | 123 | /* Let the user specify an X display with a Lisp object. |
| 119 | OBJECT may be nil, a frame or a terminal object. | 124 | OBJECT may be nil, a frame or a terminal object. |
| @@ -701,6 +706,35 @@ x_set_tool_bar_position (struct frame *f, | |||
| 701 | wrong_choice (choice, new_value); | 706 | wrong_choice (choice, new_value); |
| 702 | } | 707 | } |
| 703 | 708 | ||
| 709 | static void | ||
| 710 | x_set_inhibit_double_buffering (struct frame *f, | ||
| 711 | Lisp_Object new_value, | ||
| 712 | Lisp_Object old_value) | ||
| 713 | { | ||
| 714 | block_input (); | ||
| 715 | if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value)) | ||
| 716 | { | ||
| 717 | bool want_double_buffering = NILP (new_value); | ||
| 718 | bool was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f); | ||
| 719 | /* font_drop_xrender_surfaces in xftfont does something only if | ||
| 720 | we're double-buffered, so call font_drop_xrender_surfaces before | ||
| 721 | and after any potential change. One of the calls will end up | ||
| 722 | being a no-op. */ | ||
| 723 | if (want_double_buffering != was_double_buffered) | ||
| 724 | font_drop_xrender_surfaces (f); | ||
| 725 | if (FRAME_X_DOUBLE_BUFFERED_P (f) && !want_double_buffering) | ||
| 726 | tear_down_x_back_buffer (f); | ||
| 727 | else if (!FRAME_X_DOUBLE_BUFFERED_P (f) && want_double_buffering) | ||
| 728 | set_up_x_back_buffer (f); | ||
| 729 | if (FRAME_X_DOUBLE_BUFFERED_P (f) != was_double_buffered) | ||
| 730 | { | ||
| 731 | SET_FRAME_GARBAGED (f); | ||
| 732 | font_drop_xrender_surfaces (f); | ||
| 733 | } | ||
| 734 | } | ||
| 735 | unblock_input (); | ||
| 736 | } | ||
| 737 | |||
| 704 | #ifdef USE_GTK | 738 | #ifdef USE_GTK |
| 705 | 739 | ||
| 706 | /* Set icon from FILE for frame F. By using GTK functions the icon | 740 | /* Set icon from FILE for frame F. By using GTK functions the icon |
| @@ -2483,6 +2517,72 @@ xic_set_xfontset (struct frame *f, const char *base_fontname) | |||
| 2483 | 2517 | ||
| 2484 | 2518 | ||
| 2485 | 2519 | ||
| 2520 | |||
| 2521 | void | ||
| 2522 | x_mark_frame_dirty (struct frame *f) | ||
| 2523 | { | ||
| 2524 | if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f)) | ||
| 2525 | FRAME_X_NEED_BUFFER_FLIP (f) = true; | ||
| 2526 | } | ||
| 2527 | |||
| 2528 | static void | ||
| 2529 | set_up_x_back_buffer (struct frame *f) | ||
| 2530 | { | ||
| 2531 | #ifdef HAVE_XDBE | ||
| 2532 | block_input (); | ||
| 2533 | if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f)) | ||
| 2534 | { | ||
| 2535 | FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f); | ||
| 2536 | if (FRAME_DISPLAY_INFO (f)->supports_xdbe) | ||
| 2537 | { | ||
| 2538 | /* If allocating a back buffer fails, either because the | ||
| 2539 | server ran out of memory or we don't have the right kind | ||
| 2540 | of visual, just use single-buffered rendering. */ | ||
| 2541 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 2542 | FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName ( | ||
| 2543 | FRAME_X_DISPLAY (f), | ||
| 2544 | FRAME_X_WINDOW (f), | ||
| 2545 | XdbeCopied); | ||
| 2546 | if (x_had_errors_p (FRAME_X_DISPLAY (f))) | ||
| 2547 | FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f); | ||
| 2548 | x_uncatch_errors_after_check (); | ||
| 2549 | } | ||
| 2550 | } | ||
| 2551 | unblock_input (); | ||
| 2552 | #endif | ||
| 2553 | } | ||
| 2554 | |||
| 2555 | void | ||
| 2556 | tear_down_x_back_buffer (struct frame *f) | ||
| 2557 | { | ||
| 2558 | #ifdef HAVE_XDBE | ||
| 2559 | block_input (); | ||
| 2560 | if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f)) | ||
| 2561 | { | ||
| 2562 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) | ||
| 2563 | { | ||
| 2564 | XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f), | ||
| 2565 | FRAME_X_DRAWABLE (f)); | ||
| 2566 | FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f); | ||
| 2567 | } | ||
| 2568 | } | ||
| 2569 | unblock_input (); | ||
| 2570 | #endif | ||
| 2571 | } | ||
| 2572 | |||
| 2573 | /* Set up double buffering if the frame parameters don't prohibit | ||
| 2574 | it. */ | ||
| 2575 | void | ||
| 2576 | initial_set_up_x_back_buffer (struct frame *f) | ||
| 2577 | { | ||
| 2578 | block_input (); | ||
| 2579 | eassert (FRAME_X_WINDOW (f)); | ||
| 2580 | FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f); | ||
| 2581 | if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist)))) | ||
| 2582 | set_up_x_back_buffer (f); | ||
| 2583 | unblock_input (); | ||
| 2584 | } | ||
| 2585 | |||
| 2486 | #ifdef USE_X_TOOLKIT | 2586 | #ifdef USE_X_TOOLKIT |
| 2487 | 2587 | ||
| 2488 | /* Create and set up the X widget for frame F. */ | 2588 | /* Create and set up the X widget for frame F. */ |
| @@ -2638,7 +2738,7 @@ x_window (struct frame *f, long window_prompting) | |||
| 2638 | f->output_data.x->parent_desc, 0, 0); | 2738 | f->output_data.x->parent_desc, 0, 0); |
| 2639 | 2739 | ||
| 2640 | FRAME_X_WINDOW (f) = XtWindow (frame_widget); | 2740 | FRAME_X_WINDOW (f) = XtWindow (frame_widget); |
| 2641 | 2741 | initial_set_up_x_back_buffer (f); | |
| 2642 | validate_x_resource_name (); | 2742 | validate_x_resource_name (); |
| 2643 | 2743 | ||
| 2644 | class_hints.res_name = SSDATA (Vx_resource_name); | 2744 | class_hints.res_name = SSDATA (Vx_resource_name); |
| @@ -2784,7 +2884,8 @@ x_window (struct frame *f) | |||
| 2784 | CopyFromParent, /* depth */ | 2884 | CopyFromParent, /* depth */ |
| 2785 | InputOutput, /* class */ | 2885 | InputOutput, /* class */ |
| 2786 | FRAME_X_VISUAL (f), | 2886 | FRAME_X_VISUAL (f), |
| 2787 | attribute_mask, &attributes); | 2887 | attribute_mask, &attributes); |
| 2888 | initial_set_up_x_back_buffer (f); | ||
| 2788 | 2889 | ||
| 2789 | #ifdef HAVE_X_I18N | 2890 | #ifdef HAVE_X_I18N |
| 2790 | if (use_xim) | 2891 | if (use_xim) |
| @@ -2938,7 +3039,7 @@ x_make_gc (struct frame *f) | |||
| 2938 | gc_values.line_width = 0; /* Means 1 using fast algorithm. */ | 3039 | gc_values.line_width = 0; /* Means 1 using fast algorithm. */ |
| 2939 | f->output_data.x->normal_gc | 3040 | f->output_data.x->normal_gc |
| 2940 | = XCreateGC (FRAME_X_DISPLAY (f), | 3041 | = XCreateGC (FRAME_X_DISPLAY (f), |
| 2941 | FRAME_X_WINDOW (f), | 3042 | FRAME_X_DRAWABLE (f), |
| 2942 | GCLineWidth | GCForeground | GCBackground, | 3043 | GCLineWidth | GCForeground | GCBackground, |
| 2943 | &gc_values); | 3044 | &gc_values); |
| 2944 | 3045 | ||
| @@ -2947,7 +3048,7 @@ x_make_gc (struct frame *f) | |||
| 2947 | gc_values.background = FRAME_FOREGROUND_PIXEL (f); | 3048 | gc_values.background = FRAME_FOREGROUND_PIXEL (f); |
| 2948 | f->output_data.x->reverse_gc | 3049 | f->output_data.x->reverse_gc |
| 2949 | = XCreateGC (FRAME_X_DISPLAY (f), | 3050 | = XCreateGC (FRAME_X_DISPLAY (f), |
| 2950 | FRAME_X_WINDOW (f), | 3051 | FRAME_X_DRAWABLE (f), |
| 2951 | GCForeground | GCBackground | GCLineWidth, | 3052 | GCForeground | GCBackground | GCLineWidth, |
| 2952 | &gc_values); | 3053 | &gc_values); |
| 2953 | 3054 | ||
| @@ -2956,7 +3057,7 @@ x_make_gc (struct frame *f) | |||
| 2956 | gc_values.background = f->output_data.x->cursor_pixel; | 3057 | gc_values.background = f->output_data.x->cursor_pixel; |
| 2957 | gc_values.fill_style = FillOpaqueStippled; | 3058 | gc_values.fill_style = FillOpaqueStippled; |
| 2958 | f->output_data.x->cursor_gc | 3059 | f->output_data.x->cursor_gc |
| 2959 | = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 3060 | = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 2960 | (GCForeground | GCBackground | 3061 | (GCForeground | GCBackground |
| 2961 | | GCFillStyle | GCLineWidth), | 3062 | | GCFillStyle | GCLineWidth), |
| 2962 | &gc_values); | 3063 | &gc_values); |
| @@ -3463,6 +3564,9 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 3463 | "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); | 3564 | "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); |
| 3464 | x_default_parameter (f, parms, Qtool_bar_position, | 3565 | x_default_parameter (f, parms, Qtool_bar_position, |
| 3465 | FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); | 3566 | FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); |
| 3567 | x_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, | ||
| 3568 | "inhibitDoubleBuffering", "InhibitDoubleBuffering", | ||
| 3569 | RES_TYPE_BOOLEAN); | ||
| 3466 | 3570 | ||
| 3467 | /* Compute the size of the X window. */ | 3571 | /* Compute the size of the X window. */ |
| 3468 | window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height); | 3572 | window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height); |
| @@ -5636,7 +5740,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) | |||
| 5636 | /* Border. */ | 5740 | /* Border. */ |
| 5637 | f->border_width, | 5741 | f->border_width, |
| 5638 | CopyFromParent, InputOutput, CopyFromParent, | 5742 | CopyFromParent, InputOutput, CopyFromParent, |
| 5639 | mask, &attrs); | 5743 | mask, &attrs); |
| 5744 | initial_set_up_x_back_buffer (f); | ||
| 5640 | XChangeProperty (FRAME_X_DISPLAY (f), tip_window, | 5745 | XChangeProperty (FRAME_X_DISPLAY (f), tip_window, |
| 5641 | FRAME_DISPLAY_INFO (f)->Xatom_net_window_type, | 5746 | FRAME_DISPLAY_INFO (f)->Xatom_net_window_type, |
| 5642 | XA_ATOM, 32, PropModeReplace, | 5747 | XA_ATOM, 32, PropModeReplace, |
| @@ -6213,6 +6318,15 @@ Value is t if tooltip was open, nil otherwise. */) | |||
| 6213 | return x_hide_tip (!tooltip_reuse_hidden_frame); | 6318 | return x_hide_tip (!tooltip_reuse_hidden_frame); |
| 6214 | } | 6319 | } |
| 6215 | 6320 | ||
| 6321 | DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p, | ||
| 6322 | 0, 1, 0, | ||
| 6323 | doc: /* Return t if FRAME is being double buffered. */) | ||
| 6324 | (Lisp_Object frame) | ||
| 6325 | { | ||
| 6326 | struct frame *f = decode_live_frame (frame); | ||
| 6327 | return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil; | ||
| 6328 | } | ||
| 6329 | |||
| 6216 | 6330 | ||
| 6217 | /*********************************************************************** | 6331 | /*********************************************************************** |
| 6218 | File selection dialog | 6332 | File selection dialog |
| @@ -6864,6 +6978,7 @@ frame_parm_handler x_frame_parm_handlers[] = | |||
| 6864 | x_set_alpha, | 6978 | x_set_alpha, |
| 6865 | x_set_sticky, | 6979 | x_set_sticky, |
| 6866 | x_set_tool_bar_position, | 6980 | x_set_tool_bar_position, |
| 6981 | x_set_inhibit_double_buffering, | ||
| 6867 | }; | 6982 | }; |
| 6868 | 6983 | ||
| 6869 | void | 6984 | void |
| @@ -7080,6 +7195,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */); | |||
| 7080 | 7195 | ||
| 7081 | defsubr (&Sx_show_tip); | 7196 | defsubr (&Sx_show_tip); |
| 7082 | defsubr (&Sx_hide_tip); | 7197 | defsubr (&Sx_hide_tip); |
| 7198 | defsubr (&Sx_double_buffered_p); | ||
| 7083 | tip_timer = Qnil; | 7199 | tip_timer = Qnil; |
| 7084 | staticpro (&tip_timer); | 7200 | staticpro (&tip_timer); |
| 7085 | tip_frame = Qnil; | 7201 | tip_frame = Qnil; |
diff --git a/src/xfont.c b/src/xfont.c index 45b0e0a5f53..c2b73173968 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, | |||
| 1057 | { | 1057 | { |
| 1058 | if (s->padding_p) | 1058 | if (s->padding_p) |
| 1059 | for (i = 0; i < len; i++) | 1059 | for (i = 0; i < len; i++) |
| 1060 | XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), | 1060 | XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f), |
| 1061 | gc, x + i, y, str + i, 1); | 1061 | gc, x + i, y, str + i, 1); |
| 1062 | else | 1062 | else |
| 1063 | XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), | 1063 | XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f), |
| 1064 | gc, x, y, str, len); | 1064 | gc, x, y, str, len); |
| 1065 | } | 1065 | } |
| 1066 | else | 1066 | else |
| 1067 | { | 1067 | { |
| 1068 | if (s->padding_p) | 1068 | if (s->padding_p) |
| 1069 | for (i = 0; i < len; i++) | 1069 | for (i = 0; i < len; i++) |
| 1070 | XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), | 1070 | XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f), |
| 1071 | gc, x + i, y, str + i, 1); | 1071 | gc, x + i, y, str + i, 1); |
| 1072 | else | 1072 | else |
| 1073 | XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), | 1073 | XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f), |
| 1074 | gc, x, y, str, len); | 1074 | gc, x, y, str, len); |
| 1075 | } | 1075 | } |
| 1076 | unblock_input (); | 1076 | unblock_input (); |
| @@ -1083,20 +1083,20 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y, | |||
| 1083 | { | 1083 | { |
| 1084 | if (s->padding_p) | 1084 | if (s->padding_p) |
| 1085 | for (i = 0; i < len; i++) | 1085 | for (i = 0; i < len; i++) |
| 1086 | XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), | 1086 | XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f), |
| 1087 | gc, x + i, y, s->char2b + from + i, 1); | 1087 | gc, x + i, y, s->char2b + from + i, 1); |
| 1088 | else | 1088 | else |
| 1089 | XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), | 1089 | XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f), |
| 1090 | gc, x, y, s->char2b + from, len); | 1090 | gc, x, y, s->char2b + from, len); |
| 1091 | } | 1091 | } |
| 1092 | else | 1092 | else |
| 1093 | { | 1093 | { |
| 1094 | if (s->padding_p) | 1094 | if (s->padding_p) |
| 1095 | for (i = 0; i < len; i++) | 1095 | for (i = 0; i < len; i++) |
| 1096 | XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), | 1096 | XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f), |
| 1097 | gc, x + i, y, s->char2b + from + i, 1); | 1097 | gc, x + i, y, s->char2b + from + i, 1); |
| 1098 | else | 1098 | else |
| 1099 | XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), | 1099 | XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f), |
| 1100 | gc, x, y, s->char2b + from, len); | 1100 | gc, x, y, s->char2b + from, len); |
| 1101 | } | 1101 | } |
| 1102 | unblock_input (); | 1102 | unblock_input (); |
diff --git a/src/xftfont.c b/src/xftfont.c index 34c6f7d3e42..861ad80da5c 100644 --- a/src/xftfont.c +++ b/src/xftfont.c | |||
| @@ -586,7 +586,7 @@ xftfont_get_xft_draw (struct frame *f) | |||
| 586 | { | 586 | { |
| 587 | block_input (); | 587 | block_input (); |
| 588 | xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f), | 588 | xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f), |
| 589 | FRAME_X_WINDOW (f), | 589 | FRAME_X_DRAWABLE (f), |
| 590 | FRAME_X_VISUAL (f), | 590 | FRAME_X_VISUAL (f), |
| 591 | FRAME_X_COLORMAP (f)); | 591 | FRAME_X_COLORMAP (f)); |
| 592 | unblock_input (); | 592 | unblock_input (); |
| @@ -600,6 +600,8 @@ static int | |||
| 600 | xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, | 600 | xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, |
| 601 | bool with_background) | 601 | bool with_background) |
| 602 | { | 602 | { |
| 603 | block_input (); | ||
| 604 | |||
| 603 | struct frame *f = s->f; | 605 | struct frame *f = s->f; |
| 604 | struct face *face = s->face; | 606 | struct face *face = s->face; |
| 605 | struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font; | 607 | struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font; |
| @@ -614,7 +616,6 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, | |||
| 614 | xftface_info = (struct xftface_info *) face->extra; | 616 | xftface_info = (struct xftface_info *) face->extra; |
| 615 | xftfont_get_colors (f, face, s->gc, xftface_info, | 617 | xftfont_get_colors (f, face, s->gc, xftface_info, |
| 616 | &fg, with_background ? &bg : NULL); | 618 | &fg, with_background ? &bg : NULL); |
| 617 | block_input (); | ||
| 618 | if (s->num_clips > 0) | 619 | if (s->num_clips > 0) |
| 619 | XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips); | 620 | XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips); |
| 620 | else | 621 | else |
| @@ -652,9 +653,12 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, | |||
| 652 | x + i, y, code + i, 1); | 653 | x + i, y, code + i, 1); |
| 653 | else | 654 | else |
| 654 | XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont, | 655 | XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont, |
| 655 | x, y, code, len); | 656 | x, y, code, len); |
| 657 | /* Need to explicitly mark the frame dirty because we didn't call | ||
| 658 | FRAME_X_DRAWABLE in order to draw: we cached the drawable in the | ||
| 659 | XftDraw structure. */ | ||
| 660 | x_mark_frame_dirty (f); | ||
| 656 | unblock_input (); | 661 | unblock_input (); |
| 657 | |||
| 658 | return len; | 662 | return len; |
| 659 | } | 663 | } |
| 660 | 664 | ||
| @@ -678,13 +682,10 @@ xftfont_shape (Lisp_Object lgstring) | |||
| 678 | static int | 682 | static int |
| 679 | xftfont_end_for_frame (struct frame *f) | 683 | xftfont_end_for_frame (struct frame *f) |
| 680 | { | 684 | { |
| 685 | block_input (); | ||
| 681 | XftDraw *xft_draw; | 686 | XftDraw *xft_draw; |
| 682 | 687 | ||
| 683 | /* Don't do anything if display is dead */ | ||
| 684 | if (FRAME_X_DISPLAY (f) == NULL) return 0; | ||
| 685 | |||
| 686 | xft_draw = font_get_frame_data (f, Qxft); | 688 | xft_draw = font_get_frame_data (f, Qxft); |
| 687 | |||
| 688 | if (xft_draw) | 689 | if (xft_draw) |
| 689 | { | 690 | { |
| 690 | block_input (); | 691 | block_input (); |
| @@ -692,9 +693,19 @@ xftfont_end_for_frame (struct frame *f) | |||
| 692 | unblock_input (); | 693 | unblock_input (); |
| 693 | font_put_frame_data (f, Qxft, NULL); | 694 | font_put_frame_data (f, Qxft, NULL); |
| 694 | } | 695 | } |
| 696 | unblock_input (); | ||
| 695 | return 0; | 697 | return 0; |
| 696 | } | 698 | } |
| 697 | 699 | ||
| 700 | static void | ||
| 701 | xftfont_drop_xrender_surfaces (struct frame *f) | ||
| 702 | { | ||
| 703 | block_input (); | ||
| 704 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) | ||
| 705 | xftfont_end_for_frame (f); | ||
| 706 | unblock_input (); | ||
| 707 | } | ||
| 708 | |||
| 698 | static bool | 709 | static bool |
| 699 | xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object, | 710 | xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object, |
| 700 | Lisp_Object entity) | 711 | Lisp_Object entity) |
| @@ -777,6 +788,10 @@ This is needed with some fonts to correct vertical overlap of glyphs. */); | |||
| 777 | #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF) | 788 | #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF) |
| 778 | xftfont_driver.shape = xftfont_shape; | 789 | xftfont_driver.shape = xftfont_shape; |
| 779 | #endif | 790 | #endif |
| 791 | /* When using X double buffering, the XftDraw structure we build | ||
| 792 | seems to be useless once a frame is resized, so recreate it on | ||
| 793 | ConfigureNotify and in some other cases. */ | ||
| 794 | xftfont_driver.drop_xrender_surfaces = xftfont_drop_xrender_surfaces; | ||
| 780 | 795 | ||
| 781 | register_font_driver (&xftfont_driver, NULL); | 796 | register_font_driver (&xftfont_driver, NULL); |
| 782 | } | 797 | } |
diff --git a/src/xterm.c b/src/xterm.c index 747669446f5..f0dd0ca1dc1 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/>. */ | |||
| 45 | #include <X11/extensions/Xrender.h> | 45 | #include <X11/extensions/Xrender.h> |
| 46 | #endif | 46 | #endif |
| 47 | 47 | ||
| 48 | #ifdef HAVE_XDBE | ||
| 49 | #include <X11/extensions/Xdbe.h> | ||
| 50 | #endif | ||
| 51 | |||
| 48 | /* Load sys/types.h if not already loaded. | 52 | /* Load sys/types.h if not already loaded. |
| 49 | In some systems loading it twice is suicidal. */ | 53 | In some systems loading it twice is suicidal. */ |
| 50 | #ifndef makedev | 54 | #ifndef makedev |
| @@ -360,7 +364,7 @@ x_begin_cr_clip (struct frame *f, GC gc) | |||
| 360 | { | 364 | { |
| 361 | cairo_surface_t *surface; | 365 | cairo_surface_t *surface; |
| 362 | surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f), | 366 | surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f), |
| 363 | FRAME_X_WINDOW (f), | 367 | FRAME_X_DRAWABLE (f), |
| 364 | FRAME_DISPLAY_INFO (f)->visual, | 368 | FRAME_DISPLAY_INFO (f)->visual, |
| 365 | FRAME_PIXEL_WIDTH (f), | 369 | FRAME_PIXEL_WIDTH (f), |
| 366 | FRAME_PIXEL_HEIGHT (f)); | 370 | FRAME_PIXEL_HEIGHT (f)); |
| @@ -722,7 +726,7 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height) | |||
| 722 | cairo_fill (cr); | 726 | cairo_fill (cr); |
| 723 | x_end_cr_clip (f); | 727 | x_end_cr_clip (f); |
| 724 | #else | 728 | #else |
| 725 | XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 729 | XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 726 | gc, x, y, width, height); | 730 | gc, x, y, width, height); |
| 727 | #endif | 731 | #endif |
| 728 | } | 732 | } |
| @@ -740,7 +744,7 @@ x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height) | |||
| 740 | cairo_stroke (cr); | 744 | cairo_stroke (cr); |
| 741 | x_end_cr_clip (f); | 745 | x_end_cr_clip (f); |
| 742 | #else | 746 | #else |
| 743 | XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 747 | XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 744 | gc, x, y, width, height); | 748 | gc, x, y, width, height); |
| 745 | #endif | 749 | #endif |
| 746 | } | 750 | } |
| @@ -756,7 +760,10 @@ x_clear_window (struct frame *f) | |||
| 756 | cairo_paint (cr); | 760 | cairo_paint (cr); |
| 757 | x_end_cr_clip (f); | 761 | x_end_cr_clip (f); |
| 758 | #else | 762 | #else |
| 759 | XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); | 763 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) |
| 764 | x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); | ||
| 765 | else | ||
| 766 | XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); | ||
| 760 | #endif | 767 | #endif |
| 761 | } | 768 | } |
| 762 | 769 | ||
| @@ -1067,7 +1074,7 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1) | |||
| 1067 | #ifdef USE_CAIRO | 1074 | #ifdef USE_CAIRO |
| 1068 | x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0); | 1075 | x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0); |
| 1069 | #else | 1076 | #else |
| 1070 | XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 1077 | XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), |
| 1071 | f->output_data.x->normal_gc, x, y0, x, y1); | 1078 | f->output_data.x->normal_gc, x, y0, x, y1); |
| 1072 | #endif | 1079 | #endif |
| 1073 | } | 1080 | } |
| @@ -1175,6 +1182,41 @@ x_update_window_end (struct window *w, bool cursor_on_p, | |||
| 1175 | } | 1182 | } |
| 1176 | } | 1183 | } |
| 1177 | 1184 | ||
| 1185 | /* Show the frame back buffer. If frame is double-buffered, | ||
| 1186 | atomically publish to the user's screen graphics updates made since | ||
| 1187 | the last call to show_back_buffer. */ | ||
| 1188 | static void | ||
| 1189 | show_back_buffer (struct frame *f) | ||
| 1190 | { | ||
| 1191 | block_input (); | ||
| 1192 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) | ||
| 1193 | { | ||
| 1194 | #ifdef HAVE_XDBE | ||
| 1195 | XdbeSwapInfo swap_info; | ||
| 1196 | memset (&swap_info, 0, sizeof (swap_info)); | ||
| 1197 | swap_info.swap_window = FRAME_X_WINDOW (f); | ||
| 1198 | swap_info.swap_action = XdbeCopied; | ||
| 1199 | XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1); | ||
| 1200 | #else | ||
| 1201 | eassert (!"should have back-buffer only with XDBE"); | ||
| 1202 | #endif | ||
| 1203 | } | ||
| 1204 | FRAME_X_NEED_BUFFER_FLIP (f) = false; | ||
| 1205 | unblock_input (); | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | /* Updates back buffer and flushes changes to display. Called from | ||
| 1209 | minibuf read code. Note that we display the back buffer even if | ||
| 1210 | buffer flipping is blocked. */ | ||
| 1211 | static void | ||
| 1212 | x_flip_and_flush (struct frame *f) | ||
| 1213 | { | ||
| 1214 | block_input (); | ||
| 1215 | if (FRAME_X_NEED_BUFFER_FLIP (f)) | ||
| 1216 | show_back_buffer (f); | ||
| 1217 | x_flush (f); | ||
| 1218 | unblock_input (); | ||
| 1219 | } | ||
| 1178 | 1220 | ||
| 1179 | /* End update of frame F. This function is installed as a hook in | 1221 | /* End update of frame F. This function is installed as a hook in |
| 1180 | update_end. */ | 1222 | update_end. */ |
| @@ -1207,7 +1249,7 @@ x_update_end (struct frame *f) | |||
| 1207 | if (! FRAME_EXTERNAL_MENU_BAR (f)) | 1249 | if (! FRAME_EXTERNAL_MENU_BAR (f)) |
| 1208 | height += FRAME_MENU_BAR_HEIGHT (f); | 1250 | height += FRAME_MENU_BAR_HEIGHT (f); |
| 1209 | surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f), | 1251 | surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f), |
| 1210 | FRAME_X_WINDOW (f), | 1252 | FRAME_X_DRAWABLE (f), |
| 1211 | FRAME_DISPLAY_INFO (f)->visual, | 1253 | FRAME_DISPLAY_INFO (f)->visual, |
| 1212 | width, | 1254 | width, |
| 1213 | height); | 1255 | height); |
| @@ -1220,7 +1262,7 @@ x_update_end (struct frame *f) | |||
| 1220 | cairo_destroy (cr); | 1262 | cairo_destroy (cr); |
| 1221 | unblock_input (); | 1263 | unblock_input (); |
| 1222 | } | 1264 | } |
| 1223 | #endif /* USE_CAIRO */ | 1265 | #endif |
| 1224 | 1266 | ||
| 1225 | #ifndef XFlush | 1267 | #ifndef XFlush |
| 1226 | block_input (); | 1268 | block_input (); |
| @@ -1229,17 +1271,26 @@ x_update_end (struct frame *f) | |||
| 1229 | #endif | 1271 | #endif |
| 1230 | } | 1272 | } |
| 1231 | 1273 | ||
| 1232 | |||
| 1233 | /* This function is called from various places in xdisp.c | 1274 | /* This function is called from various places in xdisp.c |
| 1234 | whenever a complete update has been performed. */ | 1275 | whenever a complete update has been performed. */ |
| 1235 | 1276 | ||
| 1236 | static void | 1277 | static void |
| 1237 | XTframe_up_to_date (struct frame *f) | 1278 | XTframe_up_to_date (struct frame *f) |
| 1238 | { | 1279 | { |
| 1239 | if (FRAME_X_P (f)) | 1280 | eassert (FRAME_X_P (f)); |
| 1240 | FRAME_MOUSE_UPDATE (f); | 1281 | block_input (); |
| 1282 | FRAME_MOUSE_UPDATE (f); | ||
| 1283 | if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f)) | ||
| 1284 | show_back_buffer (f); | ||
| 1285 | unblock_input (); | ||
| 1241 | } | 1286 | } |
| 1242 | 1287 | ||
| 1288 | static void | ||
| 1289 | XTbuffer_flipping_unblocked_hook (struct frame *f) | ||
| 1290 | { | ||
| 1291 | if (FRAME_X_NEED_BUFFER_FLIP (f)) | ||
| 1292 | show_back_buffer (f); | ||
| 1293 | } | ||
| 1243 | 1294 | ||
| 1244 | /* Clear under internal border if any (GTK has its own version). */ | 1295 | /* Clear under internal border if any (GTK has its own version). */ |
| 1245 | #ifndef USE_GTK | 1296 | #ifndef USE_GTK |
| @@ -1354,7 +1405,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring | |||
| 1354 | #else /* not USE_CAIRO */ | 1405 | #else /* not USE_CAIRO */ |
| 1355 | if (p->which) | 1406 | if (p->which) |
| 1356 | { | 1407 | { |
| 1357 | Window window = FRAME_X_WINDOW (f); | 1408 | Drawable drawable = FRAME_X_DRAWABLE (f); |
| 1358 | char *bits; | 1409 | char *bits; |
| 1359 | Pixmap pixmap, clipmask = (Pixmap) 0; | 1410 | Pixmap pixmap, clipmask = (Pixmap) 0; |
| 1360 | int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f)); | 1411 | int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f)); |
| @@ -1367,7 +1418,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring | |||
| 1367 | 1418 | ||
| 1368 | /* Draw the bitmap. I believe these small pixmaps can be cached | 1419 | /* Draw the bitmap. I believe these small pixmaps can be cached |
| 1369 | by the server. */ | 1420 | by the server. */ |
| 1370 | pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h, | 1421 | pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h, |
| 1371 | (p->cursor_p | 1422 | (p->cursor_p |
| 1372 | ? (p->overlay_p ? face->background | 1423 | ? (p->overlay_p ? face->background |
| 1373 | : f->output_data.x->cursor_pixel) | 1424 | : f->output_data.x->cursor_pixel) |
| @@ -1386,7 +1437,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring | |||
| 1386 | XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv); | 1437 | XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv); |
| 1387 | } | 1438 | } |
| 1388 | 1439 | ||
| 1389 | XCopyArea (display, pixmap, window, gc, 0, 0, | 1440 | XCopyArea (display, pixmap, drawable, gc, 0, 0, |
| 1390 | p->wd, p->h, p->x, p->y); | 1441 | p->wd, p->h, p->x, p->y); |
| 1391 | XFreePixmap (display, pixmap); | 1442 | XFreePixmap (display, pixmap); |
| 1392 | 1443 | ||
| @@ -1487,7 +1538,7 @@ x_set_cursor_gc (struct glyph_string *s) | |||
| 1487 | mask, &xgcv); | 1538 | mask, &xgcv); |
| 1488 | else | 1539 | else |
| 1489 | FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc | 1540 | FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc |
| 1490 | = XCreateGC (s->display, s->window, mask, &xgcv); | 1541 | = XCreateGC (s->display, FRAME_X_DRAWABLE (s->f), mask, &xgcv); |
| 1491 | 1542 | ||
| 1492 | s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc; | 1543 | s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc; |
| 1493 | } | 1544 | } |
| @@ -1534,7 +1585,7 @@ x_set_mouse_face_gc (struct glyph_string *s) | |||
| 1534 | mask, &xgcv); | 1585 | mask, &xgcv); |
| 1535 | else | 1586 | else |
| 1536 | FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc | 1587 | FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc |
| 1537 | = XCreateGC (s->display, s->window, mask, &xgcv); | 1588 | = XCreateGC (s->display, FRAME_X_DRAWABLE (s->f), mask, &xgcv); |
| 1538 | 1589 | ||
| 1539 | s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc; | 1590 | s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc; |
| 1540 | 1591 | ||
| @@ -2565,7 +2616,7 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor, | |||
| 2565 | { | 2616 | { |
| 2566 | xgcv.stipple = dpyinfo->gray; | 2617 | xgcv.stipple = dpyinfo->gray; |
| 2567 | mask |= GCStipple; | 2618 | mask |= GCStipple; |
| 2568 | relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv); | 2619 | relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv); |
| 2569 | } | 2620 | } |
| 2570 | else | 2621 | else |
| 2571 | XChangeGC (dpy, relief->gc, mask, &xgcv); | 2622 | XChangeGC (dpy, relief->gc, mask, &xgcv); |
| @@ -2696,7 +2747,7 @@ x_draw_relief_rect (struct frame *f, | |||
| 2696 | x_reset_clip_rectangles (f, bottom_right_gc); | 2747 | x_reset_clip_rectangles (f, bottom_right_gc); |
| 2697 | #else | 2748 | #else |
| 2698 | Display *dpy = FRAME_X_DISPLAY (f); | 2749 | Display *dpy = FRAME_X_DISPLAY (f); |
| 2699 | Window window = FRAME_X_WINDOW (f); | 2750 | Drawable drawable = FRAME_X_DRAWABLE (f); |
| 2700 | int i; | 2751 | int i; |
| 2701 | GC gc; | 2752 | GC gc; |
| 2702 | 2753 | ||
| @@ -2715,12 +2766,12 @@ x_draw_relief_rect (struct frame *f, | |||
| 2715 | if (top_p) | 2766 | if (top_p) |
| 2716 | { | 2767 | { |
| 2717 | if (width == 1) | 2768 | if (width == 1) |
| 2718 | XDrawLine (dpy, window, gc, | 2769 | XDrawLine (dpy, drawable, gc, |
| 2719 | left_x + left_p, top_y, | 2770 | left_x + left_p, top_y, |
| 2720 | right_x + !right_p, top_y); | 2771 | right_x + !right_p, top_y); |
| 2721 | 2772 | ||
| 2722 | for (i = 1; i < width; ++i) | 2773 | for (i = 1; i < width; ++i) |
| 2723 | XDrawLine (dpy, window, gc, | 2774 | XDrawLine (dpy, drawable, gc, |
| 2724 | left_x + i * left_p, top_y + i, | 2775 | left_x + i * left_p, top_y + i, |
| 2725 | right_x + 1 - i * right_p, top_y + i); | 2776 | right_x + 1 - i * right_p, top_y + i); |
| 2726 | } | 2777 | } |
| @@ -2729,13 +2780,13 @@ x_draw_relief_rect (struct frame *f, | |||
| 2729 | if (left_p) | 2780 | if (left_p) |
| 2730 | { | 2781 | { |
| 2731 | if (width == 1) | 2782 | if (width == 1) |
| 2732 | XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y); | 2783 | XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); |
| 2733 | 2784 | ||
| 2734 | XClearArea (dpy, window, left_x, top_y, 1, 1, False); | 2785 | x_clear_area(f, left_x, top_y, 1, 1); |
| 2735 | XClearArea (dpy, window, left_x, bottom_y, 1, 1, False); | 2786 | x_clear_area(f, left_x, bottom_y, 1, 1); |
| 2736 | 2787 | ||
| 2737 | for (i = (width > 1 ? 1 : 0); i < width; ++i) | 2788 | for (i = (width > 1 ? 1 : 0); i < width; ++i) |
| 2738 | XDrawLine (dpy, window, gc, | 2789 | XDrawLine (dpy, drawable, gc, |
| 2739 | left_x + i, top_y + (i + 1) * top_p, | 2790 | left_x + i, top_y + (i + 1) * top_p, |
| 2740 | left_x + i, bottom_y + 1 - (i + 1) * bot_p); | 2791 | left_x + i, bottom_y + 1 - (i + 1) * bot_p); |
| 2741 | } | 2792 | } |
| @@ -2751,23 +2802,23 @@ x_draw_relief_rect (struct frame *f, | |||
| 2751 | { | 2802 | { |
| 2752 | /* Outermost top line. */ | 2803 | /* Outermost top line. */ |
| 2753 | if (top_p) | 2804 | if (top_p) |
| 2754 | XDrawLine (dpy, window, gc, | 2805 | XDrawLine (dpy, drawable, gc, |
| 2755 | left_x + left_p, top_y, | 2806 | left_x + left_p, top_y, |
| 2756 | right_x + !right_p, top_y); | 2807 | right_x + !right_p, top_y); |
| 2757 | 2808 | ||
| 2758 | /* Outermost left line. */ | 2809 | /* Outermost left line. */ |
| 2759 | if (left_p) | 2810 | if (left_p) |
| 2760 | XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y); | 2811 | XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); |
| 2761 | } | 2812 | } |
| 2762 | 2813 | ||
| 2763 | /* Bottom. */ | 2814 | /* Bottom. */ |
| 2764 | if (bot_p) | 2815 | if (bot_p) |
| 2765 | { | 2816 | { |
| 2766 | XDrawLine (dpy, window, gc, | 2817 | XDrawLine (dpy, drawable, gc, |
| 2767 | left_x + left_p, bottom_y, | 2818 | left_x + left_p, bottom_y, |
| 2768 | right_x + !right_p, bottom_y); | 2819 | right_x + !right_p, bottom_y); |
| 2769 | for (i = 1; i < width; ++i) | 2820 | for (i = 1; i < width; ++i) |
| 2770 | XDrawLine (dpy, window, gc, | 2821 | XDrawLine (dpy, drawable, gc, |
| 2771 | left_x + i * left_p, bottom_y - i, | 2822 | left_x + i * left_p, bottom_y - i, |
| 2772 | right_x + 1 - i * right_p, bottom_y - i); | 2823 | right_x + 1 - i * right_p, bottom_y - i); |
| 2773 | } | 2824 | } |
| @@ -2775,10 +2826,10 @@ x_draw_relief_rect (struct frame *f, | |||
| 2775 | /* Right. */ | 2826 | /* Right. */ |
| 2776 | if (right_p) | 2827 | if (right_p) |
| 2777 | { | 2828 | { |
| 2778 | XClearArea (dpy, window, right_x, top_y, 1, 1, False); | 2829 | x_clear_area(f, right_x, top_y, 1, 1); |
| 2779 | XClearArea (dpy, window, right_x, bottom_y, 1, 1, False); | 2830 | x_clear_area(f, right_x, bottom_y, 1, 1); |
| 2780 | for (i = 0; i < width; ++i) | 2831 | for (i = 0; i < width; ++i) |
| 2781 | XDrawLine (dpy, window, gc, | 2832 | XDrawLine (dpy, drawable, gc, |
| 2782 | right_x - i, top_y + (i + 1) * top_p, | 2833 | right_x - i, top_y + (i + 1) * top_p, |
| 2783 | right_x - i, bottom_y + 1 - (i + 1) * bot_p); | 2834 | right_x - i, bottom_y + 1 - (i + 1) * bot_p); |
| 2784 | } | 2835 | } |
| @@ -2930,7 +2981,8 @@ x_draw_image_foreground (struct glyph_string *s) | |||
| 2930 | image_rect.width = s->slice.width; | 2981 | image_rect.width = s->slice.width; |
| 2931 | image_rect.height = s->slice.height; | 2982 | image_rect.height = s->slice.height; |
| 2932 | if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) | 2983 | if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) |
| 2933 | XCopyArea (s->display, s->img->pixmap, s->window, s->gc, | 2984 | XCopyArea (s->display, s->img->pixmap, |
| 2985 | FRAME_X_DRAWABLE (s->f), s->gc, | ||
| 2934 | s->slice.x + r.x - x, s->slice.y + r.y - y, | 2986 | s->slice.x + r.x - x, s->slice.y + r.y - y, |
| 2935 | r.width, r.height, r.x, r.y); | 2987 | r.width, r.height, r.x, r.y); |
| 2936 | } | 2988 | } |
| @@ -2944,7 +2996,8 @@ x_draw_image_foreground (struct glyph_string *s) | |||
| 2944 | image_rect.width = s->slice.width; | 2996 | image_rect.width = s->slice.width; |
| 2945 | image_rect.height = s->slice.height; | 2997 | image_rect.height = s->slice.height; |
| 2946 | if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) | 2998 | if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) |
| 2947 | XCopyArea (s->display, s->img->pixmap, s->window, s->gc, | 2999 | XCopyArea (s->display, s->img->pixmap, |
| 3000 | FRAME_X_DRAWABLE (s->f), s->gc, | ||
| 2948 | s->slice.x + r.x - x, s->slice.y + r.y - y, | 3001 | s->slice.x + r.x - x, s->slice.y + r.y - y, |
| 2949 | r.width, r.height, r.x, r.y); | 3002 | r.width, r.height, r.x, r.y); |
| 2950 | 3003 | ||
| @@ -3184,7 +3237,7 @@ x_draw_image_glyph_string (struct glyph_string *s) | |||
| 3184 | int depth = DefaultDepthOfScreen (screen); | 3237 | int depth = DefaultDepthOfScreen (screen); |
| 3185 | 3238 | ||
| 3186 | /* Create a pixmap as large as the glyph string. */ | 3239 | /* Create a pixmap as large as the glyph string. */ |
| 3187 | pixmap = XCreatePixmap (s->display, s->window, | 3240 | pixmap = XCreatePixmap (s->display, FRAME_X_DRAWABLE (s->f), |
| 3188 | s->background_width, | 3241 | s->background_width, |
| 3189 | s->height, depth); | 3242 | s->height, depth); |
| 3190 | 3243 | ||
| @@ -3259,7 +3312,7 @@ x_draw_image_glyph_string (struct glyph_string *s) | |||
| 3259 | { | 3312 | { |
| 3260 | x_draw_image_foreground_1 (s, pixmap); | 3313 | x_draw_image_foreground_1 (s, pixmap); |
| 3261 | x_set_glyph_string_clipping (s); | 3314 | x_set_glyph_string_clipping (s); |
| 3262 | XCopyArea (s->display, pixmap, s->window, s->gc, | 3315 | XCopyArea (s->display, pixmap, FRAME_X_DRAWABLE (s->f), s->gc, |
| 3263 | 0, 0, s->background_width, s->height, s->x, s->y); | 3316 | 0, 0, s->background_width, s->height, s->x, s->y); |
| 3264 | XFreePixmap (s->display, pixmap); | 3317 | XFreePixmap (s->display, pixmap); |
| 3265 | } | 3318 | } |
| @@ -3438,7 +3491,7 @@ x_draw_underwave (struct glyph_string *s) | |||
| 3438 | 3491 | ||
| 3439 | while (x1 <= xmax) | 3492 | while (x1 <= xmax) |
| 3440 | { | 3493 | { |
| 3441 | XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2); | 3494 | XDrawLine (s->display, FRAME_X_DRAWABLE (s->f), s->gc, x1, y1, x2, y2); |
| 3442 | x1 = x2, y1 = y2; | 3495 | x1 = x2, y1 = y2; |
| 3443 | x2 += dx, y2 = y0 + odd*dy; | 3496 | x2 += dx, y2 = y0 + odd*dy; |
| 3444 | odd = !odd; | 3497 | odd = !odd; |
| @@ -3741,7 +3794,7 @@ x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, | |||
| 3741 | /* Never called on a GUI frame, see | 3794 | /* Never called on a GUI frame, see |
| 3742 | http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html | 3795 | http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html |
| 3743 | */ | 3796 | */ |
| 3744 | XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), | 3797 | XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f), |
| 3745 | f->output_data.x->normal_gc, | 3798 | f->output_data.x->normal_gc, |
| 3746 | x, y, width, height, | 3799 | x, y, width, height, |
| 3747 | x + shift_by, y); | 3800 | x + shift_by, y); |
| @@ -3782,8 +3835,14 @@ x_clear_area (struct frame *f, int x, int y, int width, int height) | |||
| 3782 | cairo_fill (cr); | 3835 | cairo_fill (cr); |
| 3783 | x_end_cr_clip (f); | 3836 | x_end_cr_clip (f); |
| 3784 | #else | 3837 | #else |
| 3785 | x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 3838 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) |
| 3786 | x, y, width, height, False); | 3839 | XFillRectangle (FRAME_X_DISPLAY (f), |
| 3840 | FRAME_X_DRAWABLE (f), | ||
| 3841 | f->output_data.x->reverse_gc, | ||
| 3842 | x, y, width, height); | ||
| 3843 | else | ||
| 3844 | x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 3845 | x, y, width, height, False); | ||
| 3787 | #endif | 3846 | #endif |
| 3788 | } | 3847 | } |
| 3789 | 3848 | ||
| @@ -3799,19 +3858,13 @@ x_clear_frame (struct frame *f) | |||
| 3799 | 3858 | ||
| 3800 | block_input (); | 3859 | block_input (); |
| 3801 | 3860 | ||
| 3861 | font_drop_xrender_surfaces (f); | ||
| 3802 | x_clear_window (f); | 3862 | x_clear_window (f); |
| 3803 | 3863 | ||
| 3804 | /* We have to clear the scroll bars. If we have changed colors or | 3864 | /* We have to clear the scroll bars. If we have changed colors or |
| 3805 | something like that, then they should be notified. */ | 3865 | something like that, then they should be notified. */ |
| 3806 | x_scroll_bar_clear (f); | 3866 | x_scroll_bar_clear (f); |
| 3807 | 3867 | ||
| 3808 | #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS) | ||
| 3809 | /* Make sure scroll bars are redrawn. As they aren't redrawn by | ||
| 3810 | redisplay, do it here. */ | ||
| 3811 | if (FRAME_GTK_WIDGET (f)) | ||
| 3812 | gtk_widget_queue_draw (FRAME_GTK_WIDGET (f)); | ||
| 3813 | #endif | ||
| 3814 | |||
| 3815 | XFlush (FRAME_X_DISPLAY (f)); | 3868 | XFlush (FRAME_X_DISPLAY (f)); |
| 3816 | 3869 | ||
| 3817 | unblock_input (); | 3870 | unblock_input (); |
| @@ -4109,7 +4162,7 @@ x_scroll_run (struct window *w, struct run *run) | |||
| 4109 | SET_FRAME_GARBAGED (f); | 4162 | SET_FRAME_GARBAGED (f); |
| 4110 | #else | 4163 | #else |
| 4111 | XCopyArea (FRAME_X_DISPLAY (f), | 4164 | XCopyArea (FRAME_X_DISPLAY (f), |
| 4112 | FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), | 4165 | FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f), |
| 4113 | f->output_data.x->normal_gc, | 4166 | f->output_data.x->normal_gc, |
| 4114 | x, from_y, | 4167 | x, from_y, |
| 4115 | width, height, | 4168 | width, height, |
| @@ -7448,6 +7501,26 @@ x_net_wm_state (struct frame *f, Window window) | |||
| 7448 | /** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/ | 7501 | /** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/ |
| 7449 | } | 7502 | } |
| 7450 | 7503 | ||
| 7504 | /* Flip back buffers on any frames with undrawn content. */ | ||
| 7505 | static void | ||
| 7506 | flush_dirty_back_buffers (void) | ||
| 7507 | { | ||
| 7508 | block_input (); | ||
| 7509 | Lisp_Object tail, frame; | ||
| 7510 | FOR_EACH_FRAME (tail, frame) | ||
| 7511 | { | ||
| 7512 | struct frame *f = XFRAME (frame); | ||
| 7513 | if (FRAME_LIVE_P (f) && | ||
| 7514 | FRAME_X_P (f) && | ||
| 7515 | FRAME_X_WINDOW (f) && | ||
| 7516 | !FRAME_GARBAGED_P (f) && | ||
| 7517 | !buffer_flipping_blocked_p () && | ||
| 7518 | FRAME_X_NEED_BUFFER_FLIP (f)) | ||
| 7519 | show_back_buffer (f); | ||
| 7520 | } | ||
| 7521 | unblock_input (); | ||
| 7522 | } | ||
| 7523 | |||
| 7451 | /* Handles the XEvent EVENT on display DPYINFO. | 7524 | /* Handles the XEvent EVENT on display DPYINFO. |
| 7452 | 7525 | ||
| 7453 | *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. | 7526 | *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. |
| @@ -7766,23 +7839,49 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 7766 | { | 7839 | { |
| 7767 | if (!FRAME_VISIBLE_P (f)) | 7840 | if (!FRAME_VISIBLE_P (f)) |
| 7768 | { | 7841 | { |
| 7842 | block_input (); | ||
| 7769 | SET_FRAME_VISIBLE (f, 1); | 7843 | SET_FRAME_VISIBLE (f, 1); |
| 7770 | SET_FRAME_ICONIFIED (f, false); | 7844 | SET_FRAME_ICONIFIED (f, false); |
| 7845 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) | ||
| 7846 | font_drop_xrender_surfaces (f); | ||
| 7771 | f->output_data.x->has_been_visible = true; | 7847 | f->output_data.x->has_been_visible = true; |
| 7772 | SET_FRAME_GARBAGED (f); | 7848 | SET_FRAME_GARBAGED (f); |
| 7849 | unblock_input (); | ||
| 7773 | } | 7850 | } |
| 7774 | else | 7851 | else if (FRAME_GARBAGED_P (f)) |
| 7775 | { | 7852 | { |
| 7776 | #ifdef USE_GTK | 7853 | #ifdef USE_GTK |
| 7777 | /* This seems to be needed for GTK 2.6 and later, see | 7854 | /* Go around the back buffer and manually clear the |
| 7778 | http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */ | 7855 | window the first time we show it. This way, we avoid |
| 7779 | x_clear_area (f, | 7856 | showing users the sanity-defying horror of whatever |
| 7780 | event->xexpose.x, event->xexpose.y, | 7857 | GtkWindow is rendering beneath us. We've garbaged |
| 7781 | event->xexpose.width, event->xexpose.height); | 7858 | the frame, so we'll redraw the whole thing on next |
| 7859 | redisplay anyway. Yuck. */ | ||
| 7860 | x_clear_area1 ( | ||
| 7861 | FRAME_X_DISPLAY (f), | ||
| 7862 | FRAME_X_WINDOW (f), | ||
| 7863 | event->xexpose.x, event->xexpose.y, | ||
| 7864 | event->xexpose.width, event->xexpose.height, | ||
| 7865 | 0); | ||
| 7782 | #endif | 7866 | #endif |
| 7783 | expose_frame (f, event->xexpose.x, event->xexpose.y, | 7867 | } |
| 7868 | |||
| 7869 | |||
| 7870 | if (!FRAME_GARBAGED_P (f)) | ||
| 7871 | { | ||
| 7872 | #ifdef USE_GTK | ||
| 7873 | /* This seems to be needed for GTK 2.6 and later, see | ||
| 7874 | http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */ | ||
| 7875 | x_clear_area (f, | ||
| 7876 | event->xexpose.x, event->xexpose.y, | ||
| 7877 | event->xexpose.width, event->xexpose.height); | ||
| 7878 | #endif | ||
| 7879 | expose_frame (f, event->xexpose.x, event->xexpose.y, | ||
| 7784 | event->xexpose.width, event->xexpose.height); | 7880 | event->xexpose.width, event->xexpose.height); |
| 7785 | } | 7881 | } |
| 7882 | |||
| 7883 | if (!FRAME_GARBAGED_P (f)) | ||
| 7884 | show_back_buffer (f); | ||
| 7786 | } | 7885 | } |
| 7787 | else | 7886 | else |
| 7788 | { | 7887 | { |
| @@ -7822,10 +7921,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 7822 | available. */ | 7921 | available. */ |
| 7823 | f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable); | 7922 | f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable); |
| 7824 | if (f) | 7923 | if (f) |
| 7825 | expose_frame (f, event->xgraphicsexpose.x, | 7924 | { |
| 7826 | event->xgraphicsexpose.y, | 7925 | expose_frame (f, event->xgraphicsexpose.x, |
| 7827 | event->xgraphicsexpose.width, | 7926 | event->xgraphicsexpose.y, |
| 7828 | event->xgraphicsexpose.height); | 7927 | event->xgraphicsexpose.width, |
| 7928 | event->xgraphicsexpose.height); | ||
| 7929 | show_back_buffer (f); | ||
| 7930 | } | ||
| 7829 | #ifdef USE_X_TOOLKIT | 7931 | #ifdef USE_X_TOOLKIT |
| 7830 | else | 7932 | else |
| 7831 | goto OTHER; | 7933 | goto OTHER; |
| @@ -8410,7 +8512,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8410 | else | 8512 | else |
| 8411 | configureEvent = next_event; | 8513 | configureEvent = next_event; |
| 8412 | } | 8514 | } |
| 8515 | |||
| 8413 | f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window); | 8516 | f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window); |
| 8517 | /* Unfortunately, we need to call font_drop_xrender_surfaces for | ||
| 8518 | _all_ ConfigureNotify events, otherwise we miss some and | ||
| 8519 | flicker. Don't try to optimize these calls by looking only | ||
| 8520 | for size changes: that's not sufficient. We miss some | ||
| 8521 | surface invalidations and flicker. */ | ||
| 8522 | block_input (); | ||
| 8523 | if (f && FRAME_X_DOUBLE_BUFFERED_P (f)) | ||
| 8524 | font_drop_xrender_surfaces (f); | ||
| 8525 | unblock_input (); | ||
| 8414 | #ifdef USE_CAIRO | 8526 | #ifdef USE_CAIRO |
| 8415 | if (f) x_cr_destroy_surface (f); | 8527 | if (f) x_cr_destroy_surface (f); |
| 8416 | #endif | 8528 | #endif |
| @@ -8419,6 +8531,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8419 | && (f = any) | 8531 | && (f = any) |
| 8420 | && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)) | 8532 | && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)) |
| 8421 | { | 8533 | { |
| 8534 | block_input (); | ||
| 8535 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) | ||
| 8536 | font_drop_xrender_surfaces (f); | ||
| 8537 | unblock_input (); | ||
| 8422 | xg_frame_resized (f, configureEvent.xconfigure.width, | 8538 | xg_frame_resized (f, configureEvent.xconfigure.width, |
| 8423 | configureEvent.xconfigure.height); | 8539 | configureEvent.xconfigure.height); |
| 8424 | #ifdef USE_CAIRO | 8540 | #ifdef USE_CAIRO |
| @@ -8429,7 +8545,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8429 | #endif | 8545 | #endif |
| 8430 | if (f) | 8546 | if (f) |
| 8431 | { | 8547 | { |
| 8432 | x_net_wm_state (f, configureEvent.xconfigure.window); | 8548 | |
| 8549 | x_net_wm_state (f, configureEvent.xconfigure.window); | ||
| 8433 | 8550 | ||
| 8434 | #ifdef USE_X_TOOLKIT | 8551 | #ifdef USE_X_TOOLKIT |
| 8435 | /* Tip frames are pure X window, set size for them. */ | 8552 | /* Tip frames are pure X window, set size for them. */ |
| @@ -8437,7 +8554,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8437 | { | 8554 | { |
| 8438 | if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height | 8555 | if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height |
| 8439 | || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width) | 8556 | || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width) |
| 8440 | SET_FRAME_GARBAGED (f); | 8557 | { |
| 8558 | SET_FRAME_GARBAGED (f); | ||
| 8559 | } | ||
| 8441 | FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height; | 8560 | FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height; |
| 8442 | FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width; | 8561 | FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width; |
| 8443 | } | 8562 | } |
| @@ -8463,8 +8582,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8463 | || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f)) | 8582 | || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f)) |
| 8464 | { | 8583 | { |
| 8465 | change_frame_size (f, width, height, false, true, false, true); | 8584 | change_frame_size (f, width, height, false, true, false, true); |
| 8466 | x_clear_under_internal_border (f); | 8585 | x_clear_under_internal_border (f); |
| 8467 | SET_FRAME_GARBAGED (f); | 8586 | SET_FRAME_GARBAGED (f); |
| 8468 | cancel_mouse_face (f); | 8587 | cancel_mouse_face (f); |
| 8469 | } | 8588 | } |
| 8470 | #endif /* not USE_GTK */ | 8589 | #endif /* not USE_GTK */ |
| @@ -8688,6 +8807,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8688 | count++; | 8807 | count++; |
| 8689 | } | 8808 | } |
| 8690 | 8809 | ||
| 8810 | /* Sometimes event processing draws to the frame outside redisplay. | ||
| 8811 | To ensure that these changes become visible, draw them here. */ | ||
| 8812 | flush_dirty_back_buffers (); | ||
| 8691 | SAFE_FREE (); | 8813 | SAFE_FREE (); |
| 8692 | return count; | 8814 | return count; |
| 8693 | } | 8815 | } |
| @@ -8880,7 +9002,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) | |||
| 8880 | if (dpyinfo->scratch_cursor_gc) | 9002 | if (dpyinfo->scratch_cursor_gc) |
| 8881 | XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv); | 9003 | XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv); |
| 8882 | else | 9004 | else |
| 8883 | dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f), | 9005 | dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), |
| 8884 | GCForeground, &xgcv); | 9006 | GCForeground, &xgcv); |
| 8885 | gc = dpyinfo->scratch_cursor_gc; | 9007 | gc = dpyinfo->scratch_cursor_gc; |
| 8886 | 9008 | ||
| @@ -8937,7 +9059,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text | |||
| 8937 | else | 9059 | else |
| 8938 | { | 9060 | { |
| 8939 | Display *dpy = FRAME_X_DISPLAY (f); | 9061 | Display *dpy = FRAME_X_DISPLAY (f); |
| 8940 | Window window = FRAME_X_WINDOW (f); | 9062 | Drawable drawable = FRAME_X_DRAWABLE (f); |
| 8941 | GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc; | 9063 | GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc; |
| 8942 | unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures; | 9064 | unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures; |
| 8943 | struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id); | 9065 | struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id); |
| @@ -8958,7 +9080,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text | |||
| 8958 | XChangeGC (dpy, gc, mask, &xgcv); | 9080 | XChangeGC (dpy, gc, mask, &xgcv); |
| 8959 | else | 9081 | else |
| 8960 | { | 9082 | { |
| 8961 | gc = XCreateGC (dpy, window, mask, &xgcv); | 9083 | gc = XCreateGC (dpy, drawable, mask, &xgcv); |
| 8962 | FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc; | 9084 | FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc; |
| 8963 | } | 9085 | } |
| 8964 | 9086 | ||
| @@ -9028,11 +9150,6 @@ static void | |||
| 9028 | x_clear_frame_area (struct frame *f, int x, int y, int width, int height) | 9150 | x_clear_frame_area (struct frame *f, int x, int y, int width, int height) |
| 9029 | { | 9151 | { |
| 9030 | x_clear_area (f, x, y, width, height); | 9152 | x_clear_area (f, x, y, width, height); |
| 9031 | #ifdef USE_GTK | ||
| 9032 | /* Must queue a redraw, because scroll bars might have been cleared. */ | ||
| 9033 | if (FRAME_GTK_WIDGET (f)) | ||
| 9034 | gtk_widget_queue_draw (FRAME_GTK_WIDGET (f)); | ||
| 9035 | #endif | ||
| 9036 | } | 9153 | } |
| 9037 | 9154 | ||
| 9038 | 9155 | ||
| @@ -10889,9 +11006,9 @@ x_make_frame_visible (struct frame *f) | |||
| 10889 | 11006 | ||
| 10890 | if (! FRAME_VISIBLE_P (f)) | 11007 | if (! FRAME_VISIBLE_P (f)) |
| 10891 | { | 11008 | { |
| 10892 | /* We test FRAME_GARBAGED_P here to make sure we don't | 11009 | /* We test asked_for_visible here to make sure we don't |
| 10893 | call x_set_offset a second time | 11010 | call x_set_offset a second time |
| 10894 | if we get to x_make_frame_visible a second time | 11011 | if we get to x_make_frame_visible a second time |
| 10895 | before the window gets really visible. */ | 11012 | before the window gets really visible. */ |
| 10896 | if (! FRAME_ICONIFIED_P (f) | 11013 | if (! FRAME_ICONIFIED_P (f) |
| 10897 | && ! FRAME_X_EMBEDDED_P (f) | 11014 | && ! FRAME_X_EMBEDDED_P (f) |
| @@ -10935,6 +11052,8 @@ x_make_frame_visible (struct frame *f) | |||
| 10935 | will set it when they are handled. */ | 11052 | will set it when they are handled. */ |
| 10936 | bool previously_visible = f->output_data.x->has_been_visible; | 11053 | bool previously_visible = f->output_data.x->has_been_visible; |
| 10937 | 11054 | ||
| 11055 | XSETFRAME (frame, f); | ||
| 11056 | |||
| 10938 | original_left = f->left_pos; | 11057 | original_left = f->left_pos; |
| 10939 | original_top = f->top_pos; | 11058 | original_top = f->top_pos; |
| 10940 | 11059 | ||
| @@ -10981,8 +11100,6 @@ x_make_frame_visible (struct frame *f) | |||
| 10981 | unblock_input (); | 11100 | unblock_input (); |
| 10982 | } | 11101 | } |
| 10983 | 11102 | ||
| 10984 | XSETFRAME (frame, f); | ||
| 10985 | |||
| 10986 | /* Process X events until a MapNotify event has been seen. */ | 11103 | /* Process X events until a MapNotify event has been seen. */ |
| 10987 | while (!FRAME_VISIBLE_P (f)) | 11104 | while (!FRAME_VISIBLE_P (f)) |
| 10988 | { | 11105 | { |
| @@ -11227,6 +11344,7 @@ x_free_frame_resources (struct frame *f) | |||
| 11227 | font-driver (e.g. xft) access a window while finishing a | 11344 | font-driver (e.g. xft) access a window while finishing a |
| 11228 | face. */ | 11345 | face. */ |
| 11229 | free_frame_faces (f); | 11346 | free_frame_faces (f); |
| 11347 | tear_down_x_back_buffer (f); | ||
| 11230 | 11348 | ||
| 11231 | if (f->output_data.x->icon_desc) | 11349 | if (f->output_data.x->icon_desc) |
| 11232 | XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc); | 11350 | XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc); |
| @@ -11258,7 +11376,7 @@ x_free_frame_resources (struct frame *f) | |||
| 11258 | /* Tooltips don't have widgets, only a simple X window, even if | 11376 | /* Tooltips don't have widgets, only a simple X window, even if |
| 11259 | we are using a toolkit. */ | 11377 | we are using a toolkit. */ |
| 11260 | else if (FRAME_X_WINDOW (f)) | 11378 | else if (FRAME_X_WINDOW (f)) |
| 11261 | XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); | 11379 | XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); |
| 11262 | 11380 | ||
| 11263 | free_frame_menubar (f); | 11381 | free_frame_menubar (f); |
| 11264 | 11382 | ||
| @@ -11270,8 +11388,9 @@ x_free_frame_resources (struct frame *f) | |||
| 11270 | xg_free_frame_widgets (f); | 11388 | xg_free_frame_widgets (f); |
| 11271 | #endif /* USE_GTK */ | 11389 | #endif /* USE_GTK */ |
| 11272 | 11390 | ||
| 11391 | tear_down_x_back_buffer (f); | ||
| 11273 | if (FRAME_X_WINDOW (f)) | 11392 | if (FRAME_X_WINDOW (f)) |
| 11274 | XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); | 11393 | XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); |
| 11275 | #endif /* !USE_X_TOOLKIT */ | 11394 | #endif /* !USE_X_TOOLKIT */ |
| 11276 | 11395 | ||
| 11277 | unload_color (f, FRAME_FOREGROUND_PIXEL (f)); | 11396 | unload_color (f, FRAME_FOREGROUND_PIXEL (f)); |
| @@ -12111,7 +12230,15 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 12111 | } | 12230 | } |
| 12112 | else | 12231 | else |
| 12113 | dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window, | 12232 | dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window, |
| 12114 | dpyinfo->visual, AllocNone); | 12233 | dpyinfo->visual, AllocNone); |
| 12234 | |||
| 12235 | #ifdef HAVE_XDBE | ||
| 12236 | dpyinfo->supports_xdbe = false; | ||
| 12237 | int xdbe_major; | ||
| 12238 | int xdbe_minor; | ||
| 12239 | if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor)) | ||
| 12240 | dpyinfo->supports_xdbe = true; | ||
| 12241 | #endif | ||
| 12115 | 12242 | ||
| 12116 | #ifdef HAVE_XFT | 12243 | #ifdef HAVE_XFT |
| 12117 | { | 12244 | { |
| @@ -12462,7 +12589,7 @@ static struct redisplay_interface x_redisplay_interface = | |||
| 12462 | x_after_update_window_line, | 12589 | x_after_update_window_line, |
| 12463 | x_update_window_begin, | 12590 | x_update_window_begin, |
| 12464 | x_update_window_end, | 12591 | x_update_window_end, |
| 12465 | x_flush, | 12592 | x_flip_and_flush, |
| 12466 | x_clear_window_mouse_face, | 12593 | x_clear_window_mouse_face, |
| 12467 | x_get_glyph_overhangs, | 12594 | x_get_glyph_overhangs, |
| 12468 | x_fix_overlapping_area, | 12595 | x_fix_overlapping_area, |
| @@ -12592,6 +12719,7 @@ x_create_terminal (struct x_display_info *dpyinfo) | |||
| 12592 | terminal->update_end_hook = x_update_end; | 12719 | terminal->update_end_hook = x_update_end; |
| 12593 | terminal->read_socket_hook = XTread_socket; | 12720 | terminal->read_socket_hook = XTread_socket; |
| 12594 | terminal->frame_up_to_date_hook = XTframe_up_to_date; | 12721 | terminal->frame_up_to_date_hook = XTframe_up_to_date; |
| 12722 | terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook; | ||
| 12595 | terminal->mouse_position_hook = XTmouse_position; | 12723 | terminal->mouse_position_hook = XTmouse_position; |
| 12596 | terminal->frame_rehighlight_hook = XTframe_rehighlight; | 12724 | terminal->frame_rehighlight_hook = XTframe_rehighlight; |
| 12597 | terminal->frame_raise_lower_hook = XTframe_raise_lower; | 12725 | terminal->frame_raise_lower_hook = XTframe_raise_lower; |
diff --git a/src/xterm.h b/src/xterm.h index 675a48443dc..01d7efc6dc8 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -475,6 +475,10 @@ struct x_display_info | |||
| 475 | #ifdef USE_XCB | 475 | #ifdef USE_XCB |
| 476 | xcb_connection_t *xcb_connection; | 476 | xcb_connection_t *xcb_connection; |
| 477 | #endif | 477 | #endif |
| 478 | |||
| 479 | #ifdef HAVE_XDBE | ||
| 480 | bool supports_xdbe; | ||
| 481 | #endif | ||
| 478 | }; | 482 | }; |
| 479 | 483 | ||
| 480 | #ifdef HAVE_X_I18N | 484 | #ifdef HAVE_X_I18N |
| @@ -527,6 +531,16 @@ struct x_output | |||
| 527 | and the X window has not yet been created. */ | 531 | and the X window has not yet been created. */ |
| 528 | Window window_desc; | 532 | Window window_desc; |
| 529 | 533 | ||
| 534 | /* The drawable to which we're rendering. In the single-buffered | ||
| 535 | base, the window itself. In the double-buffered case, the | ||
| 536 | window's back buffer. */ | ||
| 537 | Drawable draw_desc; | ||
| 538 | |||
| 539 | /* Flag that indicates whether we've modified the back buffer and | ||
| 540 | need to publish our modifications to the front buffer at a | ||
| 541 | convenient time. */ | ||
| 542 | bool need_buffer_flip; | ||
| 543 | |||
| 530 | /* The X window used for the bitmap icon; | 544 | /* The X window used for the bitmap icon; |
| 531 | or 0 if we don't have a bitmap icon. */ | 545 | or 0 if we don't have a bitmap icon. */ |
| 532 | Window icon_desc; | 546 | Window icon_desc; |
| @@ -737,6 +751,24 @@ enum | |||
| 737 | /* Return the X window used for displaying data in frame F. */ | 751 | /* Return the X window used for displaying data in frame F. */ |
| 738 | #define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc) | 752 | #define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc) |
| 739 | 753 | ||
| 754 | /* Return the drawable used for rendering to frame F. */ | ||
| 755 | #define FRAME_X_RAW_DRAWABLE(f) ((f)->output_data.x->draw_desc) | ||
| 756 | |||
| 757 | extern void x_mark_frame_dirty (struct frame *f); | ||
| 758 | |||
| 759 | /* Return the drawable used for rendering to frame F and mark the | ||
| 760 | frame as needing a buffer flip later. There's no easy way to run | ||
| 761 | code after any drawing command, but we can run code whenever | ||
| 762 | someone asks for the handle necessary to draw. */ | ||
| 763 | #define FRAME_X_DRAWABLE(f) \ | ||
| 764 | (x_mark_frame_dirty((f)), FRAME_X_RAW_DRAWABLE ((f))) | ||
| 765 | |||
| 766 | #define FRAME_X_DOUBLE_BUFFERED_P(f) \ | ||
| 767 | (FRAME_X_WINDOW (f) != FRAME_X_RAW_DRAWABLE (f)) | ||
| 768 | |||
| 769 | /* Return the need-buffer-flip flag for frame F. */ | ||
| 770 | #define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip) | ||
| 771 | |||
| 740 | /* Return the outermost X window associated with the frame F. */ | 772 | /* Return the outermost X window associated with the frame F. */ |
| 741 | #ifdef USE_X_TOOLKIT | 773 | #ifdef USE_X_TOOLKIT |
| 742 | #define FRAME_OUTER_WINDOW(f) ((f)->output_data.x->widget ? \ | 774 | #define FRAME_OUTER_WINDOW(f) ((f)->output_data.x->widget ? \ |
| @@ -1140,6 +1172,9 @@ extern bool x_wm_supports (struct frame *, Atom); | |||
| 1140 | extern void x_wait_for_event (struct frame *, int); | 1172 | extern void x_wait_for_event (struct frame *, int); |
| 1141 | extern void x_clear_under_internal_border (struct frame *f); | 1173 | extern void x_clear_under_internal_border (struct frame *f); |
| 1142 | 1174 | ||
| 1175 | extern void tear_down_x_back_buffer (struct frame *f); | ||
| 1176 | extern void initial_set_up_x_back_buffer (struct frame *f); | ||
| 1177 | |||
| 1143 | /* Defined in xselect.c. */ | 1178 | /* Defined in xselect.c. */ |
| 1144 | 1179 | ||
| 1145 | extern void x_handle_property_notify (const XPropertyEvent *); | 1180 | extern void x_handle_property_notify (const XPropertyEvent *); |