/* 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
+
+/* Using Xft implies that XRender is available. */
+#ifdef HAVE_XFT
+#include <X11/extensions/Xrender.h>
+#endif
+
/* Load sys/types.h if not already loaded.
In some systems loading it twice is suicidal. */
#ifndef makedev
#include "xsettings.h"
#include "xgselect.h"
#include "sysselect.h"
+#include "menu.h"
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>
/* 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
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 *);
-void x_delete_terminal (struct terminal *);
static void x_update_end (struct frame *);
static void XTframe_up_to_date (struct frame *);
static void x_clear_frame (struct frame *);
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;
unsigned int nchildren;
win = wi;
- XQueryTree (dpy, win, &root, &wi, &children, &nchildren);
- XFree (children);
+ if (XQueryTree (dpy, win, &root, &wi, &children, &nchildren))
+ XFree (children);
+ else
+ break;
}
return win;
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 = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
- if (face)
- XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
- face->foreground);
+ 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);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->normal_gc, x0, y0, x1 - x0, y1 - y0);
+ 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.
/* If a row with mouse-face was overwritten, arrange for
XTframe_up_to_date to redisplay the mouse highlight. */
if (mouse_face_overwritten_p)
- reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame)));
+ {
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
+
+ hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+ hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+ hlinfo->mouse_face_window = Qnil;
+ }
}
}
+/* 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
else
face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
s->face = FACE_FROM_ID (s->f, face_id);
- PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+ prepare_face_for_display (s->f, s->face);
if (s->font == s->face->font)
s->gc = s->face->gc;
static void
x_set_glyph_string_gc (struct glyph_string *s)
{
- PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+ prepare_face_for_display (s->f, s->face);
if (s->hl == DRAW_NORMAL_TEXT)
{
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);
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)
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 ();
}
/* 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);
gpointer user_data)
{
struct scroll_bar *bar = user_data;
- gdouble position;
int part = -1, whole = 0, portion = 0;
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;
- position = gtk_adjustment_get_value (adj);
-
switch (scroll)
{
part = scroll_bar_handle;
whole = gtk_adjustment_get_upper (adj) -
gtk_adjustment_get_page_size (adj);
- portion = min ((int)position, whole);
+ portion = min ((int)value, whole);
bar->dragging = portion;
}
break;
/* Compute the left edge and the width of the scroll bar area. */
left = WINDOW_SCROLL_BAR_AREA_X (w);
- width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
+ width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
/* Does the scroll bar exist yet? */
if (NILP (w->vertical_scroll_bar))
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);
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. */
#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
for (i = 0, nchars = 0; i < nbytes; i++)
{
- if (ASCII_BYTE_P (copy_bufptr[i]))
+ if (ASCII_CHAR_P (copy_bufptr[i]))
nchars++;
STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
}
|| event->xconfigure.height != FRAME_PIXEL_HEIGHT (f))
{
change_frame_size (f, width, height, 0, 1, 0, 1);
- SET_FRAME_GARBAGED (f);
+ x_clear_under_internal_border (f);
+ SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
#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
{
dpyinfo->grabbed |= (1 << event->xbutton.button);
dpyinfo->last_mouse_frame = f;
-
- if (!tool_bar_p)
- last_tool_bar_item = -1;
+#if ! defined (USE_GTK)
+ if (f && !tool_bar_p)
+ f->last_tool_bar_item = -1;
+#endif /* not USE_GTK */
}
else
dpyinfo->grabbed &= ~(1 << event->xbutton.button);
#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)
{
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
Lisp_Object frame, tail;
- ptrdiff_t idx = SPECPDL_INDEX ();
+ dynwind_begin ();
error_msg = alloca (strlen (error_message) + 1);
strcpy (error_msg, error_message);
totally_unblock_input ();
- unbind_to (idx, Qnil);
+ dynwind_end ();
clear_waiting_for_input ();
/* Tell GCC not to suggest attribute 'noreturn' for this function. */
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);
compute_fringe_widths (f, 1);
- /* Compute the scroll bar width in character columns. */
- if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
- {
- int wid = FRAME_COLUMN_WIDTH (f);
+ /* Compute character columns occupied by scrollbar.
- FRAME_CONFIG_SCROLL_BAR_COLS (f)
- = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
- }
+ Don't do things differently for non-toolkit scrollbars
+ (Bug#17163). */
+ unit = FRAME_COLUMN_WIDTH (f);
+ if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
+ 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_WIDTH (f) = 14;
- 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)
{
#endif /* HAVE_X11R6 */
-#ifdef HAVE_X11R6
-/* This isn't prototyped in OSF 5.0 or 5.1a. */
-extern char *XSetIMValues (XIM, ...);
-#endif
-
/* Open the connection to the XIM server on display DPYINFO.
RESOURCE_NAME is the resource name Emacs uses. */
{
#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);
int pixelwidth, pixelheight;
check_frame_size (f, &width, &height, pixelwise);
- f->scroll_bar_actual_width
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f));
compute_fringe_widths (f, 0);
#endif
text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (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);
+
change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
}
#else /* not USE_GTK */
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 */
unblock_input ();
}
-\f
-/* Mouse warping. */
-
-void
-x_set_mouse_position (struct frame *f, int x, int y)
-{
- int pix_x, pix_y;
-
- pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
- pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
-
- if (pix_x < 0) pix_x = 0;
- if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
-
- if (pix_y < 0) pix_y = 0;
- if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
-
- block_input ();
-
- XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
- 0, 0, 0, 0, pix_x, pix_y);
- unblock_input ();
-}
/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
void
-x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
+frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
{
block_input ();
x_make_frame_visible (struct frame *f)
{
int original_top, original_left;
+ int tries = 0;
block_input ();
/* Force processing of queued events. */
x_sync (f);
- /* This hack is still in use at least for Cygwin. See
+ /* 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
that the handler isn't always enabled here. This is
probably a bug. */
if (input_polling_used ())
- {
- /* It could be confusing if a real alarm arrives while
- processing the fake one. Turn it off and let the
- handler reset it. */
- int old_poll_suppress_count = poll_suppress_count;
- poll_suppress_count = 1;
- poll_for_input_1 ();
- poll_suppress_count = old_poll_suppress_count;
- }
+ poll_for_input_1 ();
if (XPending (FRAME_X_DISPLAY (f)))
{
commands to the X server. */
if (dpyinfo->display)
{
+ /* Always exit with visible pointer to avoid weird issue
+ with Xfixes (Bug#17609). */
+ if (f->pointer_invisible)
+ FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, 0);
+
/* We must free faces before destroying windows because some
font-driver (e.g. xft) access a window while finishing a
face. */
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))
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
resizing; min_width and min_height aren't useful for this
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. */
}
#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)
+{
+ /* FIXME: the brave tester should set EMACS_XFIXES because we're suspecting
+ X server bug, see http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17609. */
+ if (egetenv ("EMACS_XFIXES") && 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. */
{
terminal->kboard = allocate_kboard (Qx);
- if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
+ if (!EQ (SYMBOL_FUNCTION (Qvendor_specific_keysyms), Qunbound))
{
char *vendor = ServerVendor (dpy);
lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name))
memory_full (SIZE_MAX);
- dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name)
- + SBYTES (Vsystem_name) + 2);
+ dpyinfo->x_id = ++x_display_id;
+ dpyinfo->x_id_name = xmalloc_atomic (SBYTES (Vinvocation_name)
+ + SBYTES (Vsystem_name) + 2);
strcat (strcat (strcpy (dpyinfo->x_id_name, SSDATA (Vinvocation_name)), "@"),
SSDATA (Vsystem_name));
#ifdef HAVE_XFT
{
- /* If we are using Xft, check dpi value in X resources.
- It is better we use it as well, since Xft will use it, as will all
- Gnome applications. If our real DPI is smaller or larger than the
- one Xft uses, our font will look smaller or larger than other
- for other applications, even if it is the same font name (monospace-10
- for example). */
- char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
+ /* If we are using Xft, the following precautions should be made:
+
+ 1. Make sure that the Xrender extension is added before the Xft one.
+ Otherwise, the close-display hook set by Xft is called after the one
+ for Xrender, and the former tries to re-add the latter. This results
+ in inconsistency of internal states and leads to X protocol error when
+ one reconnects to the same X server (Bug#1696).
+
+ 2. Check dpi value in X resources. It is better we use it as well,
+ since Xft will use it, as will all Gnome applications. If our real DPI
+ is smaller or larger than the one Xft uses, our font will look smaller
+ or larger than other for other applications, even if it is the same
+ font name (monospace-10 for example). */
+
+ int event_base, error_base;
+ char *v;
double d;
+
+ XRenderQueryExtension (dpyinfo->display, &event_base, &error_base);
+
+ v = XGetDefault (dpyinfo->display, "Xft", "dpi");
if (v != NULL && sscanf (v, "%lf", &d) == 1)
dpyinfo->resy = dpyinfo->resx = d;
}
};
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
}
{
struct terminal *terminal;
- terminal = create_terminal ();
+ terminal = create_terminal (output_x_window, &x_redisplay_interface);
- terminal->type = output_x_window;
terminal->display_info.x = dpyinfo;
dpyinfo->terminal = terminal;
terminal->delete_glyphs_hook = x_delete_glyphs;
terminal->ring_bell_hook = XTring_bell;
terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
- terminal->reset_terminal_modes_hook = NULL;
- terminal->set_terminal_modes_hook = NULL;
terminal->update_begin_hook = x_update_begin;
terminal->update_end_hook = x_update_end;
- terminal->set_terminal_window_hook = NULL;
terminal->read_socket_hook = XTread_socket;
terminal->frame_up_to_date_hook = XTframe_up_to_date;
terminal->mouse_position_hook = XTmouse_position;
terminal->frame_rehighlight_hook = XTframe_rehighlight;
terminal->frame_raise_lower_hook = XTframe_raise_lower;
terminal->fullscreen_hook = XTfullscreen_hook;
+ terminal->menu_show_hook = x_menu_show;
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+ terminal->popup_dialog_hook = xw_popup_dialog;
+#endif
terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
-
terminal->delete_frame_hook = x_destroy_window;
terminal->delete_terminal_hook = x_delete_terminal;
-
- terminal->rif = &x_redisplay_interface;
+ /* Other hooks are NULL by default. */
return terminal;
}
-void
+static void
x_initialize (void)
{
baud_rate = 19200;
x_noop_count = 0;
- last_tool_bar_item = -1;
any_help_event_p = 0;
ignore_next_mouse_click_timeout = 0;