mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 12:31:25 +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
24 changed files with 635 additions and 216 deletions
18
configure.ac
18
configure.ac
|
|
@ -3712,6 +3712,24 @@ fi
|
||||||
AC_SUBST(XFIXES_CFLAGS)
|
AC_SUBST(XFIXES_CFLAGS)
|
||||||
AC_SUBST(XFIXES_LIBS)
|
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
|
### Use libxml (-lxml2) if available
|
||||||
### mingw32 doesn't use -lxml2, since it loads the library dynamically.
|
### mingw32 doesn't use -lxml2, since it loads the library dynamically.
|
||||||
HAVE_LIBXML2=no
|
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
|
If non-@code{nil}, the frame is visible on all virtual desktops on systems
|
||||||
with virtual desktops.
|
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
|
@ignore
|
||||||
@vindex parent-id, a frame parameter
|
@vindex parent-id, a frame parameter
|
||||||
@item parent-id
|
@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
|
any control, but Emacs does provide events that you can use to keep
|
||||||
track of such changes. @xref{Misc Events}.
|
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
|
@node Raising and Lowering
|
||||||
@section Raising and Lowering Frames
|
@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
|
of curved quotes for 'electric-quote-mode', allowing user to choose
|
||||||
the types of quotes to be used.
|
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.
|
The group 'wp', whose label was "text", is now deprecated.
|
||||||
Use the new group 'text', which inherits from 'wp', instead.
|
Use the new group 'text', which inherits from 'wp', instead.
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include "XMenuInt.h"
|
#include "XMenuInt.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include "XMenuInt.h"
|
#include "XMenuInt.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "X10.h"
|
#include "X10.h"
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,9 @@ XINERAMA_CFLAGS = @XINERAMA_CFLAGS@
|
||||||
XFIXES_LIBS = @XFIXES_LIBS@
|
XFIXES_LIBS = @XFIXES_LIBS@
|
||||||
XFIXES_CFLAGS = @XFIXES_CFLAGS@
|
XFIXES_CFLAGS = @XFIXES_CFLAGS@
|
||||||
|
|
||||||
|
XDBE_LIBS = @XDBE_LIBS@
|
||||||
|
XDBE_CFLAGS = @XDBE_CFLAGS@
|
||||||
|
|
||||||
## widget.o if USE_X_TOOLKIT, otherwise empty.
|
## widget.o if USE_X_TOOLKIT, otherwise empty.
|
||||||
WIDGET_OBJ=@WIDGET_OBJ@
|
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) \
|
$(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
|
||||||
$(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
|
$(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
|
||||||
$(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
|
$(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
|
||||||
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
|
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \
|
||||||
$(WEBKIT_CFLAGS) \
|
$(WEBKIT_CFLAGS) \
|
||||||
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
|
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
|
||||||
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
|
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
|
||||||
|
|
@ -489,6 +492,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
|
||||||
$(WEBKIT_LIBS) \
|
$(WEBKIT_LIBS) \
|
||||||
$(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
|
$(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
|
||||||
$(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
|
$(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
|
||||||
|
$(XDBE_LIBS) \
|
||||||
$(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
|
$(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
|
||||||
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
|
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
|
||||||
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
|
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
|
||||||
|
|
|
||||||
|
|
@ -1276,7 +1276,6 @@ struct glyph_string
|
||||||
|
|
||||||
/* X display and window for convenience. */
|
/* X display and window for convenience. */
|
||||||
Display *display;
|
Display *display;
|
||||||
Window window;
|
|
||||||
|
|
||||||
/* The glyph row for which this string was built. It determines the
|
/* The glyph row for which this string was built. It determines the
|
||||||
y-origin and height of the string. */
|
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 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 */
|
/* Defined in image.c */
|
||||||
|
|
||||||
#ifdef HAVE_WINDOW_SYSTEM
|
#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);
|
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
|
void
|
||||||
syms_of_font (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
|
Return non-nil if the driver support rendering of combining
|
||||||
characters for FONT according to Unicode combining class. */
|
characters for FONT according to Unicode combining class. */
|
||||||
Lisp_Object (*combining_capability) (struct font *font);
|
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,
|
extern void font_filter_properties (Lisp_Object font,
|
||||||
Lisp_Object alist,
|
Lisp_Object alist,
|
||||||
const char *const boolean_properties[],
|
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
|
#ifdef HAVE_FREETYPE
|
||||||
extern struct font_driver ftfont_driver;
|
extern struct font_driver ftfont_driver;
|
||||||
|
|
|
||||||
|
|
@ -3128,6 +3128,7 @@ static const struct frame_parm_table frame_parms[] =
|
||||||
{"alpha", SYMBOL_INDEX (Qalpha)},
|
{"alpha", SYMBOL_INDEX (Qalpha)},
|
||||||
{"sticky", SYMBOL_INDEX (Qsticky)},
|
{"sticky", SYMBOL_INDEX (Qsticky)},
|
||||||
{"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
|
{"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
|
||||||
|
{"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_WINDOW_SYSTEM
|
#ifdef HAVE_WINDOW_SYSTEM
|
||||||
|
|
@ -5044,6 +5045,7 @@ syms_of_frame (void)
|
||||||
DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
|
DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
|
||||||
DEFSYM (Qvisibility, "visibility");
|
DEFSYM (Qvisibility, "visibility");
|
||||||
DEFSYM (Qwait_for_wm, "wait-for-wm");
|
DEFSYM (Qwait_for_wm, "wait-for-wm");
|
||||||
|
DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
|
||||||
|
|
||||||
{
|
{
|
||||||
int i;
|
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))
|
if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
|
||||||
break;
|
break;
|
||||||
xgcv.foreground = color.pixel;
|
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);
|
GCForeground, &xgcv);
|
||||||
}
|
}
|
||||||
unblock_input ();
|
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;
|
p[n[0]].y = y - bitmap.top + i;
|
||||||
if (++n[0] == size)
|
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);
|
gc_fore, p, size, CoordModeOrigin);
|
||||||
n[0] = 0;
|
n[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flush && 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);
|
gc_fore, p, n[0], CoordModeOrigin);
|
||||||
}
|
}
|
||||||
else
|
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;
|
pp[n[idx]].y = y - bitmap.top + i;
|
||||||
if (++(n[idx]) == size)
|
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,
|
idx == 6 ? gc_fore : gcs[idx], pp, size,
|
||||||
CoordModeOrigin);
|
CoordModeOrigin);
|
||||||
n[idx] = 0;
|
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++)
|
for (i = 0; i < 6; i++)
|
||||||
if (n[i] > 0)
|
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);
|
gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
|
||||||
if (n[6] > 0)
|
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);
|
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,
|
XGetGCValues (FRAME_X_DISPLAY (f), gc,
|
||||||
GCForeground | GCBackground, &xgcv);
|
GCForeground | GCBackground, &xgcv);
|
||||||
XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
|
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));
|
x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
|
||||||
XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
|
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"
|
#include "emacsgtkfixed.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XDBE
|
||||||
|
#include <X11/extensions/Xdbe.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
|
#ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
|
||||||
#define gtk_widget_set_has_window(w, b) \
|
#define gtk_widget_set_has_window(w, b) \
|
||||||
(gtk_fixed_set_has_window (GTK_FIXED (w), b))
|
(gtk_fixed_set_has_window (GTK_FIXED (w), b))
|
||||||
|
|
@ -143,6 +147,8 @@ struct xg_frame_tb_info
|
||||||
GtkTextDirection dir;
|
GtkTextDirection dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GtkWidget * xg_get_widget_from_map (ptrdiff_t idx);
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
Display handling functions
|
Display handling functions
|
||||||
|
|
@ -815,12 +821,6 @@ xg_clear_under_internal_border (struct frame *f)
|
||||||
{
|
{
|
||||||
if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
|
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,
|
x_clear_area (f, 0, 0,
|
||||||
FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
|
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. */
|
by callers of this function. */
|
||||||
gtk_widget_realize (wfixed);
|
gtk_widget_realize (wfixed);
|
||||||
FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (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,
|
/* Since GTK clears its window by filling with the background color,
|
||||||
we must keep X and GTK background in sync. */
|
we must keep X and GTK background in sync. */
|
||||||
|
|
@ -1296,8 +1297,11 @@ xg_free_frame_widgets (struct frame *f)
|
||||||
if (tbinfo)
|
if (tbinfo)
|
||||||
xfree (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));
|
gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
|
||||||
FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
|
FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
|
||||||
|
FRAME_X_RAW_DRAWABLE (f) = 0;
|
||||||
FRAME_GTK_OUTER_WIDGET (f) = 0;
|
FRAME_GTK_OUTER_WIDGET (f) = 0;
|
||||||
#ifdef USE_GTK_TOOLTIP
|
#ifdef USE_GTK_TOOLTIP
|
||||||
if (x->ttip_lbl)
|
if (x->ttip_lbl)
|
||||||
|
|
@ -1440,6 +1444,18 @@ xg_set_background_color (struct frame *f, unsigned long bg)
|
||||||
{
|
{
|
||||||
block_input ();
|
block_input ();
|
||||||
xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f));
|
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 ();
|
unblock_input ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2265,7 +2281,6 @@ xg_mark_data (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Callback called when a menu item is destroyed. Used to free data.
|
/* Callback called when a menu item is destroyed. Used to free data.
|
||||||
W is the widget that is being destroyed (not used).
|
W is the widget that is being destroyed (not used).
|
||||||
CLIENT_DATA points to the xg_menu_item_cb_data associated with the W. */
|
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);
|
xg_remove_widget_from_map (id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a scroll bar widget for frame F. Store the scroll bar
|
static void
|
||||||
in BAR.
|
xg_finish_scroll_bar_creation (struct frame *f,
|
||||||
SCROLL_CALLBACK is the callback to invoke when the value of the
|
GtkWidget *wscroll,
|
||||||
bar changes.
|
struct scroll_bar *bar,
|
||||||
END_CALLBACK is the callback to invoke when scrolling ends.
|
GCallback scroll_callback,
|
||||||
SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used
|
GCallback end_callback,
|
||||||
to set resources for the widget. */
|
const char *scroll_bar_name)
|
||||||
|
|
||||||
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;
|
GtkWidget *webox = gtk_event_box_new ();
|
||||||
GtkWidget *webox;
|
|
||||||
intptr_t scroll_id;
|
|
||||||
#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));
|
|
||||||
webox = gtk_event_box_new ();
|
|
||||||
gtk_widget_set_name (wscroll, scroll_bar_name);
|
gtk_widget_set_name (wscroll, scroll_bar_name);
|
||||||
#ifndef HAVE_GTK3
|
#ifndef HAVE_GTK3
|
||||||
gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
|
gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
|
||||||
#endif
|
#endif
|
||||||
g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
|
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),
|
g_signal_connect (G_OBJECT (wscroll),
|
||||||
"destroy",
|
"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_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1);
|
||||||
gtk_container_add (GTK_CONTAINER (webox), wscroll);
|
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. */
|
/* Set the cursor to an arrow. */
|
||||||
xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
|
xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
|
||||||
|
|
||||||
bar->x_window = scroll_id;
|
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;
|
bar->horizontal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3652,8 +3687,6 @@ xg_create_horizontal_scroll_bar (struct frame *f,
|
||||||
const char *scroll_bar_name)
|
const char *scroll_bar_name)
|
||||||
{
|
{
|
||||||
GtkWidget *wscroll;
|
GtkWidget *wscroll;
|
||||||
GtkWidget *webox;
|
|
||||||
intptr_t scroll_id;
|
|
||||||
#ifdef HAVE_GTK3
|
#ifdef HAVE_GTK3
|
||||||
GtkAdjustment *hadj;
|
GtkAdjustment *hadj;
|
||||||
#else
|
#else
|
||||||
|
|
@ -3666,42 +3699,9 @@ xg_create_horizontal_scroll_bar (struct frame *f,
|
||||||
0.1, 0.1, 0.1);
|
0.1, 0.1, 0.1);
|
||||||
|
|
||||||
wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj));
|
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);
|
xg_finish_scroll_bar_creation (f, wscroll, bar, scroll_callback,
|
||||||
|
end_callback, scroll_bar_name);
|
||||||
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;
|
|
||||||
bar->horizontal = 1;
|
bar->horizontal = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3770,16 +3770,10 @@ xg_update_scrollbar_pos (struct frame *f,
|
||||||
gtk_widget_show_all (wparent);
|
gtk_widget_show_all (wparent);
|
||||||
gtk_widget_set_size_request (wscroll, width, height);
|
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)
|
if (oldx != -1 && oldw > 0 && oldh > 0)
|
||||||
{
|
{
|
||||||
/* Clear under old scroll bar position. This must be done after
|
/* Clear under old scroll bar position. */
|
||||||
the gtk_widget_queue_draw and gdk_window_process_all_updates
|
oldw += (scale - 1) * oldw;
|
||||||
above. */
|
|
||||||
oldw += (scale - 1) * oldw;
|
|
||||||
oldx -= (scale - 1) * oldw;
|
oldx -= (scale - 1) * oldw;
|
||||||
x_clear_area (f, oldx, oldy, oldw, oldh);
|
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_show_all (wparent);
|
||||||
gtk_widget_set_size_request (wscroll, width, height);
|
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)
|
if (oldx != -1 && oldw > 0 && oldh > 0)
|
||||||
/* Clear under old scroll bar position. This must be done after
|
/* Clear under old scroll bar position. */
|
||||||
the gtk_widget_queue_draw and gdk_window_process_all_updates
|
x_clear_area (f, oldx, oldy, oldw, oldh);
|
||||||
above. */
|
|
||||||
x_clear_area (f,
|
|
||||||
oldx, oldy, oldw, oldh);
|
|
||||||
|
|
||||||
/* GTK does not redraw until the main loop is entered again, but
|
/* 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
|
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
|
#ifdef HAVE_X_WINDOWS
|
||||||
Pixmap bitmap;
|
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);
|
bits, width, height);
|
||||||
if (! bitmap)
|
if (! bitmap)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -327,7 +327,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
|
||||||
|
|
||||||
filename = SSDATA (found);
|
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);
|
filename, &width, &height, &bitmap, &xhot, &yhot);
|
||||||
if (result != BitmapSuccess)
|
if (result != BitmapSuccess)
|
||||||
return -1;
|
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
|
#ifdef HAVE_X_WINDOWS
|
||||||
Display *display = FRAME_X_DISPLAY (f);
|
Display *display = FRAME_X_DISPLAY (f);
|
||||||
Window window = FRAME_X_WINDOW (f);
|
Drawable drawable = FRAME_X_DRAWABLE (f);
|
||||||
Screen *screen = FRAME_X_SCREEN (f);
|
Screen *screen = FRAME_X_SCREEN (f);
|
||||||
|
|
||||||
eassert (input_blocked_p ());
|
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);
|
(*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height);
|
||||||
|
|
||||||
/* Allocate a pixmap of the same size. */
|
/* 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)
|
if (*pixmap == NO_PIXMAP)
|
||||||
{
|
{
|
||||||
x_destroy_x_image (*ximg);
|
x_destroy_x_image (*ximg);
|
||||||
|
|
@ -2742,7 +2742,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
|
||||||
img->pixmap =
|
img->pixmap =
|
||||||
(x_check_image_size (0, img->width, img->height)
|
(x_check_image_size (0, img->width, img->height)
|
||||||
? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
|
? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
|
||||||
FRAME_X_WINDOW (f),
|
FRAME_X_DRAWABLE (f),
|
||||||
data,
|
data,
|
||||||
img->width, img->height,
|
img->width, img->height,
|
||||||
fg, bg,
|
fg, bg,
|
||||||
|
|
@ -3520,7 +3520,7 @@ x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
|
||||||
xpm_init_color_cache (f, &attrs);
|
xpm_init_color_cache (f, &attrs);
|
||||||
#endif
|
#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);
|
(char **) bits, &bitmap, &mask, &attrs);
|
||||||
if (rc != XpmSuccess)
|
if (rc != XpmSuccess)
|
||||||
{
|
{
|
||||||
|
|
@ -3758,7 +3758,7 @@ xpm_load (struct frame *f, struct image *img)
|
||||||
#ifdef HAVE_X_WINDOWS
|
#ifdef HAVE_X_WINDOWS
|
||||||
if (rc == XpmSuccess)
|
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->width, img->ximg->height,
|
||||||
img->ximg->depth);
|
img->ximg->depth);
|
||||||
if (img->pixmap == NO_PIXMAP)
|
if (img->pixmap == NO_PIXMAP)
|
||||||
|
|
@ -3768,7 +3768,7 @@ xpm_load (struct frame *f, struct image *img)
|
||||||
}
|
}
|
||||||
else if (img->mask_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->width,
|
||||||
img->mask_img->height,
|
img->mask_img->height,
|
||||||
img->mask_img->depth);
|
img->mask_img->depth);
|
||||||
|
|
@ -9541,7 +9541,7 @@ gs_load (struct frame *f, struct image *img)
|
||||||
{
|
{
|
||||||
/* Only W32 version did BLOCK_INPUT here. ++kfs */
|
/* Only W32 version did BLOCK_INPUT here. ++kfs */
|
||||||
block_input ();
|
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,
|
img->width, img->height,
|
||||||
DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
|
DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
|
||||||
unblock_input ();
|
unblock_input ();
|
||||||
|
|
@ -9557,7 +9557,7 @@ gs_load (struct frame *f, struct image *img)
|
||||||
if successful. We do not record_unwind_protect here because
|
if successful. We do not record_unwind_protect here because
|
||||||
other places in redisplay like calling window scroll functions
|
other places in redisplay like calling window scroll functions
|
||||||
don't either. Let the Lisp loader use `unwind-protect' instead. */
|
don't either. Let the Lisp loader use `unwind-protect' instead. */
|
||||||
printnum1 = FRAME_X_WINDOW (f);
|
printnum1 = FRAME_X_DRAWABLE (f);
|
||||||
printnum2 = img->pixmap;
|
printnum2 = img->pixmap;
|
||||||
window_and_pixmap_id
|
window_and_pixmap_id
|
||||||
= make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
|
= 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,
|
x_set_alpha,
|
||||||
0, /* x_set_sticky */
|
0, /* x_set_sticky */
|
||||||
0, /* x_set_tool_bar_position */
|
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. */
|
/* Called when a frame's display becomes entirely up to date. */
|
||||||
void (*frame_up_to_date_hook) (struct frame *);
|
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
|
/* Called to delete the device-specific portions of a frame that is
|
||||||
on this terminal device. */
|
on this terminal device. */
|
||||||
|
|
|
||||||
|
|
@ -9757,6 +9757,7 @@ frame_parm_handler w32_frame_parm_handlers[] =
|
||||||
x_set_alpha,
|
x_set_alpha,
|
||||||
0, /* x_set_sticky */
|
0, /* x_set_sticky */
|
||||||
0, /* x_set_tool_bar_position */
|
0, /* x_set_tool_bar_position */
|
||||||
|
0, /* x_set_inhibit_double_buffering */
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
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. */
|
/* Visible feedback for debugging. */
|
||||||
#if false && defined HAVE_X_WINDOWS
|
#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,
|
f->output_data.x->normal_gc,
|
||||||
gx, gy, width, height);
|
gx, gy, width, height);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -11349,7 +11349,7 @@ clear_garbaged_frames (void)
|
||||||
fset_redisplay (f);
|
fset_redisplay (f);
|
||||||
f->garbaged = false;
|
f->garbaged = false;
|
||||||
f->resized_p = false;
|
f->resized_p = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frame_garbaged = false;
|
frame_garbaged = false;
|
||||||
|
|
@ -13573,6 +13573,7 @@ redisplay_internal (void)
|
||||||
count = SPECPDL_INDEX ();
|
count = SPECPDL_INDEX ();
|
||||||
record_unwind_protect_void (unwind_redisplay);
|
record_unwind_protect_void (unwind_redisplay);
|
||||||
redisplaying_p = true;
|
redisplaying_p = true;
|
||||||
|
block_buffer_flips ();
|
||||||
specbind (Qinhibit_free_realized_faces, Qnil);
|
specbind (Qinhibit_free_realized_faces, Qnil);
|
||||||
|
|
||||||
/* Record this function, so it appears on the profiler's backtraces. */
|
/* 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.
|
use them in update_frame will segfault.
|
||||||
Therefore, we must redisplay this frame. */
|
Therefore, we must redisplay this frame. */
|
||||||
if (!f_redisplay_flag && f->redisplay)
|
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
|
/* Prevent various kinds of signals during display
|
||||||
update. stdio is not robust about handling
|
update. stdio is not robust about handling
|
||||||
|
|
@ -14297,6 +14314,11 @@ redisplay_internal (void)
|
||||||
RESUME_POLLING;
|
RESUME_POLLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unwind_redisplay_preserve_echo_area (void)
|
||||||
|
{
|
||||||
|
unblock_buffer_flips ();
|
||||||
|
}
|
||||||
|
|
||||||
/* Redisplay, but leave alone any recent echo area message unless
|
/* Redisplay, but leave alone any recent echo area message unless
|
||||||
another message has been requested in its place.
|
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));
|
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]))
|
if (!NILP (echo_area_buffer[1]))
|
||||||
{
|
{
|
||||||
/* We have a previously displayed message, but no current
|
/* We have a previously displayed message, but no current
|
||||||
|
|
@ -14326,6 +14354,7 @@ redisplay_preserve_echo_area (int from_where)
|
||||||
redisplay_internal ();
|
redisplay_internal ();
|
||||||
|
|
||||||
flush_frame (SELECTED_FRAME ());
|
flush_frame (SELECTED_FRAME ());
|
||||||
|
unbind_to (count, Qnil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14335,6 +14364,7 @@ static void
|
||||||
unwind_redisplay (void)
|
unwind_redisplay (void)
|
||||||
{
|
{
|
||||||
redisplaying_p = false;
|
redisplaying_p = false;
|
||||||
|
unblock_buffer_flips ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14444,6 +14474,38 @@ disp_char_vector (struct Lisp_Char_Table *dp, int c)
|
||||||
return val;
|
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;
|
s->hdc = hdc;
|
||||||
#endif
|
#endif
|
||||||
s->display = FRAME_X_DISPLAY (s->f);
|
s->display = FRAME_X_DISPLAY (s->f);
|
||||||
s->window = FRAME_X_WINDOW (s->f);
|
|
||||||
s->char2b = char2b;
|
s->char2b = char2b;
|
||||||
s->hl = hl;
|
s->hl = hl;
|
||||||
s->row = row;
|
s->row = row;
|
||||||
|
|
|
||||||
|
|
@ -495,7 +495,7 @@ x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv)
|
||||||
{
|
{
|
||||||
GC gc;
|
GC gc;
|
||||||
block_input ();
|
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 ();
|
unblock_input ();
|
||||||
IF_DEBUG (++ngcs);
|
IF_DEBUG (++ngcs);
|
||||||
return gc;
|
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"
|
#include "gtkutil.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XDBE
|
||||||
|
#include <X11/extensions/Xdbe.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_X_TOOLKIT
|
#ifdef USE_X_TOOLKIT
|
||||||
#include <X11/Shell.h>
|
#include <X11/Shell.h>
|
||||||
|
|
||||||
|
|
@ -114,6 +118,7 @@ static int dpyinfo_refcount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct x_display_info *x_display_info_for_name (Lisp_Object);
|
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.
|
/* Let the user specify an X display with a Lisp object.
|
||||||
OBJECT may be nil, a frame or a terminal 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);
|
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
|
#ifdef USE_GTK
|
||||||
|
|
||||||
/* Set icon from FILE for frame F. By using GTK functions the icon
|
/* 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
|
#ifdef USE_X_TOOLKIT
|
||||||
|
|
||||||
/* Create and set up the X widget for frame F. */
|
/* 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);
|
f->output_data.x->parent_desc, 0, 0);
|
||||||
|
|
||||||
FRAME_X_WINDOW (f) = XtWindow (frame_widget);
|
FRAME_X_WINDOW (f) = XtWindow (frame_widget);
|
||||||
|
initial_set_up_x_back_buffer (f);
|
||||||
validate_x_resource_name ();
|
validate_x_resource_name ();
|
||||||
|
|
||||||
class_hints.res_name = SSDATA (Vx_resource_name);
|
class_hints.res_name = SSDATA (Vx_resource_name);
|
||||||
|
|
@ -2784,7 +2884,8 @@ x_window (struct frame *f)
|
||||||
CopyFromParent, /* depth */
|
CopyFromParent, /* depth */
|
||||||
InputOutput, /* class */
|
InputOutput, /* class */
|
||||||
FRAME_X_VISUAL (f),
|
FRAME_X_VISUAL (f),
|
||||||
attribute_mask, &attributes);
|
attribute_mask, &attributes);
|
||||||
|
initial_set_up_x_back_buffer (f);
|
||||||
|
|
||||||
#ifdef HAVE_X_I18N
|
#ifdef HAVE_X_I18N
|
||||||
if (use_xim)
|
if (use_xim)
|
||||||
|
|
@ -2938,7 +3039,7 @@ x_make_gc (struct frame *f)
|
||||||
gc_values.line_width = 0; /* Means 1 using fast algorithm. */
|
gc_values.line_width = 0; /* Means 1 using fast algorithm. */
|
||||||
f->output_data.x->normal_gc
|
f->output_data.x->normal_gc
|
||||||
= XCreateGC (FRAME_X_DISPLAY (f),
|
= XCreateGC (FRAME_X_DISPLAY (f),
|
||||||
FRAME_X_WINDOW (f),
|
FRAME_X_DRAWABLE (f),
|
||||||
GCLineWidth | GCForeground | GCBackground,
|
GCLineWidth | GCForeground | GCBackground,
|
||||||
&gc_values);
|
&gc_values);
|
||||||
|
|
||||||
|
|
@ -2947,7 +3048,7 @@ x_make_gc (struct frame *f)
|
||||||
gc_values.background = FRAME_FOREGROUND_PIXEL (f);
|
gc_values.background = FRAME_FOREGROUND_PIXEL (f);
|
||||||
f->output_data.x->reverse_gc
|
f->output_data.x->reverse_gc
|
||||||
= XCreateGC (FRAME_X_DISPLAY (f),
|
= XCreateGC (FRAME_X_DISPLAY (f),
|
||||||
FRAME_X_WINDOW (f),
|
FRAME_X_DRAWABLE (f),
|
||||||
GCForeground | GCBackground | GCLineWidth,
|
GCForeground | GCBackground | GCLineWidth,
|
||||||
&gc_values);
|
&gc_values);
|
||||||
|
|
||||||
|
|
@ -2956,7 +3057,7 @@ x_make_gc (struct frame *f)
|
||||||
gc_values.background = f->output_data.x->cursor_pixel;
|
gc_values.background = f->output_data.x->cursor_pixel;
|
||||||
gc_values.fill_style = FillOpaqueStippled;
|
gc_values.fill_style = FillOpaqueStippled;
|
||||||
f->output_data.x->cursor_gc
|
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
|
(GCForeground | GCBackground
|
||||||
| GCFillStyle | GCLineWidth),
|
| GCFillStyle | GCLineWidth),
|
||||||
&gc_values);
|
&gc_values);
|
||||||
|
|
@ -3463,6 +3564,9 @@ This function is an internal primitive--use `make-frame' instead. */)
|
||||||
"waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
|
"waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
|
||||||
x_default_parameter (f, parms, Qtool_bar_position,
|
x_default_parameter (f, parms, Qtool_bar_position,
|
||||||
FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
|
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. */
|
/* Compute the size of the X window. */
|
||||||
window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
|
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. */
|
/* Border. */
|
||||||
f->border_width,
|
f->border_width,
|
||||||
CopyFromParent, InputOutput, CopyFromParent,
|
CopyFromParent, InputOutput, CopyFromParent,
|
||||||
mask, &attrs);
|
mask, &attrs);
|
||||||
|
initial_set_up_x_back_buffer (f);
|
||||||
XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
|
XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
|
||||||
FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
|
FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
|
||||||
XA_ATOM, 32, PropModeReplace,
|
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);
|
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
|
File selection dialog
|
||||||
|
|
@ -6864,6 +6978,7 @@ frame_parm_handler x_frame_parm_handlers[] =
|
||||||
x_set_alpha,
|
x_set_alpha,
|
||||||
x_set_sticky,
|
x_set_sticky,
|
||||||
x_set_tool_bar_position,
|
x_set_tool_bar_position,
|
||||||
|
x_set_inhibit_double_buffering,
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -7080,6 +7195,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
|
||||||
|
|
||||||
defsubr (&Sx_show_tip);
|
defsubr (&Sx_show_tip);
|
||||||
defsubr (&Sx_hide_tip);
|
defsubr (&Sx_hide_tip);
|
||||||
|
defsubr (&Sx_double_buffered_p);
|
||||||
tip_timer = Qnil;
|
tip_timer = Qnil;
|
||||||
staticpro (&tip_timer);
|
staticpro (&tip_timer);
|
||||||
tip_frame = Qnil;
|
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)
|
if (s->padding_p)
|
||||||
for (i = 0; i < len; i++)
|
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);
|
gc, x + i, y, str + i, 1);
|
||||||
else
|
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);
|
gc, x, y, str, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (s->padding_p)
|
if (s->padding_p)
|
||||||
for (i = 0; i < len; i++)
|
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);
|
gc, x + i, y, str + i, 1);
|
||||||
else
|
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);
|
gc, x, y, str, len);
|
||||||
}
|
}
|
||||||
unblock_input ();
|
unblock_input ();
|
||||||
|
|
@ -1083,20 +1083,20 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
|
||||||
{
|
{
|
||||||
if (s->padding_p)
|
if (s->padding_p)
|
||||||
for (i = 0; i < len; i++)
|
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);
|
gc, x + i, y, s->char2b + from + i, 1);
|
||||||
else
|
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);
|
gc, x, y, s->char2b + from, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (s->padding_p)
|
if (s->padding_p)
|
||||||
for (i = 0; i < len; i++)
|
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);
|
gc, x + i, y, s->char2b + from + i, 1);
|
||||||
else
|
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);
|
gc, x, y, s->char2b + from, len);
|
||||||
}
|
}
|
||||||
unblock_input ();
|
unblock_input ();
|
||||||
|
|
|
||||||
|
|
@ -586,7 +586,7 @@ xftfont_get_xft_draw (struct frame *f)
|
||||||
{
|
{
|
||||||
block_input ();
|
block_input ();
|
||||||
xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
|
xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
|
||||||
FRAME_X_WINDOW (f),
|
FRAME_X_DRAWABLE (f),
|
||||||
FRAME_X_VISUAL (f),
|
FRAME_X_VISUAL (f),
|
||||||
FRAME_X_COLORMAP (f));
|
FRAME_X_COLORMAP (f));
|
||||||
unblock_input ();
|
unblock_input ();
|
||||||
|
|
@ -600,6 +600,8 @@ static int
|
||||||
xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
|
xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
|
||||||
bool with_background)
|
bool with_background)
|
||||||
{
|
{
|
||||||
|
block_input ();
|
||||||
|
|
||||||
struct frame *f = s->f;
|
struct frame *f = s->f;
|
||||||
struct face *face = s->face;
|
struct face *face = s->face;
|
||||||
struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
|
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;
|
xftface_info = (struct xftface_info *) face->extra;
|
||||||
xftfont_get_colors (f, face, s->gc, xftface_info,
|
xftfont_get_colors (f, face, s->gc, xftface_info,
|
||||||
&fg, with_background ? &bg : NULL);
|
&fg, with_background ? &bg : NULL);
|
||||||
block_input ();
|
|
||||||
if (s->num_clips > 0)
|
if (s->num_clips > 0)
|
||||||
XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
|
XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
|
||||||
else
|
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);
|
x + i, y, code + i, 1);
|
||||||
else
|
else
|
||||||
XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
|
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 ();
|
unblock_input ();
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -678,13 +682,10 @@ xftfont_shape (Lisp_Object lgstring)
|
||||||
static int
|
static int
|
||||||
xftfont_end_for_frame (struct frame *f)
|
xftfont_end_for_frame (struct frame *f)
|
||||||
{
|
{
|
||||||
|
block_input ();
|
||||||
XftDraw *xft_draw;
|
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);
|
xft_draw = font_get_frame_data (f, Qxft);
|
||||||
|
|
||||||
if (xft_draw)
|
if (xft_draw)
|
||||||
{
|
{
|
||||||
block_input ();
|
block_input ();
|
||||||
|
|
@ -692,9 +693,19 @@ xftfont_end_for_frame (struct frame *f)
|
||||||
unblock_input ();
|
unblock_input ();
|
||||||
font_put_frame_data (f, Qxft, NULL);
|
font_put_frame_data (f, Qxft, NULL);
|
||||||
}
|
}
|
||||||
|
unblock_input ();
|
||||||
return 0;
|
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
|
static bool
|
||||||
xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
|
xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
|
||||||
Lisp_Object entity)
|
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)
|
#if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
|
||||||
xftfont_driver.shape = xftfont_shape;
|
xftfont_driver.shape = xftfont_shape;
|
||||||
#endif
|
#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);
|
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>
|
#include <X11/extensions/Xrender.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XDBE
|
||||||
|
#include <X11/extensions/Xdbe.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Load sys/types.h if not already loaded.
|
/* Load sys/types.h if not already loaded.
|
||||||
In some systems loading it twice is suicidal. */
|
In some systems loading it twice is suicidal. */
|
||||||
#ifndef makedev
|
#ifndef makedev
|
||||||
|
|
@ -360,7 +364,7 @@ x_begin_cr_clip (struct frame *f, GC gc)
|
||||||
{
|
{
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
|
surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
|
||||||
FRAME_X_WINDOW (f),
|
FRAME_X_DRAWABLE (f),
|
||||||
FRAME_DISPLAY_INFO (f)->visual,
|
FRAME_DISPLAY_INFO (f)->visual,
|
||||||
FRAME_PIXEL_WIDTH (f),
|
FRAME_PIXEL_WIDTH (f),
|
||||||
FRAME_PIXEL_HEIGHT (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);
|
cairo_fill (cr);
|
||||||
x_end_cr_clip (f);
|
x_end_cr_clip (f);
|
||||||
#else
|
#else
|
||||||
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||||
gc, x, y, width, height);
|
gc, x, y, width, height);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -740,7 +744,7 @@ x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
|
||||||
cairo_stroke (cr);
|
cairo_stroke (cr);
|
||||||
x_end_cr_clip (f);
|
x_end_cr_clip (f);
|
||||||
#else
|
#else
|
||||||
XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
|
||||||
gc, x, y, width, height);
|
gc, x, y, width, height);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -756,7 +760,10 @@ x_clear_window (struct frame *f)
|
||||||
cairo_paint (cr);
|
cairo_paint (cr);
|
||||||
x_end_cr_clip (f);
|
x_end_cr_clip (f);
|
||||||
#else
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1067,7 +1074,7 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
|
||||||
#ifdef USE_CAIRO
|
#ifdef USE_CAIRO
|
||||||
x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
|
x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
|
||||||
#else
|
#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);
|
f->output_data.x->normal_gc, x, y0, x, y1);
|
||||||
#endif
|
#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
|
/* End update of frame F. This function is installed as a hook in
|
||||||
update_end. */
|
update_end. */
|
||||||
|
|
@ -1207,7 +1249,7 @@ x_update_end (struct frame *f)
|
||||||
if (! FRAME_EXTERNAL_MENU_BAR (f))
|
if (! FRAME_EXTERNAL_MENU_BAR (f))
|
||||||
height += FRAME_MENU_BAR_HEIGHT (f);
|
height += FRAME_MENU_BAR_HEIGHT (f);
|
||||||
surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
|
surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
|
||||||
FRAME_X_WINDOW (f),
|
FRAME_X_DRAWABLE (f),
|
||||||
FRAME_DISPLAY_INFO (f)->visual,
|
FRAME_DISPLAY_INFO (f)->visual,
|
||||||
width,
|
width,
|
||||||
height);
|
height);
|
||||||
|
|
@ -1220,7 +1262,7 @@ x_update_end (struct frame *f)
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
unblock_input ();
|
unblock_input ();
|
||||||
}
|
}
|
||||||
#endif /* USE_CAIRO */
|
#endif
|
||||||
|
|
||||||
#ifndef XFlush
|
#ifndef XFlush
|
||||||
block_input ();
|
block_input ();
|
||||||
|
|
@ -1229,17 +1271,26 @@ x_update_end (struct frame *f)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function is called from various places in xdisp.c
|
/* This function is called from various places in xdisp.c
|
||||||
whenever a complete update has been performed. */
|
whenever a complete update has been performed. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
XTframe_up_to_date (struct frame *f)
|
XTframe_up_to_date (struct frame *f)
|
||||||
{
|
{
|
||||||
if (FRAME_X_P (f))
|
eassert (FRAME_X_P (f));
|
||||||
FRAME_MOUSE_UPDATE (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). */
|
/* Clear under internal border if any (GTK has its own version). */
|
||||||
#ifndef USE_GTK
|
#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 */
|
#else /* not USE_CAIRO */
|
||||||
if (p->which)
|
if (p->which)
|
||||||
{
|
{
|
||||||
Window window = FRAME_X_WINDOW (f);
|
Drawable drawable = FRAME_X_DRAWABLE (f);
|
||||||
char *bits;
|
char *bits;
|
||||||
Pixmap pixmap, clipmask = (Pixmap) 0;
|
Pixmap pixmap, clipmask = (Pixmap) 0;
|
||||||
int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
|
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
|
/* Draw the bitmap. I believe these small pixmaps can be cached
|
||||||
by the server. */
|
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->cursor_p
|
||||||
? (p->overlay_p ? face->background
|
? (p->overlay_p ? face->background
|
||||||
: f->output_data.x->cursor_pixel)
|
: 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);
|
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);
|
p->wd, p->h, p->x, p->y);
|
||||||
XFreePixmap (display, pixmap);
|
XFreePixmap (display, pixmap);
|
||||||
|
|
||||||
|
|
@ -1487,7 +1538,7 @@ x_set_cursor_gc (struct glyph_string *s)
|
||||||
mask, &xgcv);
|
mask, &xgcv);
|
||||||
else
|
else
|
||||||
FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
|
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;
|
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);
|
mask, &xgcv);
|
||||||
else
|
else
|
||||||
FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
|
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;
|
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;
|
xgcv.stipple = dpyinfo->gray;
|
||||||
mask |= GCStipple;
|
mask |= GCStipple;
|
||||||
relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
|
relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
XChangeGC (dpy, relief->gc, mask, &xgcv);
|
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);
|
x_reset_clip_rectangles (f, bottom_right_gc);
|
||||||
#else
|
#else
|
||||||
Display *dpy = FRAME_X_DISPLAY (f);
|
Display *dpy = FRAME_X_DISPLAY (f);
|
||||||
Window window = FRAME_X_WINDOW (f);
|
Drawable drawable = FRAME_X_DRAWABLE (f);
|
||||||
int i;
|
int i;
|
||||||
GC gc;
|
GC gc;
|
||||||
|
|
||||||
|
|
@ -2715,12 +2766,12 @@ x_draw_relief_rect (struct frame *f,
|
||||||
if (top_p)
|
if (top_p)
|
||||||
{
|
{
|
||||||
if (width == 1)
|
if (width == 1)
|
||||||
XDrawLine (dpy, window, gc,
|
XDrawLine (dpy, drawable, gc,
|
||||||
left_x + left_p, top_y,
|
left_x + left_p, top_y,
|
||||||
right_x + !right_p, top_y);
|
right_x + !right_p, top_y);
|
||||||
|
|
||||||
for (i = 1; i < width; ++i)
|
for (i = 1; i < width; ++i)
|
||||||
XDrawLine (dpy, window, gc,
|
XDrawLine (dpy, drawable, gc,
|
||||||
left_x + i * left_p, top_y + i,
|
left_x + i * left_p, top_y + i,
|
||||||
right_x + 1 - i * right_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 (left_p)
|
||||||
{
|
{
|
||||||
if (width == 1)
|
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);
|
x_clear_area(f, left_x, top_y, 1, 1);
|
||||||
XClearArea (dpy, window, left_x, bottom_y, 1, 1, False);
|
x_clear_area(f, left_x, bottom_y, 1, 1);
|
||||||
|
|
||||||
for (i = (width > 1 ? 1 : 0); i < width; ++i)
|
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, top_y + (i + 1) * top_p,
|
||||||
left_x + i, bottom_y + 1 - (i + 1) * bot_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. */
|
/* Outermost top line. */
|
||||||
if (top_p)
|
if (top_p)
|
||||||
XDrawLine (dpy, window, gc,
|
XDrawLine (dpy, drawable, gc,
|
||||||
left_x + left_p, top_y,
|
left_x + left_p, top_y,
|
||||||
right_x + !right_p, top_y);
|
right_x + !right_p, top_y);
|
||||||
|
|
||||||
/* Outermost left line. */
|
/* Outermost left line. */
|
||||||
if (left_p)
|
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. */
|
/* Bottom. */
|
||||||
if (bot_p)
|
if (bot_p)
|
||||||
{
|
{
|
||||||
XDrawLine (dpy, window, gc,
|
XDrawLine (dpy, drawable, gc,
|
||||||
left_x + left_p, bottom_y,
|
left_x + left_p, bottom_y,
|
||||||
right_x + !right_p, bottom_y);
|
right_x + !right_p, bottom_y);
|
||||||
for (i = 1; i < width; ++i)
|
for (i = 1; i < width; ++i)
|
||||||
XDrawLine (dpy, window, gc,
|
XDrawLine (dpy, drawable, gc,
|
||||||
left_x + i * left_p, bottom_y - i,
|
left_x + i * left_p, bottom_y - i,
|
||||||
right_x + 1 - i * right_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. */
|
/* Right. */
|
||||||
if (right_p)
|
if (right_p)
|
||||||
{
|
{
|
||||||
XClearArea (dpy, window, right_x, top_y, 1, 1, False);
|
x_clear_area(f, right_x, top_y, 1, 1);
|
||||||
XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
|
x_clear_area(f, right_x, bottom_y, 1, 1);
|
||||||
for (i = 0; i < width; ++i)
|
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, top_y + (i + 1) * top_p,
|
||||||
right_x - i, bottom_y + 1 - (i + 1) * bot_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.width = s->slice.width;
|
||||||
image_rect.height = s->slice.height;
|
image_rect.height = s->slice.height;
|
||||||
if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
|
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,
|
s->slice.x + r.x - x, s->slice.y + r.y - y,
|
||||||
r.width, r.height, r.x, r.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.width = s->slice.width;
|
||||||
image_rect.height = s->slice.height;
|
image_rect.height = s->slice.height;
|
||||||
if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
|
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,
|
s->slice.x + r.x - x, s->slice.y + r.y - y,
|
||||||
r.width, r.height, r.x, r.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);
|
int depth = DefaultDepthOfScreen (screen);
|
||||||
|
|
||||||
/* Create a pixmap as large as the glyph string. */
|
/* 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->background_width,
|
||||||
s->height, depth);
|
s->height, depth);
|
||||||
|
|
||||||
|
|
@ -3259,7 +3312,7 @@ x_draw_image_glyph_string (struct glyph_string *s)
|
||||||
{
|
{
|
||||||
x_draw_image_foreground_1 (s, pixmap);
|
x_draw_image_foreground_1 (s, pixmap);
|
||||||
x_set_glyph_string_clipping (s);
|
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);
|
0, 0, s->background_width, s->height, s->x, s->y);
|
||||||
XFreePixmap (s->display, pixmap);
|
XFreePixmap (s->display, pixmap);
|
||||||
}
|
}
|
||||||
|
|
@ -3438,7 +3491,7 @@ x_draw_underwave (struct glyph_string *s)
|
||||||
|
|
||||||
while (x1 <= xmax)
|
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;
|
x1 = x2, y1 = y2;
|
||||||
x2 += dx, y2 = y0 + odd*dy;
|
x2 += dx, y2 = y0 + odd*dy;
|
||||||
odd = !odd;
|
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
|
/* Never called on a GUI frame, see
|
||||||
http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html
|
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,
|
f->output_data.x->normal_gc,
|
||||||
x, y, width, height,
|
x, y, width, height,
|
||||||
x + shift_by, y);
|
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);
|
cairo_fill (cr);
|
||||||
x_end_cr_clip (f);
|
x_end_cr_clip (f);
|
||||||
#else
|
#else
|
||||||
x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
|
if (FRAME_X_DOUBLE_BUFFERED_P (f))
|
||||||
x, y, width, height, False);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3799,19 +3858,13 @@ x_clear_frame (struct frame *f)
|
||||||
|
|
||||||
block_input ();
|
block_input ();
|
||||||
|
|
||||||
|
font_drop_xrender_surfaces (f);
|
||||||
x_clear_window (f);
|
x_clear_window (f);
|
||||||
|
|
||||||
/* We have to clear the scroll bars. If we have changed colors or
|
/* We have to clear the scroll bars. If we have changed colors or
|
||||||
something like that, then they should be notified. */
|
something like that, then they should be notified. */
|
||||||
x_scroll_bar_clear (f);
|
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));
|
XFlush (FRAME_X_DISPLAY (f));
|
||||||
|
|
||||||
unblock_input ();
|
unblock_input ();
|
||||||
|
|
@ -4109,7 +4162,7 @@ x_scroll_run (struct window *w, struct run *run)
|
||||||
SET_FRAME_GARBAGED (f);
|
SET_FRAME_GARBAGED (f);
|
||||||
#else
|
#else
|
||||||
XCopyArea (FRAME_X_DISPLAY (f),
|
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,
|
f->output_data.x->normal_gc,
|
||||||
x, from_y,
|
x, from_y,
|
||||||
width, height,
|
width, height,
|
||||||
|
|
@ -7448,6 +7501,26 @@ x_net_wm_state (struct frame *f, Window window)
|
||||||
/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
|
/** 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.
|
/* Handles the XEvent EVENT on display DPYINFO.
|
||||||
|
|
||||||
*FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
|
*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))
|
if (!FRAME_VISIBLE_P (f))
|
||||||
{
|
{
|
||||||
|
block_input ();
|
||||||
SET_FRAME_VISIBLE (f, 1);
|
SET_FRAME_VISIBLE (f, 1);
|
||||||
SET_FRAME_ICONIFIED (f, false);
|
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;
|
f->output_data.x->has_been_visible = true;
|
||||||
SET_FRAME_GARBAGED (f);
|
SET_FRAME_GARBAGED (f);
|
||||||
|
unblock_input ();
|
||||||
}
|
}
|
||||||
else
|
else if (FRAME_GARBAGED_P (f))
|
||||||
{
|
{
|
||||||
#ifdef USE_GTK
|
#ifdef USE_GTK
|
||||||
/* This seems to be needed for GTK 2.6 and later, see
|
/* Go around the back buffer and manually clear the
|
||||||
http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
|
window the first time we show it. This way, we avoid
|
||||||
x_clear_area (f,
|
showing users the sanity-defying horror of whatever
|
||||||
event->xexpose.x, event->xexpose.y,
|
GtkWindow is rendering beneath us. We've garbaged
|
||||||
event->xexpose.width, event->xexpose.height);
|
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
|
#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);
|
event->xexpose.width, event->xexpose.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!FRAME_GARBAGED_P (f))
|
||||||
|
show_back_buffer (f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -7822,10 +7921,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||||
available. */
|
available. */
|
||||||
f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
|
f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
|
||||||
if (f)
|
if (f)
|
||||||
expose_frame (f, event->xgraphicsexpose.x,
|
{
|
||||||
event->xgraphicsexpose.y,
|
expose_frame (f, event->xgraphicsexpose.x,
|
||||||
event->xgraphicsexpose.width,
|
event->xgraphicsexpose.y,
|
||||||
event->xgraphicsexpose.height);
|
event->xgraphicsexpose.width,
|
||||||
|
event->xgraphicsexpose.height);
|
||||||
|
show_back_buffer (f);
|
||||||
|
}
|
||||||
#ifdef USE_X_TOOLKIT
|
#ifdef USE_X_TOOLKIT
|
||||||
else
|
else
|
||||||
goto OTHER;
|
goto OTHER;
|
||||||
|
|
@ -8410,7 +8512,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||||
else
|
else
|
||||||
configureEvent = next_event;
|
configureEvent = next_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
|
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
|
#ifdef USE_CAIRO
|
||||||
if (f) x_cr_destroy_surface (f);
|
if (f) x_cr_destroy_surface (f);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -8419,6 +8531,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||||
&& (f = any)
|
&& (f = any)
|
||||||
&& configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
|
&& 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,
|
xg_frame_resized (f, configureEvent.xconfigure.width,
|
||||||
configureEvent.xconfigure.height);
|
configureEvent.xconfigure.height);
|
||||||
#ifdef USE_CAIRO
|
#ifdef USE_CAIRO
|
||||||
|
|
@ -8429,7 +8545,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||||
#endif
|
#endif
|
||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
x_net_wm_state (f, configureEvent.xconfigure.window);
|
|
||||||
|
x_net_wm_state (f, configureEvent.xconfigure.window);
|
||||||
|
|
||||||
#ifdef USE_X_TOOLKIT
|
#ifdef USE_X_TOOLKIT
|
||||||
/* Tip frames are pure X window, set size for them. */
|
/* 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
|
if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
|
||||||
|| FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
|
|| FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
|
||||||
SET_FRAME_GARBAGED (f);
|
{
|
||||||
|
SET_FRAME_GARBAGED (f);
|
||||||
|
}
|
||||||
FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
|
FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
|
||||||
FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
|
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))
|
|| configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
|
||||||
{
|
{
|
||||||
change_frame_size (f, width, height, false, true, false, true);
|
change_frame_size (f, width, height, false, true, false, true);
|
||||||
x_clear_under_internal_border (f);
|
x_clear_under_internal_border (f);
|
||||||
SET_FRAME_GARBAGED (f);
|
SET_FRAME_GARBAGED (f);
|
||||||
cancel_mouse_face (f);
|
cancel_mouse_face (f);
|
||||||
}
|
}
|
||||||
#endif /* not USE_GTK */
|
#endif /* not USE_GTK */
|
||||||
|
|
@ -8688,6 +8807,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
||||||
count++;
|
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 ();
|
SAFE_FREE ();
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
@ -8880,7 +9002,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
|
||||||
if (dpyinfo->scratch_cursor_gc)
|
if (dpyinfo->scratch_cursor_gc)
|
||||||
XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
|
XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
|
||||||
else
|
else
|
||||||
dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
|
dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
|
||||||
GCForeground, &xgcv);
|
GCForeground, &xgcv);
|
||||||
gc = dpyinfo->scratch_cursor_gc;
|
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
|
else
|
||||||
{
|
{
|
||||||
Display *dpy = FRAME_X_DISPLAY (f);
|
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;
|
GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
|
||||||
unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
|
unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
|
||||||
struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
|
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);
|
XChangeGC (dpy, gc, mask, &xgcv);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gc = XCreateGC (dpy, window, mask, &xgcv);
|
gc = XCreateGC (dpy, drawable, mask, &xgcv);
|
||||||
FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
|
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_frame_area (struct frame *f, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
x_clear_area (f, x, y, width, 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))
|
if (! FRAME_VISIBLE_P (f))
|
||||||
{
|
{
|
||||||
/* We test FRAME_GARBAGED_P here to make sure we don't
|
/* We test asked_for_visible here to make sure we don't
|
||||||
call x_set_offset a second time
|
call x_set_offset a second time
|
||||||
if we get to x_make_frame_visible a second time
|
if we get to x_make_frame_visible a second time
|
||||||
before the window gets really visible. */
|
before the window gets really visible. */
|
||||||
if (! FRAME_ICONIFIED_P (f)
|
if (! FRAME_ICONIFIED_P (f)
|
||||||
&& ! FRAME_X_EMBEDDED_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. */
|
will set it when they are handled. */
|
||||||
bool previously_visible = f->output_data.x->has_been_visible;
|
bool previously_visible = f->output_data.x->has_been_visible;
|
||||||
|
|
||||||
|
XSETFRAME (frame, f);
|
||||||
|
|
||||||
original_left = f->left_pos;
|
original_left = f->left_pos;
|
||||||
original_top = f->top_pos;
|
original_top = f->top_pos;
|
||||||
|
|
||||||
|
|
@ -10981,8 +11100,6 @@ x_make_frame_visible (struct frame *f)
|
||||||
unblock_input ();
|
unblock_input ();
|
||||||
}
|
}
|
||||||
|
|
||||||
XSETFRAME (frame, f);
|
|
||||||
|
|
||||||
/* Process X events until a MapNotify event has been seen. */
|
/* Process X events until a MapNotify event has been seen. */
|
||||||
while (!FRAME_VISIBLE_P (f))
|
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
|
font-driver (e.g. xft) access a window while finishing a
|
||||||
face. */
|
face. */
|
||||||
free_frame_faces (f);
|
free_frame_faces (f);
|
||||||
|
tear_down_x_back_buffer (f);
|
||||||
|
|
||||||
if (f->output_data.x->icon_desc)
|
if (f->output_data.x->icon_desc)
|
||||||
XDestroyWindow (FRAME_X_DISPLAY (f), 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
|
/* Tooltips don't have widgets, only a simple X window, even if
|
||||||
we are using a toolkit. */
|
we are using a toolkit. */
|
||||||
else if (FRAME_X_WINDOW (f))
|
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);
|
free_frame_menubar (f);
|
||||||
|
|
||||||
|
|
@ -11270,8 +11388,9 @@ x_free_frame_resources (struct frame *f)
|
||||||
xg_free_frame_widgets (f);
|
xg_free_frame_widgets (f);
|
||||||
#endif /* USE_GTK */
|
#endif /* USE_GTK */
|
||||||
|
|
||||||
|
tear_down_x_back_buffer (f);
|
||||||
if (FRAME_X_WINDOW (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 */
|
#endif /* !USE_X_TOOLKIT */
|
||||||
|
|
||||||
unload_color (f, FRAME_FOREGROUND_PIXEL (f));
|
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
|
else
|
||||||
dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
|
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
|
#ifdef HAVE_XFT
|
||||||
{
|
{
|
||||||
|
|
@ -12462,7 +12589,7 @@ static struct redisplay_interface x_redisplay_interface =
|
||||||
x_after_update_window_line,
|
x_after_update_window_line,
|
||||||
x_update_window_begin,
|
x_update_window_begin,
|
||||||
x_update_window_end,
|
x_update_window_end,
|
||||||
x_flush,
|
x_flip_and_flush,
|
||||||
x_clear_window_mouse_face,
|
x_clear_window_mouse_face,
|
||||||
x_get_glyph_overhangs,
|
x_get_glyph_overhangs,
|
||||||
x_fix_overlapping_area,
|
x_fix_overlapping_area,
|
||||||
|
|
@ -12592,6 +12719,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
|
||||||
terminal->update_end_hook = x_update_end;
|
terminal->update_end_hook = x_update_end;
|
||||||
terminal->read_socket_hook = XTread_socket;
|
terminal->read_socket_hook = XTread_socket;
|
||||||
terminal->frame_up_to_date_hook = XTframe_up_to_date;
|
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->mouse_position_hook = XTmouse_position;
|
||||||
terminal->frame_rehighlight_hook = XTframe_rehighlight;
|
terminal->frame_rehighlight_hook = XTframe_rehighlight;
|
||||||
terminal->frame_raise_lower_hook = XTframe_raise_lower;
|
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
|
#ifdef USE_XCB
|
||||||
xcb_connection_t *xcb_connection;
|
xcb_connection_t *xcb_connection;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XDBE
|
||||||
|
bool supports_xdbe;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_X_I18N
|
#ifdef HAVE_X_I18N
|
||||||
|
|
@ -527,6 +531,16 @@ struct x_output
|
||||||
and the X window has not yet been created. */
|
and the X window has not yet been created. */
|
||||||
Window window_desc;
|
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;
|
/* The X window used for the bitmap icon;
|
||||||
or 0 if we don't have a bitmap icon. */
|
or 0 if we don't have a bitmap icon. */
|
||||||
Window icon_desc;
|
Window icon_desc;
|
||||||
|
|
@ -737,6 +751,24 @@ enum
|
||||||
/* Return the X window used for displaying data in frame F. */
|
/* Return the X window used for displaying data in frame F. */
|
||||||
#define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc)
|
#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. */
|
/* Return the outermost X window associated with the frame F. */
|
||||||
#ifdef USE_X_TOOLKIT
|
#ifdef USE_X_TOOLKIT
|
||||||
#define FRAME_OUTER_WINDOW(f) ((f)->output_data.x->widget ? \
|
#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_wait_for_event (struct frame *, int);
|
||||||
extern void x_clear_under_internal_border (struct frame *f);
|
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. */
|
/* Defined in xselect.c. */
|
||||||
|
|
||||||
extern void x_handle_property_notify (const XPropertyEvent *);
|
extern void x_handle_property_notify (const XPropertyEvent *);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue