X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/a633a9544b7099c7ec6dc53182d830571bf1a442..04c9dde8afc535589a1a4803b45b346325e353e7:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 2c6cb44d15..609ffefcbb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1,6 +1,6 @@ /* 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. @@ -217,6 +217,17 @@ static String Xt_default_resources[] = {0}; 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) @@ -336,23 +347,17 @@ static void x_clear_frame P_ ((void)); 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 x_focus_changed P_ ((int, int, struct x_display_info *, + struct frame *, struct input_event *)); +static void x_detect_focus_change P_ ((struct x_display_info *, + XEvent *, struct input_event *)); 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, 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 *)); @@ -364,11 +369,8 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *, unsigned long *)); static void x_check_fullscreen P_ ((struct frame *)); static void x_check_expected_move P_ ((struct frame *)); -static int handle_one_xevent P_ ((struct x_display_info *, - XEvent *, - struct input_event **, - int *, - int *)); +static int handle_one_xevent P_ ((struct x_display_info *, XEvent *, + int *, struct input_event *)); /* Flush display of frame F, or of all frames if F is null. */ @@ -569,7 +571,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p) output_cursor.vpos, output_cursor.x, output_cursor.y); - x_draw_vertical_border (w); + if (draw_window_fringes (w, 1)) + x_draw_vertical_border (w); + UNBLOCK_INPUT; } @@ -649,11 +653,7 @@ x_after_update_window_line (desired_row) xassert (w); if (!desired_row->mode_line_p && !w->pseudo_window_p) - { - BLOCK_INPUT; - draw_row_fringe_bitmaps (w, desired_row); - UNBLOCK_INPUT; - } + desired_row->redraw_fringe_bitmaps_p = 1; /* When a window has disappeared, make sure that no rest of full-width rows stays visible in the internal border. Could @@ -697,11 +697,26 @@ x_draw_fringe_bitmap (w, row, p) Window window = FRAME_X_WINDOW (f); GC gc = f->output_data.x->normal_gc; struct face *face = p->face; + int rowY; /* Must clip because of partially visible lines. */ - x_clip_to_row (w, row, gc); + rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); + if (p->y < rowY) + { + /* Adjust position of "bottom aligned" bitmap on partially + visible last row. */ + int oldY = row->y; + int oldVH = row->visible_height; + row->visible_height = p->h; + row->y -= rowY - p->y; + x_clip_to_row (w, row, -1, gc); + row->y = oldY; + row->visible_height = oldVH; + } + else + x_clip_to_row (w, row, -1, gc); - if (p->bx >= 0) + if (p->bx >= 0 && !p->overlay_p) { /* In case the same realized face is used for fringes and for something displayed in the text (e.g. face `region' on @@ -719,20 +734,49 @@ x_draw_fringe_bitmap (w, row, p) XSetForeground (display, face->gc, face->foreground); } - if (p->which != NO_FRINGE_BITMAP) + if (p->which) { - unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh; - Pixmap pixmap; + unsigned char *bits; + Pixmap pixmap, clipmask = (Pixmap) 0; int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f)); + XGCValues gcv; + + if (p->wd > 8) + bits = (unsigned char *)(p->bits + p->dh); + else + bits = (unsigned char *)p->bits + p->dh; /* Draw the bitmap. I believe these small pixmaps can be cached by the server. */ pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h, - face->foreground, + (p->cursor_p + ? (p->overlay_p ? face->background + : f->output_data.x->cursor_pixel) + : face->foreground), face->background, depth); + + if (p->overlay_p) + { + clipmask = XCreatePixmapFromBitmapData (display, + FRAME_X_DISPLAY_INFO (f)->root_window, + bits, p->wd, p->h, + 1, 0, 1); + gcv.clip_mask = clipmask; + gcv.clip_x_origin = p->x; + gcv.clip_y_origin = p->y; + XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv); + } + XCopyArea (display, pixmap, window, gc, 0, 0, p->wd, p->h, p->x, p->y); XFreePixmap (display, pixmap); + + if (p->overlay_p) + { + gcv.clip_mask = (Pixmap) 0; + XChangeGC (display, gc, GCClipMask, &gcv); + XFreePixmap (display, clipmask); + } } XSetClipMask (display, gc, None); @@ -936,7 +980,8 @@ static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap)); 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 *)); @@ -1974,9 +2019,10 @@ x_setup_relief_colors (s) 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); @@ -1991,10 +2037,11 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, 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) @@ -2010,10 +2057,11 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, 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) @@ -2079,15 +2127,9 @@ x_draw_glyph_string_box (s) 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 @@ -2121,7 +2163,7 @@ x_draw_glyph_string_box (s) { 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); } } @@ -2132,21 +2174,22 @@ static void 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) { @@ -2171,11 +2214,12 @@ x_draw_image_foreground (s) 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 { @@ -2184,11 +2228,12 @@ x_draw_image_foreground (s) 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 @@ -2200,15 +2245,17 @@ x_draw_image_foreground (s) { 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); } @@ -2220,21 +2267,22 @@ x_draw_image_relief (s) { 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) @@ -2250,12 +2298,17 @@ x_draw_image_relief (s) 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); } @@ -2266,21 +2319,22 @@ x_draw_image_foreground_1 (s, pixmap) 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) { @@ -2296,19 +2350,21 @@ x_draw_image_foreground_1 (s, 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 @@ -2321,14 +2377,15 @@ x_draw_image_foreground_1 (s, pixmap) 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); } @@ -2370,33 +2427,28 @@ static void 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 @@ -2435,7 +2487,19 @@ x_draw_image_glyph_string (s) } } 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; } @@ -2753,10 +2817,6 @@ x_clear_frame () XFlush (FRAME_X_DISPLAY (f)); -#ifdef USE_GTK - xg_frame_cleared (f); -#endif - UNBLOCK_INPUT; } @@ -3124,20 +3184,16 @@ x_new_focus_frame (dpyinfo, frame) /* Handle FocusIn and FocusOut state changes for FRAME. If FRAME has focus and there exists more than one frame, puts - a FOCUS_IN_EVENT into BUFP. - Returns number of events inserted into BUFP. */ + a FOCUS_IN_EVENT into *BUFP. */ -static int -x_focus_changed (type, state, dpyinfo, frame, bufp, numchars) +static void +x_focus_changed (type, state, dpyinfo, frame, bufp) 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) @@ -3147,17 +3203,12 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars) /* Don't stop displaying the initial startup message for a switch-frame event we don't need. */ - if (numchars > 0 - && GC_NILP (Vterminal_frame) + if (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; } } @@ -3183,27 +3234,24 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars) 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. */ + Returns FOCUS_IN_EVENT event in *BUFP. */ -static int -x_detect_focus_change (dpyinfo, event, bufp, numchars) +static void +x_detect_focus_change (dpyinfo, event, bufp) struct x_display_info *dpyinfo; XEvent *event; struct input_event *bufp; - int numchars; { struct frame *frame; - int nr_events = 0; frame = x_any_window_to_frame (dpyinfo, event->xany.window); - if (! frame) return nr_events; + if (! frame) + return; switch (event->type) { @@ -3217,29 +3265,20 @@ x_detect_focus_change (dpyinfo, event, bufp, numchars) if (event->xcrossing.detail != NotifyInferior && event->xcrossing.focus && ! (focus_state & FOCUS_EXPLICIT)) - nr_events = x_focus_changed ((event->type == EnterNotify - ? FocusIn : FocusOut), - FOCUS_IMPLICIT, - dpyinfo, - frame, - bufp, - numchars); + x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut), + FOCUS_IMPLICIT, + dpyinfo, frame, bufp); } break; case FocusIn: case FocusOut: - nr_events = x_focus_changed (event->type, - (event->xfocus.detail == NotifyPointer - ? FOCUS_IMPLICIT : FOCUS_EXPLICIT), - dpyinfo, - frame, - bufp, - numchars); + x_focus_changed (event->type, + (event->xfocus.detail == NotifyPointer ? + FOCUS_IMPLICIT : FOCUS_EXPLICIT), + dpyinfo, frame, bufp); break; } - - return nr_events; } @@ -3333,12 +3372,14 @@ x_find_modifier_meanings (dpyinfo) 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) @@ -3356,33 +3397,44 @@ x_find_modifier_meanings (dpyinfo) { 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. */ @@ -3584,35 +3636,39 @@ glyph_rect (f, x, y, rect) XRectangle *rect; { Lisp_Object window; - int found = 0; + struct window *w; + struct glyph_row *r, *end_row; window = window_from_coordinates (f, x, y, 0, &x, &y, 0); - if (!NILP (window)) - { - 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; + if (NILP (window)) + return 0; - for (; !found && r < end && r->enabled_p; ++r) - if (r->y >= y) - { - struct glyph *g = r->glyphs[TEXT_AREA]; - struct glyph *end = g + r->used[TEXT_AREA]; - int gx; + w = XWINDOW (window); + r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); + end_row = r + w->current_matrix->nrows - 1; - for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g) - if (gx >= x) - { - rect->width = g->pixel_width; - rect->height = r->height; - rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx); - rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y); - found = 1; - } - } + for (; r < end_row && r->enabled_p; ++r) + { + if (r->y >= y) + { + struct glyph *g = r->glyphs[TEXT_AREA]; + struct glyph *end = g + r->used[TEXT_AREA]; + int gx = r->x; + while (g < end && gx < x) + gx += g->pixel_width, ++g; + if (g < end) + { + rect->width = g->pixel_width; + rect->height = r->height; + rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx); + rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y); + return 1; + } + break; + } } - return found; + return 0; } @@ -3862,9 +3918,9 @@ x_window_to_scroll_bar (display, window_id) { 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; @@ -4221,8 +4277,6 @@ xg_scroll_callback (widget, data) 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); @@ -4236,6 +4290,8 @@ xg_scroll_callback (widget, data) previous = *p; *p = position; + if (xg_ignore_gtk_scrollbar) return; + diff = (int) (position - previous); if (diff == (int) adj->step_increment) @@ -4795,9 +4851,7 @@ x_scroll_bar_create (w, top, left, width, height) 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); @@ -4992,9 +5046,15 @@ XTset_vertical_scroll_bar (w, portion, whole, position) /* 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; @@ -5035,32 +5095,29 @@ XTset_vertical_scroll_bar (w, portion, whole, position) #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 @@ -5512,73 +5569,6 @@ x_scroll_bar_clear (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); -} - /* The main X event-reading loop - XTread_socket. */ #if 0 @@ -5605,6 +5595,11 @@ static XComposeStatus compose_status; static int temp_index; static short temp_buffer[100]; +#define STORE_KEYSYM_FOR_DEBUG(keysym) \ + if (temp_index == sizeof temp_buffer / sizeof (short)) \ + temp_index = 0; \ + temp_buffer[temp_index++] = (keysym) + /* Set this to nonzero to fake an "X I/O error" on a particular display. */ @@ -5624,15 +5619,8 @@ static struct x_display_info *next_noop_dpyinfo; f->output_data.x->saved_menu_event \ = (XEvent *) xmalloc (sizeof (XEvent)); \ bcopy (&event, f->output_data.x->saved_menu_event, size); \ - if (numchars >= 1) \ - { \ - bufp->kind = MENU_BAR_ACTIVATE_EVENT; \ - XSETFRAME (bufp->frame_or_window, f); \ - bufp->arg = Qnil; \ - bufp++; \ - count++; \ - numchars--; \ - } \ + inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \ + XSETFRAME (inev.ie.frame_or_window, f); \ } \ while (0) @@ -5674,14 +5662,13 @@ x_filter_event (dpyinfo, event) #endif #ifdef USE_GTK -static struct input_event **current_bufp; -static int *current_numcharsp; static int current_count; static int current_finish; +static struct input_event *current_hold_quit; /* This is the filter function invoked by the GTK event loop. It is invoked before the XEvent is translated to a GdkEvent, - so we have a chanse to act on the event before GTK. */ + so we have a chance to act on the event before GTK. */ static GdkFilterReturn event_handler_gdk (gxev, ev, data) GdkXEvent *gxev; @@ -5690,7 +5677,7 @@ event_handler_gdk (gxev, ev, data) { XEvent *xev = (XEvent *) gxev; - if (current_numcharsp) + if (current_count >= 0) { struct x_display_info *dpyinfo; @@ -5708,11 +5695,11 @@ event_handler_gdk (gxev, ev, data) if (! dpyinfo) current_finish = X_EVENT_NORMAL; else - current_count += handle_one_xevent (dpyinfo, - xev, - current_bufp, - current_numcharsp, - ¤t_finish); + { + current_count += + handle_one_xevent (dpyinfo, xev, ¤t_finish, + current_hold_quit); + } } else current_finish = x_dispatch_event (xev, xev->xany.display); @@ -5731,28 +5718,32 @@ event_handler_gdk (gxev, ev, data) *FINISH is zero if caller should continue reading events. *FINISH is X_EVENT_DROP if event should not be passed to the toolkit. - Events representing keys are stored in buffer *BUFP_R, - which can hold up to *NUMCHARSP characters. We return the number of characters stored into the buffer. */ static int -handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) +handle_one_xevent (dpyinfo, eventp, finish, hold_quit) struct x_display_info *dpyinfo; XEvent *eventp; - /* register */ struct input_event **bufp_r; - /* register */ int *numcharsp; int *finish; + struct input_event *hold_quit; { + union { + struct input_event ie; + struct selection_input_event sie; + } inev; int count = 0; + int do_help = 0; int nbytes = 0; struct frame *f; struct coding_system coding; - struct input_event *bufp = *bufp_r; - int numchars = *numcharsp; XEvent event = *eventp; *finish = X_EVENT_NORMAL; + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + switch (event.type) { case ClientMessage: @@ -5807,8 +5798,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) } /* Not certain about handling scroll bars here */ #endif /* 0 */ + goto done; } - else if (event.xclient.data.l[0] + + if (event.xclient.data.l[0] == dpyinfo->Xatom_wm_save_yourself) { /* Save state modify the WM_COMMAND property to @@ -5819,11 +5812,9 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) /* 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 () + if (! x_session_have_connection ()) #endif - ) { f = x_top_window_to_frame (dpyinfo, event.xclient.window); @@ -5838,41 +5829,36 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) event.xclient.window, 0, 0); } + goto done; } - else if (event.xclient.data.l[0] - == dpyinfo->Xatom_wm_delete_window) + + if (event.xclient.data.l[0] + == dpyinfo->Xatom_wm_delete_window) { - struct frame *f - = x_any_window_to_frame (dpyinfo, + f = x_any_window_to_frame (dpyinfo, event.xclient.window); + if (!f) + goto OTHER; /* May be a dialog that is to be removed */ - if (f) - { - if (numchars == 0) - abort (); - - bufp->kind = DELETE_WINDOW_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - - count += 1; - numchars -= 1; - } - else - goto OTHER; /* May be a dialog that is to be removed */ + inev.ie.kind = DELETE_WINDOW_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + goto done; } + + goto done; } - else if (event.xclient.message_type + + if (event.xclient.message_type == dpyinfo->Xatom_wm_configure_denied) { + goto done; } - else if (event.xclient.message_type - == dpyinfo->Xatom_wm_window_moved) + + if (event.xclient.message_type + == dpyinfo->Xatom_wm_window_moved) { int new_x, new_y; - struct frame *f - = x_window_to_frame (dpyinfo, event.xclient.window); + f = x_window_to_frame (dpyinfo, event.xclient.window); new_x = event.xclient.data.s[0]; new_y = event.xclient.data.s[1]; @@ -5882,45 +5868,55 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) f->left_pos = new_x; f->top_pos = new_y; } + goto done; } + #ifdef HACK_EDITRES - else if (event.xclient.message_type - == dpyinfo->Xatom_editres) + if (event.xclient.message_type + == dpyinfo->Xatom_editres) { - struct frame *f - = x_any_window_to_frame (dpyinfo, event.xclient.window); + f = x_any_window_to_frame (dpyinfo, event.xclient.window); _XEditResCheckMessages (f->output_data.x->widget, NULL, &event, NULL); + goto done; } #endif /* HACK_EDITRES */ - else if ((event.xclient.message_type - == dpyinfo->Xatom_DONE) - || (event.xclient.message_type - == dpyinfo->Xatom_PAGE)) + + if ((event.xclient.message_type + == dpyinfo->Xatom_DONE) + || (event.xclient.message_type + == dpyinfo->Xatom_PAGE)) { /* Ghostview job completed. Kill it. We could reply with "Next" if we received "Page", but we currently never do because we are interested in images, only, which should have 1 page. */ Pixmap pixmap = (Pixmap) event.xclient.data.l[1]; - struct frame *f - = x_window_to_frame (dpyinfo, event.xclient.window); + f = x_window_to_frame (dpyinfo, event.xclient.window); x_kill_gs_process (pixmap, f); expose_frame (f, 0, 0, 0, 0); + goto done; } + #ifdef USE_TOOLKIT_SCROLL_BARS /* Scroll bar callbacks send a ClientMessage from which we construct an input_event. */ - else if (event.xclient.message_type - == dpyinfo->Xatom_Scrollbar) + if (event.xclient.message_type + == dpyinfo->Xatom_Scrollbar) { - x_scroll_bar_to_input_event (&event, bufp); - ++bufp, ++count, --numchars; - goto out; + x_scroll_bar_to_input_event (&event, &inev.ie); + *finish = X_EVENT_GOTO_OUT; + goto done; } #endif /* USE_TOOLKIT_SCROLL_BARS */ - else - goto OTHER; + + f = x_any_window_to_frame (dpyinfo, event.xclient.window); + + if (!f) + goto OTHER; + + if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie)) + *finish = X_EVENT_DROP; } break; @@ -5940,19 +5936,11 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) { XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event; - if (numchars == 0) - abort (); - - bufp->kind = SELECTION_CLEAR_EVENT; - SELECTION_EVENT_DISPLAY (bufp) = eventp->display; - SELECTION_EVENT_SELECTION (bufp) = eventp->selection; - SELECTION_EVENT_TIME (bufp) = eventp->time; - bufp->frame_or_window = Qnil; - bufp->arg = Qnil; - bufp++; - - count += 1; - numchars -= 1; + 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; @@ -5961,31 +5949,19 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) 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; - if (numchars == 0) - abort (); - - bufp->kind = SELECTION_REQUEST_EVENT; - SELECTION_EVENT_DISPLAY (bufp) = eventp->display; - SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor; - SELECTION_EVENT_SELECTION (bufp) = eventp->selection; - SELECTION_EVENT_TARGET (bufp) = eventp->target; - SELECTION_EVENT_PROPERTY (bufp) = eventp->property; - SELECTION_EVENT_TIME (bufp) = eventp->time; - bufp->frame_or_window = Qnil; - bufp->arg = Qnil; - bufp++; - - count += 1; - numchars -= 1; - } + 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: @@ -6014,7 +5990,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; } goto OTHER; - break; case Expose: f = x_window_to_frame (dpyinfo, event.xexpose.window); @@ -6022,6 +5997,14 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) { 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; @@ -6116,12 +6099,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) { f->async_iconified = 1; - bufp->kind = ICONIFY_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - count++; - numchars--; + inev.ie.kind = ICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); } } goto OTHER; @@ -6138,7 +6117,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) 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 @@ -6153,12 +6132,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) if (f->iconified) { - bufp->kind = DEICONIFY_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - count++; - numchars--; + inev.ie.kind = DEICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); } else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) @@ -6171,6 +6146,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) 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 ()) @@ -6181,8 +6158,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) 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 @@ -6219,6 +6196,15 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) int copy_bufsiz = sizeof (copy_buffer); int modifiers; Lisp_Object coding_system = Qlatin_1; + Lisp_Object c; + +#ifdef USE_GTK + /* Don't pass keys to GTK. A Tab will shift focus to the + tool bar in GTK 2.4. Keys will still go to menus and + dialogs because in that case popup_activated is TRUE + (see above). */ + *finish = X_EVENT_DROP; +#endif event.xkey.state |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f), @@ -6312,49 +6298,37 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) orig_keysym = keysym; - if (numchars > 1) - { - Lisp_Object c; + /* Common for all keysym input events. */ + XSETFRAME (inev.ie.frame_or_window, f); + inev.ie.modifiers + = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers); + 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. */ - { - bufp->kind = ASCII_KEYSTROKE_EVENT; - bufp->code = keysym; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp->modifiers - = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), - modifiers); - bufp->timestamp = event.xkey.time; - bufp++; - count++; - numchars--; - } - /* Now non-ASCII. */ - else if (HASH_TABLE_P (Vx_keysym_table) - && (NATNUMP (c = Fgethash (make_number (keysym), - Vx_keysym_table, - Qnil)))) - { - bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c)) - ? ASCII_KEYSTROKE_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - bufp->code = XFASTINT (c); - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp->modifiers - = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), - modifiers); - bufp->timestamp = event.xkey.time; - bufp++; - count++; - numchars--; - } - /* Random non-modifier sorts of keysyms. */ - else if (((keysym >= XK_BackSpace && keysym <= XK_Escape) + /* First deal with keysyms which have defined + translations to characters. */ + if (keysym >= 32 && keysym < 128) + /* Avoid explicitly decoding each ASCII character. */ + { + inev.ie.kind = ASCII_KEYSTROKE_EVENT; + inev.ie.code = keysym; + goto done_keysym; + } + + /* Now non-ASCII. */ + if (HASH_TABLE_P (Vx_keysym_table) + && (NATNUMP (c = Fgethash (make_number (keysym), + Vx_keysym_table, + Qnil)))) + { + inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c)) + ? ASCII_KEYSTROKE_EVENT + : MULTIBYTE_CHAR_KEYSTROKE_EVENT); + inev.ie.code = XFASTINT (c); + goto done_keysym; + } + + /* Random non-modifier sorts of keysyms. */ + if (((keysym >= XK_BackSpace && keysym <= XK_Escape) || keysym == XK_Delete #ifdef XK_ISO_Left_Tab || (keysym >= XK_ISO_Left_Tab @@ -6435,104 +6409,80 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) <= XK_ISO_Last_Group_Lock) #endif )) - { - if (temp_index == sizeof temp_buffer / sizeof (short)) - temp_index = 0; - temp_buffer[temp_index++] = keysym; - /* make_lispy_event will convert this to a symbolic - key. */ - bufp->kind = NON_ASCII_KEYSTROKE_EVENT; - bufp->code = keysym; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp->modifiers - = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), - modifiers); - bufp->timestamp = event.xkey.time; - bufp++; - count++; - numchars--; - } - else if (numchars > nbytes) - { /* Raw bytes, not keysym. */ - register int i; - 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 - / sizeof (short))) - temp_index = 0; - temp_buffer[temp_index++] = copy_bufptr[i]; - } + { + STORE_KEYSYM_FOR_DEBUG (keysym); + /* make_lispy_event will convert this to a symbolic + key. */ + inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT; + inev.ie.code = keysym; + goto done_keysym; + } - { - /* 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 explicitly 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; - } + { /* Raw bytes, not keysym. */ + register int i; + 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++) + { + STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); + } - /* Convert the input data to a sequence of - character events. */ - for (i = 0; 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_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - bufp->code = c; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp->modifiers - = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), - modifiers); - bufp->timestamp = event.xkey.time; - bufp++; - } + { + /* 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 explicitly 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; + } - count += nchars; - numchars -= nchars; + /* Convert the input data to a sequence of + character events. */ + for (i = 0; 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); + inev.ie.kind = (SINGLE_BYTE_CHAR_P (c) + ? ASCII_KEYSTROKE_EVENT + : MULTIBYTE_CHAR_KEYSTROKE_EVENT); + inev.ie.code = c; + kbd_buffer_store_event_hold (&inev.ie, hold_quit); + } - if (keysym == NoSymbol) - break; - } - else - abort (); - } - else - abort (); + /* Previous code updated count by nchars rather than nbytes, + but that seems bogus to me. ++kfs */ + count += nbytes; + + inev.ie.kind = NO_EVENT; /* Already stored above. */ + + if (keysym == NoSymbol) + break; + } } + done_keysym: #ifdef HAVE_X_I18N /* Don't dispatch this event since XtDispatchEvent calls XFilterEvent, and two calls in a row may freeze the @@ -6553,63 +6503,41 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) #endif case EnterNotify: - { - int n; + x_detect_focus_change (dpyinfo, &event, &inev.ie); - 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); - 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) - { - /* Avoid nasty pop/raise loops. */ - if (f && (!(f->auto_raise) - || !(f->auto_lower) - || (event.xcrossing.time - enter_timestamp) > 500)) - { - x_new_focus_frame (dpyinfo, f); - enter_timestamp = event.xcrossing.time; - } - } - else if (f == dpyinfo->x_focus_frame) - x_new_focus_frame (dpyinfo, 0); + if (event.xcrossing.focus) + { + /* Avoid nasty pop/raise loops. */ + if (f && (!(f->auto_raise) + || !(f->auto_lower) + || (event.xcrossing.time - enter_timestamp) > 500)) + { + x_new_focus_frame (dpyinfo, f); + enter_timestamp = event.xcrossing.time; + } + } + 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) - note_mouse_movement (f, &event.xmotion); - goto OTHER; - } + /* EnterNotify counts as mouse movement, + so update things that depend on mouse position. */ + if (f && !f->output_data.x->hourglass_p) + note_mouse_movement (f, &event.xmotion); + goto OTHER; case FocusIn: - { - int n; - - n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); - if (n > 0) - { - bufp += n, count += n, numchars -= n; - } - } - + x_detect_focus_change (dpyinfo, &event, &inev.ie); goto OTHER; case LeaveNotify: - { - int n; - - n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); - if (n > 0) - { - bufp += n, count += n, numchars -= n; - } - } + x_detect_focus_change (dpyinfo, &event, &inev.ie); f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); if (f) @@ -6627,31 +6555,12 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) Otherwise, the startup message is cleared when the mouse leaves the frame. */ if (any_help_event_p) - { - Lisp_Object frame; - int n; - - XSETFRAME (frame, f); - help_echo_string = Qnil; - n = gen_help_event (bufp, numchars, - Qnil, frame, Qnil, Qnil, 0); - bufp += n, count += n, numchars -= n; - } - + do_help = -1; } goto OTHER; case FocusOut: - { - int n; - - n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); - if (n > 0) - { - bufp += n, count += n, numchars -= n; - } - } - + x_detect_focus_change (dpyinfo, &event, &inev.ie); goto OTHER; case MotionNotify: @@ -6689,13 +6598,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) will be selected iff it is active. */ if (WINDOWP (window) && !EQ (window, last_window) - && !EQ (window, selected_window) - && numchars > 0) + && !EQ (window, selected_window)) { - bufp->kind = SELECT_WINDOW_EVENT; - bufp->frame_or_window = window; - bufp->arg = Qnil; - ++bufp, ++count, --numchars; + inev.ie.kind = SELECT_WINDOW_EVENT; + inev.ie.frame_or_window = window; } last_window=window; @@ -6722,22 +6628,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) has changed, generate a HELP_EVENT. */ if (!NILP (help_echo_string) || !NILP (previous_help_echo_string)) - { - Lisp_Object frame; - int n; - - if (f) - XSETFRAME (frame, f); - else - frame = Qnil; - - any_help_event_p = 1; - n = gen_help_event (bufp, numchars, help_echo_string, frame, - help_echo_window, help_echo_object, - help_echo_pos); - bufp += n, count += n, numchars -= n; - } - + do_help = 1; goto OTHER; } @@ -6821,10 +6712,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) { /* If we decide we want to generate an event to be seen by the rest of Emacs, we put it here. */ - struct input_event emacs_event; int tool_bar_p = 0; - emacs_event.kind = NO_EVENT; bzero (&compose_status, sizeof (compose_status)); if (dpyinfo->grabbed @@ -6864,7 +6753,21 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) #if defined (USE_X_TOOLKIT) || defined (USE_GTK) if (! popup_activated ()) #endif - construct_mouse_click (&emacs_event, &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 @@ -6878,12 +6781,12 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) scroll bars. */ if (bar && event.xbutton.state & ControlMask) { - x_scroll_bar_handle_click (bar, &event, &emacs_event); + 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, &emacs_event); + x_scroll_bar_handle_click (bar, &event, &inev.ie); #endif /* not USE_TOOLKIT_SCROLL_BARS */ } @@ -6904,14 +6807,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) else dpyinfo->grabbed &= ~(1 << event.xbutton.button); - if (numchars >= 1 && emacs_event.kind != NO_EVENT) - { - bcopy (&emacs_event, bufp, sizeof (struct input_event)); - bufp++; - count++; - numchars--; - } - #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, @@ -6998,16 +6893,38 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) break; } - goto ret; + done: + if (inev.ie.kind != NO_EVENT) + { + kbd_buffer_store_event_hold (&inev.ie, hold_quit); + count++; + } - out: - *finish = X_EVENT_GOTO_OUT; + if (do_help + && !(hold_quit && hold_quit->kind != NO_EVENT)) + { + Lisp_Object frame; - ret: - *bufp_r = bufp; - *numcharsp = numchars; - *eventp = event; + if (f) + XSETFRAME (frame, f); + else + frame = Qnil; + + if (do_help > 0) + { + 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; + gen_help_event (Qnil, frame, Qnil, Qnil, 0); + } + count++; + } + *eventp = event; return count; } @@ -7023,28 +6940,12 @@ x_dispatch_event (event, display) Display *display; { struct x_display_info *dpyinfo; - struct input_event bufp[10]; - struct input_event *bufpp; - int numchars = 10; int finish = X_EVENT_NORMAL; - for (bufpp = bufp; bufpp != bufp + 10; bufpp++) - EVENT_INIT (*bufpp); - bufpp = bufp; - dpyinfo = x_display_info_for_display (display); if (dpyinfo) - { - int i, events; - events = handle_one_xevent (dpyinfo, - event, - &bufpp, - &numchars, - &finish); - for (i = 0; i < events; ++i) - kbd_buffer_store_event (&bufp[i]); - } + handle_one_xevent (dpyinfo, event, &finish, 0); return finish; } @@ -7054,19 +6955,16 @@ x_dispatch_event (event, display) This routine is called by the SIGIO handler. We return as soon as there are no more events to be read. - Events representing keys are stored in buffer BUFP, - which can hold up to NUMCHARS characters. We return the number of characters stored into the buffer, thus pretending to be `read'. EXPECTED is nonzero if the caller knows input is available. */ static int -XTread_socket (sd, bufp, numchars, expected) +XTread_socket (sd, expected, hold_quit) register int sd; - /* register */ struct input_event *bufp; - /* register */ int numchars; int expected; + struct input_event *hold_quit; { int count = 0; XEvent event; @@ -7085,9 +6983,6 @@ XTread_socket (sd, bufp, numchars, expected) /* So people can tell when we have read the available input. */ input_signal_count++; - if (numchars <= 0) - abort (); /* Don't think this happens. */ - ++handling_signal; /* Find the display we are supposed to read input for. @@ -7129,9 +7024,18 @@ XTread_socket (sd, bufp, numchars, expected) } #ifdef HAVE_X_SM - BLOCK_INPUT; - count += x_session_check_input (bufp, &numchars); - UNBLOCK_INPUT; + { + struct input_event inev; + BLOCK_INPUT; + /* We don't need to EVENT_INIT (inev) here, as + x_session_check_input copies an entire input_event. */ + if (x_session_check_input (&inev)) + { + kbd_buffer_store_event_hold (&inev, hold_quit); + count++; + } + UNBLOCK_INPUT; + } #endif #ifndef USE_GTK @@ -7148,11 +7052,7 @@ XTread_socket (sd, bufp, numchars, expected) #endif event_found = 1; - count += handle_one_xevent (dpyinfo, - &event, - &bufp, - &numchars, - &finish); + count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit); if (finish == X_EVENT_GOTO_OUT) goto out; @@ -7173,14 +7073,13 @@ XTread_socket (sd, bufp, numchars, expected) while (gtk_events_pending ()) { current_count = count; - current_numcharsp = &numchars; - current_bufp = &bufp; + current_hold_quit = hold_quit; gtk_main_iteration (); count = current_count; - current_bufp = 0; - current_numcharsp = 0; + current_count = -1; + current_hold_quit = 0; if (current_finish == X_EVENT_GOTO_OUT) break; @@ -7220,8 +7119,9 @@ XTread_socket (sd, bufp, numchars, expected) pending_autoraise_frame = 0; } - UNBLOCK_INPUT; --handling_signal; + UNBLOCK_INPUT; + return count; } @@ -7240,19 +7140,20 @@ XTread_socket (sd, bufp, numchars, expected) 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; @@ -7282,28 +7183,10 @@ x_draw_hollow_cursor (w, row) 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. */ @@ -7316,7 +7199,7 @@ x_draw_hollow_cursor (w, row) 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); } @@ -7388,7 +7271,7 @@ x_draw_bar_cursor (w, row, width, kind) 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, @@ -7448,6 +7331,13 @@ x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, activ w->phys_cursor_type = cursor_type; w->phys_cursor_on_p = 1; + if (glyph_row->exact_window_width_line_p + && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]) + { + glyph_row->cursor_in_fringe_p = 1; + draw_fringe_bitmap (w, glyph_row, 0); + } + else switch (cursor_type) { case HOLLOW_BOX_CURSOR: @@ -7639,11 +7529,17 @@ static Lisp_Object x_catch_errors_unwind (old_val) Lisp_Object old_val; { - Lisp_Object first; - - first = XCAR (old_val); + Lisp_Object first = XCAR (old_val); + Display *dpy = XSAVE_VALUE (first)->pointer; - 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; @@ -7854,12 +7750,41 @@ x_connection_closed (dpy, error_message) 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 + +/* 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; @@ -7876,21 +7801,6 @@ x_error_quitter (display, 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. */ @@ -7928,7 +7838,8 @@ x_new_font (f, fontname) 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); @@ -8036,11 +7947,7 @@ xim_destroy_callback (xim, client_data, call_data) 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); } } @@ -8233,70 +8140,19 @@ void x_calc_absolute_position (f) struct frame *f; { - Window child; int win_x = 0, win_y = 0; int flags = f->size_hint_flags; - int this_window; /* We have nothing to do if the current position is already for the top-left corner. */ if (! ((flags & XNegative) || (flags & YNegative))) return; - this_window = FRAME_OUTER_WINDOW (f); - - /* Find the position 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) - { - int count; - - BLOCK_INPUT; - count = x_catch_errors (FRAME_X_DISPLAY (f)); - while (1) - { - x_clear_errors (FRAME_X_DISPLAY (f)); - XTranslateCoordinates (FRAME_X_DISPLAY (f), - - /* From-window, to-window. */ - this_window, - f->output_data.x->parent_desc, - - /* From-position, to-position. */ - 0, 0, &win_x, &win_y, - - /* Child of win. */ - &child); - if (x_had_errors_p (FRAME_X_DISPLAY (f))) - { - Window newroot, newparent = 0xdeadbeef; - Window *newchildren; - unsigned int nchildren; - - if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot, - &newparent, &newchildren, &nchildren)) - break; - - XFree ((char *) newchildren); - - f->output_data.x->parent_desc = newparent; - } - else - break; - } - - x_uncatch_errors (FRAME_X_DISPLAY (f), count); - UNBLOCK_INPUT; - } - /* 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 * f->border_width - win_x - - FRAME_PIXEL_WIDTH (f) - + f->left_pos); + - FRAME_PIXEL_WIDTH (f) + f->left_pos); { int height = FRAME_PIXEL_HEIGHT (f); @@ -8318,11 +8174,7 @@ x_calc_absolute_position (f) #endif if (flags & YNegative) - f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - - 2 * f->border_width - - win_y - - height - + f->top_pos); + f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos); } /* The left_pos and top_pos @@ -8357,24 +8209,13 @@ x_set_offset (f, xoff, yoff, change_gravity) f->win_gravity = NorthWestGravity; } x_calc_absolute_position (f); - + BLOCK_INPUT; x_wm_set_size_hint (f, (long) 0, 0); modified_left = f->left_pos; modified_top = f->top_pos; -#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal, - this seems to be unnecessary and incorrect. rms, 4/17/97. */ - /* It is a mystery why we need to add the border_width here - when the frame is already visible, but experiment says we do. */ - if (change_gravity != 0) - { - modified_left += f->border_width; - modified_top += f->border_width; - } -#endif - if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A) { /* Some WMs (twm, wmaker at least) has an offset that is smaller @@ -8449,7 +8290,9 @@ x_check_expected_move (f) 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; @@ -9940,6 +9783,43 @@ x_load_font (f, fontname, size) 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)) @@ -10489,7 +10369,7 @@ x_term_init (display_name, xrm_option, resource_name) 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)) { @@ -10514,10 +10394,12 @@ x_term_init (display_name, xrm_option, resource_name) 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 @@ -10565,6 +10447,8 @@ x_term_init (display_name, xrm_option, resource_name) /* 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 @@ -10819,7 +10703,7 @@ static struct redisplay_interface x_redisplay_interface = x_update_window_end, x_cursor_to, x_flush, -#ifndef XFlush +#ifdef XFlush x_flush, #else 0, /* flush_display_optional */ @@ -10828,6 +10712,8 @@ static struct redisplay_interface x_redisplay_interface = x_get_glyph_overhangs, x_fix_overlapping_area, x_draw_fringe_bitmap, + 0, /* define_fringe_bitmap */ + 0, /* destroy_fringe_bitmap */ x_per_char_metric, x_encode_char, x_compute_glyph_string_overhangs, @@ -10874,6 +10760,11 @@ x_initialize () 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; +#endif /* Try to use interrupt input; if we can't, then start polling. */ Fset_input_mode (Qt, Qnil, Qt, Qnil); @@ -10957,6 +10848,16 @@ UNDERLINE_POSITION font properties, for example 7x13 on XFree prior 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.