#include <config.h>
#include <stdio.h>
+#ifdef USE_CAIRO
+#include <math.h>
+#endif
#include "lisp.h"
#include "blockinput.h"
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 *,
#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);
#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,
- unsigned int, unsigned int);
-static void x_draw_rectangle (struct frame *, GC, int, int,
- unsigned int, unsigned int);
-static void x_fill_trapezoid_for_relief (struct frame *, GC, int, int,
- unsigned int, unsigned 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)
static struct x_gc_ext_data *
-x_gc_get_ext_data (f, gc, create_if_not_found_p)
- struct frame *f;
- GC gc;
- int create_if_not_found_p;
+x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
XEDataObject object;
}
static void
-x_extension_initialize (dpyinfo)
- struct x_display_info *dpyinfo;
+x_extension_initialize (struct x_display_info *dpyinfo)
{
XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
}
cairo_t *
-x_begin_cr_clip (f, gc)
- struct frame *f;
- GC gc;
+x_begin_cr_clip (struct frame *f, GC gc)
{
cairo_t *cr = FRAME_CR_CONTEXT (f);
}
void
-x_end_cr_clip (f)
- struct frame *f;
+x_end_cr_clip (struct frame *f)
{
cairo_restore (FRAME_CR_CONTEXT (f));
}
void
-x_set_cr_source_with_gc_foreground (f, gc)
- struct frame *f;
- GC gc;
+x_set_cr_source_with_gc_foreground (struct frame *f, GC gc)
{
XGCValues xgcv;
XColor color;
}
void
-x_set_cr_source_with_gc_background (f, gc)
- struct frame *f;
- GC gc;
+x_set_cr_source_with_gc_background (struct frame *f, GC gc)
{
XGCValues xgcv;
XColor color;
static cairo_pattern_t **fringe_bmp = 0;
static void
-x_cr_define_fringe_bitmap (which, bits, h, wd)
- int which;
- unsigned short *bits;
- int h, wd;
+x_cr_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
{
int i, stride;
cairo_surface_t *surface;
}
static void
-x_cr_destroy_fringe_bitmap (which)
- int which;
+x_cr_destroy_fringe_bitmap (int which)
{
if (which >= max_fringe_bmp)
return;
}
static void
-x_cr_draw_image (struct frame *f,
- GC gc,
- cairo_pattern_t *image,
- int src_x,
- int src_y,
- unsigned int width,
- unsigned int height,
- int dest_x,
- int dest_y,
- bool overlay_p)
+x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
+ int src_x, int src_y, int width, int height,
+ int dest_x, int dest_y, bool overlay_p)
{
cairo_t *cr;
cairo_matrix_t matrix;
}
void
-x_cr_draw_frame (cr, f)
- cairo_t *cr;
- struct frame *f;
+x_cr_draw_frame (cairo_t *cr, struct frame *f)
{
int width, height;
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);
}
static cairo_status_t
-x_cr_accumulate_data (closure, data, length)
- void *closure;
- const unsigned char *data;
- unsigned int length;
+x_cr_accumulate_data (void *closure, const unsigned char *data,
+ unsigned int length)
{
Lisp_Object *acc = (Lisp_Object *) closure;
}
static void
-x_cr_destroy (arg)
- Lisp_Object arg;
+x_cr_destroy (Lisp_Object arg)
{
cairo_t *cr = (cairo_t *) XSAVE_POINTER (arg, 0);
}
Lisp_Object
-x_cr_export_frames (frames, surface_type)
- Lisp_Object frames;
- cairo_surface_type_t surface_type;
+x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
{
struct frame *f;
cairo_surface_t *surface;
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);
#endif /* USE_CAIRO */
static void
-x_prepare_for_xlibdraw (f)
- struct frame *f;
+x_free_cr_resources (struct frame *f)
{
#ifdef USE_CAIRO
if (f == NULL)
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
{
}
static void
-x_set_clip_rectangles (f, gc, rectangles, n)
- struct frame *f;
- GC gc;
- XRectangle *rectangles;
- int n;
+x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
{
XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
#ifdef USE_CAIRO
}
static void
-x_reset_clip_rectangles (f, gc)
- struct frame *f;
- GC gc;
+x_reset_clip_rectangles (struct frame *f, GC gc)
{
XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
#ifdef USE_CAIRO
}
static void
-x_fill_rectangle (f, gc, x, y, width, height)
- struct frame *f;
- GC gc;
- int x, y;
- unsigned int width, height;
+x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
{
#ifdef USE_CAIRO
cairo_t *cr;
}
static void
-x_draw_rectangle (f, gc, x, y, width, height)
- struct frame *f;
- GC gc;
- int x, y;
- unsigned int width, height;
+x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
{
#ifdef USE_CAIRO
cairo_t *cr;
}
static void
-x_clear_window (f)
- struct frame *f;
+x_clear_window (struct frame *f)
{
#ifdef USE_CAIRO
cairo_t *cr;
#ifdef USE_CAIRO
static void
-x_fill_trapezoid_for_relief (f, gc, x, y, width, height, top_p)
- struct frame *f;
- GC gc;
- int x, y;
- unsigned int width, height;
- int top_p;
+x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
+ int width, int height, int top_p)
{
cairo_t *cr;
cairo_line_to (cr, x, y + height);
cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
cairo_line_to (cr, x + width, y);
- cairo_close_path (cr);
cairo_fill (cr);
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)
+{
+ cairo_t *cr;
+ double dx = wave_length, dy = height - 1;
+ int xoffset, n;
+
+ cr = x_begin_cr_clip (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc);
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_clip (cr);
+
+ if (x >= 0)
+ {
+ xoffset = x % (wave_length * 2);
+ if (xoffset == 0)
+ xoffset = wave_length * 2;
+ }
+ else
+ xoffset = x % (wave_length * 2) + wave_length * 2;
+ n = (width + xoffset) / wave_length + 1;
+ if (xoffset > wave_length)
+ {
+ xoffset -= wave_length;
+ --n;
+ y += height - 1;
+ dy = -dy;
+ }
+
+ cairo_move_to (cr, x - xoffset + 0.5, y + 0.5);
+ while (--n >= 0)
+ {
+ cairo_rel_line_to (cr, dx, dy);
+ dy = -dy;
+ }
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+ x_end_cr_clip (f);
+}
#endif
\f
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;
{
sprintf (buf, "%0*X",
glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
- glyph->u.glyphless.ch);
+ glyph->u.glyphless.ch + 0u);
str = buf;
}
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)}
};
{
#ifdef USE_CAIRO
GC top_left_gc, bottom_right_gc;
+ int corners = 0;
if (raised_p)
{
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)
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_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
- x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
+ x_reset_clip_rectangles (f, top_left_gc);
+ x_reset_clip_rectangles (f, bottom_right_gc);
#else
Display *dpy = FRAME_X_DISPLAY (f);
Window window = FRAME_X_WINDOW (f);
}
/* Draw the foreground. */
+#ifdef USE_CAIRO
if (s->img->cr_data)
{
cairo_t *cr = x_begin_cr_clip (s->f, s->gc);
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);
XSetForeground (s->display, gc, xgcv.foreground);
}
- XSetClipMask (s->display, gc, None);
+ x_reset_clip_rectangles (s->f, gc);
}
}
else if (!s->background_filled_p)
x_draw_underwave (struct glyph_string *s)
{
int wave_height = 3, wave_length = 2;
+#ifdef USE_CAIRO
+ x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
+ s->width, wave_height, wave_length);
+#else /* not USE_CAIRO */
int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax;
bool odd;
XRectangle wave_clip, string_clip, final_clip;
/* Restore previous clipping rectangle(s) */
XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
+#endif /* not USE_CAIRO */
}
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,
void
-x_clear_area (f, x, y, width, height)
- struct frame *f;
- int x, y;
- int width, height;
+x_clear_area (struct frame *f, int x, int y, int width, int height)
{
#ifdef USE_CAIRO
cairo_t *cr;
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)
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 ();
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. */
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. */
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)
{
xg_frame_resized (f, event->xconfigure.width,
event->xconfigure.height);
+#ifdef USE_CAIRO
x_cr_destroy_surface (f);
+#endif
f = 0;
}
#endif
{
x_net_wm_state (f, event->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) != event->xconfigure.height
+ || FRAME_PIXEL_WIDTH (f) != event->xconfigure.width)
+ SET_FRAME_GARBAGED (f);
+ FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height;
+ FRAME_PIXEL_WIDTH (f) = event->xconfigure.width;
+ }
+#endif
+
#ifndef USE_X_TOOLKIT
#ifndef USE_GTK
int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width);
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;
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. */
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);
}
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;
}
\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)
{
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);
/* 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);
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
#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*/
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
};
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. */);