/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 02, 2003
+ Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000,01,02,03,04
Free Software Foundation, Inc.
This file is part of GNU Emacs.
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)
extern Lisp_Object Vx_no_window_manager;
-extern Lisp_Object Qface, Qmouse_face, Qeql;
+extern Lisp_Object Qeql;
extern int errno;
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 *));
static void x_after_update_window_line P_ ((struct glyph_row *));
-static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
+static struct scroll_bar *x_window_to_scroll_bar P_ ((Display *, Window));
static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
enum scroll_bar_part *,
Lisp_Object *, 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. */
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;
}
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
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
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);
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)
{
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;
}
/* 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)
/* 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;
}
}
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)
{
case EnterNotify:
case LeaveNotify:
- if (event->xcrossing.detail != NotifyInferior
- && event->xcrossing.focus
- && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
- nr_events = x_focus_changed ((event->type == EnterNotify
- ? FocusIn : FocusOut),
- FOCUS_IMPLICIT,
- dpyinfo,
- frame,
- bufp,
- numchars);
+ {
+ struct frame *focus_frame = dpyinfo->x_focus_event_frame;
+ int focus_state
+ = focus_frame ? focus_frame->output_data.x->focus_state : 0;
+
+ if (event->xcrossing.detail != NotifyInferior
+ && event->xcrossing.focus
+ && ! (focus_state & FOCUS_EXPLICIT))
+ 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;
}
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. */
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;
}
/* If not, is it one of our scroll bars? */
if (! f1)
{
- struct scroll_bar *bar = x_window_to_scroll_bar (win);
+ struct scroll_bar *bar;
+
+ bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
if (bar)
{
/* Scroll bar support. */
-/* Given an X window ID, find the struct scroll_bar which manages it.
+/* Given an X window ID and a DISPLAY, find the struct scroll_bar which
+ manages it.
This can be called in GC, so we have to make sure to strip off mark
bits. */
static struct scroll_bar *
-x_window_to_scroll_bar (window_id)
+x_window_to_scroll_bar (display, window_id)
+ Display *display;
Window window_id;
{
Lisp_Object tail;
-#ifdef USE_GTK
- window_id = (Window) xg_get_scroll_id_for_window (window_id);
-#endif /* 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 && USE_TOOLKIT_SCROLL_BARS */
for (tail = Vframe_list;
XGCTYPE (tail) == Lisp_Cons;
condemned = Qnil,
! GC_NILP (bar));
bar = XSCROLL_BAR (bar)->next)
- if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
+ if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id &&
+ FRAME_X_DISPLAY (XFRAME (frame)) == display)
return XSCROLL_BAR (bar);
}
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)
}
if (part >= 0)
- {
+ {
window_being_scrolled = bar->window;
last_scroll_bar_part = part;
x_send_scroll_bar_event (bar->window, part, portion, whole);
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. */
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. */
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.kind = MENU_BAR_ACTIVATE_EVENT; \
+ XSETFRAME (inev.frame_or_window, f); \
} \
while (0)
#endif
#ifdef USE_GTK
-static struct x_display_info *current_dpyinfo;
-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;
GdkEvent *ev;
gpointer data;
{
- XEvent *xev = (XEvent*)gxev;
+ XEvent *xev = (XEvent *) gxev;
- if (current_numcharsp)
+ if (current_count >= 0)
{
+ struct x_display_info *dpyinfo;
+
+ dpyinfo = x_display_info_for_display (xev->xany.display);
+
#ifdef HAVE_X_I18N
/* Filter events for the current X input method.
GTK calls XFilterEvent but not for key press and release,
so we do it here. */
if (xev->type == KeyPress || xev->type == KeyRelease)
- if (x_filter_event (current_dpyinfo, xev))
+ if (dpyinfo && x_filter_event (dpyinfo, xev))
return GDK_FILTER_REMOVE;
#endif
- current_count += handle_one_xevent (current_dpyinfo,
- xev,
- current_bufp,
- current_numcharsp,
- ¤t_finish);
+
+ if (! dpyinfo)
+ current_finish = X_EVENT_NORMAL;
+ else
+ {
+ current_count +=
+ handle_one_xevent (dpyinfo, xev, ¤t_finish,
+ current_hold_quit);
+ }
}
else
- current_finish = x_dispatch_event (xev, GDK_DISPLAY ());
+ current_finish = x_dispatch_event (xev, xev->xany.display);
if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
return GDK_FILTER_REMOVE;
*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;
{
+ struct input_event 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);
+ inev.kind = NO_EVENT;
+ inev.arg = Qnil;
+
switch (event.type)
{
case ClientMessage:
}
/* 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
/* 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);
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.kind = DELETE_WINDOW_EVENT;
+ XSETFRAME (inev.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];
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);
+ *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))
+ *finish = X_EVENT_DROP;
}
break;
{
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.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;
}
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;
- 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.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;
+ }
break;
case PropertyNotify:
FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
}
goto OTHER;
- break;
case Expose:
f = x_window_to_frame (dpyinfo, event.xexpose.window);
/* Dispatch event to the widget. */
goto OTHER;
#else /* not USE_TOOLKIT_SCROLL_BARS */
- bar = x_window_to_scroll_bar (event.xexpose.window);
+ bar = x_window_to_scroll_bar (event.xexpose.display,
+ event.xexpose.window);
if (bar)
x_scroll_bar_expose (bar, &event);
{
f->async_iconified = 1;
- bufp->kind = ICONIFY_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp++;
- count++;
- numchars--;
+ inev.kind = ICONIFY_EVENT;
+ XSETFRAME (inev.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)
{
- bufp->kind = DEICONIFY_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp++;
- count++;
- numchars--;
+ inev.kind = DEICONIFY_EVENT;
+ XSETFRAME (inev.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
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),
&compose_status);
#endif
+ /* If not using XIM/XIC, and a compose sequence is in progress,
+ we break here. Otherwise, chars_matched is always 0. */
+ if (compose_status.chars_matched > 0 && nbytes == 0)
+ break;
+
orig_keysym = keysym;
- if (numchars > 1)
- {
- Lisp_Object c;
+ /* Common for all keysym input events. */
+ XSETFRAME (inev.frame_or_window, f);
+ inev.modifiers
+ = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
+ inev.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.kind = ASCII_KEYSTROKE_EVENT;
+ inev.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.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+ ? ASCII_KEYSTROKE_EVENT
+ : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+ inev.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
<= 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.kind = NON_ASCII_KEYSTROKE_EVENT;
+ inev.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.kind = (SINGLE_BYTE_CHAR_P (c)
+ ? ASCII_KEYSTROKE_EVENT
+ : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+ inev.code = c;
+ kbd_buffer_store_event_hold (&inev, 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.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
#endif
case EnterNotify:
- {
- int n;
+ x_detect_focus_change (dpyinfo, &event, &inev);
- 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);
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);
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
if (f)
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);
goto OTHER;
case MotionNotify:
/* Window will be selected only when it is not selected now and
last mouse movement event was not in it. Minibuffer window
will be selected iff it is active. */
- if (WINDOWP(window)
+ 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.kind = SELECT_WINDOW_EVENT;
+ inev.frame_or_window = window;
}
last_window=window;
{
#ifndef USE_TOOLKIT_SCROLL_BARS
struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xmotion.window);
+ = x_window_to_scroll_bar (event.xmotion.display,
+ event.xmotion.window);
if (bar)
x_scroll_bar_note_movement (bar, &event);
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;
}
{
/* 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
#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, &event, f);
+ }
+ if (event.type == ButtonRelease)
+ ignore_next_mouse_click_timeout = 0;
+ }
+ else
+ construct_mouse_click (&inev, &event, f);
+ }
}
}
else
{
struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xbutton.window);
+ = x_window_to_scroll_bar (event.xbutton.display,
+ event.xbutton.window);
#ifdef USE_TOOLKIT_SCROLL_BARS
/* Make the "Ctrl-Mouse-2 splits window" work for toolkit
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);
*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);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
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,
break;
}
- goto ret;
+ done:
+ if (inev.kind != NO_EVENT)
+ {
+ kbd_buffer_store_event_hold (&inev, 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;
}
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;
-
- for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
- if (dpyinfo->display == display)
- break;
+ 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;
}
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;
/* 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.
}
#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
-#ifdef USE_GTK
- /* For GTK we must use the GTK event loop. But XEvents gets passed
- to our filter function above, and then to the big event switch.
- We use a bunch of globals to communicate with our filter function,
- that is kind of ugly, but it works. */
- current_dpyinfo = dpyinfo;
-
- while (gtk_events_pending ())
- {
- current_count = count;
- current_numcharsp = &numchars;
- current_bufp = &bufp;
-
- gtk_main_iteration ();
-
- count = current_count;
- current_bufp = 0;
- current_numcharsp = 0;
-
- if (current_finish == X_EVENT_GOTO_OUT)
- goto out;
- }
-
-#else /* not USE_GTK */
+#ifndef USE_GTK
while (XPending (dpyinfo->display))
{
int finish;
#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;
}
-#endif /* USE_GTK */
+#endif /* not USE_GTK */
}
+#ifdef USE_GTK
+
+ /* For GTK we must use the GTK event loop. But XEvents gets passed
+ to our filter function above, and then to the big event switch.
+ We use a bunch of globals to communicate with our filter function,
+ that is kind of ugly, but it works.
+
+ There is no way to do one display at the time, GTK just does events
+ from all displays. */
+
+ while (gtk_events_pending ())
+ {
+ current_count = count;
+ current_hold_quit = hold_quit;
+
+ gtk_main_iteration ();
+
+ count = current_count;
+ current_count = -1;
+ current_hold_quit = 0;
+
+ if (current_finish == X_EVENT_GOTO_OUT)
+ break;
+ }
+#endif /* USE_GTK */
+
out:;
/* On some systems, an X bug causes Emacs to get no more events
pending_autoraise_frame = 0;
}
- UNBLOCK_INPUT;
--handling_signal;
+ UNBLOCK_INPUT;
+
return count;
}
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.x = window_x;
clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
clip_rect.y = max (clip_rect.y, window_y);
clip_rect.width = window_width;
struct glyph *cursor_glyph;
GC gc;
- /* Compute frame-relative coordinates from window-relative
- coordinates. */
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
- + row->ascent - w->phys_cursor_ascent);
- h = row->height - 1;
-
/* Get the glyph the cursor is on. If we can't tell because
the current matrix is invalid or such, give up. */
cursor_glyph = get_phys_cursor_glyph (w);
wd = min (FRAME_COLUMN_WIDTH (f), wd);
w->phys_cursor_width = wd;
+ /* Compute frame-relative coordinates from window-relative
+ coordinates. */
+ 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 (min (FRAME_LINE_HEIGHT (f), row->height),
+ cursor_glyph->ascent + cursor_glyph->descent);
+ if (h < row->height)
+ y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
+ h--;
+
/* The foreground of cursor_gc is typically the same as the normal
background color, which can cause the cursor box to be invisible. */
xgcv.foreground = f->output_data.x->cursor_pixel;
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,
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:
if (STRINGP (file))
{
#ifdef USE_GTK
- /* Use gtk_window_set_icon_from_file() if available,
+ /* Use gtk_window_set_icon_from_file () if available,
It's not restricted to bitmaps */
- if (xg_set_icon(f, file))
+ if (xg_set_icon (f, file))
return 0;
#endif /* USE_GTK */
bitmap_id = x_create_bitmap_from_file (f, file);
- x_create_bitmap_mask(f, bitmap_id);
+ x_create_bitmap_mask (f, bitmap_id);
}
else
{
FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
= x_create_bitmap_from_data (f, gnu_bits,
gnu_width, gnu_height);
- x_create_bitmap_mask(f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+ x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
}
/* The first time we create the GNU bitmap and mask,
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;
}
#endif
+#ifdef USE_GTK
+ if (dpyinfo)
+ xg_display_close (dpyinfo->display);
+#endif
+
/* Indicate that this display is dead. */
if (dpyinfo)
dpyinfo->display = 0;
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;
- 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);
#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
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
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;
Display *dpy = dpyinfo->display;
int try_XLoadQueryFont = 0;
int count;
- int allow_scalable_fonts_p = 0;
+ int allow_auto_scaled_font = 0;
if (size < 0)
{
- allow_scalable_fonts_p = 1;
+ allow_auto_scaled_font = 1;
size = 0;
}
((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
tem = XCDR (dpyinfo->name_list_element);
key = Fcons (Fcons (pattern, make_number (maxnames)),
- allow_scalable_fonts_p ? Qt : Qnil);
+ allow_auto_scaled_font ? Qt : Qnil);
list = Fassoc (key, tem);
if (!NILP (list))
{
{
int width = 0;
char *p = names[i];
- int average_width = -1, dashes = 0;
+ int average_width = -1, resx = 0, dashes = 0;
/* Count the number of dashes in NAMES[I]. If there are
- 14 dashes, and the field value following 12th dash
- (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
- is usually too ugly to be used for editing. Let's
- ignore it. */
+ 14 dashes, the field value following 9th dash
+ (RESOLUTION_X) is nonzero, and the field value
+ following 12th dash (AVERAGE_WIDTH) is 0, this is a
+ auto-scaled font which is usually too ugly to be used
+ for editing. Let's ignore it. */
while (*p)
if (*p++ == '-')
{
dashes++;
if (dashes == 7) /* PIXEL_SIZE field */
width = atoi (p);
+ else if (dashes == 9)
+ resx = atoi (p);
else if (dashes == 12) /* AVERAGE_WIDTH field */
average_width = atoi (p);
}
- if (allow_scalable_fonts_p
- || dashes < 14 || average_width != 0)
+ if (allow_auto_scaled_font
+ || dashes < 14 || average_width != 0 || resx == 0)
{
tem = build_string (names[i]);
if (NILP (Fassoc (tem, list)))
char **argv2 = argv;
GdkAtom atom;
- /* GTK 2.0 can only handle one display, GTK 2.2 can handle more
- than one, but this remains to be implemented. */
- if (x_initialized > 1)
- error ("Sorry, the GTK port can only handle one display.");
- ++x_initialized;
-
- for (argc = 0; argc < NUM_ARGV; ++argc)
- argv[argc] = 0;
+ if (x_initialized++ > 1)
+ {
+ /* Opening another display. If xg_display_open returns less
+ than zero, we are probably on GTK 2.0, which can only handle
+ one display. GTK 2.2 or later can handle more than one. */
+ if (xg_display_open (SDATA (display_name), &dpy) < 0)
+ error ("Sorry, this version of GTK can only handle one display");
+ }
+ else
+ {
+ for (argc = 0; argc < NUM_ARGV; ++argc)
+ argv[argc] = 0;
- argc = 0;
- argv[argc++] = initial_argv[0];
+ argc = 0;
+ argv[argc++] = initial_argv[0];
- if (! NILP (display_name))
- {
- argv[argc++] = "--display";
- argv[argc++] = SDATA (display_name);
- }
+ if (! NILP (display_name))
+ {
+ argv[argc++] = "--display";
+ argv[argc++] = SDATA (display_name);
+ }
- argv[argc++] = "--name";
- argv[argc++] = resource_name;
+ argv[argc++] = "--name";
+ argv[argc++] = resource_name;
#ifdef HAVE_X11R5
- XSetLocaleModifiers ("");
+ XSetLocaleModifiers ("");
#endif
- gtk_init (&argc, &argv2);
+ gtk_init (&argc, &argv2);
- /* gtk_init does set_locale. We must fix locale after calling it. */
- fixup_locale ();
- xg_initialize ();
+ /* gtk_init does set_locale. We must fix locale after calling it. */
+ fixup_locale ();
+ xg_initialize ();
- dpy = GDK_DISPLAY ();
+ dpy = GDK_DISPLAY ();
- /* NULL window -> events for all windows go to our function */
- gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+ /* NULL window -> events for all windows go to our function */
+ gdk_window_add_filter (NULL, event_handler_gdk, NULL);
- /* Load our own gtkrc if it exists. */
- {
- struct gcpro gcpro1, gcpro2;
- char *file = "~/.emacs.d/gtkrc";
- Lisp_Object s, abs_file;
+ /* Load our own gtkrc if it exists. */
+ {
+ struct gcpro gcpro1, gcpro2;
+ char *file = "~/.emacs.d/gtkrc";
+ Lisp_Object s, abs_file;
- GCPRO2 (s, abs_file);
- s = make_string (file, strlen (file));
- abs_file = Fexpand_file_name(s, Qnil);
+ GCPRO2 (s, abs_file);
+ s = make_string (file, strlen (file));
+ abs_file = Fexpand_file_name (s, Qnil);
- if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
- gtk_rc_parse (SDATA (abs_file));
+ if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
+ gtk_rc_parse (SDATA (abs_file));
- UNGCPRO;
- }
+ UNGCPRO;
+ }
- XSetErrorHandler (x_error_handler);
- XSetIOErrorHandler (x_io_error_quitter);
+ XSetErrorHandler (x_error_handler);
+ XSetIOErrorHandler (x_io_error_quitter);
+ }
}
#else /* not USE_GTK */
#ifdef USE_X_TOOLKIT
x_find_modifier_meanings (dpyinfo);
/* Get the scroll bar cursor. */
+#ifdef USE_GTK
+ /* We must create a GTK cursor, it is required for GTK widgets. */
+ dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
+#endif /* USE_GTK */
+
dpyinfo->vertical_scroll_bar_cursor
= XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
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
x_update_window_end,
x_cursor_to,
x_flush,
-#ifndef XFlush
+#ifdef XFlush
x_flush,
#else
0, /* flush_display_optional */
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,
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);
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.