/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1989, 1993-2014 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2016 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
#include <stdio.h>
+#ifdef USE_CAIRO
+#include <math.h>
+#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. */
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
-/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
-/* #include <sys/param.h> */
-
-#include "charset.h"
#include "character.h"
#include "coding.h"
+#include "composite.h"
#include "frame.h"
#include "dispextern.h"
#include "fontset.h"
#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"
static int x_noop_count;
-static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
-
-static Lisp_Object Qvendor_specific_keysyms;
-static Lisp_Object Qlatin_1;
-
#ifdef USE_GTK
/* The name of the Emacs icon file. */
static Lisp_Object xg_default_icon_file;
-
-/* Used in gtkutil.c. */
-Lisp_Object Qx_gtk_map_stock;
#endif
/* Some functions take this as char *, not const char *. */
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 *, int, int, int, bool);
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_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 *,
enum scroll_bar_part *,
Lisp_Object *, Lisp_Object *,
Time *);
-static int x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
+static bool x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
static void x_check_fullscreen (struct frame *);
static void x_check_expected_move (struct frame *, int, int);
-static void x_sync_with_move (struct frame *, int, int, int);
+static void x_sync_with_move (struct frame *, int, int, bool);
static int handle_one_xevent (struct x_display_info *,
const XEvent *, int *,
struct input_event *);
#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);
-static int get_current_wm_state (struct frame *, Window, int *, int *);
+static bool get_current_wm_state (struct frame *, Window, int *, bool *);
/* Flush display of frame F. */
Debugging
***********************************************************************/
-#if 0
+#if false
/* This is a function useful for recording debugging information about
the sequence of occurrences in this file. */
event_record_index++;
}
-#endif /* 0 */
+#endif
+
+#ifdef USE_CAIRO
+
+#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 (struct frame *f, GC gc, int create_if_not_found_p)
+{
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ XEDataObject object;
+ XExtData **head, *ext_data;
+
+ object.gc = gc;
+ head = XEHeadOfExtensionList (object);
+ ext_data = XFindOnExtensionList (head, dpyinfo->ext_codes->extension);
+ if (ext_data == NULL)
+ {
+ if (!create_if_not_found_p)
+ return NULL;
+ else
+ {
+ ext_data = xzalloc (sizeof (*ext_data));
+ ext_data->number = dpyinfo->ext_codes->extension;
+ ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
+ XAddToExtensionList (head, ext_data);
+ }
+ }
+ return (struct x_gc_ext_data *) ext_data->private_data;
+}
+
+static void
+x_extension_initialize (struct x_display_info *dpyinfo)
+{
+ XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
+
+ dpyinfo->ext_codes = ext_codes;
+}
+
+static void
+x_cr_destroy_surface (struct frame *f)
+{
+ if (FRAME_CR_SURFACE (f))
+ {
+ cairo_t *cr = FRAME_CR_CONTEXT (f);
+ cairo_surface_destroy (FRAME_CR_SURFACE (f));
+ FRAME_CR_SURFACE (f) = 0;
+ if (cr) cairo_destroy (cr);
+ FRAME_CR_CONTEXT (f) = NULL;
+ }
+}
+
+cairo_t *
+x_begin_cr_clip (struct frame *f, GC gc)
+{
+ cairo_t *cr = FRAME_CR_CONTEXT (f);
+
+ if (!cr)
+ {
+
+ if (! FRAME_CR_SURFACE (f))
+ {
+ cairo_surface_t *surface;
+ surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->visual,
+ FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+ }
+ else
+ cr = cairo_create (FRAME_CR_SURFACE (f));
+ FRAME_CR_CONTEXT (f) = cr;
+ }
+ cairo_save (cr);
+
+ if (gc)
+ {
+ struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
+
+ if (gc_ext && gc_ext->n_clip_rects)
+ {
+ int i;
+
+ for (i = 0; i < gc_ext->n_clip_rects; i++)
+ cairo_rectangle (cr, gc_ext->clip_rects[i].x,
+ gc_ext->clip_rects[i].y,
+ gc_ext->clip_rects[i].width,
+ gc_ext->clip_rects[i].height);
+ cairo_clip (cr);
+ }
+ }
+
+ return cr;
+}
+
+void
+x_end_cr_clip (struct frame *f)
+{
+ cairo_restore (FRAME_CR_CONTEXT (f));
+}
+
+void
+x_set_cr_source_with_gc_foreground (struct frame *f, GC gc)
+{
+ XGCValues xgcv;
+ XColor color;
+
+ XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
+ color.pixel = xgcv.foreground;
+ x_query_color (f, &color);
+ cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
+ color.green / 65535.0, color.blue / 65535.0);
+}
+
+void
+x_set_cr_source_with_gc_background (struct frame *f, GC gc)
+{
+ XGCValues xgcv;
+ XColor color;
+
+ XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
+ color.pixel = xgcv.background;
+ x_query_color (f, &color);
+ cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
+ color.green / 65535.0, color.blue / 65535.0);
+}
+
+/* Fringe bitmaps. */
+
+static int max_fringe_bmp = 0;
+static cairo_pattern_t **fringe_bmp = 0;
+
+static void
+x_cr_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
+{
+ int i, stride;
+ cairo_surface_t *surface;
+ unsigned char *data;
+ cairo_pattern_t *pattern;
+
+ if (which >= max_fringe_bmp)
+ {
+ i = max_fringe_bmp;
+ max_fringe_bmp = which + 20;
+ fringe_bmp = (cairo_pattern_t **) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (cairo_pattern_t *));
+ while (i < max_fringe_bmp)
+ fringe_bmp[i++] = 0;
+ }
+
+ block_input ();
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
+ stride = cairo_image_surface_get_stride (surface);
+ data = cairo_image_surface_get_data (surface);
+
+ for (i = 0; i < h; i++)
+ {
+ *((unsigned short *) data) = bits[i];
+ data += stride;
+ }
+
+ cairo_surface_mark_dirty (surface);
+ pattern = cairo_pattern_create_for_surface (surface);
+ cairo_surface_destroy (surface);
+
+ unblock_input ();
+
+ fringe_bmp[which] = pattern;
+}
+
+static void
+x_cr_destroy_fringe_bitmap (int which)
+{
+ if (which >= max_fringe_bmp)
+ return;
+
+ if (fringe_bmp[which])
+ {
+ block_input ();
+ cairo_pattern_destroy (fringe_bmp[which]);
+ unblock_input ();
+ }
+ fringe_bmp[which] = 0;
+}
+
+static void
+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;
+ cairo_surface_t *surface;
+ cairo_format_t format;
+
+ cr = x_begin_cr_clip (f, gc);
+ if (overlay_p)
+ cairo_rectangle (cr, dest_x, dest_y, width, height);
+ else
+ {
+ x_set_cr_source_with_gc_background (f, gc);
+ cairo_rectangle (cr, dest_x, dest_y, width, height);
+ cairo_fill_preserve (cr);
+ }
+ cairo_clip (cr);
+ cairo_matrix_init_translate (&matrix, src_x - dest_x, src_y - dest_y);
+ cairo_pattern_set_matrix (image, &matrix);
+ cairo_pattern_get_surface (image, &surface);
+ format = cairo_image_surface_get_format (surface);
+ if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
+ {
+ cairo_set_source (cr, image);
+ cairo_fill (cr);
+ }
+ else
+ {
+ x_set_cr_source_with_gc_foreground (f, gc);
+ cairo_mask (cr, image);
+ }
+ x_end_cr_clip (f);
+}
+
+void
+x_cr_draw_frame (cairo_t *cr, struct frame *f)
+{
+ int width, height;
+
+ width = FRAME_PIXEL_WIDTH (f);
+ height = FRAME_PIXEL_HEIGHT (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);
+ FRAME_CR_CONTEXT (f) = NULL;
+}
+
+static cairo_status_t
+x_cr_accumulate_data (void *closure, const unsigned char *data,
+ unsigned int length)
+{
+ Lisp_Object *acc = (Lisp_Object *) closure;
+
+ *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+x_cr_destroy (Lisp_Object arg)
+{
+ cairo_t *cr = (cairo_t *) XSAVE_POINTER (arg, 0);
+
+ block_input ();
+ cairo_destroy (cr);
+ unblock_input ();
+}
+
+Lisp_Object
+x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
+{
+ struct frame *f;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ int width, height;
+ void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
+ Lisp_Object acc = Qnil;
+ int count = SPECPDL_INDEX ();
+
+ specbind (Qredisplay_dont_pause, Qt);
+ redisplay_preserve_echo_area (31);
+
+ f = XFRAME (XCAR (frames));
+ frames = XCDR (frames);
+ width = FRAME_PIXEL_WIDTH (f);
+ height = FRAME_PIXEL_HEIGHT (f);
+
+ block_input ();
+#ifdef CAIRO_HAS_PDF_SURFACE
+ if (surface_type == CAIRO_SURFACE_TYPE_PDF)
+ {
+ surface = cairo_pdf_surface_create_for_stream (x_cr_accumulate_data, &acc,
+ width, height);
+ surface_set_size_func = cairo_pdf_surface_set_size;
+ }
+ else
+#endif
+#ifdef CAIRO_HAS_PNG_FUNCTIONS
+ if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
+ surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
+ else
+#endif
+#ifdef CAIRO_HAS_PS_SURFACE
+ if (surface_type == CAIRO_SURFACE_TYPE_PS)
+ {
+ surface = cairo_ps_surface_create_for_stream (x_cr_accumulate_data, &acc,
+ width, height);
+ surface_set_size_func = cairo_ps_surface_set_size;
+ }
+ else
+#endif
+#ifdef CAIRO_HAS_SVG_SURFACE
+ if (surface_type == CAIRO_SURFACE_TYPE_SVG)
+ surface = cairo_svg_surface_create_for_stream (x_cr_accumulate_data, &acc,
+ width, height);
+ else
+#endif
+ abort ();
+
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+ record_unwind_protect (x_cr_destroy, make_save_ptr (cr));
+
+ while (1)
+ {
+ 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);
+ FRAME_CR_CONTEXT (f) = NULL;
+
+ if (NILP (frames))
+ break;
+
+ cairo_surface_show_page (surface);
+ f = XFRAME (XCAR (frames));
+ frames = XCDR (frames);
+ width = FRAME_PIXEL_WIDTH (f);
+ height = FRAME_PIXEL_HEIGHT (f);
+ if (surface_set_size_func)
+ (*surface_set_size_func) (surface, width, height);
+
+ unblock_input ();
+ QUIT;
+ block_input ();
+ }
+
+#ifdef CAIRO_HAS_PNG_FUNCTIONS
+ if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
+ {
+ cairo_surface_flush (surface);
+ cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
+ }
+#endif
+ unblock_input ();
+
+ unbind_to (count, Qnil);
+
+ return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
+}
+
+#endif /* USE_CAIRO */
+
+static void
+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_free_cr_resources (XFRAME (frame));
+ }
+ else
+ {
+ cairo_t *cr = FRAME_CR_CONTEXT (f);
+
+ if (cr)
+ {
+ cairo_surface_t *surface = cairo_get_target (cr);
+
+ if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
+ {
+ cairo_destroy (cr);
+ FRAME_CR_CONTEXT (f) = NULL;
+ }
+ }
+ }
+#endif
+}
+
+static void
+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
+ eassert (n >= 0 && n <= MAX_CLIP_RECTS);
+
+ {
+ struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 1);
+
+ gc_ext->n_clip_rects = n;
+ memcpy (gc_ext->clip_rects, rectangles, sizeof (XRectangle) * n);
+ }
+#endif
+}
+
+static void
+x_reset_clip_rectangles (struct frame *f, GC gc)
+{
+ XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
+#ifdef USE_CAIRO
+ {
+ struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
+
+ if (gc_ext)
+ gc_ext->n_clip_rects = 0;
+ }
+#endif
+}
+
+static void
+x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
+{
+#ifdef USE_CAIRO
+ cairo_t *cr;
+
+ cr = x_begin_cr_clip (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc);
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_fill (cr);
+ x_end_cr_clip (f);
+#else
+ XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ gc, x, y, width, height);
+#endif
+}
+
+static void
+x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
+{
+#ifdef USE_CAIRO
+ cairo_t *cr;
+ cr = x_begin_cr_clip (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc);
+ cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+ x_end_cr_clip (f);
+#else
+ XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ gc, x, y, width, height);
+#endif
+}
+
+static void
+x_clear_window (struct frame *f)
+{
+#ifdef USE_CAIRO
+ cairo_t *cr;
+
+ cr = x_begin_cr_clip (f, NULL);
+ x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
+ cairo_paint (cr);
+ x_end_cr_clip (f);
+#else
+ XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+#endif
+}
+
+#ifdef USE_CAIRO
+static void
+x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
+ int width, int height, int top_p)
+{
+ cairo_t *cr;
+
+ cr = x_begin_cr_clip (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc);
+ cairo_move_to (cr, top_p ? x : x + height, y);
+ 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_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
/* Return the struct x_display_info corresponding to DPY. */
static void
x_update_begin (struct frame *f)
{
- /* Nothing to do. */
-}
+#ifdef USE_CAIRO
+ if (! NILP (tip_frame) && XFRAME (tip_frame) == f
+ && ! FRAME_VISIBLE_P (f))
+ return;
+ if (! FRAME_CR_SURFACE (f))
+ {
+ int width, height;
+#ifdef USE_GTK
+ if (FRAME_GTK_WIDGET (f))
+ {
+ GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
+ width = gdk_window_get_width (w);
+ height = gdk_window_get_height (w);
+ }
+ else
+#endif
+ {
+ width = FRAME_PIXEL_WIDTH (f);
+ height = FRAME_PIXEL_HEIGHT (f);
+ if (! FRAME_EXTERNAL_TOOL_BAR (f))
+ height += FRAME_TOOL_BAR_HEIGHT (f);
+ if (! FRAME_EXTERNAL_MENU_BAR (f))
+ height += FRAME_MENU_BAR_HEIGHT (f);
+ }
+
+ if (width > 0 && height > 0)
+ {
+ block_input();
+ FRAME_CR_SURFACE (f) = cairo_image_surface_create
+ (CAIRO_FORMAT_ARGB32, width, height);
+ unblock_input();
+ }
+ }
+#endif /* USE_CAIRO */
+}
/* Start update of window W. */
if (f == hlinfo->mouse_face_mouse_frame)
{
/* Don't do highlighting for mouse motion during the update. */
- hlinfo->mouse_face_defer = 1;
+ hlinfo->mouse_face_defer = true;
/* If F needs to be redrawn, simply forget about any prior mouse
highlighting. */
XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
face->foreground);
+#ifdef USE_CAIRO
+ x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
+#else
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->normal_gc, x, y0, x, y1);
+#endif
}
/* Draw a window divider from (x0,y0) to (x1,y1) */
? face_last->foreground
: FRAME_FOREGROUND_PIXEL (f));
Display *display = FRAME_X_DISPLAY (f);
- Window window = FRAME_X_WINDOW (f);
if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
/* Vertical. */
{
XSetForeground (display, f->output_data.x->normal_gc, color_first);
- XFillRectangle (display, window, f->output_data.x->normal_gc,
- x0, y0, 1, y1 - y0);
+ x_fill_rectangle (f, f->output_data.x->normal_gc,
+ x0, y0, 1, y1 - y0);
XSetForeground (display, f->output_data.x->normal_gc, color);
- XFillRectangle (display, window, f->output_data.x->normal_gc,
- x0 + 1, y0, x1 - x0 - 2, y1 - y0);
+ x_fill_rectangle (f, f->output_data.x->normal_gc,
+ x0 + 1, y0, x1 - x0 - 2, y1 - y0);
XSetForeground (display, f->output_data.x->normal_gc, color_last);
- XFillRectangle (display, window, f->output_data.x->normal_gc,
- x1 - 1, y0, 1, y1 - y0);
+ x_fill_rectangle (f, f->output_data.x->normal_gc,
+ x1 - 1, y0, 1, y1 - y0);
}
else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
/* Horizontal. */
{
XSetForeground (display, f->output_data.x->normal_gc, color_first);
- XFillRectangle (display, window, f->output_data.x->normal_gc,
- x0, y0, x1 - x0, 1);
+ x_fill_rectangle (f, f->output_data.x->normal_gc,
+ x0, y0, x1 - x0, 1);
XSetForeground (display, f->output_data.x->normal_gc, color);
- XFillRectangle (display, window, f->output_data.x->normal_gc,
- x0, y0 + 1, x1 - x0, y1 - y0 - 2);
+ x_fill_rectangle (f, f->output_data.x->normal_gc,
+ x0, y0 + 1, x1 - x0, y1 - y0 - 2);
XSetForeground (display, f->output_data.x->normal_gc, color_last);
- XFillRectangle (display, window, f->output_data.x->normal_gc,
- x0, y1 - 1, x1 - x0, 1);
+ x_fill_rectangle (f, f->output_data.x->normal_gc,
+ x0, y1 - 1, x1 - x0, 1);
}
else
{
XSetForeground (display, f->output_data.x->normal_gc, color);
- XFillRectangle (display, window, f->output_data.x->normal_gc,
- x0, y0, x1 - x0, y1 - y0);
+ x_fill_rectangle (f, f->output_data.x->normal_gc,
+ x0, y0, x1 - x0, y1 - y0);
}
}
block_input ();
if (cursor_on_p)
- display_and_set_cursor (w, 1,
+ display_and_set_cursor (w, true,
w->output_cursor.hpos, w->output_cursor.vpos,
w->output_cursor.x, w->output_cursor.y);
- if (draw_window_fringes (w, 1))
+ if (draw_window_fringes (w, true))
{
if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
x_draw_right_divider (w);
x_update_end (struct frame *f)
{
/* Mouse highlight may be displayed again. */
- MOUSE_HL_INFO (f)->mouse_face_defer = 0;
+ MOUSE_HL_INFO (f)->mouse_face_defer = false;
+
+#ifdef USE_CAIRO
+ if (FRAME_CR_SURFACE (f))
+ {
+ cairo_t *cr = 0;
+ block_input();
+#if defined (USE_GTK) && defined (HAVE_GTK3)
+ if (FRAME_GTK_WIDGET (f))
+ {
+ GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
+ cr = gdk_cairo_create (w);
+ }
+ else
+#endif
+ {
+ cairo_surface_t *surface;
+ int width = FRAME_PIXEL_WIDTH (f);
+ int height = FRAME_PIXEL_HEIGHT (f);
+ if (! FRAME_EXTERNAL_TOOL_BAR (f))
+ height += FRAME_TOOL_BAR_HEIGHT (f);
+ if (! FRAME_EXTERNAL_MENU_BAR (f))
+ height += FRAME_MENU_BAR_HEIGHT (f);
+ surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->visual,
+ width,
+ height);
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+ }
+
+ cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+ unblock_input ();
+ }
+#endif /* USE_CAIRO */
#ifndef XFlush
block_input ();
{
if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
{
- Display *display = FRAME_X_DISPLAY (f);
- Window window = FRAME_X_WINDOW (f);
int border = FRAME_INTERNAL_BORDER_WIDTH (f);
int width = FRAME_PIXEL_WIDTH (f);
int height = FRAME_PIXEL_HEIGHT (f);
int margin = FRAME_TOP_MARGIN_HEIGHT (f);
block_input ();
- x_clear_area (display, window, 0, 0, border, height);
- x_clear_area (display, window, 0, margin, width, border);
- x_clear_area (display, window, width - border, 0, border, height);
- x_clear_area (display, window, 0, height - border, width, border);
+ x_clear_area (f, 0, 0, border, height);
+ x_clear_area (f, 0, margin, width, border);
+ x_clear_area (f, width - border, 0, border, height);
+ x_clear_area (f, 0, height - border, width, border);
unblock_input ();
}
}
eassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
- desired_row->redraw_fringe_bitmaps_p = 1;
+ desired_row->redraw_fringe_bitmaps_p = true;
#ifdef USE_X_TOOLKIT
/* When a window has disappeared, make sure that no rest of
int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
block_input ();
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- 0, y, width, height);
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- FRAME_PIXEL_WIDTH (f) - width,
- y, width, height);
+ x_clear_area (f, 0, y, width, height);
+ x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
unblock_input ();
}
}
else
XSetForeground (display, face->gc, face->background);
- XFillRectangle (display, window, face->gc,
- p->bx, p->by, p->nx, p->ny);
+ x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
if (!face->stipple)
XSetForeground (display, face->gc, face->foreground);
}
+#ifdef USE_CAIRO
+ if (p->which && p->which < max_fringe_bmp)
+ {
+ XGCValues gcv;
+
+ XGetGCValues (display, gc, GCForeground | GCBackground, &gcv);
+ XSetForeground (display, gc, (p->cursor_p
+ ? (p->overlay_p ? face->background
+ : f->output_data.x->cursor_pixel)
+ : face->foreground));
+ XSetBackground (display, gc, face->background);
+ x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
+ p->wd, p->h, p->x, p->y, p->overlay_p);
+ XSetForeground (display, gc, gcv.foreground);
+ XSetBackground (display, gc, gcv.background);
+ }
+#else /* not USE_CAIRO */
if (p->which)
{
char *bits;
XFreePixmap (display, clipmask);
}
}
+#endif /* not USE_CAIRO */
- XSetClipMask (display, gc, None);
+ x_reset_clip_rectangles (f, gc);
}
/***********************************************************************
static void x_clear_glyph_string_rect (struct glyph_string *, int,
int, int, int);
static void x_draw_relief_rect (struct frame *, int, int, int, int,
- int, int, int, int, int, int,
+ int, bool, bool, bool, bool, bool,
XRectangle *);
static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
- int, int, int, XRectangle *);
+ int, bool, bool, XRectangle *);
static void x_scroll_bar_clear (struct frame *);
#ifdef GLYPH_DEBUG
else if (s->hl == DRAW_CURSOR)
{
x_set_cursor_gc (s);
- s->stippled_p = 0;
+ s->stippled_p = false;
}
else if (s->hl == DRAW_MOUSE_FACE)
{
int n = get_glyph_string_clip_rects (s, r, 2);
if (n > 0)
- XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
+ x_set_clip_rectangles (s->f, s->gc, r, n);
s->num_clips = n;
}
r.height = src->height;
dst->clip[0] = r;
dst->num_clips = 1;
- XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
+ x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
}
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
XSetForeground (s->display, s->gc, xgcv.background);
- XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
+ x_fill_rectangle (s->f, s->gc, x, y, w, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
{
/* Fill background with a stipple pattern. */
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, s->gc, s->x,
+ x_fill_rectangle (s->f, s->gc, s->x,
s->y + box_line_width,
s->background_width,
s->height - 2 * box_line_width);
XSetFillStyle (s->display, s->gc, FillSolid);
- s->background_filled_p = 1;
+ 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)
x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
s->background_width,
s->height - 2 * box_line_width);
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
}
}
for (i = 0; i < s->nchars; ++i)
{
struct glyph *g = s->first_glyph + i;
- XDrawRectangle (s->display, s->window,
+ x_draw_rectangle (s->f,
s->gc, x, s->y, g->pixel_width - 1,
s->height - 1);
x += g->pixel_width;
y = s->ybase - boff;
if (s->for_overlaps
|| (s->background_filled_p && s->hl != DRAW_CURSOR))
- font->driver->draw (s, 0, s->nchars, x, y, 0);
+ font->driver->draw (s, 0, s->nchars, x, y, false);
else
- font->driver->draw (s, 0, s->nchars, x, y, 1);
+ font->driver->draw (s, 0, s->nchars, x, y, true);
if (s->face->overstrike)
- font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
+ font->driver->draw (s, 0, s->nchars, x + 1, y, false);
}
}
if (s->font_not_found_p)
{
if (s->cmp_from == 0)
- XDrawRectangle (s->display, s->window, s->gc, x, s->y,
+ x_draw_rectangle (s->f, s->gc, x, s->y,
s->width - 1, s->height - 1);
}
else if (! s->first_glyph->u.cmp.automatic)
int xx = x + s->cmp->offsets[j * 2];
int yy = y - s->cmp->offsets[j * 2 + 1];
- font->driver->draw (s, j, j + 1, xx, yy, 0);
+ font->driver->draw (s, j, j + 1, xx, yy, false);
if (s->face->overstrike)
- font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+ font->driver->draw (s, j, j + 1, xx + 1, yy, false);
}
}
else
if (j < i)
{
- font->driver->draw (s, j, i, x, y, 0);
+ font->driver->draw (s, j, i, x, y, false);
if (s->face->overstrike)
- font->driver->draw (s, j, i, x + 1, y, 0);
+ font->driver->draw (s, j, i, x + 1, y, false);
x += width;
}
xoff = LGLYPH_XOFF (glyph);
yoff = LGLYPH_YOFF (glyph);
wadjust = LGLYPH_WADJUST (glyph);
- font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+ font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
if (s->face->overstrike)
- font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, 0);
+ font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
+ false);
x += wadjust;
j = i + 1;
width = 0;
}
if (j < i)
{
- font->driver->draw (s, j, i, x, y, 0);
+ font->driver->draw (s, j, i, x, y, false);
if (s->face->overstrike)
- font->driver->draw (s, j, i, x + 1, y, 0);
+ font->driver->draw (s, j, i, x + 1, y, false);
}
}
}
{
sprintf (buf, "%0*X",
glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
- glyph->u.glyphless.ch);
+ glyph->u.glyphless.ch + 0u);
str = buf;
}
s->font->driver->draw (s, 0, upper_len,
x + glyph->slice.glyphless.upper_xoff,
s->ybase + glyph->slice.glyphless.upper_yoff,
- 0);
+ false);
s->font->driver->draw (s, upper_len, len,
x + glyph->slice.glyphless.lower_xoff,
s->ybase + glyph->slice.glyphless.lower_yoff,
- 0);
+ false);
}
if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
- XDrawRectangle (s->display, s->window, s->gc,
+ x_draw_rectangle (s->f, s->gc,
x, s->ybase - glyph->ascent,
glyph->pixel_width - 1,
glyph->ascent + glyph->descent - 1);
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)}
};
params[0] = color_name;
XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
"badValue", "cvt_string_to_pixel",
- "XtToolkitError", "Invalid color `%s'",
+ "XtToolkitError", "Invalid color '%s'",
params, &nparams);
return False;
}
{
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;
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);
}
}
+/* 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
}
-/* 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);
}
{
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 ();
success_p = x_alloc_nearest_color (f, cmap, &new);
}
else
- success_p = 1;
+ success_p = true;
*pixel = new.pixel;
}
/* Draw a relief on frame F inside the rectangle given by LEFT_X,
TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
- to draw, it must be >= 0. RAISED_P non-zero means draw a raised
- relief. LEFT_P non-zero means draw a relief on the left side of
- the rectangle. RIGHT_P non-zero means draw a relief on the right
+ to draw, it must be >= 0. RAISED_P means draw a raised
+ relief. LEFT_P means draw a relief on the left side of
+ the rectangle. RIGHT_P means draw a relief on the right
side of the rectangle. CLIP_RECT is the clipping rectangle to use
when drawing. */
-static void
-x_draw_relief_rect (struct frame *f,
- int left_x, int top_y, int right_x, int bottom_y, int width,
- int raised_p, int top_p, int bot_p, int left_p, int right_p,
- XRectangle *clip_rect)
-{
+static void
+x_draw_relief_rect (struct frame *f,
+ int left_x, int top_y, int right_x, int bottom_y,
+ int width, bool raised_p, bool top_p, bool bot_p,
+ bool left_p, bool right_p,
+ XRectangle *clip_rect)
+{
+#ifdef USE_CAIRO
+ GC top_left_gc, bottom_right_gc;
+ int corners = 0;
+
+ if (raised_p)
+ {
+ top_left_gc = f->output_data.x->white_relief.gc;
+ bottom_right_gc = f->output_data.x->black_relief.gc;
+ }
+ else
+ {
+ top_left_gc = f->output_data.x->black_relief.gc;
+ bottom_right_gc = f->output_data.x->white_relief.gc;
+ }
+
+ x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
+ 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);
+ 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);
+ if (top_p)
+ corners |= 1 << CORNER_TOP_RIGHT;
+ if (bot_p)
+ corners |= 1 << CORNER_BOTTOM_RIGHT;
+ }
+ if (top_p)
+ {
+ if (!right_p)
+ x_fill_rectangle (f, top_left_gc, left_x, top_y,
+ right_x + 1 - left_x, width);
+ else
+ x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
+ right_x + 1 - left_x, width, 1);
+ }
+ if (bot_p)
+ {
+ if (!left_p)
+ x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width,
+ right_x + 1 - left_x, width);
+ else
+ x_fill_trapezoid_for_relief (f, bottom_right_gc,
+ 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);
+#else
Display *dpy = FRAME_X_DISPLAY (f);
Window window = FRAME_X_WINDOW (f);
int i;
{
if (width == 1)
XDrawLine (dpy, window, gc,
- left_x + (left_p ? 1 : 0), top_y,
- right_x + (right_p ? 0 : 1), top_y);
+ left_x + left_p, top_y,
+ right_x + !right_p, top_y);
for (i = 1; i < width; ++i)
XDrawLine (dpy, window, gc,
/* Outermost top line. */
if (top_p)
XDrawLine (dpy, window, gc,
- left_x + (left_p ? 1 : 0), top_y,
- right_x + (right_p ? 0 : 1), top_y);
+ left_x + left_p, top_y,
+ right_x + !right_p, top_y);
/* Outermost left line. */
if (left_p)
if (bot_p)
{
XDrawLine (dpy, window, gc,
- left_x + (left_p ? 1 : 0), bottom_y,
- right_x + (right_p ? 0 : 1), bottom_y);
+ left_x + left_p, bottom_y,
+ right_x + !right_p, bottom_y);
for (i = 1; i < width; ++i)
XDrawLine (dpy, window, gc,
left_x + i * left_p, bottom_y - i,
right_x - i, bottom_y + 1 - (i + 1) * bot_p);
}
- XSetClipMask (dpy, gc, None);
+ x_reset_clip_rectangles (f, gc);
+
+#endif
}
/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
- draw, it must be >= 0. LEFT_P non-zero means draw a line on the
- left side of the rectangle. RIGHT_P non-zero means draw a line
+ draw, it must be >= 0. LEFT_P means draw a line on the
+ left side of the rectangle. RIGHT_P means draw a line
on the right side of the rectangle. CLIP_RECT is the clipping
rectangle to use when drawing. */
static void
x_draw_box_rect (struct glyph_string *s,
int left_x, int top_y, int right_x, int bottom_y, int width,
- int left_p, int right_p, XRectangle *clip_rect)
+ bool left_p, bool right_p, XRectangle *clip_rect)
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
XSetForeground (s->display, s->gc, s->face->box_color);
- XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
+ x_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
/* Top. */
- XFillRectangle (s->display, s->window, s->gc,
+ x_fill_rectangle (s->f, s->gc,
left_x, top_y, right_x - left_x + 1, width);
/* Left. */
if (left_p)
- XFillRectangle (s->display, s->window, s->gc,
+ x_fill_rectangle (s->f, s->gc,
left_x, top_y, width, bottom_y - top_y + 1);
/* Bottom. */
- XFillRectangle (s->display, s->window, s->gc,
+ x_fill_rectangle (s->f, s->gc,
left_x, bottom_y - width + 1, right_x - left_x + 1, width);
/* Right. */
if (right_p)
- XFillRectangle (s->display, s->window, s->gc,
+ x_fill_rectangle (s->f, s->gc,
right_x - width + 1, top_y, width, bottom_y - top_y + 1);
XSetForeground (s->display, s->gc, xgcv.foreground);
- XSetClipMask (s->display, s->gc, None);
+ x_reset_clip_rectangles (s->f, s->gc);
}
static void
x_draw_glyph_string_box (struct glyph_string *s)
{
- int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
- int left_p, right_p;
+ int width, left_x, right_x, top_y, bottom_y, last_x;
+ bool raised_p, left_p, right_p;
struct glyph *last_glyph;
XRectangle clip_rect;
{
x_setup_relief_colors (s);
x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
- width, raised_p, 1, 1, left_p, right_p, &clip_rect);
+ width, raised_p, true, true, left_p, right_p,
+ &clip_rect);
}
}
if (s->hl == DRAW_CURSOR)
{
int relief = eabs (s->img->relief);
- XDrawRectangle (s->display, s->window, s->gc,
+ x_draw_rectangle (s->f, s->gc,
x - relief, y - relief,
s->slice.width + relief*2 - 1,
s->slice.height + relief*2 - 1);
}
else
/* Draw a rectangle if image could not be loaded. */
- XDrawRectangle (s->display, s->window, s->gc, x, y,
+ x_draw_rectangle (s->f, s->gc, x, y,
s->slice.width - 1, s->slice.height - 1);
}
static void
x_draw_image_relief (struct glyph_string *s)
{
- int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
+ int x1, y1, thick;
+ bool raised_p, top_p, bot_p, left_p, right_p;
int extra_x, extra_y;
XRectangle r;
int x = s->x;
extra_x = extra_y = XINT (Vtool_bar_button_margin);
}
- top_p = bot_p = left_p = right_p = 0;
+ top_p = bot_p = left_p = right_p = false;
if (s->slice.x == 0)
- x -= thick + extra_x, left_p = 1;
+ x -= thick + extra_x, left_p = true;
if (s->slice.y == 0)
- y -= thick + extra_y, top_p = 1;
+ y -= thick + extra_y, top_p = true;
if (s->slice.x + s->slice.width == s->img->width)
- x1 += thick + extra_x, right_p = 1;
+ x1 += thick + extra_x, right_p = true;
if (s->slice.y + s->slice.height == s->img->height)
- y1 += thick + extra_y, bot_p = 1;
+ y1 += thick + extra_y, bot_p = true;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
if (s->hl == DRAW_CURSOR)
{
int r = eabs (s->img->relief);
- XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
+ x_draw_rectangle (s->f, s->gc, x - r, y - r,
s->slice.width + r*2 - 1,
s->slice.height + r*2 - 1);
}
}
else
/* Draw a rectangle if image could not be loaded. */
- XDrawRectangle (s->display, pixmap, s->gc, x, y,
+ x_draw_rectangle (s->f, s->gc, x, y,
s->slice.width - 1, s->slice.height - 1);
}
{
/* Fill background with a stipple pattern. */
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
+ x_fill_rectangle (s->f, s->gc, x, y, w, h);
XSetFillStyle (s->display, s->gc, FillSolid);
}
else
x_draw_glyph_string_bg_rect (s, x, y, width, height);
}
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
/* Draw the foreground. */
- if (pixmap != None)
+#ifdef USE_CAIRO
+ if (s->img->cr_data)
+ {
+ cairo_t *cr = x_begin_cr_clip (s->f, s->gc);
+
+ int x = s->x + s->img->hmargin;
+ int y = s->y + s->img->vmargin;
+ int width = s->background_width;
+
+ cairo_set_source_surface (cr, s->img->cr_data,
+ x - s->slice.x,
+ y - s->slice.y);
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_fill (cr);
+ x_end_cr_clip (s->f);
+ }
+ else
+#endif
+ if (pixmap != None)
{
x_draw_image_foreground_1 (s, pixmap);
x_set_glyph_string_clipping (s);
gc = s->face->gc;
get_glyph_string_clip_rect (s, &r);
- XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
+ x_set_clip_rectangles (s->f, gc, &r, 1);
if (s->face->stipple)
{
/* Fill background with a stipple pattern. */
XSetFillStyle (s->display, gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, gc, x, y, w, h);
+ x_fill_rectangle (s->f, gc, x, y, w, h);
XSetFillStyle (s->display, gc, FillSolid);
}
else
XGCValues xgcv;
XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
XSetForeground (s->display, gc, xgcv.background);
- XFillRectangle (s->display, s->window, gc, x, y, w, h);
+ x_fill_rectangle (s->f, gc, x, y, w, h);
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_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
}
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
/*
x_draw_underwave (struct glyph_string *s)
{
int wave_height = 3, wave_length = 2;
- int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
+#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;
dx = wave_length;
x1 = x0 - (x0 % dx);
x2 = x1 + dx;
- odd = (x1/dx) % 2;
+ odd = (x1 / dx) & 1;
y1 = y2 = y0;
if (odd)
/* 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_draw_glyph_string (struct glyph_string *s)
{
- bool relief_drawn_p = 0;
+ bool relief_drawn_p = false;
/* If S draws into the background of its successors, draw the
background of the successors first so that S can draw into it.
if (next->first_glyph->type == STRETCH_GLYPH)
x_draw_stretch_glyph_string (next);
else
- x_draw_glyph_string_background (next, 1);
+ x_draw_glyph_string_background (next, true);
next->num_clips = 0;
}
}
{
x_set_glyph_string_clipping (s);
- x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_background (s, true);
x_draw_glyph_string_box (s);
x_set_glyph_string_clipping (s);
- relief_drawn_p = 1;
+ relief_drawn_p = true;
}
else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
&& !s->clip_tail
case CHAR_GLYPH:
if (s->for_overlaps)
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 0);
+ x_draw_glyph_string_background (s, false);
x_draw_glyph_string_foreground (s);
break;
case COMPOSITE_GLYPH:
if (s->for_overlaps || (s->cmp_from > 0
&& ! s->first_glyph->u.cmp.automatic))
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_background (s, true);
x_draw_composite_glyph_string_foreground (s);
break;
case GLYPHLESS_GLYPH:
if (s->for_overlaps)
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_background (s, true);
x_draw_glyphless_glyph_string_foreground (s);
break;
s->underline_position = position;
y = s->ybase + position;
if (s->face->underline_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc,
+ x_fill_rectangle (s->f, s->gc,
s->x, y, s->width, thickness);
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
XSetForeground (s->display, s->gc, s->face->underline_color);
- XFillRectangle (s->display, s->window, s->gc,
+ x_fill_rectangle (s->f, s->gc,
s->x, y, s->width, thickness);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
unsigned long dy = 0, h = 1;
if (s->face->overline_color_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
s->width, h);
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
XSetForeground (s->display, s->gc, s->face->overline_color);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
unsigned long dy = (s->height - h) / 2;
if (s->face->strike_through_color_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
s->width, h);
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
XSetForeground (s->display, s->gc, s->face->strike_through_color);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
x_draw_glyph_string_foreground (prev);
else
x_draw_composite_glyph_string_foreground (prev);
- XSetClipMask (prev->display, prev->gc, None);
+ x_reset_clip_rectangles (prev->f, prev->gc);
prev->hl = save;
prev->num_clips = 0;
}
x_draw_glyph_string_foreground (next);
else
x_draw_composite_glyph_string_foreground (next);
- XSetClipMask (next->display, next->gc, None);
+ x_reset_clip_rectangles (next->f, next->gc);
next->hl = save;
next->num_clips = 0;
next->clip_head = s->next;
}
/* Reset clipping. */
- XSetClipMask (s->display, s->gc, None);
+ x_reset_clip_rectangles (s->f, s->gc);
s->num_clips = 0;
}
static void
x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
{
+/* 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,
/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
If they are <= 0, this is probably an error. */
+static void
+x_clear_area1 (Display *dpy, Window window,
+ int x, int y, int width, int height, int exposures)
+{
+ eassert (width > 0 && height > 0);
+ XClearArea (dpy, window, x, y, width, height, exposures);
+}
+
+
void
-x_clear_area (Display *dpy, Window window, int x, int y, int width, int height)
+x_clear_area (struct frame *f, int x, int y, int width, int height)
{
+#ifdef USE_CAIRO
+ cairo_t *cr;
+
eassert (width > 0 && height > 0);
- XClearArea (dpy, window, x, y, width, height, False);
+
+ cr = x_begin_cr_clip (f, NULL);
+ x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_fill (cr);
+ x_end_cr_clip (f);
+#else
+ x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ x, y, width, height, False);
+#endif
}
block_input ();
- XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ x_clear_window (f);
/* We have to clear the scroll bars. If we have changed colors or
something like that, then they should be notified. */
if (FRAME_OUTER_WINDOW (f))
#endif
{
- x->hourglass_p = 1;
+ x->hourglass_p = true;
if (!x->hourglass_window)
{
/* Sync here because XTread_socket looks at the
hourglass_p flag that is reset to zero below. */
XSync (FRAME_X_DISPLAY (f), False);
- x->hourglass_p = 0;
+ x->hourglass_p = false;
}
}
cairo_rectangle (cr, x, y, w, h); \
cairo_fill (cr); \
} \
- while (0)
+ while (false)
#else /* ! HAVE_GTK3 */
GdkGCValues vals;
GdkGC *gc;
gc = gdk_gc_new_with_values (window,
&vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
#define XFillRectangle(d, win, gc, x, y, w, h) \
- gdk_draw_rectangle (window, gc, TRUE, x, y, w, h)
+ gdk_draw_rectangle (window, gc, true, x, y, w, h)
#endif /* ! HAVE_GTK3 */
#else /* ! USE_GTK */
GC gc;
static void
-XTtoggle_invisible_pointer (struct frame *f, int invisible)
+XTtoggle_invisible_pointer (struct frame *f, bool invisible)
{
block_input ();
FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible);
/* Cursor off. Will be switched on again in x_update_window_end. */
x_clear_cursor (w);
+#ifdef USE_CAIRO
+ SET_FRAME_GARBAGED (f);
+#else
XCopyArea (FRAME_X_DISPLAY (f),
FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
f->output_data.x->normal_gc,
x, from_y,
width, height,
x, to_y);
+#endif
unblock_input ();
}
f->output_data.x->border_pixel);
x_uncatch_errors ();
unblock_input ();
- x_update_cursor (f, 1);
+ x_update_cursor (f, true);
x_set_frame_alpha (f);
}
f->output_data.x->border_tile);
x_uncatch_errors ();
unblock_input ();
- x_update_cursor (f, 1);
+ x_update_cursor (f, true);
x_set_frame_alpha (f);
}
XUnsetICFocus (FRAME_XIC (frame));
#endif
if (frame->pointer_invisible)
- XTtoggle_invisible_pointer (frame, 0);
+ XTtoggle_invisible_pointer (frame, false);
}
}
Alt keysyms are on. */
{
int row, col; /* The row and column in the modifier table. */
- int found_alt_or_meta;
+ bool found_alt_or_meta;
for (row = 3; row < 8; row++)
{
- found_alt_or_meta = 0;
+ found_alt_or_meta = false;
for (col = 0; col < mods->max_keypermod; col++)
{
KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
{
case XK_Meta_L:
case XK_Meta_R:
- found_alt_or_meta = 1;
+ found_alt_or_meta = true;
dpyinfo->meta_mod_mask |= (1 << row);
break;
case XK_Alt_L:
case XK_Alt_R:
- found_alt_or_meta = 1;
+ found_alt_or_meta = true;
dpyinfo->alt_mod_mask |= (1 << row);
break;
the mainstream emacs code by setting mouse_moved. If not, ask for
another motion event, so we can check again the next time it moves. */
-static int
+static bool
note_mouse_movement (struct frame *frame, const XMotionEvent *event)
{
XRectangle *r;
struct x_display_info *dpyinfo;
if (!FRAME_X_OUTPUT (frame))
- return 0;
+ return false;
dpyinfo = FRAME_DISPLAY_INFO (frame);
dpyinfo->last_mouse_movement_time = event->time;
if (event->window != FRAME_X_WINDOW (frame))
{
- frame->mouse_moved = 1;
+ frame->mouse_moved = true;
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, -1, -1);
dpyinfo->last_mouse_glyph_frame = NULL;
- return 1;
+ return true;
}
|| event->x < r->x || event->x >= r->x + r->width
|| event->y < r->y || event->y >= r->y + r->height)
{
- frame->mouse_moved = 1;
+ frame->mouse_moved = true;
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, event->x, event->y);
/* Remember which glyph we're now on. */
remember_mouse_glyph (frame, event->x, event->y, r);
dpyinfo->last_mouse_glyph_frame = frame;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Return the current position of the mouse.
FOR_EACH_FRAME (tail, frame)
if (FRAME_X_P (XFRAME (frame))
&& FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
- XFRAME (frame)->mouse_moved = 0;
+ XFRAME (frame)->mouse_moved = false;
dpyinfo->last_mouse_scroll_bar = NULL;
}
else
{
- while (1)
+ while (true)
{
XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
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)
dpyinfo->last_mouse_glyph_frame = f1;
*bar_window = Qnil;
- *part = scroll_bar_above_handle;
+ *part = 0;
*fp = f1;
XSETINT (*x, win_x);
XSETINT (*y, win_y);
#ifdef USE_TOOLKIT_SCROLL_BARS
static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
- int, int, bool);
+ int, int, bool);
/* Lisp window being scrolled. Set when starting to interact with
a toolkit scroll bar, reset to nil when ending the interaction. */
xt_action_hook (Widget widget, XtPointer client_data, String action_name,
XEvent *event, String *params, Cardinal *num_params)
{
- int scroll_bar_p;
+ bool scroll_bar_p;
const char *end_action;
#ifdef USE_MOTIF
struct scroll_bar *bar;
x_send_scroll_bar_event (window_being_scrolled,
- scroll_bar_end_scroll, 0, 0, 0);
+ scroll_bar_end_scroll, 0, 0, false);
w = XWINDOW (window_being_scrolled);
bar = XSCROLL_BAR (w->vertical_scroll_bar);
bar->last_seen_part = scroll_bar_nowhere;
#endif
/* Xt timeouts no longer needed. */
- toolkit_scroll_bar_interaction = 0;
+ toolkit_scroll_bar_interaction = false;
}
}
xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
XEvent *event, String *params, Cardinal *num_params)
{
- int scroll_bar_p;
+ bool scroll_bar_p;
const char *end_action;
#ifdef USE_MOTIF
struct scroll_bar *bar;
x_send_scroll_bar_event (window_being_scrolled,
- scroll_bar_end_scroll, 0, 0, 1);
+ scroll_bar_end_scroll, 0, 0, true);
w = XWINDOW (window_being_scrolled);
bar = XSCROLL_BAR (w->horizontal_scroll_bar);
bar->last_seen_part = scroll_bar_nowhere;
#endif
/* Xt timeouts no longer needed. */
- toolkit_scroll_bar_interaction = 0;
+ toolkit_scroll_bar_interaction = false;
}
}
#endif /* not USE_GTK */
/* Make Xt timeouts work while the scroll bar is active. */
#ifdef USE_X_TOOLKIT
- toolkit_scroll_bar_interaction = 1;
+ toolkit_scroll_bar_interaction = true;
x_activate_timeout_atimer ();
#endif
struct scroll_bar *bar = client_data;
XmScrollBarCallbackStruct *cs = call_data;
enum scroll_bar_part part = scroll_bar_nowhere;
- int horizontal = bar->horizontal, whole = 0, portion = 0;
+ bool horizontal = bar->horizontal;
+ int whole = 0, portion = 0;
switch (cs->reason)
{
if (part != scroll_bar_nowhere)
{
window_being_scrolled = bar->window;
- x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
+ x_send_scroll_bar_event (bar->window, part, portion, whole,
+ bar->horizontal);
}
}
GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
struct frame *f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
- if (xg_ignore_gtk_scrollbar) return FALSE;
+ if (xg_ignore_gtk_scrollbar) return false;
switch (scroll)
{
? scroll_bar_after_handle : scroll_bar_below_handle);
bar->dragging = -1;
break;
+ default:
+ break;
}
if (part != scroll_bar_nowhere)
{
window_being_scrolled = bar->window;
- x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
+ x_send_scroll_bar_event (bar->window, part, portion, whole,
+ bar->horizontal);
}
- return FALSE;
+ return false;
}
/* Callback for button release. Sets dragging to -1 when dragging is done. */
window_being_scrolled = Qnil;
}
- return FALSE;
+ return false;
}
float shown;
int whole, portion, height, width;
enum scroll_bar_part part;
- int horizontal = bar->horizontal;
+ bool horizontal = bar->horizontal;
if (horizontal)
window_being_scrolled = bar->window;
bar->dragging = -1;
bar->last_seen_part = part;
- x_send_scroll_bar_event (bar->window, part, position, width, bar->horizontal);
+ x_send_scroll_bar_event (bar->window, part, position, width,
+ bar->horizontal);
}
else
{
window_being_scrolled = bar->window;
bar->dragging = -1;
bar->last_seen_part = part;
- x_send_scroll_bar_event (bar->window, part, position, height, bar->horizontal);
+ x_send_scroll_bar_event (bar->window, part, position, height,
+ bar->horizontal);
}
}
xwindow = XtWindow (widget);
bar->x_window = xwindow;
bar->whole = 1;
- bar->horizontal = 0;
+ bar->horizontal = false;
unblock_input ();
}
xwindow = XtWindow (widget);
bar->x_window = xwindow;
bar->whole = 1;
- bar->horizontal = 1;
+ bar->horizontal = true;
unblock_input ();
}
XtNheight, &height,
NULL);
-#if 0
+#if false
/* Massage the top+shown values. */
if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
top = max (0, min (1, top));
work, check that 'NARROWPROTO' is defined in src/config.h.
If this is not so, most likely you need to fix configure. */
XawScrollbarSetThumb (widget, top, shown);
-#if 0
+#if false
if (top != old_top || shown != old_shown)
{
if (bar->dragging == -1)
scroll bar. */
static struct scroll_bar *
-x_scroll_bar_create (struct window *w, int top, int left, int width, int height, bool horizontal)
+x_scroll_bar_create (struct window *w, int top, int left,
+ int width, int height, bool horizontal)
{
struct frame *f = XFRAME (w->frame);
struct scroll_bar *bar
for the case that a window has been split horizontally. In
this case, no clear_frame is generated to reduce flickering. */
if (width > 0 && window_box_height (w) > 0)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, window_box_height (w));
+ x_clear_area (f, left, top, width, window_box_height (w));
window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
/* Position and size of scroll bar. */
/* Draw BAR's handle in the proper position.
If the handle is already drawn from START to END, don't bother
- redrawing it, unless REBUILD is non-zero; in that case, always
+ redrawing it, unless REBUILD; in that case, always
redraw it. (REBUILD is handy for drawing the handle after expose
events.)
to move to the very end of the buffer. */
static void
-x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild)
+x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
+ bool rebuild)
{
bool dragging = bar->dragging != -1;
Window w = bar->x_window;
/* Draw the empty space above the handle. Note that we can't clear
zero-height areas; that means "clear to end of window." */
if ((inside_width > 0) && (start > 0))
- x_clear_area (FRAME_X_DISPLAY (f), w,
+ 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)
/* Draw the empty space below the handle. Note that we can't
clear zero-height areas; that means "clear to end of window." */
if ((inside_width > 0) && (end < inside_height))
- x_clear_area (FRAME_X_DISPLAY (f), w,
+ 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 ();
if (width > 0 && height > 0)
{
block_input ();
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height);
+ x_clear_area (f, left, top, width, height);
unblock_input ();
}
- bar = x_scroll_bar_create (w, top, left, width, max (height, 1), 0);
+ bar = x_scroll_bar_create (w, top, left, width, max (height, 1), false);
}
else
{
/* Since toolkit scroll bars are smaller than the space reserved
for them on the frame, we have to clear "under" them. */
if (width > 0 && height > 0)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height);
+ x_clear_area (f, left, top, width, height);
#ifdef USE_GTK
xg_update_scrollbar_pos (f, bar->x_window, top,
left, width, max (height, 1));
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
if (whole == 0)
- x_scroll_bar_set_handle (bar, 0, top_range, 0);
+ x_scroll_bar_set_handle (bar, 0, top_range, false);
else
{
int start = ((double) position * top_range) / whole;
int end = ((double) (position + portion) * top_range) / whole;
- x_scroll_bar_set_handle (bar, start, end, 0);
+ x_scroll_bar_set_handle (bar, start, end, false);
}
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
/* Clear also part between window_width and
WINDOW_PIXEL_WIDTH. */
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, pixel_width, height);
+ x_clear_area (f, left, top, pixel_width, height);
unblock_input ();
}
- bar = x_scroll_bar_create (w, top, left, width, height, 1);
+ bar = x_scroll_bar_create (w, top, left, width, height, true);
}
else
{
/* Since toolkit scroll bars are smaller than the space reserved
for them on the frame, we have to clear "under" them. */
if (width > 0 && height > 0)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ x_clear_area (f,
WINDOW_LEFT_EDGE_X (w), top,
pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
#ifdef USE_GTK
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. */
int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width);
if (whole == 0)
- x_scroll_bar_set_handle (bar, 0, left_range, 0);
+ x_scroll_bar_set_handle (bar, 0, left_range, false);
else
{
int start = ((double) position * left_range) / whole;
int end = ((double) (position + portion) * left_range) / whole;
- x_scroll_bar_set_handle (bar, start, end, 0);
+ x_scroll_bar_set_handle (bar, start, end, false);
}
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
block_input ();
- x_scroll_bar_set_handle (bar, bar->start, bar->end, 1);
+ x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
/* Switch to scroll bar foreground color. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
int new_start = - bar->dragging;
int new_end = new_start + bar->end - bar->start;
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
+ x_scroll_bar_set_handle (bar, new_start, new_end, false);
bar->dragging = -1;
}
#endif
int new_start = y - bar->dragging;
int new_end = new_start + bar->end - bar->start;
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
+ x_scroll_bar_set_handle (bar, new_start, new_end, false);
bar->dragging = -1;
}
#endif
dpyinfo->last_mouse_movement_time = event->time;
dpyinfo->last_mouse_scroll_bar = bar;
- f->mouse_moved = 1;
+ f->mouse_moved = true;
/* If we're dragging the bar, display it. */
if (bar->dragging != -1)
{
int new_end = new_start + bar->end - bar->start;
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
+ x_scroll_bar_set_handle (bar, new_start, new_end, false);
}
}
}
XSETINT (*x, win_y);
XSETINT (*y, top_range);
- f->mouse_moved = 0;
+ f->mouse_moved = false;
dpyinfo->last_mouse_scroll_bar = NULL;
*timestamp = dpyinfo->last_mouse_movement_time;
}
XSETINT (*y, win_x);
XSETINT (*x, left_range);
- f->mouse_moved = 0;
+ f->mouse_moved = false;
dpyinfo->last_mouse_scroll_bar = NULL;
*timestamp = dpyinfo->last_mouse_movement_time;
}
{
int value = FULLSCREEN_NONE;
Lisp_Object lval = Qnil;
- int sticky = 0;
+ bool sticky = false;
- (void)get_current_wm_state (f, window, &value, &sticky);
+ get_current_wm_state (f, window, &value, &sticky);
switch (value)
{
break;
}
+ frame_size_history_add
+ (f, Qx_net_wm_state, 0, 0,
+ list2 (get_frame_param (f, Qfullscreen), lval));
+
store_frame_param (f, Qfullscreen, lval);
/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
}
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;
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;
if (f && FRAME_XIC (f))
XSetICFocus (FRAME_XIC (f));
#endif
-#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
+#if false
+ /* Emacs sets WM hints whose `input' field is `true'. This
instructs the WM to set the input focus automatically for
Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
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 */
-#endif /* 0 */
+#endif
goto done;
}
{
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;
{
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;
f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state)
{
- int not_hidden = x_handle_net_wm_state (f, &event->xproperty);
+ bool not_hidden = x_handle_net_wm_state (f, &event->xproperty);
if (not_hidden && FRAME_ICONIFIED_P (f))
{
/* Gnome shell does not iconify us when C-z is pressed.
It hides the frame. So if our state says we aren't
hidden anymore, treat it as deiconified. */
SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, 0);
- f->output_data.x->has_been_visible = 1;
+ SET_FRAME_ICONIFIED (f, false);
+ f->output_data.x->has_been_visible = true;
inev.ie.kind = DEICONIFY_EVENT;
XSETFRAME (inev.ie.frame_or_window, f);
}
else if (! not_hidden && ! FRAME_ICONIFIED_P (f))
{
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
inev.ie.kind = ICONIFY_EVENT;
XSETFRAME (inev.ie.frame_or_window, f);
}
if (!FRAME_VISIBLE_P (f))
{
SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, 0);
- f->output_data.x->has_been_visible = 1;
+ SET_FRAME_ICONIFIED (f, false);
+ f->output_data.x->has_been_visible = true;
SET_FRAME_GARBAGED (f);
}
else
#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 (event->xexpose.display,
- event->xexpose.window,
+ x_clear_area (f,
event->xexpose.x, event->xexpose.y,
event->xexpose.width, event->xexpose.height);
#endif
and that way, we know the window is not iconified now. */
if (visible || FRAME_ICONIFIED_P (f))
{
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
inev.ie.kind = ICONIFY_EVENT;
XSETFRAME (inev.ie.frame_or_window, f);
}
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. */
x_check_fullscreen (f);
SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, 0);
- f->output_data.x->has_been_visible = 1;
+ SET_FRAME_ICONIFIED (f, false);
+ f->output_data.x->has_been_visible = true;
if (iconified)
{
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 = 1;
+ hlinfo->mouse_face_hidden = true;
}
-#endif
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
if (f == 0)
which depends on which X*LookupString function
we used just above and the locale. */
setup_coding_system (coding_system, &coding);
- coding.src_multibyte = 0;
- coding.dst_multibyte = 1;
+ coding.src_multibyte = false;
+ coding.dst_multibyte = true;
/* The input is converted to events, thus we can't
handle composition. Anyway, there's no XIM that
gives us composition information. */
? 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;
if (hlinfo->mouse_face_hidden)
{
- hlinfo->mouse_face_hidden = 0;
+ hlinfo->mouse_face_hidden = false;
clear_mouse_face (hlinfo);
}
{
static Lisp_Object last_mouse_window;
Lisp_Object window = window_from_coordinates
- (f, event->xmotion.x, event->xmotion.y, 0, 0);
+ (f, event->xmotion.x, event->xmotion.y, 0, false);
/* Window will be selected only when it is not selected now and
last mouse movement event was not in it. Minibuffer window
}
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
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, 0, 1, 0, 1);
+ change_frame_size (f, width, height, false, true, false, true);
x_clear_under_internal_border (f);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
{
/* If we decide we want to generate an event to be seen
by the rest of Emacs, we put it here. */
- bool tool_bar_p = 0;
+ bool tool_bar_p = false;
memset (&compose_status, 0, sizeof (compose_status));
dpyinfo->last_mouse_glyph_frame = NULL;
int x = event->xbutton.x;
int y = event->xbutton.y;
- window = window_from_coordinates (f, x, y, 0, 1);
+ window = window_from_coordinates (f, x, y, 0, true);
tool_bar_p = EQ (window, f->tool_bar_window);
if (tool_bar_p && event->xbutton.button < 4)
any subsequent mouse-movement Emacs events should reflect
only motion after the ButtonPress/Release. */
if (f != 0)
- f->mouse_moved = 0;
+ f->mouse_moved = false;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
f = x_menubar_window_to_frame (dpyinfo, event);
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++;
}
if (do_help > 0)
{
- any_help_event_p = 1;
+ any_help_event_p = true;
gen_help_event (help_echo_string, frame, help_echo_window,
help_echo_object, help_echo_pos);
}
XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
{
int count = 0;
- int event_found = 0;
+ bool event_found = false;
struct x_display_info *dpyinfo = terminal->display_info.x;
block_input ();
if (x_filter_event (dpyinfo, &event))
continue;
#endif
- event_found = 1;
+ event_found = true;
count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
clip_rect.width = window_width;
clip_rect.height = row->visible_height;
- XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
+ x_set_clip_rectangles (f, gc, &clip_rect, 1);
}
}
/* Set clipping, draw the rectangle, and reset clipping again. */
x_clip_to_row (w, row, TEXT_AREA, gc);
- XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
- XSetClipMask (dpy, gc, None);
+ x_draw_rectangle (f, gc, x, y, wd, h - 1);
+ x_reset_clip_rectangles (f, gc);
}
xgcv.background = xgcv.foreground = face->foreground;
else
xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
- xgcv.graphics_exposures = 0;
+ xgcv.graphics_exposures = False;
if (gc)
XChangeGC (dpy, gc, mask, &xgcv);
if ((cursor_glyph->resolved_level & 1) != 0)
x += cursor_glyph->pixel_width - width;
- XFillRectangle (dpy, window, gc, x,
+ x_fill_rectangle (f, gc, x,
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
width, row->height);
}
if ((cursor_glyph->resolved_level & 1) != 0
&& cursor_glyph->pixel_width > w->phys_cursor_width - 1)
x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
- XFillRectangle (dpy, window, gc, x,
- WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
- row->height - width),
- w->phys_cursor_width - 1, width);
+ x_fill_rectangle (f, gc, x,
+ WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+ row->height - width),
+ w->phys_cursor_width - 1, width);
}
- XSetClipMask (dpy, gc, None);
+ x_reset_clip_rectangles (f, gc);
}
}
static void
x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
{
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (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))
if (on_p)
{
w->phys_cursor_type = cursor_type;
- w->phys_cursor_on_p = 1;
+ w->phys_cursor_on_p = true;
if (glyph_row->exact_window_width_line_p
&& (glyph_row->reversed_p
? (w->phys_cursor.hpos < 0)
: (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
{
- glyph_row->cursor_in_fringe_p = 1;
+ glyph_row->cursor_in_fringe_p = true;
draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
}
else
/* Make the x-window of frame F use the gnu icon bitmap. */
-int
+bool
x_bitmap_icon (struct frame *f, Lisp_Object file)
{
ptrdiff_t bitmap_id;
if (FRAME_X_WINDOW (f) == 0)
- return 1;
+ return true;
/* Free up our existing icon bitmap and mask if any. */
if (f->output_data.x->icon_bitmap > 0)
/* Use gtk_window_set_icon_from_file () if available,
It's not restricted to bitmaps */
if (xg_set_icon (f, file))
- return 0;
+ return false;
#endif /* USE_GTK */
bitmap_id = x_create_bitmap_from_file (f, file);
x_create_bitmap_mask (f, bitmap_id);
#ifdef USE_GTK
- if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id == -2
- || xg_set_icon (f, xg_default_icon_file)
+ if (xg_set_icon (f, xg_default_icon_file)
|| xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
{
FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2;
- return 0;
+ return false;
}
#elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
rc = x_create_bitmap_from_data (f, (char *) gnu_xbm_bits,
gnu_xbm_width, gnu_xbm_height);
if (rc == -1)
- return 1;
+ return true;
FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
x_wm_set_icon_pixmap (f, bitmap_id);
f->output_data.x->icon_bitmap = bitmap_id;
- return 0;
+ return false;
}
/* Make the x-window of frame F use a rectangle with text.
Use ICON_NAME as the text. */
-int
+bool
x_text_icon (struct frame *f, const char *icon_name)
{
if (FRAME_X_WINDOW (f) == 0)
- return 1;
+ return true;
{
XTextProperty text;
f->output_data.x->icon_bitmap = 0;
x_wm_set_icon_pixmap (f, 0);
- return 0;
+ return false;
}
\f
#define X_ERROR_MESSAGE_SIZE 200
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;
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
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);
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. */
x_error_message->string[0] = 0;
}
-#if 0 /* See comment in unwind_to_catch why calling this is a bad
+#if false
+ /* See comment in unwind_to_catch why calling this is a bad
* idea. --lorentey */
/* Close off all unclosed x_catch_errors calls. */
}
#endif
-#if 0
+#if false
static unsigned int x_wire_count;
x_trace_wire (void)
{
fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
}
-#endif /* ! 0 */
+#endif
\f
/************************************************************************
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);
}
{
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;
}
\f
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);
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);
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,
- 0, Qfont);
+ 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
x_calc_absolute_position (f);
block_input ();
- x_wm_set_size_hint (f, 0, 0);
+ x_wm_set_size_hint (f, 0, false);
modified_left = f->left_pos;
modified_top = f->top_pos;
modified_left, modified_top);
x_sync_with_move (f, f->left_pos, f->top_pos,
- FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
- ? 1 : 0);
+ FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
/* change_gravity is non-zero when this function is called from Lisp to
programmatically move a frame. In that case, we call
either the window manager type (A/B) is unknown or it is Type A but we
need to compute the top/left offset adjustment for this frame. */
- if (change_gravity != 0 &&
- (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
- || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
- && (FRAME_X_OUTPUT (f)->move_offset_left == 0
- && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
+ if (change_gravity != 0
+ && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+ || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
+ && (FRAME_X_OUTPUT (f)->move_offset_left == 0
+ && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
x_check_expected_move (f, modified_left, modified_top);
unblock_input ();
}
-/* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
+/* Return true if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
on the root window for frame F contains ATOMNAME.
This is how a WM check shall be done according to the Window Manager
Specification/Extended Window Manager Hints at
http://freedesktop.org/wiki/Specifications/wm-spec. */
-static int
-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;
int i, rc, actual_format;
+ bool ret;
Window wmcheck_window;
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
Window target_window = dpyinfo->root_window;
- long max_len = 65536;
+ int max_len = 65536;
Display *dpy = FRAME_X_DISPLAY (f);
unsigned char *tmp_data = NULL;
Atom target_type = XA_WINDOW;
if (tmp_data) XFree (tmp_data);
x_uncatch_errors ();
unblock_input ();
- return 0;
+ return false;
}
wmcheck_window = *(Window *) tmp_data;
/* 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 0;
+ return false;
}
if (dpyinfo->net_supported_window != wmcheck_window)
if (tmp_data) XFree (tmp_data);
x_uncatch_errors ();
unblock_input ();
- return 0;
+ return false;
}
dpyinfo->net_supported_atoms = (Atom *)tmp_data;
dpyinfo->net_supported_window = wmcheck_window;
}
- rc = 0;
+ ret = false;
- for (i = 0; rc == 0 && i < dpyinfo->nr_net_supported_atoms; ++i)
- rc = dpyinfo->net_supported_atoms[i] == want_atom;
+ for (i = 0; !ret && i < dpyinfo->nr_net_supported_atoms; ++i)
+ ret = dpyinfo->net_supported_atoms[i] == want_atom;
x_uncatch_errors ();
unblock_input ();
- return rc;
+ return ret;
}
static void
-set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value)
+set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
make_number (32),
/* 1 = add, 0 = remove */
Fcons
- (make_number (add ? 1 : 0),
+ (make_number (add),
Fcons
(make_fixnum_or_float (atom),
(value != 0
XSETFRAME (frame, f);
- set_wm_state (frame, NILP (new_value) ? 0 : 1,
+ set_wm_state (frame, !NILP (new_value),
dpyinfo->Xatom_net_wm_state_sticky, None);
}
/* Return the current _NET_WM_STATE.
SIZE_STATE is set to one of the FULLSCREEN_* values.
- STICKY is set to 1 if the sticky state is set, 0 if not.
+ Set *STICKY to the sticky state.
- Return non-zero if we are not hidden, zero if we are. */
+ Return true iff we are not hidden. */
-static int
+static bool
get_current_wm_state (struct frame *f,
Window window,
int *size_state,
- int *sticky)
+ bool *sticky)
{
- Atom actual_type;
- unsigned long actual_size, bytes_remaining;
- int i, rc, actual_format, is_hidden = 0;
+ unsigned long actual_size;
+ int i;
+ bool is_hidden = false;
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
long max_len = 65536;
+ Atom target_type = XA_ATOM;
+ /* If XCB is available, we can avoid three XSync calls. */
+#ifdef USE_XCB
+ xcb_get_property_cookie_t prop_cookie;
+ xcb_get_property_reply_t *prop;
+ xcb_atom_t *reply_data;
+#else
Display *dpy = FRAME_X_DISPLAY (f);
+ unsigned long bytes_remaining;
+ int rc, actual_format;
+ Atom actual_type;
unsigned char *tmp_data = NULL;
- Atom target_type = XA_ATOM;
+ Atom *reply_data;
+#endif
- *sticky = 0;
+ *sticky = false;
*size_state = FULLSCREEN_NONE;
block_input ();
+
+#ifdef USE_XCB
+ prop_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, window,
+ dpyinfo->Xatom_net_wm_state,
+ target_type, 0, max_len);
+ prop = xcb_get_property_reply (dpyinfo->xcb_connection, prop_cookie, NULL);
+ if (prop && prop->type == target_type)
+ {
+ int actual_bytes = xcb_get_property_value_length (prop);
+ eassume (0 <= actual_bytes);
+ actual_size = actual_bytes / sizeof *reply_data;
+ reply_data = xcb_get_property_value (prop);
+ }
+ else
+ {
+ actual_size = 0;
+ is_hidden = FRAME_ICONIFIED_P (f);
+ }
+#else
x_catch_errors (dpy);
rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
0, max_len, False, target_type,
&actual_type, &actual_format, &actual_size,
&bytes_remaining, &tmp_data);
- if (rc != Success || actual_type != target_type || x_had_errors_p (dpy))
+ if (rc == Success && actual_type == target_type && ! x_had_errors_p (dpy))
+ reply_data = (Atom *) tmp_data;
+ else
{
- if (tmp_data) XFree (tmp_data);
- x_uncatch_errors ();
- unblock_input ();
- return !FRAME_ICONIFIED_P (f);
+ actual_size = 0;
+ is_hidden = FRAME_ICONIFIED_P (f);
}
x_uncatch_errors ();
+#endif
for (i = 0; i < actual_size; ++i)
{
- Atom a = ((Atom*)tmp_data)[i];
+ Atom a = reply_data[i];
if (a == dpyinfo->Xatom_net_wm_state_hidden)
- {
- is_hidden = 1;
- }
+ is_hidden = true;
else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
{
if (*size_state == FULLSCREEN_HEIGHT)
else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
*size_state = FULLSCREEN_BOTH;
else if (a == dpyinfo->Xatom_net_wm_state_sticky)
- *sticky = 1;
+ *sticky = true;
}
+#ifdef USE_XCB
+ free (prop);
+#else
if (tmp_data) XFree (tmp_data);
+#endif
+
unblock_input ();
return ! is_hidden;
}
/* Do fullscreen as specified in extended window manager hints */
-static int
+static bool
do_ewmh_fullscreen (struct frame *f)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
- int have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state);
- int cur, dummy;
+ bool have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state);
+ int cur;
+ bool dummy;
- (void)get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
+ get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
/* 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)
{
switch (f->want_fullscreen)
{
case FULLSCREEN_BOTH:
- if (cur == FULLSCREEN_WIDTH || cur == FULLSCREEN_MAXIMIZED
- || cur == FULLSCREEN_HEIGHT)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_maximized_horz,
- dpyinfo->Xatom_net_wm_state_maximized_vert);
- set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_fullscreen, None);
+ if (cur != FULLSCREEN_BOTH)
+ set_wm_state (frame, true, dpyinfo->Xatom_net_wm_state_fullscreen,
+ None);
break;
case FULLSCREEN_WIDTH:
- if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
- || cur == FULLSCREEN_MAXIMIZED)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen,
- dpyinfo->Xatom_net_wm_state_maximized_vert);
- if (cur != FULLSCREEN_MAXIMIZED)
- set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+ if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
+ {
+ set_wm_state (frame, false,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
+ dpyinfo->Xatom_net_wm_state_maximized_vert);
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+ }
+ else
+ {
+ if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
+ || cur == FULLSCREEN_MAXIMIZED)
+ set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+ dpyinfo->Xatom_net_wm_state_maximized_vert);
+ if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+ }
break;
case FULLSCREEN_HEIGHT:
- if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
- || cur == FULLSCREEN_MAXIMIZED)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen,
- dpyinfo->Xatom_net_wm_state_maximized_horz);
- if (cur != FULLSCREEN_MAXIMIZED)
- set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+ if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
+ {
+ set_wm_state (frame, false,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
+ dpyinfo->Xatom_net_wm_state_maximized_vert);
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+ }
+ else
+ {
+ if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
+ || cur == FULLSCREEN_MAXIMIZED)
+ set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+ dpyinfo->Xatom_net_wm_state_maximized_horz);
+ if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+ }
break;
case FULLSCREEN_MAXIMIZED:
- if (cur == FULLSCREEN_BOTH)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen, None);
- set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_horz,
- dpyinfo->Xatom_net_wm_state_maximized_vert);
+ if (x_frame_normalize_before_maximize && cur == FULLSCREEN_BOTH)
+ {
+ set_wm_state (frame, false,
+ dpyinfo->Xatom_net_wm_state_fullscreen, None);
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
+ dpyinfo->Xatom_net_wm_state_maximized_vert);
+ }
+ else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_WIDTH)
+ {
+ set_wm_state (frame, false,
+ dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
+ dpyinfo->Xatom_net_wm_state_maximized_vert);
+ }
+ else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_HEIGHT)
+ {
+ set_wm_state (frame, false,
+ dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
+ dpyinfo->Xatom_net_wm_state_maximized_vert);
+ }
+ else
+ {
+ if (cur == FULLSCREEN_BOTH)
+ set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+ None);
+ else if (cur == FULLSCREEN_HEIGHT)
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+ else if (cur == FULLSCREEN_WIDTH)
+ set_wm_state (frame, true, None,
+ dpyinfo->Xatom_net_wm_state_maximized_vert);
+ else
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
+ dpyinfo->Xatom_net_wm_state_maximized_vert);
+ }
break;
case FULLSCREEN_NONE:
if (cur == FULLSCREEN_BOTH)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen, None);
+ set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+ None);
else
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_maximized_horz,
+ set_wm_state (frame, false,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
dpyinfo->Xatom_net_wm_state_maximized_vert);
}
}
-static int
+static bool
x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
{
int value = FULLSCREEN_NONE;
Lisp_Object lval;
- int sticky = 0;
- int not_hidden = get_current_wm_state (f, event->window, &value, &sticky);
+ bool sticky = false;
+ bool not_hidden = get_current_wm_state (f, event->window, &value, &sticky);
lval = Qnil;
switch (value)
break;
}
+ frame_size_history_add
+ (f, Qx_handle_net_wm_state, 0, 0,
+ list2 (get_frame_param (f, Qfullscreen), lval));
+
store_frame_param (f, Qfullscreen, lval);
store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
static void
x_check_fullscreen (struct frame *f)
{
+ Lisp_Object lval = Qnil;
+
if (do_ewmh_fullscreen (f))
return;
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_WIDTH:
+ 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);
+ width, height);
+
+ if (FRAME_VISIBLE_P (f))
+ x_wait_for_event (f, ConfigureNotify);
+ else
+ {
+ change_frame_size (f, width, height - FRAME_MENUBAR_HEIGHT (f),
+ false, true, false, true);
+ 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
XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
adjusted_left, adjusted_top);
- x_sync_with_move (f, expected_left, expected_top, 0);
+ x_sync_with_move (f, expected_left, expected_top, false);
}
else
/* It's a "Type B" window manager. We don't have to adjust the
of an exact comparison. */
static void
-x_sync_with_move (struct frame *f, int left, int top, int fuzzy)
+x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
{
int count = 0;
/* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
will then return up-to-date position info. */
- wait_reading_process_output (0, 500000000, 0, 0, Qnil, NULL, 0);
+ wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0);
}
while (f->wait_event_type)
{
- pending_signals = 1;
+ pending_signals = true;
totally_unblock_input ();
/* XTread_socket is called after unblock. */
block_input ();
/* Change the size of frame F's X window to WIDTH/HEIGHT in the case F
- doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
+ doesn't have a widget. If CHANGE_GRAVITY, change to
top-left-corner window gravity for this size change and subsequent
- size changes. Otherwise we leave the window gravity unchanged. */
+ size changes. Otherwise leave the window gravity unchanged. */
static void
-x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
+x_set_window_size_1 (struct frame *f, bool change_gravity,
+ int width, int height)
{
- int pixelwidth, pixelheight;
-
- pixelwidth = (pixelwise
- ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width)
- : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width));
- pixelheight = ((pixelwise
- ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height)
- : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height)));
+ int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
+ int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
+ int old_width = FRAME_PIXEL_WIDTH (f);
+ int old_height = FRAME_PIXEL_HEIGHT (f);
+ Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
if (change_gravity) f->win_gravity = NorthWestGravity;
- x_wm_set_size_hint (f, 0, 0);
- XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
- pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
+ x_wm_set_size_hint (f, 0, false);
+
+ /* When the frame is fullheight and we only want to change the width
+ or it is fullwidth and we only want to change the height we should
+ be able to preserve the fullscreen property. However, due to the
+ fact that we have to send a resize request anyway, the window
+ manager will abolish it. At least the respective size should
+ remain unchanged but giving the frame back its normal size will
+ be broken ... */
+ if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
+ {
+ frame_size_history_add
+ (f, Qx_set_window_size_1, width, height,
+ list2 (make_number (old_height),
+ make_number (pixelheight + FRAME_MENUBAR_HEIGHT (f))));
+
+ XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+ old_width, pixelheight + FRAME_MENUBAR_HEIGHT (f));
+ }
+ else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
+ {
+ frame_size_history_add
+ (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),
+ pixelwidth, old_height);
+ }
+
+ else
+ {
+ frame_size_history_add
+ (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)),
+ make_number (FRAME_MENUBAR_HEIGHT (f))));
+
+ XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+ pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
+ fullscreen = Qnil;
+ }
+
/* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
wouldn't be reported in the frame parameters until some random
point in the future when the ConfigureNotify event arrives.
- We pass 1 for DELAY since we can't run Lisp code inside of
+ Pass true for DELAY since we can't run Lisp code inside of
a BLOCK_INPUT. */
/* But the ConfigureNotify may in fact never arrive, and then this is
not right if the frame is visible. Instead wait (with timeout)
for the ConfigureNotify. */
if (FRAME_VISIBLE_P (f))
- x_wait_for_event (f, ConfigureNotify);
+ {
+ x_wait_for_event (f, ConfigureNotify);
+
+ if (!NILP (fullscreen))
+ /* Try to restore fullscreen state. */
+ {
+ store_frame_param (f, Qfullscreen, fullscreen);
+ x_set_fullscreen (f, fullscreen, fullscreen);
+ }
+ }
else
{
- change_frame_size (f, pixelwidth, pixelheight, 0, 1, 0, 1);
+ change_frame_size (f, width, height, false, true, false, true);
x_sync (f);
}
}
/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+ If CHANGE_GRAVITY, change to top-left-corner window gravity
for this size change and subsequent size changes.
Otherwise we leave the window gravity unchanged. */
void
-x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
+x_set_window_size (struct frame *f, bool change_gravity,
+ int width, int height, bool pixelwise)
{
block_input ();
/* The following breaks our calculations. If it's really needed,
think of something else. */
-#if 0
+#if false
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
{
int text_width, text_height;
text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh);
- change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
+ change_frame_size (f, text_width, text_height, false, true, false, true);
}
#endif
+ /* Pixelize width and height, if necessary. */
+ if (! pixelwise)
+ {
+ width = width * FRAME_COLUMN_WIDTH (f);
+ height = height * FRAME_LINE_HEIGHT (f);
+ }
+
#ifdef USE_GTK
if (FRAME_GTK_WIDGET (f))
- if (! pixelwise)
- xg_frame_set_char_size (f, width * FRAME_COLUMN_WIDTH (f),
- height * FRAME_LINE_HEIGHT (f));
- else
- xg_frame_set_char_size (f, width, height);
+ xg_frame_set_char_size (f, width, height);
else
- x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
+ x_set_window_size_1 (f, change_gravity, width, height);
#else /* not USE_GTK */
-
- x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
+ x_set_window_size_1 (f, change_gravity, width, height);
x_clear_under_internal_border (f);
-
#endif /* not USE_GTK */
/* If cursor was outside the new size, mark it as off. */
cancel_mouse_face (f);
unblock_input ();
-
- do_pending_window_change (0);
}
/* Move the mouse to position pixel PIX_X, PIX_Y relative to 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);
}
static void
-XTframe_raise_lower (struct frame *f, int raise_flag)
+XTframe_raise_lower (struct frame *f, bool raise_flag)
{
if (raise_flag)
x_raise_frame (f);
&& ! f->output_data.x->asked_for_visible)
x_set_offset (f, f->left_pos, f->top_pos, 0);
- f->output_data.x->asked_for_visible = 1;
+ f->output_data.x->asked_for_visible = true;
if (! EQ (Vx_no_window_manager, Qt))
x_wm_set_window_state (f, NormalState);
/* This must be before UNBLOCK_INPUT
since events that arrive in response to the actions above
will set it when they are handled. */
- int previously_visible = f->output_data.x->has_been_visible;
+ bool previously_visible = f->output_data.x->has_been_visible;
original_left = f->left_pos;
original_top = f->top_pos;
program-specified, so that when the window is mapped again, it will be
placed at the same location, without forcing the user to position it
by hand again (they have already done that once for this window.) */
- x_wm_set_size_hint (f, 0, 1);
+ x_wm_set_size_hint (f, 0, true);
#ifdef USE_GTK
if (FRAME_GTK_OUTER_WIDGET (f))
FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
and synchronize with the server to make sure we agree. */
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 0);
+ SET_FRAME_ICONIFIED (f, false);
x_sync (f);
gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
unblock_input ();
return;
}
that an invisible frame was changed to an icon,
so we have to record it here. */
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
unblock_input ();
return;
}
if (!result)
error ("Can't notify window manager of iconification");
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
SET_FRAME_VISIBLE (f, 0);
block_input ();
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
}
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
SET_FRAME_VISIBLE (f, 0);
XFlush (FRAME_X_DISPLAY (f));
free_frame_xic (f);
#endif
+ x_free_cr_resources (f);
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
{
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);
/* 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. */
/* Whether atimer for Xt timeouts is activated or not. */
-static int x_timeout_atimer_activated_flag;
+static bool x_timeout_atimer_activated_flag;
#endif /* USE_X_TOOLKIT */
/* Test whether two display-name strings agree up to the dot that separates
the screen number from the server number. */
-static int
+static bool
same_x_server (const char *name1, const char *name2)
{
- int seen_colon = 0;
- const char *system_name = SSDATA (Vsystem_name);
- ptrdiff_t system_name_length = SBYTES (Vsystem_name);
+ bool seen_colon = false;
+ Lisp_Object sysname = Fsystem_name ();
+ const char *system_name = SSDATA (sysname);
+ ptrdiff_t system_name_length = SBYTES (sysname);
ptrdiff_t length_until_period = 0;
while (system_name[length_until_period] != 0
for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
{
if (*name1 == ':')
- seen_colon = 1;
+ seen_colon = true;
if (seen_colon && *name1 == '.')
- return 1;
+ return true;
}
return (seen_colon
&& (*name1 == '.' || *name1 == '\0')
*bits = nr;
}
-/* Return 1 if display DISPLAY is available for use, 0 otherwise.
+/* Return true iff display DISPLAY is available for use.
But don't permanently open it, just test its availability. */
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);
- return dpy ? (XCloseDisplay (dpy), 1) : 0;
+ request_sigio ();
+ if (!dpy)
+ return false;
+ XCloseDisplay (dpy);
+ return true;
}
#ifdef USE_GTK
struct terminal *terminal;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
- ptrdiff_t lim;
+#ifdef USE_XCB
+ xcb_connection_t *xcb_conn;
+#endif
block_input ();
/* 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";
argv[argc++] = xrm_option;
}
- turn_on_atimers (0);
+ 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);
- turn_on_atimers (1);
+ request_sigio ();
+ turn_on_atimers (true);
#ifdef HAVE_X11XTR6
/* I think this is to compensate for XtSetLanguageProc. */
#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*/
return 0;
}
+#ifdef USE_XCB
+ xcb_conn = XGetXCBConnection (dpy);
+ if (xcb_conn == 0)
+ {
+#ifdef USE_GTK
+ xg_display_close (dpy);
+#else
+#ifdef USE_X_TOOLKIT
+ XtCloseDisplay (dpy);
+#else
+ XCloseDisplay (dpy);
+#endif
+#endif /* ! USE_GTK */
+
+ unblock_input ();
+ return 0;
+ }
+#endif
+
/* We have definitely succeeded. Record the new connection. */
dpyinfo = xzalloc (sizeof *dpyinfo);
{
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 ();
block_input ();
terminal->next_terminal = terminal_list;
terminal_list = terminal;
- UNGCPRO;
}
/* Don't let the initial kboard remain current longer than necessary.
dpyinfo->name_list_element = Fcons (display_name, Qnil);
dpyinfo->display = dpy;
dpyinfo->connection = ConnectionNumber (dpyinfo->display);
+#ifdef USE_XCB
+ dpyinfo->xcb_connection = xcb_conn;
+#endif
+
+ /* 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);
-#if 0
+#if false
XSetAfterFunction (x_current_display, x_trace_wire);
-#endif /* ! 0 */
+#endif
- lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
- if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name))
+ Lisp_Object system_name = Fsystem_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 (Vsystem_name) + 2);
+ dpyinfo->x_id_name = xmalloc (nbytes);
char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
*nametail++ = '@';
- lispstpcpy (nametail, Vsystem_name);
+ lispstpcpy (nametail, system_name);
/* Figure out which modifier bits mean what. */
x_find_modifier_meanings (dpyinfo);
x_session_initialize (dpyinfo);
#endif
+#ifdef USE_CAIRO
+ x_extension_initialize (dpyinfo);
+#endif
+
unblock_input ();
return dpyinfo;
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. */
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);
x_process_timeouts (struct atimer *timer)
{
block_input ();
- x_timeout_atimer_activated_flag = 0;
+ x_timeout_atimer_activated_flag = false;
if (toolkit_scroll_bar_interaction || popup_activated ())
{
while (XtAppPending (Xt_app_con) & XtIMTimer)
{
struct timespec interval = make_timespec (0, 100 * 1000 * 1000);
start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
- x_timeout_atimer_activated_flag = 1;
+ x_timeout_atimer_activated_flag = true;
}
unblock_input ();
}
x_get_glyph_overhangs,
x_fix_overlapping_area,
x_draw_fringe_bitmap,
+#ifdef USE_CAIRO
+ x_cr_define_fringe_bitmap,
+ x_cr_destroy_fringe_bitmap,
+#else
0, /* define_fringe_bitmap */
0, /* destroy_fringe_bitmap */
+#endif
x_compute_glyph_string_overhangs,
x_draw_glyph_string,
x_define_frame_cursor,
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
};
xim_close_dpy (dpyinfo);
#endif
- /* If called from x_connection_closed, the display may already be closed
- and dpyinfo->display was set to 0 to indicate that. */
+ /* Normally, the display is available... */
if (dpyinfo->display)
{
x_destroy_all_bitmaps (dpyinfo);
don't destroy the database here in order to avoid the crash
in the above situations for now, though that may cause memory
leaks in other situations. */
-#if 0
+#if false
#ifdef HAVE_XRMSETDATABASE
XrmSetDatabase (dpyinfo->display, NULL);
#else
XCloseDisplay (dpyinfo->display);
#endif
#endif /* ! USE_GTK */
-
- /* No more input on this descriptor. Do not close it because
- it's already closed by X(t)CloseDisplay (Bug#18403). */
- eassert (0 <= dpyinfo->connection);
- delete_keyboard_wait_descriptor (dpyinfo->connection);
-
- /* Mark as dead. */
+ /* Do not close the connection here because it's already closed
+ by X(t)CloseDisplay (Bug#18403). */
dpyinfo->display = NULL;
- dpyinfo->connection = -1;
}
+ /* ...but if called from x_connection_closed, the display may already
+ be closed and dpyinfo->display was set to 0 to indicate that. Since
+ X server is most likely gone, explicit close is the only reliable
+ way to continue and avoid Bug#19147. */
+ else if (dpyinfo->connection >= 0)
+ emacs_close (dpyinfo->connection);
+
+ /* No more input on this descriptor. */
+ delete_keyboard_wait_descriptor (dpyinfo->connection);
+ /* Mark as dead. */
+ dpyinfo->connection = -1;
+
x_delete_display (dpyinfo);
unblock_input ();
}
baud_rate = 19200;
x_noop_count = 0;
- any_help_event_p = 0;
+ any_help_event_p = false;
ignore_next_mouse_click_timeout = 0;
#ifdef USE_GTK
#endif
#endif
+#ifdef USE_CAIRO
+ x_cr_init_fringe (&x_redisplay_interface);
+#endif
+
/* Note that there is no real way portable across R3/R4 to get the
original error handler. */
XSetErrorHandler (x_error_handler);
to 4.1, set this to nil. You can also use `underline-minimum-offset'
to override the font's UNDERLINE_POSITION for small font display
sizes. */);
- x_use_underline_position_properties = 1;
+ x_use_underline_position_properties = true;
DEFVAR_BOOL ("x-underline-at-descent-line",
x_underline_at_descent_line,
A value of nil means to draw the underline according to the value of the
variable `x-use-underline-position-properties', which is usually at the
baseline level. The default value is nil. */);
- x_underline_at_descent_line = 0;
+ x_underline_at_descent_line = false;
DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
x_mouse_click_focus_ignore_position,
of nil, means that the selected window and cursor position changes to
reflect the mouse click position, while a non-nil value means that the
selected window or cursor position is preserved. */);
- x_mouse_click_focus_ignore_position = 0;
+ x_mouse_click_focus_ignore_position = false;
DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
doc: /* Which toolkit scroll bars Emacs uses, if any.
make_float (DEFAULT_REHASH_SIZE),
make_float (DEFAULT_REHASH_THRESHOLD),
Qnil);
+
+ 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 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. */);
+ x_frame_normalize_before_maximize = false;
}