/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1989, 1993-2013 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2014 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "xterm.h"
#include <X11/cursorfont.h>
+/* If we have Xfixes extension, use it for pointer blanking. */
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
/* Load sys/types.h if not already loaded.
In some systems loading it twice is suicidal. */
#ifndef makedev
#ifdef USE_TOOLKIT_SCROLL_BARS
#if defined USE_MOTIF
-#include <Xm/Xm.h> /* for LESSTIF_VERSION */
+#include <Xm/Xm.h> /* For LESSTIF_VERSION */
#include <Xm/ScrollBar.h>
#else /* !USE_MOTIF i.e. use Xaw */
/* Default to using XIM if available. */
#ifdef USE_XIM
-int use_xim = 1;
+bool use_xim = true;
#else
-int use_xim = 0; /* configure --without-xim */
+bool use_xim = false; /* configure --without-xim */
#endif
/* Non-zero means that a HELP_EVENT has been generated since Emacs
struct x_display_info *x_display_list;
-/* This is a list of cons cells, each of the form (NAME
- . FONT-LIST-CACHE), one for each element of x_display_list and in
- the same order. NAME is the name of the frame. FONT-LIST-CACHE
- records previous values returned by x-list-fonts. */
-
-Lisp_Object x_display_name_list;
-
#ifdef USE_X_TOOLKIT
/* The application context for Xt use. */
static Time ignore_next_mouse_click_timeout;
-/* Incremented by XTread_socket whenever it really tries to read
- events. */
-
-static int volatile input_signal_count;
-
/* Used locally within XTread_socket. */
static int x_noop_count;
};
static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
-static void x_set_window_size_1 (struct frame *, int, int, int);
+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 handle_one_xevent (struct x_display_info *,
const XEvent *, int *,
struct input_event *);
-#ifdef USE_GTK
+#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
void
record_event (char *locus, int type)
{
- if (event_record_index == sizeof (event_record) / sizeof (struct record))
+ if (event_record_index == ARRAYELTS (event_record))
event_record_index = 0;
event_record[event_record_index].locus = locus;
f->output_data.x->normal_gc, x, y0, x, y1);
}
+/* Draw a window divider from (x0,y0) to (x1,y1) */
+
+static void
+x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+ struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+ struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
+ unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
+ unsigned long color_first = (face_first
+ ? face_first->foreground
+ : FRAME_FOREGROUND_PIXEL (f));
+ unsigned long color_last = (face_last
+ ? 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);
+ 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);
+ 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);
+ }
+ 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);
+ 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);
+ 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);
+ }
+ 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);
+ }
+}
+
/* End update of window W.
Draw vertical borders between horizontally adjacent windows, and
w->output_cursor.x, w->output_cursor.y);
if (draw_window_fringes (w, 1))
- x_draw_vertical_border (w);
+ {
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ x_draw_right_divider (w);
+ else
+ x_draw_vertical_border (w);
+ }
unblock_input ();
}
}
+/* Clear under internal border if any for non-toolkit builds. */
+
+
+#if !defined USE_X_TOOLKIT && !defined USE_GTK
+void
+x_clear_under_internal_border (struct frame *f)
+{
+ 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);
+ unblock_input ();
+ }
+}
+#endif
+
/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
arrow bitmaps, or clear the fringes if no bitmaps are required
before DESIRED_ROW is made current. This function is called from
static void
x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
{
- struct frame *f;
- int width, height;
-
eassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
desired_row->redraw_fringe_bitmaps_p = 1;
+#ifdef USE_X_TOOLKIT
/* When a window has disappeared, make sure that no rest of
full-width rows stays visible in the internal border. Could
check here if updated window is the leftmost/rightmost window,
but I guess it's not worth doing since vertically split windows
are almost never used, internal border is rarely set, and the
overhead is very small. */
- if (windows_or_buffers_changed
- && desired_row->full_width_p
- && (f = XFRAME (w->frame),
- width = FRAME_INTERNAL_BORDER_WIDTH (f),
- width != 0)
- && (height = desired_row->visible_height,
- height > 0))
- {
- int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
+ {
+ struct frame *f;
+ int width, height;
+
+ if (windows_or_buffers_changed
+ && desired_row->full_width_p
+ && (f = XFRAME (w->frame),
+ width = FRAME_INTERNAL_BORDER_WIDTH (f),
+ width != 0)
+ && (height = desired_row->visible_height,
+ height > 0))
+ {
+ 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);
- unblock_input ();
- }
+ 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);
+ unblock_input ();
+ }
+ }
+#endif
}
static void
/* Must clip because of partially visible lines. */
x_clip_to_row (w, row, ANY_AREA, gc);
- if (!p->overlay_p)
+ if (p->bx >= 0 && !p->overlay_p)
{
- int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
-
/* In case the same realized face is used for fringes and
for something displayed in the text (e.g. face `region' on
mono-displays, the fill style may have been changed to
else
XSetForeground (display, face->gc, face->background);
-#ifdef USE_TOOLKIT_SCROLL_BARS
- /* If the fringe is adjacent to the left (right) scroll bar of a
- leftmost (rightmost, respectively) window, then extend its
- background to the gap between the fringe and the bar. */
- if ((WINDOW_LEFTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
- || (WINDOW_RIGHTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
- {
- int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
- if (sb_width > 0)
- {
- int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
- int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
- * FRAME_COLUMN_WIDTH (f));
-
- if (bx < 0)
- {
- /* Bitmap fills the fringe. */
- if (bar_area_x + bar_area_width == p->x)
- bx = bar_area_x + sb_width;
- else if (p->x + p->wd == bar_area_x)
- bx = bar_area_x;
- if (bx >= 0)
- {
- int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
-
- nx = bar_area_width - sb_width;
- by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- row->y));
- ny = row->visible_height;
- }
- }
- else
- {
- if (bar_area_x + bar_area_width == bx)
- {
- bx = bar_area_x + sb_width;
- nx += bar_area_width - sb_width;
- }
- else if (bx + nx == bar_area_x)
- nx += bar_area_width - sb_width;
- }
- }
- }
-#endif
- if (bx >= 0 && nx > 0)
- XFillRectangle (display, window, face->gc, bx, by, nx, ny);
+ XFillRectangle (display, window, face->gc,
+ p->bx, p->by, p->nx, p->ny);
if (!face->stipple)
XSetForeground (display, face->gc, face->foreground);
s->stippled_p = s->face->stipple != 0;
}
else
- {
- s->gc = s->face->gc;
- s->stippled_p = s->face->stipple != 0;
- }
+ emacs_abort ();
/* GC must have been set. */
eassert (s->gc != 0);
get color reference counts right. */
unsigned long
-x_copy_color (struct frame *f, long unsigned int pixel)
+x_copy_color (struct frame *f, unsigned long pixel)
{
XColor color;
Value is non-zero if successful. */
static bool
-x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap, long unsigned int *pixel, double factor, int delta)
+x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
+ unsigned long *pixel, double factor, int delta)
{
XColor color, new;
long bright;
be allocated, use DEFAULT_PIXEL, instead. */
static void
-x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int delta, long unsigned int default_pixel)
+x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
+ int delta, unsigned long default_pixel)
{
XGCValues xgcv;
struct x_output *di = f->output_data.x;
/* Free previously allocated color. The color cell will be reused
when it has been freed as many times as it was allocated, so this
doesn't affect faces using the same colors. */
- if (relief->gc
- && relief->allocated_p)
+ if (relief->gc && relief->pixel != -1)
{
x_free_colors (f, &relief->pixel, 1);
- relief->allocated_p = 0;
+ relief->pixel = -1;
}
/* Allocate new color. */
pixel = background;
if (dpyinfo->n_planes != 1
&& x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
- {
- relief->allocated_p = 1;
- xgcv.foreground = relief->pixel = pixel;
- }
+ xgcv.foreground = relief->pixel = pixel;
if (relief->gc == 0)
{
x_draw_image_relief (struct glyph_string *s)
{
int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
+ int extra_x, extra_y;
XRectangle r;
int x = s->x;
int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
x1 = x + s->slice.width - 1;
y1 = y + s->slice.height - 1;
+
+ extra_x = extra_y = 0;
+ if (s->face->id == TOOL_BAR_FACE_ID)
+ {
+ if (CONSP (Vtool_bar_button_margin)
+ && INTEGERP (XCAR (Vtool_bar_button_margin))
+ && INTEGERP (XCDR (Vtool_bar_button_margin)))
+ {
+ extra_x = XINT (XCAR (Vtool_bar_button_margin));
+ extra_y = XINT (XCDR (Vtool_bar_button_margin));
+ }
+ else if (INTEGERP (Vtool_bar_button_margin))
+ extra_x = extra_y = XINT (Vtool_bar_button_margin);
+ }
+
top_p = bot_p = left_p = right_p = 0;
if (s->slice.x == 0)
- x -= thick, left_p = 1;
+ x -= thick + extra_x, left_p = 1;
if (s->slice.y == 0)
- y -= thick, top_p = 1;
+ y -= thick + extra_y, top_p = 1;
if (s->slice.x + s->slice.width == s->img->width)
- x1 += thick, right_p = 1;
+ x1 += thick + extra_x, right_p = 1;
if (s->slice.y + s->slice.height == s->img->height)
- y1 += thick, bot_p = 1;
+ y1 += thick + extra_y, bot_p = 1;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
{
int x = s->x;
int y = s->y;
+ int width = s->background_width;
if (s->first_glyph->left_box_line_p
&& s->slice.x == 0)
- x += box_line_hwidth;
+ {
+ x += box_line_hwidth;
+ width -= box_line_hwidth;
+ }
if (s->slice.y == 0)
y += box_line_vwidth;
- x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+ x_draw_glyph_string_bg_rect (s, x, y, width, height);
}
s->background_filled_p = 1;
XFillRectangle (s->display, s->window, gc, x, y, w, h);
XSetForeground (s->display, gc, xgcv.foreground);
}
+
+ XSetClipMask (s->display, gc, None);
}
}
else if (!s->background_filled_p)
#endif
{
/* Get the height not including a menu bar widget. */
- int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
+ int height = FRAME_PIXEL_HEIGHT (f);
/* Height of each line to flash. */
int flash_height = FRAME_LINE_HEIGHT (f);
/* These will be the left and right margins of the rectangles. */
XTtoggle_invisible_pointer (struct frame *f, int invisible)
{
block_input ();
- if (invisible)
- {
- if (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0)
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- FRAME_DISPLAY_INFO (f)->invisible_cursor);
- }
- else
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->current_cursor);
- f->pointer_invisible = invisible;
+ FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible);
unblock_input ();
}
fringe of W. */
window_box (w, ANY_AREA, &x, &y, &width, &height);
-#ifdef USE_TOOLKIT_SCROLL_BARS
- /* If the fringe is adjacent to the left (right) scroll bar of a
- leftmost (rightmost, respectively) window, then extend its
- background to the gap between the fringe and the bar. */
- if ((WINDOW_LEFTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
- || (WINDOW_RIGHTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
- {
- int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
- if (sb_width > 0)
- {
- int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
- int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
- * FRAME_COLUMN_WIDTH (f));
-
- if (bar_area_x + bar_area_width == x)
- {
- x = bar_area_x + sb_width;
- width += bar_area_width - sb_width;
- }
- else if (x + width == bar_area_x)
- width += bar_area_width - sb_width;
- }
- }
-#endif
-
from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
bottom_y = y + height;
/* Don't stop displaying the initial startup message
for a switch-frame event we don't need. */
/* When run as a daemon, Vterminal_frame is always NIL. */
- bufp->arg = (((NILP (Vterminal_frame) || EQ (Fdaemonp (), Qt))
+ bufp->arg = (((NILP (Vterminal_frame)
+ || ! FRAME_X_P (XFRAME (Vterminal_frame))
+ || EQ (Fdaemonp (), Qt))
&& CONSP (Vframe_list)
&& !NILP (XCDR (Vframe_list)))
? Qt : Qnil);
}
-#if defined HAVE_MENUS && !defined USE_X_TOOLKIT && !defined USE_GTK
+#if !defined USE_X_TOOLKIT && !defined USE_GTK
/* Handle an event saying the mouse has moved out of an Emacs frame. */
void
/* Clear the area of W that will serve as a scroll bar. This is
for the case that a window has been split horizontally. In
this case, no clear_frame is generated to reduce flickering. */
- if (width > 0 && height > 0)
+ 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));
bar->start = 0;
bar->end = 0;
bar->dragging = -1;
- bar->fringe_extended_p = 0;
#if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
bar->last_seen_part = scroll_bar_nowhere;
#endif
struct frame *f = XFRAME (w->frame);
Lisp_Object barobj;
struct scroll_bar *bar;
- int top, height, left, sb_left, width, sb_width;
+ int top, height, left, width;
int window_y, window_height;
-#ifdef USE_TOOLKIT_SCROLL_BARS
- bool fringe_extended_p;
-#endif
/* Get window dimensions. */
window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
top = window_y;
- width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
height = window_height;
- /* Compute the left edge of the scroll bar area. */
+ /* Compute the left edge and the width of the scroll bar area. */
left = WINDOW_SCROLL_BAR_AREA_X (w);
-
- /* Compute the width of the scroll bar which might be less than
- the width of the area reserved for the scroll bar. */
- if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
- sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
- else
- sb_width = width;
-
- /* Compute the left edge of the scroll bar. */
-#ifdef USE_TOOLKIT_SCROLL_BARS
- if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
- sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
- else
- sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
-#else
- if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
- sb_left = left + width - sb_width;
- else
- sb_left = left;
-#endif
-
-#ifdef USE_TOOLKIT_SCROLL_BARS
- fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w);
-#endif
+ width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
/* Does the scroll bar exist yet? */
if (NILP (w->vertical_scroll_bar))
if (width > 0 && height > 0)
{
block_input ();
-#ifdef USE_TOOLKIT_SCROLL_BARS
- if (fringe_extended_p)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- sb_left, top, sb_width, height);
- else
-#endif
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width, height);
unblock_input ();
}
- bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
+ bar = x_scroll_bar_create (w, top, left, width, max (height, 1));
}
else
{
block_input ();
- if (sb_left != bar->left)
+ if (left != bar->left)
mask |= CWX;
if (top != bar->top)
mask |= CWY;
- if (sb_width != bar->width)
+ if (width != bar->width)
mask |= CWWidth;
if (height != bar->height)
mask |= CWHeight;
#ifdef USE_TOOLKIT_SCROLL_BARS
/* Move/size the scroll bar widget. */
- if (mask || bar->fringe_extended_p != fringe_extended_p)
+ if (mask)
{
/* 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)
- {
- if (fringe_extended_p)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- sb_left, top, sb_width, height);
- else
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height);
- }
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width, height);
#ifdef USE_GTK
xg_update_scrollbar_pos (f, bar->x_window, top,
- sb_left, sb_width, max (height, 1));
+ left, width, max (height, 1));
#else /* not USE_GTK */
XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
- sb_left, top, sb_width, max (height, 1), 0);
+ left, top, width, max (height, 1), 0);
#endif /* not USE_GTK */
}
#else /* not USE_TOOLKIT_SCROLL_BARS */
- /* Clear areas not covered by the scroll bar because it's not as
- wide as the area reserved for it. This makes sure a
- previous mode line display is cleared after C-x 2 C-x 1, for
- example. */
- {
- int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
- int rest = area_width - sb_width;
- if (rest > 0 && height > 0)
- {
- if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left + area_width - rest, top, rest, height);
- else
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, rest, height);
- }
- }
-
/* Move/size the scroll bar window. */
if (mask)
{
XWindowChanges wc;
- wc.x = sb_left;
+ wc.x = left;
wc.y = top;
- wc.width = sb_width;
+ wc.width = width;
wc.height = height;
XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
mask, &wc);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
/* Remember new settings. */
- bar->left = sb_left;
+ bar->left = left;
bar->top = top;
- bar->width = sb_width;
+ bar->width = width;
bar->height = height;
unblock_input ();
}
#ifdef USE_TOOLKIT_SCROLL_BARS
- bar->fringe_extended_p = fringe_extended_p;
-
x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
#else /* not USE_TOOLKIT_SCROLL_BARS */
/* Set the scroll bar's current state, unless we're currently being
static short temp_buffer[100];
#define STORE_KEYSYM_FOR_DEBUG(keysym) \
- if (temp_index == sizeof temp_buffer / sizeof (short)) \
+ if (temp_index == ARRAYELTS (temp_buffer)) \
temp_index = 0; \
temp_buffer[temp_index++] = (keysym)
/* This is the filter function invoked by the GTK event loop.
It is invoked before the XEvent is translated to a GdkEvent,
- so we have a chance to act on the event before GTK. */
+ so we have a chance to act on the event before GTK. */
static GdkFilterReturn
event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
{
if (! dpyinfo)
current_finish = X_EVENT_NORMAL;
else
- current_count +=
- handle_one_xevent (dpyinfo, xev, ¤t_finish,
- current_hold_quit);
+ current_count
+ += handle_one_xevent (dpyinfo, xev, ¤t_finish,
+ current_hold_quit);
}
else
current_finish = x_dispatch_event (xev, xev->xany.display);
*FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
*EVENT is unchanged unless we're processing KeyPress event.
- We return the number of characters stored into the buffer. */
+ We return the number of characters stored into the buffer. */
static int
handle_one_xevent (struct x_display_info *dpyinfo,
if (f)
{
bool iconified = FRAME_ICONIFIED_P (f);
- /* wait_reading_process_output will notice this and update
- the frame's display structures.
- If we where iconified, we should not set garbaged,
- because that stops redrawing on Expose events. This looks
- bad if we are called from a recursive event loop
- (x_dispatch_event), for example when a dialog is up. */
- if (!iconified)
- SET_FRAME_GARBAGED (f);
/* Check if fullscreen was specified before we where mapped the
- first time, i.e. from the command line. */
+ first time, i.e. from the command line. */
if (!f->output_data.x->has_been_visible)
x_check_fullscreen (f);
#ifdef USE_GTK
/* Don't pass keys to GTK. A Tab will shift focus to the
tool bar in GTK 2.4. Keys will still go to menus and
- dialogs because in that case popup_activated is TRUE
+ dialogs because in that case popup_activated is nonzero
(see above). */
*finish = X_EVENT_DROP;
#endif
{
#ifndef USE_X_TOOLKIT
#ifndef USE_GTK
- int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event->xconfigure.height);
- int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event->xconfigure.width);
+ int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width);
+ int height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, event->xconfigure.height);
/* In the toolkit version, change_frame_size
is called by the code that handles resizing
/* Even if the number of character rows and columns has
not changed, the font size may have changed, so we need
to check the pixel dimensions as well. */
- if (columns != FRAME_COLS (f)
- || rows != FRAME_LINES (f)
+ 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))
{
- change_frame_size (f, rows, columns, 0, 1, 0);
- SET_FRAME_GARBAGED (f);
+ change_frame_size (f, width, height, 0, 1, 0, 1);
+ x_clear_under_internal_border (f);
+ SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
- FRAME_PIXEL_WIDTH (f) = event->xconfigure.width;
- FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height;
+/** FRAME_PIXEL_WIDTH (f) = event->xconfigure.width; **/
+/** FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height; **/
#endif /* not USE_GTK */
#endif
#ifdef USE_GTK
/* GTK creates windows but doesn't map them.
- Only get real positions when mapped. */
+ Only get real positions when mapped. */
if (FRAME_GTK_OUTER_WIDGET (f)
&& gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
#endif
return count;
}
-#if defined USE_GTK || defined USE_X_TOOLKIT
-
/* Handles the XEvent EVENT on display DISPLAY.
This is used for event loops outside the normal event handling,
i.e. looping while a popup menu or a dialog is posted.
return finish;
}
-#endif
-
/* Read events coming from the X server.
Return as soon as there are no more events to be read.
block_input ();
- /* So people can tell when we have read the available input. */
- input_signal_count++;
-
/* For debugging, this gives a way to fake an I/O error. */
if (dpyinfo == XTread_socket_fake_io_error)
{
#ifdef USE_GTK
- if (xg_set_icon (f, xg_default_icon_file)
- || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
- return 0;
+ if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id == -2
+ || 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;
+ }
#elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
struct font *font = XFONT_OBJECT (font_object);
+ int unit;
if (fontset < 0)
fontset = fontset_from_font (font_object);
FRAME_COLUMN_WIDTH (f) = font->average_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
+ FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
+ FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
+
compute_fringe_widths (f, 1);
- /* Compute the scroll bar width in character columns. */
+ /* Compute character columns occupied by scrollbar.
+
+ Don't do things differently for non-toolkit scrollbars
+ (Bug#17163). */
+ unit = FRAME_COLUMN_WIDTH (f);
if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
- {
- int wid = FRAME_COLUMN_WIDTH (f);
- FRAME_CONFIG_SCROLL_BAR_COLS (f)
- = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
- }
+ FRAME_CONFIG_SCROLL_BAR_COLS (f)
+ = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
else
- {
- int wid = FRAME_COLUMN_WIDTH (f);
- FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
- }
+ FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
if (FRAME_X_WINDOW (f) != 0)
{
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)
- x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+ x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1);
}
#ifdef HAVE_X_I18N
{
#ifdef HAVE_X11R6_XIM
struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
+ Bool ret;
dpyinfo->xim_callback_data = xim_inst;
xim_inst->dpyinfo = dpyinfo;
xim_inst->resource_name = xstrdup (resource_name);
- XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
- resource_name, emacs_class,
- xim_instantiate_callback,
- /* This is XPointer in XFree86
- but (XPointer *) on Tru64, at
- least, hence the configure test. */
- (XRegisterIMInstantiateCallback_arg6) xim_inst);
+ ret = XRegisterIMInstantiateCallback
+ (dpyinfo->display, dpyinfo->xrdb, xim_inst->resource_name,
+ emacs_class, xim_instantiate_callback,
+ /* This is XPointer in XFree86 but (XPointer *)
+ on Tru64, at least, hence the configure test. */
+ (XRegisterIMInstantiateCallback_arg6) xim_inst);
+ eassert (ret == True);
#else /* not HAVE_X11R6_XIM */
xim_open_dpy (dpyinfo, resource_name);
#endif /* not HAVE_X11R6_XIM */
if (use_xim)
{
#ifdef HAVE_X11R6_XIM
+ struct xim_inst_t *xim_inst = dpyinfo->xim_callback_data;
+
if (dpyinfo->display)
- XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
- NULL, emacs_class,
- xim_instantiate_callback, NULL);
- xfree (dpyinfo->xim_callback_data->resource_name);
- xfree (dpyinfo->xim_callback_data);
+ {
+ Bool ret = XUnregisterIMInstantiateCallback
+ (dpyinfo->display, dpyinfo->xrdb, xim_inst->resource_name,
+ emacs_class, xim_instantiate_callback,
+ (XRegisterIMInstantiateCallback_arg6) xim_inst);
+ eassert (ret == True);
+ }
+ xfree (xim_inst->resource_name);
+ xfree (xim_inst);
#endif /* HAVE_X11R6_XIM */
if (dpyinfo->display)
XCloseIM (dpyinfo->xim);
size changes. Otherwise we leave the window gravity unchanged. */
static void
-x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
{
int pixelwidth, pixelheight;
- check_frame_size (f, &rows, &cols);
- f->scroll_bar_actual_width
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f));
+ check_frame_size (f, &width, &height, pixelwise);
compute_fringe_widths (f, 0);
- pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
- + FRAME_TOOLBAR_WIDTH (f);
- pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
- + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
-
+ pixelwidth = ((pixelwise
+ ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width)
+ : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width))
+ + FRAME_TOOLBAR_WIDTH (f));
+ pixelheight = ((pixelwise
+ ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height)
+ : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height))
+ + FRAME_MENUBAR_HEIGHT (f)
+ + FRAME_TOOLBAR_HEIGHT (f));
if (change_gravity) f->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
x_wait_for_event (f, ConfigureNotify);
else
{
- change_frame_size (f, rows, cols, 0, 1, 0);
- FRAME_PIXEL_WIDTH (f) = pixelwidth;
- FRAME_PIXEL_HEIGHT (f) = pixelheight;
+ change_frame_size (f, width, height, 0, 1, 0, 1);
x_sync (f);
}
}
Otherwise we leave the window gravity unchanged. */
void
-x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
{
block_input ();
+ check_frame_size (f, &width, &height, pixelwise);
+
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
{
- int r, c;
+ int text_width, text_height;
/* When the frame is maximized/fullscreen or running under for
example Xmonad, x_set_window_size_1 will be a no-op.
- In that case, the right thing to do is extend rows/cols to
+ In that case, the right thing to do is extend rows/width to
the current frame size. We do that first if x_set_window_size_1
turns out to not be a no-op (there is no way to know).
The size will be adjusted again if the frame gets a
is however. */
pixelh -= FRAME_MENUBAR_HEIGHT (f);
#endif
- r = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
- /* Update f->scroll_bar_actual_width because it is used in
- FRAME_PIXEL_WIDTH_TO_TEXT_COLS. */
- f->scroll_bar_actual_width
- = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
- c = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
- change_frame_size (f, r, c, 0, 1, 0);
+ 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);
}
#ifdef USE_GTK
if (FRAME_GTK_WIDGET (f))
- xg_frame_set_char_size (f, cols, rows);
+ 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);
else
- x_set_window_size_1 (f, change_gravity, cols, rows);
+ x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
#else /* not USE_GTK */
- x_set_window_size_1 (f, change_gravity, cols, rows);
+ x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
+#if !defined USE_X_TOOLKIT
+ x_clear_under_internal_border (f);
+#endif
#endif /* not USE_GTK */
x_make_frame_visible (struct frame *f)
{
int original_top, original_left;
- int retry_count = 2;
-
- retry:
+ int tries = 0;
block_input ();
so that incoming events are handled. */
{
Lisp_Object frame;
- int count;
/* This must be before UNBLOCK_INPUT
since events that arrive in response to the actions above
will set it when they are handled. */
XSETFRAME (frame, f);
- /* Wait until the frame is visible. Process X events until a
- MapNotify event has been seen, or until we think we won't get a
- MapNotify at all.. */
- for (count = input_signal_count + 10;
- input_signal_count < count && !FRAME_VISIBLE_P (f);)
+ /* Process X events until a MapNotify event has been seen. */
+ while (!FRAME_VISIBLE_P (f))
{
/* Force processing of queued events. */
x_sync (f);
- /* Machines that do polling rather than SIGIO have been
+ /* If on another desktop, the deiconify/map may be ignored and the
+ frame never becomes visible. XMonad does this.
+ Prevent an endless loop. */
+ if (FRAME_ICONIFIED_P (f) && ++tries > 100)
+ break;
+
+ /* This hack is still in use at least for Cygwin. See
+ http://lists.gnu.org/archive/html/emacs-devel/2013-12/msg00351.html.
+
+ Machines that do polling rather than SIGIO have been
observed to go into a busy-wait here. So we'll fake an
alarm signal to let the handler know that there's something
to be read. We used to raise a real alarm, but it seems
poll_for_input_1 ();
poll_suppress_count = old_poll_suppress_count;
}
- }
-
- /* 2000-09-28: In
-
- (let ((f (selected-frame)))
- (iconify-frame f)
- (raise-frame f))
- the frame is not raised with various window managers on
- FreeBSD, GNU/Linux and Solaris. It turns out that, for some
- unknown reason, the call to XtMapWidget is completely ignored.
- Mapping the widget a second time works. */
-
- if (!FRAME_VISIBLE_P (f) && --retry_count != 0)
- goto retry;
+ if (XPending (FRAME_X_DISPLAY (f)))
+ {
+ XEvent xev;
+ XNextEvent (FRAME_X_DISPLAY (f), &xev);
+ x_dispatch_event (&xev, FRAME_X_DISPLAY (f));
+ }
+ }
}
}
/* We must free faces before destroying windows because some
font-driver (e.g. xft) access a window while finishing a
face. */
- if (FRAME_FACE_CACHE (f))
- free_frame_faces (f);
+ free_frame_faces (f);
if (f->output_data.x->icon_desc)
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
#endif /* USE_TOOLKIT_SCROLL_BARS */
- if (f->output_data.x->white_relief.allocated_p)
+ if (f->output_data.x->white_relief.pixel != -1)
unload_color (f, f->output_data.x->white_relief.pixel);
- if (f->output_data.x->black_relief.allocated_p)
+ if (f->output_data.x->black_relief.pixel != -1)
unload_color (f, f->output_data.x->black_relief.pixel);
x_free_gcs (f);
f->output_data.x->black_relief.gc = 0;
}
+ /* Free cursors. */
+ if (f->output_data.x->text_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
+ if (f->output_data.x->nontext_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
+ if (f->output_data.x->modeline_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
+ if (f->output_data.x->hand_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hand_cursor);
+ if (f->output_data.x->hourglass_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor);
+ if (f->output_data.x->horizontal_drag_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
+ if (f->output_data.x->vertical_drag_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->vertical_drag_cursor);
+
XFlush (FRAME_X_DISPLAY (f));
}
size_hints.height = FRAME_PIXEL_HEIGHT (f);
size_hints.width = FRAME_PIXEL_WIDTH (f);
- size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
- size_hints.height_inc = FRAME_LINE_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);
+
size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
- check_frame_size (f, &min_rows, &min_cols);
+ check_frame_size (f, &min_cols, &min_rows, 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
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 * size_hints.width_inc;
- size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+ size_hints.min_width = base_width + min_cols * FRAME_COLUMN_WIDTH (f);
+ size_hints.min_height = base_height + min_rows * FRAME_LINE_HEIGHT (f);
}
/* If we don't need the old flags, we don't need the old hint at all. */
get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
to 5. */
static void
-get_bits_and_offset (long unsigned int mask, int *bits, int *offset)
+get_bits_and_offset (unsigned long mask, int *bits, int *offset)
{
int nr = 0;
int off = 0;
}
#endif
+/* Create invisible cursor on X display referred by DPYINFO. */
+
+static Cursor
+make_invisible_cursor (struct x_display_info *dpyinfo)
+{
+ Display *dpy = dpyinfo->display;
+ static char const no_data[] = { 0 };
+ Pixmap pix;
+ XColor col;
+ Cursor c = 0;
+
+ x_catch_errors (dpy);
+ pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1);
+ if (! x_had_errors_p (dpy) && pix != None)
+ {
+ Cursor pixc;
+ col.pixel = 0;
+ col.red = col.green = col.blue = 0;
+ col.flags = DoRed | DoGreen | DoBlue;
+ pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
+ if (! x_had_errors_p (dpy) && pixc != None)
+ c = pixc;
+ XFreePixmap (dpy, pix);
+ }
+
+ x_uncatch_errors ();
+
+ return c;
+}
+
+/* True if DPY supports Xfixes extension >= 4. */
+
+static bool
+x_probe_xfixes_extension (Display *dpy)
+{
+#ifdef HAVE_XFIXES
+ int major, minor;
+ return XFixesQueryVersion (dpy, &major, &minor) && major >= 4;
+#else
+ return false;
+#endif /* HAVE_XFIXES */
+}
+
+/* Toggle mouse pointer visibility on frame F by using Xfixes functions. */
+
+static void
+xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
+{
+#ifdef HAVE_XFIXES
+ if (invisible)
+ XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ else
+ XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ f->pointer_invisible = invisible;
+#else
+ emacs_abort ();
+#endif /* HAVE_XFIXES */
+}
+
+/* Toggle mouse pointer visibility on frame F by using invisible cursor. */
+
+static void
+x_toggle_visible_pointer (struct frame *f, bool invisible)
+{
+ eassert (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0);
+ if (invisible)
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->invisible_cursor);
+ else
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ f->output_data.x->current_cursor);
+ f->pointer_invisible = invisible;
+}
+
+/* Setup pointer blanking, prefer Xfixes if available. */
+
+static void
+x_setup_pointer_blanking (struct x_display_info *dpyinfo)
+{
+ if (x_probe_xfixes_extension (dpyinfo->display))
+ dpyinfo->toggle_visible_pointer = xfixes_toggle_visible_pointer;
+ else
+ {
+ dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer;
+ dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
+ }
+}
+
+/* Current X display connection identifier. Incremented for each next
+ connection established. */
+static unsigned x_display_id;
+
/* Open a connection to X display DISPLAY_NAME, and return
the structure that describes the open display.
If we cannot contact the display, return null. */
{
struct x_display_info *share;
- Lisp_Object tail;
- for (share = x_display_list, tail = x_display_name_list; share;
- share = share->next, tail = XCDR (tail))
- if (same_x_server (SSDATA (XCAR (XCAR (tail))),
+ for (share = x_display_list; share; share = share->next)
+ if (same_x_server (SSDATA (XCAR (share->name_list_element)),
SSDATA (display_name)))
break;
if (share)
terminal->kboard = share->terminal->kboard;
else
{
- terminal->kboard = xmalloc (sizeof *terminal->kboard);
- init_kboard (terminal->kboard);
- kset_window_system (terminal->kboard, Qx);
-
- /* Add the keyboard to the list before running Lisp code (via
- Qvendor_specific_keysyms below), since these are not traced
- via terminals but only through all_kboards. */
- terminal->kboard->next_kboard = all_kboards;
- all_kboards = terminal->kboard;
+ terminal->kboard = allocate_kboard (Qx);
if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
{
dpyinfo->next = x_display_list;
x_display_list = dpyinfo;
- /* Put it on x_display_name_list as well, to keep them parallel. */
- x_display_name_list = Fcons (Fcons (display_name, Qnil),
- x_display_name_list);
- dpyinfo->name_list_element = XCAR (x_display_name_list);
-
+ dpyinfo->name_list_element = Fcons (display_name, Qnil);
dpyinfo->display = dpy;
/* Set the name of the terminal. */
lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name))
memory_full (SIZE_MAX);
+ dpyinfo->x_id = ++x_display_id;
dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name)
+ SBYTES (Vsystem_name) + 2);
strcat (strcat (strcpy (dpyinfo->x_id_name, SSDATA (Vinvocation_name)), "@"),
};
int i;
- const int atom_count = sizeof (atom_refs) / sizeof (atom_refs[0]);
+ const int atom_count = ARRAYELTS (atom_refs);
/* 1 for _XSETTINGS_SN */
const int total_atom_count = 1 + atom_count;
Atom *atoms_return = xmalloc (total_atom_count * sizeof *atoms_return);
gray_bits, gray_width, gray_height,
1, 0, 1);
+ x_setup_pointer_blanking (dpyinfo);
+
#ifdef HAVE_X_I18N
xim_initialize (dpyinfo, resource_name);
#endif
#ifdef USE_LUCID
{
+ XFontStruct *xfont = NULL;
XrmValue d, fr, to;
Font font;
x_catch_errors (dpy);
if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
emacs_abort ();
- if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
+ if (x_had_errors_p (dpy) || !((xfont = XQueryFont (dpy, font))))
XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
+ if (xfont)
+ XFreeFont (dpy, xfont);
x_uncatch_errors ();
}
#endif
if (STRINGP (value)
&& (!strcmp (SSDATA (value), "false")
|| !strcmp (SSDATA (value), "off")))
- use_xim = 0;
+ use_xim = false;
#else
if (STRINGP (value)
&& (!strcmp (SSDATA (value), "true")
|| !strcmp (SSDATA (value), "on")))
- use_xim = 1;
+ use_xim = true;
#endif
}
break;
}
- /* Discard this display from x_display_name_list and x_display_list.
- We can't use Fdelq because that can quit. */
- if (! NILP (x_display_name_list)
- && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
- x_display_name_list = XCDR (x_display_name_list);
- else
- {
- Lisp_Object tail;
-
- tail = x_display_name_list;
- while (CONSP (tail) && CONSP (XCDR (tail)))
- {
- if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
- {
- XSETCDR (tail, XCDR (XCDR (tail)));
- break;
- }
- tail = XCDR (tail);
- }
- }
-
if (next_noop_dpyinfo == dpyinfo)
next_noop_dpyinfo = dpyinfo->next;
x_clear_frame_area,
x_draw_window_cursor,
x_draw_vertical_window_border,
+ x_draw_window_divider,
x_shift_glyphs_for_insert
};
terminal->delete_terminal_hook = x_delete_terminal;
terminal->rif = &x_redisplay_interface;
- terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
- terminal->char_ins_del_ok = 1;
- terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
- terminal->fast_clear_end_of_line = 1; /* X does this well. */
- terminal->memory_below_frame = 0; /* We don't remember what scrolls
- off the bottom. */
return terminal;
}
{
x_error_message = NULL;
- staticpro (&x_display_name_list);
- x_display_name_list = Qnil;
-
DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
DEFSYM (Qlatin_1, "latin-1");
Vx_toolkit_scroll_bars = Qnil;
#endif
- Qmodifier_value = intern_c_string ("modifier-value");
- Qalt = intern_c_string ("alt");
+ DEFSYM (Qmodifier_value, "modifier-value");
+ DEFSYM (Qalt, "alt");
Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
- Qhyper = intern_c_string ("hyper");
+ DEFSYM (Qhyper, "hyper");
Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
- Qmeta = intern_c_string ("meta");
+ DEFSYM (Qmeta, "meta");
Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
- Qsuper = intern_c_string ("super");
+ DEFSYM (Qsuper, "super");
Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,