mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-02-01 20:06:00 +00:00
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
This commit is contained in:
parent
f5543ffcf5
commit
c29071587c
18
configure.ac
18
configure.ac
@ -3712,6 +3712,24 @@ fi
|
||||
AC_SUBST(XFIXES_CFLAGS)
|
||||
AC_SUBST(XFIXES_LIBS)
|
||||
|
||||
### Use Xdbe (-lXdbe) if available
|
||||
HAVE_XDBE=no
|
||||
if test "${HAVE_X11}" = "yes"; then
|
||||
AC_CHECK_HEADER(X11/extensions/Xdbe.h,
|
||||
[AC_CHECK_LIB(Xext, XdbeAllocateBackBufferName, HAVE_XDBE=yes)],
|
||||
[],
|
||||
[#include <X11/Xlib.h>
|
||||
])
|
||||
if test $HAVE_XDBE = yes; then
|
||||
XDBE_LIBS=-lXext
|
||||
fi
|
||||
if test $HAVE_XDBE = yes; then
|
||||
AC_DEFINE(HAVE_XDBE, 1, [Define to 1 if you have the Xdbe extension.])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(XDBE_CFLAGS)
|
||||
AC_SUBST(XDBE_LIBS)
|
||||
|
||||
### Use libxml (-lxml2) if available
|
||||
### mingw32 doesn't use -lxml2, since it loads the library dynamically.
|
||||
HAVE_LIBXML2=no
|
||||
|
@ -1539,6 +1539,13 @@ prevent hanging with those window managers.
|
||||
If non-@code{nil}, the frame is visible on all virtual desktops on systems
|
||||
with virtual desktops.
|
||||
|
||||
@vindex inhibit-double-buffering, a frame parameter
|
||||
@item inhibit-double-buffering
|
||||
If non-@code{nil}, the frame is drawn to the screen without double buffering.
|
||||
Emacs normally attempts to use double buffering, where available, to
|
||||
reduce flicker. Set this property if you experience display bugs or
|
||||
pine for that retro, flicker-y feeling.
|
||||
|
||||
@ignore
|
||||
@vindex parent-id, a frame parameter
|
||||
@item parent-id
|
||||
@ -2210,6 +2217,12 @@ window manager. This happens below the level at which Emacs can exert
|
||||
any control, but Emacs does provide events that you can use to keep
|
||||
track of such changes. @xref{Misc Events}.
|
||||
|
||||
@defun x-double-buffered-p &optional frame
|
||||
This function returns non-@code{nil} if @var{frame} is currently
|
||||
being rendered with double buffering. @var{frame} defaults to the
|
||||
selected frame.
|
||||
@end defun
|
||||
|
||||
@node Raising and Lowering
|
||||
@section Raising and Lowering Frames
|
||||
|
||||
|
6
etc/NEWS
6
etc/NEWS
@ -66,6 +66,12 @@ affected by this, as SGI stopped supporting IRIX in December 2013.
|
||||
of curved quotes for 'electric-quote-mode', allowing user to choose
|
||||
the types of quotes to be used.
|
||||
|
||||
+++
|
||||
** Emacs now uses double buffering to reduce flicker when editing and
|
||||
resizing graphical Emacs frames on the X Window System. This support
|
||||
requires the DOUBLE-BUFFER extension, which major X servers have
|
||||
supported for many years.
|
||||
|
||||
---
|
||||
The group 'wp', whose label was "text", is now deprecated.
|
||||
Use the new group 'text', which inherits from 'wp', instead.
|
||||
|
@ -12,6 +12,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "XMenuInt.h"
|
||||
|
||||
int
|
||||
|
@ -13,6 +13,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "XMenuInt.h"
|
||||
|
||||
int
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <errno.h>
|
||||
#include "X10.h"
|
||||
|
@ -254,6 +254,9 @@ XINERAMA_CFLAGS = @XINERAMA_CFLAGS@
|
||||
XFIXES_LIBS = @XFIXES_LIBS@
|
||||
XFIXES_CFLAGS = @XFIXES_CFLAGS@
|
||||
|
||||
XDBE_LIBS = @XDBE_LIBS@
|
||||
XDBE_CFLAGS = @XDBE_CFLAGS@
|
||||
|
||||
## widget.o if USE_X_TOOLKIT, otherwise empty.
|
||||
WIDGET_OBJ=@WIDGET_OBJ@
|
||||
|
||||
@ -372,7 +375,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
|
||||
$(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
|
||||
$(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
|
||||
$(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
|
||||
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
|
||||
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \
|
||||
$(WEBKIT_CFLAGS) \
|
||||
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
|
||||
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
|
||||
@ -489,6 +492,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
|
||||
$(WEBKIT_LIBS) \
|
||||
$(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
|
||||
$(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
|
||||
$(XDBE_LIBS) \
|
||||
$(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
|
||||
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
|
||||
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
|
||||
|
@ -1276,7 +1276,6 @@ struct glyph_string
|
||||
|
||||
/* X display and window for convenience. */
|
||||
Display *display;
|
||||
Window window;
|
||||
|
||||
/* The glyph row for which this string was built. It determines the
|
||||
y-origin and height of the string. */
|
||||
@ -3357,6 +3356,10 @@ void x_cr_init_fringe (struct redisplay_interface *);
|
||||
|
||||
extern unsigned row_hash (struct glyph_row *);
|
||||
|
||||
extern void block_buffer_flips(void);
|
||||
extern void unblock_buffer_flips(void);
|
||||
extern bool buffer_flipping_blocked_p(void);
|
||||
|
||||
/* Defined in image.c */
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
|
10
src/font.c
10
src/font.c
@ -5274,6 +5274,16 @@ font_deferred_log (const char *action, Lisp_Object arg, Lisp_Object result)
|
||||
ASET (Vfont_log_deferred, 2, result);
|
||||
}
|
||||
|
||||
void
|
||||
font_drop_xrender_surfaces (struct frame *f)
|
||||
{
|
||||
struct font_driver_list *list;
|
||||
|
||||
for (list = f->font_driver_list; list; list = list->next)
|
||||
if (list->on && list->driver->drop_xrender_surfaces)
|
||||
list->driver->drop_xrender_surfaces (f);
|
||||
}
|
||||
|
||||
void
|
||||
syms_of_font (void)
|
||||
{
|
||||
|
11
src/font.h
11
src/font.h
@ -763,6 +763,13 @@ struct font_driver
|
||||
Return non-nil if the driver support rendering of combining
|
||||
characters for FONT according to Unicode combining class. */
|
||||
Lisp_Object (*combining_capability) (struct font *font);
|
||||
|
||||
/* Optional
|
||||
|
||||
Called when frame F is double-buffered and its size changes; Xft
|
||||
relies on this hook to throw away its old XftDraw (which won't
|
||||
work after the size change) and get a new one. */
|
||||
void (*drop_xrender_surfaces) (struct frame *f);
|
||||
};
|
||||
|
||||
|
||||
@ -862,7 +869,9 @@ extern void *font_get_frame_data (struct frame *f, Lisp_Object);
|
||||
extern void font_filter_properties (Lisp_Object font,
|
||||
Lisp_Object alist,
|
||||
const char *const boolean_properties[],
|
||||
const char *const non_boolean_properties[]);
|
||||
const char *const non_boolean_properties[]);
|
||||
|
||||
extern void font_drop_xrender_surfaces (struct frame *f);
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
extern struct font_driver ftfont_driver;
|
||||
|
@ -3128,6 +3128,7 @@ static const struct frame_parm_table frame_parms[] =
|
||||
{"alpha", SYMBOL_INDEX (Qalpha)},
|
||||
{"sticky", SYMBOL_INDEX (Qsticky)},
|
||||
{"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
|
||||
{"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
|
||||
};
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
@ -5044,6 +5045,7 @@ syms_of_frame (void)
|
||||
DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
|
||||
DEFSYM (Qvisibility, "visibility");
|
||||
DEFSYM (Qwait_for_wm, "wait-for-wm");
|
||||
DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
|
||||
|
||||
{
|
||||
int i;
|
||||
|
@ -95,7 +95,7 @@ ftxfont_get_gcs (struct frame *f, unsigned long foreground, unsigned long backgr
|
||||
if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
|
||||
break;
|
||||
xgcv.foreground = color.pixel;
|
||||
new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
GCForeground, &xgcv);
|
||||
}
|
||||
unblock_input ();
|
||||
@ -139,14 +139,14 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
|
||||
p[n[0]].y = y - bitmap.top + i;
|
||||
if (++n[0] == size)
|
||||
{
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
gc_fore, p, size, CoordModeOrigin);
|
||||
n[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flush && n[0] > 0)
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
gc_fore, p, n[0], CoordModeOrigin);
|
||||
}
|
||||
else
|
||||
@ -168,7 +168,7 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
|
||||
pp[n[idx]].y = y - bitmap.top + i;
|
||||
if (++(n[idx]) == size)
|
||||
{
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
idx == 6 ? gc_fore : gcs[idx], pp, size,
|
||||
CoordModeOrigin);
|
||||
n[idx] = 0;
|
||||
@ -180,10 +180,10 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
|
||||
{
|
||||
for (i = 0; i < 6; i++)
|
||||
if (n[i] > 0)
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
|
||||
if (n[6] > 0)
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
gc_fore, p + 0x600, n[6], CoordModeOrigin);
|
||||
}
|
||||
}
|
||||
@ -203,7 +203,7 @@ ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y
|
||||
XGetGCValues (FRAME_X_DISPLAY (f), gc,
|
||||
GCForeground | GCBackground, &xgcv);
|
||||
XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
|
||||
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
|
||||
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
|
||||
x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
|
||||
XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
|
||||
}
|
||||
|
167
src/gtkutil.c
167
src/gtkutil.c
@ -48,6 +48,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "emacsgtkfixed.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XDBE
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
|
||||
#define gtk_widget_set_has_window(w, b) \
|
||||
(gtk_fixed_set_has_window (GTK_FIXED (w), b))
|
||||
@ -143,6 +147,8 @@ struct xg_frame_tb_info
|
||||
GtkTextDirection dir;
|
||||
};
|
||||
|
||||
static GtkWidget * xg_get_widget_from_map (ptrdiff_t idx);
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Display handling functions
|
||||
@ -815,12 +821,6 @@ xg_clear_under_internal_border (struct frame *f)
|
||||
{
|
||||
if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
|
||||
{
|
||||
#ifndef USE_CAIRO
|
||||
GtkWidget *wfixed = f->output_data.x->edit_widget;
|
||||
|
||||
gtk_widget_queue_draw (wfixed);
|
||||
gdk_window_process_all_updates ();
|
||||
#endif
|
||||
x_clear_area (f, 0, 0,
|
||||
FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
|
||||
|
||||
@ -1233,6 +1233,7 @@ xg_create_frame_widgets (struct frame *f)
|
||||
by callers of this function. */
|
||||
gtk_widget_realize (wfixed);
|
||||
FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed);
|
||||
initial_set_up_x_back_buffer (f);
|
||||
|
||||
/* Since GTK clears its window by filling with the background color,
|
||||
we must keep X and GTK background in sync. */
|
||||
@ -1296,8 +1297,11 @@ xg_free_frame_widgets (struct frame *f)
|
||||
if (tbinfo)
|
||||
xfree (tbinfo);
|
||||
|
||||
/* x_free_frame_resources should have taken care of it */
|
||||
eassert (!FRAME_X_DOUBLE_BUFFERED_P (f));
|
||||
gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
|
||||
FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
|
||||
FRAME_X_RAW_DRAWABLE (f) = 0;
|
||||
FRAME_GTK_OUTER_WIDGET (f) = 0;
|
||||
#ifdef USE_GTK_TOOLTIP
|
||||
if (x->ttip_lbl)
|
||||
@ -1440,6 +1444,18 @@ xg_set_background_color (struct frame *f, unsigned long bg)
|
||||
{
|
||||
block_input ();
|
||||
xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f));
|
||||
|
||||
Lisp_Object bar;
|
||||
for (bar = FRAME_SCROLL_BARS (f);
|
||||
!NILP (bar);
|
||||
bar = XSCROLL_BAR (bar)->next)
|
||||
{
|
||||
GtkWidget *scrollbar =
|
||||
xg_get_widget_from_map (XSCROLL_BAR (bar)->x_window);
|
||||
GtkWidget *webox = gtk_widget_get_parent (scrollbar);
|
||||
xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f));
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
}
|
||||
}
|
||||
@ -2265,7 +2281,6 @@ xg_mark_data (void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Callback called when a menu item is destroyed. Used to free data.
|
||||
W is the widget that is being destroyed (not used).
|
||||
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)
|
||||
xg_remove_widget_from_map (id);
|
||||
}
|
||||
|
||||
/* Create a scroll bar widget for frame F. Store the scroll bar
|
||||
in BAR.
|
||||
SCROLL_CALLBACK is the callback to invoke when the value of the
|
||||
bar changes.
|
||||
END_CALLBACK is the callback to invoke when scrolling ends.
|
||||
SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used
|
||||
to set resources for the widget. */
|
||||
|
||||
void
|
||||
xg_create_scroll_bar (struct frame *f,
|
||||
struct scroll_bar *bar,
|
||||
GCallback scroll_callback,
|
||||
GCallback end_callback,
|
||||
const char *scroll_bar_name)
|
||||
static void
|
||||
xg_finish_scroll_bar_creation (struct frame *f,
|
||||
GtkWidget *wscroll,
|
||||
struct scroll_bar *bar,
|
||||
GCallback scroll_callback,
|
||||
GCallback end_callback,
|
||||
const char *scroll_bar_name)
|
||||
{
|
||||
GtkWidget *wscroll;
|
||||
GtkWidget *webox;
|
||||
intptr_t scroll_id;
|
||||
#ifdef HAVE_GTK3
|
||||
GtkAdjustment *vadj;
|
||||
#else
|
||||
GtkObject *vadj;
|
||||
#endif
|
||||
GtkWidget *webox = gtk_event_box_new ();
|
||||
|
||||
/* Page, step increment values are not so important here, they
|
||||
will be corrected in x_set_toolkit_scroll_bar_thumb. */
|
||||
vadj = gtk_adjustment_new (XG_SB_MIN, XG_SB_MIN, XG_SB_MAX,
|
||||
0.1, 0.1, 0.1);
|
||||
|
||||
wscroll = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (vadj));
|
||||
webox = gtk_event_box_new ();
|
||||
gtk_widget_set_name (wscroll, scroll_bar_name);
|
||||
#ifndef HAVE_GTK3
|
||||
gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
|
||||
#endif
|
||||
g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
|
||||
|
||||
scroll_id = xg_store_widget_in_map (wscroll);
|
||||
ptrdiff_t scroll_id = xg_store_widget_in_map (wscroll);
|
||||
|
||||
g_signal_connect (G_OBJECT (wscroll),
|
||||
"destroy",
|
||||
@ -3630,11 +3624,52 @@ xg_create_scroll_bar (struct frame *f,
|
||||
gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1);
|
||||
gtk_container_add (GTK_CONTAINER (webox), wscroll);
|
||||
|
||||
xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f));
|
||||
|
||||
/* N.B. The event box doesn't become a real X11 window until we ask
|
||||
for its XID via GTK_WIDGET_TO_X_WIN. If the event box is not a
|
||||
real X window, it and its scroll-bar child try to draw on the
|
||||
Emacs main window, which we draw over using Xlib. */
|
||||
gtk_widget_realize (webox);
|
||||
GTK_WIDGET_TO_X_WIN (webox);
|
||||
|
||||
/* Set the cursor to an arrow. */
|
||||
xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
|
||||
|
||||
bar->x_window = scroll_id;
|
||||
}
|
||||
|
||||
/* Create a scroll bar widget for frame F. Store the scroll bar
|
||||
in BAR.
|
||||
SCROLL_CALLBACK is the callback to invoke when the value of the
|
||||
bar changes.
|
||||
END_CALLBACK is the callback to invoke when scrolling ends.
|
||||
SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used
|
||||
to set resources for the widget. */
|
||||
|
||||
void
|
||||
xg_create_scroll_bar (struct frame *f,
|
||||
struct scroll_bar *bar,
|
||||
GCallback scroll_callback,
|
||||
GCallback end_callback,
|
||||
const char *scroll_bar_name)
|
||||
{
|
||||
GtkWidget *wscroll;
|
||||
#ifdef HAVE_GTK3
|
||||
GtkAdjustment *vadj;
|
||||
#else
|
||||
GtkObject *vadj;
|
||||
#endif
|
||||
|
||||
/* Page, step increment values are not so important here, they
|
||||
will be corrected in x_set_toolkit_scroll_bar_thumb. */
|
||||
vadj = gtk_adjustment_new (XG_SB_MIN, XG_SB_MIN, XG_SB_MAX,
|
||||
0.1, 0.1, 0.1);
|
||||
|
||||
wscroll = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (vadj));
|
||||
|
||||
xg_finish_scroll_bar_creation (f, wscroll, bar, scroll_callback,
|
||||
end_callback, scroll_bar_name);
|
||||
bar->horizontal = 0;
|
||||
}
|
||||
|
||||
@ -3652,8 +3687,6 @@ xg_create_horizontal_scroll_bar (struct frame *f,
|
||||
const char *scroll_bar_name)
|
||||
{
|
||||
GtkWidget *wscroll;
|
||||
GtkWidget *webox;
|
||||
intptr_t scroll_id;
|
||||
#ifdef HAVE_GTK3
|
||||
GtkAdjustment *hadj;
|
||||
#else
|
||||
@ -3666,42 +3699,9 @@ xg_create_horizontal_scroll_bar (struct frame *f,
|
||||
0.1, 0.1, 0.1);
|
||||
|
||||
wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj));
|
||||
webox = gtk_event_box_new ();
|
||||
gtk_widget_set_name (wscroll, scroll_bar_name);
|
||||
#ifndef HAVE_GTK3
|
||||
gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
|
||||
#endif
|
||||
g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
|
||||
|
||||
scroll_id = xg_store_widget_in_map (wscroll);
|
||||
|
||||
g_signal_connect (G_OBJECT (wscroll),
|
||||
"destroy",
|
||||
G_CALLBACK (xg_gtk_scroll_destroy),
|
||||
(gpointer) scroll_id);
|
||||
g_signal_connect (G_OBJECT (wscroll),
|
||||
"change-value",
|
||||
scroll_callback,
|
||||
(gpointer) bar);
|
||||
g_signal_connect (G_OBJECT (wscroll),
|
||||
"button-release-event",
|
||||
end_callback,
|
||||
(gpointer) bar);
|
||||
|
||||
/* The scroll bar widget does not draw on a window of its own. Instead
|
||||
it draws on the parent window, in this case the edit widget. So
|
||||
whenever the edit widget is cleared, the scroll bar needs to redraw
|
||||
also, which causes flicker. Put an event box between the edit widget
|
||||
and the scroll bar, so the scroll bar instead draws itself on the
|
||||
event box window. */
|
||||
gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1);
|
||||
gtk_container_add (GTK_CONTAINER (webox), wscroll);
|
||||
|
||||
|
||||
/* Set the cursor to an arrow. */
|
||||
xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
|
||||
|
||||
bar->x_window = scroll_id;
|
||||
xg_finish_scroll_bar_creation (f, wscroll, bar, scroll_callback,
|
||||
end_callback, scroll_bar_name);
|
||||
bar->horizontal = 1;
|
||||
}
|
||||
|
||||
@ -3770,16 +3770,10 @@ xg_update_scrollbar_pos (struct frame *f,
|
||||
gtk_widget_show_all (wparent);
|
||||
gtk_widget_set_size_request (wscroll, width, height);
|
||||
}
|
||||
#ifndef USE_CAIRO
|
||||
gtk_widget_queue_draw (wfixed);
|
||||
gdk_window_process_all_updates ();
|
||||
#endif
|
||||
if (oldx != -1 && oldw > 0 && oldh > 0)
|
||||
{
|
||||
/* Clear under old scroll bar position. This must be done after
|
||||
the gtk_widget_queue_draw and gdk_window_process_all_updates
|
||||
above. */
|
||||
oldw += (scale - 1) * oldw;
|
||||
/* Clear under old scroll bar position. */
|
||||
oldw += (scale - 1) * oldw;
|
||||
oldx -= (scale - 1) * oldw;
|
||||
x_clear_area (f, oldx, oldy, oldw, oldh);
|
||||
}
|
||||
@ -3841,14 +3835,9 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
|
||||
gtk_widget_show_all (wparent);
|
||||
gtk_widget_set_size_request (wscroll, width, height);
|
||||
}
|
||||
gtk_widget_queue_draw (wfixed);
|
||||
gdk_window_process_all_updates ();
|
||||
if (oldx != -1 && oldw > 0 && oldh > 0)
|
||||
/* Clear under old scroll bar position. This must be done after
|
||||
the gtk_widget_queue_draw and gdk_window_process_all_updates
|
||||
above. */
|
||||
x_clear_area (f,
|
||||
oldx, oldy, oldw, oldh);
|
||||
/* Clear under old scroll bar position. */
|
||||
x_clear_area (f, oldx, oldy, oldw, oldh);
|
||||
|
||||
/* GTK does not redraw until the main loop is entered again, but
|
||||
if there are no X events pending we will not enter it. So we sync
|
||||
|
20
src/image.c
20
src/image.c
@ -220,7 +220,7 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi
|
||||
|
||||
#ifdef HAVE_X_WINDOWS
|
||||
Pixmap bitmap;
|
||||
bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
bits, width, height);
|
||||
if (! bitmap)
|
||||
return -1;
|
||||
@ -327,7 +327,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
|
||||
|
||||
filename = SSDATA (found);
|
||||
|
||||
result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
filename, &width, &height, &bitmap, &xhot, &yhot);
|
||||
if (result != BitmapSuccess)
|
||||
return -1;
|
||||
@ -1952,7 +1952,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
|
||||
{
|
||||
#ifdef HAVE_X_WINDOWS
|
||||
Display *display = FRAME_X_DISPLAY (f);
|
||||
Window window = FRAME_X_WINDOW (f);
|
||||
Drawable drawable = FRAME_X_DRAWABLE (f);
|
||||
Screen *screen = FRAME_X_SCREEN (f);
|
||||
|
||||
eassert (input_blocked_p ());
|
||||
@ -1981,7 +1981,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
|
||||
(*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height);
|
||||
|
||||
/* Allocate a pixmap of the same size. */
|
||||
*pixmap = XCreatePixmap (display, window, width, height, depth);
|
||||
*pixmap = XCreatePixmap (display, drawable, width, height, depth);
|
||||
if (*pixmap == NO_PIXMAP)
|
||||
{
|
||||
x_destroy_x_image (*ximg);
|
||||
@ -2742,7 +2742,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
|
||||
img->pixmap =
|
||||
(x_check_image_size (0, img->width, img->height)
|
||||
? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f),
|
||||
FRAME_X_DRAWABLE (f),
|
||||
data,
|
||||
img->width, img->height,
|
||||
fg, bg,
|
||||
@ -3520,7 +3520,7 @@ x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
|
||||
xpm_init_color_cache (f, &attrs);
|
||||
#endif
|
||||
|
||||
rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
(char **) bits, &bitmap, &mask, &attrs);
|
||||
if (rc != XpmSuccess)
|
||||
{
|
||||
@ -3758,7 +3758,7 @@ xpm_load (struct frame *f, struct image *img)
|
||||
#ifdef HAVE_X_WINDOWS
|
||||
if (rc == XpmSuccess)
|
||||
{
|
||||
img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
img->ximg->width, img->ximg->height,
|
||||
img->ximg->depth);
|
||||
if (img->pixmap == NO_PIXMAP)
|
||||
@ -3768,7 +3768,7 @@ xpm_load (struct frame *f, struct image *img)
|
||||
}
|
||||
else if (img->mask_img)
|
||||
{
|
||||
img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
img->mask_img->width,
|
||||
img->mask_img->height,
|
||||
img->mask_img->depth);
|
||||
@ -9541,7 +9541,7 @@ gs_load (struct frame *f, struct image *img)
|
||||
{
|
||||
/* Only W32 version did BLOCK_INPUT here. ++kfs */
|
||||
block_input ();
|
||||
img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
img->width, img->height,
|
||||
DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
|
||||
unblock_input ();
|
||||
@ -9557,7 +9557,7 @@ gs_load (struct frame *f, struct image *img)
|
||||
if successful. We do not record_unwind_protect here because
|
||||
other places in redisplay like calling window scroll functions
|
||||
don't either. Let the Lisp loader use `unwind-protect' instead. */
|
||||
printnum1 = FRAME_X_WINDOW (f);
|
||||
printnum1 = FRAME_X_DRAWABLE (f);
|
||||
printnum2 = img->pixmap;
|
||||
window_and_pixmap_id
|
||||
= make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
|
||||
|
@ -971,6 +971,7 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
|
||||
x_set_alpha,
|
||||
0, /* x_set_sticky */
|
||||
0, /* x_set_tool_bar_position */
|
||||
0, /* x_set_inhibit_double_buffering */
|
||||
};
|
||||
|
||||
|
||||
|
@ -631,6 +631,11 @@ struct terminal
|
||||
/* Called when a frame's display becomes entirely up to date. */
|
||||
void (*frame_up_to_date_hook) (struct frame *);
|
||||
|
||||
/* Called when buffer flipping becomes unblocked after having
|
||||
previously been blocked. Redisplay always blocks buffer flips
|
||||
while it runs. */
|
||||
void (*buffer_flipping_unblocked_hook) (struct frame *);
|
||||
|
||||
|
||||
/* Called to delete the device-specific portions of a frame that is
|
||||
on this terminal device. */
|
||||
|
@ -9757,6 +9757,7 @@ frame_parm_handler w32_frame_parm_handlers[] =
|
||||
x_set_alpha,
|
||||
0, /* x_set_sticky */
|
||||
0, /* x_set_tool_bar_position */
|
||||
0, /* x_set_inhibit_double_buffering */
|
||||
};
|
||||
|
||||
void
|
||||
|
69
src/xdisp.c
69
src/xdisp.c
@ -2501,7 +2501,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
|
||||
|
||||
/* Visible feedback for debugging. */
|
||||
#if false && defined HAVE_X_WINDOWS
|
||||
XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
f->output_data.x->normal_gc,
|
||||
gx, gy, width, height);
|
||||
#endif
|
||||
@ -11349,7 +11349,7 @@ clear_garbaged_frames (void)
|
||||
fset_redisplay (f);
|
||||
f->garbaged = false;
|
||||
f->resized_p = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frame_garbaged = false;
|
||||
@ -13573,6 +13573,7 @@ redisplay_internal (void)
|
||||
count = SPECPDL_INDEX ();
|
||||
record_unwind_protect_void (unwind_redisplay);
|
||||
redisplaying_p = true;
|
||||
block_buffer_flips ();
|
||||
specbind (Qinhibit_free_realized_faces, Qnil);
|
||||
|
||||
/* Record this function, so it appears on the profiler's backtraces. */
|
||||
@ -14070,7 +14071,23 @@ redisplay_internal (void)
|
||||
use them in update_frame will segfault.
|
||||
Therefore, we must redisplay this frame. */
|
||||
if (!f_redisplay_flag && f->redisplay)
|
||||
goto retry_frame;
|
||||
goto retry_frame;
|
||||
|
||||
/* In some case (e.g., window resize), we notice
|
||||
only during window updating that the window
|
||||
content changed unpredictably (e.g., a GTK
|
||||
scrollbar moved) and that our previous estimation
|
||||
of the frame content was garbage. We have to
|
||||
start over. These cases should be rare, so going
|
||||
all the way back to the top of redisplay should
|
||||
be good enough.
|
||||
|
||||
Why FRAME_WINDOW_P? See
|
||||
https://lists.gnu.org/archive/html/emacs-devel/2016-10/msg00957.html
|
||||
|
||||
*/
|
||||
if (FRAME_GARBAGED_P (f) && FRAME_WINDOW_P (f))
|
||||
goto retry;
|
||||
|
||||
/* Prevent various kinds of signals during display
|
||||
update. stdio is not robust about handling
|
||||
@ -14297,6 +14314,11 @@ redisplay_internal (void)
|
||||
RESUME_POLLING;
|
||||
}
|
||||
|
||||
static void
|
||||
unwind_redisplay_preserve_echo_area (void)
|
||||
{
|
||||
unblock_buffer_flips ();
|
||||
}
|
||||
|
||||
/* Redisplay, but leave alone any recent echo area message unless
|
||||
another message has been requested in its place.
|
||||
@ -14314,6 +14336,12 @@ redisplay_preserve_echo_area (int from_where)
|
||||
{
|
||||
TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where));
|
||||
|
||||
block_input ();
|
||||
ptrdiff_t count = SPECPDL_INDEX ();
|
||||
record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
|
||||
block_buffer_flips ();
|
||||
unblock_input ();
|
||||
|
||||
if (!NILP (echo_area_buffer[1]))
|
||||
{
|
||||
/* We have a previously displayed message, but no current
|
||||
@ -14326,6 +14354,7 @@ redisplay_preserve_echo_area (int from_where)
|
||||
redisplay_internal ();
|
||||
|
||||
flush_frame (SELECTED_FRAME ());
|
||||
unbind_to (count, Qnil);
|
||||
}
|
||||
|
||||
|
||||
@ -14335,6 +14364,7 @@ static void
|
||||
unwind_redisplay (void)
|
||||
{
|
||||
redisplaying_p = false;
|
||||
unblock_buffer_flips ();
|
||||
}
|
||||
|
||||
|
||||
@ -14444,6 +14474,38 @@ disp_char_vector (struct Lisp_Char_Table *dp, int c)
|
||||
return val;
|
||||
}
|
||||
|
||||
static int buffer_flip_blocked_depth;
|
||||
|
||||
void
|
||||
block_buffer_flips(void)
|
||||
{
|
||||
eassert (buffer_flip_blocked_depth >= 0);
|
||||
buffer_flip_blocked_depth++;
|
||||
}
|
||||
|
||||
void
|
||||
unblock_buffer_flips(void)
|
||||
{
|
||||
eassert (buffer_flip_blocked_depth > 0);
|
||||
if (--buffer_flip_blocked_depth == 0)
|
||||
{
|
||||
Lisp_Object tail, frame;
|
||||
block_input ();
|
||||
FOR_EACH_FRAME (tail, frame)
|
||||
{
|
||||
struct frame *f = XFRAME (frame);
|
||||
if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
|
||||
(*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
|
||||
}
|
||||
unblock_input ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
buffer_flipping_blocked_p (void)
|
||||
{
|
||||
return buffer_flip_blocked_depth > 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
@ -24626,7 +24688,6 @@ init_glyph_string (struct glyph_string *s,
|
||||
s->hdc = hdc;
|
||||
#endif
|
||||
s->display = FRAME_X_DISPLAY (s->f);
|
||||
s->window = FRAME_X_WINDOW (s->f);
|
||||
s->char2b = char2b;
|
||||
s->hl = hl;
|
||||
s->row = row;
|
||||
|
@ -495,7 +495,7 @@ x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv)
|
||||
{
|
||||
GC gc;
|
||||
block_input ();
|
||||
gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgcv);
|
||||
gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), mask, xgcv);
|
||||
unblock_input ();
|
||||
IF_DEBUG (++ngcs);
|
||||
return gc;
|
||||
|
128
src/xfns.c
128
src/xfns.c
@ -53,6 +53,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "gtkutil.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XDBE
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_X_TOOLKIT
|
||||
#include <X11/Shell.h>
|
||||
|
||||
@ -114,6 +118,7 @@ static int dpyinfo_refcount;
|
||||
#endif
|
||||
|
||||
static struct x_display_info *x_display_info_for_name (Lisp_Object);
|
||||
static void set_up_x_back_buffer (struct frame *f);
|
||||
|
||||
/* Let the user specify an X display with a Lisp object.
|
||||
OBJECT may be nil, a frame or a terminal object.
|
||||
@ -701,6 +706,35 @@ x_set_tool_bar_position (struct frame *f,
|
||||
wrong_choice (choice, new_value);
|
||||
}
|
||||
|
||||
static void
|
||||
x_set_inhibit_double_buffering (struct frame *f,
|
||||
Lisp_Object new_value,
|
||||
Lisp_Object old_value)
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value))
|
||||
{
|
||||
bool want_double_buffering = NILP (new_value);
|
||||
bool was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
|
||||
/* font_drop_xrender_surfaces in xftfont does something only if
|
||||
we're double-buffered, so call font_drop_xrender_surfaces before
|
||||
and after any potential change. One of the calls will end up
|
||||
being a no-op. */
|
||||
if (want_double_buffering != was_double_buffered)
|
||||
font_drop_xrender_surfaces (f);
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f) && !want_double_buffering)
|
||||
tear_down_x_back_buffer (f);
|
||||
else if (!FRAME_X_DOUBLE_BUFFERED_P (f) && want_double_buffering)
|
||||
set_up_x_back_buffer (f);
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f) != was_double_buffered)
|
||||
{
|
||||
SET_FRAME_GARBAGED (f);
|
||||
font_drop_xrender_surfaces (f);
|
||||
}
|
||||
}
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
#ifdef USE_GTK
|
||||
|
||||
/* 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)
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
x_mark_frame_dirty (struct frame *f)
|
||||
{
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f))
|
||||
FRAME_X_NEED_BUFFER_FLIP (f) = true;
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_x_back_buffer (struct frame *f)
|
||||
{
|
||||
#ifdef HAVE_XDBE
|
||||
block_input ();
|
||||
if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
{
|
||||
FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
|
||||
if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
|
||||
{
|
||||
/* If allocating a back buffer fails, either because the
|
||||
server ran out of memory or we don't have the right kind
|
||||
of visual, just use single-buffered rendering. */
|
||||
x_catch_errors (FRAME_X_DISPLAY (f));
|
||||
FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName (
|
||||
FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f),
|
||||
XdbeCopied);
|
||||
if (x_had_errors_p (FRAME_X_DISPLAY (f)))
|
||||
FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
|
||||
x_uncatch_errors_after_check ();
|
||||
}
|
||||
}
|
||||
unblock_input ();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
tear_down_x_back_buffer (struct frame *f)
|
||||
{
|
||||
#ifdef HAVE_XDBE
|
||||
block_input ();
|
||||
if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
{
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
{
|
||||
XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_DRAWABLE (f));
|
||||
FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
|
||||
}
|
||||
}
|
||||
unblock_input ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set up double buffering if the frame parameters don't prohibit
|
||||
it. */
|
||||
void
|
||||
initial_set_up_x_back_buffer (struct frame *f)
|
||||
{
|
||||
block_input ();
|
||||
eassert (FRAME_X_WINDOW (f));
|
||||
FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
|
||||
if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
|
||||
set_up_x_back_buffer (f);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
#ifdef USE_X_TOOLKIT
|
||||
|
||||
/* Create and set up the X widget for frame F. */
|
||||
@ -2638,7 +2738,7 @@ x_window (struct frame *f, long window_prompting)
|
||||
f->output_data.x->parent_desc, 0, 0);
|
||||
|
||||
FRAME_X_WINDOW (f) = XtWindow (frame_widget);
|
||||
|
||||
initial_set_up_x_back_buffer (f);
|
||||
validate_x_resource_name ();
|
||||
|
||||
class_hints.res_name = SSDATA (Vx_resource_name);
|
||||
@ -2784,7 +2884,8 @@ x_window (struct frame *f)
|
||||
CopyFromParent, /* depth */
|
||||
InputOutput, /* class */
|
||||
FRAME_X_VISUAL (f),
|
||||
attribute_mask, &attributes);
|
||||
attribute_mask, &attributes);
|
||||
initial_set_up_x_back_buffer (f);
|
||||
|
||||
#ifdef HAVE_X_I18N
|
||||
if (use_xim)
|
||||
@ -2938,7 +3039,7 @@ x_make_gc (struct frame *f)
|
||||
gc_values.line_width = 0; /* Means 1 using fast algorithm. */
|
||||
f->output_data.x->normal_gc
|
||||
= XCreateGC (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f),
|
||||
FRAME_X_DRAWABLE (f),
|
||||
GCLineWidth | GCForeground | GCBackground,
|
||||
&gc_values);
|
||||
|
||||
@ -2947,7 +3048,7 @@ x_make_gc (struct frame *f)
|
||||
gc_values.background = FRAME_FOREGROUND_PIXEL (f);
|
||||
f->output_data.x->reverse_gc
|
||||
= XCreateGC (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f),
|
||||
FRAME_X_DRAWABLE (f),
|
||||
GCForeground | GCBackground | GCLineWidth,
|
||||
&gc_values);
|
||||
|
||||
@ -2956,7 +3057,7 @@ x_make_gc (struct frame *f)
|
||||
gc_values.background = f->output_data.x->cursor_pixel;
|
||||
gc_values.fill_style = FillOpaqueStippled;
|
||||
f->output_data.x->cursor_gc
|
||||
= XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
= XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
(GCForeground | GCBackground
|
||||
| GCFillStyle | GCLineWidth),
|
||||
&gc_values);
|
||||
@ -3463,6 +3564,9 @@ This function is an internal primitive--use `make-frame' instead. */)
|
||||
"waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
|
||||
x_default_parameter (f, parms, Qtool_bar_position,
|
||||
FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
|
||||
x_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
|
||||
"inhibitDoubleBuffering", "InhibitDoubleBuffering",
|
||||
RES_TYPE_BOOLEAN);
|
||||
|
||||
/* Compute the size of the X window. */
|
||||
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)
|
||||
/* Border. */
|
||||
f->border_width,
|
||||
CopyFromParent, InputOutput, CopyFromParent,
|
||||
mask, &attrs);
|
||||
mask, &attrs);
|
||||
initial_set_up_x_back_buffer (f);
|
||||
XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
|
||||
FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
@ -6213,6 +6318,15 @@ Value is t if tooltip was open, nil otherwise. */)
|
||||
return x_hide_tip (!tooltip_reuse_hidden_frame);
|
||||
}
|
||||
|
||||
DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
|
||||
0, 1, 0,
|
||||
doc: /* Return t if FRAME is being double buffered. */)
|
||||
(Lisp_Object frame)
|
||||
{
|
||||
struct frame *f = decode_live_frame (frame);
|
||||
return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
File selection dialog
|
||||
@ -6864,6 +6978,7 @@ frame_parm_handler x_frame_parm_handlers[] =
|
||||
x_set_alpha,
|
||||
x_set_sticky,
|
||||
x_set_tool_bar_position,
|
||||
x_set_inhibit_double_buffering,
|
||||
};
|
||||
|
||||
void
|
||||
@ -7080,6 +7195,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
|
||||
|
||||
defsubr (&Sx_show_tip);
|
||||
defsubr (&Sx_hide_tip);
|
||||
defsubr (&Sx_double_buffered_p);
|
||||
tip_timer = Qnil;
|
||||
staticpro (&tip_timer);
|
||||
tip_frame = Qnil;
|
||||
|
16
src/xfont.c
16
src/xfont.c
@ -1057,20 +1057,20 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
|
||||
{
|
||||
if (s->padding_p)
|
||||
for (i = 0; i < len; i++)
|
||||
XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
||||
XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
|
||||
gc, x + i, y, str + i, 1);
|
||||
else
|
||||
XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
||||
XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
|
||||
gc, x, y, str, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->padding_p)
|
||||
for (i = 0; i < len; i++)
|
||||
XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
||||
XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
|
||||
gc, x + i, y, str + i, 1);
|
||||
else
|
||||
XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
||||
XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
|
||||
gc, x, y, str, len);
|
||||
}
|
||||
unblock_input ();
|
||||
@ -1083,20 +1083,20 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
|
||||
{
|
||||
if (s->padding_p)
|
||||
for (i = 0; i < len; i++)
|
||||
XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
||||
XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
|
||||
gc, x + i, y, s->char2b + from + i, 1);
|
||||
else
|
||||
XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
||||
XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
|
||||
gc, x, y, s->char2b + from, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->padding_p)
|
||||
for (i = 0; i < len; i++)
|
||||
XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
||||
XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
|
||||
gc, x + i, y, s->char2b + from + i, 1);
|
||||
else
|
||||
XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
||||
XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
|
||||
gc, x, y, s->char2b + from, len);
|
||||
}
|
||||
unblock_input ();
|
||||
|
@ -586,7 +586,7 @@ xftfont_get_xft_draw (struct frame *f)
|
||||
{
|
||||
block_input ();
|
||||
xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f),
|
||||
FRAME_X_DRAWABLE (f),
|
||||
FRAME_X_VISUAL (f),
|
||||
FRAME_X_COLORMAP (f));
|
||||
unblock_input ();
|
||||
@ -600,6 +600,8 @@ static int
|
||||
xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
|
||||
bool with_background)
|
||||
{
|
||||
block_input ();
|
||||
|
||||
struct frame *f = s->f;
|
||||
struct face *face = s->face;
|
||||
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,
|
||||
xftface_info = (struct xftface_info *) face->extra;
|
||||
xftfont_get_colors (f, face, s->gc, xftface_info,
|
||||
&fg, with_background ? &bg : NULL);
|
||||
block_input ();
|
||||
if (s->num_clips > 0)
|
||||
XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
|
||||
else
|
||||
@ -652,9 +653,12 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
|
||||
x + i, y, code + i, 1);
|
||||
else
|
||||
XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
|
||||
x, y, code, len);
|
||||
x, y, code, len);
|
||||
/* Need to explicitly mark the frame dirty because we didn't call
|
||||
FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
|
||||
XftDraw structure. */
|
||||
x_mark_frame_dirty (f);
|
||||
unblock_input ();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -678,13 +682,10 @@ xftfont_shape (Lisp_Object lgstring)
|
||||
static int
|
||||
xftfont_end_for_frame (struct frame *f)
|
||||
{
|
||||
block_input ();
|
||||
XftDraw *xft_draw;
|
||||
|
||||
/* Don't do anything if display is dead */
|
||||
if (FRAME_X_DISPLAY (f) == NULL) return 0;
|
||||
|
||||
xft_draw = font_get_frame_data (f, Qxft);
|
||||
|
||||
if (xft_draw)
|
||||
{
|
||||
block_input ();
|
||||
@ -692,9 +693,19 @@ xftfont_end_for_frame (struct frame *f)
|
||||
unblock_input ();
|
||||
font_put_frame_data (f, Qxft, NULL);
|
||||
}
|
||||
unblock_input ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
xftfont_drop_xrender_surfaces (struct frame *f)
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
xftfont_end_for_frame (f);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
static bool
|
||||
xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
|
||||
Lisp_Object entity)
|
||||
@ -777,6 +788,10 @@ This is needed with some fonts to correct vertical overlap of glyphs. */);
|
||||
#if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
|
||||
xftfont_driver.shape = xftfont_shape;
|
||||
#endif
|
||||
/* When using X double buffering, the XftDraw structure we build
|
||||
seems to be useless once a frame is resized, so recreate it on
|
||||
ConfigureNotify and in some other cases. */
|
||||
xftfont_driver.drop_xrender_surfaces = xftfont_drop_xrender_surfaces;
|
||||
|
||||
register_font_driver (&xftfont_driver, NULL);
|
||||
}
|
||||
|
288
src/xterm.c
288
src/xterm.c
@ -45,6 +45,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XDBE
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
#endif
|
||||
|
||||
/* Load sys/types.h if not already loaded.
|
||||
In some systems loading it twice is suicidal. */
|
||||
#ifndef makedev
|
||||
@ -360,7 +364,7 @@ x_begin_cr_clip (struct frame *f, GC gc)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f),
|
||||
FRAME_X_DRAWABLE (f),
|
||||
FRAME_DISPLAY_INFO (f)->visual,
|
||||
FRAME_PIXEL_WIDTH (f),
|
||||
FRAME_PIXEL_HEIGHT (f));
|
||||
@ -722,7 +726,7 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
|
||||
cairo_fill (cr);
|
||||
x_end_cr_clip (f);
|
||||
#else
|
||||
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
gc, x, y, width, height);
|
||||
#endif
|
||||
}
|
||||
@ -740,7 +744,7 @@ x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
|
||||
cairo_stroke (cr);
|
||||
x_end_cr_clip (f);
|
||||
#else
|
||||
XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
gc, x, y, width, height);
|
||||
#endif
|
||||
}
|
||||
@ -756,7 +760,10 @@ x_clear_window (struct frame *f)
|
||||
cairo_paint (cr);
|
||||
x_end_cr_clip (f);
|
||||
#else
|
||||
XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
|
||||
else
|
||||
XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1067,7 +1074,7 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
|
||||
#ifdef USE_CAIRO
|
||||
x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
|
||||
#else
|
||||
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||
f->output_data.x->normal_gc, x, y0, x, y1);
|
||||
#endif
|
||||
}
|
||||
@ -1175,6 +1182,41 @@ x_update_window_end (struct window *w, bool cursor_on_p,
|
||||
}
|
||||
}
|
||||
|
||||
/* Show the frame back buffer. If frame is double-buffered,
|
||||
atomically publish to the user's screen graphics updates made since
|
||||
the last call to show_back_buffer. */
|
||||
static void
|
||||
show_back_buffer (struct frame *f)
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
{
|
||||
#ifdef HAVE_XDBE
|
||||
XdbeSwapInfo swap_info;
|
||||
memset (&swap_info, 0, sizeof (swap_info));
|
||||
swap_info.swap_window = FRAME_X_WINDOW (f);
|
||||
swap_info.swap_action = XdbeCopied;
|
||||
XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
|
||||
#else
|
||||
eassert (!"should have back-buffer only with XDBE");
|
||||
#endif
|
||||
}
|
||||
FRAME_X_NEED_BUFFER_FLIP (f) = false;
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
/* Updates back buffer and flushes changes to display. Called from
|
||||
minibuf read code. Note that we display the back buffer even if
|
||||
buffer flipping is blocked. */
|
||||
static void
|
||||
x_flip_and_flush (struct frame *f)
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_X_NEED_BUFFER_FLIP (f))
|
||||
show_back_buffer (f);
|
||||
x_flush (f);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
/* End update of frame F. This function is installed as a hook in
|
||||
update_end. */
|
||||
@ -1207,7 +1249,7 @@ x_update_end (struct frame *f)
|
||||
if (! FRAME_EXTERNAL_MENU_BAR (f))
|
||||
height += FRAME_MENU_BAR_HEIGHT (f);
|
||||
surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f),
|
||||
FRAME_X_DRAWABLE (f),
|
||||
FRAME_DISPLAY_INFO (f)->visual,
|
||||
width,
|
||||
height);
|
||||
@ -1220,7 +1262,7 @@ x_update_end (struct frame *f)
|
||||
cairo_destroy (cr);
|
||||
unblock_input ();
|
||||
}
|
||||
#endif /* USE_CAIRO */
|
||||
#endif
|
||||
|
||||
#ifndef XFlush
|
||||
block_input ();
|
||||
@ -1229,17 +1271,26 @@ x_update_end (struct frame *f)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* This function is called from various places in xdisp.c
|
||||
whenever a complete update has been performed. */
|
||||
|
||||
static void
|
||||
XTframe_up_to_date (struct frame *f)
|
||||
{
|
||||
if (FRAME_X_P (f))
|
||||
FRAME_MOUSE_UPDATE (f);
|
||||
eassert (FRAME_X_P (f));
|
||||
block_input ();
|
||||
FRAME_MOUSE_UPDATE (f);
|
||||
if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f))
|
||||
show_back_buffer (f);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
static void
|
||||
XTbuffer_flipping_unblocked_hook (struct frame *f)
|
||||
{
|
||||
if (FRAME_X_NEED_BUFFER_FLIP (f))
|
||||
show_back_buffer (f);
|
||||
}
|
||||
|
||||
/* Clear under internal border if any (GTK has its own version). */
|
||||
#ifndef USE_GTK
|
||||
@ -1354,7 +1405,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
|
||||
#else /* not USE_CAIRO */
|
||||
if (p->which)
|
||||
{
|
||||
Window window = FRAME_X_WINDOW (f);
|
||||
Drawable drawable = FRAME_X_DRAWABLE (f);
|
||||
char *bits;
|
||||
Pixmap pixmap, clipmask = (Pixmap) 0;
|
||||
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
|
||||
|
||||
/* Draw the bitmap. I believe these small pixmaps can be cached
|
||||
by the server. */
|
||||
pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
|
||||
pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h,
|
||||
(p->cursor_p
|
||||
? (p->overlay_p ? face->background
|
||||
: f->output_data.x->cursor_pixel)
|
||||
@ -1386,7 +1437,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
|
||||
XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
|
||||
}
|
||||
|
||||
XCopyArea (display, pixmap, window, gc, 0, 0,
|
||||
XCopyArea (display, pixmap, drawable, gc, 0, 0,
|
||||
p->wd, p->h, p->x, p->y);
|
||||
XFreePixmap (display, pixmap);
|
||||
|
||||
@ -1487,7 +1538,7 @@ x_set_cursor_gc (struct glyph_string *s)
|
||||
mask, &xgcv);
|
||||
else
|
||||
FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
|
||||
= XCreateGC (s->display, s->window, mask, &xgcv);
|
||||
= XCreateGC (s->display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
|
||||
|
||||
s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
|
||||
}
|
||||
@ -1534,7 +1585,7 @@ x_set_mouse_face_gc (struct glyph_string *s)
|
||||
mask, &xgcv);
|
||||
else
|
||||
FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
|
||||
= XCreateGC (s->display, s->window, mask, &xgcv);
|
||||
= XCreateGC (s->display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
|
||||
|
||||
s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
|
||||
|
||||
@ -2565,7 +2616,7 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
|
||||
{
|
||||
xgcv.stipple = dpyinfo->gray;
|
||||
mask |= GCStipple;
|
||||
relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
|
||||
relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
|
||||
}
|
||||
else
|
||||
XChangeGC (dpy, relief->gc, mask, &xgcv);
|
||||
@ -2696,7 +2747,7 @@ x_draw_relief_rect (struct frame *f,
|
||||
x_reset_clip_rectangles (f, bottom_right_gc);
|
||||
#else
|
||||
Display *dpy = FRAME_X_DISPLAY (f);
|
||||
Window window = FRAME_X_WINDOW (f);
|
||||
Drawable drawable = FRAME_X_DRAWABLE (f);
|
||||
int i;
|
||||
GC gc;
|
||||
|
||||
@ -2715,12 +2766,12 @@ x_draw_relief_rect (struct frame *f,
|
||||
if (top_p)
|
||||
{
|
||||
if (width == 1)
|
||||
XDrawLine (dpy, window, gc,
|
||||
XDrawLine (dpy, drawable, gc,
|
||||
left_x + left_p, top_y,
|
||||
right_x + !right_p, top_y);
|
||||
|
||||
for (i = 1; i < width; ++i)
|
||||
XDrawLine (dpy, window, gc,
|
||||
XDrawLine (dpy, drawable, gc,
|
||||
left_x + i * left_p, top_y + i,
|
||||
right_x + 1 - i * right_p, top_y + i);
|
||||
}
|
||||
@ -2729,13 +2780,13 @@ x_draw_relief_rect (struct frame *f,
|
||||
if (left_p)
|
||||
{
|
||||
if (width == 1)
|
||||
XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
|
||||
XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
|
||||
|
||||
XClearArea (dpy, window, left_x, top_y, 1, 1, False);
|
||||
XClearArea (dpy, window, left_x, bottom_y, 1, 1, False);
|
||||
x_clear_area(f, left_x, top_y, 1, 1);
|
||||
x_clear_area(f, left_x, bottom_y, 1, 1);
|
||||
|
||||
for (i = (width > 1 ? 1 : 0); i < width; ++i)
|
||||
XDrawLine (dpy, window, gc,
|
||||
XDrawLine (dpy, drawable, gc,
|
||||
left_x + i, top_y + (i + 1) * top_p,
|
||||
left_x + i, bottom_y + 1 - (i + 1) * bot_p);
|
||||
}
|
||||
@ -2751,23 +2802,23 @@ x_draw_relief_rect (struct frame *f,
|
||||
{
|
||||
/* Outermost top line. */
|
||||
if (top_p)
|
||||
XDrawLine (dpy, window, gc,
|
||||
XDrawLine (dpy, drawable, gc,
|
||||
left_x + left_p, top_y,
|
||||
right_x + !right_p, top_y);
|
||||
|
||||
/* Outermost left line. */
|
||||
if (left_p)
|
||||
XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
|
||||
XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
|
||||
}
|
||||
|
||||
/* Bottom. */
|
||||
if (bot_p)
|
||||
{
|
||||
XDrawLine (dpy, window, gc,
|
||||
XDrawLine (dpy, drawable, gc,
|
||||
left_x + left_p, bottom_y,
|
||||
right_x + !right_p, bottom_y);
|
||||
for (i = 1; i < width; ++i)
|
||||
XDrawLine (dpy, window, gc,
|
||||
XDrawLine (dpy, drawable, gc,
|
||||
left_x + i * left_p, bottom_y - i,
|
||||
right_x + 1 - i * right_p, bottom_y - i);
|
||||
}
|
||||
@ -2775,10 +2826,10 @@ x_draw_relief_rect (struct frame *f,
|
||||
/* Right. */
|
||||
if (right_p)
|
||||
{
|
||||
XClearArea (dpy, window, right_x, top_y, 1, 1, False);
|
||||
XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
|
||||
x_clear_area(f, right_x, top_y, 1, 1);
|
||||
x_clear_area(f, right_x, bottom_y, 1, 1);
|
||||
for (i = 0; i < width; ++i)
|
||||
XDrawLine (dpy, window, gc,
|
||||
XDrawLine (dpy, drawable, gc,
|
||||
right_x - i, top_y + (i + 1) * top_p,
|
||||
right_x - i, bottom_y + 1 - (i + 1) * bot_p);
|
||||
}
|
||||
@ -2930,7 +2981,8 @@ x_draw_image_foreground (struct glyph_string *s)
|
||||
image_rect.width = s->slice.width;
|
||||
image_rect.height = s->slice.height;
|
||||
if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
|
||||
XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
|
||||
XCopyArea (s->display, s->img->pixmap,
|
||||
FRAME_X_DRAWABLE (s->f), s->gc,
|
||||
s->slice.x + r.x - x, s->slice.y + r.y - y,
|
||||
r.width, r.height, r.x, r.y);
|
||||
}
|
||||
@ -2944,7 +2996,8 @@ x_draw_image_foreground (struct glyph_string *s)
|
||||
image_rect.width = s->slice.width;
|
||||
image_rect.height = s->slice.height;
|
||||
if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
|
||||
XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
|
||||
XCopyArea (s->display, s->img->pixmap,
|
||||
FRAME_X_DRAWABLE (s->f), s->gc,
|
||||
s->slice.x + r.x - x, s->slice.y + r.y - y,
|
||||
r.width, r.height, r.x, r.y);
|
||||
|
||||
@ -3184,7 +3237,7 @@ x_draw_image_glyph_string (struct glyph_string *s)
|
||||
int depth = DefaultDepthOfScreen (screen);
|
||||
|
||||
/* Create a pixmap as large as the glyph string. */
|
||||
pixmap = XCreatePixmap (s->display, s->window,
|
||||
pixmap = XCreatePixmap (s->display, FRAME_X_DRAWABLE (s->f),
|
||||
s->background_width,
|
||||
s->height, depth);
|
||||
|
||||
@ -3259,7 +3312,7 @@ x_draw_image_glyph_string (struct glyph_string *s)
|
||||
{
|
||||
x_draw_image_foreground_1 (s, pixmap);
|
||||
x_set_glyph_string_clipping (s);
|
||||
XCopyArea (s->display, pixmap, s->window, s->gc,
|
||||
XCopyArea (s->display, pixmap, FRAME_X_DRAWABLE (s->f), s->gc,
|
||||
0, 0, s->background_width, s->height, s->x, s->y);
|
||||
XFreePixmap (s->display, pixmap);
|
||||
}
|
||||
@ -3438,7 +3491,7 @@ x_draw_underwave (struct glyph_string *s)
|
||||
|
||||
while (x1 <= xmax)
|
||||
{
|
||||
XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2);
|
||||
XDrawLine (s->display, FRAME_X_DRAWABLE (s->f), s->gc, x1, y1, x2, y2);
|
||||
x1 = x2, y1 = y2;
|
||||
x2 += dx, y2 = y0 + odd*dy;
|
||||
odd = !odd;
|
||||
@ -3741,7 +3794,7 @@ x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height,
|
||||
/* Never called on a GUI frame, see
|
||||
http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html
|
||||
*/
|
||||
XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
|
||||
XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
|
||||
f->output_data.x->normal_gc,
|
||||
x, y, width, height,
|
||||
x + shift_by, y);
|
||||
@ -3782,8 +3835,14 @@ x_clear_area (struct frame *f, int x, int y, int width, int height)
|
||||
cairo_fill (cr);
|
||||
x_end_cr_clip (f);
|
||||
#else
|
||||
x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
x, y, width, height, False);
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
XFillRectangle (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_DRAWABLE (f),
|
||||
f->output_data.x->reverse_gc,
|
||||
x, y, width, height);
|
||||
else
|
||||
x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
||||
x, y, width, height, False);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -3799,19 +3858,13 @@ x_clear_frame (struct frame *f)
|
||||
|
||||
block_input ();
|
||||
|
||||
font_drop_xrender_surfaces (f);
|
||||
x_clear_window (f);
|
||||
|
||||
/* We have to clear the scroll bars. If we have changed colors or
|
||||
something like that, then they should be notified. */
|
||||
x_scroll_bar_clear (f);
|
||||
|
||||
#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
|
||||
/* Make sure scroll bars are redrawn. As they aren't redrawn by
|
||||
redisplay, do it here. */
|
||||
if (FRAME_GTK_WIDGET (f))
|
||||
gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
|
||||
#endif
|
||||
|
||||
XFlush (FRAME_X_DISPLAY (f));
|
||||
|
||||
unblock_input ();
|
||||
@ -4109,7 +4162,7 @@ x_scroll_run (struct window *w, struct run *run)
|
||||
SET_FRAME_GARBAGED (f);
|
||||
#else
|
||||
XCopyArea (FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
|
||||
FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
|
||||
f->output_data.x->normal_gc,
|
||||
x, from_y,
|
||||
width, height,
|
||||
@ -7448,6 +7501,26 @@ x_net_wm_state (struct frame *f, Window window)
|
||||
/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
|
||||
}
|
||||
|
||||
/* Flip back buffers on any frames with undrawn content. */
|
||||
static void
|
||||
flush_dirty_back_buffers (void)
|
||||
{
|
||||
block_input ();
|
||||
Lisp_Object tail, frame;
|
||||
FOR_EACH_FRAME (tail, frame)
|
||||
{
|
||||
struct frame *f = XFRAME (frame);
|
||||
if (FRAME_LIVE_P (f) &&
|
||||
FRAME_X_P (f) &&
|
||||
FRAME_X_WINDOW (f) &&
|
||||
!FRAME_GARBAGED_P (f) &&
|
||||
!buffer_flipping_blocked_p () &&
|
||||
FRAME_X_NEED_BUFFER_FLIP (f))
|
||||
show_back_buffer (f);
|
||||
}
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
/* Handles the XEvent EVENT on display DPYINFO.
|
||||
|
||||
*FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
|
||||
@ -7766,23 +7839,49 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||
{
|
||||
if (!FRAME_VISIBLE_P (f))
|
||||
{
|
||||
block_input ();
|
||||
SET_FRAME_VISIBLE (f, 1);
|
||||
SET_FRAME_ICONIFIED (f, false);
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
font_drop_xrender_surfaces (f);
|
||||
f->output_data.x->has_been_visible = true;
|
||||
SET_FRAME_GARBAGED (f);
|
||||
unblock_input ();
|
||||
}
|
||||
else
|
||||
{
|
||||
else if (FRAME_GARBAGED_P (f))
|
||||
{
|
||||
#ifdef USE_GTK
|
||||
/* This seems to be needed for GTK 2.6 and later, see
|
||||
http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
|
||||
x_clear_area (f,
|
||||
event->xexpose.x, event->xexpose.y,
|
||||
event->xexpose.width, event->xexpose.height);
|
||||
/* Go around the back buffer and manually clear the
|
||||
window the first time we show it. This way, we avoid
|
||||
showing users the sanity-defying horror of whatever
|
||||
GtkWindow is rendering beneath us. We've garbaged
|
||||
the frame, so we'll redraw the whole thing on next
|
||||
redisplay anyway. Yuck. */
|
||||
x_clear_area1 (
|
||||
FRAME_X_DISPLAY (f),
|
||||
FRAME_X_WINDOW (f),
|
||||
event->xexpose.x, event->xexpose.y,
|
||||
event->xexpose.width, event->xexpose.height,
|
||||
0);
|
||||
#endif
|
||||
expose_frame (f, event->xexpose.x, event->xexpose.y,
|
||||
}
|
||||
|
||||
|
||||
if (!FRAME_GARBAGED_P (f))
|
||||
{
|
||||
#ifdef USE_GTK
|
||||
/* This seems to be needed for GTK 2.6 and later, see
|
||||
http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
|
||||
x_clear_area (f,
|
||||
event->xexpose.x, event->xexpose.y,
|
||||
event->xexpose.width, event->xexpose.height);
|
||||
#endif
|
||||
expose_frame (f, event->xexpose.x, event->xexpose.y,
|
||||
event->xexpose.width, event->xexpose.height);
|
||||
}
|
||||
}
|
||||
|
||||
if (!FRAME_GARBAGED_P (f))
|
||||
show_back_buffer (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7822,10 +7921,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||
available. */
|
||||
f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
|
||||
if (f)
|
||||
expose_frame (f, event->xgraphicsexpose.x,
|
||||
event->xgraphicsexpose.y,
|
||||
event->xgraphicsexpose.width,
|
||||
event->xgraphicsexpose.height);
|
||||
{
|
||||
expose_frame (f, event->xgraphicsexpose.x,
|
||||
event->xgraphicsexpose.y,
|
||||
event->xgraphicsexpose.width,
|
||||
event->xgraphicsexpose.height);
|
||||
show_back_buffer (f);
|
||||
}
|
||||
#ifdef USE_X_TOOLKIT
|
||||
else
|
||||
goto OTHER;
|
||||
@ -8410,7 +8512,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||
else
|
||||
configureEvent = next_event;
|
||||
}
|
||||
|
||||
f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
|
||||
/* Unfortunately, we need to call font_drop_xrender_surfaces for
|
||||
_all_ ConfigureNotify events, otherwise we miss some and
|
||||
flicker. Don't try to optimize these calls by looking only
|
||||
for size changes: that's not sufficient. We miss some
|
||||
surface invalidations and flicker. */
|
||||
block_input ();
|
||||
if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
font_drop_xrender_surfaces (f);
|
||||
unblock_input ();
|
||||
#ifdef USE_CAIRO
|
||||
if (f) x_cr_destroy_surface (f);
|
||||
#endif
|
||||
@ -8419,6 +8531,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||
&& (f = any)
|
||||
&& configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
|
||||
{
|
||||
block_input ();
|
||||
if (FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||
font_drop_xrender_surfaces (f);
|
||||
unblock_input ();
|
||||
xg_frame_resized (f, configureEvent.xconfigure.width,
|
||||
configureEvent.xconfigure.height);
|
||||
#ifdef USE_CAIRO
|
||||
@ -8429,7 +8545,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||
#endif
|
||||
if (f)
|
||||
{
|
||||
x_net_wm_state (f, configureEvent.xconfigure.window);
|
||||
|
||||
x_net_wm_state (f, configureEvent.xconfigure.window);
|
||||
|
||||
#ifdef USE_X_TOOLKIT
|
||||
/* Tip frames are pure X window, set size for them. */
|
||||
@ -8437,7 +8554,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||
{
|
||||
if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
|
||||
|| FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
|
||||
SET_FRAME_GARBAGED (f);
|
||||
{
|
||||
SET_FRAME_GARBAGED (f);
|
||||
}
|
||||
FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
|
||||
FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
|
||||
}
|
||||
@ -8463,8 +8582,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||
|| configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
|
||||
{
|
||||
change_frame_size (f, width, height, false, true, false, true);
|
||||
x_clear_under_internal_border (f);
|
||||
SET_FRAME_GARBAGED (f);
|
||||
x_clear_under_internal_border (f);
|
||||
SET_FRAME_GARBAGED (f);
|
||||
cancel_mouse_face (f);
|
||||
}
|
||||
#endif /* not USE_GTK */
|
||||
@ -8688,6 +8807,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Sometimes event processing draws to the frame outside redisplay.
|
||||
To ensure that these changes become visible, draw them here. */
|
||||
flush_dirty_back_buffers ();
|
||||
SAFE_FREE ();
|
||||
return count;
|
||||
}
|
||||
@ -8880,7 +9002,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
|
||||
if (dpyinfo->scratch_cursor_gc)
|
||||
XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
|
||||
else
|
||||
dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
|
||||
dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
|
||||
GCForeground, &xgcv);
|
||||
gc = dpyinfo->scratch_cursor_gc;
|
||||
|
||||
@ -8937,7 +9059,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
|
||||
else
|
||||
{
|
||||
Display *dpy = FRAME_X_DISPLAY (f);
|
||||
Window window = FRAME_X_WINDOW (f);
|
||||
Drawable drawable = FRAME_X_DRAWABLE (f);
|
||||
GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
|
||||
unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
|
||||
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
|
||||
XChangeGC (dpy, gc, mask, &xgcv);
|
||||
else
|
||||
{
|
||||
gc = XCreateGC (dpy, window, mask, &xgcv);
|
||||
gc = XCreateGC (dpy, drawable, mask, &xgcv);
|
||||
FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
|
||||
}
|
||||
|
||||
@ -9028,11 +9150,6 @@ static void
|
||||
x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
|
||||
{
|
||||
x_clear_area (f, x, y, width, height);
|
||||
#ifdef USE_GTK
|
||||
/* Must queue a redraw, because scroll bars might have been cleared. */
|
||||
if (FRAME_GTK_WIDGET (f))
|
||||
gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -10889,9 +11006,9 @@ x_make_frame_visible (struct frame *f)
|
||||
|
||||
if (! FRAME_VISIBLE_P (f))
|
||||
{
|
||||
/* We test FRAME_GARBAGED_P here to make sure we don't
|
||||
call x_set_offset a second time
|
||||
if we get to x_make_frame_visible a second time
|
||||
/* We test asked_for_visible here to make sure we don't
|
||||
call x_set_offset a second time
|
||||
if we get to x_make_frame_visible a second time
|
||||
before the window gets really visible. */
|
||||
if (! FRAME_ICONIFIED_P (f)
|
||||
&& ! FRAME_X_EMBEDDED_P (f)
|
||||
@ -10935,6 +11052,8 @@ x_make_frame_visible (struct frame *f)
|
||||
will set it when they are handled. */
|
||||
bool previously_visible = f->output_data.x->has_been_visible;
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
original_left = f->left_pos;
|
||||
original_top = f->top_pos;
|
||||
|
||||
@ -10981,8 +11100,6 @@ x_make_frame_visible (struct frame *f)
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
/* Process X events until a MapNotify event has been seen. */
|
||||
while (!FRAME_VISIBLE_P (f))
|
||||
{
|
||||
@ -11227,6 +11344,7 @@ x_free_frame_resources (struct frame *f)
|
||||
font-driver (e.g. xft) access a window while finishing a
|
||||
face. */
|
||||
free_frame_faces (f);
|
||||
tear_down_x_back_buffer (f);
|
||||
|
||||
if (f->output_data.x->icon_desc)
|
||||
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
|
||||
@ -11258,7 +11376,7 @@ x_free_frame_resources (struct frame *f)
|
||||
/* Tooltips don't have widgets, only a simple X window, even if
|
||||
we are using a toolkit. */
|
||||
else if (FRAME_X_WINDOW (f))
|
||||
XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
|
||||
XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
|
||||
|
||||
free_frame_menubar (f);
|
||||
|
||||
@ -11270,8 +11388,9 @@ x_free_frame_resources (struct frame *f)
|
||||
xg_free_frame_widgets (f);
|
||||
#endif /* USE_GTK */
|
||||
|
||||
tear_down_x_back_buffer (f);
|
||||
if (FRAME_X_WINDOW (f))
|
||||
XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
|
||||
XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
|
||||
#endif /* !USE_X_TOOLKIT */
|
||||
|
||||
unload_color (f, FRAME_FOREGROUND_PIXEL (f));
|
||||
@ -12111,7 +12230,15 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
|
||||
}
|
||||
else
|
||||
dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
|
||||
dpyinfo->visual, AllocNone);
|
||||
dpyinfo->visual, AllocNone);
|
||||
|
||||
#ifdef HAVE_XDBE
|
||||
dpyinfo->supports_xdbe = false;
|
||||
int xdbe_major;
|
||||
int xdbe_minor;
|
||||
if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
|
||||
dpyinfo->supports_xdbe = true;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XFT
|
||||
{
|
||||
@ -12462,7 +12589,7 @@ static struct redisplay_interface x_redisplay_interface =
|
||||
x_after_update_window_line,
|
||||
x_update_window_begin,
|
||||
x_update_window_end,
|
||||
x_flush,
|
||||
x_flip_and_flush,
|
||||
x_clear_window_mouse_face,
|
||||
x_get_glyph_overhangs,
|
||||
x_fix_overlapping_area,
|
||||
@ -12592,6 +12719,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
|
||||
terminal->update_end_hook = x_update_end;
|
||||
terminal->read_socket_hook = XTread_socket;
|
||||
terminal->frame_up_to_date_hook = XTframe_up_to_date;
|
||||
terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
|
||||
terminal->mouse_position_hook = XTmouse_position;
|
||||
terminal->frame_rehighlight_hook = XTframe_rehighlight;
|
||||
terminal->frame_raise_lower_hook = XTframe_raise_lower;
|
||||
|
35
src/xterm.h
35
src/xterm.h
@ -475,6 +475,10 @@ struct x_display_info
|
||||
#ifdef USE_XCB
|
||||
xcb_connection_t *xcb_connection;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XDBE
|
||||
bool supports_xdbe;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef HAVE_X_I18N
|
||||
@ -527,6 +531,16 @@ struct x_output
|
||||
and the X window has not yet been created. */
|
||||
Window window_desc;
|
||||
|
||||
/* The drawable to which we're rendering. In the single-buffered
|
||||
base, the window itself. In the double-buffered case, the
|
||||
window's back buffer. */
|
||||
Drawable draw_desc;
|
||||
|
||||
/* Flag that indicates whether we've modified the back buffer and
|
||||
need to publish our modifications to the front buffer at a
|
||||
convenient time. */
|
||||
bool need_buffer_flip;
|
||||
|
||||
/* The X window used for the bitmap icon;
|
||||
or 0 if we don't have a bitmap icon. */
|
||||
Window icon_desc;
|
||||
@ -737,6 +751,24 @@ enum
|
||||
/* Return the X window used for displaying data in frame F. */
|
||||
#define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc)
|
||||
|
||||
/* Return the drawable used for rendering to frame F. */
|
||||
#define FRAME_X_RAW_DRAWABLE(f) ((f)->output_data.x->draw_desc)
|
||||
|
||||
extern void x_mark_frame_dirty (struct frame *f);
|
||||
|
||||
/* Return the drawable used for rendering to frame F and mark the
|
||||
frame as needing a buffer flip later. There's no easy way to run
|
||||
code after any drawing command, but we can run code whenever
|
||||
someone asks for the handle necessary to draw. */
|
||||
#define FRAME_X_DRAWABLE(f) \
|
||||
(x_mark_frame_dirty((f)), FRAME_X_RAW_DRAWABLE ((f)))
|
||||
|
||||
#define FRAME_X_DOUBLE_BUFFERED_P(f) \
|
||||
(FRAME_X_WINDOW (f) != FRAME_X_RAW_DRAWABLE (f))
|
||||
|
||||
/* Return the need-buffer-flip flag for frame F. */
|
||||
#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip)
|
||||
|
||||
/* Return the outermost X window associated with the frame F. */
|
||||
#ifdef USE_X_TOOLKIT
|
||||
#define FRAME_OUTER_WINDOW(f) ((f)->output_data.x->widget ? \
|
||||
@ -1140,6 +1172,9 @@ extern bool x_wm_supports (struct frame *, Atom);
|
||||
extern void x_wait_for_event (struct frame *, int);
|
||||
extern void x_clear_under_internal_border (struct frame *f);
|
||||
|
||||
extern void tear_down_x_back_buffer (struct frame *f);
|
||||
extern void initial_set_up_x_back_buffer (struct frame *f);
|
||||
|
||||
/* Defined in xselect.c. */
|
||||
|
||||
extern void x_handle_property_notify (const XPropertyEvent *);
|
||||
|
Loading…
Reference in New Issue
Block a user