X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/016b9ec0c84124bc7754014c447fb08ae2f2df47..1087305574fd61256d66eb0c995f8bb74bd91afe:/src/xterm.c
diff --git a/src/xterm.c b/src/xterm.c
index c1970cc433..5756378bd3 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -22,10 +22,12 @@ along with GNU Emacs. If not, see . */
#include
#include
+#ifdef USE_CAIRO
+#include
+#endif
#include "lisp.h"
#include "blockinput.h"
-#include "syssignal.h"
/* This may include sys/types.h, and that somehow loses
if this is not done before the other system files. */
@@ -55,12 +57,9 @@ along with GNU Emacs. If not, see . */
#include
#include
#include
-/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
-/* #include */
-
-#include "charset.h"
#include "character.h"
#include "coding.h"
+#include "composite.h"
#include "frame.h"
#include "dispextern.h"
#include "fontset.h"
@@ -68,17 +67,12 @@ along with GNU Emacs. If not, see . */
#include "termopts.h"
#include "termchar.h"
#include "emacs-icon.h"
-#include "disptab.h"
#include "buffer.h"
#include "window.h"
#include "keyboard.h"
-#include "intervals.h"
-#include "process.h"
#include "atimer.h"
-#include "keymap.h"
#include "font.h"
#include "xsettings.h"
-#include "xgselect.h"
#include "sysselect.h"
#include "menu.h"
@@ -211,34 +205,16 @@ enum xembed_message
XEMBED_ACTIVATE_ACCELERATOR = 14
};
+static void x_free_cr_resources (struct frame *);
static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
-static void x_set_window_size_1 (struct frame *, bool, int, int);
static void x_raise_frame (struct frame *);
static void x_lower_frame (struct frame *);
-static const XColor *x_color_cells (Display *, int *);
static int x_io_error_quitter (Display *);
static struct terminal *x_create_terminal (struct x_display_info *);
-static void x_update_end (struct frame *);
-static void XTframe_up_to_date (struct frame *);
-static void x_clear_area1 (Display *, Window, int, int, int, int, int);
-static void x_clear_frame (struct frame *);
-static _Noreturn void x_ins_del_lines (struct frame *, int, int);
-static void frame_highlight (struct frame *);
-static void frame_unhighlight (struct frame *);
-static void x_new_focus_frame (struct x_display_info *, struct frame *);
-static void x_focus_changed (int, int, struct x_display_info *,
- struct frame *, struct input_event *);
-static void XTframe_rehighlight (struct frame *);
static void x_frame_rehighlight (struct x_display_info *);
-static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
-static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
- enum text_cursor_kinds);
static void x_clip_to_row (struct window *, struct glyph_row *,
enum glyph_row_area, GC);
-static void x_flush (struct frame *f);
-static void x_update_begin (struct frame *);
-static void x_update_window_begin (struct window *);
static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
enum scroll_bar_part *,
@@ -258,9 +234,6 @@ static int handle_one_xevent (struct x_display_info *,
#if ! (defined USE_X_TOOLKIT || defined USE_MOTIF)
static int x_dispatch_event (XEvent *, Display *);
#endif
-/* Don't declare this _Noreturn because we want no
- interference with debugging failing X calls. */
-static void x_connection_closed (Display *, const char *);
static void x_wm_set_window_state (struct frame *, int);
static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
static void x_initialize (void);
@@ -326,21 +299,7 @@ record_event (char *locus, int type)
#endif
-static void x_prepare_for_xlibdraw (struct frame *);
-static void x_set_clip_rectangles (struct frame *, GC, XRectangle *, int);
-static void x_reset_clip_rectangles (struct frame *, GC);
-static void x_fill_rectangle (struct frame *, GC, int, int, int, int);
-static void x_draw_rectangle (struct frame *, GC, int, int, int, int);
-static void x_fill_trapezoid_for_relief (struct frame *, GC, int, int,
- int, int, int);
-static void x_clear_window (struct frame *);
-
#ifdef USE_CAIRO
-static struct x_gc_ext_data *x_gc_get_ext_data (struct frame *, GC, int);
-static void x_extension_initialize (struct x_display_info *);
-static cairo_status_t x_cr_accumulate_data (void *,
- const unsigned char *,
- unsigned int);
#define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
#define FRAME_CR_SURFACE(f) ((f)->output_data.x->cr_surface)
@@ -571,7 +530,7 @@ x_cr_draw_frame (cairo_t *cr, struct frame *f)
width = FRAME_PIXEL_WIDTH (f);
height = FRAME_PIXEL_HEIGHT (f);
- x_prepare_for_xlibdraw (f);
+ x_free_cr_resources (f);
FRAME_CR_CONTEXT (f) = cr;
x_clear_area (f, 0, 0, width, height);
expose_frame (f, 0, 0, width, height);
@@ -584,7 +543,7 @@ x_cr_accumulate_data (void *closure, const unsigned char *data,
{
Lisp_Object *acc = (Lisp_Object *) closure;
- *acc = Fcons (make_unibyte_string (data, length), *acc);
+ *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
return CAIRO_STATUS_SUCCESS;
}
@@ -607,7 +566,7 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
cairo_t *cr;
int width, height;
void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
- Lisp_Object acc = Qnil, args[2];
+ Lisp_Object acc = Qnil;
int count = SPECPDL_INDEX ();
Fredisplay (Qt);
@@ -659,7 +618,7 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
QUIT;
block_input ();
- x_prepare_for_xlibdraw (f);
+ x_free_cr_resources (f);
FRAME_CR_CONTEXT (f) = cr;
x_clear_area (f, 0, 0, width, height);
expose_frame (f, 0, 0, width, height);
@@ -691,15 +650,13 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
#endif
unbind_to (count, Qnil);
- args[0] = intern ("concat");
- args[1] = Fnreverse (acc);
- return Fapply (2, args);
+ return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
}
#endif /* USE_CAIRO */
static void
-x_prepare_for_xlibdraw (struct frame *f)
+x_free_cr_resources (struct frame *f)
{
#ifdef USE_CAIRO
if (f == NULL)
@@ -707,7 +664,7 @@ x_prepare_for_xlibdraw (struct frame *f)
Lisp_Object rest, frame;
FOR_EACH_FRAME (rest, frame)
if (FRAME_X_P (XFRAME (frame)))
- x_prepare_for_xlibdraw (XFRAME (frame));
+ x_free_cr_resources (XFRAME (frame));
}
else
{
@@ -824,6 +781,48 @@ x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
x_end_cr_clip (f);
}
+enum corners
+ {
+ CORNER_BOTTOM_RIGHT, /* 0 -> pi/2 */
+ CORNER_BOTTOM_LEFT, /* pi/2 -> pi */
+ CORNER_TOP_LEFT, /* pi -> 3pi/2 */
+ CORNER_TOP_RIGHT, /* 3pi/2 -> 2pi */
+ CORNER_LAST
+ };
+
+static void
+x_erase_corners_for_relief (struct frame *f, GC gc, int x, int y,
+ int width, int height,
+ double radius, double margin, int corners)
+{
+ cairo_t *cr;
+ int i;
+
+ cr = x_begin_cr_clip (f, gc);
+ x_set_cr_source_with_gc_background (f, gc);
+ for (i = 0; i < CORNER_LAST; i++)
+ if (corners & (1 << i))
+ {
+ double xm, ym, xc, yc;
+
+ if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT)
+ xm = x - margin, xc = xm + radius;
+ else
+ xm = x + width + margin, xc = xm - radius;
+ if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT)
+ ym = y - margin, yc = ym + radius;
+ else
+ ym = y + height + margin, yc = ym - radius;
+
+ cairo_move_to (cr, xm, ym);
+ cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2);
+ }
+ cairo_clip (cr);
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_fill (cr);
+ x_end_cr_clip (f);
+}
+
static void
x_draw_horizontal_wave (struct frame *f, GC gc, int x, int y,
int width, int height, int wave_length)
@@ -993,6 +992,10 @@ static void
x_update_begin (struct frame *f)
{
#ifdef USE_CAIRO
+ if (! NILP (tip_frame) && XFRAME (tip_frame) == f
+ && ! FRAME_VISIBLE_P (f))
+ return;
+
if (! FRAME_CR_SURFACE (f))
{
int width, height;
@@ -1710,6 +1713,11 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
s->background_filled_p = true;
}
else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+ /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
+ font dimensions, since the actual glyphs might be
+ much smaller. So in that case we always clear the
+ rectangle with background color. */
+ || FONT_TOO_HIGH (s->font)
|| s->font_not_found_p
|| s->extends_to_end_of_line_p
|| force_p)
@@ -1906,7 +1914,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
{
sprintf (buf, "%0*X",
glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
- glyph->u.glyphless.ch);
+ glyph->u.glyphless.ch + 0u);
str = buf;
}
@@ -1999,9 +2007,9 @@ x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap
static XtConvertArgRec cvt_string_to_pixel_args[] =
{
- {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
+ {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.screen),
sizeof (Screen *)},
- {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
+ {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.colormap),
sizeof (Colormap)}
};
@@ -2077,7 +2085,7 @@ cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
params[0] = color_name;
XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
"badValue", "cvt_string_to_pixel",
- "XtToolkitError", "Invalid color `%s'",
+ "XtToolkitError", "Invalid color '%s'",
params, &nparams);
return False;
}
@@ -2180,6 +2188,50 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ if (dpyinfo->red_bits > 0)
+ {
+ /* For TrueColor displays, we can decompose the RGB value
+ directly. */
+ int i;
+ unsigned int rmult, gmult, bmult;
+ unsigned int rmask, gmask, bmask;
+
+ rmask = (1 << dpyinfo->red_bits) - 1;
+ gmask = (1 << dpyinfo->green_bits) - 1;
+ bmask = (1 << dpyinfo->blue_bits) - 1;
+ /* If we're widening, for example, 8 bits in the pixel value to
+ 16 bits for the separate-color representation, we want to
+ extrapolate the lower bits based on those bits available --
+ in other words, we'd like 0xff to become 0xffff instead of
+ the 0xff00 we'd get by just zero-filling the lower bits.
+
+ We generate a 32-bit scaled-up value and shift it, in case
+ the bit count doesn't divide 16 evenly (e.g., when dealing
+ with a 3-3-2 bit RGB display), to get more of the lower bits
+ correct.
+
+ Should we cache the multipliers in dpyinfo? Maybe
+ special-case the 8-8-8 common case? */
+ rmult = 0xffffffff / rmask;
+ gmult = 0xffffffff / gmask;
+ bmult = 0xffffffff / bmask;
+
+ for (i = 0; i < ncolors; ++i)
+ {
+ unsigned int r, g, b;
+ unsigned long pixel = colors[i].pixel;
+
+ r = (pixel >> dpyinfo->red_offset) & rmask;
+ g = (pixel >> dpyinfo->green_offset) & gmask;
+ b = (pixel >> dpyinfo->blue_offset) & bmask;
+
+ colors[i].red = (r * rmult) >> 16;
+ colors[i].green = (g * gmult) >> 16;
+ colors[i].blue = (b * bmult) >> 16;
+ }
+ return;
+ }
+
if (dpyinfo->color_cells)
{
int i;
@@ -2190,9 +2242,10 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors)
eassert (dpyinfo->color_cells[pixel].pixel == pixel);
colors[i] = dpyinfo->color_cells[pixel];
}
+ return;
}
- else
- XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
+
+ XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
}
@@ -2206,6 +2259,51 @@ x_query_color (struct frame *f, XColor *color)
}
+/* On frame F, translate the color name to RGB values. Use cached
+ information, if possible.
+
+ Note that there is currently no way to clean old entries out of the
+ cache. However, it is limited to names in the server's database,
+ and names we've actually looked up; list-colors-display is probably
+ the most color-intensive case we're likely to hit. */
+
+Status x_parse_color (struct frame *f, const char *color_name,
+ XColor *color)
+{
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Colormap cmap = FRAME_X_COLORMAP (f);
+ struct color_name_cache_entry *cache_entry;
+
+ if (color_name[0] == '#')
+ {
+ /* The hex form is parsed directly by XParseColor without
+ talking to the X server. No need for caching. */
+ return XParseColor (dpy, cmap, color_name, color);
+ }
+
+ for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry;
+ cache_entry = cache_entry->next)
+ {
+ if (!xstrcasecmp(cache_entry->name, color_name))
+ {
+ *color = cache_entry->rgb;
+ return 1;
+ }
+ }
+
+ if (XParseColor (dpy, cmap, color_name, color) == 0)
+ /* No caching of negative results, currently. */
+ return 0;
+
+ cache_entry = xzalloc (sizeof *cache_entry);
+ cache_entry->rgb = *color;
+ cache_entry->name = xstrdup (color_name);
+ cache_entry->next = FRAME_DISPLAY_INFO (f)->color_names;
+ FRAME_DISPLAY_INFO (f)->color_names = cache_entry;
+ return 1;
+}
+
+
/* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
exact match can't be allocated, try the nearest color available.
Value is true if successful. Set *COLOR to the color
@@ -2278,15 +2376,27 @@ x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
}
-/* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
- exact match can't be allocated, try the nearest color available.
- Value is true if successful. Set *COLOR to the color
- allocated. */
+/* Allocate the color COLOR->pixel on frame F, colormap CMAP, after
+ gamma correction. If an exact match can't be allocated, try the
+ nearest color available. Value is true if successful. Set *COLOR
+ to the color allocated. */
bool
x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
{
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+
gamma_correct (f, color);
+
+ if (dpyinfo->red_bits > 0)
+ {
+ color->pixel = x_make_truecolor_pixel (dpyinfo,
+ color->red,
+ color->green,
+ color->blue);
+ return true;
+ }
+
return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
}
@@ -2300,8 +2410,16 @@ x_copy_color (struct frame *f, unsigned long pixel)
{
XColor color;
+ /* If display has an immutable color map, freeing colors is not
+ necessary and some servers don't allow it. Since we won't free a
+ color once we've allocated it, we don't need to re-allocate it to
+ maintain the server's reference count. */
+ if (!x_mutable_colormap (FRAME_X_VISUAL (f)))
+ return pixel;
+
color.pixel = pixel;
block_input ();
+ /* The color could still be found in the color_cells array. */
x_query_color (f, &color);
XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
unblock_input ();
@@ -2505,6 +2623,7 @@ x_draw_relief_rect (struct frame *f,
{
#ifdef USE_CAIRO
GC top_left_gc, bottom_right_gc;
+ int corners = 0;
if (raised_p)
{
@@ -2521,11 +2640,23 @@ x_draw_relief_rect (struct frame *f,
x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
if (left_p)
- x_fill_rectangle (f, top_left_gc, left_x, top_y,
- width, bottom_y + 1 - top_y);
+ {
+ x_fill_rectangle (f, top_left_gc, left_x, top_y,
+ width, bottom_y + 1 - top_y);
+ if (top_p)
+ corners |= 1 << CORNER_TOP_LEFT;
+ if (bot_p)
+ corners |= 1 << CORNER_BOTTOM_LEFT;
+ }
if (right_p)
- x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
- width, bottom_y + 1 - top_y);
+ {
+ x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
+ width, bottom_y + 1 - top_y);
+ if (top_p)
+ corners |= 1 << CORNER_TOP_RIGHT;
+ if (bot_p)
+ corners |= 1 << CORNER_BOTTOM_RIGHT;
+ }
if (top_p)
{
if (!right_p)
@@ -2545,6 +2676,20 @@ x_draw_relief_rect (struct frame *f,
left_x, bottom_y + 1 - width,
right_x + 1 - left_x, width, 0);
}
+ if (left_p && width != 1)
+ x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
+ 1, bottom_y + 1 - top_y);
+ if (top_p && width != 1)
+ x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
+ right_x + 1 - left_x, 1);
+ if (corners)
+ {
+ XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
+ FRAME_BACKGROUND_PIXEL (f));
+ x_erase_corners_for_relief (f, top_left_gc, left_x, top_y,
+ right_x - left_x + 1, bottom_y - top_y + 1,
+ 6, 1, corners);
+ }
x_reset_clip_rectangles (f, top_left_gc);
x_reset_clip_rectangles (f, bottom_right_gc);
@@ -3091,6 +3236,7 @@ x_draw_image_glyph_string (struct glyph_string *s)
}
/* Draw the foreground. */
+#ifdef USE_CAIRO
if (s->img->cr_data)
{
cairo_t *cr = x_begin_cr_clip (s->f, s->gc);
@@ -3106,7 +3252,9 @@ x_draw_image_glyph_string (struct glyph_string *s)
cairo_fill (cr);
x_end_cr_clip (s->f);
}
- else if (pixmap != None)
+ else
+#endif
+ if (pixmap != None)
{
x_draw_image_foreground_1 (s, pixmap);
x_set_glyph_string_clipping (s);
@@ -3585,7 +3733,9 @@ x_draw_glyph_string (struct glyph_string *s)
static void
x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
{
- x_prepare_for_xlibdraw (f);
+/* Never called on a GUI frame, see
+ http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html
+*/
XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
f->output_data.x->normal_gc,
x, y, width, height,
@@ -4833,7 +4983,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
f1 = 0;
- x_uncatch_errors ();
+ x_uncatch_errors_after_check ();
/* If not, is it one of our scroll bars? */
if (! f1)
@@ -5356,6 +5506,8 @@ xg_scroll_callback (GtkRange *range,
? scroll_bar_after_handle : scroll_bar_below_handle);
bar->dragging = -1;
break;
+ default:
+ break;
}
if (part != scroll_bar_nowhere)
@@ -6355,7 +6507,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
x_clear_area1 (FRAME_X_DISPLAY (f), w,
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER,
- inside_width, start);
+ inside_width, start, False);
/* Change to proper foreground color if one is specified. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
@@ -6363,7 +6515,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
f->output_data.x->scroll_bar_foreground_pixel);
/* Draw the handle itself. */
- x_fill_rectangle (f, gc,
+ XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
/* x, y, width, height */
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER + start,
@@ -6380,7 +6532,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
x_clear_area1 (FRAME_X_DISPLAY (f), w,
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER + end,
- inside_width, inside_height - end);
+ inside_width, inside_height - end, False);
}
unblock_input ();
@@ -6614,8 +6766,7 @@ XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int posit
int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
int rest = area_height - height;
if (rest > 0 && width > 0)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, rest);
+ x_clear_area (f, left, top, width, rest);
}
/* Move/size the scroll bar window. */
@@ -6839,7 +6990,7 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
f->output_data.x->scroll_bar_foreground_pixel);
/* Draw a one-pixel border just inside the edges of the scroll bar. */
- x_draw_rectangle (f, gc,
+ XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
/* x, y, width, height */
0, 0, bar->width - 1, bar->height - 1);
@@ -7308,10 +7459,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
const XEvent *event,
int *finish, struct input_event *hold_quit)
{
- union {
- struct input_event ie;
- struct selection_input_event sie;
- } inev;
+ union buffered_input_event inev;
int count = 0;
int do_help = 0;
ptrdiff_t nbytes = 0;
@@ -7323,6 +7471,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
says that a portable program can't use this, but Stephen Gildea assures
me that letting the compiler initialize it to zeros will work okay. */
static XComposeStatus compose_status;
+ XEvent configureEvent;
+ XEvent next_event;
USE_SAFE_ALLOCA;
@@ -7383,9 +7533,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
the only valid choice. */
RevertToParent,
event->xclient.data.l[1]);
- /* This is needed to detect the error
- if there is an error. */
- XSync (d, False);
x_uncatch_errors ();
}
/* Not certain about handling scroll bars here */
@@ -7539,7 +7686,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
const XSelectionClearEvent *eventp = &event->xselectionclear;
- inev.ie.kind = SELECTION_CLEAR_EVENT;
+ inev.sie.kind = SELECTION_CLEAR_EVENT;
SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
@@ -7555,7 +7702,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
const XSelectionRequestEvent *eventp = &event->xselectionrequest;
- inev.ie.kind = SELECTION_REQUEST_EVENT;
+ inev.sie.kind = SELECTION_REQUEST_EVENT;
SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
@@ -7623,7 +7770,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
else
{
-#if defined (USE_GTK) && ! defined (HAVE_GTK3) && ! defined (USE_CAIRO)
+#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,
@@ -7720,11 +7867,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto OTHER;
case MapNotify:
- if (event->xmap.window == tip_window)
- /* The tooltip has been drawn already. Avoid
- the SET_FRAME_GARBAGED below. */
- goto OTHER;
-
/* We use x_top_window_to_frame because map events can
come for sub-windows and they don't mean that the
frame is visible. */
@@ -7771,17 +7913,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
f = any;
-#if ! defined (USE_GTK)
/* If mouse-highlight is an integer, input clears out
mouse highlighting. */
if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+#if ! defined (USE_GTK)
&& (f == 0
- || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)))
+ || !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
+#endif
+ )
{
clear_mouse_face (hlinfo);
hlinfo->mouse_face_hidden = true;
}
-#endif
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
if (f == 0)
@@ -8070,7 +8213,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
? ASCII_KEYSTROKE_EVENT
: MULTIBYTE_CHAR_KEYSTROKE_EVENT);
inev.ie.code = ch;
- kbd_buffer_store_event_hold (&inev.ie, hold_quit);
+ kbd_buffer_store_buffered_event (&inev, hold_quit);
}
count += nchars;
@@ -8239,29 +8382,74 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
case ConfigureNotify:
- f = x_top_window_to_frame (dpyinfo, event->xconfigure.window);
+ /* An opaque move can generate a stream of events as the window
+ is dragged around. If the connection round trip time isn't
+ really short, they may come faster than we can respond to
+ them, given the multiple queries we can do to check window
+ manager state, translate coordinates, etc.
+
+ So if this ConfigureNotify is immediately followed by another
+ for the same window, use the info from the latest update, and
+ consider the events all handled. */
+ /* Opaque resize may be trickier; ConfigureNotify events are
+ mixed with Expose events for multiple windows. */
+ configureEvent = *event;
+ while (XPending (dpyinfo->display))
+ {
+ XNextEvent (dpyinfo->display, &next_event);
+ if (next_event.type != ConfigureNotify
+ || next_event.xconfigure.window != event->xconfigure.window
+ /* Skipping events with different sizes can lead to a
+ mispositioned mode line at initial window creation.
+ Only drop window motion events for now. */
+ || next_event.xconfigure.width != event->xconfigure.width
+ || next_event.xconfigure.height != event->xconfigure.height)
+ {
+ XPutBackEvent (dpyinfo->display, &next_event);
+ break;
+ }
+ else
+ configureEvent = next_event;
+ }
+ f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
#ifdef USE_CAIRO
if (f) x_cr_destroy_surface (f);
#endif
#ifdef USE_GTK
if (!f
&& (f = any)
- && event->xconfigure.window == FRAME_X_WINDOW (f))
+ && configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
{
- xg_frame_resized (f, event->xconfigure.width,
- event->xconfigure.height);
+ xg_frame_resized (f, configureEvent.xconfigure.width,
+ configureEvent.xconfigure.height);
+#ifdef USE_CAIRO
x_cr_destroy_surface (f);
+#endif
f = 0;
}
#endif
if (f)
{
- x_net_wm_state (f, event->xconfigure.window);
+ x_net_wm_state (f, configureEvent.xconfigure.window);
+
+#ifdef USE_X_TOOLKIT
+ /* Tip frames are pure X window, set size for them. */
+ if (! NILP (tip_frame) && XFRAME (tip_frame) == f)
+ {
+ if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
+ || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
+ SET_FRAME_GARBAGED (f);
+ FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
+ FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
+ }
+#endif
#ifndef USE_X_TOOLKIT
#ifndef USE_GTK
- int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width);
- int height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, event->xconfigure.height);
+ int width =
+ FRAME_PIXEL_TO_TEXT_WIDTH (f, configureEvent.xconfigure.width);
+ int height =
+ FRAME_PIXEL_TO_TEXT_HEIGHT (f, configureEvent.xconfigure.height);
/* In the toolkit version, change_frame_size
is called by the code that handles resizing
@@ -8272,8 +8460,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
to check the pixel dimensions as well. */
if (width != FRAME_TEXT_WIDTH (f)
|| height != FRAME_TEXT_HEIGHT (f)
- || event->xconfigure.width != FRAME_PIXEL_WIDTH (f)
- || event->xconfigure.height != FRAME_PIXEL_HEIGHT (f))
+ || configureEvent.xconfigure.width != FRAME_PIXEL_WIDTH (f)
+ || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
{
change_frame_size (f, width, height, false, true, false, true);
x_clear_under_internal_border (f);
@@ -8473,7 +8661,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
done:
if (inev.ie.kind != NO_EVENT)
{
- kbd_buffer_store_event_hold (&inev.ie, hold_quit);
+ kbd_buffer_store_buffered_event (&inev, hold_quit);
count++;
}
@@ -9026,6 +9214,8 @@ x_text_icon (struct frame *f, const char *icon_name)
struct x_error_message_stack {
char string[X_ERROR_MESSAGE_SIZE];
Display *dpy;
+ x_special_error_handler handler;
+ void *handler_data;
struct x_error_message_stack *prev;
};
static struct x_error_message_stack *x_error_message;
@@ -9040,6 +9230,9 @@ x_error_catcher (Display *display, XErrorEvent *event)
XGetErrorText (display, event->error_code,
x_error_message->string,
X_ERROR_MESSAGE_SIZE);
+ if (x_error_message->handler)
+ x_error_message->handler (display, event, x_error_message->string,
+ x_error_message->handler_data);
}
/* Begin trapping X errors for display DPY. Actually we trap X errors
@@ -9053,10 +9246,14 @@ x_error_catcher (Display *display, XErrorEvent *event)
Calling x_check_errors signals an Emacs error if an X error has
occurred since the last call to x_catch_errors or x_check_errors.
- Calling x_uncatch_errors resumes the normal error handling. */
+ Calling x_uncatch_errors resumes the normal error handling.
+ Calling x_uncatch_errors_after_check is similar, but skips an XSync
+ to the server, and should be used only immediately after
+ x_had_errors_p or x_check_errors. */
void
-x_catch_errors (Display *dpy)
+x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
+ void *handler_data)
{
struct x_error_message_stack *data = xmalloc (sizeof *data);
@@ -9065,10 +9262,37 @@ x_catch_errors (Display *dpy)
data->dpy = dpy;
data->string[0] = 0;
+ data->handler = handler;
+ data->handler_data = handler_data;
data->prev = x_error_message;
x_error_message = data;
}
+void
+x_catch_errors (Display *dpy)
+{
+ x_catch_errors_with_handler (dpy, NULL, NULL);
+}
+
+/* Undo the last x_catch_errors call.
+ DPY should be the display that was passed to x_catch_errors.
+
+ This version should be used only if the immediately preceding
+ X-protocol-related thing was x_check_errors or x_had_error_p, both
+ of which issue XSync calls, so we don't need to re-sync here. */
+
+void
+x_uncatch_errors_after_check (void)
+{
+ struct x_error_message_stack *tmp;
+
+ block_input ();
+ tmp = x_error_message;
+ x_error_message = x_error_message->prev;
+ xfree (tmp);
+ unblock_input ();
+}
+
/* Undo the last x_catch_errors call.
DPY should be the display that was passed to x_catch_errors. */
@@ -9163,7 +9387,7 @@ static char *error_msg;
the text of an error message that lead to the connection loss. */
static void
-x_connection_closed (Display *dpy, const char *error_message)
+x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
{
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
Lisp_Object frame, tail;
@@ -9182,6 +9406,7 @@ x_connection_closed (Display *dpy, const char *error_message)
dpyinfo->reference_count++;
dpyinfo->terminal->reference_count++;
}
+ if (ioerror) dpyinfo->display = 0;
/* First delete frames whose mini-buffers are on frames
that are on the dead display. */
@@ -9319,7 +9544,7 @@ x_error_quitter (Display *display, XErrorEvent *event)
XGetErrorText (display, event->error_code, buf, sizeof (buf));
sprintf (buf1, "X protocol error: %s on protocol request %d",
buf, event->request_code);
- x_connection_closed (display, buf1);
+ x_connection_closed (display, buf1, false);
}
@@ -9332,9 +9557,9 @@ x_io_error_quitter (Display *display)
{
char buf[256];
- snprintf (buf, sizeof buf, "Connection lost to X server `%s'",
+ snprintf (buf, sizeof buf, "Connection lost to X server '%s'",
DisplayString (display));
- x_connection_closed (display, buf);
+ x_connection_closed (display, buf, true);
return 0;
}
@@ -9349,7 +9574,11 @@ Lisp_Object
x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
struct font *font = XFONT_OBJECT (font_object);
- int unit;
+ int unit, font_ascent, font_descent;
+#ifndef USE_X_TOOLKIT
+ int old_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
+ Lisp_Object fullscreen;
+#endif
if (fontset < 0)
fontset = fontset_from_font (font_object);
@@ -9362,7 +9591,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
FRAME_FONT (f) = font;
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = font->average_width;
- FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
+ get_font_ascent_descent (font, &font_ascent, &font_descent);
+ FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
#ifndef USE_X_TOOLKIT
FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
@@ -9385,9 +9615,25 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
doing it because it's done in Fx_show_tip, and it leads to
problems because the tip frame has no widget. */
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+ {
adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
false, Qfont);
+#ifndef USE_X_TOOLKIT
+ if (FRAME_MENU_BAR_HEIGHT (f) != old_menu_bar_height
+ && !f->after_make_frame
+ && (EQ (frame_inhibit_implied_resize, Qt)
+ || (CONSP (frame_inhibit_implied_resize)
+ && NILP (Fmemq (Qfont, frame_inhibit_implied_resize))))
+ && (NILP (fullscreen = get_frame_param (f, Qfullscreen))
+ || EQ (fullscreen, Qfullwidth)))
+ /* If the menu bar height changes, try to keep text height
+ constant. */
+ adjust_frame_size
+ (f, -1, FRAME_TEXT_HEIGHT (f) + FRAME_MENU_BAR_HEIGHT (f)
+ - old_menu_bar_height, 1, false, Qfont);
+#endif /* USE_X_TOOLKIT */
+ }
}
#ifdef HAVE_X_I18N
@@ -9723,8 +9969,8 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
Specification/Extended Window Manager Hints at
http://freedesktop.org/wiki/Specifications/wm-spec. */
-static bool
-wm_supports (struct frame *f, Atom want_atom)
+bool
+x_wm_supports (struct frame *f, Atom want_atom)
{
Atom actual_type;
unsigned long actual_size, bytes_remaining;
@@ -9760,10 +10006,9 @@ wm_supports (struct frame *f, Atom want_atom)
/* Check if window exists. */
XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
- x_sync (f);
if (x_had_errors_p (dpy))
{
- x_uncatch_errors ();
+ x_uncatch_errors_after_check ();
unblock_input ();
return false;
}
@@ -9917,7 +10162,7 @@ static bool
do_ewmh_fullscreen (struct frame *f)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
- bool have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state);
+ bool have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state);
int cur;
bool dummy;
@@ -9926,7 +10171,7 @@ do_ewmh_fullscreen (struct frame *f)
/* Some window managers don't say they support _NET_WM_STATE, but they do say
they support _NET_WM_STATE_FULLSCREEN. Try that also. */
if (!have_net_atom)
- have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
+ have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
if (have_net_atom && cur != f->want_fullscreen)
{
@@ -10096,6 +10341,8 @@ x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
static void
x_check_fullscreen (struct frame *f)
{
+ Lisp_Object lval = Qnil;
+
if (do_ewmh_fullscreen (f))
return;
@@ -10114,22 +10361,34 @@ x_check_fullscreen (struct frame *f)
switch (f->want_fullscreen)
{
/* No difference between these two when there is no WM */
- case FULLSCREEN_BOTH:
case FULLSCREEN_MAXIMIZED:
+ lval = Qmaximized;
+ width = x_display_pixel_width (dpyinfo);
+ height = x_display_pixel_height (dpyinfo);
+ break;
+ case FULLSCREEN_BOTH:
+ lval = Qfullboth;
width = x_display_pixel_width (dpyinfo);
height = x_display_pixel_height (dpyinfo);
break;
case FULLSCREEN_WIDTH:
+ lval = Qfullwidth;
width = x_display_pixel_width (dpyinfo);
height = height + FRAME_MENUBAR_HEIGHT (f);
break;
case FULLSCREEN_HEIGHT:
+ lval = Qfullheight;
height = x_display_pixel_height (dpyinfo);
+ break;
+ default:
+ emacs_abort ();
}
frame_size_history_add
(f, Qx_check_fullscreen, width, height, Qnil);
+ x_wm_set_size_hint (f, 0, false);
+
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
width, height);
@@ -10142,6 +10401,10 @@ x_check_fullscreen (struct frame *f)
x_sync (f);
}
}
+
+ /* `x_net_wm_state' might have reset the fullscreen frame parameter,
+ restore it. */
+ store_frame_param (f, Qfullscreen, lval);
}
/* This function is called by x_set_offset to determine whether the window
@@ -10302,7 +10565,7 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
{
frame_size_history_add
- (f, Qxg_frame_set_char_size_1, width, height,
+ (f, Qx_set_window_size_1, width, height,
list2 (make_number (old_height),
make_number (pixelheight + FRAME_MENUBAR_HEIGHT (f))));
@@ -10312,7 +10575,7 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
{
frame_size_history_add
- (f, Qxg_frame_set_char_size_2, width, height,
+ (f, Qx_set_window_size_2, width, height,
list2 (make_number (old_width), make_number (pixelwidth)));
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
@@ -10322,10 +10585,11 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
else
{
frame_size_history_add
- (f, Qxg_frame_set_char_size_3, width, height,
- list2 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
+ (f, Qx_set_window_size_3, width, height,
+ list3 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
- + FRAME_MENUBAR_HEIGHT (f))));
+ + FRAME_MENUBAR_HEIGHT (f)),
+ make_number (FRAME_MENUBAR_HEIGHT (f))));
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
@@ -10441,8 +10705,6 @@ x_set_window_size (struct frame *f, bool change_gravity,
cancel_mouse_face (f);
unblock_input ();
-
- do_pending_window_change (false);
}
/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
@@ -10505,7 +10767,7 @@ x_ewmh_activate_frame (struct frame *f)
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
- if (FRAME_VISIBLE_P (f) && wm_supports (f, dpyinfo->Xatom_net_active_window))
+ if (FRAME_VISIBLE_P (f) && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
{
Lisp_Object frame;
XSETFRAME (frame, f);
@@ -10949,7 +11211,7 @@ x_free_frame_resources (struct frame *f)
free_frame_xic (f);
#endif
- x_prepare_for_xlibdraw (f);
+ x_free_cr_resources (f);
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
{
@@ -11097,8 +11359,8 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
size_hints.x = f->left_pos;
size_hints.y = f->top_pos;
- size_hints.height = FRAME_PIXEL_HEIGHT (f);
size_hints.width = FRAME_PIXEL_WIDTH (f);
+ size_hints.height = FRAME_PIXEL_HEIGHT (f);
size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
@@ -11111,34 +11373,21 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
/* Calculate the base and minimum sizes. */
{
int base_width, base_height;
- int min_rows = 0, min_cols = 0;
base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
- if (frame_resize_pixelwise)
- /* Needed to prevent a bad protocol error crash when making the
- frame size very small. */
- {
- min_cols = 2 * min_cols;
- min_rows = 2 * min_rows;
- }
-
/* The window manager uses the base width hints to calculate the
current number of rows and columns in the frame while
resizing; min_width and min_height aren't useful for this
purpose, since they might not give the dimensions for a
- zero-row, zero-column frame.
-
- We use the base_width and base_height members if we have
- them; otherwise, we set the min_width and min_height members
- to the size for a zero x zero frame. */
+ zero-row, zero-column frame. */
size_hints.flags |= PBaseSize;
size_hints.base_width = base_width;
size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
- size_hints.min_width = base_width + min_cols * FRAME_COLUMN_WIDTH (f);
- size_hints.min_height = base_height + min_rows * FRAME_LINE_HEIGHT (f);
+ size_hints.min_width = base_width;
+ size_hints.min_height = base_height;
}
/* If we don't need the old flags, we don't need the old hint at all. */
@@ -11399,7 +11648,10 @@ get_bits_and_offset (unsigned long mask, int *bits, int *offset)
bool
x_display_ok (const char *display)
{
+ /* XOpenDisplay fails if it gets a signal. Block SIGIO which may arrive. */
+ unrequest_sigio ();
Display *dpy = XOpenDisplay (display);
+ request_sigio ();
if (!dpy)
return false;
XCloseDisplay (dpy);
@@ -11521,7 +11773,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
struct terminal *terminal;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
- ptrdiff_t lim;
block_input ();
@@ -11579,7 +11830,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
/* gtk_init does set_locale. Fix locale before and after. */
fixup_locale ();
+ unrequest_sigio (); /* See comment in x_display_ok. */
gtk_init (&argc, &argv2);
+ request_sigio ();
fixup_locale ();
g_log_remove_handler ("GLib", id);
@@ -11629,10 +11882,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
argv[argc++] = xrm_option;
}
turn_on_atimers (false);
+ unrequest_sigio (); /* See comment in x_display_ok. */
dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
resource_name, EMACS_CLASS,
emacs_options, XtNumber (emacs_options),
&argc, argv);
+ request_sigio ();
turn_on_atimers (true);
#ifdef HAVE_X11XTR6
@@ -11643,7 +11898,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
#else /* not USE_X_TOOLKIT */
XSetLocaleModifiers ("");
+ unrequest_sigio (); // See comment in x_display_ok.
dpy = XOpenDisplay (SSDATA (display_name));
+ request_sigio ();
#endif /* not USE_X_TOOLKIT */
#endif /* not USE_GTK*/
@@ -11676,13 +11933,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
{
char *vendor = ServerVendor (dpy);
- /* Protect terminal from GC before removing it from the
- list of terminals. */
- struct gcpro gcpro1;
- Lisp_Object gcpro_term;
- XSETTERMINAL (gcpro_term, terminal);
- GCPRO1 (gcpro_term);
-
/* Temporarily hide the partially initialized terminal. */
terminal_list = terminal->next_terminal;
unblock_input ();
@@ -11693,7 +11943,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
block_input ();
terminal->next_terminal = terminal_list;
terminal_list = terminal;
- UNGCPRO;
}
/* Don't let the initial kboard remain current longer than necessary.
@@ -11713,6 +11962,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->display = dpy;
dpyinfo->connection = ConnectionNumber (dpyinfo->display);
+ /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
+ dpyinfo->smallest_font_height = 1;
+ dpyinfo->smallest_char_width = 1;
+
/* Set the name of the terminal. */
terminal->name = xlispstrdup (display_name);
@@ -11720,13 +11973,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
XSetAfterFunction (x_current_display, x_trace_wire);
#endif
- lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
Lisp_Object system_name = Fsystem_name ();
- if (lim - SBYTES (Vinvocation_name) < SBYTES (system_name))
+ ptrdiff_t nbytes;
+ if (INT_ADD_WRAPV (SBYTES (Vinvocation_name), SBYTES (system_name) + 2,
+ &nbytes))
memory_full (SIZE_MAX);
dpyinfo->x_id = ++x_display_id;
- dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name)
- + SBYTES (system_name) + 2);
+ dpyinfo->x_id_name = xmalloc (nbytes);
char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
*nametail++ = '@';
lispstpcpy (nametail, system_name);
@@ -12043,6 +12296,7 @@ static void
x_delete_display (struct x_display_info *dpyinfo)
{
struct terminal *t;
+ struct color_name_cache_entry *color_entry, *next_color_entry;
/* Close all frames and delete the generic struct terminal for this
X display. */
@@ -12072,6 +12326,15 @@ x_delete_display (struct x_display_info *dpyinfo)
tail->next = tail->next->next;
}
+ for (color_entry = dpyinfo->color_names;
+ color_entry;
+ color_entry = next_color_entry)
+ {
+ next_color_entry = color_entry->next;
+ xfree (color_entry->name);
+ xfree (color_entry);
+ }
+
xfree (dpyinfo->x_id_name);
xfree (dpyinfo->x_dnd_atoms);
xfree (dpyinfo->color_cells);
@@ -12156,7 +12419,7 @@ static struct redisplay_interface x_redisplay_interface =
x_draw_window_cursor,
x_draw_vertical_window_border,
x_draw_window_divider,
- x_shift_glyphs_for_insert,
+ x_shift_glyphs_for_insert, /* Never called; see comment in function. */
x_show_hourglass,
x_hide_hourglass
};
@@ -12457,9 +12720,11 @@ default is nil, which is the same as `super'. */);
DEFVAR_BOOL ("x-frame-normalize-before-maximize",
x_frame_normalize_before_maximize,
doc: /* Non-nil means normalize frame before maximizing.
-If this variable is t, Emacs asks the window manager to give the frame
-intermediately its normal size whenever changing from a full-height or
-full-width state to the fully maximized one and vice versa.
+If this variable is t, Emacs first asks the window manager to give the
+frame its normal size, and only then the final state, whenever changing
+from a full-height, full-width or full-both state to the maximized one
+or when changing from the maximized to the full-height or full-width
+state.
Set this variable only if your window manager cannot handle the
transition between the various maximization states. */);