/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
+ Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#ifdef HAVE_X_WINDOWS
-#define DOC_STRINGS_IN_COMMENTS
#include "lisp.h"
#include "blockinput.h"
#include <unistd.h>
#endif
+#ifdef USE_LUCID
+extern int xlwmenu_window_p P_ ((Widget w, Window window));
+extern void xlwmenu_redisplay P_ ((Widget));
+#endif
+
#ifdef USE_X_TOOLKIT
extern void free_frame_menubar P_ ((struct frame *));
#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
\f
-/* Bitmaps for truncated lines. */
+/* Fringe bitmaps. */
-enum bitmap_type
+enum fringe_bitmap_type
{
- NO_BITMAP,
+ NO_FRINGE_BITMAP,
LEFT_TRUNCATION_BITMAP,
RIGHT_TRUNCATION_BITMAP,
OVERLAY_ARROW_BITMAP,
`indicate-empty-lines' is non-nil. */
#define zv_width 8
-#define zv_height 8
+#define zv_height 72
+#define zv_period 3
static unsigned char zv_bits[] = {
- 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
/* An arrow like this: `<-'. */
static int any_help_event_p;
+/* Non-zero means autoselect window with the mouse cursor. */
+
+int mouse_autoselect_window;
+
+/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
+static Lisp_Object last_window;
+
/* Non-zero means draw block and hollow cursor as wide as the glyph
under it. For example, if a block cursor is over a tab, it will be
drawn as wide as that tab on the display. */
extern struct frame *updating_frame;
-extern int waiting_for_input;
-
/* This is a frame waiting to be auto-raised, within XTread_socket. */
struct frame *pending_autoraise_frame;
/* A mask of extra modifier bits to put into every keyboard char. */
-extern int extra_keyboard_modifiers;
+extern EMACS_INT extra_keyboard_modifiers;
+
+/* The keysyms to use for the various modifiers. */
+
+Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
+static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
static Lisp_Object Qvendor_specific_keysyms;
+static Lisp_Object Qlatin_1, Qutf_8;
extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
extern Lisp_Object x_icon_type P_ ((struct frame *));
static void set_output_cursor P_ ((struct cursor_pos *));
static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
int *, int *, int *, int));
-static void note_mode_line_highlight P_ ((struct window *, int, int));
+static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
+ int, int));
static void note_mouse_highlight P_ ((struct frame *, int, int));
static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
enum draw_glyphs_face));
static void x_update_end P_ ((struct frame *));
static void XTframe_up_to_date P_ ((struct frame *));
-static void XTreassert_line_highlight P_ ((int, int));
-static void x_change_line_highlight P_ ((int, int, int, int));
static void XTset_terminal_modes P_ ((void));
static void XTreset_terminal_modes P_ ((void));
static void XTcursor_to P_ ((int, int, int, int));
static void frame_highlight P_ ((struct frame *));
static void frame_unhighlight P_ ((struct frame *));
static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
+static int x_focus_changed P_ ((int,
+ int,
+ struct x_display_info *,
+ struct frame *,
+ struct input_event *,
+ int));
+static int x_detect_focus_change P_ ((struct x_display_info *,
+ XEvent *,
+ struct input_event *,
+ int));
static void XTframe_rehighlight P_ ((struct frame *));
static void x_frame_rehighlight P_ ((struct x_display_info *));
static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
+ enum text_cursor_kinds));
static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
XRectangle *));
static void expose_frame P_ ((struct frame *, int, int, int, int));
static int expose_window_tree P_ ((struct window *, XRectangle *));
+static void expose_overlaps P_ ((struct window *, struct glyph_row *,
+ struct glyph_row *));
static int expose_window P_ ((struct window *, XRectangle *));
static void expose_area P_ ((struct window *, struct glyph_row *,
XRectangle *, enum glyph_row_area));
static void x_update_window_cursor P_ ((struct window *, int));
static void x_erase_phys_cursor P_ ((struct window *));
void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
-static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
- enum bitmap_type));
+static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
+ enum fringe_bitmap_type, int left_p));
static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
GC, int));
static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
-static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
-static void notice_overwritten_cursor P_ ((struct window *, int, int));
+static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
+static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,
+ int, int, int, int));
static void x_flush P_ ((struct frame *f));
static void x_update_begin P_ ((struct frame *));
static void x_update_window_begin P_ ((struct window *));
enum scroll_bar_part *,
Lisp_Object *, Lisp_Object *,
unsigned long *));
+static void x_check_fullscreen P_ ((struct frame *));
+static void x_check_fullscreen_move P_ ((struct frame *));
/* Flush display of frame F, or of all frames if F is null. */
int x0, x1, y0, y1;
window_box_edges (w, -1, &x0, &y0, &x1, &y1);
- x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
+ x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
y1 -= 1;
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
- arrow bitmaps, or clear the areas where they would be displayed
+ arrow bitmaps, or clear the fringes if no bitmaps are required
before DESIRED_ROW is made current. The window being updated is
found in updated_window. This function It is called from
update_window_line only if it is known that there are differences
struct glyph_row *desired_row;
{
struct window *w = updated_window;
+ struct frame *f;
+ int width, height;
xassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
{
- struct frame *f;
- int width;
-
BLOCK_INPUT;
- x_draw_row_bitmaps (w, desired_row);
-
- /* When a window has disappeared, make sure that no rest of
- full-width rows stays visible in the internal border. */
- if (windows_or_buffers_changed
- && (f = XFRAME (w->frame),
- width = FRAME_INTERNAL_BORDER_WIDTH (f),
- width != 0))
- {
- int height = desired_row->visible_height;
- int x = (window_box_right (w, -1)
- + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
- int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
-
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- x, y, width, height, False);
- }
+ x_draw_row_fringe_bitmaps (w, desired_row);
+ UNBLOCK_INPUT;
+ }
+ /* 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));
+
+ /* Internal border is drawn below the tool bar. */
+ if (WINDOWP (f->tool_bar_window)
+ && w == XWINDOW (f->tool_bar_window))
+ y -= width;
+
+ BLOCK_INPUT;
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ 0, y, width, height, False);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ f->output_data.x->pixel_width - width,
+ y, width, height, False);
UNBLOCK_INPUT;
}
}
-/* Draw the bitmap WHICH in one of the areas to the left or right of
+/* Draw the bitmap WHICH in one of the left or right fringes of
window W. ROW is the glyph row for which to display the bitmap; it
determines the vertical position at which the bitmap has to be
drawn. */
static void
-x_draw_bitmap (w, row, which)
+x_draw_fringe_bitmap (w, row, which, left_p)
struct window *w;
struct glyph_row *row;
- enum bitmap_type which;
+ enum fringe_bitmap_type which;
+ int left_p;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
Display *display = FRAME_X_DISPLAY (f);
Window window = FRAME_X_WINDOW (f);
int x, y, wd, h, dy;
- unsigned char *bits;
+ int b1, b2;
+ unsigned char *bits = NULL;
Pixmap pixmap;
GC gc = f->output_data.x->normal_gc;
struct face *face;
/* Must clip because of partially visible lines. */
x_clip_to_row (w, row, gc, 1);
+ /* Convert row to frame coordinates. */
+ y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
switch (which)
{
+ case NO_FRINGE_BITMAP:
+ wd = 0;
+ h = 0;
+ break;
+
case LEFT_TRUNCATION_BITMAP:
wd = left_width;
h = left_height;
bits = left_bits;
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case OVERLAY_ARROW_BITMAP:
- wd = left_width;
- h = left_height;
+ wd = ov_width;
+ h = ov_height;
bits = ov_bits;
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case RIGHT_TRUNCATION_BITMAP:
wd = right_width;
h = right_height;
bits = right_bits;
- x = window_box_right (w, -1);
- x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
break;
case CONTINUED_LINE_BITMAP:
- wd = right_width;
- h = right_height;
+ wd = continued_width;
+ h = continued_height;
bits = continued_bits;
- x = window_box_right (w, -1);
- x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
break;
case CONTINUATION_LINE_BITMAP:
wd = continuation_width;
h = continuation_height;
bits = continuation_bits;
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case ZV_LINE_BITMAP:
wd = zv_width;
- h = zv_height;
- bits = zv_bits;
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
+ h = zv_height - (y % zv_period);
+ bits = zv_bits + (y % zv_period);
break;
default:
abort ();
}
- /* Convert to frame coordinates. Set dy to the offset in the row to
- start drawing the bitmap. */
- y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
- dy = (row->height - h) / 2;
-
- /* Draw the bitmap. I believe these small pixmaps can be cached
- by the server. */
- face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
- pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
- face->foreground,
- face->background, depth);
- XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
- XFreePixmap (display, pixmap);
- XSetClipMask (display, gc, None);
-}
-
+ /* Clip bitmap if too high. */
+ if (h > row->height)
+ h = row->height;
-/* Draw flags bitmaps for glyph row ROW on window W. Call this
- function with input blocked. */
-
-static void
-x_draw_row_bitmaps (w, row)
- struct window *w;
- struct glyph_row *row;
-{
- struct frame *f = XFRAME (w->frame);
- enum bitmap_type bitmap;
- struct face *face;
- int header_line_height = -1;
-
- xassert (interrupt_input_blocked);
-
- /* If row is completely invisible, because of vscrolling, we
- don't have to draw anything. */
- if (row->visible_height <= 0)
- return;
+ /* Set dy to the offset in the row to start drawing the bitmap. */
+ dy = (row->height - h) / 2;
- face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
+ face = FACE_FROM_ID (f, FRINGE_FACE_ID);
PREPARE_FACE_FOR_DISPLAY (f, face);
- /* Decide which bitmap to draw at the left side. */
- if (row->overlay_arrow_p)
- bitmap = OVERLAY_ARROW_BITMAP;
- else if (row->truncated_on_left_p)
- bitmap = LEFT_TRUNCATION_BITMAP;
- else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
- bitmap = CONTINUATION_LINE_BITMAP;
- else if (row->indicate_empty_line_p)
- bitmap = ZV_LINE_BITMAP;
+ /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
+ the fringe. */
+ b1 = b2 = -1;
+ if (left_p)
+ {
+ if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
+ wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
+ x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
+ - wd
+ - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
+ if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
+ {
+ /* If W has a vertical border to its left, don't draw over it. */
+ int border = ((XFASTINT (w->left) > 0
+ && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ ? 1 : 0);
+ b1 = (window_box_left (w, -1)
+ - FRAME_X_LEFT_FRINGE_WIDTH (f)
+ + border);
+ b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
+ }
+ }
else
- bitmap = NO_BITMAP;
-
- /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
- the flags area. */
- if (bitmap == NO_BITMAP
- || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
- || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
- {
- /* If W has a vertical border to its left, don't draw over it. */
- int border = ((XFASTINT (w->left) > 0
- && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- ? 1 : 0);
- int left = window_box_left (w, -1);
-
- if (header_line_height < 0)
- header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+ {
+ if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
+ wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+ x = (window_box_right (w, -1)
+ + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
+ /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
+ the fringe. */
+ if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
+ {
+ b1 = window_box_right (w, -1);
+ b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+ }
+ }
+
+ if (b1 >= 0)
+ {
+ int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
- /* In case the same realized face is used for bitmap areas and
+ /* 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
FillSolid in x_draw_glyph_string_background. */
if (face->stipple)
- XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
+ XSetFillStyle (display, face->gc, FillOpaqueStippled);
else
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
+ XSetForeground (display, face->gc, face->background);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- face->gc,
- (left
- - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
- + border),
+ XFillRectangle (display, window, face->gc,
+ b1,
WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
row->y)),
- FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
+ b2,
row->visible_height);
if (!face->stipple)
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
+ XSetForeground (display, face->gc, face->foreground);
}
- /* Draw the left bitmap. */
- if (bitmap != NO_BITMAP)
- x_draw_bitmap (w, row, bitmap);
-
- /* Decide which bitmap to draw at the right side. */
- if (row->truncated_on_right_p)
- bitmap = RIGHT_TRUNCATION_BITMAP;
- else if (row->continued_p)
- bitmap = CONTINUED_LINE_BITMAP;
- else
- bitmap = NO_BITMAP;
-
- /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
- the flags area. */
- if (bitmap == NO_BITMAP
- || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
- || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
+ if (which != NO_FRINGE_BITMAP)
{
- int right = window_box_right (w, -1);
-
- if (header_line_height < 0)
- header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-
- /* In case the same realized face is used for bitmap areas and
- for something displayed in the text (e.g. face `region' on
- mono-displays, the fill style may have been changed to
- FillSolid in x_draw_glyph_string_background. */
- if (face->stipple)
- XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
- else
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- face->gc,
- right,
- WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- row->y)),
- FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
- row->visible_height);
- if (!face->stipple)
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
+ /* Draw the bitmap. I believe these small pixmaps can be cached
+ by the server. */
+ pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
+ face->foreground,
+ face->background, depth);
+ XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
+ XFreePixmap (display, pixmap);
}
-
- /* Draw the right bitmap. */
- if (bitmap != NO_BITMAP)
- x_draw_bitmap (w, row, bitmap);
+
+ XSetClipMask (display, gc, None);
}
-\f
-/***********************************************************************
- Line Highlighting
- ***********************************************************************/
-/* External interface to control of standout mode. Not used for X
- frames. Aborts when called. */
+/* Draw fringe bitmaps for glyph row ROW on window W. Call this
+ function with input blocked. */
static void
-XTreassert_line_highlight (new, vpos)
- int new, vpos;
+x_draw_row_fringe_bitmaps (w, row)
+ struct window *w;
+ struct glyph_row *row;
{
- abort ();
-}
+ struct frame *f = XFRAME (w->frame);
+ enum fringe_bitmap_type bitmap;
+
+ xassert (interrupt_input_blocked);
+ /* If row is completely invisible, because of vscrolling, we
+ don't have to draw anything. */
+ if (row->visible_height <= 0)
+ return;
-/* Call this when about to modify line at position VPOS and change
- whether it is highlighted. Not used for X frames. Aborts when
- called. */
+ if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
+ {
+ /* Decide which bitmap to draw in the left fringe. */
+ if (row->overlay_arrow_p)
+ bitmap = OVERLAY_ARROW_BITMAP;
+ else if (row->truncated_on_left_p)
+ bitmap = LEFT_TRUNCATION_BITMAP;
+ else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
+ bitmap = CONTINUATION_LINE_BITMAP;
+ else if (row->indicate_empty_line_p)
+ bitmap = ZV_LINE_BITMAP;
+ else
+ bitmap = NO_FRINGE_BITMAP;
-static void
-x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
- int new_highlight, vpos, y, first_unused_hpos;
-{
- abort ();
+ x_draw_fringe_bitmap (w, row, bitmap, 1);
+ }
+
+ if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
+ {
+ /* Decide which bitmap to draw in the right fringe. */
+ if (row->truncated_on_right_p)
+ bitmap = RIGHT_TRUNCATION_BITMAP;
+ else if (row->continued_p)
+ bitmap = CONTINUED_LINE_BITMAP;
+ else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
+ bitmap = ZV_LINE_BITMAP;
+ else
+ bitmap = NO_FRINGE_BITMAP;
+
+ x_draw_fringe_bitmap (w, row, bitmap, 0);
+ }
}
+\f
/* This is called when starting Emacs and when restarting after
suspend. When starting Emacs, no X window is mapped. And nothing
XChar2b *,
int *));
static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
- int, XChar2b *, int));
+ int, XChar2b *, int,
+ int));
static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
static void x_append_glyph P_ ((struct it *));
/* Get face and two-byte form of character C in face FACE_ID on frame
F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
- means we want to display multibyte text. Value is a pointer to a
- realized face that is ready for display. */
+ means we want to display multibyte text. DISPLAY_P non-zero means
+ make sure that X resources for the face returned are allocated.
+ Value is a pointer to a realized face that is ready for display if
+ DISPLAY_P is non-zero. */
static INLINE struct face *
-x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
+x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
struct frame *f;
int c, face_id;
XChar2b *char2b;
- int multibyte_p;
+ int multibyte_p, display_p;
{
struct face *face = FACE_FROM_ID (f, face_id);
}
/* Make sure X resources of the face are allocated. */
- xassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
+ if (display_p)
+ {
+ xassert (face != NULL);
+ PREPARE_FACE_FOR_DISPLAY (f, face);
+ }
return face;
}
4. `:height HEIGHT' specifies that the height of the stretch produced
should be HEIGHT, measured in canonical character units.
- 5. `:relative-height FACTOR' specifies that the height of the the
+ 5. `:relative-height FACTOR' specifies that the height of the
stretch should be FACTOR times the height of the characters having
the glyph property.
/* Get font to use. Encode IT->char_to_display. */
x_get_char_face_and_encoding (it->f, it->char_to_display,
it->face_id, &char2b,
- it->multibyte_p);
+ it->multibyte_p, 0);
font = face->font;
/* When no suitable font found, use the default font. */
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
x_get_char_face_and_encoding (it->f, it->char_to_display,
- it->face_id, &char2b, it->multibyte_p);
+ it->face_id, &char2b, it->multibyte_p, 0);
font = face->font;
/* When no suitable font found, use the default font. */
face = FACE_FROM_ID (it->f, face_id);
x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
- it->multibyte_p);
+ it->multibyte_p, 0);
font = face->font;
if (font == NULL)
{
enum draw_glyphs_face));
static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
enum glyph_row_area, int, int,
- enum draw_glyphs_face, int *, int *, int));
+ enum draw_glyphs_face, int));
static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
static void x_set_glyph_string_gc P_ ((struct glyph_string *));
static void x_draw_glyph_string_background P_ ((struct glyph_string *,
if (s->face->use_box_color_for_shadows_p)
color = s->face->box_color;
+ else if (s->first_glyph->type == IMAGE_GLYPH
+ && s->img->pixmap
+ && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+ color = IMAGE_BACKGROUND (s->img, s->f, 0);
else
{
XGCValues xgcv;
for (i = 0; i < width; ++i)
XDrawLine (dpy, window, gc,
left_x + i * left_p, bottom_y - i,
- right_x + 2 - i * right_p, bottom_y - i);
+ right_x + 1 - i * right_p, bottom_y - i);
/* Right. */
if (right_p)
if (s->row->full_width_p
&& !s->w->pseudo_window_p)
{
- last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
+ last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
}
|| (s->hl == DRAW_MOUSE_FACE
&& (s->next == NULL
|| s->next->hl != s->hl)));
-
+
x_get_glyph_string_clip_rect (s, &clip_rect);
if (s->face->box == FACE_SIMPLE_BOX)
}
else
{
- unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
- XGCValues xgcv;
XRectangle clip_rect, image_rect, r;
x_get_glyph_string_clip_rect (s, &clip_rect);
the image. I believe it's looking better if we do
nothing here for mouse-face. */
if (s->hl == DRAW_CURSOR)
- XDrawRectangle (s->display, s->window, s->gc, x, y,
- s->img->width - 1, s->img->height - 1);
+ {
+ int r = s->img->relief;
+ if (r < 0) r = -r;
+ XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
+ s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+ }
}
}
else
if (s->hl == DRAW_IMAGE_SUNKEN
|| s->hl == DRAW_IMAGE_RAISED)
{
- thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
+ thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
raised_p = s->hl == DRAW_IMAGE_RAISED;
}
else
the image. I believe it's looking better if we do
nothing here for mouse-face. */
if (s->hl == DRAW_CURSOR)
- XDrawRectangle (s->display, pixmap, s->gc, x, y,
- s->img->width - 1, s->img->height - 1);
+ {
+ int r = s->img->relief;
+ if (r < 0) r = -r;
+ XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
+ s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+ }
}
}
else
/* Set up S->gc, set clipping and draw S. */
x_set_glyph_string_gc (s);
- x_set_glyph_string_clipping (s);
/* Draw relief (if any) in advance for char/composition so that the
glyph string can be drawn over it. */
|| s->first_glyph->type == COMPOSITE_GLYPH))
{
+ x_set_glyph_string_clipping (s);
x_draw_glyph_string_background (s, 1);
x_draw_glyph_string_box (s);
+ x_set_glyph_string_clipping (s);
relief_drawn_p = 1;
}
+ else
+ x_set_glyph_string_clipping (s);
switch (s->first_glyph->type)
{
|| s->face->background != default_face->background
|| s->face->stipple != default_face->stipple
|| s->row->mouse_face_p))
- || s->hl == DRAW_MOUSE_FACE))
+ || s->hl == DRAW_MOUSE_FACE
+ || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
+ && s->row->fill_line_p)))
s->extends_to_end_of_line_p = 1;
/* If S extends its face to the end of the line, set its
int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
x_get_char_face_and_encoding (XFRAME (w->frame), c, \
- this_face_id, char2b + n, 1); \
+ this_face_id, char2b + n, 1, 1); \
} \
\
/* Make glyph_strings for each glyph sequence that is drawable by \
DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
DRAW_IMAGE_RAISED draw an image with a raised relief around it
- If REAL_START is non-null, return in *REAL_START the real starting
- position for display. This can be different from START in case
- overlapping glyphs must be displayed. If REAL_END is non-null,
- return in *REAL_END the real end position for display. This can be
- different from END in case overlapping glyphs must be displayed.
-
If OVERLAPS_P is non-zero, draw only the foreground of characters
and clip to the physical height of ROW.
Value is the x-position reached, relative to AREA of W. */
static int
-x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
- overlaps_p)
+x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
struct window *w;
int x;
struct glyph_row *row;
enum glyph_row_area area;
int start, end;
enum draw_glyphs_face hl;
- int *real_start, *real_end;
int overlaps_p;
{
struct glyph_string *head, *tail;
end = min (end, row->used[area]);
start = max (0, start);
start = min (end, start);
- if (real_start)
- *real_start = start;
- if (real_end)
- *real_end = end;
/* Translate X to frame coordinates. Set last_x to the right
end of the drawing area. */
if (row->full_width_p)
{
/* X is relative to the left edge of W, without scroll bars
- or flag areas. */
+ or fringes. */
struct frame *f = XFRAME (w->frame);
- /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
x += window_left_x;
DRAW_NORMAL_TEXT, dummy_x, last_x,
overlaps_p);
start = i;
- if (real_start)
- *real_start = start;
x_compute_overhangs_and_x (t, head->x, 1);
x_prepend_glyph_string_lists (&head, &tail, h, t);
}
overlaps_p);
for (s = h; s; s = s->next)
s->background_filled_p = 1;
- if (real_start)
- *real_start = i;
x_compute_overhangs_and_x (t, head->x, 1);
x_prepend_glyph_string_lists (&head, &tail, h, t);
}
overlaps_p);
x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
x_append_glyph_string_lists (&head, &tail, h, t);
- if (real_end)
- *real_end = i;
}
/* Append glyph strings for glyphs following the last glyph
s->background_filled_p = 1;
x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
x_append_glyph_string_lists (&head, &tail, h, t);
- if (real_end)
- *real_end = i;
}
}
for (s = head; s; s = s->next)
x_draw_glyph_string (s);
+ if (area == TEXT_AREA
+ && !row->full_width_p
+ /* When drawing overlapping rows, only the glyph strings'
+ foreground is drawn, which doesn't erase a cursor
+ completely. */
+ && !overlaps_p)
+ {
+ int x0 = head ? head->x : x;
+ int x1 = tail ? tail->x + tail->background_width : x;
+
+ x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
+ x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
+
+ if (XFASTINT (w->left_margin_width) != 0)
+ {
+ int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
+ x0 -= left_area_width;
+ x1 -= left_area_width;
+ }
+
+ notice_overwritten_cursor (w, area, x0, x1,
+ row->y, MATRIX_ROW_BOTTOM_Y (row));
+ }
+
/* Value is the x-position up to which drawn, relative to AREA of W.
This doesn't include parts drawn because of overhangs. */
x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
if (!row->full_width_p)
{
- if (area > LEFT_MARGIN_AREA)
+ if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
if (area > TEXT_AREA)
x_reached -= window_box_width (w, TEXT_AREA);
&& row->glyphs[area][i].overlaps_vertically_p);
x_draw_glyphs (w, start_x, row, area, start, i,
- (row->inverse_p
- ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
- NULL, NULL, 1);
+ DRAW_NORMAL_TEXT, 1);
}
else
{
struct glyph *start;
int len;
{
- int x, hpos, real_start, real_end;
+ int x, hpos;
xassert (updated_window && updated_row);
BLOCK_INPUT;
x = x_draw_glyphs (updated_window, output_cursor.x,
updated_row, updated_area,
hpos, hpos + len,
- (updated_row->inverse_p
- ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
- &real_start, &real_end, 0);
+ DRAW_NORMAL_TEXT, 0);
- /* If we drew over the cursor, note that it is not visible any more. */
- notice_overwritten_cursor (updated_window, real_start,
- real_end - real_start);
+ /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
+ if (updated_area == TEXT_AREA
+ && updated_window->phys_cursor_on_p
+ && updated_window->phys_cursor.vpos == output_cursor.vpos
+ && updated_window->phys_cursor.hpos >= hpos
+ && updated_window->phys_cursor.hpos < hpos + len)
+ updated_window->phys_cursor_on_p = 0;
UNBLOCK_INPUT;
int line_height, shift_by_width, shifted_region_width;
struct glyph_row *row;
struct glyph *glyph;
- int frame_x, frame_y, hpos, real_start, real_end;
+ int frame_x, frame_y, hpos;
xassert (updated_window && updated_row);
BLOCK_INPUT;
/* Write the glyphs. */
hpos = start - row->glyphs[updated_area];
x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
- DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
- notice_overwritten_cursor (w, real_start, real_end - real_start);
+ DRAW_NORMAL_TEXT, 0);
/* Advance the output cursor. */
output_cursor.hpos += len;
/* Notice if the cursor will be cleared by this operation. */
if (!updated_row->full_width_p)
- notice_overwritten_cursor (w, output_cursor.hpos, -1);
+ notice_overwritten_cursor (w, updated_area,
+ output_cursor.x, -1,
+ updated_row->y,
+ MATRIX_ROW_BOTTOM_Y (updated_row));
from_x = output_cursor.x;
int x, y, width, height, from_y, to_y, bottom_y;
/* Get frame-relative bounding box of the text display area of W,
- without mode lines. Include in this box the flags areas to the
- left and right of W. */
+ without mode lines. Include in this box the left and right
+ fringe of W. */
window_box (w, -1, &x, &y, &width, &height);
- width += FRAME_X_FLAGS_AREA_WIDTH (f);
- x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
+ width += FRAME_X_FRINGE_WIDTH (f);
+ x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
if (area == TEXT_AREA && row->fill_line_p)
/* If row extends face to end of line write the whole line. */
- x_draw_glyphs (w, 0, row, area,
- 0, row->used[area],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
+ x_draw_glyphs (w, 0, row, area, 0, row->used[area],
+ DRAW_NORMAL_TEXT, 0);
else
{
/* Set START_X to the window-relative start position for drawing glyphs of
x_draw_glyphs (w, first_x - start_x, row, area,
first - row->glyphs[area],
last - row->glyphs[area],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
+ DRAW_NORMAL_TEXT, 0);
}
}
if (row->mode_line_p || w->pseudo_window_p)
x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
+ DRAW_NORMAL_TEXT, 0);
else
{
if (row->used[LEFT_MARGIN_AREA])
expose_area (w, row, r, TEXT_AREA);
if (row->used[RIGHT_MARGIN_AREA])
expose_area (w, row, r, RIGHT_MARGIN_AREA);
- x_draw_row_bitmaps (w, row);
+ x_draw_row_fringe_bitmaps (w, row);
}
return row->mouse_face_p;
}
+/* Redraw those parts of glyphs rows during expose event handling that
+ overlap other rows. Redrawing of an exposed line writes over parts
+ of lines overlapping that exposed line; this function fixes that.
+
+ W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
+ row in W's current matrix that is exposed and overlaps other rows.
+ LAST_OVERLAPPING_ROW is the last such row. */
+
+static void
+expose_overlaps (w, first_overlapping_row, last_overlapping_row)
+ struct window *w;
+ struct glyph_row *first_overlapping_row;
+ struct glyph_row *last_overlapping_row;
+{
+ struct glyph_row *row;
+
+ for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
+ if (row->overlapping_p)
+ {
+ xassert (row->enabled_p && !row->mode_line_p);
+
+ if (row->used[LEFT_MARGIN_AREA])
+ x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
+
+ if (row->used[TEXT_AREA])
+ x_fix_overlapping_area (w, row, TEXT_AREA);
+
+ if (row->used[RIGHT_MARGIN_AREA])
+ x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
+ }
+}
+
+
/* Redraw the part of window W intersection rectangle FR. Pixel
coordinates in FR are frame-relative. Call this function with
input blocked. Value is non-zero if the exposure overwrites
int yb = window_text_bottom_y (w);
struct glyph_row *row;
int cursor_cleared_p;
+ struct glyph_row *first_overlapping_row, *last_overlapping_row;
TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
r.x, r.y, r.width, r.height));
else
cursor_cleared_p = 0;
- /* Find the first row intersecting the rectangle R. */
+ /* Update lines intersecting rectangle R. */
+ first_overlapping_row = last_overlapping_row = NULL;
for (row = w->current_matrix->rows;
row->enabled_p;
++row)
|| (r.y >= y0 && r.y < y1)
|| (r.y + r.height > y0 && r.y + r.height < y1))
{
+ if (row->overlapping_p)
+ {
+ if (first_overlapping_row == NULL)
+ first_overlapping_row = row;
+ last_overlapping_row = row;
+ }
+
if (expose_line (w, row, &r))
mouse_face_overwritten_p = 1;
}
if (!w->pseudo_window_p)
{
+ /* Fix the display of overlapping rows. */
+ if (first_overlapping_row)
+ expose_overlaps (w, first_overlapping_row, last_overlapping_row);
+
/* Draw border between windows. */
x_draw_vertical_border (w);
x_frame_rehighlight (dpyinfo);
}
+/* Handle FocusIn and FocusOut state changes for FRAME.
+ If FRAME has focus and there exists more than one frame, puts
+ an FOCUS_IN_EVENT into BUFP.
+ Returns number of events inserted into BUFP. */
+
+static int
+x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
+ int type;
+ int state;
+ struct x_display_info *dpyinfo;
+ struct frame *frame;
+ struct input_event *bufp;
+ int numchars;
+{
+ int nr_events = 0;
+
+ if (type == FocusIn)
+ {
+ if (dpyinfo->x_focus_event_frame != frame)
+ {
+ x_new_focus_frame (dpyinfo, frame);
+ dpyinfo->x_focus_event_frame = frame;
+
+ /* Don't stop displaying the initial startup message
+ for a switch-frame event we don't need. */
+ if (numchars > 0
+ && GC_NILP (Vterminal_frame)
+ && GC_CONSP (Vframe_list)
+ && !GC_NILP (XCDR (Vframe_list)))
+ {
+ bufp->kind = FOCUS_IN_EVENT;
+ XSETFRAME (bufp->frame_or_window, frame);
+ bufp->arg = Qnil;
+ ++bufp;
+ numchars--;
+ ++nr_events;
+ }
+ }
+
+ frame->output_data.x->focus_state |= state;
+
+#ifdef HAVE_X_I18N
+ if (FRAME_XIC (frame))
+ XSetICFocus (FRAME_XIC (frame));
+#endif
+ }
+ else if (type == FocusOut)
+ {
+ frame->output_data.x->focus_state &= ~state;
+
+ if (dpyinfo->x_focus_event_frame == frame)
+ {
+ dpyinfo->x_focus_event_frame = 0;
+ x_new_focus_frame (dpyinfo, 0);
+ }
+
+#ifdef HAVE_X_I18N
+ if (FRAME_XIC (frame))
+ XUnsetICFocus (FRAME_XIC (frame));
+#endif
+ }
+
+ return nr_events;
+}
+
+/* The focus may have changed. Figure out if it is a real focus change,
+ by checking both FocusIn/Out and Enter/LeaveNotify events.
+
+ Returns number of events inserted into BUFP. */
+
+static int
+x_detect_focus_change (dpyinfo, event, bufp, numchars)
+ struct x_display_info *dpyinfo;
+ XEvent *event;
+ struct input_event *bufp;
+ int numchars;
+{
+ struct frame *frame;
+ int nr_events = 0;
+
+ frame = x_top_window_to_frame (dpyinfo, event->xany.window);
+ if (! frame) return nr_events;
+
+ switch (event->type)
+ {
+ case EnterNotify:
+ case LeaveNotify:
+ if (event->xcrossing.detail != NotifyInferior
+ && event->xcrossing.focus
+ && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
+ nr_events = x_focus_changed ((event->type == EnterNotify
+ ? FocusIn : FocusOut),
+ FOCUS_IMPLICIT,
+ dpyinfo,
+ frame,
+ bufp,
+ numchars);
+ break;
+
+ case FocusIn:
+ case FocusOut:
+ nr_events = x_focus_changed (event->type,
+ (event->xfocus.detail == NotifyPointer
+ ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+ dpyinfo,
+ frame,
+ bufp,
+ numchars);
+ break;
+ }
+
+ return nr_events;
+}
+
+
/* Handle an event saying the mouse has moved out of an Emacs frame. */
void
struct x_display_info *dpyinfo;
unsigned int state;
{
+ EMACS_UINT mod_meta = meta_modifier;
+ EMACS_UINT mod_alt = alt_modifier;
+ EMACS_UINT mod_hyper = hyper_modifier;
+ EMACS_UINT mod_super = super_modifier;
+ Lisp_Object tem;
+
+ tem = Fget (Vx_alt_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
+ tem = Fget (Vx_meta_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
+ tem = Fget (Vx_hyper_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
+ tem = Fget (Vx_super_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
+
+
return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
- | ((state & ControlMask) ? ctrl_modifier : 0)
- | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
- | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
- | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
- | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
+ | ((state & ControlMask) ? ctrl_modifier : 0)
+ | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
+ | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
+ | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
+ | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
}
static unsigned int
struct x_display_info *dpyinfo;
unsigned int state;
{
- return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
- | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
- | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
- | ((state & shift_modifier) ? ShiftMask : 0)
- | ((state & ctrl_modifier) ? ControlMask : 0)
- | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
+ EMACS_UINT mod_meta = meta_modifier;
+ EMACS_UINT mod_alt = alt_modifier;
+ EMACS_UINT mod_hyper = hyper_modifier;
+ EMACS_UINT mod_super = super_modifier;
+
+ Lisp_Object tem;
+
+ tem = Fget (Vx_alt_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
+ tem = Fget (Vx_meta_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
+ tem = Fget (Vx_hyper_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
+ tem = Fget (Vx_super_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
+
+
+ return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
+ | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
+ | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
+ | ((state & shift_modifier) ? ShiftMask : 0)
+ | ((state & ctrl_modifier) ? ControlMask : 0)
+ | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
}
/* Convert a keysym to its name. */
XButtonEvent *event;
struct frame *f;
{
- /* Make the event type no_event; we'll change that when we decide
+ /* Make the event type NO_EVENT; we'll change that when we decide
otherwise. */
- result->kind = mouse_click;
+ result->kind = MOUSE_CLICK_EVENT;
result->code = event->button - Button1;
result->timestamp = event->time;
result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
}
}
-/* This is used for debugging, to turn off note_mouse_highlight. */
-
- int disable_mouse_highlight;
-
-
\f
/************************************************************************
Mouse Face
}
-/* Take proper action when mouse has moved to the mode or header line of
- window W, x-position X. MODE_LINE_P non-zero means mouse is on the
- mode line. X is relative to the start of the text display area of
- W, so the width of bitmap areas and scroll bars must be subtracted
- to get a position relative to the start of the mode line. */
-
+/* Take proper action when mouse has moved to the mode or header line
+ or marginal area of window W, x-position X and y-position Y. Area
+ is 1, 3, 6 or 7 for the mode line, header line, left and right
+ marginal area respectively. X is relative to the start of the text
+ display area of W, so the width of bitmap areas and scroll bars
+ must be subtracted to get a position relative to the start of the
+ mode line. */
+
static void
-note_mode_line_highlight (w, x, mode_line_p)
+note_mode_line_or_margin_highlight (w, x, y, portion)
struct window *w;
- int x, mode_line_p;
+ int x, y, portion;
{
struct frame *f = XFRAME (w->frame);
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
- struct glyph_row *row;
+ int charpos;
+ Lisp_Object string, help, map, pos;
- if (mode_line_p)
- row = MATRIX_MODE_LINE_ROW (w->current_matrix);
- else
- row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
+ if (portion == 1 || portion == 3)
+ string = mode_line_string (w, x, y, portion == 1, &charpos);
+ else
+ string = marginal_area_string (w, x, y, portion, &charpos);
- if (row->enabled_p)
+ if (STRINGP (string))
{
- struct glyph *glyph, *end;
- Lisp_Object help, map;
- int x0;
-
- /* Find the glyph under X. */
- glyph = row->glyphs[TEXT_AREA];
- end = glyph + row->used[TEXT_AREA];
- x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
- + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
+ pos = make_number (charpos);
- while (glyph < end
- && x >= x0 + glyph->pixel_width)
+ /* If we're on a string with `help-echo' text property, arrange
+ for the help to be displayed. This is done by setting the
+ global variable help_echo to the help string. */
+ help = Fget_text_property (pos, Qhelp_echo, string);
+ if (!NILP (help))
{
- x0 += glyph->pixel_width;
- ++glyph;
+ help_echo = help;
+ XSETWINDOW (help_echo_window, w);
+ help_echo_object = string;
+ help_echo_pos = charpos;
}
- if (glyph < end
- && STRINGP (glyph->object)
- && XSTRING (glyph->object)->intervals
- && glyph->charpos >= 0
- && glyph->charpos < XSTRING (glyph->object)->size)
- {
- /* If we're on a string with `help-echo' text property,
- arrange for the help to be displayed. This is done by
- setting the global variable help_echo to the help string. */
- help = Fget_text_property (make_number (glyph->charpos),
- Qhelp_echo, glyph->object);
- if (!NILP (help))
- {
- help_echo = help;
- XSETWINDOW (help_echo_window, w);
- help_echo_object = glyph->object;
- help_echo_pos = glyph->charpos;
- }
-
- /* Change the mouse pointer according to what is under X/Y. */
- map = Fget_text_property (make_number (glyph->charpos),
- Qlocal_map, glyph->object);
- if (KEYMAPP (map))
- cursor = f->output_data.x->nontext_cursor;
- else
- {
- map = Fget_text_property (make_number (glyph->charpos),
- Qkeymap, glyph->object);
- if (KEYMAPP (map))
- cursor = f->output_data.x->nontext_cursor;
- }
- }
+ /* Change the mouse pointer according to what is under X/Y. */
+ map = Fget_text_property (pos, Qlocal_map, string);
+ if (!KEYMAPP (map))
+ map = Fget_text_property (pos, Qkeymap, string);
+ if (KEYMAPP (map))
+ cursor = f->output_data.x->nontext_cursor;
}
-
+
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
}
return;
#endif
- if (disable_mouse_highlight
+ if (NILP (Vmouse_highlight)
|| !f->glyphs_initialized_p)
return;
return;
}
- /* Mouse is on the mode or header line? */
- if (portion == 1 || portion == 3)
+ /* Mouse is on the mode, header line or margin? */
+ if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
{
- note_mode_line_highlight (w, x, portion == 1);
+ note_mode_line_or_margin_highlight (w, x, y, portion);
return;
}
if (NILP (b))
b = make_number (0);
if (NILP (e))
- e = make_number (XSTRING (object)->size - 1);
+ e = make_number (SCHARS (object) - 1);
fast_find_string_pos (w, XINT (b), object,
&dpyinfo->mouse_face_beg_col,
&dpyinfo->mouse_face_beg_row,
{
Lisp_Object before = Foverlay_start (overlay);
Lisp_Object after = Foverlay_end (overlay);
- Lisp_Object ignore;
+ int ignore;
/* Note that we might not be able to find position
BEFORE in the glyph matrix if the overlay is
/* Try text properties. */
if (STRINGP (object)
&& charpos >= 0
- && charpos < XSTRING (object)->size)
+ && charpos < SCHARS (object))
{
help = Fget_text_property (make_number (charpos),
Qhelp_echo, object);
/* Handle mouse button event on the tool-bar of frame F, at
- frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
+ frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
or ButtonRelase. */
static void
set_help_echo:
- /* Set help_echo to a help string.to display for this tool-bar item.
+ /* Set help_echo to a help string to display for this tool-bar item.
XTread_socket does the rest. */
help_echo_object = help_echo_window = Qnil;
help_echo_pos = -1;
int i, past_end = 0;
first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
- row = row_containing_pos (w, charpos, first, NULL);
+ row = row_containing_pos (w, charpos, first, NULL, 0);
if (row == NULL)
{
if (charpos < MATRIX_ROW_START_CHARPOS (first))
#endif /* not 0 */
-/* Find the position of the the glyph for position POS in OBJECT in
- window W's current matrix, and return in *X/*Y the pixel
- coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
+/* Find the position of the glyph for position POS in OBJECT in
+ window W's current matrix, and return in *X, *Y the pixel
+ coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
RIGHT_P non-zero means return the position of the right edge of the
glyph, RIGHT_P zero means return the left edge position.
{
struct window *w = XWINDOW (dpyinfo->mouse_face_window);
struct frame *f = XFRAME (WINDOW_FRAME (w));
- int i;
- int cursor_off_p = 0;
- struct cursor_pos saved_cursor;
-
- saved_cursor = output_cursor;
-
- /* If window is in the process of being destroyed, don't bother
- to do anything. */
- if (w->current_matrix == NULL)
- goto set_x_cursor;
-
- /* Recognize when we are called to operate on rows that don't exist
- anymore. This can happen when a window is split. */
- if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
- goto set_x_cursor;
- set_output_cursor (&w->phys_cursor);
-
- /* Note that mouse_face_beg_row etc. are window relative. */
- for (i = dpyinfo->mouse_face_beg_row;
- i <= dpyinfo->mouse_face_end_row;
- i++)
+ if (/* If window is in the process of being destroyed, don't bother
+ to do anything. */
+ w->current_matrix != NULL
+ /* Don't update mouse highlight if hidden */
+ && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
+ /* Recognize when we are called to operate on rows that don't exist
+ anymore. This can happen when a window is split. */
+ && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
{
- int start_hpos, end_hpos, start_x;
- struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
-
- /* Don't do anything if row doesn't have valid contents. */
- if (!row->enabled_p)
- continue;
+ int phys_cursor_on_p = w->phys_cursor_on_p;
+ struct glyph_row *row, *first, *last;
- /* For all but the first row, the highlight starts at column 0. */
- if (i == dpyinfo->mouse_face_beg_row)
- {
- start_hpos = dpyinfo->mouse_face_beg_col;
- start_x = dpyinfo->mouse_face_beg_x;
- }
- else
+ first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
+ last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+
+ for (row = first; row <= last && row->enabled_p; ++row)
{
- start_hpos = 0;
- start_x = 0;
- }
+ int start_hpos, end_hpos, start_x;
- if (i == dpyinfo->mouse_face_end_row)
- end_hpos = dpyinfo->mouse_face_end_col;
- else
- end_hpos = row->used[TEXT_AREA];
+ /* For all but the first row, the highlight starts at column 0. */
+ if (row == first)
+ {
+ start_hpos = dpyinfo->mouse_face_beg_col;
+ start_x = dpyinfo->mouse_face_beg_x;
+ }
+ else
+ {
+ start_hpos = 0;
+ start_x = 0;
+ }
- /* If the cursor's in the text we are about to rewrite, turn the
- cursor off. */
- if (!w->pseudo_window_p
- && i == output_cursor.vpos
- && output_cursor.hpos >= start_hpos - 1
- && output_cursor.hpos <= end_hpos)
- {
- x_update_window_cursor (w, 0);
- cursor_off_p = 1;
- }
+ if (row == last)
+ end_hpos = dpyinfo->mouse_face_end_col;
+ else
+ end_hpos = row->used[TEXT_AREA];
- if (end_hpos > start_hpos)
- {
- x_draw_glyphs (w, start_x, row, TEXT_AREA,
- start_hpos, end_hpos, draw, NULL, NULL, 0);
- row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
- }
- }
+ if (end_hpos > start_hpos)
+ {
+ x_draw_glyphs (w, start_x, row, TEXT_AREA,
+ start_hpos, end_hpos, draw, 0);
- /* If we turned the cursor off, turn it back on. */
- if (cursor_off_p)
- x_display_cursor (w, 1,
- output_cursor.hpos, output_cursor.vpos,
- output_cursor.x, output_cursor.y);
+ row->mouse_face_p
+ = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
+ }
+ }
- output_cursor = saved_cursor;
+ /* When we've written over the cursor, arrange for it to
+ be displayed again. */
+ if (phys_cursor_on_p && !w->phys_cursor_on_p)
+ x_display_cursor (w, 1,
+ w->phys_cursor.hpos, w->phys_cursor.vpos,
+ w->phys_cursor.x, w->phys_cursor.y);
+ }
- set_x_cursor:
-
/* Change the mouse cursor. */
if (draw == DRAW_NORMAL_TEXT)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
struct window *w = XWINDOW (window);
struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
struct glyph_row *end = r + w->current_matrix->nrows - 1;
- int area;
frame_to_window_pixel_xy (w, &x, &y);
/* Action hook installed via XtAppAddActionHook when toolkit scroll
bars are used.. The hook is responsible for detecting when
the user ends an interaction with the scroll bar, and generates
- a `end-scroll' scroll_bar_click' event if so. */
+ a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
static void
xt_action_hook (widget, client_data, action_name, event, params,
XSETWINDOW (window, w);
f = XFRAME (w->frame);
- ievent->kind = scroll_bar_click;
+ ievent->kind = SCROLL_BAR_CLICK_EVENT;
ievent->frame_or_window = window;
ievent->arg = Qnil;
ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
- CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
+ CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
static void
xm_scroll_callback (widget, client_data, call_data)
XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
UNBLOCK_INPUT;
- /* At the max position of the scroll bar, do a line-wise
- movement. Without doing anything, we would be called with
- the same cs->value again and again. If we want to make
- sure that we can reach the end of the buffer, we have to do
- something.
-
- Implementation note: setting bar->dragging always to
- cs->value gives a smoother movement at the max position.
- Setting it to nil when doing line-wise movement gives
- a better slider behavior. */
-
- if (cs->value + slider_size == XM_SB_MAX
- || (dragging_down_p
- && last_scroll_bar_part == scroll_bar_down_arrow))
- {
- part = scroll_bar_down_arrow;
- bar->dragging = Qnil;
- }
- else
- {
- whole = XM_SB_RANGE;
- portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
- part = scroll_bar_handle;
- bar->dragging = make_number (cs->value);
- }
+ whole = XM_SB_RANGE - slider_size;
+ portion = min (cs->value - XM_SB_MIN, whole);
+ part = scroll_bar_handle;
+ bar->dragging = make_number (cs->value);
}
break;
#endif /* !USE_MOTIF */
- /* Install an action hook that let's us detect when the user
+ /* Install an action hook that lets us detect when the user
finishes interacting with a scroll bar. */
if (action_hook_id == 0)
action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
float top, shown;
- if (whole == 0)
+ BLOCK_INPUT;
+
+#ifdef USE_MOTIF
+
+ /* We use an estimate of 30 chars per line rather than the real
+ `portion' value. This has the disadvantage that the thumb size
+ is not very representative, but it makes our life a lot easier.
+ Otherwise, we have to constantly adjust the thumb size, which
+ we can't always do quickly enough: while dragging, the size of
+ the thumb might prevent the user from dragging the thumb all the
+ way to the end. but Motif and some versions of Xaw3d don't allow
+ updating the thumb size while dragging. Also, even if we can update
+ its size, the update will often happen too late.
+ If you don't believe it, check out revision 1.650 of xterm.c to see
+ what hoops we were going through and the still poor behavior we got. */
+ portion = XFASTINT (XWINDOW (bar->window)->height) * 30;
+ /* When the thumb is at the bottom, position == whole.
+ So we need to increase `whole' to make space for the thumb. */
+ whole += portion;
+
+ if (whole <= 0)
top = 0, shown = 1;
else
{
shown = (float) portion / whole;
}
- BLOCK_INPUT;
-
-#ifdef USE_MOTIF
- {
- int size, value;
-
- /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
- is the scroll bar's maximum and MIN is the scroll bar's minimum
- value. */
- size = shown * XM_SB_RANGE;
- size = min (size, XM_SB_RANGE);
- size = max (size, 1);
+ if (NILP (bar->dragging))
+ {
+ int size, value;
- /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
- value = top * XM_SB_RANGE;
- value = min (value, XM_SB_MAX - size);
- value = max (value, XM_SB_MIN);
+ /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
+ is the scroll bar's maximum and MIN is the scroll bar's minimum
+ value. */
+ size = shown * XM_SB_RANGE;
+ size = min (size, XM_SB_RANGE);
+ size = max (size, 1);
- if (NILP (bar->dragging))
+ /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
+ value = top * XM_SB_RANGE;
+ value = min (value, XM_SB_MAX - size);
+ value = max (value, XM_SB_MIN);
+
XmScrollBarSetValues (widget, value, size, 0, 0, False);
- else if (last_scroll_bar_part == scroll_bar_down_arrow)
- /* This has the negative side effect that the slider value is
- not what it would be if we scrolled here using line-wise or
- page-wise movement. */
- XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
- else
- {
- /* If currently dragging, only update the slider size.
- This reduces flicker effects. */
- int old_value, old_size, increment, page_increment;
-
- XmScrollBarGetValues (widget, &old_value, &old_size,
- &increment, &page_increment);
- XmScrollBarSetValues (widget, old_value,
- min (size, XM_SB_RANGE - old_value),
- 0, 0, False);
- }
- }
+ }
#else /* !USE_MOTIF i.e. use Xaw */
+
+ if (whole == 0)
+ top = 0, shown = 1;
+ else
+ {
+ top = (float) position / whole;
+ shown = (float) portion / whole;
+ }
+
{
float old_top, old_shown;
Dimension height;
/* Create a scroll bar and return the scroll bar vector for it. W is
the Emacs window on which to create the scroll bar. TOP, LEFT,
- WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
+ WIDTH and HEIGHT are the pixel coordinates and dimensions of the
scroll bar. */
static struct scroll_bar *
/* 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. */
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width,
- window_box_height (w), False);
+ if (width > 0 && height > 0)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width,
+ window_box_height (w), False);
window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
/* Position and size of scroll bar. */
/* Does the scroll bar exist yet? */
if (NILP (w->vertical_scroll_bar))
{
- BLOCK_INPUT;
- if (width && height)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height, 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, False);
+ UNBLOCK_INPUT;
+ }
+
bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
}
else
/* Since toolkit scroll bars are smaller than the space reserved
for them on the frame, we have to clear "under" them. */
- if (width && height)
+ if (width > 0 && height > 0)
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
left, top, width, height, False);
}
/* Clear areas not covered by the scroll bar because it's not as
- wide as the area reserved for it . This makes sure a
+ 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 = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
int rest = area_width - sb_width;
- if (rest > 0)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left + area_width - rest, 0,
- rest, max (height, 1), False);
+ if (rest > 0 && height > 0)
+ {
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left + area_width - rest, top,
+ rest, height, False);
+ else
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, rest, height, False);
+ }
}
/* Move/size the scroll bar window. */
}
/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
- is set to something other than no_event, it is enqueued.
+ is set to something other than NO_EVENT, it is enqueued.
This may be called from a signal handler, so we have to ignore GC
mark bits. */
if (! GC_WINDOWP (bar->window))
abort ();
- emacs_event->kind = scroll_bar_click;
+ emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
emacs_event->code = event->xbutton.button - Button1;
emacs_event->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
\f
/* The main X event-reading loop - XTread_socket. */
+#if 0
/* Time stamp of enter window event. This is only used by XTread_socket,
but we have to put it out here, since static variables within functions
sometimes don't work. */
static Time enter_timestamp;
+#endif
/* This holds the state XLookupString needs to implement dead keys
and other tricks known as "compose processing". _X Window System_
me that letting the compiler initialize it to zeros will work okay.
This must be defined outside of XTread_socket, for the same reasons
- given for enter_time stamp, above. */
+ given for enter_timestamp, above. */
static XComposeStatus compose_status;
bcopy (&event, f->output_data.x->saved_menu_event, size); \
if (numchars >= 1) \
{ \
- bufp->kind = menu_bar_activate_event; \
+ bufp->kind = MENU_BAR_ACTIVATE_EVENT; \
XSETFRAME (bufp->frame_or_window, f); \
bufp->arg = Qnil; \
bufp++; \
EXPECTED is nonzero if the caller knows input is available. */
-int
+static int
XTread_socket (sd, bufp, numchars, expected)
register int sd;
/* register */ struct input_event *bufp;
++handling_signal;
- /* The input should be decoded if it is from XIM. Currently the
- locale of XIM is the same as that of the system. So, we can use
- Vlocale_coding_system which is initialized properly at Emacs
- startup time. */
- setup_coding_system (Vlocale_coding_system, &coding);
- coding.src_multibyte = 0;
- coding.dst_multibyte = 1;
- /* The input is converted to events, thus we can't handle
- composition. Anyway, there's no XIM that gives us composition
- information. */
- coding.composing = COMPOSITION_DISABLED;
-
/* Find the display we are supposed to read input for.
It's the one communicating on descriptor SD. */
for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
x_io_error_quitter (dpyinfo->display);
}
+#ifdef HAVE_X_SM
+ BLOCK_INPUT;
+ count += x_session_check_input (bufp, &numchars);
+ UNBLOCK_INPUT;
+#endif
+
while (XPending (dpyinfo->display))
{
XNextEvent (dpyinfo->display, &event);
the session manager, who's looking for such a
PropertyNotify. Can restart processing when
a keyboard or mouse event arrives. */
- if (numchars > 0)
+ /* If we have a session manager, don't set this.
+ KDE will then start two Emacsen, one for the
+ session manager and one for this. */
+ if (numchars > 0
+#ifdef HAVE_X_SM
+ && ! x_session_have_connection ()
+#endif
+ )
{
f = x_top_window_to_frame (dpyinfo,
event.xclient.window);
-
/* This is just so we only give real data once
for a single Emacs process. */
if (f == SELECTED_FRAME ())
if (numchars == 0)
abort ();
- bufp->kind = delete_window_event;
+ bufp->kind = DELETE_WINDOW_EVENT;
XSETFRAME (bufp->frame_or_window, f);
bufp->arg = Qnil;
bufp++;
if (numchars == 0)
abort ();
- bufp->kind = selection_clear_event;
+ bufp->kind = SELECTION_CLEAR_EVENT;
SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
SELECTION_EVENT_TIME (bufp) = eventp->time;
if (numchars == 0)
abort ();
- bufp->kind = selection_request_event;
+ bufp->kind = SELECTION_REQUEST_EVENT;
SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
f = x_window_to_frame (dpyinfo, event.xexpose.window);
if (f)
{
+ x_check_fullscreen (f);
+
if (f->async_visible == 0)
{
f->async_visible = 1;
break;
case GraphicsExpose: /* This occurs when an XCopyArea's
- source area was obscured or not
- available.*/
+ source area was obscured or not
+ available. */
f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
if (f)
{
case NoExpose: /* This occurs when an XCopyArea's
source area was completely
- available */
+ available. */
break;
case UnmapNotify:
f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
if (f) /* F may no longer exist if
- the frame was deleted. */
+ the frame was deleted. */
{
/* While a frame is unmapped, display generation is
disabled; you don't want to spend time updating a
{
f->async_iconified = 1;
- bufp->kind = iconify_event;
+ bufp->kind = ICONIFY_EVENT;
XSETFRAME (bufp->frame_or_window, f);
bufp->arg = Qnil;
bufp++;
if (f->iconified)
{
- bufp->kind = deiconify_event;
+ bufp->kind = DEICONIFY_EVENT;
XSETFRAME (bufp->frame_or_window, f);
bufp->arg = Qnil;
bufp++;
goto OTHER;
case KeyPress:
+
+ /* Dispatch KeyPress events when in menu. */
+ if (popup_activated_flag)
+ goto OTHER;
+
f = x_any_window_to_frame (dpyinfo, event.xkey.window);
+ if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+ {
+ dpyinfo->mouse_face_hidden = 1;
+ clear_mouse_face (dpyinfo);
+ }
+
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
if (f == 0)
{
status_return even if the input is too long to
fit in 81 bytes. So, we must prepare sufficient
bytes for copy_buffer. 513 bytes (256 chars for
- two-byte character set) seems to be a faily good
+ two-byte character set) seems to be a fairly good
approximation. -- 2000.8.10 handa@etl.go.jp */
unsigned char copy_buffer[513];
unsigned char *copy_bufptr = copy_buffer;
int copy_bufsiz = sizeof (copy_buffer);
int modifiers;
+ Lisp_Object coding_system = Qlatin_1;
event.xkey.state
|= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
{
Status status_return;
+ coding_system = Vlocale_coding_system;
nbytes = XmbLookupString (FRAME_XIC (f),
&event.xkey, copy_bufptr,
copy_bufsiz, &keysym,
copy_bufsiz, &keysym,
&status_return);
}
+/* Xutf8LookupString is a new but already deprecated interface. -stef */
+#if 0 && defined X_HAVE_UTF8_STRING
+ else if (status_return == XLookupKeySym)
+ { /* Try again but with utf-8. */
+ coding_system = Qutf_8;
+ nbytes = Xutf8LookupString (FRAME_XIC (f),
+ &event.xkey, copy_bufptr,
+ copy_bufsiz, &keysym,
+ &status_return);
+ if (status_return == XBufferOverflow)
+ {
+ copy_bufsiz = nbytes + 1;
+ copy_bufptr = (char *) alloca (copy_bufsiz);
+ nbytes = Xutf8LookupString (FRAME_XIC (f),
+ &event.xkey,
+ copy_bufptr,
+ copy_bufsiz, &keysym,
+ &status_return);
+ }
+ }
+#endif
if (status_return == XLookupNone)
break;
|| ((unsigned)(orig_keysym) == XK_Num_Lock)
#endif
#endif /* not HAVE_X11R5 */
+ /* The symbols from XK_ISO_Lock to
+ XK_ISO_Last_Group_Lock doesn't have real
+ modifiers but should be treated similarly
+ to Mode_switch by Emacs. */
+#if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
+ || ((unsigned)(orig_keysym) >= XK_ISO_Lock
+ && (unsigned)(orig_keysym) <= XK_ISO_Last_Group_Lock)
+#endif
))
{
if (temp_index == sizeof temp_buffer / sizeof (short))
temp_index = 0;
temp_buffer[temp_index++] = keysym;
- bufp->kind = non_ascii_keystroke;
+ bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
bufp->code = keysym;
XSETFRAME (bufp->frame_or_window, f);
bufp->arg = Qnil;
register int c;
int nchars, len;
+ /* The input should be decoded with `coding_system'
+ 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;
+ /* The input is converted to events, thus we can't
+ handle composition. Anyway, there's no XIM that
+ gives us composition information. */
+ coding.composing = COMPOSITION_DISABLED;
+
for (i = 0; i < nbytes; i++)
{
if (temp_index == (sizeof temp_buffer
temp_buffer[temp_index++] = copy_bufptr[i];
}
- if (/* If the event is not from XIM, */
- event.xkey.keycode != 0
- /* or the current locale doesn't request
- decoding of the intup data, ... */
- || coding.type == coding_type_raw_text
- || coding.type == coding_type_no_conversion)
- {
- /* ... we can use the input data as is. */
- nchars = nbytes;
- }
- else
- {
- /* We have to decode the input data. */
- int require;
- unsigned char *p;
-
- require = decoding_buffer_size (&coding, nbytes);
- p = (unsigned char *) alloca (require);
- coding.mode |= CODING_MODE_LAST_BLOCK;
- decode_coding (&coding, copy_bufptr, p,
- nbytes, require);
- nbytes = coding.produced;
- nchars = coding.produced_char;
- copy_bufptr = p;
- }
+ {
+ /* Decode the input data. */
+ int require;
+ unsigned char *p;
+
+ require = decoding_buffer_size (&coding, nbytes);
+ p = (unsigned char *) alloca (require);
+ coding.mode |= CODING_MODE_LAST_BLOCK;
+ /* We explicitely disable composition
+ handling because key data should
+ not contain any composition
+ sequence. */
+ coding.composing = COMPOSITION_DISABLED;
+ decode_coding (&coding, copy_bufptr, p,
+ nbytes, require);
+ nbytes = coding.produced;
+ nchars = coding.produced_char;
+ copy_bufptr = p;
+ }
/* Convert the input data to a sequence of
character events. */
for (i = 0; i < nbytes; i += len)
{
- c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
- nbytes - i, len);
+ if (nchars == nbytes)
+ c = copy_bufptr[i], len = 1;
+ else
+ c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+ nbytes - i, len);
+
bufp->kind = (SINGLE_BYTE_CHAR_P (c)
- ? ascii_keystroke
- : multibyte_char_keystroke);
+ ? ASCII_KEYSTROKE_EVENT
+ : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
bufp->code = c;
XSETFRAME (bufp->frame_or_window, f);
bufp->arg = Qnil;
goto OTHER;
#endif
- /* Here's a possible interpretation of the whole
- FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
- you get a FocusIn event, you have to get a FocusOut
- event before you relinquish the focus. If you
- haven't received a FocusIn event, then a mere
- LeaveNotify is enough to free you. */
-
case EnterNotify:
{
+ int n;
+
+ n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+ if (n > 0)
+ {
+ bufp += n, count += n, numchars -= n;
+ }
+
f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
+#if 0
if (event.xcrossing.focus)
{
/* Avoid nasty pop/raise loops. */
}
else if (f == dpyinfo->x_focus_frame)
x_new_focus_frame (dpyinfo, 0);
-
+#endif
+
/* EnterNotify counts as mouse movement,
so update things that depend on mouse position. */
if (f && !f->output_data.x->hourglass_p)
}
case FocusIn:
- f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
- if (event.xfocus.detail != NotifyPointer)
- dpyinfo->x_focus_event_frame = f;
- if (f)
- {
- x_new_focus_frame (dpyinfo, f);
+ {
+ int n;
- /* Don't stop displaying the initial startup message
- for a switch-frame event we don't need. */
- if (GC_NILP (Vterminal_frame)
- && GC_CONSP (Vframe_list)
- && !GC_NILP (XCDR (Vframe_list)))
- {
- bufp->kind = FOCUS_IN_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- ++bufp, ++count, --numchars;
- }
- }
-
-#ifdef HAVE_X_I18N
- if (f && FRAME_XIC (f))
- XSetICFocus (FRAME_XIC (f));
-#endif
+ n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+ if (n > 0)
+ {
+ bufp += n, count += n, numchars -= n;
+ }
+ }
goto OTHER;
case LeaveNotify:
+ {
+ int n;
+
+ n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+ if (n > 0)
+ {
+ bufp += n, count += n, numchars -= n;
+ }
+ }
+
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
if (f)
{
bufp += n, count += n, numchars -= n;
}
- if (event.xcrossing.focus)
- x_mouse_leave (dpyinfo);
- else
- {
- if (f == dpyinfo->x_focus_event_frame)
- dpyinfo->x_focus_event_frame = 0;
- if (f == dpyinfo->x_focus_frame)
- x_new_focus_frame (dpyinfo, 0);
- }
}
goto OTHER;
case FocusOut:
- f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
- if (event.xfocus.detail != NotifyPointer
- && f == dpyinfo->x_focus_event_frame)
- dpyinfo->x_focus_event_frame = 0;
- if (f && f == dpyinfo->x_focus_frame)
- x_new_focus_frame (dpyinfo, 0);
+ {
+ int n;
-#ifdef HAVE_X_I18N
- if (f && FRAME_XIC (f))
- XUnsetICFocus (FRAME_XIC (f));
-#endif
+ n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+ if (n > 0)
+ {
+ bufp += n, count += n, numchars -= n;
+ }
+ }
goto OTHER;
else
f = x_window_to_frame (dpyinfo, event.xmotion.window);
+ if (dpyinfo->mouse_face_hidden)
+ {
+ dpyinfo->mouse_face_hidden = 0;
+ clear_mouse_face (dpyinfo);
+ }
+
if (f)
- note_mouse_movement (f, &event.xmotion);
+ {
+
+ /* Generate SELECT_WINDOW_EVENTs when needed. */
+ if (mouse_autoselect_window)
+ {
+ Lisp_Object window;
+ int area;
+
+ window = window_from_coordinates (f,
+ event.xmotion.x, event.xmotion.y,
+ &area, 0);
+
+ /* Window will be selected only when it is not selected now and
+ last mouse movement event was not in it. Minibuffer window
+ will be selected iff it is active. */
+ if (WINDOWP(window)
+ && !EQ (window, last_window)
+ && !EQ (window, selected_window)
+ && numchars > 0)
+ {
+ bufp->kind = SELECT_WINDOW_EVENT;
+ bufp->frame_or_window = window;
+ bufp->arg = Qnil;
+ ++bufp, ++count, --numchars;
+ }
+
+ last_window=window;
+ }
+ note_mouse_movement (f, &event.xmotion);
+ }
else
{
#ifndef USE_TOOLKIT_SCROLL_BARS
if (f)
{
#ifndef USE_X_TOOLKIT
+ /* If there is a pending resize for fullscreen, don't
+ do this one, the right one will come later.
+ The toolkit version doesn't seem to need this, but we
+ need to reset it below. */
+ int dont_resize =
+ ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+ && FRAME_NEW_WIDTH (f) != 0);
int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
+ if (dont_resize)
+ goto OTHER;
/* In the toolkit version, change_frame_size
is called by the code that handles resizing
x_real_positions (f, &f->output_data.x->left_pos,
&f->output_data.x->top_pos);
+ x_check_fullscreen_move(f);
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+ f->output_data.x->want_fullscreen &=
+ ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
#ifdef HAVE_X_I18N
if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
xic_set_statusarea (f);
struct input_event emacs_event;
int tool_bar_p = 0;
- emacs_event.kind = no_event;
+ emacs_event.kind = NO_EVENT;
bzero (&compose_status, sizeof (compose_status));
if (dpyinfo->grabbed
dpyinfo->grabbed &= ~(1 << event.xbutton.button);
}
- if (numchars >= 1 && emacs_event.kind != no_event)
+ if (numchars >= 1 && emacs_event.kind != NO_EVENT)
{
bcopy (&emacs_event, bufp, sizeof (struct input_event));
bufp++;
Text Cursor
***********************************************************************/
-/* Notice if the text cursor of window W has been overwritten by a
- drawing operation that outputs N glyphs starting at HPOS in the
- line given by output_cursor.vpos.
-
- N < 0 means all the rest of the line after HPOS has been
- written. */
+/* Notice when the text cursor of window W has been completely
+ overwritten by a drawing operation that outputs glyphs in AREA
+ starting at X0 and ending at X1 in the line starting at Y0 and
+ ending at Y1. X coordinates are area-relative. X1 < 0 means all
+ the rest of the line after X0 has been written. Y coordinates
+ are window-relative. */
static void
-notice_overwritten_cursor (w, hpos, n)
+notice_overwritten_cursor (w, area, x0, x1, y0, y1)
struct window *w;
- int hpos, n;
+ enum glyph_row_area area;
+ int x0, y0, x1, y1;
{
- if (updated_area == TEXT_AREA
- && output_cursor.vpos == w->phys_cursor.vpos
- && output_cursor.x <= w->phys_cursor.x
- && w->phys_cursor_on_p)
+ if (area == TEXT_AREA && w->phys_cursor_on_p)
{
- if (n < 0)
- w->phys_cursor_on_p = 0;
- else
- {
- /* It depends on the width of the N glyphs written at HPOS
- if the cursor has been overwritten or not. */
- struct glyph *glyph = &updated_row->glyphs[TEXT_AREA][hpos];
- struct glyph *end = glyph + n;
- int width = 0;
+ int cx0 = w->phys_cursor.x;
+ int cx1 = cx0 + w->phys_cursor_width;
+ int cy0 = w->phys_cursor.y;
+ int cy1 = cy0 + w->phys_cursor_height;
- for (; glyph < end; ++glyph)
- width += glyph->pixel_width;
-
- if (output_cursor.x + width > w->phys_cursor.x)
+ if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
+ {
+ /* The cursor image will be completely removed from the
+ screen if the output area intersects the cursor area in
+ y-direction. When we draw in [y0 y1[, and some part of
+ the cursor is at y < y0, that part must have been drawn
+ before. When scrolling, the cursor is erased before
+ actually scrolling, so we don't come here. When not
+ scrolling, the rows above the old cursor row must have
+ changed, and in this case these rows must have written
+ over the cursor image.
+
+ Likewise if part of the cursor is below y1, with the
+ exception of the cursor being in the first blank row at
+ the buffer and window end because update_text_area
+ doesn't draw that row. (Except when it does, but
+ that's handled in update_text_area.) */
+
+ if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
+ && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
w->phys_cursor_on_p = 0;
}
}
the rectangle to the left and increase its width. */
if (whole_line_p)
{
- clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
- clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
+ clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
+ clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
}
XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
if (cursor_glyph->type == STRETCH_GLYPH
&& !x_stretch_cursor_p)
wd = min (CANON_X_UNIT (f), wd);
+ w->phys_cursor_width = wd;
/* The foreground of cursor_gc is typically the same as the normal
background color, which can cause the cursor box to be invisible. */
--gerd. */
static void
-x_draw_bar_cursor (w, row, width)
+x_draw_bar_cursor (w, row, width, kind)
struct window *w;
struct glyph_row *row;
int width;
+ enum text_cursor_kinds kind;
{
struct frame *f = XFRAME (w->frame);
struct glyph *cursor_glyph;
- GC gc;
- int x;
- unsigned long mask;
- XGCValues xgcv;
- Display *dpy;
- Window window;
/* If cursor is out of bounds, don't draw garbage. This can happen
in mini-buffer windows when switching between echo area glyphs
}
else
{
- xgcv.background = f->output_data.x->cursor_pixel;
- xgcv.foreground = f->output_data.x->cursor_pixel;
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Window window = FRAME_X_WINDOW (f);
+ GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
+ unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
+ struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
+ XGCValues xgcv;
+
+ /* If the glyph's background equals the color we normally draw
+ the bar cursor in, the bar cursor in its normal color is
+ invisible. Use the glyph's foreground color instead in this
+ case, on the assumption that the glyph's colors are chosen so
+ that the glyph is legible. */
+ if (face->background == f->output_data.x->cursor_pixel)
+ xgcv.background = xgcv.foreground = face->foreground;
+ else
+ xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
xgcv.graphics_exposures = 0;
- mask = GCForeground | GCBackground | GCGraphicsExposures;
- dpy = FRAME_X_DISPLAY (f);
- window = FRAME_X_WINDOW (f);
- gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
if (gc)
XChangeGC (dpy, gc, mask, &xgcv);
if (width < 0)
width = f->output_data.x->cursor_width;
+ width = min (cursor_glyph->pixel_width, width);
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+ w->phys_cursor_width = width;
x_clip_to_row (w, row, gc, 0);
- XFillRectangle (dpy, window, gc,
- x,
- WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
- min (cursor_glyph->pixel_width, width),
- row->height);
+
+ if (kind == BAR_CURSOR)
+ XFillRectangle (dpy, window, gc,
+ WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+ WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+ width, row->height);
+ else
+ XFillRectangle (dpy, window, gc,
+ WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+ WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+ row->height - width),
+ cursor_glyph->pixel_width,
+ width);
+
XSetClipMask (dpy, gc, None);
}
}
glyphs and mini-buffer. */
if (w->phys_cursor.hpos < row->used[TEXT_AREA])
{
- x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
- w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
- hl, 0, 0, 0);
+ int on_p = w->phys_cursor_on_p;
+ int x1;
+
+ x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
+ w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
+ hl, 0);
+ w->phys_cursor_on_p = on_p;
+
+ if (hl == DRAW_CURSOR)
+ w->phys_cursor_width = x1 - w->phys_cursor.x;
/* When we erase the cursor, and ROW is overlapped by other
rows, make sure that these overlapping parts of other rows
are redrawn. */
- if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
+ else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
{
if (row > w->current_matrix->rows
&& MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
if (!cursor_row->enabled_p)
goto mark_cursor_off;
+ /* If row is completely invisible, don't attempt to delete a cursor which
+ isn't there. This can happen if cursor is at top of a window, and
+ we switch to a buffer with a header line in that window. */
+ if (cursor_row->visible_height <= 0)
+ goto mark_cursor_off;
+
/* This can happen when the new row is shorter than the old one.
In this case, either x_draw_glyphs or clear_end_of_line
should have cleared the cursor. Note that we wouldn't be
/* Erase the cursor by redrawing the character underneath it. */
if (mouse_face_here_p)
hl = DRAW_MOUSE_FACE;
- else if (cursor_row->inverse_p)
- hl = DRAW_INVERSE_VIDEO;
else
hl = DRAW_NORMAL_TEXT;
x_draw_phys_cursor_glyph (w, cursor_row, hl);
struct frame *f = XFRAME (w->frame);
int new_cursor_type;
int new_cursor_width;
+ int cursor_off_state = 0;
struct glyph_matrix *current_glyphs;
struct glyph_row *glyph_row;
struct glyph *glyph;
marked off, draw no cursor. In all other cases, we want a hollow
box cursor. */
new_cursor_width = -1;
+ new_cursor_type = -2;
+
+ /* Echo area */
if (cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f)
&& EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
{
if (w == XWINDOW (echo_area_window))
new_cursor_type = FRAME_DESIRED_CURSOR (f);
+ else if (NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+ w->buffer)))
+ new_cursor_type = NO_CURSOR;
else
- new_cursor_type = HOLLOW_BOX_CURSOR;
+ cursor_off_state = 1;
}
- else
+
+ /* Nonselected window or nonselected frame. */
+ else if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
+ || w != XWINDOW (f->selected_window))
{
- if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
- || w != XWINDOW (f->selected_window))
- {
- extern int cursor_in_non_selected_windows;
-
- if (MINI_WINDOW_P (w)
- || !cursor_in_non_selected_windows
- || NILP (XBUFFER (w->buffer)->cursor_type))
- new_cursor_type = NO_CURSOR;
- else
- new_cursor_type = HOLLOW_BOX_CURSOR;
- }
- else if (w->cursor_off_p)
+ if ((MINI_WINDOW_P (w) && minibuf_level == 0)
+ || NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+ w->buffer))
+ || NILP (XBUFFER (w->buffer)->cursor_type))
new_cursor_type = NO_CURSOR;
else
- {
- struct buffer *b = XBUFFER (w->buffer);
+ cursor_off_state = 1;
+ }
- if (EQ (b->cursor_type, Qt))
- new_cursor_type = FRAME_DESIRED_CURSOR (f);
- else
- new_cursor_type = x_specified_cursor_type (b->cursor_type,
- &new_cursor_width);
+ /* If new_cursor_type isn't decided yet, decide it now. */
+ if (new_cursor_type == -2)
+ {
+ struct buffer *b = XBUFFER (w->buffer);
+
+ if (EQ (b->cursor_type, Qt))
+ {
+ new_cursor_type = FRAME_DESIRED_CURSOR (f);
+ new_cursor_width = FRAME_CURSOR_WIDTH (f);
}
+ else
+ new_cursor_type = x_specified_cursor_type (b->cursor_type,
+ &new_cursor_width);
}
+ /* Dim out or hollow out the cursor,
+ if it has blinked off or for nonselected windows. */
+ if (w->cursor_off_p || cursor_off_state)
+ {
+ if (new_cursor_type == FILLED_BOX_CURSOR)
+ new_cursor_type = HOLLOW_BOX_CURSOR;
+ else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
+ new_cursor_width = 1;
+ else
+ new_cursor_type = NO_CURSOR;
+ }
+
+ /* Now new_cursor_type is correct. */
+
/* If cursor is currently being shown and we don't want it to be or
it is in the wrong place, or the cursor type is not what we want,
erase it. */
&& (!on
|| w->phys_cursor.x != x
|| w->phys_cursor.y != y
- || new_cursor_type != w->phys_cursor_type))
+ || new_cursor_type != w->phys_cursor_type
+ || (new_cursor_type == BAR_CURSOR
+ && new_cursor_width != w->phys_cursor_width)))
x_erase_phys_cursor (w);
- /* If the cursor is now invisible and we want it to be visible,
- display it. */
- if (on && !w->phys_cursor_on_p)
+ /* Don't check phys_cursor_on_p here because that flag is only set
+ to zero in some cases where we know that the cursor has been
+ completely erased, to avoid the extra work of erasing the cursor
+ twice. In other words, phys_cursor_on_p can be 1 and the cursor
+ still not be visible, or it has only been partly erased. */
+ if (on)
{
w->phys_cursor_ascent = glyph_row->ascent;
w->phys_cursor_height = glyph_row->height;
break;
case BAR_CURSOR:
- x_draw_bar_cursor (w, glyph_row, new_cursor_width);
+ x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
+ break;
+
+ case HBAR_CURSOR:
+ x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
break;
case NO_CURSOR:
+ w->phys_cursor_width = 0;
break;
default:
XErrorEvent *error;
{
XGetErrorText (display, error->error_code,
- XSTRING (x_error_message_string)->data,
+ SDATA (x_error_message_string),
X_ERROR_MESSAGE_SIZE);
}
x_catch_errors (dpy)
Display *dpy;
{
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
/* Make sure any errors from previous requests have been dealt with. */
XSync (dpy, False);
record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
- XSTRING (x_error_message_string)->data[0] = 0;
+ SSET (x_error_message_string, 0, 0);
return count;
}
/* Make sure to catch any errors incurred so far. */
XSync (dpy, False);
- if (XSTRING (x_error_message_string)->data[0])
- error (format, XSTRING (x_error_message_string)->data);
+ if (SREF (x_error_message_string, 0))
+ error (format, SDATA (x_error_message_string));
}
/* Nonzero if we had any X protocol errors
/* Make sure to catch any errors incurred so far. */
XSync (dpy, False);
- return XSTRING (x_error_message_string)->data[0] != 0;
+ return SREF (x_error_message_string, 0) != 0;
}
/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
x_clear_errors (dpy)
Display *dpy;
{
- XSTRING (x_error_message_string)->data[0] = 0;
+ SSET (x_error_message_string, 0, 0);
}
/* Stop catching X protocol errors and let them make Emacs die.
static char *error_msg;
-/* Function installed as fatal_error_signal_hook.in
+/* Function installed as fatal_error_signal_hook in
x_connection_closed. Print the X error message, and exit normally,
instead of dumping core when XtCloseDisplay fails. */
f->output_data.x->font = (XFontStruct *) (fontp->font);
f->output_data.x->baseline_offset = fontp->baseline_offset;
f->output_data.x->fontset = -1;
-
+
+ x_compute_fringe_widths (f, 1);
+
/* Compute the scroll bar width in character columns. */
if (f->scroll_bar_pixel_width > 0)
{
to do. */
return fontset_name (fontset);
- result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
+ result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
if (!STRINGP (result))
/* Can't load ASCII font. */
#ifdef HAVE_X_I18N
if (FRAME_XIC (f)
&& (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
- xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
+ xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
#endif
return build_string (fontsetname);
}
+/* Compute actual fringe widths */
+
+void
+x_compute_fringe_widths (f, redraw)
+ struct frame *f;
+ int redraw;
+{
+ int o_left = f->output_data.x->left_fringe_width;
+ int o_right = f->output_data.x->right_fringe_width;
+ int o_cols = f->output_data.x->fringe_cols;
+
+ Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
+ Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
+ int left_fringe_width, right_fringe_width;
+
+ if (!NILP (left_fringe))
+ left_fringe = Fcdr (left_fringe);
+ if (!NILP (right_fringe))
+ right_fringe = Fcdr (right_fringe);
+
+ left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
+ XINT (left_fringe));
+ right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
+ XINT (right_fringe));
+
+ if (left_fringe_width || right_fringe_width)
+ {
+ int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
+ int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
+ int conf_wid = left_wid + right_wid;
+ int font_wid = FONT_WIDTH (f->output_data.x->font);
+ int cols = (left_wid + right_wid + font_wid-1) / font_wid;
+ int real_wid = cols * font_wid;
+ if (left_wid && right_wid)
+ {
+ if (left_fringe_width < 0)
+ {
+ /* Left fringe width is fixed, adjust right fringe if necessary */
+ f->output_data.x->left_fringe_width = left_wid;
+ f->output_data.x->right_fringe_width = real_wid - left_wid;
+ }
+ else if (right_fringe_width < 0)
+ {
+ /* Right fringe width is fixed, adjust left fringe if necessary */
+ f->output_data.x->left_fringe_width = real_wid - right_wid;
+ f->output_data.x->right_fringe_width = right_wid;
+ }
+ else
+ {
+ /* Adjust both fringes with an equal amount.
+ Note that we are doing integer arithmetic here, so don't
+ lose a pixel if the total width is an odd number. */
+ int fill = real_wid - conf_wid;
+ f->output_data.x->left_fringe_width = left_wid + fill/2;
+ f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
+ }
+ }
+ else if (left_fringe_width)
+ {
+ f->output_data.x->left_fringe_width = real_wid;
+ f->output_data.x->right_fringe_width = 0;
+ }
+ else
+ {
+ f->output_data.x->left_fringe_width = 0;
+ f->output_data.x->right_fringe_width = real_wid;
+ }
+ f->output_data.x->fringe_cols = cols;
+ f->output_data.x->fringes_extra = real_wid;
+ }
+ else
+ {
+ f->output_data.x->left_fringe_width = 0;
+ f->output_data.x->right_fringe_width = 0;
+ f->output_data.x->fringe_cols = 0;
+ f->output_data.x->fringes_extra = 0;
+ }
+
+ if (redraw && FRAME_VISIBLE_P (f))
+ if (o_left != f->output_data.x->left_fringe_width ||
+ o_right != f->output_data.x->right_fringe_width ||
+ o_cols != f->output_data.x->fringe_cols)
+ redraw_frame (f);
+}
\f
/***********************************************************************
X Input Methods
UNBLOCK_INPUT;
}
+/* Check if we need to resize the frame due to a fullscreen request.
+ If so needed, resize the frame. */
+static void
+x_check_fullscreen (f)
+ struct frame *f;
+{
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
+ {
+ int width, height, ign;
+
+ x_real_positions (f, &f->output_data.x->left_pos,
+ &f->output_data.x->top_pos);
+
+ x_fullscreen_adjust (f, &width, &height, &ign, &ign);
+
+ /* We do not need to move the window, it shall be taken care of
+ when setting WM manager hints.
+ If the frame is visible already, the position is checked by
+ x_check_fullscreen_move. */
+ if (f->width != width || f->height != height)
+ {
+ change_frame_size (f, height, width, 0, 1, 0);
+ SET_FRAME_GARBAGED (f);
+ cancel_mouse_face (f);
+
+ /* Wait for the change of frame size to occur */
+ f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
+
+ }
+ }
+}
+
+/* If frame parameters are set after the frame is mapped, we need to move
+ the window. This is done in xfns.c.
+ Some window managers moves the window to the right position, some
+ moves the outer window manager window to the specified position.
+ Here we check that we are in the right spot. If not, make a second
+ move, assuming we are dealing with the second kind of window manager. */
+static void
+x_check_fullscreen_move (f)
+ struct frame *f;
+{
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
+ {
+ int expect_top = f->output_data.x->top_pos;
+ int expect_left = f->output_data.x->left_pos;
+
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
+ expect_top = 0;
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
+ expect_left = 0;
+
+ if (expect_top != f->output_data.x->top_pos
+ || expect_left != f->output_data.x->left_pos)
+ x_set_offset (f, expect_left, expect_top, 1);
+
+ /* Just do this once */
+ f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
+ }
+}
+
+
+/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
+ wanted positions of the WM window (not emacs window).
+ Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
+ window (FRAME_X_WINDOW).
+ */
+void
+x_fullscreen_adjust (f, width, height, top_pos, left_pos)
+ struct frame *f;
+ int *width;
+ int *height;
+ int *top_pos;
+ int *left_pos;
+{
+ int newwidth = f->width, newheight = f->height;
+
+ *top_pos = f->output_data.x->top_pos;
+ *left_pos = f->output_data.x->left_pos;
+
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
+ {
+ int ph;
+
+ ph = FRAME_X_DISPLAY_INFO (f)->height;
+ newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+ ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
+ - f->output_data.x->y_pixels_diff;
+ newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+ *top_pos = 0;
+ }
+
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
+ {
+ int pw;
+
+ pw = FRAME_X_DISPLAY_INFO (f)->width;
+ newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+ pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
+ - f->output_data.x->x_pixels_diff;
+ newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+ *left_pos = 0;
+ }
+
+ *width = newwidth;
+ *height = newheight;
+}
+
/* Change the size of frame F's X window to COLS/ROWS in the case F
doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
: FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
: (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
- f->output_data.x->flags_areas_extra
- = FRAME_FLAGS_AREA_WIDTH (f);
+
+ x_compute_fringe_widths (f, 0);
+
pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
struct frame *f;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Lisp_Object bar;
+ struct scroll_bar *b;
BLOCK_INPUT;
{
if (f->output_data.x->icon_desc)
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
-
+
+#ifdef USE_X_TOOLKIT
+ /* Explicitly destroy the scroll bars of the frame. Without
+ this, we get "BadDrawable" errors from the toolkit later on,
+ presumably from expose events generated for the disappearing
+ toolkit scroll bars. */
+ for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
+ {
+ b = XSCROLL_BAR (bar);
+ x_scroll_bar_remove (b);
+ }
+#endif
+
#ifdef HAVE_X_I18N
if (FRAME_XIC (f))
free_frame_xic (f);
#endif
-
- if (FRAME_X_WINDOW (f))
- XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-
+
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
{
XtDestroyWidget (f->output_data.x->widget);
f->output_data.x->widget = NULL;
}
+ /* Tooltips don't have widgets, only a simple X window, even if
+ we are using a toolkit. */
+ else if (FRAME_X_WINDOW (f))
+ XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+
free_frame_menubar (f);
-#endif /* USE_X_TOOLKIT */
+#else /* !USE_X_TOOLKIT */
+ if (FRAME_X_WINDOW (f))
+ XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+#endif /* !USE_X_TOOLKIT */
unload_color (f, f->output_data.x->foreground_pixel);
unload_color (f, f->output_data.x->background_pixel);
unload_color (f, f->output_data.x->cursor_foreground_pixel);
unload_color (f, f->output_data.x->border_pixel);
unload_color (f, f->output_data.x->mouse_pixel);
-
+
if (f->output_data.x->scroll_bar_background_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_background_pixel);
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
XFontStruct *font;
unsigned long value;
- font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
+ font = XLoadQueryFont (dpy, SDATA (pattern));
if (x_had_errors_p (dpy))
{
/* This error is perhaps due to insufficient memory on X
{
/* We try at least 10 fonts because XListFonts will return
auto-scaled fonts at the head. */
- names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
+ names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
&num_fonts);
if (x_had_errors_p (dpy))
{
}
/* Now store the result in the cache. */
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
label_cached:
if (NILP (list)) continue; /* Try the remaining alternatives. */
BLOCK_INPUT;
count = x_catch_errors (dpy);
thisinfo = XLoadQueryFont (dpy,
- XSTRING (XCAR (tem))->data);
+ SDATA (XCAR (tem)));
if (x_had_errors_p (dpy))
{
/* This error is perhaps due to insufficient memory on X
if (thisinfo)
{
- XCDR (tem)
- = (thisinfo->min_bounds.width == 0
- ? make_number (0)
- : make_number (thisinfo->max_bounds.width));
+ XSETCDR (tem,
+ (thisinfo->min_bounds.width == 0
+ ? make_number (0)
+ : make_number (thisinfo->max_bounds.width)));
BLOCK_INPUT;
XFreeFont (dpy, thisinfo);
UNBLOCK_INPUT;
/* For unknown reason, the previous call of XListFont had
returned a font which can't be opened. Record the size
as 0 not to try to open it again. */
- XCDR (tem) = make_number (0);
+ XSETCDR (tem, make_number (0));
}
found_size = XINT (XCDR (tem));
for (tail = font_names; CONSP (tail); tail = XCDR (tail))
if (dpyinfo->font_table[i].name
&& (!strcmp (dpyinfo->font_table[i].name,
- XSTRING (XCAR (tail))->data)
+ SDATA (XCAR (tail)))
|| !strcmp (dpyinfo->font_table[i].full_name,
- XSTRING (XCAR (tail))->data)))
+ SDATA (XCAR (tail)))))
return (dpyinfo->font_table + i);
}
a bug of not finding a font even if the font surely exists and
is loadable by XLoadQueryFont. */
if (size > 0 && !NILP (font_names))
- fontname = (char *) XSTRING (XCAR (font_names))->data;
+ fontname = (char *) SDATA (XCAR (font_names));
BLOCK_INPUT;
count = x_catch_errors (FRAME_X_DISPLAY (f));
Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
Qnil);
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (key,
- Fcons (Fcons (lispy_full_name,
- make_number (fontp->size)),
- Qnil)),
- XCDR (dpyinfo->name_list_element));
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key,
+ Fcons (Fcons (lispy_full_name,
+ make_number (fontp->size)),
+ Qnil)),
+ XCDR (dpyinfo->name_list_element)));
if (full_name)
{
key = Fcons (Fcons (lispy_full_name, make_number (256)),
Qnil);
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (key,
- Fcons (Fcons (lispy_full_name,
- make_number (fontp->size)),
- Qnil)),
- XCDR (dpyinfo->name_list_element));
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key,
+ Fcons (Fcons (lispy_full_name,
+ make_number (fontp->size)),
+ Qnil)),
+ XCDR (dpyinfo->name_list_element)));
}
}
/* Set global flag fonts_changed_p to non-zero if the font loaded
has a character with a smaller width than any other character
- before, or if the font loaded has a smalle>r height than any
+ before, or if the font loaded has a smaller height than any
other font loaded before. If this happens, it will make a
glyph matrix reallocation necessary. */
- fonts_changed_p = x_compute_min_glyph_bounds (f);
+ fonts_changed_p |= x_compute_min_glyph_bounds (f);
UNBLOCK_INPUT;
return fontp;
}
the screen number from the server number. */
static int
same_x_server (name1, name2)
- char *name1, *name2;
+ const char *name1, *name2;
{
int seen_colon = 0;
- unsigned char *system_name = XSTRING (Vsystem_name)->data;
+ const unsigned char *system_name = SDATA (Vsystem_name);
int system_name_length = strlen (system_name);
int length_until_period = 0;
argv[argc++] = "-xrm";
argv[argc++] = xrm_option;
}
- dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
+ stop_polling ();
+ dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
resource_name, EMACS_CLASS,
emacs_options, XtNumber (emacs_options),
&argc, argv);
+ start_polling ();
#ifdef HAVE_X11XTR6
/* I think this is to compensate for XtSetLanguageProc. */
#ifdef HAVE_X11R5
XSetLocaleModifiers ("");
#endif
- dpy = XOpenDisplay (XSTRING (display_name)->data);
+ dpy = XOpenDisplay (SDATA (display_name));
#endif /* not USE_X_TOOLKIT */
/* Detect failure. */
for (share = x_display_list, tail = x_display_name_list; share;
share = share->next, tail = XCDR (tail))
- if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
- XSTRING (display_name)->data))
+ if (same_x_server (SDATA (XCAR (XCAR (tail))),
+ SDATA (display_name)))
break;
if (share)
dpyinfo->kboard = share->kboard;
#endif /* ! 0 */
dpyinfo->x_id_name
- = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
- + STRING_BYTES (XSTRING (Vsystem_name))
+ = (char *) xmalloc (SBYTES (Vinvocation_name)
+ + SBYTES (Vsystem_name)
+ 2);
sprintf (dpyinfo->x_id_name, "%s@%s",
- XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
+ SDATA (Vinvocation_name), SDATA (Vsystem_name));
/* Figure out which modifier bits mean what. */
x_find_modifier_meanings (dpyinfo);
dpyinfo->mouse_face_overlay = Qnil;
dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
dpyinfo->mouse_face_defer = 0;
+ dpyinfo->mouse_face_hidden = 0;
dpyinfo->x_focus_frame = 0;
dpyinfo->x_focus_event_frame = 0;
dpyinfo->x_highlight_frame = 0;
build_string ("PrivateColormap"),
Qnil, Qnil);
if (STRINGP (value)
- && (!strcmp (XSTRING (value)->data, "true")
- || !strcmp (XSTRING (value)->data, "on")))
+ && (!strcmp (SDATA (value), "true")
+ || !strcmp (SDATA (value), "on")))
dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
}
}
build_string ("Synchronous"),
Qnil, Qnil);
if (STRINGP (value)
- && (!strcmp (XSTRING (value)->data, "true")
- || !strcmp (XSTRING (value)->data, "on")))
+ && (!strcmp (SDATA (value), "true")
+ || !strcmp (SDATA (value), "on")))
XSynchronize (dpyinfo->display, True);
}
{
if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
{
- XCDR (tail) = XCDR (XCDR (tail));
+ XSETCDR (tail, XCDR (XCDR (tail)));
break;
}
tail = XCDR (tail);
clear_frame_hook = x_clear_frame;
ins_del_lines_hook = x_ins_del_lines;
- change_line_highlight_hook = x_change_line_highlight;
delete_glyphs_hook = x_delete_glyphs;
ring_bell_hook = XTring_bell;
reset_terminal_modes_hook = XTreset_terminal_modes;
set_terminal_window_hook = XTset_terminal_window;
read_socket_hook = XTread_socket;
frame_up_to_date_hook = XTframe_up_to_date;
- reassert_line_highlight_hook = XTreassert_line_highlight;
mouse_position_hook = XTmouse_position;
frame_rehighlight_hook = XTframe_rehighlight;
frame_raise_lower_hook = XTframe_raise_lower;
/* Disable Window Change signals; they are handled by X events. */
#ifdef SIGWINCH
signal (SIGWINCH, SIG_DFL);
-#endif /* ! defined (SIGWINCH) */
+#endif /* SIGWINCH */
signal (SIGPIPE, x_connection_signal);
+
+#ifdef HAVE_X_SM
+ x_session_initialize ();
+#endif
}
staticpro (&Qvendor_specific_keysyms);
Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
+ staticpro (&Qutf_8);
+ Qutf_8 = intern ("utf-8");
+ staticpro (&Qlatin_1);
+ Qlatin_1 = intern ("latin-1");
+
staticpro (&last_mouse_press_frame);
last_mouse_press_frame = Qnil;
staticpro (&previous_help_echo);
help_echo_pos = -1;
- DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
- /* *Non-nil means draw block cursor as wide as the glyph under it.
+ DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
+ doc: /* *Non-nil means autoselect window with mouse pointer. */);
+ mouse_autoselect_window = 0;
+
+ DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
+ doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
For example, if a block cursor is over a tab, it will be drawn as
wide as that tab on the display. */);
x_stretch_cursor_p = 0;
DEFVAR_BOOL ("x-use-underline-position-properties",
- &x_use_underline_position_properties
- /* *Non-nil means make use of UNDERLINE_POSITION font properties.
-Nil means ignore them. If you encounter fonts with bogus
+ &x_use_underline_position_properties,
+ doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
+nil means ignore them. If you encounter fonts with bogus
UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
to 4.1, set this to nil. */);
x_use_underline_position_properties = 1;
- DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
- /* What X toolkit scroll bars Emacs uses.
+ DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
+ doc: /* What X toolkit scroll bars Emacs uses.
A value of nil means Emacs doesn't use X toolkit scroll bars.
Otherwise, value is a symbol describing the X toolkit. */);
#ifdef USE_TOOLKIT_SCROLL_BARS
staticpro (&last_mouse_motion_frame);
last_mouse_motion_frame = Qnil;
+
+ Qmodifier_value = intern ("modifier-value");
+ Qalt = intern ("alt");
+ Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
+ Qhyper = intern ("hyper");
+ Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
+ Qmeta = intern ("meta");
+ Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
+ Qsuper = intern ("super");
+ Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+
+ DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
+ doc: /* Which keys Emacs uses for the alt modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `alt' means use the Alt_L and Alt_R keysyms. The default
+is nil, which is the same as `alt'. */);
+ Vx_alt_keysym = Qnil;
+
+ DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
+ doc: /* Which keys Emacs uses for the hyper modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
+default is nil, which is the same as `hyper'. */);
+ Vx_hyper_keysym = Qnil;
+
+ DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
+ doc: /* Which keys Emacs uses for the meta modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `meta' means use the Meta_L and Meta_R keysyms. The
+default is nil, which is the same as `meta'. */);
+ Vx_meta_keysym = Qnil;
+
+ DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
+ doc: /* Which keys Emacs uses for the super modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `super' means use the Super_L and Super_R keysyms. The
+default is nil, which is the same as `super'. */);
+ Vx_super_keysym = Qnil;
+
}
#endif /* HAVE_X_WINDOWS */