along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* Serious problems:
-
- Kludge: dup2 is used to put the X-connection socket into desc # 0
- so that wait_reading_process_input will wait for it in place of
- actual terminal input.
-
-*/
-
/* Xt features made by Fred Pierresteguy. */
-#define NEW_SELECTIONS
-
/* 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. */
extern XtAppContext Xt_app_con;
extern Widget Xt_app_shell;
extern void free_frame_menubar ();
+extern void _XEditResCheckMessages ();
#endif /* USE_X_TOOLKIT */
#ifndef USE_X_TOOLKIT
#define x_any_window_to_frame x_window_to_frame
+#define x_top_window_to_frame x_window_to_frame
#endif
#ifdef HAVE_X11
x_focus_event_frame. */
struct frame *x_focus_frame;
+/* This is a frame waiting to be autoraised, within XTread_socket. */
+struct frame *pending_autoraise_frame;
+
/* The last frame mentioned in a FocusIn or FocusOut event. This is
separate from x_focus_frame, because whether or not LeaveNotify
events cause us to lose focus depends on whether or not we have
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
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 Lisp_Object mouse_face_window;
static int mouse_face_face_id;
+/* 1 if a mouse motion event came and we didn't handle it right away because
+ gc was in progress. */
+static int mouse_face_deferred_gc;
+
/* FRAME and X, Y position of mouse when last checked for highlighting. */
static FRAME_PTR mouse_face_mouse_frame;
static int mouse_face_mouse_x, mouse_face_mouse_y;
/* Nonzero enables some debugging for the X interface code. */
extern int _Xdebug;
-extern Qface, Qmouse_face;
+extern Lisp_Object Qface, Qmouse_face;
#else /* ! defined (HAVE_X11) */
static void flashback ();
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 ();
if (f == mouse_face_mouse_frame)
{
+ /* Don't do highlighting for mouse motion during the update. */
mouse_face_defer = 1;
if (!NILP (mouse_face_window))
- clear_mouse_face ();
+ {
+ int firstline, lastline, i;
+ struct window *w = XWINDOW (mouse_face_window);
+
+ /* Find the first, and the last+1, lines affected by redisplay. */
+ for (firstline = 0; firstline < f->height; firstline++)
+ if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
+ break;
+
+ lastline = f->height;
+ for (i = f->height - 1; i >= 0; i--)
+ {
+ if (FRAME_DESIRED_GLYPHS (f)->enable[i])
+ break;
+ else
+ lastline = i;
+ }
+
+ /* Can we tell that this update does not affect the window
+ where the mouse highlight is? If so, no need to turn off. */
+ if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
+ || lastline < XFASTINT (w->top)))
+ /* Otherwise turn off the mouse highlight now. */
+ clear_mouse_face ();
+ }
}
#ifndef HAVE_X11
dumpqueue ();
UNBLOCK_INPUT;
}
-/* This is called when all windows on frame F are now up to date. */
+/* This is called after a redisplay on frame F. */
static
XTframe_up_to_date (f)
FRAME_PTR f;
{
- if (f == mouse_face_mouse_frame)
- note_mouse_highlight (f, mouse_face_mouse_x, mouse_face_mouse_y);
+ if (mouse_face_deferred_gc || f == mouse_face_mouse_frame)
+ {
+ note_mouse_highlight (mouse_face_mouse_frame,
+ mouse_face_mouse_x, mouse_face_mouse_y);
+ mouse_face_deferred_gc = 0;
+ }
}
\f
/* External interface to control of standout mode.
WINDOW is the x-window to output to. LEFT and TOP are starting coords.
HL is 1 if this text is highlighted, 2 if the cursor is on it,
3 if should appear in its mouse-face.
+ JUST_FOREGROUND if 1 means draw only the foreground;
+ don't alter the background.
FONT is the default font to use (for glyphs whose font-code is 0).
/* This is the multi-face code. */
static void
-dumpglyphs (f, left, top, gp, n, hl)
+dumpglyphs (f, left, top, gp, n, hl, just_foreground)
struct frame *f;
int left, top;
register GLYPH *gp; /* Points to first GLYPH. */
register int n; /* Number of glyphs to display. */
int hl;
+ int just_foreground;
{
/* Holds characters to be displayed. */
char *buf = (char *) alloca (f->width * sizeof (*buf));
register int tlen = GLYPH_TABLE_LENGTH;
register Lisp_Object *tbase = GLYPH_TABLE_BASE;
Window window = FRAME_X_WINDOW (f);
+ int orig_left = left;
while (n > 0)
{
struct face *face = FRAME_DEFAULT_FACE (f);
FONT_TYPE *font = FACE_FONT (face);
GC gc = FACE_GC (face);
- int defaulted = 1;
int gc_temporary = 0;
/* HL = 3 means use a mouse face previously chosen. */
face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
font = FACE_FONT (face);
gc = FACE_GC (face);
- defaulted = 0;
}
/* Then comes the distinction between modeline and normal text. */
face = FRAME_MODE_LINE_FACE (f);
font = FACE_FONT (face);
gc = FACE_GC (face);
- defaulted = 0;
}
#define FACE_DEFAULT (~0)
/* Now override that if the cursor's on this character. */
if (hl == 2)
{
- if (defaulted
- || !face->font
+ if (!face->font
|| (int) face->font == FACE_DEFAULT)
{
gc = f->display.x->cursor_gc;
if ((int) font == FACE_DEFAULT)
font = f->display.x->font;
- XDrawImageString (x_current_display, window, gc,
- left, top + FONT_BASE (font), buf, len);
+ if (just_foreground)
+ XDrawString (x_current_display, window, gc,
+ left, top + FONT_BASE (font), buf, len);
+ else
+ {
+ XDrawImageString (x_current_display, window, gc,
+ left, top + FONT_BASE (font), buf, len);
+ /* Clear the rest of the line's height. */
+ if (f->display.x->line_height != FONT_HEIGHT (font))
+ XClearArea (x_current_display, window, left,
+ top + FONT_HEIGHT (font),
+ FONT_WIDTH (font) * len,
+ /* This is how many pixels of height
+ we have to clear. */
+ f->display.x->line_height - FONT_HEIGHT (font),
+ False);
+ }
+
+#if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
+ which often is not up to date yet. */
+ if (!just_foreground)
+ {
+ if (left == orig_left)
+ redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
+ PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+ if (n == 0)
+ redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
+ PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+ }
+#endif
if (gc_temporary)
XFreeGC (x_current_display, gc);
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, curs_x),
CHAR_TO_PIXEL_ROW (f, curs_y),
- start, len, highlight);
+ start, len, highlight, 0);
/* If we drew on top of the cursor, note that it is turned off. */
if (curs_y == f->phys_cursor_y
CHAR_TO_PIXEL_COL (f, curs_x),
CHAR_TO_PIXEL_ROW (f, curs_y),
FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
- FONT_HEIGHT (f->display.x->font), False);
+ f->display.x->line_height, False);
#if 0
- redraw_previous_char (f, curs_x, curs_y);
+ 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),
- FONT_HEIGHT (f->display.x->font),
+ f->display.x->line_height,
f->display.x->background_pixel);
#endif /* ! defined (HAVE_X11) */
UNBLOCK_INPUT;
}
+static
+XTclear_frame ()
+{
+ int mask;
+ struct frame *f = updating_frame;
+
+ if (f == 0)
+ f = selected_frame;
+
+ f->phys_cursor_x = -1; /* Cursor not visible. */
+ curs_x = 0; /* Nominal cursor position is top left. */
+ curs_y = 0;
+
+ BLOCK_INPUT;
+
+ XClear (FRAME_X_WINDOW (f));
+
+ /* We have to clear the scroll bars, too. If we have changed
+ 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;
+}
+\f
+#if 0
+/* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
+ always contain the right glyphs to use.
+
+ It also needs to be changed to look at the details of the font and
+ see whether there is really overlap, and do nothing when there is
+ not. This can use font_char_overlap_left and font_char_overlap_right,
+ but just how to use them is not clear. */
+
/* Erase the character (if any) at the position just before X, Y in frame F,
then redraw it and the character before it.
This is necessary when we erase starting at X,
Call this function with input blocked. */
static void
-redraw_previous_char (f, x, y)
+redraw_previous_char (f, x, y, highlight_flag)
FRAME_PTR f;
int x, y;
+ int highlight_flag;
{
/* Erase the character before the new ones, in case
what was here before overlaps it.
CHAR_TO_PIXEL_COL (f, x - 1),
CHAR_TO_PIXEL_ROW (f, y),
FONT_WIDTH (f->display.x->font),
- FONT_HEIGHT (f->display.x->font), False);
+ f->display.x->line_height, False);
dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
CHAR_TO_PIXEL_ROW (f, y),
&FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
- x - start_x, highlight);
+ x - start_x, highlight_flag, 1);
}
}
-static
-XTclear_frame ()
+/* Erase the character (if any) at the position X, Y in frame F,
+ then redraw it and the character after it.
+ This is necessary when we erase endng at X,
+ in case the character after X overlaps into the one before X.
+ Call this function with input blocked. */
+
+static void
+redraw_following_char (f, x, y, highlight_flag)
+ FRAME_PTR f;
+ int x, y;
+ int highlight_flag;
{
- int mask;
- struct frame *f = updating_frame;
+ int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
+ /* Erase the character after the new ones, in case
+ what was here before overlaps it.
+ Reoutput that character, and the following character
+ (in case the following character overlaps it). */
+ if (x < limit
+ && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
+ {
+ int end_x = x + 2;
+ if (end_x > limit)
+ end_x = limit;
+ XClearArea (x_current_display, FRAME_X_WINDOW (f),
+ CHAR_TO_PIXEL_COL (f, x),
+ CHAR_TO_PIXEL_ROW (f, y),
+ FONT_WIDTH (f->display.x->font),
+ f->display.x->line_height, False);
- if (f == 0)
- f = selected_frame;
+ dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
+ CHAR_TO_PIXEL_ROW (f, y),
+ &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
+ end_x - x, highlight_flag, 1);
+ }
+}
+#endif /* 0 */
+\f
+#if 0 /* Not in use yet */
- f->phys_cursor_x = -1; /* Cursor not visible. */
- curs_x = 0; /* Nominal cursor position is top left. */
- curs_y = 0;
-
- BLOCK_INPUT;
+/* Return 1 if character C in font F extends past its left edge. */
- XClear (FRAME_X_WINDOW (f));
+static int
+font_char_overlap_left (font, c)
+ XFontStruct *font;
+ int c;
+{
+ XCharStruct *s;
- /* We have to clear the scroll bars, too. If we have changed
- colors or something like that, then they should be notified. */
- x_scroll_bar_clear (f);
+ /* Find the bounding-box info for C. */
+ if (font->per_char == 0)
+ s = &font->max_bounds;
+ else
+ {
+ int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
+ int row, within;
+
+ /* Decode char into row number (byte 1) and code within row (byte 2). */
+ row = c >> 8;
+ within = c & 0177;
+ if (!(within >= font->min_char_or_byte2
+ && within <= font->max_char_or_byte2
+ && row >= font->min_byte1
+ && row <= font->max_byte1))
+ {
+ /* If char is out of range, try the font's default char instead. */
+ c = font->default_char;
+ row = c >> (INTBITS - 8);
+ within = c & 0177;
+ }
+ if (!(within >= font->min_char_or_byte2
+ && within <= font->max_char_or_byte2
+ && row >= font->min_byte1
+ && row <= font->max_byte1))
+ /* Still out of range means this char does not overlap. */
+ return 0;
+ else
+ /* We found the info for this char. */
+ s = (font->per_char + (within - font->min_char_or_byte2)
+ + row * rowlen);
+ }
-#ifndef HAVE_X11
- dumpborder (f, 0);
-#endif /* HAVE_X11 */
+ return (s && s->lbearing < 0);
+}
- XFlushQueue ();
- UNBLOCK_INPUT;
+/* Return 1 if character C in font F extends past its right edge. */
+
+static int
+font_char_overlap_right (font, c)
+ XFontStruct *font;
+ int c;
+{
+ XCharStruct *s;
+
+ /* Find the bounding-box info for C. */
+ if (font->per_char == 0)
+ s = &font->max_bounds;
+ else
+ {
+ int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
+ int row, within;
+
+ /* Decode char into row number (byte 1) and code within row (byte 2). */
+ row = c >> 8;
+ within = c & 0177;
+ if (!(within >= font->min_char_or_byte2
+ && within <= font->max_char_or_byte2
+ && row >= font->min_byte1
+ && row <= font->max_byte1))
+ {
+ /* If char is out of range, try the font's default char instead. */
+ c = font->default_char;
+ row = c >> (INTBITS - 8);
+ within = c & 0177;
+ }
+ if (!(within >= font->min_char_or_byte2
+ && within <= font->max_char_or_byte2
+ && row >= font->min_byte1
+ && row <= font->max_byte1))
+ /* Still out of range means this char does not overlap. */
+ return 0;
+ else
+ /* We found the info for this char. */
+ s = (font->per_char + (within - font->min_char_or_byte2)
+ + row * rowlen);
+ }
+
+ return (s && s->rbearing >= s->width);
}
+#endif /* 0 */
\f
/* Invert the middle quarter of the frame for .15 sec. */
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 * FONT_HEIGHT (f->display.x->font), intborder,
+ 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 * FONT_HEIGHT (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
XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
CHAR_TO_PIXEL_ROW (f, topregion),
f->width * FONT_WIDTH (f->display.x->font),
- n * FONT_HEIGHT (f->display.x->font), False);
+ 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 * FONT_HEIGHT (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, curs_y),
f->width * FONT_WIDTH (f->display.x->font),
- (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
+ (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) * FONT_HEIGHT (f->display.x->font),
+ (flexlines - curs_y) * f->display.x->line_height,
f->display.x->background_pixel);
#endif /* ! defined (HAVE_X11) */
}
intborder,
CHAR_TO_PIXEL_ROW (f, curs_y + n),
f->width * FONT_WIDTH (f->display.x->font),
- (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
+ (flexlines - (curs_y + n)) * f->display.x->line_height,
intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
XClearArea (x_current_display, FRAME_X_WINDOW (f),
intborder,
CHAR_TO_PIXEL_ROW (f, flexlines - n),
f->width * FONT_WIDTH (f->display.x->font),
- n * FONT_HEIGHT (f->display.x->font), False);
+ 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)) * FONT_HEIGHT (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
XPixSet (FRAME_X_WINDOW (f), intborder,
CHAR_TO_PIXEL_ROW (f, flexlines - n),
f->width * FONT_WIDTH (f->display.x->font),
- n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
+ n * f->display.x->line_height, f->display.x->background_pixel);
#endif /* ! defined (HAVE_X11) */
}
}
/* If the rectangle includes any of the internal border area,
redisplay the border emphasis. */
if (top < intborder || left < intborder
- || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
- || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
+ || 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. */
Round down for left and top, up for right and bottom. */
top = PIXEL_TO_CHAR_ROW (f, top);
left = PIXEL_TO_CHAR_COL (f, left);
- bottom += (FONT_HEIGHT (f->display.x->font) - 1);
+ bottom += (f->display.x->line_height - 1);
right += (FONT_WIDTH (f->display.x->font) - 1);
bottom = PIXEL_TO_CHAR_ROW (f, bottom);
right = PIXEL_TO_CHAR_COL (f, right);
CHAR_TO_PIXEL_COL (f, left),
CHAR_TO_PIXEL_ROW (f, y),
line, min (cols, active_frame->used[y] - left),
- active_frame->highlight[y]);
+ active_frame->highlight[y], 0);
}
/* Turn the cursor on if we turned it off. */
/ FONT_WIDTH (f->display.x->font));
temp_height = ((windowinfo.height- 2 * intborder
- f->display.x->h_scroll_bar_height)
- / FONT_HEIGHT (f->display.x->font));
+ / f->display.x->line_height);
if (temp_width != f->width || temp_height != f->height)
{
change_frame_size (f, max (1, temp_height),
#endif /* ! 0 */
if (x_focus_frame && x_focus_frame->auto_raise)
- x_raise_frame (x_focus_frame);
+ pending_autoraise_frame = x_focus_frame;
+ else
+ pending_autoraise_frame = 0;
}
XTframe_rehighlight ();
if (pix_x < 0)
pix_x -= FONT_WIDTH ((f)->display.x->font) - 1;
if (pix_y < 0)
- pix_y -= FONT_HEIGHT ((f)->display.x->font) - 1;
+ pix_y -= (f)->display.x->line_height - 1;
pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
if (bounds)
{
bounds->width = FONT_WIDTH (f->display.x->font);
- bounds->height = FONT_HEIGHT (f->display.x->font);
+ bounds->height = f->display.x->line_height;
bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
}
if (mouse_face_defer)
return;
+ if (gc_in_progress)
+ {
+ mouse_face_deferred_gc = 1;
+ return;
+ }
+
/* Find out which glyph the mouse is on. */
pixel_to_glyph_coords (f, x, y, &column, &row,
&new_glyph, x_mouse_grabbed);
if (! EQ (window, mouse_face_window))
clear_mouse_face ();
- /* Are we in a window whose display is up to date? */
+ /* 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
- && EQ (w->window_end_valid, Qt))
+ && EQ (w->window_end_valid, w->buffer)
+ && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
{
int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
int i, pos;
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)))
{
Lisp_Object mouse_face, overlay, position;
Lisp_Object *overlay_vec;
int len, noverlays, ignor1;
struct buffer *obuf;
+ int obegv, ozv;
- /* If we get an out-of-range value, return now;
- don't get an error. */
- if (pos > BUF_ZV (XBUFFER (w->buffer)))
+ /* If we get an out-of-range value, return now; avoid an error. */
+ if (pos > BUF_Z (XBUFFER (w->buffer)))
return;
/* Make the window's buffer temporarily current for
overlays_at and compute_char_face. */
obuf = current_buffer;
current_buffer = XBUFFER (w->buffer);
+ obegv = BEGV;
+ ozv = ZV;
+ BEGV = BEG;
+ ZV = Z;
/* Yes. Clear the display of the old active region, if any. */
clear_mouse_face ();
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);
+ 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);
= 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);
+ 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,
/* Display it as active. */
show_mouse_face (1);
}
+ BEGV = obegv;
+ ZV = ozv;
current_buffer = obuf;
}
- else if (pos <= 0)
- clear_mouse_face ();
}
}
\f
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;
- fast_find_position (mouse_face_window, mouse_face_beg,
- &begcol, &begrow);
- fast_find_position (mouse_face_window, mouse_face_end,
- &endcol, &endrow);
-
- x_display_cursor (f, 0);
-
- 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] - w->left);
+
+ /* If the cursor's in the text we are about to rewrite,
+ turn the cursor off. */
+ if (i == curs_y
+ && curs_x >= mouse_face_beg_col - 1 && curs_x <= mouse_face_end_col)
+ {
+ x_display_cursor (f, 0);
+ cursor_off = 1;
+ }
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, column),
FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
endcolumn - column,
/* Highlight with mouse face if hl > 0. */
- hl > 0 ? 3 : 0);
+ hl > 0 ? 3 : 0, 0);
}
- x_display_cursor (f, 1);
+ /* If we turned the cursor off, turn it back on. */
+ if (cursor_off)
+ x_display_cursor (f, 1);
+
+ /* Change the mouse cursor according to the value of HL. */
+ if (hl > 0)
+ XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), f->display.x->cross_cursor);
+ else
+ XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), f->display.x->text_cursor);
}
/* Clear out the mouse-highlighted active region.
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;
}
\f
win = root;
- if (x_mouse_grabbed)
+ if (x_mouse_grabbed && 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. */
/* Window manager communication. */
Atom Xatom_wm_change_state;
+/* EditRes protocol */
+Atom Xatom_editres_name;
+
/* Record the last 100 characters stored
to help debug the loss-of-chars-during-GC problem. */
int temp_index;
{
if (event.xclient.data.l[0] == Xatom_wm_take_focus)
{
-#ifdef USE_X_TOOLKIT
- /* f = x_any_window_to_frame (event.xclient.window); */
- f = x_window_to_frame (event.xclient.window);
-#else
f = x_window_to_frame (event.xclient.window);
-#endif
+ /* 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);
+ XSetInputFocus (event.xclient.display,
+ event.xclient.window,
+ RevertToPointerRoot,
+ event.xclient.data.l[1]);
/* Not certain about handling scroll bars here */
}
else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
f->display.x->top_pos = new_y;
}
}
+#if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
+ else if (event.xclient.message_type == Xatom_editres_name)
+ {
+ struct frame *f = x_any_window_to_frame (event.xclient.window);
+ _XEditResCheckMessages (f->display.x->widget, NULL, &event, NULL);
+ }
+#endif /* USE_X_TOOLKIT and HAVE_X11R5 */
}
break;
-#ifdef NEW_SELECTIONS
case SelectionNotify:
#ifdef USE_X_TOOLKIT
- if (x_window_to_frame (event.xselection.requestor))
- x_handle_selection_notify (&event);
- else
+ if (! x_window_to_frame (event.xselection.requestor))
goto OTHER;
-#else /* not USE_X_TOOLKIT */
- x_handle_selection_notify (&event);
#endif /* not USE_X_TOOLKIT */
+ x_handle_selection_notify (&event);
break;
-#endif /* NEW_SELECTIONS */
case SelectionClear: /* Someone has grabbed ownership. */
-#ifdef NEW_SELECTIONS
- {
#ifdef USE_X_TOOLKIT
- if (x_window_to_frame (event.xselectionclear.window))
- {
+ if (! x_window_to_frame (event.xselectionclear.window))
+ goto OTHER;
#endif /* USE_X_TOOLKIT */
+ {
XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
if (numchars == 0)
count += 1;
numchars -= 1;
-#ifdef USE_X_TOOLKIT
}
- else
- goto OTHER;
-#endif /* USE_X_TOOLKIT */
- }
-#else /* not NEW_SELECTIONS */
- x_disown_selection (event.xselectionclear.window,
- event.xselectionclear.selection,
- event.xselectionclear.time);
-#endif /* not NEW_SELECTIONS */
break;
case SelectionRequest: /* Someone wants our selection. */
-#ifdef NEW_SELECTIONS
- {
#ifdef USE_X_TOOLKIT
- if (x_window_to_frame (event.xselectionrequest.owner))
- {
+ if (!x_window_to_frame (event.xselectionrequest.owner))
+ goto OTHER;
#endif /* USE_X_TOOLKIT */
+ {
XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
if (numchars == 0)
count += 1;
numchars -= 1;
-#ifdef USE_X_TOOLKIT
}
- else
- goto OTHER;
-#endif /* USE_X_TOOLKIT */
- }
-#else /* not NEW_SELECTIONS */
- x_answer_selection_request (event);
-#endif /* not NEW_SELECTIONS */
break;
case PropertyNotify:
-#ifdef NEW_SELECTIONS
#ifdef USE_X_TOOLKIT
- if (x_any_window_to_frame (event.xproperty.window))
- x_handle_property_notify (&event);
- else
+ if (!x_any_window_to_frame (event.xproperty.window))
goto OTHER;
-#else /* not USE_X_TOOLKIT */
- x_handle_property_notify (&event);
#endif /* not USE_X_TOOLKIT */
-#else /* not NEW_SELECTIONS */
- /* If we're being told about a root window property, then it's
- a cut buffer change. */
- if (event.xproperty.window == ROOT_WINDOW)
- x_invalidate_cut_buffer_cache (&event.xproperty);
-
- /* Otherwise, we're probably handling an incremental
- selection transmission. */
- else
- {
- /* If we were to do this synchronously, there'd be no worry
- about re-selecting. */
- x_send_incremental (event);
- }
-#endif /* not NEW_SELECTIONS */
+ x_handle_property_notify (&event);
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:
SET_FRAME_GARBAGED (f);
}
else
- {
- dumprectangle (x_window_to_frame (event.xexpose.window),
- event.xexpose.x, event.xexpose.y,
- event.xexpose.width, event.xexpose.height);
- }
+ dumprectangle (x_window_to_frame (event.xexpose.window),
+ event.xexpose.x, event.xexpose.y,
+ event.xexpose.width, event.xexpose.height);
}
else
{
#ifdef HAVE_X11
case UnmapNotify:
- f = x_window_to_frame (event.xunmap.window);
+ f = x_any_window_to_frame (event.xunmap.window);
if (f) /* F may no longer exist if
the frame was deleted. */
{
disabled; you don't want to spend time updating a
display that won't ever be seen. */
f->async_visible = 0;
- /* The window manager never makes a window invisible
- ("withdrawn"); all it does is switch between visible
- and iconified. Frames get into the invisible state
- only through x_make_frame_invisible. */
+ /* We can't distinguish, from the event, whether the window
+ has become iconified or invisible. So assume, if it
+ was previously visible, than now it is iconified.
+ We depend on x_make_frame_invisible to mark it iconified. */
if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
f->async_iconified = 1;
}
break;
case MapNotify:
-#ifdef USE_X_TOOLKIT
- f = x_any_window_to_frame (event.xmap.window);
-#else /* not USE_X_TOOLKIT */
- f = x_window_to_frame (event.xmap.window);
-#endif /* not USE_X_TOOLKIT */
+ /* We use x_top_window_to_frame because map events can come
+ for subwindows and they don't mean that the frame is visible. */
+ f = x_top_window_to_frame (event.xmap.window);
if (f)
{
f->async_visible = 1;
#ifdef USE_X_TOOLKIT
goto OTHER;
#endif /* USE_X_TOOLKIT */
- break;
+ break;
/* Turn off processing if we become fully obscured. */
case VisibilityNotify:
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;
#ifdef HAVE_X11
case MotionNotify:
{
- if (x_mouse_grabbed)
+ if (x_mouse_grabbed && FRAME_LIVE_P (last_mouse_frame))
f = last_mouse_frame;
else
f = x_window_to_frame (event.xmotion.window);
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;
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 */
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;
+ }
}
#endif /* not USE_X_TOOLKIT */
break;
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;
}
int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
int width = FONT_WIDTH (f->display.x->font);
- int height = FONT_HEIGHT (f->display.x->font);
+ int height = f->display.x->line_height;
#ifdef HAVE_X11
XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
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), FONT_HEIGHT (f->display.x->font),
+ 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;
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, column),
CHAR_TO_PIXEL_ROW (f, row),
- &glyph, 1, highlight);
+ &glyph, 1, highlight, 0);
}
static void
f->display.x->cursor_gc,
CHAR_TO_PIXEL_COL (f, curs_x),
CHAR_TO_PIXEL_ROW (f, curs_y),
- 1, FONT_HEIGHT (f->display.x->font));
+ 1, f->display.x->line_height);
f->phys_cursor_x = curs_x;
f->phys_cursor_y = curs_y;
|| (f->display.x->current_cursor != hollow_box_cursor
&& (f != x_highlight_frame))))
{
+ /* 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)
+ XClearArea (x_current_display, 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, False);
/* 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,
XSetFont (x_current_display, f->display.x->cursor_gc,
f->display.x->font->fid);
+ frame_update_line_height (f);
x_set_window_size (f, 0, f->width, f->height);
}
+ else
+ /* If we are setting a new frame's font for the first time,
+ there are no faces yet, so this font's height is the line height. */
+ f->display.x->line_height = FONT_HEIGHT (f->display.x->font);
{
Lisp_Object lispy_name;
#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. */
/* 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);
-
+ /* 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);
#else /* ! defined (HAVE_X11) */
WINDOWINFO_TYPE parentinfo;
#endif /* ! defined (HAVE_X11) */
}
-x_set_offset (f, xoff, yoff)
+/* 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);
XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
f->display.x->left_pos, f->display.x->top_pos);
#endif /* not USE_X_TOOLKIT */
-#ifdef HAVE_X11
- x_wm_set_size_hint (f, 0, 1, xoff, yoff);
-#endif /* ! defined (HAVE_X11) */
UNBLOCK_INPUT;
}
#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 */
pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
#ifdef HAVE_X11
- x_wm_set_size_hint (f, 0, change_gravity, 0, 0);
+ f->display.x->win_gravity = NorthWestGravity;
+ x_wm_set_size_hint (f, 0, 0);
#endif /* ! defined (HAVE_X11) */
+ XSync (x_current_display, False);
XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
/* Now, strictly speaking, we can't be sure that this is accurate,
2 * f->display.x->internal_border_width,
2 * f->display.x->internal_border_width,
FONT_WIDTH (f->display.x->font),
- FONT_HEIGHT (f->display.x->font));
+ f->display.x->line_height);
}
#endif /* HAVE_X11 */
\f
/* Mouse warping, focus shifting, raising and lowering. */
+void
x_set_mouse_position (f, x, y)
struct frame *f;
int x, y;
{
int pix_x, pix_y;
-#if 0 /* Let the user ask for this if he wants it. */
- x_raise_frame (f);
-#endif
-
pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
- pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
+ pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->display.x->line_height / 2;
if (pix_x < 0) pix_x = 0;
if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
UNBLOCK_INPUT;
}
+/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
+
+void
+x_set_mouse_pixel_position (f, pix_x, pix_y)
+ struct frame *f;
+ int pix_x, pix_y;
+{
+ BLOCK_INPUT;
+
+ XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
+ UNBLOCK_INPUT;
+}
+
#ifdef HAVE_X11
x_focus_on_frame (f)
struct frame *f;
if (! FRAME_VISIBLE_P (f))
{
#ifdef HAVE_X11
+#ifndef USE_X_TOOLKIT
+ 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 */
+#if 0 /* This seems to bring back scroll bars in the wrong places
+ if the window configuration has changed. They seem
+ to come back ok without this. */
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)
if (x_highlight_frame == f)
x_highlight_frame = 0;
+#if 0/* This might add unreliability; I don't trust it -- rms. */
if (! f->async_visible && ! f->async_iconified)
return;
+#endif
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
#else /* not USE_X_TOOLKIT */
if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
DefaultScreen (x_current_display)))
-#endif /* not USE_X_TOOLKIT */
{
UNBLOCK_INPUT_RESIGNAL;
error ("can't notify window manager of window withdrawal");
}
+#endif /* not USE_X_TOOLKIT */
#else /* ! defined (HAVE_X11R4) */
#ifdef HAVE_X11
#else /* ! defined (HAVE_X11) */
XUnmapWindow (FRAME_X_WINDOW (f));
- f->async_visible = 0; /* Handled by the UnMap event for X11 */
if (f->display.x->icon_desc != 0)
XUnmapWindow (f->display.x->icon_desc);
#endif /* ! defined (HAVE_X11) */
#endif /* ! defined (HAVE_X11R4) */
- XFlushQueue ();
+ /* We can't distinguish this from iconification
+ just by the event that we get from the server.
+ So we can't win using the usual strategy of letting
+ FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
+ and synchronize with the server to make sure we agree. */
+ f->visible = 0;
+ FRAME_ICONIFIED_P (f) = 0;
+ f->async_visible = 0;
+ f->async_iconified = 0;
+
+ x_sync ();
+
UNBLOCK_INPUT;
}
{
/* If the frame was withdrawn, before, we must map it. */
XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
+#if 0 /* We don't have subwindows in the icon. */
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
+#endif
}
f->async_iconified = 1;
if (f == x_highlight_frame)
x_highlight_frame = 0;
+ if (f == mouse_face_mouse_frame)
+ {
+ mouse_face_beg_row = mouse_face_beg_col = -1;
+ mouse_face_end_row = mouse_face_end_col = -1;
+ mouse_face_window = Qnil;
+ }
+
UNBLOCK_INPUT;
}
\f
#ifdef HAVE_X11
-/* Record the gravity used previously, in case CHANGE_GRAVITY is 0. */
-static int previous_gravity;
+/* 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). */
-/* 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 ignore SPEC_X and SPEC_Y
- and leave the gravity unchanged. */
-
-x_wm_set_size_hint (f, prompting, change_gravity, spec_x, spec_y)
+x_wm_set_size_hint (f, flags, user_position)
struct frame *f;
- long prompting;
- int change_gravity;
- int spec_x, spec_y;
+ long flags;
+ int user_position;
{
XSizeHints size_hints;
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++;
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 = FONT_HEIGHT (f->display.x->font);
-#if 0
+ 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);
-#endif
+
{
int base_width, base_height;
+ int min_rows = 0, min_cols = 0;
base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
- {
- int min_rows = 0, min_cols = 0;
- check_frame_size (f, &min_rows, &min_cols);
-
- /* The window manager uses the base width hints to calculate the
- current number of rows and columns in the frame while
- resizing; min_width and min_height aren't useful for this
- purpose, since they might not give the dimensions for a
- zero-row, zero-column frame.
+ check_frame_size (f, &min_rows, &min_cols);
- We use the base_width and base_height members if we have
- them; otherwise, we set the min_width and min_height members
- to the size for a zero x zero frame. */
+ /* The window manager uses the base width hints to calculate the
+ current number of rows and columns in the frame while
+ resizing; min_width and min_height aren't useful for this
+ purpose, since they might not give the dimensions for a
+ zero-row, zero-column frame.
+
+ We use the base_width and base_height members if we have
+ them; otherwise, we set the min_width and min_height members
+ to the size for a zero x zero frame. */
#ifdef HAVE_X11R4
- size_hints.flags |= PBaseSize;
- size_hints.base_width = base_width;
- size_hints.base_height = base_height;
- size_hints.min_width = base_width + min_cols * size_hints.width_inc;
- size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+ size_hints.flags |= PBaseSize;
+ size_hints.base_width = base_width;
+ size_hints.base_height = base_height;
+ size_hints.min_width = base_width + min_cols * size_hints.width_inc;
+ size_hints.min_height = base_height + min_rows * size_hints.height_inc;
#else
- size_hints.min_width = base_width;
- size_hints.min_height = base_height;
+ size_hints.min_width = base_width;
+ size_hints.min_height = base_height;
#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;
if (hints.flags & USSize)
size_hints.flags |= USSize;
}
-#if defined (PWinGravity)
- if (change_gravity)
- {
- switch (((spec_x < 0) << 1) + (spec_y < 0))
- {
- case 0:
- size_hints.win_gravity = NorthWestGravity;
- break;
- case 1:
- size_hints.win_gravity = NorthEastGravity;
- break;
- case 2:
- size_hints.win_gravity = SouthWestGravity;
- break;
- case 3:
- size_hints.win_gravity = SouthEastGravity;
- break;
- }
- previous_gravity = size_hints.win_gravity;
- }
- else
- size_hints.win_gravity = previous_gravity;
+#ifdef PWinGravity
+ size_hints.win_gravity = f->display.x->win_gravity;
size_hints.flags |= PWinGravity;
+
+ if (user_position)
+ {
+ size_hints.flags &= ~ PPosition;
+ size_hints.flags |= USPosition;
+ }
#endif /* PWinGravity */
#ifdef HAVE_X11R4
x_focus_frame = x_highlight_frame = 0;
#ifdef USE_X_TOOLKIT
- argv = (char **) XtMalloc (3 * sizeof (char *));
+ argv = (char **) XtMalloc (5 * sizeof (char *));
argv [0] = "";
argv [1] = "-display";
argv [2] = display_name;
- argc = 3;
+ argv [3] = "-name";
+ argv [4] = "emacs";
+ argc = 5;
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 */