X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/afb66a9aa83c6ff9b97d79d90fabbdf75c3aad8e..c0a04927384f3254c83a97ea4cf1c5f808324e25:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 06f4545003..bb290730c3 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -22,11 +22,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* On 4.3 these lose if they come after xterm.h. */ /* On HP-UX 8.0 signal.h loses if it comes after config.h. */ /* Putting these at the beginning seems to be standard for other .c files. */ -#include #include #include +#include + /* Need syssignal.h for various externs and definitions that may be required by some configurations for calls to signal later in this source file. */ #include "syssignal.h" @@ -51,11 +52,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef BSD #include -#include -#else /* ! defined (BSD) */ -#ifndef VMS -#include -#endif #endif /* ! defined (BSD) */ #include "systty.h" @@ -83,6 +79,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "disptab.h" #include "buffer.h" #include "window.h" +#include "keyboard.h" +#include "intervals.h" #ifdef USE_X_TOOLKIT extern XtAppContext Xt_app_con; @@ -96,12 +94,13 @@ extern void _XEditResCheckMessages (); #define x_top_window_to_frame x_window_to_frame #endif -#ifdef HAVE_X11 +#ifdef USE_X_TOOLKIT +#ifndef XtNinitialState +#define XtNinitialState "initialState" +#endif +#endif + #define XMapWindow XMapRaised /* Raise them when mapping. */ -#else /* ! defined (HAVE_X11) */ -#include -/*#include */ -#endif /* ! defined (HAVE_X11) */ #ifdef FD_SET /* We could get this from param.h, but better not to depend on finding that. @@ -141,18 +140,6 @@ static int expose_all_windows; static int expose_all_icons; -#ifndef HAVE_X11 -/* ExposeRegion events, when received, are copied into this queue - for later processing. */ - -static struct event_queue x_expose_queue; - -/* ButtonPress and ButtonReleased events, when received, - are copied into this queue for later processing. */ - -struct event_queue x_mouse_queue; -#endif /* HAVE_X11 */ - #if defined (SIGIO) && defined (FIONREAD) int BLOCK_INPUT_mask; #endif /* ! defined (SIGIO) && defined (FIONREAD) */ @@ -169,8 +156,12 @@ static FONT_TYPE *icon_font_info; /* Stuff for dealing with the main icon title. */ -extern Lisp_Object Vcommand_line_args; -char *hostname, *x_id_name; +extern Lisp_Object Vcommand_line_args, Vsystem_name; +char *x_id_name; + +/* Initial values of argv and argc. */ +extern char **initial_argv; +extern int initial_argc; /* This is the X connection that we are using. */ @@ -228,6 +219,9 @@ static int highlight; static int curs_x; static int curs_y; +/* Reusable Graphics Context for drawing a cursor in a non-default face. */ +static GC scratch_cursor_gc; + /* Mouse movement. In order to avoid asking for motion events and then throwing most @@ -261,7 +255,7 @@ static XRectangle last_mouse_glyph; to Qnil, to tell XTmouse_position to return an ordinary motion event. */ static Lisp_Object last_mouse_scroll_bar; -/* Record which buttons are currently pressed. */ +/* Record which buttons are currently pressed. */ unsigned int x_mouse_grabbed; /* This is a hack. We would really prefer that XTmouse_position would @@ -276,7 +270,9 @@ static Time last_mouse_movement_time; in its mouse-face, together with the window they apply to. As long as the mouse stays within this range, we need not redraw anything on its account. */ -static int mouse_face_beg, mouse_face_end; +static int mouse_face_beg_row, mouse_face_beg_col; +static int mouse_face_end_row, mouse_face_end_col; +static int mouse_face_past_end; static Lisp_Object mouse_face_window; static int mouse_face_face_id; @@ -284,14 +280,21 @@ static int mouse_face_face_id; gc was in progress. */ static int mouse_face_deferred_gc; -/* FRAME and X, Y position of mouse when last checked for highlighting. */ +/* FRAME and X, Y position of mouse when last checked for + highlighting. X and Y can be negative or out of range for the frame. */ static FRAME_PTR mouse_face_mouse_frame; static int mouse_face_mouse_x, mouse_face_mouse_y; /* Nonzero means defer mouse-motion highlighting. */ static int mouse_face_defer; -#ifdef HAVE_X11 +/* Incremented by XTread_socket whenever it really tries to read events. */ +#ifdef __STDC__ +static int volatile input_signal_count; +#else +static int input_signal_count; +#endif + /* `t' if a mouse button is depressed. */ extern Lisp_Object Vmouse_depressed; @@ -311,27 +314,8 @@ extern int _Xdebug; extern Lisp_Object Qface, Qmouse_face; -#else /* ! defined (HAVE_X11) */ - -/* Bit patterns for the mouse cursor. */ - -short MouseCursor[] = { - 0x0000, 0x0008, 0x0018, 0x0038, - 0x0078, 0x00f8, 0x01f8, 0x03f8, - 0x07f8, 0x00f8, 0x00d8, 0x0188, - 0x0180, 0x0300, 0x0300, 0x0000}; - -short MouseMask[] = { - 0x000c, 0x001c, 0x003c, 0x007c, - 0x00fc, 0x01fc, 0x03fc, 0x07fc, - 0x0ffc, 0x0ffc, 0x01fc, 0x03dc, - 0x03cc, 0x0780, 0x0780, 0x0300}; +static int x_noop_count; -static short grey_bits[] = { - 0x0005, 0x000a, 0x0005, 0x000a}; - -static Pixmap GreyPixmap = 0; -#endif /* ! defined (HAVE_X11) */ /* From time to time we get info on an Emacs window, here. */ @@ -353,14 +337,11 @@ static void redraw_previous_char (); static void redraw_following_char (); static unsigned int x_x_to_emacs_modifiers (); +static int fast_find_position (); static void note_mouse_highlight (); static void clear_mouse_face (); static void show_mouse_face (); -#ifndef HAVE_X11 -static void dumpqueue (); -#endif /* HAVE_X11 */ - void dumpborder (); static int XTcursor_to (); static int XTclear_end_of_line (); @@ -422,16 +403,10 @@ XTupdate_begin (f) clear_mouse_face (); } } -#ifndef HAVE_X11 - dumpqueue (); -#endif /* HAVE_X11 */ + UNBLOCK_INPUT; } -#ifndef HAVE_X11 -static void x_do_pending_expose (); -#endif - static XTupdate_end (f) struct frame *f; @@ -439,10 +414,6 @@ XTupdate_end (f) int mask; BLOCK_INPUT; -#ifndef HAVE_X11 - dumpqueue (); - x_do_pending_expose (); -#endif /* HAVE_X11 */ x_display_cursor (f, 1); @@ -610,7 +581,6 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) struct face *face = FRAME_DEFAULT_FACE (f); FONT_TYPE *font = FACE_FONT (face); GC gc = FACE_GC (face); - int gc_temporary = 0; /* HL = 3 means use a mouse face previously chosen. */ if (hl == 3) @@ -648,8 +618,11 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) /* Now override that if the cursor's on this character. */ if (hl == 2) { - if (!face->font - || (int) face->font == FACE_DEFAULT) + if ((!face->font + || (int) face->font == FACE_DEFAULT + || face->font == f->display.x->font) + && face->background == f->display.x->background_pixel + && face->foreground == f->display.x->foreground_pixel) { gc = f->display.x->cursor_gc; } @@ -660,14 +633,11 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) unsigned long mask; xgcv.background = f->display.x->cursor_pixel; - if (face == FRAME_DEFAULT_FACE (f)) - xgcv.foreground = f->display.x->cursor_foreground_pixel; - else - xgcv.foreground = face->foreground; + xgcv.foreground = face->background; /* If the glyph would be invisible, try a different foreground. */ if (xgcv.foreground == xgcv.background) - xgcv.foreground = face->background; + xgcv.foreground = face->foreground; if (xgcv.foreground == xgcv.background) xgcv.foreground = f->display.x->cursor_foreground_pixel; if (xgcv.foreground == xgcv.background) @@ -682,13 +652,18 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) xgcv.font = face->font->fid; xgcv.graphics_exposures = 0; mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; - gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f), - mask, &xgcv); + if (scratch_cursor_gc) + XChangeGC (x_current_display, scratch_cursor_gc, mask, &xgcv); + else + scratch_cursor_gc = + XCreateGC (x_current_display, window, mask, &xgcv); + gc = scratch_cursor_gc; #if 0 +/* If this code is restored, it must also reset to the default stipple + if necessary. */ if (face->stipple && face->stipple != FACE_DEFAULT) XSetStipple (x_current_display, gc, face->stipple); #endif - gc_temporary = 1; } } @@ -726,9 +701,6 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) } #endif - if (gc_temporary) - XFreeGC (x_current_display, gc); - /* We should probably check for XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS properties on the font, but let's just get the thing working, and come back to that. */ @@ -866,7 +838,6 @@ XTclear_end_of_line (first_unused) && f->phys_cursor_x < first_unused) f->phys_cursor_x = -1; -#ifdef HAVE_X11 XClearArea (x_current_display, FRAME_X_WINDOW (f), CHAR_TO_PIXEL_COL (f, curs_x), CHAR_TO_PIXEL_ROW (f, curs_y), @@ -875,14 +846,6 @@ XTclear_end_of_line (first_unused) #if 0 redraw_previous_char (f, curs_x, curs_y, highlight); #endif -#else /* ! defined (HAVE_X11) */ - XPixSet (FRAME_X_WINDOW (f), - CHAR_TO_PIXEL_COL (f, curs_x), - CHAR_TO_PIXEL_ROW (f, curs_y), - FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), - f->display.x->line_height, - f->display.x->background_pixel); -#endif /* ! defined (HAVE_X11) */ UNBLOCK_INPUT; } @@ -908,10 +871,6 @@ XTclear_frame () colors or something like that, then they should be notified. */ x_scroll_bar_clear (f); -#ifndef HAVE_X11 - dumpborder (f, 0); -#endif /* HAVE_X11 */ - XFlushQueue (); UNBLOCK_INPUT; } @@ -1198,11 +1157,7 @@ XTflash (f) /* Make audible bell. */ -#ifdef HAVE_X11 #define XRINGBELL XBell (x_current_display, 0) -#else /* ! defined (HAVE_X11) */ -#define XRINGBELL XFeep (0); -#endif /* ! defined (HAVE_X11) */ XTring_bell () { @@ -1279,51 +1234,21 @@ stufflines (n) newtop = topregion + n; length = (bottomregion - topregion) + 1; -#ifndef HAVE_X11 - dumpqueue (); -#endif /* HAVE_X11 */ - if ((length > 0) && (newtop <= flexlines)) - { -#ifdef HAVE_X11 - XCopyArea (x_current_display, FRAME_X_WINDOW (f), - FRAME_X_WINDOW (f), f->display.x->normal_gc, - intborder, CHAR_TO_PIXEL_ROW (f, topregion), - f->width * FONT_WIDTH (f->display.x->font), - length * f->display.x->line_height, intborder, - CHAR_TO_PIXEL_ROW (f, newtop)); -#else /* ! defined (HAVE_X11) */ - XMoveArea (FRAME_X_WINDOW (f), - intborder, CHAR_TO_PIXEL_ROW (f, topregion), - intborder, CHAR_TO_PIXEL_ROW (f, newtop), - f->width * FONT_WIDTH (f->display.x->font), - length * f->display.x->line_height); - /* Now we must process any ExposeRegion events that occur - if the area being copied from is obscured. - We can't let it wait because further i/d operations - may want to copy this area to another area. */ - x_read_exposes (); -#endif /* ! defined (HAVE_X11) */ - } + XCopyArea (x_current_display, FRAME_X_WINDOW (f), + FRAME_X_WINDOW (f), f->display.x->normal_gc, + intborder, CHAR_TO_PIXEL_ROW (f, topregion), + f->width * FONT_WIDTH (f->display.x->font), + length * f->display.x->line_height, intborder, + CHAR_TO_PIXEL_ROW (f, newtop)); newtop = min (newtop, (flexlines - 1)); length = newtop - topregion; if (length > 0) - { -#ifdef HAVE_X11 - XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, - CHAR_TO_PIXEL_ROW (f, topregion), - f->width * FONT_WIDTH (f->display.x->font), - n * f->display.x->line_height, False); -#else /* ! defined (HAVE_X11) */ - XPixSet (FRAME_X_WINDOW (f), - intborder, - CHAR_TO_PIXEL_ROW (f, topregion), - f->width * FONT_WIDTH (f->display.x->font), - n * f->display.x->line_height, - f->display.x->background_pixel); -#endif /* ! defined (HAVE_X11) */ - } + XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, + CHAR_TO_PIXEL_ROW (f, topregion), + f->width * FONT_WIDTH (f->display.x->font), + n * f->display.x->line_height, False); } /* Perform a delete-lines operation, deleting N lines @@ -1340,31 +1265,16 @@ scraplines (n) if (curs_y >= flexlines) return; -#ifndef HAVE_X11 - dumpqueue (); -#endif /* HAVE_X11 */ - if ((curs_y + n) >= flexlines) { if (flexlines >= (curs_y + 1)) - { -#ifdef HAVE_X11 - XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, - CHAR_TO_PIXEL_ROW (f, curs_y), - f->width * FONT_WIDTH (f->display.x->font), - (flexlines - curs_y) * f->display.x->line_height, False); -#else /* ! defined (HAVE_X11) */ - XPixSet (FRAME_X_WINDOW (f), - intborder, CHAR_TO_PIXEL_ROW (f, curs_y), - f->width * FONT_WIDTH (f->display.x->font), - (flexlines - curs_y) * f->display.x->line_height, - f->display.x->background_pixel); -#endif /* ! defined (HAVE_X11) */ - } + XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, + CHAR_TO_PIXEL_ROW (f, curs_y), + f->width * FONT_WIDTH (f->display.x->font), + (flexlines - curs_y) * f->display.x->line_height, False); } else { -#ifdef HAVE_X11 XCopyArea (x_current_display, FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), f->display.x->normal_gc, intborder, @@ -1377,23 +1287,6 @@ scraplines (n) CHAR_TO_PIXEL_ROW (f, flexlines - n), f->width * FONT_WIDTH (f->display.x->font), n * f->display.x->line_height, False); -#else /* ! defined (HAVE_X11) */ - XMoveArea (FRAME_X_WINDOW (f), - intborder, - CHAR_TO_PIXEL_ROW (f, curs_y + n), - intborder, CHAR_TO_PIXEL_ROW (f, curs_y), - f->width * FONT_WIDTH (f->display.x->font), - (flexlines - (curs_y + n)) * f->display.x->line_height); - /* Now we must process any ExposeRegion events that occur - if the area being copied from is obscured. - We can't let it wait because further i/d operations - may want to copy this area to another area. */ - x_read_exposes (); - XPixSet (FRAME_X_WINDOW (f), intborder, - CHAR_TO_PIXEL_ROW (f, flexlines - n), - f->width * FONT_WIDTH (f->display.x->font), - n * f->display.x->line_height, f->display.x->background_pixel); -#endif /* ! defined (HAVE_X11) */ } } @@ -1445,19 +1338,6 @@ dumprectangle (f, left, top, cols, rows) /* Express rectangle as four edges, instead of position-and-size. */ bottom = top + rows; right = left + cols; - -#ifndef HAVE_X11 /* Window manger does this for X11. */ - { - int intborder = f->display.x->internal_border_width; - - /* If the rectangle includes any of the internal border area, - redisplay the border emphasis. */ - if (top < intborder || left < intborder - || bottom > intborder + f->height * f->display.x->line_height - || right > intborder + f->width * f->display.x->line_height) - dumpborder (f, 0); - } -#endif /* not HAVE_X11 Window manger does this for X11. */ /* Convert rectangle edges in pixels to edges in chars. Round down for left and top, up for right and bottom. */ @@ -1516,99 +1396,7 @@ dumprectangle (f, left, top, cols, rows) if (cursor_cleared) x_display_cursor (f, 1); } - -#ifndef HAVE_X11 -/* Process all queued ExposeRegion events. */ - -static void -dumpqueue () -{ - register int i; - XExposeRegionEvent r; - - while (dequeue_event (&r, &x_expose_queue)) - { - struct frame *f = x_window_to_frame (r.window); - if (f->display.x->icon_desc == r.window) - refreshicon (f); - else - dumprectangle (f, r.x, r.y, r.width, r.height); - } - XFlushQueue (); -} -#endif /* HAVE_X11 */ -/* Process all expose events that are pending, for X10. - Redraws the cursor if necessary on any frame that - is not in the process of being updated with update_frame. */ - -#ifndef HAVE_X11 -static void -x_do_pending_expose () -{ - int mask; - struct frame *f; - Lisp_Object tail, frame; - - if (expose_all_windows) - { - expose_all_windows = 0; - for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) - { - register int temp_width, temp_height; - int intborder; - - frame = XCONS (tail)->car; - if (XGCTYPE (frame) != Lisp_Frame) - continue; - f = XFRAME (frame); - if (! FRAME_X_P (f)) - continue; - if (!f->async_visible) - continue; - if (!f->display.x->needs_exposure) - continue; - - intborder = f->display.x->internal_border_width; - - clear_cursor (f); - XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo); - temp_width = ((windowinfo.width - 2 * intborder - - f->display.x->v_scroll_bar_width) - / FONT_WIDTH (f->display.x->font)); - temp_height = ((windowinfo.height- 2 * intborder - - f->display.x->h_scroll_bar_height) - / f->display.x->line_height); - if (temp_width != f->width || temp_height != f->height) - { - change_frame_size (f, max (1, temp_height), - max (1, temp_width), 0, 1); - x_resize_scroll_bars (f); - } - f->display.x->left_pos = windowinfo.x; - f->display.x->top_pos = windowinfo.y; - dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f)); -#if 0 - dumpborder (f, 0); -#endif /* ! 0 */ - f->display.x->needs_exposure = 0; - if (updating_frame != f) - x_display_cursor (f, 1); - XFlushQueue (); - } - } - else - /* Handle any individual-rectangle expose events queued - for various windows. */ -#ifdef HAVE_X11 - ; -#else /* ! defined (HAVE_X11) */ - dumpqueue (); -#endif /* ! defined (HAVE_X11) */ -} -#endif - -#ifdef HAVE_X11 static void frame_highlight (frame) struct frame *frame; @@ -1638,50 +1426,6 @@ frame_unhighlight (frame) UNBLOCK_INPUT; x_display_cursor (frame, 1); } -#else /* ! defined (HAVE_X11) */ -/* Dump the border-emphasis of frame F. - If F is selected, this is a lining of the same color as the border, - just within the border, occupying a portion of the internal border. - If F is not selected, it is background in the same place. - If ALWAYS is 0, don't bother explicitly drawing if it's background. - - ALWAYS = 1 is used when a frame becomes selected or deselected. - In that case, we also turn the cursor off and on again - so it will appear in the proper shape (solid if selected; else hollow.) */ - -static void -dumpborder (f, always) - struct frame *f; - int always; -{ - int thickness = f->display.x->internal_border_width / 2; - int width = PIXEL_WIDTH (f); - int height = PIXEL_HEIGHT (f); - int pixel; - - if (f != selected_frame) - { - if (!always) - return; - - pixel = f->display.x->background_pixel; - } - else - { - pixel = f->display.x->border_pixel; - } - - XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel); - XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel); - XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width, - thickness, pixel); - XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness, - height, pixel); - - if (always) - x_display_cursor (f, 1); -} -#endif /* ! defined (HAVE_X11) */ static void XTframe_rehighlight (); @@ -1909,25 +1653,8 @@ x_emacs_to_x_modifiers (state) | ((state & ctrl_modifier) ? ControlMask : 0) | ((state & meta_modifier) ? x_meta_mod_mask : 0)); } - -/* Return true iff KEYSYM is a vendor-specific keysym that we should - return as a function key. If you add a keysym to this, you should - make sure that the tables make_lispy_event uses contain a suitable - name for it. */ -static int -x_is_vendor_fkey (sym) - KeySym sym; -{ - return 0 -#ifdef DXK_Remove - || (sym == DXK_Remove) -#endif - ; -} - /* Mouse clicks and mouse movement. Rah. */ -#ifdef HAVE_X11 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle @@ -2008,21 +1735,6 @@ construct_mouse_click (result, event, f) ? up_modifier : down_modifier)); - /* Notice if the mouse is still grabbed. */ - if (event->type == ButtonPress) - { - if (! x_mouse_grabbed) - Vmouse_depressed = Qt; - x_mouse_grabbed |= (1 << event->button); - last_mouse_frame = f; - } - else if (event->type == ButtonRelease) - { - x_mouse_grabbed &= ~(1 << event->button); - if (!x_mouse_grabbed) - Vmouse_depressed = Qnil; - } - { int row, column; @@ -2076,11 +1788,30 @@ note_mouse_movement (frame, event) { last_mouse_movement_time = event->time; + if (event->window != FRAME_X_WINDOW (frame)) + { + mouse_moved = 1; + last_mouse_scroll_bar = Qnil; + + note_mouse_highlight (frame, -1, -1); + + /* Ask for another mouse motion event. */ + { + int dummy; + Window dummy_window; + + XQueryPointer (event->display, FRAME_X_WINDOW (frame), + &dummy_window, &dummy_window, + &dummy, &dummy, &dummy, &dummy, + (unsigned int *) &dummy); + } + } + /* Has the mouse moved off the glyph it was on at the last sighting? */ - if (event->x < last_mouse_glyph.x - || event->x >= last_mouse_glyph.x + last_mouse_glyph.width - || event->y < last_mouse_glyph.y - || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) + else if (event->x < last_mouse_glyph.x + || event->x >= last_mouse_glyph.x + last_mouse_glyph.width + || event->y < last_mouse_glyph.y + || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) { mouse_moved = 1; last_mouse_scroll_bar = Qnil; @@ -2090,9 +1821,10 @@ note_mouse_movement (frame, event) /* Ask for another mouse motion event. */ { int dummy; + Window dummy_window; - XQueryPointer (event->display, event->window, - (Window *) &dummy, (Window *) &dummy, + XQueryPointer (event->display, FRAME_X_WINDOW (frame), + &dummy_window, &dummy_window, &dummy, &dummy, &dummy, &dummy, (unsigned int *) &dummy); } @@ -2103,9 +1835,10 @@ note_mouse_movement (frame, event) event the next time the mouse moves and we can see if it's *still* on the same glyph. */ int dummy; + Window dummy_window; - XQueryPointer (event->display, event->window, - (Window *) &dummy, (Window *) &dummy, + XQueryPointer (event->display, FRAME_X_WINDOW (frame), + &dummy_window, &dummy_window, &dummy, &dummy, &dummy, &dummy, (unsigned int *) &dummy); } @@ -2116,7 +1849,8 @@ static int disable_mouse_highlight; /* Take proper action when the mouse has moved to position X, Y on frame F as regards highlighting characters that have mouse-face properties. - Also dehighlighting chars where the mouse was before. */ + Also dehighlighting chars where the mouse was before. + X and Y can be negative or out of range. */ static void note_mouse_highlight (f, x, y) @@ -2157,7 +1891,8 @@ note_mouse_highlight (f, x, y) /* Are we in a window whose display is up to date? And verify the buffer's text has not changed. */ - if (WINDOWP (window) && portion == 0 + if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0 + && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f) && EQ (w->window_end_valid, w->buffer) && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))) { @@ -2170,9 +1905,14 @@ note_mouse_highlight (f, x, y) break; pos = ptr[i]; /* Is it outside the displayed active region (if any)? */ - if (pos > 0 - && ! (EQ (window, mouse_face_window) - && pos >= mouse_face_beg && pos < mouse_face_end)) + if (pos <= 0) + clear_mouse_face (); + else if (! (EQ (window, mouse_face_window) + && row >= mouse_face_beg_row + && row <= mouse_face_end_row + && (row > mouse_face_beg_row || column >= mouse_face_beg_col) + && (row < mouse_face_end_row || column < mouse_face_end_col + || mouse_face_past_end))) { Lisp_Object mouse_face, overlay, position; Lisp_Object *overlay_vec; @@ -2204,7 +1944,8 @@ note_mouse_highlight (f, x, y) /* Put all the overlays we want in a vector in overlay_vec. Store the length in len. */ - noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &ignor1); + noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, + NULL, NULL); noverlays = sort_overlays (overlay_vec, noverlays, w); /* Find the highest priority overlay that has a mouse-face prop. */ @@ -2234,8 +1975,11 @@ note_mouse_highlight (f, x, y) before = Foverlay_start (overlay); after = Foverlay_end (overlay); /* Record this as the current active region. */ - mouse_face_beg = XFASTINT (before); - mouse_face_end = XFASTINT (after); + fast_find_position (window, before, &mouse_face_beg_col, + &mouse_face_beg_row); + mouse_face_past_end + = !fast_find_position (window, after, &mouse_face_end_col, + &mouse_face_end_row); mouse_face_window = window; mouse_face_face_id = compute_char_face (f, w, pos, 0, 0, &ignore, pos + 1, 1); @@ -2263,8 +2007,11 @@ note_mouse_highlight (f, x, y) = Fnext_single_property_change (position, Qmouse_face, w->buffer, end); /* Record this as the current active region. */ - mouse_face_beg = XFASTINT (before); - mouse_face_end = XFASTINT (after); + fast_find_position (window, before, &mouse_face_beg_col, + &mouse_face_beg_row); + mouse_face_past_end + = !fast_find_position (window, after, &mouse_face_end_col, + &mouse_face_end_row); mouse_face_window = window; mouse_face_face_id = compute_char_face (f, w, pos, 0, 0, @@ -2277,8 +2024,6 @@ note_mouse_highlight (f, x, y) ZV = ozv; current_buffer = obuf; } - else if (pos <= 0) - clear_mouse_face (); } } @@ -2287,7 +2032,9 @@ note_mouse_highlight (f, x, y) This assumes display in WINDOW is up to date. If POS is above start of WINDOW, return coords of start of first screen line. - If POS is after end of WINDOW, return coords of end of last screen line. */ + If POS is after end of WINDOW, return coords of end of last screen line. + + Value is 1 if POS is in range, 0 if it was off screen. */ static int fast_find_position (window, pos, columnp, rowp) @@ -2298,7 +2045,7 @@ fast_find_position (window, pos, columnp, rowp) struct window *w = XWINDOW (window); FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); int i; - int row; + int row = 0; int left = w->left; int top = w->top; int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w); @@ -2306,6 +2053,7 @@ fast_find_position (window, pos, columnp, rowp) int *charstarts; int lastcol; + /* Find the right row. */ for (i = 0; i < height; i++) @@ -2317,6 +2065,7 @@ fast_find_position (window, pos, columnp, rowp) row = i; } + /* Find the right column with in it. */ charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row]; lastcol = left; for (i = 0; i < width; i++) @@ -2328,6 +2077,8 @@ fast_find_position (window, pos, columnp, rowp) return 1; } else if (charstarts[left + i] > pos) + break; + else if (charstarts[left + i] > 0) lastcol = left + i; } @@ -2343,30 +2094,30 @@ static void show_mouse_face (hl) int hl; { - int begcol, begrow, endcol, endrow; struct window *w = XWINDOW (mouse_face_window); int width = window_internal_width (w); FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); int i; - int curs_x = f->phys_cursor_x; - int curs_y = f->phys_cursor_y; int cursor_off = 0; + int old_curs_x = curs_x; + int old_curs_y = curs_y; - fast_find_position (mouse_face_window, mouse_face_beg, - &begcol, &begrow); - fast_find_position (mouse_face_window, mouse_face_end, - &endcol, &endrow); + /* Set these variables temporarily + so that if we have to turn the cursor off and on again + we will put it back at the same place. */ + curs_x = f->phys_cursor_x; + curs_y = f->phys_cursor_y; - for (i = begrow; i <= endrow; i++) + for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++) { - int column = (i == begrow ? begcol : w->left); - int endcolumn = (i == endrow ? endcol : w->left + width); - endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i] - w->left); + int column = (i == mouse_face_beg_row ? mouse_face_beg_col : w->left); + int endcolumn = (i == mouse_face_end_row ? mouse_face_end_col : w->left + width); + endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]); /* If the cursor's in the text we are about to rewrite, turn the cursor off. */ if (i == curs_y - && (curs_x >= begrow - 1 || curs_x <= endrow)) + && curs_x >= mouse_face_beg_col - 1 && curs_x <= mouse_face_end_col) { x_display_cursor (f, 0); cursor_off = 1; @@ -2385,6 +2136,9 @@ show_mouse_face (hl) if (cursor_off) x_display_cursor (f, 1); + curs_x = old_curs_x; + curs_y = old_curs_y; + /* Change the mouse cursor according to the value of HL. */ if (hl > 0) XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), f->display.x->cross_cursor); @@ -2401,8 +2155,8 @@ clear_mouse_face () if (! NILP (mouse_face_window)) show_mouse_face (0); - mouse_face_beg = -1; - mouse_face_end = -1; + mouse_face_beg_row = mouse_face_beg_col = -1; + mouse_face_end_row = mouse_face_end_col = -1; mouse_face_window = Qnil; } @@ -2485,7 +2239,8 @@ XTmouse_position (f, bar_window, part, x, y, time) win = root; - if (x_mouse_grabbed) + if (x_mouse_grabbed && last_mouse_frame + && FRAME_LIVE_P (last_mouse_frame)) { /* If mouse was grabbed on a frame, give coords for that frame even if the mouse is now outside it. */ @@ -2573,10 +2328,6 @@ XTmouse_position (f, bar_window, part, x, y, time) UNBLOCK_INPUT; } - -#else /* ! defined (HAVE_X11) */ -#define XEvent XKeyPressedEvent -#endif /* ! defined (HAVE_X11) */ /* Scroll bar support. */ @@ -2864,7 +2615,10 @@ XTset_vertical_scroll_bar (window, portion, whole, position) /* Where should this scroll bar be, pixelwise? */ int pixel_top = CHAR_TO_PIXEL_ROW (f, top); int pixel_left = CHAR_TO_PIXEL_COL (f, left); - int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f); + int pixel_width + = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0 + ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f) + : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->display.x->font))); int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height); struct scroll_bar *bar; @@ -3140,9 +2894,10 @@ x_scroll_bar_note_movement (bar, event) moves and we can see *still* on the same position. */ { int dummy; + Window dummy_window; XQueryPointer (event->xmotion.display, event->xmotion.window, - (Window *) &dummy, (Window *) &dummy, + &dummy_window, &dummy_window, &dummy, &dummy, &dummy, &dummy, (unsigned int *) &dummy); } @@ -3233,8 +2988,7 @@ x_scroll_bar_clear (f) { Lisp_Object bar; - for (bar = FRAME_SCROLL_BARS (f); - XTYPE (bar) == Lisp_Vector; + for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar); bar = XSCROLL_BAR (bar)->next) XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)), 0, 0, 0, 0, True); @@ -3279,7 +3033,68 @@ process_expose_from_menu (event) UNBLOCK_INPUT; } + +/* 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 (event) + XEvent *event; +{ + struct selection_event_queue *queue_tmp + = (struct selection_event_queue *) malloc (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 () +{ + while (queue != NULL) + { + struct selection_event_queue *queue_tmp = queue; + XPutBackEvent (XDISPLAY &queue_tmp->event); + queue = queue_tmp->next; + free ((char *)queue_tmp); + } +} + +/* Start queuing SelectionRequest events. */ + +void +x_start_queuing_selection_requests () +{ + x_queue_selection_requests++; +} + +/* Stop queuing SelectionRequest events. */ +void +x_stop_queuing_selection_requests () +{ + x_queue_selection_requests--; + x_unqueue_events (); +} /* The main X event-reading loop - XTread_socket. */ @@ -3358,7 +3173,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected) interrupt_input_pending = 0; BLOCK_INPUT; - + + /* So people can tell when we have read the available input. */ + input_signal_count++; + if (numchars <= 0) abort (); /* Don't think this happens. */ @@ -3389,7 +3207,6 @@ XTread_socket (sd, bufp, numchars, waitp, expected) switch (event.type) { -#ifdef HAVE_X11 case ClientMessage: { if (event.xclient.message_type == Xatom_wm_protocols @@ -3398,13 +3215,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected) if (event.xclient.data.l[0] == Xatom_wm_take_focus) { f = x_window_to_frame (event.xclient.window); -#if 0 /* x_focus_on_frame is a no-op anyway. */ + /* Since we set WM_TAKE_FOCUS, we must call + XSetInputFocus explicitly. But not if f is null, + since that might be an event for a deleted frame. */ if (f) - x_focus_on_frame (f); - else -#endif - /* Since we set WM_TAKE_FOCUS, we must call - XSetInputFocus explicitly. */ XSetInputFocus (event.xclient.display, event.xclient.window, RevertToPointerRoot, @@ -3420,6 +3234,17 @@ XTread_socket (sd, bufp, numchars, waitp, expected) a keyboard or mouse event arrives. */ if (numchars > 0) { + /* This is just so we only give real data once + for a single Emacs process. */ + if (x_top_window_to_frame (event.xclient.window) + == selected_frame) + XSetCommand (x_current_display, + event.xclient.window, + initial_argv, initial_argc); + else + XSetCommand (x_current_display, + event.xclient.window, + 0, 0); } } else if (event.xclient.data.l[0] == Xatom_wm_delete_window) @@ -3502,24 +3327,27 @@ XTread_socket (sd, bufp, numchars, waitp, expected) if (!x_window_to_frame (event.xselectionrequest.owner)) goto OTHER; #endif /* USE_X_TOOLKIT */ - { - XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event; + if (x_queue_selection_requests) + x_queue_event (&event); + else + { + XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event; - if (numchars == 0) - abort (); + 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++; + 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++; - count += 1; - numchars -= 1; - } + count += 1; + numchars -= 1; + } break; case PropertyNotify: @@ -3531,9 +3359,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected) break; case ReparentNotify: - f = x_window_to_frame (event.xreparent.window); + f = x_top_window_to_frame (event.xreparent.window); if (f) - f->display.x->parent_desc = event.xreparent.parent; + { + int x, y; + f->display.x->parent_desc = event.xreparent.parent; + x_real_positions (f, &x, &y); + f->display.x->left_pos = x; + f->display.x->top_pos = y; + } break; case Expose: @@ -3586,55 +3420,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) source area was completely available */ break; -#else /* ! defined (HAVE_X11) */ - case ExposeWindow: - if (event.subwindow != 0) - break; /* duplicate event */ - f = x_window_to_frame (event.window); - if (event.window == f->display.x->icon_desc) - { - refreshicon (f); - f->async_iconified = 1; - } - if (event.window == FRAME_X_WINDOW (f)) - { - /* Say must check all windows' needs_exposure flags. */ - expose_all_windows = 1; - f->display.x->needs_exposure = 1; - f->async_visible = 1; - } - break; - - case ExposeRegion: - if (event.subwindow != 0) - break; /* duplicate event */ - f = x_window_to_frame (event.window); - if (event.window == f->display.x->icon_desc) - { - refreshicon (f); - break; - } - /* If window already needs full redraw, ignore this rectangle. */ - if (expose_all_windows && f->display.x->needs_exposure) - break; - /* Put the event on the queue of rectangles to redraw. */ - if (enqueue_event (&event, &x_expose_queue)) - /* If it is full, we can't record the rectangle, - so redraw this entire window. */ - { - /* Say must check all windows' needs_exposure flags. */ - expose_all_windows = 1; - f->display.x->needs_exposure = 1; - } - break; - - case ExposeCopy: - /* This should happen only when we are expecting it, - in x_read_exposes. */ - abort (); -#endif /* ! defined (HAVE_X11) */ -#ifdef HAVE_X11 case UnmapNotify: f = x_any_window_to_frame (event.xunmap.window); if (f) /* F may no longer exist if @@ -3678,17 +3464,6 @@ XTread_socket (sd, bufp, numchars, waitp, expected) case VisibilityNotify: break; -#else /* ! defined (HAVE_X11) */ - case UnmapWindow: - f = x_window_to_frame (event.window); - if (event.window == f->display.x->icon_desc) - f->async_iconified = 0; - if (event.window == FRAME_X_WINDOW (f)) - f->async_visible = 0; - break; -#endif /* ! defined (HAVE_X11) */ - -#ifdef HAVE_X11 case KeyPress: f = x_any_window_to_frame (event.xkey.window); @@ -3713,11 +3488,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) XLookupString (&event.xkey, copy_buffer, 80, &keysym, &compose_status); - /* Strip off the vendor-specific keysym bit, and take a shot - at recognizing the codes. HP servers have extra keysyms - that fit into the MiscFunctionKey category. */ orig_keysym = keysym; - keysym &= ~(1<<28); if (numchars > 1) { @@ -3774,7 +3545,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected) #endif || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ - || x_is_vendor_fkey (orig_keysym)) + /* Any "vendor-specific" key is ok. */ + || (orig_keysym & (1 << 28))) && ! (IsModifierKey (orig_keysym) #ifndef HAVE_X11R5 #ifdef XK_Mode_switch @@ -3825,56 +3597,6 @@ XTread_socket (sd, bufp, numchars, waitp, expected) abort (); } break; -#else /* ! defined (HAVE_X11) */ - case KeyPressed: - { - register char *where_mapping; - - f = x_window_to_frame (event.window); - /* Ignore keys typed on icon windows. */ - if (f != 0 && event.window == f->display.x->icon_desc) - break; - where_mapping = XLookupMapping (&event, &nbytes); - /* Nasty fix for arrow keys */ - if (!nbytes && IsCursorKey (event.detail & 0xff)) - { - switch (event.detail & 0xff) - { - case KC_CURSOR_LEFT: - where_mapping = "\002"; - break; - case KC_CURSOR_RIGHT: - where_mapping = "\006"; - break; - case KC_CURSOR_UP: - where_mapping = "\020"; - break; - case KC_CURSOR_DOWN: - where_mapping = "\016"; - break; - } - nbytes = 1; - } - if (numchars - nbytes > 0) - { - register int i; - - for (i = 0; i < nbytes; i++) - { - bufp->kind = ascii_keystroke; - bufp->code = where_mapping[i]; - XSET (bufp->time, Lisp_Int, event.xkey.time); - XSET (bufp->frame_or_window, Lisp_Frame, f); - bufp++; - } - count += nbytes; - numchars -= nbytes; - } - } - break; -#endif /* ! defined (HAVE_X11) */ - -#ifdef HAVE_X11 /* Here's a possible interpretation of the whole FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a @@ -3898,6 +3620,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected) } else if (f == x_focus_frame) x_new_focus_frame (0); + /* EnterNotify counts as mouse movement, + so update things that depend on mouse position. */ + if (f) + note_mouse_movement (f, &event.xmotion); #ifdef USE_X_TOOLKIT goto OTHER; #endif /* USE_X_TOOLKIT */ @@ -3916,26 +3642,28 @@ XTread_socket (sd, bufp, numchars, waitp, expected) case LeaveNotify: - f = x_any_window_to_frame (event.xcrossing.window); - - if (f == mouse_face_mouse_frame) - /* If we move outside the frame, - then we're certainly no longer on any text in the frame. */ - clear_mouse_face (); - - if (event.xcrossing.focus) - { - if (! x_focus_event_frame) - x_new_focus_frame (0); - else - x_new_focus_frame (f); - } - else + f = x_top_window_to_frame (event.xcrossing.window); + if (f) { - if (f == x_focus_event_frame) - x_focus_event_frame = 0; - if (f == x_focus_frame) - x_new_focus_frame (0); + if (f == mouse_face_mouse_frame) + /* If we move outside the frame, + then we're certainly no longer on any text in the frame. */ + clear_mouse_face (); + + if (event.xcrossing.focus) + { + if (! x_focus_event_frame) + x_new_focus_frame (0); + else + x_new_focus_frame (f); + } + else + { + if (f == x_focus_event_frame) + x_focus_event_frame = 0; + if (f == x_focus_frame) + x_new_focus_frame (0); + } } #ifdef USE_X_TOOLKIT goto OTHER; @@ -3954,46 +3682,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected) #endif /* USE_X_TOOLKIT */ break; -#else /* ! defined (HAVE_X11) */ - - case EnterWindow: - if ((event.detail & 0xFF) == 1) - break; /* Coming from our own subwindow */ - if (event.subwindow != 0) - break; /* Entering our own subwindow. */ - + case MotionNotify: { - f = x_window_to_frame (event.window); - x_mouse_frame = f; - - x_new_focus_frame (f); - } - break; - - case LeaveWindow: - if ((event.detail & 0xFF) == 1) - break; /* Entering our own subwindow */ - if (event.subwindow != 0) - break; /* Leaving our own subwindow. */ - - x_mouse_frame = 0; - if (x_focus_frame == 0 - && x_input_frame != 0 - && x_input_frame == x_window_to_frame (event.window) - && event.window == FRAME_X_WINDOW (x_input_frame)) - { - f = x_input_frame; - x_input_frame = 0; - if (f) - frame_unhighlight (f); - } - break; -#endif /* ! defined (HAVE_X11) */ - -#ifdef HAVE_X11 - case MotionNotify: - { - if (x_mouse_grabbed) + if (x_mouse_grabbed && last_mouse_frame + && FRAME_LIVE_P (last_mouse_frame)) f = last_mouse_frame; else f = x_window_to_frame (event.xmotion.window); @@ -4012,16 +3704,23 @@ XTread_socket (sd, bufp, numchars, waitp, expected) clear_mouse_face (); } } +#if 0 /* This should be unnecessary, since the toolkit has no use + for motion events that happen outside of the menu event loop, + and it seems to cause the bug that mouse events stop coming + after a while. */ #ifdef USE_X_TOOLKIT goto OTHER; #endif /* USE_X_TOOLKIT */ +#endif break; case ConfigureNotify: f = x_any_window_to_frame (event.xconfigure.window); #ifdef USE_X_TOOLKIT if (f +#if 0 && ! event.xconfigure.send_event +#endif && (event.xconfigure.window == XtWindow (f->display.x->widget))) { Window win, child; @@ -4052,6 +3751,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected) f->display.x->pixel_height = event.xconfigure.height; f->display.x->left_pos = event.xconfigure.x; f->display.x->top_pos = event.xconfigure.y; + + /* What we have now is the position of Emacs's own window. + Convert that to the position of the window manager window. */ + { + int x, y; + x_real_positions (f, &x, &y); + f->display.x->left_pos = x; + f->display.x->top_pos = y; + } } goto OTHER; #else /* not USE_X_TOOLKIT */ @@ -4103,6 +3811,22 @@ XTread_socket (sd, bufp, numchars, waitp, expected) f->display.x->pixel_height = event.xconfigure.height; f->display.x->left_pos = event.xconfigure.x; f->display.x->top_pos = event.xconfigure.y; + + /* What we have now is the position of Emacs's own window. + Convert that to the position of the window manager window. */ + { + int x, y; + x_real_positions (f, &x, &y); + f->display.x->left_pos = x; + f->display.x->top_pos = y; + if (y != event.xconfigure.y) + { + /* Since the WM decorations come below top_pos now, + we must put them below top_pos in the future. */ + f->display.x->win_gravity = NorthWestGravity; + x_wm_set_size_hint (f, 0, 0); + } + } } #endif /* not USE_X_TOOLKIT */ break; @@ -4115,6 +3839,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected) struct input_event emacs_event; emacs_event.kind = no_event; + bzero (&compose_status, sizeof (compose_status)); + f = x_window_to_frame (event.xbutton.window); if (f) { @@ -4123,25 +3849,35 @@ XTread_socket (sd, bufp, numchars, waitp, expected) } else { - struct scroll_bar *bar = - x_window_to_scroll_bar (event.xbutton.window); + struct scroll_bar *bar + = x_window_to_scroll_bar (event.xbutton.window); if (bar) x_scroll_bar_handle_click (bar, &event, &emacs_event); #ifdef USE_X_TOOLKIT else { - f = x_any_window_to_frame (event.xbutton.window); - if (f && event.type == ButtonPress) - goto OTHER; -#if 0 - construct_menu_click (&emacs_event, - &event, f); -#endif + /* Assume we have a menubar button press. A bad + assumption should behave benignly. */ + popup_get_selection (&event); + break; } #endif /* USE_X_TOOLKIT */ } + if (event.type == ButtonPress) + { + x_mouse_grabbed |= (1 << event.xbutton.button); + Vmouse_depressed = Qt; + last_mouse_frame = f; + } + else + { + x_mouse_grabbed &= ~(1 << event.xbutton.button); + if (!x_mouse_grabbed) + Vmouse_depressed = Qnil; + } + if (numchars >= 1 && emacs_event.kind != no_event) { bcopy (&emacs_event, bufp, sizeof (struct input_event)); @@ -4156,56 +3892,11 @@ XTread_socket (sd, bufp, numchars, waitp, expected) } break; -#else /* ! defined (HAVE_X11) */ - case ButtonPressed: - case ButtonReleased: - f = x_window_to_frame (event.window); - if (f) - { - if (event.window == f->display.x->icon_desc) - { - x_make_frame_visible (f); - - if (warp_mouse_on_deiconify) - XWarpMouse (FRAME_X_WINDOW (f), 10, 10); - break; - } - if (event.window == FRAME_X_WINDOW (f)) - { - if (f->auto_raise) - x_raise_frame (f); - } - } - enqueue_event (&event, &x_mouse_queue); - if (numchars >= 2) - { - bufp->kind = ascii_keystroke; - bufp->code = 'X' & 037; /* C-x */ - XSET (bufp->frame_or_window, Lisp_Frame, f); - XSET (bufp->time, Lisp_Int, event.xkey.time); - bufp++; - - bufp->kind = ascii_keystroke; - bufp->code = 0; /* C-@ */ - XSET (bufp->frame_or_window, Lisp_Frame, f); - XSET (bufp->time, Lisp_Int, event.xkey.time); - bufp++; - - count += 2; - numchars -= 2; - } - break; -#endif /* ! defined (HAVE_X11) */ - -#ifdef HAVE_X11 - case CirculateNotify: break; case CirculateRequest: break; -#endif /* ! defined (HAVE_X11) */ - case MappingNotify: /* Someone has changed the keyboard mapping - update the local cache. */ @@ -4233,12 +3924,20 @@ XTread_socket (sd, bufp, numchars, waitp, expected) } } -#ifdef X_IO_BUG - if (! event_found) - /* On some systems, an X bug causes Emacs to get no more events - when the window is destroyed. Detect that. (1994.) */ - XNoOp (x_current_display); -#endif /* X_IO_BUG */ + /* On some systems, an X bug causes Emacs to get no more events + when the window is destroyed. Detect that. (1994.) */ + if (! event_found) + { + /* Emacs and the X Server eats up CPU time if XNoOp is done every time. + One XNOOP in 100 loops will make Emacs terminate. + B. Bretthauer, 1994 */ + x_noop_count++; + if (x_noop_count >= 100) + { + x_noop_count=0; + XNoOp (x_current_display); + } + } #if 0 /* This fails for serial-line connections to the X server, because the characters arrive one by one, and a partial @@ -4267,90 +3966,17 @@ XTread_socket (sd, bufp, numchars, waitp, expected) #endif /* HAVE_SELECT */ #endif /* 0 */ -#ifndef HAVE_X11 - if (updating_frame == 0) - x_do_pending_expose (); -#endif - /* If the focus was just given to an autoraising frame, raise it now. */ -#ifdef HAVE_X11 if (pending_autoraise_frame) { x_raise_frame (pending_autoraise_frame); pending_autoraise_frame = 0; } -#endif UNBLOCK_INPUT; return count; } - -#ifndef HAVE_X11 -/* Read and process only Expose events - until we get an ExposeCopy event; then return. - This is used in insert/delete line. - We assume input is already blocked. */ - -static void -x_read_exposes () -{ - struct frame *f; - XKeyPressedEvent event; - - while (1) - { - /* while there are more events*/ - XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event); - switch (event.type) - { - case ExposeWindow: - if (event.subwindow != 0) - break; /* duplicate event */ - f = x_window_to_frame (event.window); - if (event.window == f->display.x->icon_desc) - { - refreshicon (f); - break; - } - if (event.window == FRAME_X_WINDOW (f)) - { - expose_all_windows = 1; - f->display.x->needs_exposure = 1; - break; - } - break; - - case ExposeRegion: - if (event.subwindow != 0) - break; /* duplicate event */ - f = x_window_to_frame (event.window); - if (event.window == f->display.x->icon_desc) - { - refreshicon (f); - break; - } - /* If window already needs full redraw, ignore this rectangle. */ - if (expose_all_windows && f->display.x->needs_exposure) - break; - /* Put the event on the queue of rectangles to redraw. */ - if (enqueue_event (&event, &x_expose_queue)) - /* If it is full, we can't record the rectangle, - so redraw this entire window. */ - { - /* Say must check all windows' needs_exposure flags. */ - expose_all_windows = 1; - f->display.x->needs_exposure = 1; - } - break; - - case ExposeCopy: - return; - } - } -} -#endif /* HAVE_X11 */ - /* Drawing the cursor. */ @@ -4361,32 +3987,14 @@ static void x_draw_box (f) struct frame *f; { - int left = CHAR_TO_PIXEL_COL (f, f->cursor_x); - int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y); + int left = CHAR_TO_PIXEL_COL (f, curs_x); + int top = CHAR_TO_PIXEL_ROW (f, curs_y); int width = FONT_WIDTH (f->display.x->font); int height = f->display.x->line_height; -#ifdef HAVE_X11 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f), f->display.x->cursor_gc, left, top, width - 1, height - 1); -#else /* ! defined (HAVE_X11) */ - XPixSet (FRAME_X_WINDOW (f), - left, top, width, 1, - f->display.x->cursor_pixel); - - XPixSet (FRAME_X_WINDOW (f), - left, top, 1, height, - f->display.x->cursor_pixel); - - XPixSet (FRAME_X_WINDOW (f), - left+width-1, top, 1, height, - f->display.x->cursor_pixel); - - XPixSet (FRAME_X_WINDOW (f), - left, top+height-1, width, 1, - f->display.x->cursor_pixel); -#endif /* ! defined (HAVE_X11) */ } /* Clear the cursor of frame F to background color, @@ -4404,15 +4012,7 @@ clear_cursor (f) || f->phys_cursor_x < 0) return; -#ifdef HAVE_X11 x_display_cursor (f, 0); -#else /* ! defined (HAVE_X11) */ - XPixSet (FRAME_X_WINDOW (f), - CHAR_TO_PIXEL_COL (f, f->phys_cursor_x), - CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y), - FONT_WIDTH (f->display.x->font), f->display.x->line_height, - f->display.x->background_pixel); -#endif /* ! defined (HAVE_X11) */ f->phys_cursor_x = -1; } @@ -4538,6 +4138,21 @@ x_display_box_cursor (f, on) || (f->display.x->current_cursor != hollow_box_cursor && (f != x_highlight_frame)))) { + int mouse_face_here = 0; + + /* If the cursor is in the mouse face area, redisplay that when + we clear the cursor. */ + if (f == mouse_face_mouse_frame + && + (f->phys_cursor_y > mouse_face_beg_row + || (f->phys_cursor_y == mouse_face_beg_row + && f->phys_cursor_x >= mouse_face_beg_col)) + && + (f->phys_cursor_y < mouse_face_end_row + || (f->phys_cursor_y == mouse_face_end_row + && f->phys_cursor_x < mouse_face_end_col))) + mouse_face_here = 1; + /* If the font is not as tall as a whole line, we must explicitly clear the line's whole height. */ if (FONT_HEIGHT (f->display.x->font) != f->display.x->line_height) @@ -4549,7 +4164,9 @@ x_display_box_cursor (f, on) /* Erase the cursor by redrawing the character underneath it. */ x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x, f->phys_cursor_glyph, - current_glyphs->highlight[f->phys_cursor_y]); + (mouse_face_here + ? 3 + : current_glyphs->highlight[f->phys_cursor_y])); f->phys_cursor_x = -1; } @@ -4611,38 +4228,7 @@ x_display_cursor (f, on) refreshicon (f) struct frame *f; { -#ifdef HAVE_X11 /* Normally, the window manager handles this function. */ -#else /* ! defined (HAVE_X11) */ - int mask; - - if (f->display.x->icon_bitmap_flag) - XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height, - sink_bits, BlackPixel, WHITE_PIX_DEFAULT, - icon_bitmap, GXcopy, AllPlanes); - else - { - extern struct frame *selected_frame; - struct Lisp_String *str; - unsigned char *string; - - string - = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data; - - if (f->display.x->icon_label != string) - { - f->display.x->icon_label = string; - XChangeWindow (f->display.x->icon_desc, - XQueryWidth (string, icon_font_info->id) + 10, - icon_font_info->height + 10); - } - - XText (f->display.x->icon_desc, 5, 5, string, - str->size, icon_font_info->id, - BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT); - } - XFlushQueue (); -#endif /* ! defined (HAVE_X11) */ } /* Make the x-window of frame F use the gnu icon bitmap. */ @@ -4657,37 +4243,12 @@ x_bitmap_icon (f) if (FRAME_X_WINDOW (f) == 0) return 1; -#ifdef HAVE_X11 if (! icon_bitmap) icon_bitmap = XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f), gnu_bits, gnu_width, gnu_height); x_wm_set_icon_pixmap (f, icon_bitmap); f->display.x->icon_bitmap_flag = 1; -#else /* ! defined (HAVE_X11) */ - if (f->display.x->icon_desc) - { - XClearIconWindow (FRAME_X_WINDOW (f)); - XDestroyWindow (f->display.x->icon_desc); - } - - icon_window = XCreateWindow (f->display.x->parent_desc, - 0, 0, sink_width, sink_height, - 2, WhitePixmap, (Pixmap) NULL); - - if (icon_window == 0) - return 1; - - XSetIconWindow (FRAME_X_WINDOW (f), icon_window); - XSelectInput (icon_window, ExposeWindow | UnmapWindow); - - f->display.x->icon_desc = icon_window; - f->display.x->icon_bitmap_flag = 1; - - if (icon_bitmap == 0) - icon_bitmap - = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits); -#endif /* ! defined (HAVE_X11) */ return 0; } @@ -4700,26 +4261,9 @@ x_text_icon (f, icon_name) struct frame *f; char *icon_name; { -#ifndef HAVE_X11 - int mask; - int width; - Window icon_window; - char *X_DefaultValue; - Bitmap b1; - -#ifndef WhitePixel -#define WhitePixel 1 -#endif /* WhitePixel */ - -#ifndef BlackPixel -#define BlackPixel 0 -#endif /* BlackPixel */ -#endif /* HAVE_X11 */ - if (FRAME_X_WINDOW (f) == 0) return 1; -#ifdef HAVE_X11 if (icon_name) f->display.x->icon_label = icon_name; else @@ -4733,42 +4277,6 @@ x_text_icon (f, icon_name) f->display.x->icon_bitmap_flag = 0; x_wm_set_icon_pixmap (f, 0); -#else /* ! defined (HAVE_X11) */ - if (icon_font_info == 0) - icon_font_info - = XGetFont (XGetDefault (XDISPLAY - (char *) XSTRING (Vinvocation_name)->data, - "BodyFont")); - - if (f->display.x->icon_desc) - { - XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f)); - XDestroyWindow (XDISPLAY f->display.x->icon_desc); - } - - if (icon_name) - f->display.x->icon_label = (unsigned char *) icon_name; - else - if (! f->display.x->icon_label) - f->display.x->icon_label = XSTRING (f->name)->data; - - width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0); - icon_window = XCreateWindow (f->display.x->parent_desc, - f->display.x->left_pos, - f->display.x->top_pos, - width + 10, icon_font_info->height + 10, - 2, BlackPixmap, WhitePixmap); - - if (icon_window == 0) - return 1; - - XSetIconWindow (FRAME_X_WINDOW (f), icon_window); - XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed); - - f->display.x->icon_desc = icon_window; - f->display.x->icon_bitmap_flag = 0; - f->display.x->icon_label = 0; -#endif /* ! defined (HAVE_X11) */ return 0; } @@ -4935,12 +4443,11 @@ x_trace_wire () to the font named NEWNAME. This is safe to use even before F has an actual x-window. */ -#ifdef HAVE_X11 - struct font_info { XFontStruct *font; char *name; + char *full_name; }; /* A table of all the fonts we have already loaded. */ @@ -4954,6 +4461,11 @@ static int x_font_table_size; 0 <= n_fonts <= x_font_table_size. */ static int n_fonts; +/* Give frame F the font named FONTNAME as its default font, and + return the full name of that font. FONTNAME may be a wildcard + pattern; in that case, we choose some font that fits the pattern. + The return value shows which font we chose. */ + Lisp_Object x_new_font (f, fontname) struct frame *f; @@ -4986,10 +4498,11 @@ x_new_font (f, fontname) for (i = 0; i < n_fonts; i++) for (j = 0; j < n_matching_fonts; j++) - if (!strcmp (x_font_table[i].name, font_names[j])) + if (!strcmp (x_font_table[i].name, font_names[j]) + || !strcmp (x_font_table[i].full_name, font_names[j])) { already_loaded = i; - fontname = font_names[j]; + fontname = x_font_table[i].full_name; goto found_font; } } @@ -4998,11 +4511,11 @@ x_new_font (f, fontname) /* If we have, just return it from the table. */ if (already_loaded >= 0) f->display.x->font = x_font_table[already_loaded].font; - /* Otherwise, load the font and add it to the table. */ else { int i; + char *full_name; XFontStruct *font; /* Try to find a character-cell font in the list. */ @@ -5046,10 +4559,58 @@ x_new_font (f, fontname) * sizeof (x_font_table[0]))); } + /* Try to get the full name of FONT. Put it in full_name. */ + full_name = 0; + for (i = 0; i < font->n_properties; i++) + { + char *atom + = XGetAtomName (x_current_display, font->properties[i].name); + if (!strcmp (atom, "FONT")) + { + char *name = XGetAtomName (x_current_display, + (Atom) (font->properties[i].card32)); + char *p = name; + int dashes = 0; + + /* Count the number of dashes in the "full name". + If it is too few, this isn't really the font's full name, + so don't use it. + In X11R4, the fonts did not come with their canonical names + stored in them. */ + while (*p) + { + if (*p == '-') + dashes++; + p++; + } + + if (dashes >= 13) + full_name = name; + } + + XFree (atom); + } + x_font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1); bcopy (fontname, x_font_table[n_fonts].name, strlen (fontname) + 1); + if (full_name != 0) + x_font_table[n_fonts].full_name = full_name; + else + x_font_table[n_fonts].full_name = x_font_table[n_fonts].name; f->display.x->font = x_font_table[n_fonts++].font = font; + + if (full_name) + fontname = full_name; + } + + /* Compute the scroll bar width in character columns. */ + if (f->scroll_bar_pixel_width > 0) + { + int wid = FONT_WIDTH (f->display.x->font); + f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid; } + else + f->scroll_bar_cols = 2; /* Now make the frame display the given font. */ if (FRAME_X_WINDOW (f) != 0) @@ -5081,36 +4642,13 @@ x_new_font (f, fontname) return lispy_name; } } -#else /* ! defined (HAVE_X11) */ -x_new_font (f, newname) - struct frame *f; - register char *newname; -{ - FONT_TYPE *temp; - int mask; - - temp = XGetFont (newname); - if (temp == (FONT_TYPE *) 0) - return 1; - - if (f->display.x->font) - XLoseFont (f->display.x->font); - - f->display.x->font = temp; - - if (FRAME_X_WINDOW (f) != 0) - x_set_window_size (f, 0, f->width, f->height); - - return 0; -} -#endif /* ! defined (HAVE_X11) */ x_calc_absolute_position (f) struct frame *f; { -#ifdef HAVE_X11 Window win, child; int win_x = 0, win_y = 0; + int flags = f->display.x->size_hint_flags; /* Find the position of the outside upper-left corner of the inner window, with respect to the outer window. */ @@ -5133,43 +4671,49 @@ x_calc_absolute_position (f) /* Treat negative positions as relative to the leftmost bottommost position that fits on the screen. */ - if (f->display.x->left_pos < 0) + if (flags & XNegative) f->display.x->left_pos = (x_screen_width - 2 * f->display.x->border_width - win_x - PIXEL_WIDTH (f) + f->display.x->left_pos); - if (f->display.x->top_pos < 0) + if (flags & YNegative) f->display.x->top_pos = (x_screen_height - 2 * f->display.x->border_width - win_y - PIXEL_HEIGHT (f) + f->display.x->top_pos); - -#else /* ! defined (HAVE_X11) */ - WINDOWINFO_TYPE parentinfo; - - XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo); - - if (f->display.x->left_pos < 0) - f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1) - - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width; - - if (f->display.x->top_pos < 0) - f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1) - - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width; -#endif /* ! defined (HAVE_X11) */ + /* The left_pos and top_pos + are now relative to the top and left screen edges, + so the flags should correspond. */ + f->display.x->size_hint_flags &= ~ (XNegative | YNegative); } +/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, + to really change the position, and 0 when calling from + x_make_frame_visible (in that case, XOFF and YOFF are the current + position values). */ + x_set_offset (f, xoff, yoff, change_gravity) struct frame *f; register int xoff, yoff; int change_gravity; { - f->display.x->top_pos = yoff; - f->display.x->left_pos = xoff; + if (change_gravity) + { + f->display.x->top_pos = yoff; + f->display.x->left_pos = xoff; + f->display.x->size_hint_flags &= ~ (XNegative | YNegative); + if (xoff < 0) + f->display.x->size_hint_flags |= XNegative; + if (yoff < 0) + f->display.x->size_hint_flags |= YNegative; + f->display.x->win_gravity = NorthWestGravity; + } x_calc_absolute_position (f); BLOCK_INPUT; + x_wm_set_size_hint (f, 0, 0); + #ifdef USE_X_TOOLKIT XMoveWindow (XDISPLAY XtWindow (f->display.x->widget), f->display.x->left_pos, f->display.x->top_pos); @@ -5177,12 +4721,6 @@ x_set_offset (f, xoff, yoff, change_gravity) XMoveWindow (XDISPLAY FRAME_X_WINDOW (f), f->display.x->left_pos, f->display.x->top_pos); #endif /* not USE_X_TOOLKIT */ -#ifdef HAVE_X11 - if (change_gravity) - f->display.x->win_gravity = NorthWestGravity; - - x_wm_set_size_hint (f, 0, 1); -#endif /* ! defined (HAVE_X11) */ UNBLOCK_INPUT; } @@ -5201,7 +4739,17 @@ x_set_window_size (f, change_gravity, cols, rows) #ifdef USE_X_TOOLKIT BLOCK_INPUT; - EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows); + { + /* The x and y position of the widget is clobbered by the + call to XtSetValues within EmacsFrameSetCharSize. + This is a real kludge, but I don't understand Xt so I can't + figure out a correct fix. Can anyone else tell me? -- rms. */ + int xpos = f->display.x->widget->core.x; + int ypos = f->display.x->widget->core.y; + EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows); + f->display.x->widget->core.x = xpos; + f->display.x->widget->core.y = ypos; + } UNBLOCK_INPUT; #else /* not USE_X_TOOLKIT */ @@ -5210,15 +4758,17 @@ x_set_window_size (f, change_gravity, cols, rows) check_frame_size (f, &rows, &cols); f->display.x->vertical_scroll_bar_extra - = (FRAME_HAS_VERTICAL_SCROLL_BARS (f) - ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f) - : 0); + = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f) + ? 0 + : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0 + ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f) + : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->display.x->font))); pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); -#ifdef HAVE_X11 - x_wm_set_size_hint (f, 0, change_gravity); -#endif /* ! defined (HAVE_X11) */ + f->display.x->win_gravity = NorthWestGravity; + x_wm_set_size_hint (f, 0, 0); + XSync (x_current_display, False); XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight); @@ -5236,6 +4786,14 @@ x_set_window_size (f, change_gravity, cols, rows) PIXEL_WIDTH (f) = pixelwidth; PIXEL_HEIGHT (f) = pixelheight; + /* If cursor was outside the new size, mark it as off. */ + if (f->phys_cursor_y >= rows + || f->phys_cursor_x >= cols) + { + f->phys_cursor_x = -1; + f->phys_cursor_y = -1; + } + /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to receive in the ConfigureNotify event; if we get what we asked for, then the event won't cause the screen to become garbaged, so @@ -5246,18 +4804,6 @@ x_set_window_size (f, change_gravity, cols, rows) UNBLOCK_INPUT; #endif /* not USE_X_TOOLKIT */ } - -#ifndef HAVE_X11 -x_set_resize_hint (f) - struct frame *f; -{ - XSetResizeHint (FRAME_X_WINDOW (f), - 2 * f->display.x->internal_border_width, - 2 * f->display.x->internal_border_width, - FONT_WIDTH (f->display.x->font), - f->display.x->line_height); -} -#endif /* HAVE_X11 */ /* Mouse warping, focus shifting, raising and lowering. */ @@ -5296,7 +4842,6 @@ x_set_mouse_pixel_position (f, pix_x, pix_y) UNBLOCK_INPUT; } -#ifdef HAVE_X11 x_focus_on_frame (f) struct frame *f; { @@ -5323,8 +4868,6 @@ x_unfocus_frame (f) #endif /* ! 0 */ } -#endif /* ! defined (HAVE_X11) */ - /* Raise frame F. */ x_raise_frame (f) @@ -5372,8 +4915,8 @@ XTframe_raise_lower (f, raise) x_lower_frame (f); } - -/* Change from withdrawn state to mapped state. */ +/* Change from withdrawn state to mapped state, + or deiconify. */ x_make_frame_visible (f) struct frame *f; @@ -5384,13 +4927,16 @@ x_make_frame_visible (f) if (! FRAME_VISIBLE_P (f)) { -#ifdef HAVE_X11 - x_set_offset (f, f->display.x->left_pos, f->display.x->top_pos, 0); +#ifndef USE_X_TOOLKIT + if (! FRAME_ICONIFIED_P (f)) + x_set_offset (f, f->display.x->left_pos, f->display.x->top_pos, 0); +#endif if (! EQ (Vx_no_window_manager, Qt)) x_wm_set_window_state (f, NormalState); #ifdef USE_X_TOOLKIT - XtPopup (f->display.x->widget, XtGrabNone); + /* This was XtPopup, but that did nothing for an iconified frame. */ + XtMapWidget (f->display.x->widget); #else /* not USE_X_TOOLKIT */ XMapWindow (XDISPLAY FRAME_X_WINDOW (f)); #endif /* not USE_X_TOOLKIT */ @@ -5400,23 +4946,54 @@ x_make_frame_visible (f) if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) XMapSubwindows (x_current_display, FRAME_X_WINDOW (f)); #endif -#else /* ! defined (HAVE_X11) */ - XMapWindow (XDISPLAY FRAME_X_WINDOW (f)); - if (f->display.x->icon_desc != 0) - XUnmapWindow (f->display.x->icon_desc); - - /* Handled by the MapNotify event for X11 */ - f->async_visible = 1; - f->async_iconified = 0; - - /* NOTE: this may cause problems for the first frame. */ - XTcursor_to (0, 0); -#endif /* ! defined (HAVE_X11) */ } XFlushQueue (); - UNBLOCK_INPUT; + /* Synchronize to ensure Emacs knows the frame is visible + before we do anything else. We do this loop with input not blocked + so that incoming events are handled. */ + { + Lisp_Object frame; + int count = input_signal_count; + + /* This must come after we set COUNT. */ + UNBLOCK_INPUT; + + XSET (frame, Lisp_Frame, f); + + while (1) + { + x_sync (frame); + /* Once we have handled input events, + we should have received the MapNotify if one is coming. + So if we have not got it yet, stop looping. + Some window managers make their own decisions + about visibility. */ + if (input_signal_count != count) + break; + /* Machines that do polling rather than SIGIO have been observed + to go into a busy-wait here. So we'll fake an alarm signal + to let the handler know that there's something to be read. + We used to raise a real alarm, but it seems that the handler + isn't always enabled here. This is probably a bug. */ + if (input_polling_used ()) + { + /* It could be confusing if a real alarm arrives while processing + the fake one. Turn it off and let the handler reset it. */ + alarm (0); + input_poll_signal (); + } + /* Once we have handled input events, + we should have received the MapNotify if one is coming. + So if we have not got it yet, stop looping. + Some window managers make their own decisions + about visibility. */ + if (input_signal_count != count) + break; + } + FRAME_SAMPLE_VISIBILITY (f); + } } /* Change from mapped state to withdrawn state. */ @@ -5425,6 +5002,14 @@ x_make_frame_invisible (f) struct frame *f; { int mask; + Window window; + +#ifdef USE_X_TOOLKIT + /* Use the frame's outermost window, not the one we normally draw on. */ + window = XtWindow (f->display.x->widget); +#else /* not USE_X_TOOLKIT */ + window = FRAME_X_WINDOW (f); +#endif /* not USE_X_TOOLKIT */ /* Don't keep the highlight on an invisible frame. */ if (x_highlight_frame == f) @@ -5437,21 +5022,22 @@ x_make_frame_invisible (f) BLOCK_INPUT; + /* Before unmapping the window, update the WM_SIZE_HINTS property to claim + that the current position of the window is user-specified, rather than + program-specified, so that when the window is mapped again, it will be + placed at the same location, without forcing the user to position it + by hand again (they have already done that once for this window.) */ + x_wm_set_size_hint (f, 0, 1); + #ifdef HAVE_X11R4 -#ifdef USE_X_TOOLKIT - XtPopdown (f->display.x->widget); -#else /* not USE_X_TOOLKIT */ - if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f), + if (! XWithdrawWindow (x_current_display, window, DefaultScreen (x_current_display))) { UNBLOCK_INPUT_RESIGNAL; - error ("can't notify window manager of window withdrawal"); + error ("Can't notify window manager of window withdrawal"); } -#endif /* not USE_X_TOOLKIT */ - #else /* ! defined (HAVE_X11R4) */ -#ifdef HAVE_X11 /* Tell the window manager what we're going to do. */ if (! EQ (Vx_no_window_manager, Qt)) @@ -5459,11 +5045,7 @@ x_make_frame_invisible (f) XEvent unmap; unmap.xunmap.type = UnmapNotify; -#ifdef USE_X_TOOLKIT - unmap.xunmap.window = XtWindow (f->display.x->widget); -#else /* not USE_X_TOOLKIT */ - unmap.xunmap.window = FRAME_X_WINDOW (f); -#endif /* not USE_X_TOOLKIT */ + unmap.xunmap.window = window; unmap.xunmap.event = DefaultRootWindow (x_current_display); unmap.xunmap.from_configure = False; if (! XSendEvent (x_current_display, @@ -5473,23 +5055,12 @@ x_make_frame_invisible (f) &unmap)) { UNBLOCK_INPUT_RESIGNAL; - error ("can't notify window manager of withdrawal"); + error ("Can't notify window manager of withdrawal"); } } /* Unmap the window ourselves. Cheeky! */ -#ifdef USE_X_TOOLKIT - XUnmapWindow (x_current_display, XtWindow (f->display.x->widget)); -#else /* not USE_X_TOOLKIT */ - XUnmapWindow (x_current_display, FRAME_X_WINDOW (f)); -#endif /* not USE_X_TOOLKIT */ -#else /* ! defined (HAVE_X11) */ - - XUnmapWindow (FRAME_X_WINDOW (f)); - if (f->display.x->icon_desc != 0) - XUnmapWindow (f->display.x->icon_desc); - -#endif /* ! defined (HAVE_X11) */ + XUnmapWindow (x_current_display, window); #endif /* ! defined (HAVE_X11R4) */ /* We can't distinguish this from iconification @@ -5524,13 +5095,24 @@ x_iconify_frame (f) #ifdef USE_X_TOOLKIT BLOCK_INPUT; + + if (! FRAME_VISIBLE_P (f)) + { + if (! EQ (Vx_no_window_manager, Qt)) + x_wm_set_window_state (f, IconicState); + /* This was XtPopup, but that did nothing for an iconified frame. */ + XtMapWidget (f->display.x->widget); + UNBLOCK_INPUT; + return; + } + result = XIconifyWindow (x_current_display, XtWindow (f->display.x->widget), DefaultScreen (x_current_display)); UNBLOCK_INPUT; if (!result) - error ("Can't notify window manager of iconification."); + error ("Can't notify window manager of iconification"); f->async_iconified = 1; @@ -5541,7 +5123,11 @@ x_iconify_frame (f) BLOCK_INPUT; -#ifdef HAVE_X11 + /* Make sure the X server knows where the window should be positioned, + in case the user deiconifies with the window manager. */ + if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f)) + x_set_offset (f, f->display.x->left_pos, f->display.x->top_pos, 0); + /* Since we don't know which revision of X we're running, we'll use both the X11R3 and X11R4 techniques. I don't know if this is a good idea. */ @@ -5563,7 +5149,7 @@ x_iconify_frame (f) &message)) { UNBLOCK_INPUT_RESIGNAL; - error ("Can't notify window manager of iconification."); + error ("Can't notify window manager of iconification"); } } @@ -5582,16 +5168,6 @@ x_iconify_frame (f) } f->async_iconified = 1; -#else /* ! defined (HAVE_X11) */ - XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f)); - - f->async_visible = 0; /* Handled in the UnMap event for X11. */ - if (f->display.x->icon_desc != 0) - { - XMapWindow (XDISPLAY f->display.x->icon_desc); - refreshicon (f); - } -#endif /* ! defined (HAVE_X11) */ XFlushQueue (); UNBLOCK_INPUT; @@ -5616,6 +5192,12 @@ x_destroy_window (f) free_frame_faces (f); XFlushQueue (); + FRAME_X_SCREEN (f)->reference_count--; +#if 0 + if (FRAME_X_SCREEN (f)->reference_count == 0) + free (FRAME_X_SCREEN (f)); +#endif + xfree (f->display.x); f->display.x = 0; if (f == x_focus_frame) @@ -5625,100 +5207,26 @@ x_destroy_window (f) if (f == mouse_face_mouse_frame) { - mouse_face_beg = -1; - mouse_face_end = -1; + mouse_face_beg_row = mouse_face_beg_col = -1; + mouse_face_end_row = mouse_face_end_col = -1; mouse_face_window = Qnil; } UNBLOCK_INPUT; } -/* Manage event queues for X10. */ - -#ifndef HAVE_X11 - -/* Manage event queues. - - This code is only used by the X10 support. - - We cannot leave events in the X queue and get them when we are ready - because X does not provide a subroutine to get only a certain kind - of event but not block if there are no queued events of that kind. - - Therefore, we must examine events as they come in and copy events - of certain kinds into our private queues. - - All ExposeRegion events are put in x_expose_queue. - All ButtonPress and ButtonRelease events are put in x_mouse_queue. */ - - -/* Write the event *P_XREP into the event queue *QUEUE. - If the queue is full, do nothing, but return nonzero. */ - -int -enqueue_event (p_xrep, queue) - register XEvent *p_xrep; - register struct event_queue *queue; -{ - int newindex = queue->windex + 1; - if (newindex == EVENT_BUFFER_SIZE) - newindex = 0; - if (newindex == queue->rindex) - return -1; - queue->xrep[queue->windex] = *p_xrep; - queue->windex = newindex; - return 0; -} - -/* Fetch the next event from queue *QUEUE and store it in *P_XREP. - If *QUEUE is empty, do nothing and return 0. */ - -int -dequeue_event (p_xrep, queue) - register XEvent *p_xrep; - register struct event_queue *queue; -{ - if (queue->windex == queue->rindex) - return 0; - *p_xrep = queue->xrep[queue->rindex++]; - if (queue->rindex == EVENT_BUFFER_SIZE) - queue->rindex = 0; - return 1; -} - -/* Return the number of events buffered in *QUEUE. */ - -int -queue_event_count (queue) - register struct event_queue *queue; -{ - int tem = queue->windex - queue->rindex; - if (tem >= 0) - return tem; - return EVENT_BUFFER_SIZE + tem; -} - -/* Return nonzero if mouse input is pending. */ - -int -mouse_event_pending_p () -{ - return queue_event_count (&x_mouse_queue); -} -#endif /* HAVE_X11 */ - /* Setting window manager hints. */ -#ifdef HAVE_X11 - -/* SPEC_X and SPEC_Y are the specified positions. - We look only at their sign, to decide the gravity. - If CHANGE_GRAVITY is 0, we may set PWinGravity. */ +/* Set the normal size hints for the window manager, for frame F. + FLAGS is the flags word to use--or 0 meaning preserve the flags + that the window now has. + If USER_POSITION is nonzero, we set the USPosition + flag (this is useful when FLAGS is 0). */ -x_wm_set_size_hint (f, prompting, change_gravity) +x_wm_set_size_hint (f, flags, user_position) struct frame *f; - long prompting; - int change_gravity; + long flags; + int user_position; { XSizeHints size_hints; @@ -5731,12 +5239,14 @@ x_wm_set_size_hint (f, prompting, change_gravity) Window window = FRAME_X_WINDOW (f); #endif /* not USE_X_TOOLKIT */ + /* Setting PMaxSize caused various problems. */ size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */; flexlines = f->height; size_hints.x = f->display.x->left_pos; size_hints.y = f->display.x->top_pos; + #ifdef USE_X_TOOLKIT XtSetArg (al[ac], XtNwidth, &widget_width); ac++; XtSetArg (al[ac], XtNheight, &widget_height); ac++; @@ -5747,8 +5257,11 @@ x_wm_set_size_hint (f, prompting, change_gravity) size_hints.height = PIXEL_HEIGHT (f); size_hints.width = PIXEL_WIDTH (f); #endif /* not USE_X_TOOLKIT */ + size_hints.width_inc = FONT_WIDTH (f->display.x->font); size_hints.height_inc = f->display.x->line_height; + size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0); + size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0); { int base_width, base_height; @@ -5781,13 +5294,22 @@ x_wm_set_size_hint (f, prompting, change_gravity) #endif } - if (prompting) - size_hints.flags |= prompting; + if (flags) + size_hints.flags |= flags; else { XSizeHints hints; /* Sometimes I hate X Windows... */ + long supplied_return; + int value; + +#ifdef HAVE_X11R4 + value = XGetWMNormalHints (x_current_display, window, &hints, + &supplied_return); +#else + value = XGetNormalHints (x_current_display, window, &hints); +#endif - if (XGetNormalHints (x_current_display, window, &hints) == 0) + if (value == 0) hints.flags = 0; if (hints.flags & PSize) size_hints.flags |= PSize; @@ -5799,13 +5321,14 @@ x_wm_set_size_hint (f, prompting, change_gravity) size_hints.flags |= USSize; } +#ifdef PWinGravity size_hints.win_gravity = f->display.x->win_gravity; + size_hints.flags |= PWinGravity; -#if defined (PWinGravity) - if (change_gravity) + if (user_position) { - if (! (size_hints.flags & USPosition)) - size_hints.flags |= PWinGravity; + size_hints.flags &= ~ PPosition; + size_hints.flags |= USPosition; } #endif /* PWinGravity */ @@ -5822,22 +5345,29 @@ x_wm_set_window_state (f, state) int state; { #ifdef USE_X_TOOLKIT - Window window = XtWindow (f->display.x->widget); + Arg al[1]; + + XtSetArg (al[0], XtNinitialState, state); + XtSetValues (f->display.x->widget, al, 1); #else /* not USE_X_TOOLKIT */ Window window = FRAME_X_WINDOW (f); -#endif /* not USE_X_TOOLKIT */ f->display.x->wm_hints.flags |= StateHint; f->display.x->wm_hints.initial_state = state; XSetWMHints (x_current_display, window, &f->display.x->wm_hints); +#endif /* not USE_X_TOOLKIT */ } x_wm_set_icon_pixmap (f, icon_pixmap) struct frame *f; Pixmap icon_pixmap; { +#ifdef USE_X_TOOLKIT + Window window = XtWindow (f->display.x->widget); +#else Window window = FRAME_X_WINDOW (f); +#endif if (icon_pixmap) { @@ -5854,7 +5384,11 @@ x_wm_set_icon_position (f, icon_x, icon_y) struct frame *f; int icon_x, icon_y; { +#ifdef USE_X_TOOLKIT + Window window = XtWindow (f->display.x->widget); +#else Window window = FRAME_X_WINDOW (f); +#endif f->display.x->wm_hints.flags |= IconPositionHint; f->display.x->wm_hints.icon_x = icon_x; @@ -5886,8 +5420,10 @@ static XrmOptionDescRec emacs_options[] = { #endif /* USE_X_TOOLKIT */ void -x_term_init (display_name) +x_term_init (display_name, xrm_option, resource_name) char *display_name; + char *xrm_option; + char *resource_name; { Lisp_Object frame; char *defaultvalue; @@ -5899,21 +5435,29 @@ x_term_init (display_name) #endif /* ! defined (F_SETOWN) */ #endif /* F_SETOWN_BUG */ + x_noop_count = 0; + x_focus_frame = x_highlight_frame = 0; #ifdef USE_X_TOOLKIT - argv = (char **) XtMalloc (5 * sizeof (char *)); - argv [0] = ""; - argv [1] = "-display"; - argv [2] = display_name; - argv [3] = "-name"; - argv [4] = "emacs"; + argv = (char **) XtMalloc (7 * sizeof (char *)); + argv[0] = ""; + argv[1] = "-display"; + argv[2] = display_name; + argv[3] = "-name"; + /* Usually `emacs', but not always. */ + argv[4] = resource_name; argc = 5; + if (xrm_option) + { + argv[argc++] = "-xrm"; + argv[argc++] = xrm_option; + } Xt_app_shell = XtAppInitialize (&Xt_app_con, "Emacs", emacs_options, XtNumber (emacs_options), &argc, argv, NULL, NULL, 0); - XtFree (argv); + XtFree ((char *)argv); x_current_display = XtDisplay (Xt_app_shell); #else /* not USE_X_TOOLKIT */ @@ -5924,16 +5468,15 @@ x_term_init (display_name) Check the DISPLAY environment variable or use \"-d\"\n", display_name); -#ifdef HAVE_X11 { #if 0 XSetAfterFunction (x_current_display, x_trace_wire); #endif /* ! 0 */ - hostname = get_system_name (); x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size - + strlen (hostname) + + XSTRING (Vsystem_name)->size + 2); - sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname); + sprintf (x_id_name, "%s@%s", + XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data); } /* Figure out which modifier bits mean what. */ @@ -5953,8 +5496,6 @@ Check the DISPLAY environment variable or use \"-d\"\n", change_keyboard_wait_descriptor (ConnectionNumber (x_current_display)); change_input_fd (ConnectionNumber (x_current_display)); -#endif /* ! defined (HAVE_X11) */ - #ifndef F_SETOWN_BUG #ifdef F_SETOWN old_fcntl_owner = fcntl (ConnectionNumber (x_current_display), F_GETOWN, 0); @@ -6030,5 +5571,4 @@ syms_of_xterm () staticpro (&mouse_face_window); mouse_face_window = Qnil; } -#endif /* ! defined (HAVE_X11) */ #endif /* ! defined (HAVE_X_WINDOWS) */