/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 02, 2003
- Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* New display code by Gerd Moellmann <gerd@gnu.org>. */
/* Xt features made by Fred Pierresteguy. */
#ifdef HAVE_XAW3D
#include <X11/Xaw3d/Simple.h>
#include <X11/Xaw3d/Scrollbar.h>
-#define ARROW_SCROLLBAR
-#define XAW_ARROW_SCROLLBARS
-#include <X11/Xaw3d/ScrollbarP.h>
+#include <X11/Xaw3d/ThreeD.h>
#else /* !HAVE_XAW3D */
#include <X11/Xaw/Simple.h>
#include <X11/Xaw/Scrollbar.h>
static int toolkit_scroll_bar_interaction;
+/* Non-zero means to not move point as a result of clicking on a
+ frame to focus it (when focus-follows-mouse is nil). */
+
+int x_mouse_click_focus_ignore_position;
+
+/* Non-zero timeout value means ignore next mouse click if it arrives
+ before that timeout elapses (i.e. as part of the same sequence of
+ events resulting from clicking on a frame to select it). */
+
+static unsigned long ignore_next_mouse_click_timeout;
+
/* Mouse movement.
Formerly, we used PointerMotionHintMask (in standard_event_mask)
static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
enum text_cursor_kinds));
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
+static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
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 *));
int x, y0, y1;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
+ struct face *face;
+
+ face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+ if (face)
+ XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
+ face->foreground);
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->normal_gc, x, y0, x, y1);
output_cursor.vpos,
output_cursor.x, output_cursor.y);
- x_draw_vertical_border (w);
-
- draw_window_fringes (w);
+ if (draw_window_fringes (w, 1))
+ x_draw_vertical_border (w);
UNBLOCK_INPUT;
}
int oldVH = row->visible_height;
row->visible_height = p->h;
row->y -= rowY - p->y;
- x_clip_to_row (w, row, gc);
+ x_clip_to_row (w, row, -1, gc);
row->y = oldY;
row->visible_height = oldVH;
}
else
- x_clip_to_row (w, row, gc);
+ x_clip_to_row (w, row, -1, gc);
if (p->bx >= 0 && !p->overlay_p)
{
if (p->overlay_p)
{
- clipmask = XCreatePixmapFromBitmapData (display,
+ clipmask = XCreatePixmapFromBitmapData (display,
FRAME_X_DISPLAY_INFO (f)->root_window,
- bits, p->wd, p->h,
+ bits, p->wd, p->h,
1, 0, 1);
gcv.clip_mask = clipmask;
gcv.clip_x_origin = p->x;
- gcv.clip_y_origin = p->y;
+ gcv.clip_y_origin = p->y;
XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
}
/* It's a program. */
struct ccl_program *ccl = font_info->font_encoder;
+ check_ccl_update (ccl);
if (CHARSET_DIMENSION (charset) == 1)
{
ccl->reg[0] = charset;
static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
int, int, int));
static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
- int, int, int, int, XRectangle *));
+ int, int, int, int, int, int,
+ XRectangle *));
static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
int, int, int, XRectangle *));
static void
x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
- raised_p, left_p, right_p, clip_rect)
+ raised_p, top_p, bot_p, left_p, right_p, clip_rect)
struct frame *f;
- int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
+ int left_x, top_y, right_x, bottom_y, width;
+ int top_p, bot_p, left_p, right_p, raised_p;
XRectangle *clip_rect;
{
Display *dpy = FRAME_X_DISPLAY (f);
XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
/* Top. */
- for (i = 0; i < width; ++i)
- XDrawLine (dpy, window, gc,
- left_x + i * left_p, top_y + i,
- right_x + 1 - i * right_p, top_y + i);
+ if (top_p)
+ for (i = 0; i < width; ++i)
+ XDrawLine (dpy, window, gc,
+ left_x + i * left_p, top_y + i,
+ right_x + 1 - i * right_p, top_y + i);
/* Left. */
if (left_p)
XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
/* Bottom. */
- for (i = 0; i < width; ++i)
- XDrawLine (dpy, window, gc,
- left_x + i * left_p, bottom_y - i,
- right_x + 1 - i * right_p, bottom_y - i);
+ if (bot_p)
+ for (i = 0; i < width; ++i)
+ XDrawLine (dpy, window, gc,
+ left_x + i * left_p, bottom_y - i,
+ right_x + 1 - i * right_p, bottom_y - i);
/* Right. */
if (right_p)
struct glyph *last_glyph;
XRectangle clip_rect;
- last_x = window_box_right (s->w, s->area);
- if (s->row->full_width_p
- && !s->w->pseudo_window_p)
- {
- last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
- if (s->area != RIGHT_MARGIN_AREA
- || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
- last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
- }
+ last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
+ ? WINDOW_RIGHT_EDGE_X (s->w)
+ : window_box_right (s->w, s->area));
/* The glyph that may have a right box line. */
last_glyph = (s->cmp || s->img
{
x_setup_relief_colors (s);
x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
- width, raised_p, left_p, right_p, &clip_rect);
+ width, raised_p, 1, 1, left_p, right_p, &clip_rect);
}
}
x_draw_image_foreground (s)
struct glyph_string *s;
{
- int x;
- int y = s->ybase - image_ascent (s->img, s->face);
+ int x = s->x;
+ int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
/* If first glyph of S has a left box line, start drawing it to the
right of that line. */
if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + abs (s->face->box_line_width);
- else
- x = s->x;
+ && s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += abs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
+ if (s->slice.x == 0)
+ x += s->img->hmargin;
+ if (s->slice.y == 0)
+ y += s->img->vmargin;
if (s->img->pixmap)
{
get_glyph_string_clip_rect (s, &clip_rect);
image_rect.x = x;
image_rect.y = y;
- image_rect.width = s->img->width;
- image_rect.height = s->img->height;
+ image_rect.width = s->slice.width;
+ image_rect.height = s->slice.height;
if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
- r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+ s->slice.x + r.x - x, s->slice.y + r.y - y,
+ r.width, r.height, r.x, r.y);
}
else
{
get_glyph_string_clip_rect (s, &clip_rect);
image_rect.x = x;
image_rect.y = y;
- image_rect.width = s->img->width;
- image_rect.height = s->img->height;
+ image_rect.width = s->slice.width;
+ image_rect.height = s->slice.height;
if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
- r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+ s->slice.x + r.x - x, s->slice.y + r.y - y,
+ r.width, r.height, r.x, r.y);
/* When the image has a mask, we can expect that at
least part of a mouse highlight or a block cursor will
{
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);
+ XDrawRectangle (s->display, s->window, s->gc,
+ x - r, y - r,
+ s->slice.width + r*2 - 1,
+ s->slice.height + r*2 - 1);
}
}
}
else
/* Draw a rectangle if image could not be loaded. */
XDrawRectangle (s->display, s->window, s->gc, x, y,
- s->img->width - 1, s->img->height - 1);
+ s->slice.width - 1, s->slice.height - 1);
}
{
int x0, y0, x1, y1, thick, raised_p;
XRectangle r;
- int x;
- int y = s->ybase - image_ascent (s->img, s->face);
+ int x = s->x;
+ int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
/* If first glyph of S has a left box line, start drawing it to the
right of that line. */
if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + abs (s->face->box_line_width);
- else
- x = s->x;
+ && s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += abs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
+ if (s->slice.x == 0)
+ x += s->img->hmargin;
+ if (s->slice.y == 0)
+ y += s->img->vmargin;
if (s->hl == DRAW_IMAGE_SUNKEN
|| s->hl == DRAW_IMAGE_RAISED)
x0 = x - thick;
y0 = y - thick;
- x1 = x + s->img->width + thick - 1;
- y1 = y + s->img->height + thick - 1;
+ x1 = x + s->slice.width + thick - 1;
+ y1 = y + s->slice.height + thick - 1;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
- x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+ x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
+ s->slice.y == 0,
+ s->slice.y + s->slice.height == s->img->height,
+ s->slice.x == 0,
+ s->slice.x + s->slice.width == s->img->width,
+ &r);
}
struct glyph_string *s;
Pixmap pixmap;
{
- int x;
- int y = s->ybase - s->y - image_ascent (s->img, s->face);
+ int x = 0;
+ int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
/* If first glyph of S has a left box line, start drawing it to the
right of that line. */
if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = abs (s->face->box_line_width);
- else
- x = 0;
+ && s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += abs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
+ if (s->slice.x == 0)
+ x += s->img->hmargin;
+ if (s->slice.y == 0)
+ y += s->img->vmargin;
if (s->img->pixmap)
{
XGCValues xgcv;
xgcv.clip_mask = s->img->mask;
- xgcv.clip_x_origin = x;
- xgcv.clip_y_origin = y;
+ xgcv.clip_x_origin = x - s->slice.x;
+ xgcv.clip_y_origin = y - s->slice.y;
xgcv.function = GXcopy;
XChangeGC (s->display, s->gc, mask, &xgcv);
XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
- 0, 0, s->img->width, s->img->height, x, y);
+ s->slice.x, s->slice.y,
+ s->slice.width, s->slice.height, x, y);
XSetClipMask (s->display, s->gc, None);
}
else
{
XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
- 0, 0, s->img->width, s->img->height, x, y);
+ s->slice.x, s->slice.y,
+ s->slice.width, s->slice.height, x, y);
/* When the image has a mask, we can expect that at
least part of a mouse highlight or a block cursor will
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);
+ s->slice.width + r*2 - 1,
+ s->slice.height + r*2 - 1);
}
}
}
else
/* Draw a rectangle if image could not be loaded. */
XDrawRectangle (s->display, pixmap, s->gc, x, y,
- s->img->width - 1, s->img->height - 1);
+ s->slice.width - 1, s->slice.height - 1);
}
x_draw_image_glyph_string (s)
struct glyph_string *s;
{
- int x, y;
int box_line_hwidth = abs (s->face->box_line_width);
int box_line_vwidth = max (s->face->box_line_width, 0);
int height;
Pixmap pixmap = None;
- height = s->height - 2 * box_line_vwidth;
-
+ height = s->height;
+ if (s->slice.y == 0)
+ height -= box_line_vwidth;
+ if (s->slice.y + s->slice.height >= s->img->height)
+ height -= box_line_vwidth;
/* Fill background with face under the image. Do it only if row is
taller than image or if image has a clip mask to reduce
flickering. */
s->stippled_p = s->face->stipple != 0;
- if (height > s->img->height
+ if (height > s->slice.height
|| s->img->hmargin
|| s->img->vmargin
|| s->img->mask
|| s->img->pixmap == 0
|| s->width != s->background_width)
{
- if (box_line_hwidth && s->first_glyph->left_box_line_p)
- x = s->x + box_line_hwidth;
- else
- x = s->x;
-
- y = s->y + box_line_vwidth;
-
if (s->img->mask)
{
/* Create a pixmap as large as the glyph string. Fill it
}
}
else
- x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+ {
+ int x = s->x;
+ int y = s->y;
+
+ if (s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += box_line_hwidth;
+
+ if (s->slice.y == 0)
+ y += box_line_vwidth;
+
+ x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+ }
s->background_filled_p = 1;
}
XFlush (FRAME_X_DISPLAY (f));
-#ifdef USE_GTK
- xg_frame_cleared (f);
-#endif
-
UNBLOCK_INPUT;
}
struct input_event *bufp;
{
struct frame *frame;
- int nr_events = 0;
frame = x_any_window_to_frame (dpyinfo, event->xany.window);
if (! frame)
Alt keysyms are on. */
{
int row, col; /* The row and column in the modifier table. */
+ int found_alt_or_meta;
for (row = 3; row < 8; row++)
+ {
+ found_alt_or_meta = 0;
for (col = 0; col < mods->max_keypermod; col++)
{
- KeyCode code
- = mods->modifiermap[(row * mods->max_keypermod) + col];
+ KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
/* Zeroes are used for filler. Skip them. */
if (code == 0)
{
case XK_Meta_L:
case XK_Meta_R:
+ found_alt_or_meta = 1;
dpyinfo->meta_mod_mask |= (1 << row);
break;
case XK_Alt_L:
case XK_Alt_R:
+ found_alt_or_meta = 1;
dpyinfo->alt_mod_mask |= (1 << row);
break;
case XK_Hyper_L:
case XK_Hyper_R:
- dpyinfo->hyper_mod_mask |= (1 << row);
+ if (!found_alt_or_meta)
+ dpyinfo->hyper_mod_mask |= (1 << row);
+ code_col = syms_per_code;
+ col = mods->max_keypermod;
break;
case XK_Super_L:
case XK_Super_R:
- dpyinfo->super_mod_mask |= (1 << row);
+ if (!found_alt_or_meta)
+ dpyinfo->super_mod_mask |= (1 << row);
+ code_col = syms_per_code;
+ col = mods->max_keypermod;
break;
case XK_Shift_Lock:
/* Ignore this if it's not on the lock modifier. */
- if ((1 << row) == LockMask)
+ if (!found_alt_or_meta && ((1 << row) == LockMask))
dpyinfo->shift_lock_mask = LockMask;
+ code_col = syms_per_code;
+ col = mods->max_keypermod;
break;
}
}
}
}
+ }
}
/* If we couldn't find any meta keys, accept any alt keys as meta keys. */
{
Lisp_Object tail;
-#ifdef USE_GTK
+#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
-#endif /* USE_GTK */
+#endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
for (tail = Vframe_list;
XGCTYPE (tail) == Lisp_Cons;
int part = -1, whole = 0, portion = 0;
GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
- if (xg_ignore_gtk_scrollbar) return;
-
position = gtk_adjustment_get_value (adj);
p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
previous = *p;
*p = position;
+ if (xg_ignore_gtk_scrollbar) return;
+
diff = (int) (position - previous);
if (diff == (int) adj->step_increment)
f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
}
+#ifdef XtNbeNiceToColormap
/* Tell the toolkit about them. */
if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
|| f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
if (pixel != -1)
{
- XtSetArg (av[ac], "topShadowPixel", pixel);
+ XtSetArg (av[ac], XtNtopShadowPixel, pixel);
++ac;
}
pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
if (pixel != -1)
{
- XtSetArg (av[ac], "bottomShadowPixel", pixel);
+ XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
++ac;
}
}
+#endif
widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
f->output_data.x->edit_widget, av, ac);
char *initial = "";
char *val = initial;
XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
+#ifdef XtNarrowScrollbars
+ XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
+#endif
XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
- if (val == initial)
+ if (xaw3d_arrow_scroll || val == initial)
{ /* ARROW_SCROLL */
xaw3d_arrow_scroll = True;
- /* Isn't that just a personal preference ? -sm */
+ /* Isn't that just a personal preference ? --Stef */
XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
}
}
XawScrollbarSetThumb (widget, top, shown);
else
{
-#ifdef HAVE_XAW3D
- ScrollbarWidget sb = (ScrollbarWidget) widget;
- int scroll_mode = 0;
-
- /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
- if (xaw3d_arrow_scroll)
- {
- /* Xaw3d stupidly ignores resize requests while dragging
- so we have to make it believe it's not in dragging mode. */
- scroll_mode = sb->scrollbar.scroll_mode;
- if (scroll_mode == 2)
- sb->scrollbar.scroll_mode = 0;
- }
-#endif
/* Try to make the scrolling a tad smoother. */
if (!xaw3d_pick_top)
shown = min (shown, old_shown);
XawScrollbarSetThumb (widget, top, shown);
-
-#ifdef HAVE_XAW3D
- if (xaw3d_arrow_scroll && scroll_mode == 2)
- sb->scrollbar.scroll_mode = scroll_mode;
-#endif
}
}
}
top,
left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- max (height, 1),
- left,
- width);
+ max (height, 1));
xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
#else /* not USE_GTK */
Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
/* Compute the left edge of the scroll bar. */
#ifdef USE_TOOLKIT_SCROLL_BARS
if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
- sb_left = left + width - sb_width - (width - sb_width) / 2;
+ sb_left = (left +
+ (WINDOW_RIGHTMOST_P (w)
+ ? width - sb_width - (width - sb_width) / 2
+ : 0));
else
- sb_left = left + (width - sb_width) / 2;
+ sb_left = (left +
+ (WINDOW_LEFTMOST_P (w)
+ ? (width - sb_width) / 2
+ : width - sb_width));
#else
if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
sb_left = left + width - sb_width;
#ifdef USE_TOOLKIT_SCROLL_BARS
-#ifdef USE_GTK
- if (mask)
- xg_update_scrollbar_pos (f,
- SCROLL_BAR_X_WINDOW (bar),
- top,
- sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
- sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- max (height, 1),
- left,
- width);
-#else /* not USE_GTK */
-
- /* Since toolkit scroll bars are smaller than the space reserved
- for them on the frame, we have to clear "under" them. */
- if (width > 0 && height > 0)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height, False);
/* Move/size the scroll bar widget. */
if (mask)
+ {
+ /* Since toolkit scroll bars are smaller than the space reserved
+ for them on the frame, we have to clear "under" them. */
+ if (width > 0 && height > 0)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width, height, False);
+#ifdef USE_GTK
+ xg_update_scrollbar_pos (f,
+ SCROLL_BAR_X_WINDOW (bar),
+ top,
+ sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+ sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
+ max (height, 1));
+#else /* not USE_GTK */
XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
top,
sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
max (height, 1), 0);
-
#endif /* not USE_GTK */
+ }
#else /* not USE_TOOLKIT_SCROLL_BARS */
/* Clear areas not covered by the scroll bar because of
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
-\f
-/* Define a queue to save up SelectionRequest events for later handling. */
-
-struct selection_event_queue
- {
- XEvent event;
- struct selection_event_queue *next;
- };
-
-static struct selection_event_queue *queue;
-
-/* Nonzero means queue up certain events--don't process them yet. */
-
-static int x_queue_selection_requests;
-
-/* Queue up an X event *EVENT, to be processed later. */
-
-static void
-x_queue_event (f, event)
- FRAME_PTR f;
- XEvent *event;
-{
- struct selection_event_queue *queue_tmp
- = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
-
- if (queue_tmp != NULL)
- {
- queue_tmp->event = *event;
- queue_tmp->next = queue;
- queue = queue_tmp;
- }
-}
-
-/* Take all the queued events and put them back
- so that they get processed afresh. */
-
-static void
-x_unqueue_events (display)
- Display *display;
-{
- while (queue != NULL)
- {
- struct selection_event_queue *queue_tmp = queue;
- XPutBackEvent (display, &queue_tmp->event);
- queue = queue_tmp->next;
- xfree ((char *)queue_tmp);
- }
-}
-
-/* Start queuing SelectionRequest events. */
-
-void
-x_start_queuing_selection_requests (display)
- Display *display;
-{
- x_queue_selection_requests++;
-}
-
-/* Stop queuing SelectionRequest events. */
-
-void
-x_stop_queuing_selection_requests (display)
- Display *display;
-{
- x_queue_selection_requests--;
- x_unqueue_events (display);
-}
\f
/* The main X event-reading loop - XTread_socket. */
f->output_data.x->saved_menu_event \
= (XEvent *) xmalloc (sizeof (XEvent)); \
bcopy (&event, f->output_data.x->saved_menu_event, size); \
- inev.kind = MENU_BAR_ACTIVATE_EVENT; \
- XSETFRAME (inev.frame_or_window, f); \
+ inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
+ XSETFRAME (inev.ie.frame_or_window, f); \
} \
while (0)
else
{
current_count +=
- handle_one_xevent (dpyinfo, xev, ¤t_finish,
+ handle_one_xevent (dpyinfo, xev, ¤t_finish,
current_hold_quit);
}
}
int *finish;
struct input_event *hold_quit;
{
- struct input_event inev;
+ union {
+ struct input_event ie;
+ struct selection_input_event sie;
+ } inev;
int count = 0;
int do_help = 0;
int nbytes = 0;
*finish = X_EVENT_NORMAL;
- EVENT_INIT (inev);
- inev.kind = NO_EVENT;
- inev.arg = Qnil;
+ EVENT_INIT (inev.ie);
+ inev.ie.kind = NO_EVENT;
+ inev.ie.arg = Qnil;
switch (event.type)
{
if (!f)
goto OTHER; /* May be a dialog that is to be removed */
- inev.kind = DELETE_WINDOW_EVENT;
- XSETFRAME (inev.frame_or_window, f);
+ inev.ie.kind = DELETE_WINDOW_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
goto done;
}
if (event.xclient.message_type
== dpyinfo->Xatom_Scrollbar)
{
- x_scroll_bar_to_input_event (&event, &inev);
+ x_scroll_bar_to_input_event (&event, &inev.ie);
*finish = X_EVENT_GOTO_OUT;
goto done;
}
if (!f)
goto OTHER;
- if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev))
+ if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
*finish = X_EVENT_DROP;
}
break;
{
XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
- inev.kind = SELECTION_CLEAR_EVENT;
- SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
- SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
- SELECTION_EVENT_TIME (&inev) = eventp->time;
- inev.frame_or_window = Qnil;
+ inev.ie.kind = SELECTION_CLEAR_EVENT;
+ SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+ SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+ SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+ inev.ie.frame_or_window = Qnil;
}
break;
if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
goto OTHER;
#endif /* USE_X_TOOLKIT */
- if (x_queue_selection_requests)
- x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
- &event);
- else
- {
+ {
XSelectionRequestEvent *eventp
= (XSelectionRequestEvent *) &event;
- inev.kind = SELECTION_REQUEST_EVENT;
- SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
- SELECTION_EVENT_REQUESTOR (&inev) = eventp->requestor;
- SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
- SELECTION_EVENT_TARGET (&inev) = eventp->target;
- SELECTION_EVENT_PROPERTY (&inev) = eventp->property;
- SELECTION_EVENT_TIME (&inev) = eventp->time;
- inev.frame_or_window = Qnil;
- }
+ inev.ie.kind = SELECTION_REQUEST_EVENT;
+ SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+ SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
+ SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+ SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
+ SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
+ SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+ inev.ie.frame_or_window = Qnil;
+ }
break;
case PropertyNotify:
{
x_check_fullscreen (f);
+#ifdef USE_GTK
+ /* This seems to be needed for GTK 2.6. */
+ x_clear_area (event.xexpose.display,
+ event.xexpose.window,
+ event.xexpose.x, event.xexpose.y,
+ event.xexpose.width, event.xexpose.height,
+ FALSE);
+#endif
if (f->async_visible == 0)
{
f->async_visible = 1;
{
f->async_iconified = 1;
- inev.kind = ICONIFY_EVENT;
- XSETFRAME (inev.frame_or_window, f);
+ inev.ie.kind = ICONIFY_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
}
}
goto OTHER;
f = x_top_window_to_frame (dpyinfo, event.xmap.window);
if (f)
{
- /* wait_reading_process_input will notice this and update
+ /* wait_reading_process_output will notice this and update
the frame's display structures.
If we where iconified, we should not set garbaged,
because that stops redrawing on Expose events. This looks
if (f->iconified)
{
- inev.kind = DEICONIFY_EVENT;
- XSETFRAME (inev.frame_or_window, f);
+ inev.ie.kind = DEICONIFY_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
}
else if (! NILP (Vframe_list)
&& ! NILP (XCDR (Vframe_list)))
case KeyPress:
+ ignore_next_mouse_click_timeout = 0;
+
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Dispatch KeyPress events when in menu. */
if (popup_activated ())
if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
{
- dpyinfo->mouse_face_hidden = 1;
clear_mouse_face (dpyinfo);
+ dpyinfo->mouse_face_hidden = 1;
}
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
if (compose_status.chars_matched > 0 && nbytes == 0)
break;
+ bzero (&compose_status, sizeof (compose_status));
orig_keysym = keysym;
/* Common for all keysym input events. */
- XSETFRAME (inev.frame_or_window, f);
- inev.modifiers
+ XSETFRAME (inev.ie.frame_or_window, f);
+ inev.ie.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
- inev.timestamp = event.xkey.time;
+ inev.ie.timestamp = event.xkey.time;
/* First deal with keysyms which have defined
translations to characters. */
if (keysym >= 32 && keysym < 128)
/* Avoid explicitly decoding each ASCII character. */
{
- inev.kind = ASCII_KEYSTROKE_EVENT;
- inev.code = keysym;
+ inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
goto done_keysym;
}
Vx_keysym_table,
Qnil))))
{
- inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.code = XFASTINT (c);
+ inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+ ? ASCII_KEYSTROKE_EVENT
+ : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+ inev.ie.code = XFASTINT (c);
goto done_keysym;
}
STORE_KEYSYM_FOR_DEBUG (keysym);
/* make_lispy_event will convert this to a symbolic
key. */
- inev.kind = NON_ASCII_KEYSTROKE_EVENT;
- inev.code = keysym;
+ inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
goto done_keysym;
}
else
c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
nbytes - i, len);
- inev.kind = (SINGLE_BYTE_CHAR_P (c)
+ inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
? ASCII_KEYSTROKE_EVENT
: MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.code = c;
- kbd_buffer_store_event_hold (&inev, hold_quit);
+ inev.ie.code = c;
+ kbd_buffer_store_event_hold (&inev.ie, hold_quit);
}
/* Previous code updated count by nchars rather than nbytes,
but that seems bogus to me. ++kfs */
count += nbytes;
- inev.kind = NO_EVENT; /* Already stored above. */
+ inev.ie.kind = NO_EVENT; /* Already stored above. */
if (keysym == NoSymbol)
break;
#endif
case EnterNotify:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
+ if (f && x_mouse_click_focus_ignore_position)
+ ignore_next_mouse_click_timeout = event.xmotion.time + 200;
+
#if 0
if (event.xcrossing.focus)
{
goto OTHER;
case FocusIn:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
goto OTHER;
case LeaveNotify:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
if (f)
goto OTHER;
case FocusOut:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
goto OTHER;
case MotionNotify:
&& !EQ (window, last_window)
&& !EQ (window, selected_window))
{
- inev.kind = SELECT_WINDOW_EVENT;
- inev.frame_or_window = window;
+ inev.ie.kind = SELECT_WINDOW_EVENT;
+ inev.ie.frame_or_window = window;
}
last_window=window;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
if (! popup_activated ())
#endif
- construct_mouse_click (&inev, &event, f);
+ {
+ if (ignore_next_mouse_click_timeout)
+ {
+ if (event.type == ButtonPress
+ && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
+ {
+ ignore_next_mouse_click_timeout = 0;
+ construct_mouse_click (&inev.ie, &event, f);
+ }
+ if (event.type == ButtonRelease)
+ ignore_next_mouse_click_timeout = 0;
+ }
+ else
+ construct_mouse_click (&inev.ie, &event, f);
+ }
}
}
else
scroll bars. */
if (bar && event.xbutton.state & ControlMask)
{
- x_scroll_bar_handle_click (bar, &event, &inev);
+ x_scroll_bar_handle_click (bar, &event, &inev.ie);
*finish = X_EVENT_DROP;
}
#else /* not USE_TOOLKIT_SCROLL_BARS */
if (bar)
- x_scroll_bar_handle_click (bar, &event, &inev);
+ x_scroll_bar_handle_click (bar, &event, &inev.ie);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
{
dpyinfo->grabbed |= (1 << event.xbutton.button);
last_mouse_frame = f;
- /* Ignore any mouse motion that happened
- before this event; any subsequent mouse-movement
- Emacs events should reflect only motion after
- the ButtonPress. */
- if (f != 0)
- f->mouse_moved = 0;
if (!tool_bar_p)
last_tool_bar_item = -1;
else
dpyinfo->grabbed &= ~(1 << event.xbutton.button);
+ /* Ignore any mouse motion that happened before this event;
+ any subsequent mouse-movement Emacs events should reflect
+ only motion after the ButtonPress/Release. */
+ if (f != 0)
+ f->mouse_moved = 0;
+
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
/* For a down-event in the menu bar,
}
done:
- if (inev.kind != NO_EVENT)
+ if (inev.ie.kind != NO_EVENT)
{
- kbd_buffer_store_event_hold (&inev, hold_quit);
+ kbd_buffer_store_event_hold (&inev.ie, hold_quit);
count++;
}
any_help_event_p = 1;
gen_help_event (help_echo_string, frame, help_echo_window,
help_echo_object, help_echo_pos);
- }
+ }
else
{
help_echo_string = Qnil;
mode lines must be clipped to the whole window. */
static void
-x_clip_to_row (w, row, gc)
+x_clip_to_row (w, row, area, gc)
struct window *w;
struct glyph_row *row;
+ int area;
GC gc;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
XRectangle clip_rect;
- int window_y, window_width;
+ int window_x, window_y, window_width;
- window_box (w, -1, 0, &window_y, &window_width, 0);
+ window_box (w, area, &window_x, &window_y, &window_width, 0);
- clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
- clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+ clip_rect.x = window_x;
+ clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
clip_rect.y = max (clip_rect.y, window_y);
clip_rect.width = window_width;
clip_rect.height = row->visible_height;
if (cursor_glyph == NULL)
return;
- /* Compute the width of the rectangle to draw. If on a stretch
- glyph, and `x-stretch-block-cursor' is nil, don't draw a
- rectangle as wide as the glyph, but use a canonical character
- width instead. */
- wd = cursor_glyph->pixel_width - 1;
- if (cursor_glyph->type == STRETCH_GLYPH
- && !x_stretch_cursor_p)
- wd = min (FRAME_COLUMN_WIDTH (f), wd);
- w->phys_cursor_width = wd;
-
- /* Compute frame-relative coordinates from window-relative
- coordinates. */
+ /* Compute frame-relative coordinates for phys cursor. */
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
-
- /* Compute the proper height and ascent of the rectangle, based
- on the actual glyph. Using the full height of the row looks
- bad when there are tall images on that row. */
- h = max (FRAME_LINE_HEIGHT (f), cursor_glyph->ascent + cursor_glyph->descent);
- if (h < row->height)
- y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
- h--;
+ y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
+ wd = w->phys_cursor_width;
/* The foreground of cursor_gc is typically the same as the normal
background color, which can cause the cursor box to be invisible. */
gc = dpyinfo->scratch_cursor_gc;
/* Set clipping, draw the rectangle, and reset clipping again. */
- x_clip_to_row (w, row, gc);
+ x_clip_to_row (w, row, TEXT_AREA, gc);
XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
XSetClipMask (dpy, gc, None);
}
width = min (cursor_glyph->pixel_width, width);
w->phys_cursor_width = width;
- x_clip_to_row (w, row, gc);
+ x_clip_to_row (w, row, TEXT_AREA, gc);
if (kind == BAR_CURSOR)
XFillRectangle (dpy, window, gc,
x_catch_errors_unwind (old_val)
Lisp_Object old_val;
{
- Lisp_Object first;
+ Lisp_Object first = XCAR (old_val);
+ Display *dpy = XSAVE_VALUE (first)->pointer;
- first = XCAR (old_val);
-
- XSync (XSAVE_VALUE (first)->pointer, False);
+ /* The display may have been closed before this function is called.
+ Check if it is still open before calling XSync. */
+ if (x_display_info_for_display (dpy) != 0)
+ {
+ BLOCK_INPUT;
+ XSync (dpy, False);
+ UNBLOCK_INPUT;
+ }
x_error_message_string = XCDR (old_val);
return Qnil;
error ("%s", error_msg);
}
+/* We specifically use it before defining it, so that gcc doesn't inline it,
+ otherwise gdb doesn't know how to properly put a breakpoint on it. */
+static void x_error_quitter (Display *display, XErrorEvent *error);
+
+/* This is the first-level handler for X protocol errors.
+ It calls x_error_quitter or x_error_catcher. */
+
+static int
+x_error_handler (display, error)
+ Display *display;
+ XErrorEvent *error;
+{
+ if (! NILP (x_error_message_string))
+ x_error_catcher (display, error);
+ else
+ x_error_quitter (display, error);
+ return 0;
+}
/* This is the usual handler for X protocol errors.
It kills all frames on the display that we got the error for.
If that was the only one, it prints an error message and kills Emacs. */
-static void
+/* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
+
+#if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */
+#define NO_INLINE __attribute__((noinline))
+#else
+#define NO_INLINE
+#endif
+
+/* Some versions of GNU/Linux define noinline in their headers. */
+
+#ifdef noinline
+#undef noinline
+#endif
+
+/* On older GCC versions, just putting x_error_quitter
+ after x_error_handler prevents inlining into the former. */
+
+static void NO_INLINE
x_error_quitter (display, error)
Display *display;
XErrorEvent *error;
}
-/* This is the first-level handler for X protocol errors.
- It calls x_error_quitter or x_error_catcher. */
-
-static int
-x_error_handler (display, error)
- Display *display;
- XErrorEvent *error;
-{
- if (! NILP (x_error_message_string))
- x_error_catcher (display, error);
- else
- x_error_quitter (display, error);
- return 0;
-}
-
/* This is the handler for X IO errors, always.
It kills all frames on the display that we lost touch with.
If that was the only one, it prints an error message and kills Emacs. */
FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
FRAME_FONTSET (f) = -1;
- FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+ FRAME_COLUMN_WIDTH (f) = fontp->average_width;
+ FRAME_SPACE_WIDTH (f) = fontp->space_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
compute_fringe_widths (f, 1);
if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
{
FRAME_XIC (f) = NULL;
- if (FRAME_XIC_FONTSET (f))
- {
- XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
- FRAME_XIC_FONTSET (f) = NULL;
- }
+ xic_free_xfontset (f);
}
}
x_calc_absolute_position (f)
struct frame *f;
{
- Window child;
int win_x = 0, win_y = 0;
int flags = f->size_hint_flags;
if (! ((flags & XNegative) || (flags & YNegative)))
return;
- /* Find the offsets of the outside upper-left corner of
- the inner window, with respect to the outer window.
- But do this only if we will need the results. */
- if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
- /* This is to get *_pixels_outer_diff. */
- x_real_positions (f, &win_x, &win_y);
-
/* Treat negative positions as relative to the leftmost bottommost
position that fits on the screen. */
if (flags & XNegative)
f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
- - 2 * FRAME_X_OUTPUT (f)->x_pixels_outer_diff
- - FRAME_PIXEL_WIDTH (f)
- + f->left_pos);
+ - FRAME_PIXEL_WIDTH (f) + f->left_pos);
{
int height = FRAME_PIXEL_HEIGHT (f);
#endif
if (flags & YNegative)
- f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
- - FRAME_X_OUTPUT (f)->y_pixels_outer_diff
-
- /* Assume the window manager decorations are the same size on
- three sides, i.e. left, right and bottom. This is to
- compensate for the bottom part. */
- - FRAME_X_OUTPUT (f)->x_pixels_outer_diff
- - height
- + f->top_pos);
+ f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
}
/* The left_pos and top_pos
f->win_gravity = NorthWestGravity;
}
x_calc_absolute_position (f);
-
+
BLOCK_INPUT;
x_wm_set_size_hint (f, (long) 0, 0);
FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
- x_set_offset (f, expect_left, expect_top, 1);
+ f->left_pos = expect_left;
+ f->top_pos = expect_top;
+ x_set_offset (f, expect_left, expect_top, 0);
}
else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
#endif
}
-#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
+
+#ifdef USE_GTK
+ {
+ xg_set_frame_icon (f, icon_pixmap, icon_mask);
+ return;
+ }
+
+#elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
{
Arg al[1];
XtSetValues (f->output_data.x->widget, al, 1);
}
-#else /* not USE_X_TOOLKIT */
+#else /* not USE_X_TOOLKIT && not USE_GTK */
f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
}
void
fontp->name = (char *) xmalloc (strlen (fontname) + 1);
bcopy (fontname, fontp->name, strlen (fontname) + 1);
+ if (font->min_bounds.width == font->max_bounds.width)
+ {
+ /* Fixed width font. */
+ fontp->average_width = fontp->space_width = font->min_bounds.width;
+ }
+ else
+ {
+ XChar2b char2b;
+ XCharStruct *pcm;
+
+ char2b.byte1 = 0x00, char2b.byte2 = 0x20;
+ pcm = x_per_char_metric (font, &char2b, 0);
+ if (pcm)
+ fontp->space_width = pcm->width;
+ else
+ fontp->space_width = FONT_WIDTH (font);
+
+ fontp->average_width
+ = (XGetFontProperty (font, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
+ ? (long) value / 10 : 0);
+ if (fontp->average_width < 0)
+ fontp->average_width = - fontp->average_width;
+ if (fontp->average_width == 0)
+ {
+ if (pcm)
+ {
+ int width = pcm->width;
+ for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
+ if ((pcm = x_per_char_metric (font, &char2b, 0)) != NULL)
+ width += pcm->width;
+ fontp->average_width = width / 95;
+ }
+ else
+ fontp->average_width = FONT_WIDTH (font);
+ }
+ }
+
/* Try to get the full name of FONT. Put it in FULL_NAME. */
full_name = 0;
if (XGetFontProperty (font, XA_FONT, &value))
get_bits_and_offset (dpyinfo->visual->green_mask,
&dpyinfo->green_bits, &dpyinfo->green_offset);
}
-
+
/* See if a private colormap is requested. */
if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
{
int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
double pixels = DisplayHeight (dpyinfo->display, screen_number);
double mm = DisplayHeightMM (dpyinfo->display, screen_number);
- dpyinfo->resy = pixels * 25.4 / mm;
+ /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
+ dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
pixels = DisplayWidth (dpyinfo->display, screen_number);
+ /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
mm = DisplayWidthMM (dpyinfo->display, screen_number);
- dpyinfo->resx = pixels * 25.4 / mm;
+ dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
}
dpyinfo->Xatom_wm_protocols
/* For properties of font. */
dpyinfo->Xatom_PIXEL_SIZE
= XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
+ dpyinfo->Xatom_AVERAGE_WIDTH
+ = XInternAtom (dpyinfo->display, "AVERAGE_WIDTH", False);
dpyinfo->Xatom_MULE_BASELINE_OFFSET
= XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
x_update_window_end,
x_cursor_to,
x_flush,
-#ifndef XFlush
+#ifdef XFlush
x_flush,
#else
0, /* flush_display_optional */
x_noop_count = 0;
last_tool_bar_item = -1;
any_help_event_p = 0;
+ ignore_next_mouse_click_timeout = 0;
#ifdef USE_GTK
current_count = -1;
to 4.1, set this to nil. */);
x_use_underline_position_properties = 1;
+ DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
+ &x_mouse_click_focus_ignore_position,
+ doc: /* Non-nil means that a mouse click to focus a frame does not move point.
+This variable is only used when the window manager requires that you
+click on a frame to select it (give it focus). In that case, a value
+of nil, means that the selected window and cursor position changes to
+reflect the mouse click position, while a non-nil value means that the
+selected window or cursor position is preserved. */);
+ x_mouse_click_focus_ignore_position = 0;
+
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.