(XTread_socket, case KeyPress) [HPUX]: Test IsModifiedKey.
[emacs.git] / src / xterm.c
blob77cc54021dd76106a9110a38e688756c7a53bb45
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Serious problems:
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 #define NEW_SELECTIONS
30 /* On 4.3 these lose if they come after xterm.h. */
31 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
32 /* Putting these at the beginning seems to be standard for other .c files. */
33 #include <stdio.h>
34 #include <signal.h>
36 #include "config.h"
38 #ifdef HAVE_X_WINDOWS
40 #include "lisp.h"
41 #include "blockinput.h"
43 /* This may include sys/types.h, and that somehow loses
44 if this is not done before the other system files. */
45 #include "xterm.h"
46 #include <X11/cursorfont.h>
48 #ifndef USG
49 /* Load sys/types.h if not already loaded.
50 In some systems loading it twice is suicidal. */
51 #ifndef makedev
52 #include <sys/types.h>
53 #endif /* makedev */
54 #endif /* USG */
56 #ifdef BSD
57 #include <sys/ioctl.h>
58 #include <strings.h>
59 #else /* ! defined (BSD) */
60 #ifndef VMS
61 #include <string.h>
62 #endif
63 #endif /* ! defined (BSD) */
65 #include "systty.h"
66 #include "systime.h"
68 #include <fcntl.h>
69 #include <ctype.h>
70 #include <errno.h>
71 #include <setjmp.h>
72 #include <sys/stat.h>
73 #include <sys/param.h>
75 #include "dispextern.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #if 0
80 #include "sink.h"
81 #include "sinkmask.h"
82 #endif /* ! 0 */
83 #include "gnu.h"
84 #include "frame.h"
85 #include "disptab.h"
86 #include "buffer.h"
87 #include "window.h"
89 #ifdef HAVE_X11
90 #define XMapWindow XMapRaised /* Raise them when mapping. */
91 #else /* ! defined (HAVE_X11) */
92 #include <X/Xkeyboard.h>
93 /*#include <X/Xproto.h> */
94 #endif /* ! defined (HAVE_X11) */
96 /* For sending Meta-characters. Do we need this? */
97 #define METABIT 0200
99 #define min(a,b) ((a)<(b) ? (a) : (b))
100 #define max(a,b) ((a)>(b) ? (a) : (b))
102 /* Nonzero means we must reprint all windows
103 because 1) we received an ExposeWindow event
104 or 2) we received too many ExposeRegion events to record.
106 This is never needed under X11. */
107 static int expose_all_windows;
109 /* Nonzero means we must reprint all icon windows. */
111 static int expose_all_icons;
113 #ifndef HAVE_X11
114 /* ExposeRegion events, when received, are copied into this queue
115 for later processing. */
117 static struct event_queue x_expose_queue;
119 /* ButtonPressed and ButtonReleased events, when received,
120 are copied into this queue for later processing. */
122 struct event_queue x_mouse_queue;
123 #endif /* HAVE_X11 */
125 #if defined (SIGIO) && defined (FIONREAD)
126 int BLOCK_INPUT_mask;
127 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
129 /* The id of a bitmap used for icon windows.
130 One such map is shared by all Emacs icon windows.
131 This is zero if we have not yet had a need to create the bitmap. */
133 static Bitmap icon_bitmap;
135 /* Font used for text icons. */
137 static FONT_TYPE *icon_font_info;
139 /* Stuff for dealing with the main icon title. */
141 extern Lisp_Object Vcommand_line_args;
142 char *hostname, *x_id_name;
144 /* This is the X connection that we are using. */
146 Display *x_current_display;
148 /* The cursor to use for vertical scroll bars on x_current_display. */
149 static Cursor x_vertical_scroll_bar_cursor;
151 /* Frame being updated by update_frame. This is declared in term.c.
152 This is set by update_begin and looked at by all the
153 XT functions. It is zero while not inside an update.
154 In that case, the XT functions assume that `selected_frame'
155 is the frame to apply to. */
156 extern struct frame *updating_frame;
158 /* The frame (if any) which has the X window that has keyboard focus.
159 Zero if none. This is examined by Ffocus_frame in frame.c. Note
160 that a mere EnterNotify event can set this; if you need to know the
161 last frame specified in a FocusIn or FocusOut event, use
162 x_focus_event_frame. */
163 struct frame *x_focus_frame;
165 /* The last frame mentioned in a FocusIn or FocusOut event. This is
166 separate from x_focus_frame, because whether or not LeaveNotify
167 events cause us to lose focus depends on whether or not we have
168 received a FocusIn event for it. */
169 struct frame *x_focus_event_frame;
171 /* The frame which currently has the visual highlight, and should get
172 keyboard input (other sorts of input have the frame encoded in the
173 event). It points to the X focus frame's selected window's
174 frame. It differs from x_focus_frame when we're using a global
175 minibuffer. */
176 static struct frame *x_highlight_frame;
178 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
179 mouse is moved to inside of frame when frame is de-iconified. */
181 static int warp_mouse_on_deiconify;
183 /* During an update, maximum vpos for ins/del line operations to affect. */
185 static int flexlines;
187 /* During an update, nonzero if chars output now should be highlighted. */
189 static int highlight;
191 /* Nominal cursor position -- where to draw output.
192 During an update, these are different from the cursor-box position. */
194 static int curs_x;
195 static int curs_y;
197 #ifdef HAVE_X11
198 /* `t' if a mouse button is depressed. */
200 extern Lisp_Object Vmouse_depressed;
202 /* Tells if a window manager is present or not. */
204 extern Lisp_Object Vx_no_window_manager;
206 /* Timestamp that we requested selection data was made. */
207 extern Time requestor_time;
209 /* ID of the window requesting selection data. */
210 extern Window requestor_window;
212 /* Nonzero enables some debugging for the X interface code. */
213 extern int _Xdebug;
215 #else /* ! defined (HAVE_X11) */
217 /* Bit patterns for the mouse cursor. */
219 short MouseCursor[] = {
220 0x0000, 0x0008, 0x0018, 0x0038,
221 0x0078, 0x00f8, 0x01f8, 0x03f8,
222 0x07f8, 0x00f8, 0x00d8, 0x0188,
223 0x0180, 0x0300, 0x0300, 0x0000};
225 short MouseMask[] = {
226 0x000c, 0x001c, 0x003c, 0x007c,
227 0x00fc, 0x01fc, 0x03fc, 0x07fc,
228 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
229 0x03cc, 0x0780, 0x0780, 0x0300};
231 static short grey_bits[] = {
232 0x0005, 0x000a, 0x0005, 0x000a};
234 static Pixmap GreyPixmap = 0;
235 #endif /* ! defined (HAVE_X11) */
237 /* From time to time we get info on an Emacs window, here. */
239 static WINDOWINFO_TYPE windowinfo;
241 extern int errno;
243 /* A mask of extra modifier bits to put into every keyboard char. */
244 extern int extra_keyboard_modifiers;
246 extern Display *XOpenDisplay ();
247 extern Window XCreateWindow ();
249 extern Cursor XCreateCursor ();
250 extern FONT_TYPE *XOpenFont ();
252 static void flashback ();
254 #ifndef HAVE_X11
255 static void dumpqueue ();
256 #endif /* HAVE_X11 */
258 void dumpborder ();
259 static int XTcursor_to ();
260 static int XTclear_end_of_line ();
263 /* Starting and ending updates.
265 These hooks are called by update_frame at the beginning and end
266 of a frame update. We record in `updating_frame' the identity
267 of the frame being updated, so that the XT... functions do not
268 need to take a frame as argument. Most of the XT... functions
269 should never be called except during an update, the only exceptions
270 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
272 extern int mouse_track_top, mouse_track_left, mouse_track_width;
274 static
275 XTupdate_begin (f)
276 struct frame *f;
278 int mask;
280 if (f == 0)
281 abort ();
283 flexlines = f->height;
284 highlight = 0;
286 BLOCK_INPUT;
287 #ifndef HAVE_X11
288 dumpqueue ();
289 #endif /* HAVE_X11 */
290 UNBLOCK_INPUT;
293 #ifndef HAVE_X11
294 static void x_do_pending_expose ();
295 #endif
297 static
298 XTupdate_end (f)
299 struct frame *f;
301 int mask;
303 if (updating_frame == 0
304 || updating_frame != f)
305 abort ();
307 BLOCK_INPUT;
308 #ifndef HAVE_X11
309 dumpqueue ();
310 x_do_pending_expose ();
311 #endif /* HAVE_X11 */
313 x_display_cursor (f, 1);
315 XFlushQueue ();
316 UNBLOCK_INPUT;
319 /* External interface to control of standout mode.
320 Call this when about to modify line at position VPOS
321 and not change whether it is highlighted. */
323 XTreassert_line_highlight (new, vpos)
324 int new, vpos;
326 highlight = new;
329 /* Call this when about to modify line at position VPOS
330 and change whether it is highlighted. */
332 static
333 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
334 int new_highlight, vpos, first_unused_hpos;
336 highlight = new_highlight;
337 XTcursor_to (vpos, 0);
338 XTclear_end_of_line (updating_frame->width);
341 /* This is used when starting Emacs and when restarting after suspend.
342 When starting Emacs, no X window is mapped. And nothing must be done
343 to Emacs's own window if it is suspended (though that rarely happens). */
345 static
346 XTset_terminal_modes ()
350 /* This is called when exiting or suspending Emacs.
351 Exiting will make the X-windows go away, and suspending
352 requires no action. */
354 static
355 XTreset_terminal_modes ()
357 /* XTclear_frame (); */
360 /* Set the nominal cursor position of the frame.
361 This is where display update commands will take effect.
362 This does not affect the place where the cursor-box is displayed. */
364 static int
365 XTcursor_to (row, col)
366 register int row, col;
368 int mask;
369 int orow = row;
371 curs_x = col;
372 curs_y = row;
374 if (updating_frame == 0)
376 BLOCK_INPUT;
377 x_display_cursor (selected_frame, 1);
378 XFlushQueue ();
379 UNBLOCK_INPUT;
383 /* Display a sequence of N glyphs found at GP.
384 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
385 HL is 1 if this text is highlighted, 2 if the cursor is on it.
387 FONT is the default font to use (for glyphs whose font-code is 0).
389 Since the display generation code is responsible for calling
390 compute_char_face and compute_glyph_face on everything it puts in
391 the display structure, we can assume that the face code on each
392 glyph is a valid index into FRAME_FACES (f), and the one to which
393 we can actually apply intern_face. */
395 #if 1
396 /* This is the multi-face code. */
398 static void
399 dumpglyphs (f, left, top, gp, n, hl)
400 struct frame *f;
401 int left, top;
402 register GLYPH *gp; /* Points to first GLYPH. */
403 register int n; /* Number of glyphs to display. */
404 int hl;
406 /* Holds characters to be displayed. */
407 char *buf = (char *) alloca (f->width * sizeof (*buf));
408 register char *cp; /* Steps through buf[]. */
409 register int tlen = GLYPH_TABLE_LENGTH;
410 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
411 Window window = FRAME_X_WINDOW (f);
413 while (n > 0)
415 /* Get the face-code of the next GLYPH. */
416 int cf, len;
417 int g = *gp;
419 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
420 cf = GLYPH_FACE (g);
422 /* Find the run of consecutive glyphs with the same face-code.
423 Extract their character codes into BUF. */
424 cp = buf;
425 while (n > 0)
427 g = *gp;
428 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
429 if (GLYPH_FACE (g) != cf)
430 break;
432 *cp++ = GLYPH_CHAR (g);
433 --n;
434 ++gp;
437 /* LEN gets the length of the run. */
438 len = cp - buf;
440 /* Now output this run of chars, with the font and pixel values
441 determined by the face code CF. */
443 struct face *face = FRAME_DEFAULT_FACE (f);
444 FONT_TYPE *font = FACE_FONT (face);
445 GC gc = FACE_GC (face);
446 int defaulted = 1;
447 int gc_temporary = 0;
449 /* First look at the face of the text itself. */
450 if (cf != 0)
452 /* The face codes on the glyphs must be valid indices into the
453 frame's face table. */
454 if (cf < 0 || cf >= FRAME_N_FACES (f))
455 abort ();
457 if (cf == 1)
458 face = FRAME_MODE_LINE_FACE (f);
459 else
460 face = intern_face (f, FRAME_FACES (f) [cf]);
461 font = FACE_FONT (face);
462 gc = FACE_GC (face);
463 defaulted = 0;
466 /* Then comes the distinction between modeline and normal text. */
467 else if (hl == 0)
469 else if (hl == 1)
471 face = FRAME_MODE_LINE_FACE (f);
472 font = FACE_FONT (face);
473 gc = FACE_GC (face);
474 defaulted = 0;
477 #define FACE_DEFAULT (~0)
479 /* Now override that if the cursor's on this character. */
480 if (hl == 2)
482 if (defaulted
483 || !face->font
484 || (int) face->font == FACE_DEFAULT)
486 gc = f->display.x->cursor_gc;
488 /* Cursor on non-default face: must merge. */
489 else
491 XGCValues xgcv;
492 unsigned long mask;
494 xgcv.background = f->display.x->cursor_pixel;
495 xgcv.foreground = f->display.x->cursor_foreground_pixel;
496 xgcv.font = face->font->fid;
497 xgcv.graphics_exposures = 0;
498 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
499 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
500 mask, &xgcv);
501 #if 0
502 if (face->stipple && face->stipple != FACE_DEFAULT)
503 XSetStipple (x_current_display, gc, face->stipple);
504 #endif
505 gc_temporary = 1;
509 if ((int) font == FACE_DEFAULT)
510 font = f->display.x->font;
512 XDrawImageString (x_current_display, window, gc,
513 left, top + FONT_BASE (font), buf, len);
515 if (gc_temporary)
516 XFreeGC (x_current_display, gc);
518 /* We should probably check for XA_UNDERLINE_POSITION and
519 XA_UNDERLINE_THICKNESS properties on the font, but let's
520 just get the thing working, and come back to that. */
522 int underline_position = 1;
524 if (font->descent <= underline_position)
525 underline_position = font->descent - 1;
527 if (face->underline)
528 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
529 FACE_GC (face),
530 left, (top
531 + FONT_BASE (font)
532 + underline_position),
533 len * FONT_WIDTH (font), 1);
536 left += len * FONT_WIDTH (font);
540 #endif /* 1 */
542 #if 0
543 /* This is the old single-face code. */
545 static void
546 dumpglyphs (f, left, top, gp, n, hl, font)
547 struct frame *f;
548 int left, top;
549 register GLYPH *gp; /* Points to first GLYPH. */
550 register int n; /* Number of glyphs to display. */
551 int hl;
552 FONT_TYPE *font;
554 register int len;
555 Window window = FRAME_X_WINDOW (f);
556 GC drawing_gc = (hl == 2 ? f->display.x->cursor_gc
557 : (hl ? f->display.x->reverse_gc
558 : f->display.x->normal_gc));
560 if (sizeof (GLYPH) == sizeof (XChar2b))
561 XDrawImageString16 (x_current_display, window, drawing_gc,
562 left, top + FONT_BASE (font), (XChar2b *) gp, n);
563 else if (sizeof (GLYPH) == sizeof (unsigned char))
564 XDrawImageString (x_current_display, window, drawing_gc,
565 left, top + FONT_BASE (font), (char *) gp, n);
566 else
567 /* What size of glyph ARE you using? And does X have a function to
568 draw them? */
569 abort ();
571 #endif
573 /* Output some text at the nominal frame cursor position.
574 Advance the cursor over the text.
575 Output LEN glyphs at START.
577 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
578 controls the pixel values used for foreground and background. */
580 static
581 XTwrite_glyphs (start, len)
582 register GLYPH *start;
583 int len;
585 register int temp_length;
586 int mask;
587 struct frame *f;
589 BLOCK_INPUT;
591 f = updating_frame;
592 if (f == 0)
594 f = selected_frame;
595 /* If not within an update,
596 output at the frame's visible cursor. */
597 curs_x = f->cursor_x;
598 curs_y = f->cursor_y;
601 dumpglyphs (f,
602 CHAR_TO_PIXEL_COL (f, curs_x),
603 CHAR_TO_PIXEL_ROW (f, curs_y),
604 start, len, highlight);
606 /* If we drew on top of the cursor, note that it is turned off. */
607 if (curs_y == f->phys_cursor_y
608 && curs_x <= f->phys_cursor_x
609 && curs_x + len > f->phys_cursor_x)
610 f->phys_cursor_x = -1;
612 if (updating_frame == 0)
614 f->cursor_x += len;
615 x_display_cursor (f, 1);
616 f->cursor_x -= len;
618 else
619 curs_x += len;
621 UNBLOCK_INPUT;
624 /* Clear to the end of the line.
625 Erase the current text line from the nominal cursor position (inclusive)
626 to column FIRST_UNUSED (exclusive). The idea is that everything
627 from FIRST_UNUSED onward is already erased. */
629 static int
630 XTclear_end_of_line (first_unused)
631 register int first_unused;
633 struct frame *f = updating_frame;
634 int mask;
636 if (f == 0)
637 abort ();
639 if (curs_y < 0 || curs_y >= f->height)
640 return;
641 if (first_unused <= 0)
642 return;
644 if (first_unused >= f->width)
645 first_unused = f->width;
647 BLOCK_INPUT;
649 /* Notice if the cursor will be cleared by this operation. */
650 if (curs_y == f->phys_cursor_y
651 && curs_x <= f->phys_cursor_x
652 && f->phys_cursor_x < first_unused)
653 f->phys_cursor_x = -1;
655 #ifdef HAVE_X11
656 XClearArea (x_current_display, FRAME_X_WINDOW (f),
657 CHAR_TO_PIXEL_COL (f, curs_x),
658 CHAR_TO_PIXEL_ROW (f, curs_y),
659 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
660 FONT_HEIGHT (f->display.x->font), False);
662 #else /* ! defined (HAVE_X11) */
663 XPixSet (FRAME_X_WINDOW (f),
664 CHAR_TO_PIXEL_COL (f, curs_x),
665 CHAR_TO_PIXEL_ROW (f, curs_y),
666 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
667 FONT_HEIGHT (f->display.x->font),
668 f->display.x->background_pixel);
669 #endif /* ! defined (HAVE_X11) */
671 UNBLOCK_INPUT;
674 static
675 XTclear_frame ()
677 int mask;
678 struct frame *f = updating_frame;
680 if (f == 0)
681 f = selected_frame;
683 f->phys_cursor_x = -1; /* Cursor not visible. */
684 curs_x = 0; /* Nominal cursor position is top left. */
685 curs_y = 0;
687 BLOCK_INPUT;
689 XClear (FRAME_X_WINDOW (f));
691 /* We have to clear the scroll bars, too. If we have changed
692 colors or something like that, then they should be notified. */
693 x_scroll_bar_clear (f);
695 #ifndef HAVE_X11
696 dumpborder (f, 0);
697 #endif /* HAVE_X11 */
699 XFlushQueue ();
700 UNBLOCK_INPUT;
703 /* Invert the middle quarter of the frame for .15 sec. */
705 /* We use the select system call to do the waiting, so we have to make sure
706 it's avaliable. If it isn't, we just won't do visual bells. */
707 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
709 /* Subtract the `struct timeval' values X and Y,
710 storing the result in RESULT.
711 Return 1 if the difference is negative, otherwise 0. */
713 static int
714 timeval_subtract (result, x, y)
715 struct timeval *result, x, y;
717 /* Perform the carry for the later subtraction by updating y.
718 This is safer because on some systems
719 the tv_sec member is unsigned. */
720 if (x.tv_usec < y.tv_usec)
722 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
723 y.tv_usec -= 1000000 * nsec;
724 y.tv_sec += nsec;
726 if (x.tv_usec - y.tv_usec > 1000000)
728 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
729 y.tv_usec += 1000000 * nsec;
730 y.tv_sec -= nsec;
733 /* Compute the time remaining to wait. tv_usec is certainly positive. */
734 result->tv_sec = x.tv_sec - y.tv_sec;
735 result->tv_usec = x.tv_usec - y.tv_usec;
737 /* Return indication of whether the result should be considered negative. */
738 return x.tv_sec < y.tv_sec;
741 XTflash (f)
742 struct frame *f;
744 BLOCK_INPUT;
747 GC gc;
749 /* Create a GC that will use the GXxor function to flip foreground pixels
750 into background pixels. */
752 XGCValues values;
754 values.function = GXxor;
755 values.foreground = (f->display.x->foreground_pixel
756 ^ f->display.x->background_pixel);
758 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
759 GCFunction | GCForeground, &values);
763 int width = PIXEL_WIDTH (f);
764 int height = PIXEL_HEIGHT (f);
766 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
767 width/4, height/4, width/2, height/2);
768 XFlush (x_current_display);
771 struct timeval wakeup, now;
773 gettimeofday (&wakeup, (struct timezone *) 0);
775 /* Compute time to wait until, propagating carry from usecs. */
776 wakeup.tv_usec += 150000;
777 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
778 wakeup.tv_usec %= 1000000;
780 /* Keep waiting until past the time wakeup. */
781 while (1)
783 struct timeval timeout;
785 gettimeofday (&timeout, (struct timezone *)0);
787 /* In effect, timeout = wakeup - timeout.
788 Break if result would be negative. */
789 if (timeval_subtract (&timeout, wakeup, timeout))
790 break;
792 /* Try to wait that long--but we might wake up sooner. */
793 select (0, 0, 0, 0, &timeout);
797 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
798 width/4, height/4, width/2, height/2);
799 XFreeGC (x_current_display, gc);
800 XFlush (x_current_display);
804 UNBLOCK_INPUT;
807 #endif
810 /* Make audible bell. */
812 #ifdef HAVE_X11
813 #define XRINGBELL XBell(x_current_display, 0)
814 #else /* ! defined (HAVE_X11) */
815 #define XRINGBELL XFeep(0);
816 #endif /* ! defined (HAVE_X11) */
818 XTring_bell ()
820 if (x_current_display == 0)
821 return;
823 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
824 if (visible_bell)
825 XTflash (selected_frame);
826 else
827 #endif
829 BLOCK_INPUT;
830 XRINGBELL;
831 XFlushQueue ();
832 UNBLOCK_INPUT;
836 /* Insert and delete character.
837 These are not supposed to be used because we are supposed to turn
838 off the feature of using them. */
840 static
841 XTinsert_glyphs (start, len)
842 register char *start;
843 register int len;
845 abort ();
848 static
849 XTdelete_glyphs (n)
850 register int n;
852 abort ();
855 /* Specify how many text lines, from the top of the window,
856 should be affected by insert-lines and delete-lines operations.
857 This, and those operations, are used only within an update
858 that is bounded by calls to XTupdate_begin and XTupdate_end. */
860 static
861 XTset_terminal_window (n)
862 register int n;
864 if (updating_frame == 0)
865 abort ();
867 if ((n <= 0) || (n > updating_frame->height))
868 flexlines = updating_frame->height;
869 else
870 flexlines = n;
873 /* Perform an insert-lines operation.
874 Insert N lines at a vertical position curs_y. */
876 static void
877 stufflines (n)
878 register int n;
880 register int topregion, bottomregion;
881 register int length, newtop, mask;
882 register struct frame *f = updating_frame;
883 int intborder = f->display.x->internal_border_width;
885 if (curs_y >= flexlines)
886 return;
888 topregion = curs_y;
889 bottomregion = flexlines - (n + 1);
890 newtop = topregion + n;
891 length = (bottomregion - topregion) + 1;
893 #ifndef HAVE_X11
894 dumpqueue ();
895 #endif /* HAVE_X11 */
897 if ((length > 0) && (newtop <= flexlines))
899 #ifdef HAVE_X11
900 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
901 FRAME_X_WINDOW (f), f->display.x->normal_gc,
902 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
903 f->width * FONT_WIDTH (f->display.x->font),
904 length * FONT_HEIGHT (f->display.x->font), intborder,
905 CHAR_TO_PIXEL_ROW (f, newtop));
906 #else /* ! defined (HAVE_X11) */
907 XMoveArea (FRAME_X_WINDOW (f),
908 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
909 intborder, CHAR_TO_PIXEL_ROW (f, newtop),
910 f->width * FONT_WIDTH (f->display.x->font),
911 length * FONT_HEIGHT (f->display.x->font));
912 /* Now we must process any ExposeRegion events that occur
913 if the area being copied from is obscured.
914 We can't let it wait because further i/d operations
915 may want to copy this area to another area. */
916 x_read_exposes ();
917 #endif /* ! defined (HAVE_X11) */
920 newtop = min (newtop, (flexlines - 1));
921 length = newtop - topregion;
922 if (length > 0)
924 #ifdef HAVE_X11
925 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
926 CHAR_TO_PIXEL_ROW (f, topregion),
927 f->width * FONT_WIDTH (f->display.x->font),
928 n * FONT_HEIGHT (f->display.x->font), False);
929 #else /* ! defined (HAVE_X11) */
930 XPixSet (FRAME_X_WINDOW (f),
931 intborder,
932 CHAR_TO_PIXEL_ROW (f, topregion),
933 f->width * FONT_WIDTH (f->display.x->font),
934 n * FONT_HEIGHT (f->display.x->font),
935 f->display.x->background_pixel);
936 #endif /* ! defined (HAVE_X11) */
940 /* Perform a delete-lines operation, deleting N lines
941 at a vertical position curs_y. */
943 static void
944 scraplines (n)
945 register int n;
947 int mask;
948 register struct frame *f = updating_frame;
949 int intborder = f->display.x->internal_border_width;
951 if (curs_y >= flexlines)
952 return;
954 #ifndef HAVE_X11
955 dumpqueue ();
956 #endif /* HAVE_X11 */
958 if ((curs_y + n) >= flexlines)
960 if (flexlines >= (curs_y + 1))
962 #ifdef HAVE_X11
963 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
964 CHAR_TO_PIXEL_ROW (f, curs_y),
965 f->width * FONT_WIDTH (f->display.x->font),
966 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
967 #else /* ! defined (HAVE_X11) */
968 XPixSet (FRAME_X_WINDOW (f),
969 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
970 f->width * FONT_WIDTH (f->display.x->font),
971 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font),
972 f->display.x->background_pixel);
973 #endif /* ! defined (HAVE_X11) */
976 else
978 #ifdef HAVE_X11
979 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
980 FRAME_X_WINDOW (f), f->display.x->normal_gc,
981 intborder,
982 CHAR_TO_PIXEL_ROW (f, curs_y + n),
983 f->width * FONT_WIDTH (f->display.x->font),
984 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
985 intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
986 XClearArea (x_current_display, FRAME_X_WINDOW (f),
987 intborder,
988 CHAR_TO_PIXEL_ROW (f, flexlines - n),
989 f->width * FONT_WIDTH (f->display.x->font),
990 n * FONT_HEIGHT (f->display.x->font), False);
991 #else /* ! defined (HAVE_X11) */
992 XMoveArea (FRAME_X_WINDOW (f),
993 intborder,
994 CHAR_TO_PIXEL_ROW (f, curs_y + n),
995 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
996 f->width * FONT_WIDTH (f->display.x->font),
997 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font));
998 /* Now we must process any ExposeRegion events that occur
999 if the area being copied from is obscured.
1000 We can't let it wait because further i/d operations
1001 may want to copy this area to another area. */
1002 x_read_exposes ();
1003 XPixSet (FRAME_X_WINDOW (f), intborder,
1004 CHAR_TO_PIXEL_ROW (f, flexlines - n),
1005 f->width * FONT_WIDTH (f->display.x->font),
1006 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
1007 #endif /* ! defined (HAVE_X11) */
1011 /* Perform an insert-lines or delete-lines operation,
1012 inserting N lines or deleting -N lines at vertical position VPOS. */
1014 XTins_del_lines (vpos, n)
1015 int vpos, n;
1017 if (updating_frame == 0)
1018 abort ();
1020 /* Hide the cursor. */
1021 x_display_cursor (updating_frame, 0);
1023 XTcursor_to (vpos, 0);
1025 BLOCK_INPUT;
1026 if (n >= 0)
1027 stufflines (n);
1028 else
1029 scraplines (-n);
1030 XFlushQueue ();
1031 UNBLOCK_INPUT;
1034 /* Support routines for exposure events. */
1035 static void clear_cursor ();
1037 /* Output into a rectangle of an X-window (for frame F)
1038 the characters in f->phys_lines that overlap that rectangle.
1039 TOP and LEFT are the position of the upper left corner of the rectangle.
1040 ROWS and COLS are the size of the rectangle. */
1042 static void
1043 dumprectangle (f, left, top, cols, rows)
1044 struct frame *f;
1045 register int left, top, cols, rows;
1047 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1048 int cursor_cleared = 0;
1049 int bottom, right;
1050 register int y;
1052 if (FRAME_GARBAGED_P (f))
1053 return;
1055 /* Express rectangle as four edges, instead of position-and-size. */
1056 bottom = top + rows;
1057 right = left + cols;
1059 #ifndef HAVE_X11 /* Window manger does this for X11. */
1061 int intborder = f->display.x->internal_border_width;
1063 /* If the rectangle includes any of the internal border area,
1064 redisplay the border emphasis. */
1065 if (top < intborder || left < intborder
1066 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
1067 || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
1068 dumpborder (f, 0);
1070 #endif /* HAVE_X11 Window manger does this for X11. */
1072 /* Convert rectangle edges in pixels to edges in chars.
1073 Round down for left and top, up for right and bottom. */
1074 top = PIXEL_TO_CHAR_ROW (f, top);
1075 left = PIXEL_TO_CHAR_COL (f, left);
1076 bottom += (FONT_HEIGHT (f->display.x->font) - 1);
1077 right += (FONT_WIDTH (f->display.x->font) - 1);
1078 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1079 right = PIXEL_TO_CHAR_COL (f, right);
1081 /* Clip the rectangle to what can be visible. */
1082 if (left < 0)
1083 left = 0;
1084 if (top < 0)
1085 top = 0;
1086 if (right > f->width)
1087 right = f->width;
1088 if (bottom > f->height)
1089 bottom = f->height;
1091 /* Get size in chars of the rectangle. */
1092 cols = right - left;
1093 rows = bottom - top;
1095 /* If rectangle has zero area, return. */
1096 if (rows <= 0) return;
1097 if (cols <= 0) return;
1099 /* Turn off the cursor if it is in the rectangle.
1100 We will turn it back on afterward. */
1101 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1102 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1104 clear_cursor (f);
1105 cursor_cleared = 1;
1108 /* Display the text in the rectangle, one text line at a time. */
1110 for (y = top; y < bottom; y++)
1112 GLYPH *line = &active_frame->glyphs[y][left];
1114 if (! active_frame->enable[y] || left > active_frame->used[y])
1115 continue;
1117 dumpglyphs (f,
1118 CHAR_TO_PIXEL_COL (f, left),
1119 CHAR_TO_PIXEL_ROW (f, y),
1120 line, min (cols, active_frame->used[y] - left),
1121 active_frame->highlight[y]);
1124 /* Turn the cursor on if we turned it off. */
1126 if (cursor_cleared)
1127 x_display_cursor (f, 1);
1130 #ifndef HAVE_X11
1131 /* Process all queued ExposeRegion events. */
1133 static void
1134 dumpqueue ()
1136 register int i;
1137 XExposeRegionEvent r;
1139 while (dequeue_event (&r, &x_expose_queue))
1141 struct frame *f = x_window_to_frame (r.window);
1142 if (f->display.x->icon_desc == r.window)
1143 refreshicon (f);
1144 else
1145 dumprectangle (f, r.x, r.y, r.width, r.height);
1147 XFlushQueue ();
1149 #endif /* HAVE_X11 */
1151 /* Process all expose events that are pending, for X10.
1152 Redraws the cursor if necessary on any frame that
1153 is not in the process of being updated with update_frame. */
1155 #ifndef HAVE_X11
1156 static void
1157 x_do_pending_expose ()
1159 int mask;
1160 struct frame *f;
1161 Lisp_Object tail, frame;
1163 if (expose_all_windows)
1165 expose_all_windows = 0;
1166 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1168 register int temp_width, temp_height;
1169 int intborder;
1171 frame = XCONS (tail)->car;
1172 if (XGCTYPE (frame) != Lisp_Frame)
1173 continue;
1174 f = XFRAME (frame);
1175 if (! FRAME_X_P (f))
1176 continue;
1177 if (!f->async_visible)
1178 continue;
1179 if (!f->display.x->needs_exposure)
1180 continue;
1182 intborder = f->display.x->internal_border_width;
1184 clear_cursor (f);
1185 XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo);
1186 temp_width = ((windowinfo.width - 2 * intborder
1187 - f->display.x->v_scroll_bar_width)
1188 / FONT_WIDTH (f->display.x->font));
1189 temp_height = ((windowinfo.height- 2 * intborder
1190 - f->display.x->h_scroll_bar_height)
1191 / FONT_HEIGHT (f->display.x->font));
1192 if (temp_width != f->width || temp_height != f->height)
1194 change_frame_size (f, max (1, temp_height),
1195 max (1, temp_width), 0, 1);
1196 x_resize_scroll_bars (f);
1198 f->display.x->left_pos = windowinfo.x;
1199 f->display.x->top_pos = windowinfo.y;
1200 dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f));
1201 #if 0
1202 dumpborder (f, 0);
1203 #endif /* ! 0 */
1204 f->display.x->needs_exposure = 0;
1205 if (updating_frame != f)
1206 x_display_cursor (f, 1);
1207 XFlushQueue ();
1210 else
1211 /* Handle any individual-rectangle expose events queued
1212 for various windows. */
1213 #ifdef HAVE_X11
1215 #else /* ! defined (HAVE_X11) */
1216 dumpqueue ();
1217 #endif /* ! defined (HAVE_X11) */
1219 #endif
1221 #ifdef HAVE_X11
1222 static void
1223 frame_highlight (frame)
1224 struct frame *frame;
1226 if (! EQ (Vx_no_window_manager, Qnil))
1227 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
1228 frame->display.x->border_pixel);
1229 x_display_cursor (frame, 1);
1232 static void
1233 frame_unhighlight (frame)
1234 struct frame *frame;
1236 if (! EQ (Vx_no_window_manager, Qnil))
1237 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
1238 frame->display.x->border_tile);
1239 x_display_cursor (frame, 1);
1241 #else /* ! defined (HAVE_X11) */
1242 /* Dump the border-emphasis of frame F.
1243 If F is selected, this is a lining of the same color as the border,
1244 just within the border, occupying a portion of the internal border.
1245 If F is not selected, it is background in the same place.
1246 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1248 ALWAYS = 1 is used when a frame becomes selected or deselected.
1249 In that case, we also turn the cursor off and on again
1250 so it will appear in the proper shape (solid if selected; else hollow.) */
1252 static void
1253 dumpborder (f, always)
1254 struct frame *f;
1255 int always;
1257 int thickness = f->display.x->internal_border_width / 2;
1258 int width = PIXEL_WIDTH (f);
1259 int height = PIXEL_HEIGHT (f);
1260 int pixel;
1262 if (f != selected_frame)
1264 if (!always)
1265 return;
1267 pixel = f->display.x->background_pixel;
1269 else
1271 pixel = f->display.x->border_pixel;
1274 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1275 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1276 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
1277 thickness, pixel);
1278 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
1279 height, pixel);
1281 if (always)
1282 x_display_cursor (f, 1);
1284 #endif /* ! defined (HAVE_X11) */
1286 static void XTframe_rehighlight ();
1288 /* The focus has changed. Update the frames as necessary to reflect
1289 the new situation. Note that we can't change the selected frame
1290 here, because the lisp code we are interrupting might become confused.
1291 Each event gets marked with the frame in which it occured, so the
1292 lisp code can tell when the switch took place by examining the events. */
1294 static void
1295 x_new_focus_frame (frame)
1296 struct frame *frame;
1298 struct frame *old_focus = x_focus_frame;
1299 int events_enqueued = 0;
1301 if (frame != x_focus_frame)
1303 /* Set this before calling other routines, so that they see
1304 the correct value of x_focus_frame. */
1305 x_focus_frame = frame;
1307 if (old_focus && old_focus->auto_lower)
1308 x_lower_frame (old_focus);
1310 #if 0
1311 selected_frame = frame;
1312 XSET (XWINDOW (selected_frame->selected_window)->frame,
1313 Lisp_Frame, selected_frame);
1314 Fselect_window (selected_frame->selected_window);
1315 choose_minibuf_frame ();
1316 #endif /* ! 0 */
1318 if (x_focus_frame && x_focus_frame->auto_raise)
1319 x_raise_frame (x_focus_frame);
1322 XTframe_rehighlight ();
1326 /* The focus has changed, or we have redirected a frame's focus to
1327 another frame (this happens when a frame uses a surrogate
1328 minibuffer frame). Shift the highlight as appropriate. */
1329 static void
1330 XTframe_rehighlight ()
1332 struct frame *old_highlight = x_highlight_frame;
1334 if (x_focus_frame)
1336 x_highlight_frame =
1337 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame)
1338 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
1339 : x_focus_frame);
1340 if (! FRAME_LIVE_P (x_highlight_frame))
1342 FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
1343 x_highlight_frame = x_focus_frame;
1346 else
1347 x_highlight_frame = 0;
1349 if (x_highlight_frame != old_highlight)
1351 if (old_highlight)
1352 frame_unhighlight (old_highlight);
1353 if (x_highlight_frame)
1354 frame_highlight (x_highlight_frame);
1358 /* Mouse clicks and mouse movement. Rah. */
1359 #ifdef HAVE_X11
1361 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1362 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1363 that the glyph at X, Y occupies, if BOUNDS != 0. */
1364 static void
1365 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
1366 FRAME_PTR f;
1367 register unsigned int pix_x, pix_y;
1368 register int *x, *y;
1369 XRectangle *bounds;
1371 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1372 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1374 if (bounds)
1376 bounds->width = FONT_WIDTH (f->display.x->font);
1377 bounds->height = FONT_HEIGHT (f->display.x->font);
1378 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1379 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1382 if (pix_x < 0) pix_x = 0;
1383 else if (pix_x > f->width) pix_x = f->width;
1385 if (pix_y < 0) pix_y = 0;
1386 else if (pix_y > f->height) pix_y = f->height;
1388 *x = pix_x;
1389 *y = pix_y;
1392 /* Any buttons grabbed. */
1393 unsigned int x_mouse_grabbed;
1395 /* Which modifier keys are on which modifier bits?
1397 With each keystroke, X returns eight bits indicating which modifier
1398 keys were held down when the key was pressed. The interpretation
1399 of the top five modifier bits depends on what keys are attached
1400 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1401 is the meta bit.
1403 x_meta_mod_mask is a mask containing the bits used for the meta key.
1404 It may have more than one bit set, if more than one modifier bit
1405 has meta keys on it. Basically, if EVENT is a KeyPress event,
1406 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1408 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1409 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1410 only be affected by the lock modifier bit if XK_Shift_Lock is in
1411 use; XK_Caps_Lock should only affect alphabetic keys. With this
1412 arrangement, the lock modifier should shift the character if
1413 (EVENT.state & x_shift_lock_mask) != 0. */
1414 static int x_meta_mod_mask, x_shift_lock_mask;
1416 /* These are like x_meta_mod_mask, but for different modifiers. */
1417 static int x_alt_mod_mask, x_super_mod_mask, x_hyper_mod_mask;
1419 /* Initialize mode_switch_bit and modifier_meaning. */
1420 static void
1421 x_find_modifier_meanings ()
1423 int min_code, max_code;
1424 KeySym *syms;
1425 int syms_per_code;
1426 XModifierKeymap *mods;
1428 x_meta_mod_mask = 0;
1429 x_shift_lock_mask = 0;
1430 x_alt_mod_mask = 0;
1431 x_super_mod_mask = 0;
1432 x_hyper_mod_mask = 0;
1434 #ifdef HAVE_X11R4
1435 XDisplayKeycodes (x_current_display, &min_code, &max_code);
1436 #else
1437 min_code = x_current_display->min_keycode;
1438 max_code = x_current_display->max_keycode;
1439 #endif
1441 syms = XGetKeyboardMapping (x_current_display,
1442 min_code, max_code - min_code + 1,
1443 &syms_per_code);
1444 mods = XGetModifierMapping (x_current_display);
1446 /* Scan the modifier table to see which modifier bits the Meta and
1447 Alt keysyms are on. */
1449 int row, col; /* The row and column in the modifier table. */
1451 for (row = 3; row < 8; row++)
1452 for (col = 0; col < mods->max_keypermod; col++)
1454 KeyCode code =
1455 mods->modifiermap[(row * mods->max_keypermod) + col];
1457 /* Are any of this keycode's keysyms a meta key? */
1459 int code_col;
1461 for (code_col = 0; code_col < syms_per_code; code_col++)
1463 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1465 switch (sym)
1467 case XK_Meta_L:
1468 case XK_Meta_R:
1469 x_meta_mod_mask |= (1 << row);
1470 break;
1472 case XK_Alt_L:
1473 case XK_Alt_R:
1474 x_alt_mod_mask |= (1 << row);
1475 break;
1477 case XK_Hyper_L:
1478 case XK_Hyper_R:
1479 x_hyper_mod_mask |= (1 << row);
1480 break;
1482 case XK_Super_L:
1483 case XK_Super_R:
1484 x_super_mod_mask |= (1 << row);
1485 break;
1487 case XK_Shift_Lock:
1488 /* Ignore this if it's not on the lock modifier. */
1489 if ((1 << row) == LockMask)
1490 x_shift_lock_mask = LockMask;
1491 break;
1498 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1499 if (! x_meta_mod_mask)
1501 x_meta_mod_mask = x_alt_mod_mask;
1502 x_alt_mod_mask = 0;
1505 /* If some keys are both alt and meta,
1506 make them just meta, not alt. */
1507 if (x_alt_mod_mask & x_meta_mod_mask)
1509 x_alt_mod_mask &= ~x_meta_mod_mask;
1512 XFree ((char *) syms);
1513 XFreeModifiermap (mods);
1517 /* Convert between the modifier bits X uses and the modifier bits
1518 Emacs uses. */
1519 static unsigned int
1520 x_x_to_emacs_modifiers (state)
1521 unsigned int state;
1523 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1524 | ((state & ControlMask) ? ctrl_modifier : 0)
1525 | ((state & x_meta_mod_mask) ? meta_modifier : 0)
1526 | ((state & x_alt_mod_mask) ? alt_modifier : 0)
1527 | ((state & x_super_mod_mask) ? super_modifier : 0)
1528 | ((state & x_hyper_mod_mask) ? hyper_modifier : 0));
1531 static unsigned int
1532 x_emacs_to_x_modifiers (state)
1533 unsigned int state;
1535 return ( ((state & alt_modifier) ? x_alt_mod_mask : 0)
1536 | ((state & super_modifier) ? x_super_mod_mask : 0)
1537 | ((state & hyper_modifier) ? x_hyper_mod_mask : 0)
1538 | ((state & shift_modifier) ? ShiftMask : 0)
1539 | ((state & ctrl_modifier) ? ControlMask : 0)
1540 | ((state & meta_modifier) ? x_meta_mod_mask : 0));
1543 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1545 If the event is a button press, then note that we have grabbed
1546 the mouse. */
1548 static Lisp_Object
1549 construct_mouse_click (result, event, f)
1550 struct input_event *result;
1551 XButtonEvent *event;
1552 struct frame *f;
1554 /* Make the event type no_event; we'll change that when we decide
1555 otherwise. */
1556 result->kind = mouse_click;
1557 XSET (result->code, Lisp_Int, event->button - Button1);
1558 result->timestamp = event->time;
1559 result->modifiers = (x_x_to_emacs_modifiers (event->state)
1560 | (event->type == ButtonRelease
1561 ? up_modifier
1562 : down_modifier));
1564 /* Notice if the mouse is still grabbed. */
1565 if (event->type == ButtonPress)
1567 if (! x_mouse_grabbed)
1568 Vmouse_depressed = Qt;
1569 x_mouse_grabbed |= (1 << event->button);
1571 else if (event->type == ButtonRelease)
1573 x_mouse_grabbed &= ~(1 << event->button);
1574 if (!x_mouse_grabbed)
1575 Vmouse_depressed = Qnil;
1579 int row, column;
1581 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1582 XFASTINT (result->x) = column;
1583 XFASTINT (result->y) = row;
1584 XSET (result->frame_or_window, Lisp_Frame, f);
1589 /* Mouse movement. Rah.
1591 In order to avoid asking for motion events and then throwing most
1592 of them away or busy-polling the server for mouse positions, we ask
1593 the server for pointer motion hints. This means that we get only
1594 one event per group of mouse movements. "Groups" are delimited by
1595 other kinds of events (focus changes and button clicks, for
1596 example), or by XQueryPointer calls; when one of these happens, we
1597 get another MotionNotify event the next time the mouse moves. This
1598 is at least as efficient as getting motion events when mouse
1599 tracking is on, and I suspect only negligibly worse when tracking
1600 is off.
1602 The silly O'Reilly & Associates Nutshell guides barely document
1603 pointer motion hints at all (I think you have to infer how they
1604 work from an example), and the description of XQueryPointer doesn't
1605 mention that calling it causes you to get another motion hint from
1606 the server, which is very important. */
1608 /* Where the mouse was last time we reported a mouse event. */
1609 static FRAME_PTR last_mouse_frame;
1610 static XRectangle last_mouse_glyph;
1612 /* The scroll bar in which the last X motion event occurred.
1614 If the last X motion event occured in a scroll bar, we set this
1615 so XTmouse_position can know whether to report a scroll bar motion or
1616 an ordinary motion.
1618 If the last X motion event didn't occur in a scroll bar, we set this
1619 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1620 static Lisp_Object last_mouse_scroll_bar;
1622 /* This is a hack. We would really prefer that XTmouse_position would
1623 return the time associated with the position it returns, but there
1624 doesn't seem to be any way to wrest the timestamp from the server
1625 along with the position query. So, we just keep track of the time
1626 of the last movement we received, and return that in hopes that
1627 it's somewhat accurate. */
1628 static Time last_mouse_movement_time;
1630 /* Function to report a mouse movement to the mainstream Emacs code.
1631 The input handler calls this.
1633 We have received a mouse movement event, which is given in *event.
1634 If the mouse is over a different glyph than it was last time, tell
1635 the mainstream emacs code by setting mouse_moved. If not, ask for
1636 another motion event, so we can check again the next time it moves. */
1637 static void
1638 note_mouse_movement (frame, event)
1639 FRAME_PTR frame;
1640 XMotionEvent *event;
1643 last_mouse_movement_time = event->time;
1645 /* Has the mouse moved off the glyph it was on at the last sighting? */
1646 if (event->x < last_mouse_glyph.x
1647 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1648 || event->y < last_mouse_glyph.y
1649 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1651 mouse_moved = 1;
1652 last_mouse_scroll_bar = Qnil;
1654 else
1656 /* It's on the same glyph. Call XQueryPointer so we'll get an
1657 event the next time the mouse moves and we can see if it's
1658 *still* on the same glyph. */
1659 int dummy;
1661 XQueryPointer (event->display, event->window,
1662 (Window *) &dummy, (Window *) &dummy,
1663 &dummy, &dummy, &dummy, &dummy,
1664 (unsigned int *) &dummy);
1668 static struct scroll_bar *x_window_to_scroll_bar ();
1669 static void x_scroll_bar_report_motion ();
1671 /* Return the current position of the mouse.
1673 If the mouse movement started in a scroll bar, set *f, *bar_window,
1674 and *part to the frame, window, and scroll bar part that the mouse
1675 is over. Set *x and *y to the portion and whole of the mouse's
1676 position on the scroll bar.
1678 If the mouse movement started elsewhere, set *f to the frame the
1679 mouse is on, *bar_window to nil, and *x and *y to the character cell
1680 the mouse is over.
1682 Set *time to the server timestamp for the time at which the mouse
1683 was at this position.
1685 This clears the mouse_moved flag, so we can wait for the next mouse
1686 movement. This also calls XQueryPointer, which will cause the
1687 server to give us another MotionNotify when the mouse moves
1688 again. */
1690 static void
1691 XTmouse_position (f, bar_window, part, x, y, time)
1692 FRAME_PTR *f;
1693 Lisp_Object *bar_window;
1694 enum scroll_bar_part *part;
1695 Lisp_Object *x, *y;
1696 unsigned long *time;
1698 BLOCK_INPUT;
1700 if (! NILP (last_mouse_scroll_bar))
1701 x_scroll_bar_report_motion (f, bar_window, part, x, y, time);
1702 else
1704 Window root;
1705 int root_x, root_y;
1707 Window dummy_window;
1708 int dummy;
1710 mouse_moved = 0;
1711 last_mouse_scroll_bar = Qnil;
1713 /* Figure out which root window we're on. */
1714 XQueryPointer (x_current_display,
1715 DefaultRootWindow (x_current_display),
1717 /* The root window which contains the pointer. */
1718 &root,
1720 /* Trash which we can't trust if the pointer is on
1721 a different screen. */
1722 &dummy_window,
1724 /* The position on that root window. */
1725 &root_x, &root_y,
1727 /* More trash we can't trust. */
1728 &dummy, &dummy,
1730 /* Modifier keys and pointer buttons, about which
1731 we don't care. */
1732 (unsigned int *) &dummy);
1734 /* Now we have a position on the root; find the innermost window
1735 containing the pointer. */
1737 Window win, child;
1738 int win_x, win_y;
1739 int parent_x, parent_y;
1741 win = root;
1742 for (;;)
1744 XTranslateCoordinates (x_current_display,
1746 /* From-window, to-window. */
1747 root, win,
1749 /* From-position, to-position. */
1750 root_x, root_y, &win_x, &win_y,
1752 /* Child of win. */
1753 &child);
1755 if (child == None)
1756 break;
1758 win = child;
1759 parent_x = win_x;
1760 parent_y = win_y;
1763 /* Now we know that:
1764 win is the innermost window containing the pointer
1765 (XTC says it has no child containing the pointer),
1766 win_x and win_y are the pointer's position in it
1767 (XTC did this the last time through), and
1768 parent_x and parent_y are the pointer's position in win's parent.
1769 (They are what win_x and win_y were when win was child.
1770 If win is the root window, it has no parent, and
1771 parent_{x,y} are invalid, but that's okay, because we'll
1772 never use them in that case.) */
1774 /* Is win one of our frames? */
1775 *f = x_window_to_frame (win);
1777 /* If not, is it one of our scroll bars? */
1778 if (! *f)
1780 struct scroll_bar *bar = x_window_to_scroll_bar (win);
1782 if (bar)
1784 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1785 win_x = parent_x;
1786 win_y = parent_y;
1790 if (*f)
1792 pixel_to_glyph_coords (*f, win_x, win_y, &win_x, &win_y,
1793 &last_mouse_glyph);
1795 *bar_window = Qnil;
1796 *part = 0;
1797 XSET (*x, Lisp_Int, win_x);
1798 XSET (*y, Lisp_Int, win_y);
1799 *time = last_mouse_movement_time;
1804 UNBLOCK_INPUT;
1807 #else /* ! defined (HAVE_X11) */
1808 #define XEvent XKeyPressedEvent
1809 #endif /* ! defined (HAVE_X11) */
1811 /* Scroll bar support. */
1813 /* Given an X window ID, find the struct scroll_bar which manages it.
1814 This can be called in GC, so we have to make sure to strip off mark
1815 bits. */
1816 static struct scroll_bar *
1817 x_window_to_scroll_bar (window_id)
1818 Window window_id;
1820 Lisp_Object tail, frame;
1822 for (tail = Vframe_list;
1823 XGCTYPE (tail) == Lisp_Cons;
1824 tail = XCONS (tail)->cdr)
1826 Lisp_Object frame = XCONS (tail)->car;
1827 Lisp_Object bar, condemned;
1829 /* All elements of Vframe_list should be frames. */
1830 if (XGCTYPE (frame) != Lisp_Frame)
1831 abort ();
1833 /* Scan this frame's scroll bar list for a scroll bar with the
1834 right window ID. */
1835 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1836 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1837 /* This trick allows us to search both the ordinary and
1838 condemned scroll bar lists with one loop. */
1839 ! GC_NILP (bar) || (bar = condemned,
1840 condemned = Qnil,
1841 ! GC_NILP (bar));
1842 bar = XSCROLL_BAR(bar)->next)
1843 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
1844 return XSCROLL_BAR (bar);
1847 return 0;
1850 /* Open a new X window to serve as a scroll bar, and return the
1851 scroll bar vector for it. */
1852 static struct scroll_bar *
1853 x_scroll_bar_create (window, top, left, width, height)
1854 struct window *window;
1855 int top, left, width, height;
1857 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window));
1858 struct scroll_bar *bar =
1859 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1861 BLOCK_INPUT;
1864 XSetWindowAttributes a;
1865 unsigned long mask;
1867 a.background_pixel = frame->display.x->background_pixel;
1868 a.event_mask = (ButtonPressMask | ButtonReleaseMask
1869 | ButtonMotionMask | PointerMotionHintMask
1870 | ExposureMask);
1871 a.cursor = x_vertical_scroll_bar_cursor;
1873 mask = (CWBackPixel | CWEventMask | CWCursor);
1875 SET_SCROLL_BAR_X_WINDOW
1876 (bar,
1877 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
1879 /* Position and size of scroll bar. */
1880 left, top, width, height,
1882 /* Border width, depth, class, and visual. */
1883 0, CopyFromParent, CopyFromParent, CopyFromParent,
1885 /* Attributes. */
1886 mask, &a));
1889 XSET (bar->window, Lisp_Window, window);
1890 XSET (bar->top, Lisp_Int, top);
1891 XSET (bar->left, Lisp_Int, left);
1892 XSET (bar->width, Lisp_Int, width);
1893 XSET (bar->height, Lisp_Int, height);
1894 XSET (bar->start, Lisp_Int, 0);
1895 XSET (bar->end, Lisp_Int, 0);
1896 bar->dragging = Qnil;
1898 /* Add bar to its frame's list of scroll bars. */
1899 bar->next = FRAME_SCROLL_BARS (frame);
1900 bar->prev = Qnil;
1901 XSET (FRAME_SCROLL_BARS (frame), Lisp_Vector, bar);
1902 if (! NILP (bar->next))
1903 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
1905 XMapWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
1907 UNBLOCK_INPUT;
1909 return bar;
1912 /* Draw BAR's handle in the proper position.
1913 If the handle is already drawn from START to END, don't bother
1914 redrawing it, unless REBUILD is non-zero; in that case, always
1915 redraw it. (REBUILD is handy for drawing the handle after expose
1916 events.)
1918 Normally, we want to constrain the start and end of the handle to
1919 fit inside its rectangle, but if the user is dragging the scroll bar
1920 handle, we want to let them drag it down all the way, so that the
1921 bar's top is as far down as it goes; otherwise, there's no way to
1922 move to the very end of the buffer. */
1923 static void
1924 x_scroll_bar_set_handle (bar, start, end, rebuild)
1925 struct scroll_bar *bar;
1926 int start, end;
1927 int rebuild;
1929 int dragging = ! NILP (bar->dragging);
1930 Window w = SCROLL_BAR_X_WINDOW (bar);
1931 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
1933 /* If the display is already accurate, do nothing. */
1934 if (! rebuild
1935 && start == XINT (bar->start)
1936 && end == XINT (bar->end))
1937 return;
1939 BLOCK_INPUT;
1942 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
1943 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
1944 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
1946 /* Make sure the values are reasonable, and try to preserve
1947 the distance between start and end. */
1949 int length = end - start;
1951 if (start < 0)
1952 start = 0;
1953 else if (start > top_range)
1954 start = top_range;
1955 end = start + length;
1957 if (end < start)
1958 end = start;
1959 else if (end > top_range && ! dragging)
1960 end = top_range;
1963 /* Store the adjusted setting in the scroll bar. */
1964 XSET (bar->start, Lisp_Int, start);
1965 XSET (bar->end, Lisp_Int, end);
1967 /* Clip the end position, just for display. */
1968 if (end > top_range)
1969 end = top_range;
1971 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1972 below top positions, to make sure the handle is always at least
1973 that many pixels tall. */
1974 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
1976 /* Draw the empty space above the handle. Note that we can't clear
1977 zero-height areas; that means "clear to end of window." */
1978 if (0 < start)
1979 XClearArea (x_current_display, w,
1981 /* x, y, width, height, and exposures. */
1982 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1983 VERTICAL_SCROLL_BAR_TOP_BORDER,
1984 inside_width, start,
1985 False);
1987 /* Draw the handle itself. */
1988 XFillRectangle (x_current_display, w, gc,
1990 /* x, y, width, height */
1991 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1992 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
1993 inside_width, end - start);
1996 /* Draw the empty space below the handle. Note that we can't
1997 clear zero-height areas; that means "clear to end of window." */
1998 if (end < inside_height)
1999 XClearArea (x_current_display, w,
2001 /* x, y, width, height, and exposures. */
2002 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2003 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
2004 inside_width, inside_height - end,
2005 False);
2009 UNBLOCK_INPUT;
2012 /* Move a scroll bar around on the screen, to accomodate changing
2013 window configurations. */
2014 static void
2015 x_scroll_bar_move (bar, top, left, width, height)
2016 struct scroll_bar *bar;
2017 int top, left, width, height;
2019 BLOCK_INPUT;
2022 XWindowChanges wc;
2023 unsigned int mask = 0;
2025 wc.x = left;
2026 wc.y = top;
2027 wc.width = width;
2028 wc.height = height;
2030 if (left != XINT (bar->left)) mask |= CWX;
2031 if (top != XINT (bar->top)) mask |= CWY;
2032 if (width != XINT (bar->width)) mask |= CWWidth;
2033 if (height != XINT (bar->height)) mask |= CWHeight;
2035 if (mask)
2036 XConfigureWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar),
2037 mask, &wc);
2040 XSET (bar->left, Lisp_Int, left);
2041 XSET (bar->top, Lisp_Int, top);
2042 XSET (bar->width, Lisp_Int, width);
2043 XSET (bar->height, Lisp_Int, height);
2045 UNBLOCK_INPUT;
2048 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2049 to nil. */
2050 static void
2051 x_scroll_bar_remove (bar)
2052 struct scroll_bar *bar;
2054 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2056 BLOCK_INPUT;
2058 /* Destroy the window. */
2059 XDestroyWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
2061 /* Disassociate this scroll bar from its window. */
2062 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2064 UNBLOCK_INPUT;
2067 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2068 that we are displaying PORTION characters out of a total of WHOLE
2069 characters, starting at POSITION. If WINDOW has no scroll bar,
2070 create one. */
2071 static void
2072 XTset_vertical_scroll_bar (window, portion, whole, position)
2073 struct window *window;
2074 int portion, whole, position;
2076 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2077 int top = XINT (window->top);
2078 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2079 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2081 /* Where should this scroll bar be, pixelwise? */
2082 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2083 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2084 int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f);
2085 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2087 struct scroll_bar *bar;
2089 /* Does the scroll bar exist yet? */
2090 if (NILP (window->vertical_scroll_bar))
2091 bar = x_scroll_bar_create (window,
2092 pixel_top, pixel_left,
2093 pixel_width, pixel_height);
2094 else
2096 /* It may just need to be moved and resized. */
2097 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2098 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2101 /* Set the scroll bar's current state, unless we're currently being
2102 dragged. */
2103 if (NILP (bar->dragging))
2105 int top_range =
2106 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2108 if (whole == 0)
2109 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2110 else
2112 int start = (position * top_range) / whole;
2113 int end = ((position + portion) * top_range) / whole;
2115 x_scroll_bar_set_handle (bar, start, end, 0);
2119 XSET (window->vertical_scroll_bar, Lisp_Vector, bar);
2123 /* The following three hooks are used when we're doing a thorough
2124 redisplay of the frame. We don't explicitly know which scroll bars
2125 are going to be deleted, because keeping track of when windows go
2126 away is a real pain - "Can you say set-window-configuration, boys
2127 and girls?" Instead, we just assert at the beginning of redisplay
2128 that *all* scroll bars are to be removed, and then save a scroll bar
2129 from the fiery pit when we actually redisplay its window. */
2131 /* Arrange for all scroll bars on FRAME to be removed at the next call
2132 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2133 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2134 static void
2135 XTcondemn_scroll_bars (frame)
2136 FRAME_PTR frame;
2138 /* The condemned list should be empty at this point; if it's not,
2139 then the rest of Emacs isn't using the condemn/redeem/judge
2140 protocol correctly. */
2141 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2142 abort ();
2144 /* Move them all to the "condemned" list. */
2145 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2146 FRAME_SCROLL_BARS (frame) = Qnil;
2149 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2150 Note that WINDOW isn't necessarily condemned at all. */
2151 static void
2152 XTredeem_scroll_bar (window)
2153 struct window *window;
2155 struct scroll_bar *bar;
2157 /* We can't redeem this window's scroll bar if it doesn't have one. */
2158 if (NILP (window->vertical_scroll_bar))
2159 abort ();
2161 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2163 /* Unlink it from the condemned list. */
2165 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2167 if (NILP (bar->prev))
2169 /* If the prev pointer is nil, it must be the first in one of
2170 the lists. */
2171 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2172 /* It's not condemned. Everything's fine. */
2173 return;
2174 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2175 window->vertical_scroll_bar))
2176 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2177 else
2178 /* If its prev pointer is nil, it must be at the front of
2179 one or the other! */
2180 abort ();
2182 else
2183 XSCROLL_BAR (bar->prev)->next = bar->next;
2185 if (! NILP (bar->next))
2186 XSCROLL_BAR (bar->next)->prev = bar->prev;
2188 bar->next = FRAME_SCROLL_BARS (f);
2189 bar->prev = Qnil;
2190 XSET (FRAME_SCROLL_BARS (f), Lisp_Vector, bar);
2191 if (! NILP (bar->next))
2192 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
2196 /* Remove all scroll bars on FRAME that haven't been saved since the
2197 last call to `*condemn_scroll_bars_hook'. */
2198 static void
2199 XTjudge_scroll_bars (f)
2200 FRAME_PTR f;
2202 Lisp_Object bar, next;
2204 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2206 /* Clear out the condemned list now so we won't try to process any
2207 more events on the hapless scroll bars. */
2208 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2210 for (; ! NILP (bar); bar = next)
2212 struct scroll_bar *b = XSCROLL_BAR (bar);
2214 x_scroll_bar_remove (b);
2216 next = b->next;
2217 b->next = b->prev = Qnil;
2220 /* Now there should be no references to the condemned scroll bars,
2221 and they should get garbage-collected. */
2225 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2227 This may be called from a signal handler, so we have to ignore GC
2228 mark bits. */
2229 static void
2230 x_scroll_bar_expose (bar, event)
2231 struct scroll_bar *bar;
2232 XEvent *event;
2234 Window w = SCROLL_BAR_X_WINDOW (bar);
2235 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
2237 BLOCK_INPUT;
2239 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
2241 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2242 XDrawRectangle (x_current_display, w, gc,
2244 /* x, y, width, height */
2245 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
2247 /* Draw another line to make the extra-thick border on the right. */
2248 XFillRectangle (x_current_display, w, gc,
2250 /* x, y, width, height */
2251 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2);
2253 UNBLOCK_INPUT;
2256 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2257 is set to something other than no_event, it is enqueued.
2259 This may be called from a signal handler, so we have to ignore GC
2260 mark bits. */
2261 static void
2262 x_scroll_bar_handle_click (bar, event, emacs_event)
2263 struct scroll_bar *bar;
2264 XEvent *event;
2265 struct input_event *emacs_event;
2267 if (XGCTYPE (bar->window) != Lisp_Window)
2268 abort ();
2270 emacs_event->kind = scroll_bar_click;
2271 XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1);
2272 emacs_event->modifiers =
2273 (x_x_to_emacs_modifiers (event->xbutton.state)
2274 | (event->type == ButtonRelease
2275 ? up_modifier
2276 : down_modifier));
2277 emacs_event->frame_or_window = bar->window;
2278 emacs_event->timestamp = event->xbutton.time;
2280 int internal_height =
2281 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2282 int top_range =
2283 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2284 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
2286 if (y < 0) y = 0;
2287 if (y > top_range) y = top_range;
2289 if (y < XINT (bar->start))
2290 emacs_event->part = scroll_bar_above_handle;
2291 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2292 emacs_event->part = scroll_bar_handle;
2293 else
2294 emacs_event->part = scroll_bar_below_handle;
2296 /* Just because the user has clicked on the handle doesn't mean
2297 they want to drag it. Lisp code needs to be able to decide
2298 whether or not we're dragging. */
2299 #if 0
2300 /* If the user has just clicked on the handle, record where they're
2301 holding it. */
2302 if (event->type == ButtonPress
2303 && emacs_event->part == scroll_bar_handle)
2304 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start));
2305 #endif
2307 /* If the user has released the handle, set it to its final position. */
2308 if (event->type == ButtonRelease
2309 && ! NILP (bar->dragging))
2311 int new_start = y - XINT (bar->dragging);
2312 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2314 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2315 bar->dragging = Qnil;
2318 /* Same deal here as the other #if 0. */
2319 #if 0
2320 /* Clicks on the handle are always reported as occuring at the top of
2321 the handle. */
2322 if (emacs_event->part == scroll_bar_handle)
2323 emacs_event->x = bar->start;
2324 else
2325 XSET (emacs_event->x, Lisp_Int, y);
2326 #else
2327 XSET (emacs_event->x, Lisp_Int, y);
2328 #endif
2330 XSET (emacs_event->y, Lisp_Int, top_range);
2334 /* Handle some mouse motion while someone is dragging the scroll bar.
2336 This may be called from a signal handler, so we have to ignore GC
2337 mark bits. */
2338 static void
2339 x_scroll_bar_note_movement (bar, event)
2340 struct scroll_bar *bar;
2341 XEvent *event;
2343 last_mouse_movement_time = event->xmotion.time;
2345 mouse_moved = 1;
2346 XSET (last_mouse_scroll_bar, Lisp_Vector, bar);
2348 /* If we're dragging the bar, display it. */
2349 if (! GC_NILP (bar->dragging))
2351 /* Where should the handle be now? */
2352 int new_start = event->xmotion.y - XINT (bar->dragging);
2354 if (new_start != XINT (bar->start))
2356 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2358 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2362 /* Call XQueryPointer so we'll get an event the next time the mouse
2363 moves and we can see *still* on the same position. */
2365 int dummy;
2367 XQueryPointer (event->xmotion.display, event->xmotion.window,
2368 (Window *) &dummy, (Window *) &dummy,
2369 &dummy, &dummy, &dummy, &dummy,
2370 (unsigned int *) &dummy);
2374 /* Return information to the user about the current position of the mouse
2375 on the scroll bar. */
2376 static void
2377 x_scroll_bar_report_motion (f, bar_window, part, x, y, time)
2378 FRAME_PTR *f;
2379 Lisp_Object *bar_window;
2380 enum scroll_bar_part *part;
2381 Lisp_Object *x, *y;
2382 unsigned long *time;
2384 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2385 int win_x, win_y;
2386 Window dummy_window;
2387 int dummy_coord;
2388 unsigned int dummy_mask;
2390 BLOCK_INPUT;
2392 /* Get the mouse's position relative to the scroll bar window, and
2393 report that. */
2394 if (! XQueryPointer (x_current_display,
2395 SCROLL_BAR_X_WINDOW (bar),
2397 /* Root, child, root x and root y. */
2398 &dummy_window, &dummy_window,
2399 &dummy_coord, &dummy_coord,
2401 /* Position relative to scroll bar. */
2402 &win_x, &win_y,
2404 /* Mouse buttons and modifier keys. */
2405 &dummy_mask))
2406 *f = 0;
2407 else
2409 int inside_height
2410 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2411 int top_range
2412 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2414 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
2416 if (! NILP (bar->dragging))
2417 win_y -= XINT (bar->dragging);
2419 if (win_y < 0)
2420 win_y = 0;
2421 if (win_y > top_range)
2422 win_y = top_range;
2424 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2425 *bar_window = bar->window;
2427 if (! NILP (bar->dragging))
2428 *part = scroll_bar_handle;
2429 else if (win_y < XINT (bar->start))
2430 *part = scroll_bar_above_handle;
2431 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2432 *part = scroll_bar_handle;
2433 else
2434 *part = scroll_bar_below_handle;
2436 XSET (*x, Lisp_Int, win_y);
2437 XSET (*y, Lisp_Int, top_range);
2439 mouse_moved = 0;
2440 last_mouse_scroll_bar = Qnil;
2443 *time = last_mouse_movement_time;
2445 UNBLOCK_INPUT;
2449 /* The screen has been cleared so we may have changed foreground or
2450 background colors, and the scroll bars may need to be redrawn.
2451 Clear out the scroll bars, and ask for expose events, so we can
2452 redraw them. */
2454 x_scroll_bar_clear (f)
2455 FRAME_PTR f;
2457 Lisp_Object bar;
2459 for (bar = FRAME_SCROLL_BARS (f);
2460 XTYPE (bar) == Lisp_Vector;
2461 bar = XSCROLL_BAR (bar)->next)
2462 XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
2463 0, 0, 0, 0, True);
2468 /* The main X event-reading loop - XTread_socket. */
2470 /* Timestamp of enter window event. This is only used by XTread_socket,
2471 but we have to put it out here, since static variables within functions
2472 sometimes don't work. */
2473 static Time enter_timestamp;
2475 /* This holds the state XLookupString needs to implement dead keys
2476 and other tricks known as "compose processing". _X Window System_
2477 says that a portable program can't use this, but Stephen Gildea assures
2478 me that letting the compiler initialize it to zeros will work okay.
2480 This must be defined outside of XTread_socket, for the same reasons
2481 given for enter_timestamp, above. */
2482 static XComposeStatus compose_status;
2484 /* Communication with window managers. */
2485 Atom Xatom_wm_protocols;
2487 /* Kinds of protocol things we may receive. */
2488 Atom Xatom_wm_take_focus;
2489 Atom Xatom_wm_save_yourself;
2490 Atom Xatom_wm_delete_window;
2492 /* Other WM communication */
2493 Atom Xatom_wm_configure_denied; /* When our config request is denied */
2494 Atom Xatom_wm_window_moved; /* When the WM moves us. */
2496 /* Window manager communication. */
2497 Atom Xatom_wm_change_state;
2499 /* Record the last 100 characters stored
2500 to help debug the loss-of-chars-during-GC problem. */
2501 int temp_index;
2502 short temp_buffer[100];
2504 /* Read events coming from the X server.
2505 This routine is called by the SIGIO handler.
2506 We return as soon as there are no more events to be read.
2508 Events representing keys are stored in buffer BUFP,
2509 which can hold up to NUMCHARS characters.
2510 We return the number of characters stored into the buffer,
2511 thus pretending to be `read'.
2513 WAITP is nonzero if we should block until input arrives.
2514 EXPECTED is nonzero if the caller knows input is available. */
2517 XTread_socket (sd, bufp, numchars, waitp, expected)
2518 register int sd;
2519 register struct input_event *bufp;
2520 register int numchars;
2521 int waitp;
2522 int expected;
2524 int count = 0;
2525 int nbytes = 0;
2526 int mask;
2527 int items_pending; /* How many items are in the X queue. */
2528 XEvent event;
2529 struct frame *f;
2530 int event_found;
2531 int prefix;
2532 Lisp_Object part;
2534 if (interrupt_input_blocked)
2536 interrupt_input_pending = 1;
2537 return -1;
2540 interrupt_input_pending = 0;
2541 BLOCK_INPUT;
2543 if (numchars <= 0)
2544 abort (); /* Don't think this happens. */
2546 #ifdef FIOSNBIO
2547 /* If available, Xlib uses FIOSNBIO to make the socket
2548 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2549 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2550 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2551 fcntl (fileno (stdin), F_SETFL, 0);
2552 #endif /* ! defined (FIOSNBIO) */
2554 #ifndef SIGIO
2555 #ifndef HAVE_SELECT
2556 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
2558 extern int read_alarm_should_throw;
2559 read_alarm_should_throw = 1;
2560 XPeekEvent (XDISPLAY &event);
2561 read_alarm_should_throw = 0;
2563 #endif /* HAVE_SELECT */
2564 #endif /* SIGIO */
2566 while (XStuffPending () != 0)
2568 XNextEvent (XDISPLAY &event);
2569 event_found = 1;
2571 switch (event.type)
2573 #ifdef HAVE_X11
2574 case ClientMessage:
2576 if (event.xclient.message_type == Xatom_wm_protocols
2577 && event.xclient.format == 32)
2579 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
2581 f = x_window_to_frame (event.xclient.window);
2582 if (f)
2583 x_focus_on_frame (f);
2584 /* Not certain about handling scroll bars here */
2586 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
2588 /* Save state modify the WM_COMMAND property to
2589 something which can reinstate us. This notifies
2590 the session manager, who's looking for such a
2591 PropertyNotify. Can restart processing when
2592 a keyboard or mouse event arrives. */
2593 if (numchars > 0)
2597 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
2599 struct frame *f = x_window_to_frame (event.xclient.window);
2601 if (f)
2602 if (numchars > 0)
2607 else if (event.xclient.message_type == Xatom_wm_configure_denied)
2610 else if (event.xclient.message_type == Xatom_wm_window_moved)
2612 int new_x, new_y;
2614 new_x = event.xclient.data.s[0];
2615 new_y = event.xclient.data.s[1];
2618 break;
2620 #ifdef NEW_SELECTIONS
2621 case SelectionNotify:
2622 x_handle_selection_notify (&event);
2623 break;
2624 #endif
2626 case SelectionClear: /* Someone has grabbed ownership. */
2627 #ifdef NEW_SELECTIONS
2629 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
2631 if (numchars == 0)
2632 abort ();
2634 bufp->kind = selection_clear_event;
2635 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2636 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2637 SELECTION_EVENT_TIME (bufp) = eventp->time;
2638 bufp++;
2640 count += 1;
2641 numchars -= 1;
2643 #else
2644 x_disown_selection (event.xselectionclear.window,
2645 event.xselectionclear.selection,
2646 event.xselectionclear.time);
2647 #endif
2648 break;
2650 case SelectionRequest: /* Someone wants our selection. */
2651 #ifdef NEW_SELECTIONS
2653 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
2655 if (numchars == 0)
2656 abort ();
2658 bufp->kind = selection_request_event;
2659 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2660 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
2661 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2662 SELECTION_EVENT_TARGET (bufp) = eventp->target;
2663 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
2664 SELECTION_EVENT_TIME (bufp) = eventp->time;
2665 bufp++;
2667 count += 1;
2668 numchars -= 1;
2670 #else
2671 x_answer_selection_request (event);
2672 #endif
2673 break;
2675 case PropertyNotify:
2676 #ifdef NEW_SELECTIONS
2677 x_handle_property_notify (&event);
2678 #else
2679 /* If we're being told about a root window property, then it's
2680 a cut buffer change. */
2681 if (event.xproperty.window == ROOT_WINDOW)
2682 x_invalidate_cut_buffer_cache (&event.xproperty);
2684 /* Otherwise, we're probably handling an incremental
2685 selection transmission. */
2686 else
2688 /* If we were to do this synchronously, there'd be no worry
2689 about re-selecting. */
2690 x_send_incremental (event);
2692 #endif
2693 break;
2695 case ReparentNotify:
2696 f = x_window_to_frame (event.xreparent.window);
2697 if (f)
2698 f->display.x->parent_desc = event.xreparent.parent;
2699 break;
2701 case Expose:
2702 f = x_window_to_frame (event.xexpose.window);
2703 if (f)
2705 if (f->async_visible == 0)
2707 f->async_visible = 1;
2708 f->async_iconified = 0;
2709 SET_FRAME_GARBAGED (f);
2711 else
2713 dumprectangle (x_window_to_frame (event.xexpose.window),
2714 event.xexpose.x, event.xexpose.y,
2715 event.xexpose.width, event.xexpose.height);
2718 else
2720 struct scroll_bar *bar
2721 = x_window_to_scroll_bar (event.xexpose.window);
2723 if (bar)
2724 x_scroll_bar_expose (bar, &event);
2726 break;
2728 case GraphicsExpose: /* This occurs when an XCopyArea's
2729 source area was obscured or not
2730 available.*/
2731 f = x_window_to_frame (event.xgraphicsexpose.drawable);
2732 if (f)
2734 dumprectangle (f,
2735 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
2736 event.xgraphicsexpose.width,
2737 event.xgraphicsexpose.height);
2739 break;
2741 case NoExpose: /* This occurs when an XCopyArea's
2742 source area was completely
2743 available */
2744 break;
2745 #else /* ! defined (HAVE_X11) */
2746 case ExposeWindow:
2747 if (event.subwindow != 0)
2748 break; /* duplicate event */
2749 f = x_window_to_frame (event.window);
2750 if (event.window == f->display.x->icon_desc)
2752 refreshicon (f);
2753 f->async_iconified = 1;
2755 if (event.window == FRAME_X_WINDOW (f))
2757 /* Say must check all windows' needs_exposure flags. */
2758 expose_all_windows = 1;
2759 f->display.x->needs_exposure = 1;
2760 f->async_visible = 1;
2762 break;
2764 case ExposeRegion:
2765 if (event.subwindow != 0)
2766 break; /* duplicate event */
2767 f = x_window_to_frame (event.window);
2768 if (event.window == f->display.x->icon_desc)
2770 refreshicon (f);
2771 break;
2773 /* If window already needs full redraw, ignore this rectangle. */
2774 if (expose_all_windows && f->display.x->needs_exposure)
2775 break;
2776 /* Put the event on the queue of rectangles to redraw. */
2777 if (enqueue_event (&event, &x_expose_queue))
2778 /* If it is full, we can't record the rectangle,
2779 so redraw this entire window. */
2781 /* Say must check all windows' needs_exposure flags. */
2782 expose_all_windows = 1;
2783 f->display.x->needs_exposure = 1;
2785 break;
2787 case ExposeCopy:
2788 /* This should happen only when we are expecting it,
2789 in x_read_exposes. */
2790 abort ();
2791 #endif /* ! defined (HAVE_X11) */
2793 #ifdef HAVE_X11
2794 case UnmapNotify:
2795 f = x_window_to_frame (event.xunmap.window);
2796 if (f) /* F may no longer exist if
2797 the frame was deleted. */
2799 /* While a frame is unmapped, display generation is
2800 disabled; you don't want to spend time updating a
2801 display that won't ever be seen. */
2802 f->async_visible = 0;
2803 /* The window manager never makes a window invisible
2804 ("withdrawn"); all it does is switch between visible
2805 and iconified. Frames get into the invisible state
2806 only through x_make_frame_invisible.
2807 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
2808 f->async_iconified = 1;
2810 break;
2812 case MapNotify:
2813 f = x_window_to_frame (event.xmap.window);
2814 if (f)
2816 f->async_visible = 1;
2817 f->async_iconified = 0;
2819 /* wait_reading_process_input will notice this and update
2820 the frame's display structures. */
2821 SET_FRAME_GARBAGED (f);
2823 break;
2825 /* Turn off processing if we become fully obscured. */
2826 case VisibilityNotify:
2827 break;
2829 #else /* ! defined (HAVE_X11) */
2830 case UnmapWindow:
2831 f = x_window_to_frame (event.window);
2832 if (event.window == f->display.x->icon_desc)
2833 f->async_iconified = 0;
2834 if (event.window == FRAME_X_WINDOW (f))
2835 f->async_visible = 0;
2836 break;
2837 #endif /* ! defined (HAVE_X11) */
2839 #ifdef HAVE_X11
2840 case KeyPress:
2841 f = x_window_to_frame (event.xkey.window);
2843 if (f != 0)
2845 KeySym keysym, orig_keysym;
2846 char copy_buffer[80];
2847 int modifiers;
2849 event.xkey.state
2850 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers);
2851 modifiers = event.xkey.state;
2853 /* This will have to go some day... */
2855 /* make_lispy_event turns chars into control chars.
2856 Don't do it here because XLookupString is too eager. */
2857 event.xkey.state &= ~ControlMask;
2858 nbytes =
2859 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
2860 &compose_status);
2862 /* Strip off the vendor-specific keysym bit, and take a shot
2863 at recognizing the codes. HP servers have extra keysyms
2864 that fit into the MiscFunctionKey category. */
2865 orig_keysym = keysym;
2866 keysym &= ~(1<<28);
2868 if (numchars > 1)
2870 if ((keysym >= XK_BackSpace && keysym <= XK_Escape)
2871 || keysym == XK_Delete
2872 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
2873 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff7e */
2874 #ifdef HPUX
2875 /* This recognizes the "extended function keys".
2876 It seems there's no cleaner way.
2877 Test IsModifierKey to avoid handling mode_switch
2878 incorrectly. */
2879 || (!IsModifierKey (orig_keysym)
2880 && (unsigned) (keysym) >= XK_Select
2881 && (unsigned)(keysym) < XK_KP_Space)
2882 #endif
2883 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
2884 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
2886 if (temp_index == sizeof temp_buffer / sizeof (short))
2887 temp_index = 0;
2888 temp_buffer[temp_index++] = keysym;
2889 bufp->kind = non_ascii_keystroke;
2890 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00);
2891 XSET (bufp->frame_or_window, Lisp_Frame, f);
2892 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
2893 bufp->timestamp = event.xkey.time;
2894 bufp++;
2895 count++;
2896 numchars--;
2898 else if (numchars > nbytes)
2900 register int i;
2902 for (i = 0; i < nbytes; i++)
2904 if (temp_index == sizeof temp_buffer / sizeof (short))
2905 temp_index = 0;
2906 temp_buffer[temp_index++] = copy_buffer[i];
2907 bufp->kind = ascii_keystroke;
2908 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
2909 XSET (bufp->frame_or_window, Lisp_Frame, f);
2910 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
2911 bufp->timestamp = event.xkey.time;
2912 bufp++;
2915 count += nbytes;
2916 numchars -= nbytes;
2918 else
2919 abort ();
2921 else
2922 abort ();
2924 break;
2925 #else /* ! defined (HAVE_X11) */
2926 case KeyPressed:
2928 register char *where_mapping;
2930 f = x_window_to_frame (event.window);
2931 /* Ignore keys typed on icon windows. */
2932 if (f != 0 && event.window == f->display.x->icon_desc)
2933 break;
2934 where_mapping = XLookupMapping (&event, &nbytes);
2935 /* Nasty fix for arrow keys */
2936 if (!nbytes && IsCursorKey (event.detail & 0xff))
2938 switch (event.detail & 0xff)
2940 case KC_CURSOR_LEFT:
2941 where_mapping = "\002";
2942 break;
2943 case KC_CURSOR_RIGHT:
2944 where_mapping = "\006";
2945 break;
2946 case KC_CURSOR_UP:
2947 where_mapping = "\020";
2948 break;
2949 case KC_CURSOR_DOWN:
2950 where_mapping = "\016";
2951 break;
2953 nbytes = 1;
2955 if (numchars - nbytes > 0)
2957 register int i;
2959 for (i = 0; i < nbytes; i++)
2961 bufp->kind = ascii_keystroke;
2962 XSET (bufp->code, Lisp_Int, where_mapping[i]);
2963 XSET (bufp->time, Lisp_Int, event.xkey.time);
2964 XSET (bufp->frame_or_window, Lisp_Frame, f);
2965 bufp++;
2967 count += nbytes;
2968 numchars -= nbytes;
2971 break;
2972 #endif /* ! defined (HAVE_X11) */
2974 #ifdef HAVE_X11
2976 /* Here's a possible interpretation of the whole
2977 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2978 FocusIn event, you have to get a FocusOut event before you
2979 relinquish the focus. If you haven't received a FocusIn event,
2980 then a mere LeaveNotify is enough to free you. */
2982 case EnterNotify:
2983 f = x_window_to_frame (event.xcrossing.window);
2985 if (event.xcrossing.focus) /* Entered Window */
2987 /* Avoid nasty pop/raise loops. */
2988 if (f && (!(f->auto_raise)
2989 || !(f->auto_lower)
2990 || (event.xcrossing.time - enter_timestamp) > 500))
2992 x_new_focus_frame (f);
2993 enter_timestamp = event.xcrossing.time;
2996 else if (f == x_focus_frame)
2997 x_new_focus_frame (0);
2999 break;
3001 case FocusIn:
3002 f = x_window_to_frame (event.xfocus.window);
3003 if (event.xfocus.detail != NotifyPointer)
3004 x_focus_event_frame = f;
3005 if (f)
3006 x_new_focus_frame (f);
3007 break;
3010 case LeaveNotify:
3011 f = x_window_to_frame (event.xcrossing.window);
3013 if (event.xcrossing.focus)
3015 if (! x_focus_event_frame)
3016 x_new_focus_frame (0);
3017 else
3018 x_new_focus_frame (f);
3020 else
3022 if (f == x_focus_event_frame)
3023 x_focus_event_frame = 0;
3024 if (f == x_focus_frame)
3025 x_new_focus_frame (0);
3027 break;
3029 case FocusOut:
3030 f = x_window_to_frame (event.xfocus.window);
3031 if (event.xfocus.detail != NotifyPointer
3032 && f == x_focus_event_frame)
3033 x_focus_event_frame = 0;
3034 if (f && f == x_focus_frame)
3035 x_new_focus_frame (0);
3036 break;
3038 #else /* ! defined (HAVE_X11) */
3040 case EnterWindow:
3041 if ((event.detail & 0xFF) == 1)
3042 break; /* Coming from our own subwindow */
3043 if (event.subwindow != 0)
3044 break; /* Entering our own subwindow. */
3047 f = x_window_to_frame (event.window);
3048 x_mouse_frame = f;
3050 x_new_focus_frame (f);
3052 break;
3054 case LeaveWindow:
3055 if ((event.detail & 0xFF) == 1)
3056 break; /* Entering our own subwindow */
3057 if (event.subwindow != 0)
3058 break; /* Leaving our own subwindow. */
3060 x_mouse_frame = 0;
3061 if (x_focus_frame == 0
3062 && x_input_frame != 0
3063 && x_input_frame == x_window_to_frame (event.window)
3064 && event.window == FRAME_X_WINDOW (x_input_frame))
3066 f = x_input_frame;
3067 x_input_frame = 0;
3068 if (f)
3069 frame_unhighlight (f);
3071 break;
3072 #endif /* ! defined (HAVE_X11) */
3074 #ifdef HAVE_X11
3075 case MotionNotify:
3077 f = x_window_to_frame (event.xmotion.window);
3078 if (f)
3079 note_mouse_movement (f, &event.xmotion);
3080 else
3082 struct scroll_bar *bar =
3083 x_window_to_scroll_bar (event.xmotion.window);
3085 if (bar)
3086 x_scroll_bar_note_movement (bar, &event);
3089 break;
3091 case ConfigureNotify:
3092 f = x_window_to_frame (event.xconfigure.window);
3093 if (f)
3095 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3096 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3098 /* Even if the number of character rows and columns has
3099 not changed, the font size may have changed, so we need
3100 to check the pixel dimensions as well. */
3101 if (columns != f->width
3102 || rows != f->height
3103 || event.xconfigure.width != f->display.x->pixel_width
3104 || event.xconfigure.height != f->display.x->pixel_height)
3106 change_frame_size (f, rows, columns, 0, 1);
3107 SET_FRAME_GARBAGED (f);
3110 if (! event.xconfigure.send_event)
3112 Window win, child;
3113 int win_x, win_y;
3115 /* Coords are relative to the parent.
3116 Convert them to root-relative. */
3117 XTranslateCoordinates (x_current_display,
3119 /* From-window, to-window. */
3120 f->display.x->parent_desc,
3121 ROOT_WINDOW,
3123 /* From-position, to-position. */
3124 event.xconfigure.x,
3125 event.xconfigure.y,
3126 &win_x, &win_y,
3128 /* Child of win. */
3129 &child);
3130 event.xconfigure.x = win_x;
3131 event.xconfigure.y = win_y;
3134 f->display.x->pixel_width = event.xconfigure.width;
3135 f->display.x->pixel_height = event.xconfigure.height;
3136 f->display.x->left_pos = event.xconfigure.x;
3137 f->display.x->top_pos = event.xconfigure.y;
3139 break;
3141 case ButtonPress:
3142 case ButtonRelease:
3144 /* If we decide we want to generate an event to be seen
3145 by the rest of Emacs, we put it here. */
3146 struct input_event emacs_event;
3147 emacs_event.kind = no_event;
3149 f = x_window_to_frame (event.xbutton.window);
3150 if (f)
3152 if (!x_focus_frame || (f == x_focus_frame))
3153 construct_mouse_click (&emacs_event,
3154 &event, f);
3156 else
3158 struct scroll_bar *bar =
3159 x_window_to_scroll_bar (event.xbutton.window);
3161 if (bar)
3162 x_scroll_bar_handle_click (bar, &event, &emacs_event);
3165 if (numchars >= 1 && emacs_event.kind != no_event)
3167 bcopy (&emacs_event, bufp, sizeof (struct input_event));
3168 bufp++;
3169 count++;
3170 numchars--;
3173 break;
3175 #else /* ! defined (HAVE_X11) */
3176 case ButtonPressed:
3177 case ButtonReleased:
3178 f = x_window_to_frame (event.window);
3179 if (f)
3181 if (event.window == f->display.x->icon_desc)
3183 x_make_frame_visible (f);
3185 if (warp_mouse_on_deiconify)
3186 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
3187 break;
3189 if (event.window == FRAME_X_WINDOW (f))
3191 if (f->auto_raise)
3192 x_raise_frame (f);
3195 enqueue_event (&event, &x_mouse_queue);
3196 if (numchars >= 2)
3198 bufp->kind = ascii_keystroke;
3199 bufp->code = (char) 'X' & 037; /* C-x */
3200 XSET (bufp->frame_or_window, Lisp_Frame, f);
3201 XSET (bufp->time, Lisp_Int, event.xkey.time);
3202 bufp++;
3204 bufp->kind = ascii_keystroke;
3205 bufp->code = (char) 0; /* C-@ */
3206 XSET (bufp->frame_or_window, Lisp_Frame, f);
3207 XSET (bufp->time, Lisp_Int, event.xkey.time);
3208 bufp++;
3210 count += 2;
3211 numchars -= 2;
3213 break;
3214 #endif /* ! defined (HAVE_X11) */
3216 #ifdef HAVE_X11
3218 case CirculateNotify:
3219 break;
3220 case CirculateRequest:
3221 break;
3223 #endif /* ! defined (HAVE_X11) */
3225 case MappingNotify:
3226 /* Someone has changed the keyboard mapping - update the
3227 local cache. */
3228 switch (event.xmapping.request)
3230 case MappingModifier:
3231 x_find_modifier_meanings ();
3232 /* This is meant to fall through. */
3233 case MappingKeyboard:
3234 XRefreshKeyboardMapping (&event.xmapping);
3236 break;
3238 default:
3239 break;
3243 #if 0
3244 #ifdef HAVE_SELECT
3245 if (expected && ! event_found)
3247 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3248 there is an EOF condition; in other words, that X has died.
3249 Act as if there had been a hangup. */
3251 int fd = ConnectionNumber (x_current_display);
3252 int mask = 1 << fd;
3254 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
3255 (EMACS_TIME) 0)
3256 && !XStuffPending ())
3257 kill (getpid (), SIGHUP);
3259 #endif /* ! defined (HAVE_SELECT) */
3260 #endif /* ! 0 */
3262 #ifndef HAVE_X11
3263 if (updating_frame == 0)
3264 x_do_pending_expose ();
3265 #endif
3267 UNBLOCK_INPUT;
3268 return count;
3271 #ifndef HAVE_X11
3272 /* Read and process only Expose events
3273 until we get an ExposeCopy event; then return.
3274 This is used in insert/delete line.
3275 We assume input is already blocked. */
3277 static void
3278 x_read_exposes ()
3280 struct frame *f;
3281 XKeyPressedEvent event;
3283 while (1)
3285 /* while there are more events*/
3286 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
3287 switch (event.type)
3289 case ExposeWindow:
3290 if (event.subwindow != 0)
3291 break; /* duplicate event */
3292 f = x_window_to_frame (event.window);
3293 if (event.window == f->display.x->icon_desc)
3295 refreshicon (f);
3296 break;
3298 if (event.window == FRAME_X_WINDOW (f))
3300 expose_all_windows = 1;
3301 f->display.x->needs_exposure = 1;
3302 break;
3304 break;
3306 case ExposeRegion:
3307 if (event.subwindow != 0)
3308 break; /* duplicate event */
3309 f = x_window_to_frame (event.window);
3310 if (event.window == f->display.x->icon_desc)
3312 refreshicon (f);
3313 break;
3315 /* If window already needs full redraw, ignore this rectangle. */
3316 if (expose_all_windows && f->display.x->needs_exposure)
3317 break;
3318 /* Put the event on the queue of rectangles to redraw. */
3319 if (enqueue_event (&event, &x_expose_queue))
3320 /* If it is full, we can't record the rectangle,
3321 so redraw this entire window. */
3323 /* Say must check all windows' needs_exposure flags. */
3324 expose_all_windows = 1;
3325 f->display.x->needs_exposure = 1;
3327 break;
3329 case ExposeCopy:
3330 return;
3334 #endif /* HAVE_X11 */
3337 /* Drawing the cursor. */
3340 /* Draw a hollow box cursor. Don't change the inside of the box. */
3342 static void
3343 x_draw_box (f)
3344 struct frame *f;
3346 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
3347 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
3348 int width = FONT_WIDTH (f->display.x->font);
3349 int height = FONT_HEIGHT (f->display.x->font);
3351 #ifdef HAVE_X11
3352 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
3353 f->display.x->cursor_gc,
3354 left, top, width - 1, height - 1);
3355 #else /* ! defined (HAVE_X11) */
3356 XPixSet (FRAME_X_WINDOW (f),
3357 left, top, width, 1,
3358 f->display.x->cursor_pixel);
3360 XPixSet (FRAME_X_WINDOW (f),
3361 left, top, 1, height,
3362 f->display.x->cursor_pixel);
3364 XPixSet (FRAME_X_WINDOW (f),
3365 left+width-1, top, 1, height,
3366 f->display.x->cursor_pixel);
3368 XPixSet (FRAME_X_WINDOW (f),
3369 left, top+height-1, width, 1,
3370 f->display.x->cursor_pixel);
3371 #endif /* ! defined (HAVE_X11) */
3374 /* Clear the cursor of frame F to background color,
3375 and mark the cursor as not shown.
3376 This is used when the text where the cursor is
3377 is about to be rewritten. */
3379 static void
3380 clear_cursor (f)
3381 struct frame *f;
3383 int mask;
3385 if (! FRAME_VISIBLE_P (f)
3386 || f->phys_cursor_x < 0)
3387 return;
3389 #ifdef HAVE_X11
3390 x_display_cursor (f, 0);
3391 #else /* ! defined (HAVE_X11) */
3392 XPixSet (FRAME_X_WINDOW (f),
3393 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3394 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
3395 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
3396 f->display.x->background_pixel);
3397 #endif /* ! defined (HAVE_X11) */
3398 f->phys_cursor_x = -1;
3401 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3402 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3403 glyph drawn. */
3405 static void
3406 x_draw_single_glyph (f, row, column, glyph, highlight)
3407 struct frame *f;
3408 int row, column;
3409 GLYPH glyph;
3410 int highlight;
3412 dumpglyphs (f,
3413 CHAR_TO_PIXEL_COL (f, column),
3414 CHAR_TO_PIXEL_ROW (f, row),
3415 &glyph, 1, highlight);
3418 static void
3419 x_display_bar_cursor (f, on)
3420 struct frame *f;
3421 int on;
3423 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3425 /* This is pointless on invisible frames, and dangerous on garbaged
3426 frames; in the latter case, the frame may be in the midst of
3427 changing its size, and curs_x and curs_y may be off the frame. */
3428 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3429 return;
3431 if (! on && f->phys_cursor_x < 0)
3432 return;
3434 /* If we're not updating, then we want to use the current frame's
3435 cursor position, not our local idea of where the cursor ought to be. */
3436 if (f != updating_frame)
3438 curs_x = FRAME_CURSOR_X (f);
3439 curs_y = FRAME_CURSOR_Y (f);
3442 /* If there is anything wrong with the current cursor state, remove it. */
3443 if (f->phys_cursor_x >= 0
3444 && (!on
3445 || f->phys_cursor_x != curs_x
3446 || f->phys_cursor_y != curs_y
3447 || f->display.x->current_cursor != bar_cursor))
3449 /* Erase the cursor by redrawing the character underneath it. */
3450 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3451 f->phys_cursor_glyph,
3452 current_glyphs->highlight[f->phys_cursor_y]);
3453 f->phys_cursor_x = -1;
3456 /* If we now need a cursor in the new place or in the new form, do it so. */
3457 if (on
3458 && (f->phys_cursor_x < 0
3459 || (f->display.x->current_cursor != bar_cursor)))
3461 f->phys_cursor_glyph
3462 = ((current_glyphs->enable[curs_y]
3463 && curs_x < current_glyphs->used[curs_y])
3464 ? current_glyphs->glyphs[curs_y][curs_x]
3465 : SPACEGLYPH);
3466 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
3467 f->display.x->cursor_gc,
3468 CHAR_TO_PIXEL_COL (f, curs_x),
3469 CHAR_TO_PIXEL_ROW (f, curs_y),
3470 1, FONT_HEIGHT (f->display.x->font));
3472 f->phys_cursor_x = curs_x;
3473 f->phys_cursor_y = curs_y;
3475 f->display.x->current_cursor = bar_cursor;
3478 if (updating_frame != f)
3479 XFlushQueue ();
3483 /* Turn the displayed cursor of frame F on or off according to ON.
3484 If ON is nonzero, where to put the cursor is specified
3485 by F->cursor_x and F->cursor_y. */
3487 static void
3488 x_display_box_cursor (f, on)
3489 struct frame *f;
3490 int on;
3492 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3494 /* This is pointless on invisible frames, and dangerous on garbaged
3495 frames; in the latter case, the frame may be in the midst of
3496 changing its size, and curs_x and curs_y may be off the frame. */
3497 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3498 return;
3500 /* If cursor is off and we want it off, return quickly. */
3501 if (!on && f->phys_cursor_x < 0)
3502 return;
3504 /* If we're not updating, then we want to use the current frame's
3505 cursor position, not our local idea of where the cursor ought to be. */
3506 if (f != updating_frame)
3508 curs_x = FRAME_CURSOR_X (f);
3509 curs_y = FRAME_CURSOR_Y (f);
3512 /* If cursor is currently being shown and we don't want it to be
3513 or it is in the wrong place,
3514 or we want a hollow box and it's not so, (pout!)
3515 erase it. */
3516 if (f->phys_cursor_x >= 0
3517 && (!on
3518 || f->phys_cursor_x != curs_x
3519 || f->phys_cursor_y != curs_y
3520 || (f->display.x->current_cursor != hollow_box_cursor
3521 && (f != x_highlight_frame))))
3523 /* Erase the cursor by redrawing the character underneath it. */
3524 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3525 f->phys_cursor_glyph,
3526 current_glyphs->highlight[f->phys_cursor_y]);
3527 f->phys_cursor_x = -1;
3530 /* If we want to show a cursor,
3531 or we want a box cursor and it's not so,
3532 write it in the right place. */
3533 if (on
3534 && (f->phys_cursor_x < 0
3535 || (f->display.x->current_cursor != filled_box_cursor
3536 && f == x_highlight_frame)))
3538 f->phys_cursor_glyph
3539 = ((current_glyphs->enable[curs_y]
3540 && curs_x < current_glyphs->used[curs_y])
3541 ? current_glyphs->glyphs[curs_y][curs_x]
3542 : SPACEGLYPH);
3543 if (f != x_highlight_frame)
3545 x_draw_box (f);
3546 f->display.x->current_cursor = hollow_box_cursor;
3548 else
3550 x_draw_single_glyph (f, curs_y, curs_x,
3551 f->phys_cursor_glyph, 2);
3552 f->display.x->current_cursor = filled_box_cursor;
3555 f->phys_cursor_x = curs_x;
3556 f->phys_cursor_y = curs_y;
3559 if (updating_frame != f)
3560 XFlushQueue ();
3563 x_display_cursor (f, on)
3564 struct frame *f;
3565 int on;
3567 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
3568 x_display_box_cursor (f, on);
3569 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3570 x_display_bar_cursor (f, on);
3571 else
3572 /* Those are the only two we have implemented! */
3573 abort ();
3576 /* Icons. */
3578 /* Refresh bitmap kitchen sink icon for frame F
3579 when we get an expose event for it. */
3581 refreshicon (f)
3582 struct frame *f;
3584 #ifdef HAVE_X11
3585 /* Normally, the window manager handles this function. */
3586 #else /* ! defined (HAVE_X11) */
3587 int mask;
3589 if (f->display.x->icon_bitmap_flag)
3590 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
3591 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
3592 icon_bitmap, GXcopy, AllPlanes);
3593 else
3595 extern struct frame *selected_frame;
3596 struct Lisp_String *str;
3597 unsigned char *string;
3599 string
3600 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
3602 if (f->display.x->icon_label != string)
3604 f->display.x->icon_label = string;
3605 XChangeWindow (f->display.x->icon_desc,
3606 XQueryWidth (string, icon_font_info->id) + 10,
3607 icon_font_info->height + 10);
3610 XText (f->display.x->icon_desc, 5, 5, string,
3611 str->size, icon_font_info->id,
3612 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
3614 XFlushQueue ();
3615 #endif /* ! defined (HAVE_X11) */
3618 /* Make the x-window of frame F use the gnu icon bitmap. */
3621 x_bitmap_icon (f)
3622 struct frame *f;
3624 int mask;
3625 Window icon_window;
3627 if (FRAME_X_WINDOW (f) == 0)
3628 return 1;
3630 #ifdef HAVE_X11
3631 if (! icon_bitmap)
3632 icon_bitmap =
3633 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
3634 gnu_bits, gnu_width, gnu_height);
3635 x_wm_set_icon_pixmap (f, icon_bitmap);
3636 f->display.x->icon_bitmap_flag = 1;
3637 #else /* ! defined (HAVE_X11) */
3638 if (f->display.x->icon_desc)
3640 XClearIconWindow (FRAME_X_WINDOW (f));
3641 XDestroyWindow (f->display.x->icon_desc);
3644 icon_window = XCreateWindow (f->display.x->parent_desc,
3645 0, 0, sink_width, sink_height,
3646 2, WhitePixmap, (Pixmap) NULL);
3648 if (icon_window == 0)
3649 return 1;
3651 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3652 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
3654 f->display.x->icon_desc = icon_window;
3655 f->display.x->icon_bitmap_flag = 1;
3657 if (icon_bitmap == 0)
3658 icon_bitmap
3659 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
3660 #endif /* ! defined (HAVE_X11) */
3662 return 0;
3666 /* Make the x-window of frame F use a rectangle with text. */
3669 x_text_icon (f, icon_name)
3670 struct frame *f;
3671 char *icon_name;
3673 #ifndef HAVE_X11
3674 int mask;
3675 int width;
3676 Window icon_window;
3677 char *X_DefaultValue;
3678 Bitmap b1;
3680 #ifndef WhitePixel
3681 #define WhitePixel 1
3682 #endif /* WhitePixel */
3684 #ifndef BlackPixel
3685 #define BlackPixel 0
3686 #endif /* BlackPixel */
3687 #endif /* HAVE_X11 */
3689 if (FRAME_X_WINDOW (f) == 0)
3690 return 1;
3692 #ifdef HAVE_X11
3693 if (icon_name)
3694 f->display.x->icon_label = icon_name;
3695 else
3696 if (! f->display.x->icon_label)
3697 f->display.x->icon_label = " *emacs* ";
3699 #if 0
3700 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
3701 (char *) f->display.x->icon_label);
3702 #endif
3704 f->display.x->icon_bitmap_flag = 0;
3705 x_wm_set_icon_pixmap (f, 0);
3706 #else /* ! defined (HAVE_X11) */
3707 if (icon_font_info == 0)
3708 icon_font_info
3709 = XGetFont (XGetDefault (XDISPLAY
3710 (char *) XSTRING (Vinvocation_name)->data,
3711 "BodyFont"));
3713 if (f->display.x->icon_desc)
3715 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
3716 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
3719 if (icon_name)
3720 f->display.x->icon_label = (unsigned char *) icon_name;
3721 else
3722 if (! f->display.x->icon_label)
3723 f->display.x->icon_label = XSTRING (f->name)->data;
3725 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
3726 icon_window = XCreateWindow (f->display.x->parent_desc,
3727 f->display.x->left_pos,
3728 f->display.x->top_pos,
3729 width + 10, icon_font_info->height + 10,
3730 2, BlackPixmap, WhitePixmap);
3732 if (icon_window == 0)
3733 return 1;
3735 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3736 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
3738 f->display.x->icon_desc = icon_window;
3739 f->display.x->icon_bitmap_flag = 0;
3740 f->display.x->icon_label = 0;
3741 #endif /* ! defined (HAVE_X11) */
3743 return 0;
3746 /* Handling X errors. */
3748 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3749 X server's connection, or an error reported via the X protocol. */
3751 static SIGTYPE
3752 x_connection_closed ()
3754 if (_Xdebug)
3755 abort ();
3757 shut_down_emacs (0, 1);
3759 exit (70);
3762 /* An X error handler which prints an error message and then kills
3763 Emacs. This is what's normally installed as Xlib's handler for
3764 protocol errors. */
3765 static int
3766 x_error_quitter (display, error)
3767 Display *display;
3768 XErrorEvent *error;
3770 char buf[256];
3772 /* Note that there is no real way portable across R3/R4 to get the
3773 original error handler. */
3775 XGetErrorText (display, error->error_code, buf, sizeof (buf));
3776 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
3777 buf, error->request_code);
3779 /* While we're testing Emacs 19, we'll just dump core whenever we
3780 get an X error, so we can figure out why it happened. */
3781 abort ();
3783 x_connection_closed ();
3786 /* A handler for X IO errors which prints an error message and then
3787 kills Emacs. This is what is always installed as Xlib's handler
3788 for I/O errors. */
3789 static int
3790 x_io_error_quitter (display)
3791 Display *display;
3793 fprintf (stderr, "Connection to X server %s lost.\n",
3794 XDisplayName (DisplayString (display)));
3796 /* While we're testing Emacs 19, we'll just dump core whenever we
3797 get an X error, so we can figure out why it happened. */
3798 abort ();
3800 x_connection_closed ();
3803 /* A buffer for storing X error messages. */
3804 static char (*x_caught_error_message)[200];
3806 /* An X error handler which stores the error message in
3807 x_caught_error_message. This is what's installed when
3808 x_catch_errors is in effect. */
3809 static int
3810 x_error_catcher (display, error)
3811 Display *display;
3812 XErrorEvent *error;
3814 XGetErrorText (display, error->error_code,
3815 *x_caught_error_message, sizeof (*x_caught_error_message));
3819 /* Begin trapping X errors.
3821 After calling this function, X protocol errors no longer cause
3822 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3824 Calling x_check_errors signals an Emacs error if an X error has
3825 occurred since the last call to x_catch_errors or x_check_errors.
3827 Calling x_uncatch_errors resumes the normal error handling. */
3829 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3831 void
3832 x_catch_errors ()
3834 /* Make sure any errors from previous requests have been dealt with. */
3835 XSync (x_current_display, False);
3837 /* Set up the error buffer. */
3838 x_caught_error_message =
3839 (char (*)[]) xmalloc (sizeof (*x_caught_error_message));
3840 (*x_caught_error_message)[0] = '\0';
3842 /* Install our little error handler. */
3843 XHandleError (x_error_catcher);
3846 /* If any X protocol errors have arrived since the last call to
3847 x_catch_errors or x_check_errors, signal an Emacs error using
3848 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3849 void
3850 x_check_errors (format)
3851 char *format;
3853 /* Make sure to catch any errors incurred so far. */
3854 XSync (x_current_display, False);
3856 if ((*x_caught_error_message)[0])
3858 char buf[256];
3860 sprintf (buf, format, *x_caught_error_message);
3861 xfree (x_caught_error_message);
3863 x_uncatch_errors ();
3864 error (buf);
3868 void
3869 x_uncatch_errors ()
3871 xfree (x_caught_error_message);
3872 XHandleError (x_error_quitter);
3875 #if 0
3876 static unsigned int x_wire_count;
3877 x_trace_wire ()
3879 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3881 #endif /* ! 0 */
3884 /* Changing the font of the frame. */
3886 /* Set the font of the x-window specified by frame F
3887 to the font named NEWNAME. This is safe to use
3888 even before F has an actual x-window. */
3890 #ifdef HAVE_X11
3892 /* A table of all the fonts we have already loaded. */
3893 static XFontStruct **x_font_table;
3895 /* The current capacity of x_font_table. */
3896 static int x_font_table_size;
3898 /* The number of fonts actually stored in x_font_table.
3899 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3900 0 <= n_fonts <= x_font_table_size. */
3901 static int n_fonts;
3903 Lisp_Object
3904 x_new_font (f, fontname)
3905 struct frame *f;
3906 register char *fontname;
3908 int already_loaded;
3909 int n_matching_fonts;
3910 XFontStruct *font_info;
3911 char **font_names;
3913 /* Get a list of all the fonts that match this name. Once we
3914 have a list of matching fonts, we compare them against the fonts
3915 we already have by comparing font ids. */
3916 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3917 1024, &n_matching_fonts,
3918 &font_info);
3920 /* If the server couldn't find any fonts whose named matched fontname,
3921 return an error code. */
3922 if (n_matching_fonts == 0)
3923 return Qnil;
3925 /* See if we've already loaded a matching font. */
3927 int i, j;
3929 already_loaded = 0;
3930 for (i = 0; i < n_fonts; i++)
3931 for (j = 0; j < n_matching_fonts; j++)
3932 if (x_font_table[i]->fid == font_info[j].fid)
3934 already_loaded = i;
3935 fontname = font_names[j];
3936 goto found_font;
3939 found_font:
3941 /* If we have, just return it from the table. */
3942 if (already_loaded)
3943 f->display.x->font = x_font_table[already_loaded];
3945 /* Otherwise, load the font and add it to the table. */
3946 else
3948 int i;
3949 XFontStruct *font;
3951 /* Try to find a character-cell font in the list. */
3952 #if 0
3953 /* A laudable goal, but this isn't how to do it. */
3954 for (i = 0; i < n_matching_fonts; i++)
3955 if (! font_info[i].per_char)
3956 break;
3957 #else
3958 i = 0;
3959 #endif
3961 if (i >= n_matching_fonts)
3962 return Qt;
3963 else
3964 fontname = font_names[i];
3966 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
3967 if (! font)
3968 return Qnil;
3970 /* Do we need to create the table? */
3971 if (x_font_table_size == 0)
3973 x_font_table_size = 16;
3974 x_font_table
3975 = (XFontStruct **) xmalloc (x_font_table_size
3976 * sizeof (x_font_table[0]));
3978 /* Do we need to grow the table? */
3979 else if (n_fonts >= x_font_table_size)
3981 x_font_table_size *= 2;
3982 x_font_table
3983 = (XFontStruct **) xrealloc (x_font_table,
3984 (x_font_table_size
3985 * sizeof (x_font_table[0])));
3988 f->display.x->font = x_font_table[n_fonts++] = font;
3991 /* Now make the frame display the given font. */
3992 if (FRAME_X_WINDOW (f) != 0)
3994 XSetFont (x_current_display, f->display.x->normal_gc,
3995 f->display.x->font->fid);
3996 XSetFont (x_current_display, f->display.x->reverse_gc,
3997 f->display.x->font->fid);
3998 XSetFont (x_current_display, f->display.x->cursor_gc,
3999 f->display.x->font->fid);
4001 x_set_window_size (f, f->width, f->height);
4005 Lisp_Object lispy_name = build_string (fontname);
4008 /* Free the information from XListFontsWithInfo. The data
4009 we actually retain comes from XLoadQueryFont. */
4010 XFreeFontInfo (font_names, font_info, n_matching_fonts);
4012 return lispy_name;
4015 #else /* ! defined (HAVE_X11) */
4016 x_new_font (f, newname)
4017 struct frame *f;
4018 register char *newname;
4020 FONT_TYPE *temp;
4021 int mask;
4023 temp = XGetFont (newname);
4024 if (temp == (FONT_TYPE *) 0)
4025 return 1;
4027 if (f->display.x->font)
4028 XLoseFont (f->display.x->font);
4030 f->display.x->font = temp;
4032 if (FRAME_X_WINDOW (f) != 0)
4033 x_set_window_size (f, f->width, f->height);
4035 return 0;
4037 #endif /* ! defined (HAVE_X11) */
4039 /* X Window sizes and positions. */
4041 x_calc_absolute_position (f)
4042 struct frame *f;
4044 #ifdef HAVE_X11
4045 if (f->display.x->left_pos < 0)
4046 f->display.x->left_pos
4047 = x_screen_width - PIXEL_WIDTH (f) + f->display.x->left_pos;
4049 if (f->display.x->top_pos < 0)
4050 f->display.x->top_pos
4051 = x_screen_height - PIXEL_HEIGHT (f) + f->display.x->top_pos;
4052 #else /* ! defined (HAVE_X11) */
4053 WINDOWINFO_TYPE parentinfo;
4055 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
4057 if (f->display.x->left_pos < 0)
4058 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
4059 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
4061 if (f->display.x->top_pos < 0)
4062 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
4063 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
4064 #endif /* ! defined (HAVE_X11) */
4067 x_set_offset (f, xoff, yoff)
4068 struct frame *f;
4069 register int xoff, yoff;
4071 f->display.x->top_pos = yoff;
4072 f->display.x->left_pos = xoff;
4073 x_calc_absolute_position (f);
4075 BLOCK_INPUT;
4076 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
4077 f->display.x->left_pos, f->display.x->top_pos);
4078 #ifdef HAVE_X11
4079 x_wm_set_size_hint (f, 0);
4080 #endif /* ! defined (HAVE_X11) */
4081 UNBLOCK_INPUT;
4084 /* Call this to change the size of frame F's x-window. */
4086 x_set_window_size (f, cols, rows)
4087 struct frame *f;
4088 int cols, rows;
4090 int pixelwidth, pixelheight;
4091 int mask;
4093 BLOCK_INPUT;
4095 check_frame_size (f, &rows, &cols);
4096 f->display.x->vertical_scroll_bar_extra =
4097 (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4098 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
4099 : 0);
4100 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
4101 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
4103 #ifdef HAVE_X11
4104 x_wm_set_size_hint (f, 0);
4105 #endif /* ! defined (HAVE_X11) */
4106 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
4108 /* Now, strictly speaking, we can't be sure that this is accurate,
4109 but the window manager will get around to dealing with the size
4110 change request eventually, and we'll hear how it went when the
4111 ConfigureNotify event gets here.
4113 We could just not bother storing any of this information here,
4114 and let the ConfigureNotify event set everything up, but that
4115 might be kind of confusing to the lisp code, since size changes
4116 wouldn't be reported in the frame parameters until some random
4117 point in the future when the ConfigureNotify event arrives. */
4118 change_frame_size (f, rows, cols, 0, 0);
4119 PIXEL_WIDTH (f) = pixelwidth;
4120 PIXEL_HEIGHT (f) = pixelheight;
4122 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4123 receive in the ConfigureNotify event; if we get what we asked
4124 for, then the event won't cause the screen to become garbaged, so
4125 we have to make sure to do it here. */
4126 SET_FRAME_GARBAGED (f);
4128 XFlushQueue ();
4129 UNBLOCK_INPUT;
4132 #ifndef HAVE_X11
4133 x_set_resize_hint (f)
4134 struct frame *f;
4136 XSetResizeHint (FRAME_X_WINDOW (f),
4137 2 * f->display.x->internal_border_width,
4138 2 * f->display.x->internal_border_width,
4139 FONT_WIDTH (f->display.x->font),
4140 FONT_HEIGHT (f->display.x->font));
4142 #endif /* HAVE_X11 */
4144 /* Mouse warping, focus shifting, raising and lowering. */
4146 x_set_mouse_position (f, x, y)
4147 struct frame *f;
4148 int x, y;
4150 int pix_x, pix_y;
4152 x_raise_frame (f);
4154 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
4155 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
4157 if (pix_x < 0) pix_x = 0;
4158 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4160 if (pix_y < 0) pix_y = 0;
4161 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
4163 BLOCK_INPUT;
4165 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
4166 UNBLOCK_INPUT;
4169 #ifdef HAVE_X11
4170 x_focus_on_frame (f)
4171 struct frame *f;
4173 x_raise_frame (f);
4174 #if 0
4175 /* I don't think that the ICCCM allows programs to do things like this
4176 without the interaction of the window manager. Whatever you end up
4177 doing with this code, do it to x_unfocus_frame too. */
4178 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
4179 RevertToPointerRoot, CurrentTime);
4180 #endif /* ! 0 */
4183 x_unfocus_frame (f)
4184 struct frame *f;
4186 #if 0
4187 /* Look at the remarks in x_focus_on_frame. */
4188 if (x_focus_frame == f)
4189 XSetInputFocus (x_current_display, PointerRoot,
4190 RevertToPointerRoot, CurrentTime);
4191 #endif /* ! 0 */
4194 #endif /* ! defined (HAVE_X11) */
4196 /* Raise frame F. */
4198 x_raise_frame (f)
4199 struct frame *f;
4201 if (f->async_visible)
4203 BLOCK_INPUT;
4204 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
4205 XFlushQueue ();
4206 UNBLOCK_INPUT;
4210 /* Lower frame F. */
4212 x_lower_frame (f)
4213 struct frame *f;
4215 if (f->async_visible)
4217 BLOCK_INPUT;
4218 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
4219 XFlushQueue ();
4220 UNBLOCK_INPUT;
4224 static void
4225 XTframe_raise_lower (f, raise)
4226 FRAME_PTR f;
4227 int raise;
4229 if (raise)
4230 x_raise_frame (f);
4231 else
4232 x_lower_frame (f);
4236 /* Change from withdrawn state to mapped state. */
4238 x_make_frame_visible (f)
4239 struct frame *f;
4241 int mask;
4243 BLOCK_INPUT;
4245 if (! FRAME_VISIBLE_P (f))
4247 #ifdef HAVE_X11
4248 if (! EQ (Vx_no_window_manager, Qt))
4249 x_wm_set_window_state (f, NormalState);
4251 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4252 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4253 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4254 #else /* ! defined (HAVE_X11) */
4255 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4256 if (f->display.x->icon_desc != 0)
4257 XUnmapWindow (f->display.x->icon_desc);
4259 /* Handled by the MapNotify event for X11 */
4260 f->async_visible = 1;
4261 f->async_iconified = 0;
4263 /* NOTE: this may cause problems for the first frame. */
4264 XTcursor_to (0, 0);
4265 #endif /* ! defined (HAVE_X11) */
4268 XFlushQueue ();
4270 UNBLOCK_INPUT;
4273 /* Change from mapped state to withdrawn state. */
4275 x_make_frame_invisible (f)
4276 struct frame *f;
4278 int mask;
4280 /* Don't keep the highlight on an invisible frame. */
4281 if (x_highlight_frame == f)
4282 x_highlight_frame = 0;
4284 if (! f->async_visible && ! f->async_iconified)
4285 return;
4287 BLOCK_INPUT;
4289 #ifdef HAVE_X11R4
4291 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
4292 DefaultScreen (x_current_display)))
4294 UNBLOCK_INPUT_RESIGNAL;
4295 error ("can't notify window manager of window withdrawl");
4298 #else /* ! defined (HAVE_X11R4) */
4299 #ifdef HAVE_X11
4301 /* Tell the window manager what we're going to do. */
4302 if (! EQ (Vx_no_window_manager, Qt))
4304 XEvent unmap;
4306 unmap.xunmap.type = UnmapNotify;
4307 unmap.xunmap.window = FRAME_X_WINDOW (f);
4308 unmap.xunmap.event = DefaultRootWindow (x_current_display);
4309 unmap.xunmap.from_configure = False;
4310 if (! XSendEvent (x_current_display,
4311 DefaultRootWindow (x_current_display),
4312 False,
4313 SubstructureRedirectMask|SubstructureNotifyMask,
4314 &unmap))
4316 UNBLOCK_INPUT_RESIGNAL;
4317 error ("can't notify window manager of withdrawal");
4321 /* Unmap the window ourselves. Cheeky! */
4322 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
4324 #else /* ! defined (HAVE_X11) */
4326 XUnmapWindow (FRAME_X_WINDOW (f));
4327 f->async_visible = 0; /* Handled by the UnMap event for X11 */
4328 if (f->display.x->icon_desc != 0)
4329 XUnmapWindow (f->display.x->icon_desc);
4331 #endif /* ! defined (HAVE_X11) */
4332 #endif /* ! defined (HAVE_X11R4) */
4334 XFlushQueue ();
4335 UNBLOCK_INPUT;
4338 /* Change window state from mapped to iconified. */
4340 x_iconify_frame (f)
4341 struct frame *f;
4343 int mask;
4345 /* Don't keep the highlight on an invisible frame. */
4346 if (x_highlight_frame == f)
4347 x_highlight_frame = 0;
4349 if (f->async_iconified)
4350 return;
4352 BLOCK_INPUT;
4354 #ifdef HAVE_X11
4355 /* Since we don't know which revision of X we're running, we'll use both
4356 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4358 /* X11R4: send a ClientMessage to the window manager using the
4359 WM_CHANGE_STATE type. */
4361 XEvent message;
4363 message.xclient.window = FRAME_X_WINDOW (f);
4364 message.xclient.type = ClientMessage;
4365 message.xclient.message_type = Xatom_wm_change_state;
4366 message.xclient.format = 32;
4367 message.xclient.data.l[0] = IconicState;
4369 if (! XSendEvent (x_current_display,
4370 DefaultRootWindow (x_current_display),
4371 False,
4372 SubstructureRedirectMask | SubstructureNotifyMask,
4373 &message))
4375 UNBLOCK_INPUT_RESIGNAL;
4376 error ("Can't notify window manager of iconification.");
4380 /* X11R3: set the initial_state field of the window manager hints to
4381 IconicState. */
4382 x_wm_set_window_state (f, IconicState);
4384 f->async_iconified = 1;
4385 #else /* ! defined (HAVE_X11) */
4386 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
4388 f->async_visible = 0; /* Handled in the UnMap event for X11. */
4389 if (f->display.x->icon_desc != 0)
4391 XMapWindow (XDISPLAY f->display.x->icon_desc);
4392 refreshicon (f);
4394 #endif /* ! defined (HAVE_X11) */
4396 XFlushQueue ();
4397 UNBLOCK_INPUT;
4400 /* Destroy the X window of frame F. */
4402 x_destroy_window (f)
4403 struct frame *f;
4405 BLOCK_INPUT;
4407 if (f->display.x->icon_desc != 0)
4408 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4409 XDestroyWindow (XDISPLAY f->display.x->window_desc);
4410 free_frame_faces (f);
4411 XFlushQueue ();
4413 xfree (f->display.x);
4414 f->display.x = 0;
4415 if (f == x_focus_frame)
4416 x_focus_frame = 0;
4417 if (f == x_highlight_frame)
4418 x_highlight_frame = 0;
4420 UNBLOCK_INPUT;
4423 /* Manage event queues for X10. */
4425 #ifndef HAVE_X11
4427 /* Manage event queues.
4429 This code is only used by the X10 support.
4431 We cannot leave events in the X queue and get them when we are ready
4432 because X does not provide a subroutine to get only a certain kind
4433 of event but not block if there are no queued events of that kind.
4435 Therefore, we must examine events as they come in and copy events
4436 of certain kinds into our private queues.
4438 All ExposeRegion events are put in x_expose_queue.
4439 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4442 /* Write the event *P_XREP into the event queue *QUEUE.
4443 If the queue is full, do nothing, but return nonzero. */
4446 enqueue_event (p_xrep, queue)
4447 register XEvent *p_xrep;
4448 register struct event_queue *queue;
4450 int newindex = queue->windex + 1;
4451 if (newindex == EVENT_BUFFER_SIZE)
4452 newindex = 0;
4453 if (newindex == queue->rindex)
4454 return -1;
4455 queue->xrep[queue->windex] = *p_xrep;
4456 queue->windex = newindex;
4457 return 0;
4460 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4461 If *QUEUE is empty, do nothing and return 0. */
4464 dequeue_event (p_xrep, queue)
4465 register XEvent *p_xrep;
4466 register struct event_queue *queue;
4468 if (queue->windex == queue->rindex)
4469 return 0;
4470 *p_xrep = queue->xrep[queue->rindex++];
4471 if (queue->rindex == EVENT_BUFFER_SIZE)
4472 queue->rindex = 0;
4473 return 1;
4476 /* Return the number of events buffered in *QUEUE. */
4479 queue_event_count (queue)
4480 register struct event_queue *queue;
4482 int tem = queue->windex - queue->rindex;
4483 if (tem >= 0)
4484 return tem;
4485 return EVENT_BUFFER_SIZE + tem;
4488 /* Return nonzero if mouse input is pending. */
4491 mouse_event_pending_p ()
4493 return queue_event_count (&x_mouse_queue);
4495 #endif /* HAVE_X11 */
4497 /* Setting window manager hints. */
4499 #ifdef HAVE_X11
4501 x_wm_set_size_hint (f, prompting)
4502 struct frame *f;
4503 long prompting;
4505 XSizeHints size_hints;
4506 Window window = FRAME_X_WINDOW (f);
4508 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
4510 flexlines = f->height;
4512 size_hints.x = f->display.x->left_pos;
4513 size_hints.y = f->display.x->top_pos;
4514 size_hints.height = PIXEL_HEIGHT (f);
4515 size_hints.width = PIXEL_WIDTH (f);
4516 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
4517 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
4518 #if 0
4519 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
4520 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
4521 #endif
4523 int base_width, base_height;
4525 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
4526 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
4529 int min_rows = 0, min_cols = 0;
4530 check_frame_size (f, &min_rows, &min_cols);
4532 /* The window manager uses the base width hints to calculate the
4533 current number of rows and columns in the frame while
4534 resizing; min_width and min_height aren't useful for this
4535 purpose, since they might not give the dimensions for a
4536 zero-row, zero-column frame.
4538 We use the base_width and base_height members if we have
4539 them; otherwise, we set the min_width and min_height members
4540 to the size for a zero x zero frame. */
4542 #ifdef HAVE_X11R4
4543 size_hints.flags |= PBaseSize;
4544 size_hints.base_width = base_width;
4545 size_hints.base_height = base_height;
4546 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
4547 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
4548 #else
4549 size_hints.min_width = base_width;
4550 size_hints.min_height = base_height;
4551 #endif
4556 if (prompting)
4557 size_hints.flags |= prompting;
4558 else
4560 XSizeHints hints; /* Sometimes I hate X Windows... */
4562 XGetNormalHints (x_current_display, window, &hints);
4563 if (hints.flags & PSize)
4564 size_hints.flags |= PSize;
4565 if (hints.flags & PPosition)
4566 size_hints.flags |= PPosition;
4567 if (hints.flags & USPosition)
4568 size_hints.flags |= USPosition;
4569 if (hints.flags & USSize)
4570 size_hints.flags |= USSize;
4573 #ifdef HAVE_X11R4
4574 XSetWMNormalHints (x_current_display, window, &size_hints);
4575 #else
4576 XSetNormalHints (x_current_display, window, &size_hints);
4577 #endif
4580 /* Used for IconicState or NormalState */
4581 x_wm_set_window_state (f, state)
4582 struct frame *f;
4583 int state;
4585 Window window = FRAME_X_WINDOW (f);
4587 f->display.x->wm_hints.flags |= StateHint;
4588 f->display.x->wm_hints.initial_state = state;
4590 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4593 x_wm_set_icon_pixmap (f, icon_pixmap)
4594 struct frame *f;
4595 Pixmap icon_pixmap;
4597 Window window = FRAME_X_WINDOW (f);
4599 if (icon_pixmap)
4601 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
4602 f->display.x->wm_hints.flags |= IconPixmapHint;
4604 else
4605 f->display.x->wm_hints.flags &= ~IconPixmapHint;
4607 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4610 x_wm_set_icon_position (f, icon_x, icon_y)
4611 struct frame *f;
4612 int icon_x, icon_y;
4614 Window window = FRAME_X_WINDOW (f);
4616 f->display.x->wm_hints.flags |= IconPositionHint;
4617 f->display.x->wm_hints.icon_x = icon_x;
4618 f->display.x->wm_hints.icon_y = icon_y;
4620 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4624 /* Initialization. */
4626 void
4627 x_term_init (display_name)
4628 char *display_name;
4630 Lisp_Object frame;
4631 char *defaultvalue;
4632 #ifdef F_SETOWN
4633 extern int old_fcntl_owner;
4634 #endif /* ! defined (F_SETOWN) */
4636 x_focus_frame = x_highlight_frame = 0;
4638 x_current_display = XOpenDisplay (display_name);
4639 if (x_current_display == 0)
4640 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4641 display_name);
4643 #ifdef HAVE_X11
4645 int hostname_size = 256;
4647 hostname = (char *) xmalloc (hostname_size);
4649 #if 0
4650 XSetAfterFunction (x_current_display, x_trace_wire);
4651 #endif /* ! 0 */
4653 /* Try to get the host name; if the buffer is too short, try
4654 again. Apparently, the only indication gethostname gives of
4655 whether the buffer was large enough is the presence or absence
4656 of a '\0' in the string. Eech. */
4657 for (;;)
4659 gethostname (hostname, hostname_size - 1);
4660 hostname[hostname_size - 1] = '\0';
4662 /* Was the buffer large enough for gethostname to store the '\0'? */
4663 if (strlen (hostname) < hostname_size - 1)
4664 break;
4666 hostname_size <<= 1;
4667 hostname = (char *) xrealloc (hostname, hostname_size);
4669 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4670 + strlen (hostname)
4671 + 2);
4672 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
4675 /* Figure out which modifier bits mean what. */
4676 x_find_modifier_meanings ();
4678 /* Get the scroll bar cursor. */
4679 x_vertical_scroll_bar_cursor
4680 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
4682 #if 0
4683 /* Watch for PropertyNotify events on the root window; we use them
4684 to figure out when to invalidate our cache of the cut buffers. */
4685 x_watch_cut_buffer_cache ();
4686 #endif
4688 if (ConnectionNumber (x_current_display) != 0)
4690 dup2 (ConnectionNumber (x_current_display), 0);
4692 #ifndef SYSV_STREAMS
4693 /* Streams somehow keeps track of which descriptor number
4694 is being used to talk to X. So it is not safe to substitute
4695 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4696 close (ConnectionNumber (x_current_display));
4697 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
4698 * check the def of the macro;
4699 * it is a genuine lvalue */
4700 #endif /* SYSV_STREAMS */
4703 #endif /* ! defined (HAVE_X11) */
4705 #ifdef F_SETOWN
4706 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
4707 #ifdef F_SETOWN_SOCK_NEG
4708 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
4709 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4710 fcntl (0, F_SETOWN, getpid ());
4711 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4712 #endif /* ! defined (F_SETOWN) */
4714 #ifdef SIGIO
4715 init_sigio ();
4716 #endif /* ! defined (SIGIO) */
4718 /* Must use interrupt input because we cannot otherwise
4719 arrange for C-g to be noticed immediately.
4720 We cannot connect it to SIGINT. */
4721 Fset_input_mode (Qt, Qnil, Qt, Qnil);
4723 expose_all_windows = 0;
4725 clear_frame_hook = XTclear_frame;
4726 clear_end_of_line_hook = XTclear_end_of_line;
4727 ins_del_lines_hook = XTins_del_lines;
4728 change_line_highlight_hook = XTchange_line_highlight;
4729 insert_glyphs_hook = XTinsert_glyphs;
4730 write_glyphs_hook = XTwrite_glyphs;
4731 delete_glyphs_hook = XTdelete_glyphs;
4732 ring_bell_hook = XTring_bell;
4733 reset_terminal_modes_hook = XTreset_terminal_modes;
4734 set_terminal_modes_hook = XTset_terminal_modes;
4735 update_begin_hook = XTupdate_begin;
4736 update_end_hook = XTupdate_end;
4737 set_terminal_window_hook = XTset_terminal_window;
4738 read_socket_hook = XTread_socket;
4739 cursor_to_hook = XTcursor_to;
4740 reassert_line_highlight_hook = XTreassert_line_highlight;
4741 mouse_position_hook = XTmouse_position;
4742 frame_rehighlight_hook = XTframe_rehighlight;
4743 frame_raise_lower_hook = XTframe_raise_lower;
4744 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
4745 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
4746 redeem_scroll_bar_hook = XTredeem_scroll_bar;
4747 judge_scroll_bars_hook = XTjudge_scroll_bars;
4749 scroll_region_ok = 1; /* we'll scroll partial frames */
4750 char_ins_del_ok = 0; /* just as fast to write the line */
4751 line_ins_del_ok = 1; /* we'll just blt 'em */
4752 fast_clear_end_of_line = 1; /* X does this well */
4753 memory_below_frame = 0; /* we don't remember what scrolls
4754 off the bottom */
4755 baud_rate = 19200;
4757 /* Note that there is no real way portable across R3/R4 to get the
4758 original error handler. */
4759 XHandleError (x_error_quitter);
4760 XHandleIOError (x_io_error_quitter);
4762 /* Disable Window Change signals; they are handled by X events. */
4763 #ifdef SIGWINCH
4764 signal (SIGWINCH, SIG_DFL);
4765 #endif /* ! defined (SIGWINCH) */
4767 signal (SIGPIPE, x_connection_closed);
4770 void
4771 syms_of_xterm ()
4773 staticpro (&last_mouse_scroll_bar);
4775 #endif /* ! defined (HAVE_X11) */
4776 #endif /* ! defined (HAVE_X_WINDOWS) */