1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 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)
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. */
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 /* Xt features made by Fred Pierresteguy. */
30 #define NEW_SELECTIONS
32 /* On 4.3 these lose if they come after xterm.h. */
33 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
34 /* Putting these at the beginning seems to be standard for other .c files. */
40 /* Need syssignal.h for various externs and definitions that may be required
41 by some configurations for calls to signal later in this source file. */
42 #include "syssignal.h"
47 #include "blockinput.h"
49 /* This may include sys/types.h, and that somehow loses
50 if this is not done before the other system files. */
52 #include <X11/cursorfont.h>
55 /* Load sys/types.h if not already loaded.
56 In some systems loading it twice is suicidal. */
58 #include <sys/types.h>
63 #include <sys/ioctl.h>
65 #else /* ! defined (BSD) */
69 #endif /* ! defined (BSD) */
74 #ifndef INCLUDED_FCNTL
81 #include <sys/param.h>
83 #include "dispextern.h"
84 #include "termhooks.h"
98 extern XtAppContext Xt_app_con
;
99 extern Widget Xt_app_shell
;
100 extern void free_frame_menubar ();
101 #endif /* USE_X_TOOLKIT */
103 #ifndef USE_X_TOOLKIT
104 #define x_any_window_to_frame x_window_to_frame
108 #define XMapWindow XMapRaised /* Raise them when mapping. */
109 #else /* ! defined (HAVE_X11) */
110 #include <X/Xkeyboard.h>
111 /*#include <X/Xproto.h> */
112 #endif /* ! defined (HAVE_X11) */
115 /* We could get this from param.h, but better not to depend on finding that.
116 And better not to risk that it might define other symbols used in this
119 #define MAXDESC FD_SETSIZE
123 #define SELECT_TYPE fd_set
124 #else /* no FD_SET */
126 #define SELECT_TYPE int
128 /* Define the macros to access a single-int bitmap of descriptors. */
129 #define FD_SET(n, p) (*(p) |= (1 << (n)))
130 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
131 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
132 #define FD_ZERO(p) (*(p) = 0)
133 #endif /* no FD_SET */
135 /* For sending Meta-characters. Do we need this? */
138 #define min(a,b) ((a)<(b) ? (a) : (b))
139 #define max(a,b) ((a)>(b) ? (a) : (b))
141 /* Nonzero means we must reprint all windows
142 because 1) we received an ExposeWindow event
143 or 2) we received too many ExposeRegion events to record.
145 This is never needed under X11. */
146 static int expose_all_windows
;
148 /* Nonzero means we must reprint all icon windows. */
150 static int expose_all_icons
;
153 /* ExposeRegion events, when received, are copied into this queue
154 for later processing. */
156 static struct event_queue x_expose_queue
;
158 /* ButtonPress and ButtonReleased events, when received,
159 are copied into this queue for later processing. */
161 struct event_queue x_mouse_queue
;
162 #endif /* HAVE_X11 */
164 #if defined (SIGIO) && defined (FIONREAD)
165 int BLOCK_INPUT_mask
;
166 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
168 /* The id of a bitmap used for icon windows.
169 One such map is shared by all Emacs icon windows.
170 This is zero if we have not yet had a need to create the bitmap. */
172 static Bitmap icon_bitmap
;
174 /* Font used for text icons. */
176 static FONT_TYPE
*icon_font_info
;
178 /* Stuff for dealing with the main icon title. */
180 extern Lisp_Object Vcommand_line_args
;
181 char *hostname
, *x_id_name
;
183 /* This is the X connection that we are using. */
185 Display
*x_current_display
;
187 /* The cursor to use for vertical scroll bars on x_current_display. */
188 static Cursor x_vertical_scroll_bar_cursor
;
190 /* Frame being updated by update_frame. This is declared in term.c.
191 This is set by update_begin and looked at by all the
192 XT functions. It is zero while not inside an update.
193 In that case, the XT functions assume that `selected_frame'
194 is the frame to apply to. */
195 extern struct frame
*updating_frame
;
197 /* The frame (if any) which has the X window that has keyboard focus.
198 Zero if none. This is examined by Ffocus_frame in frame.c. Note
199 that a mere EnterNotify event can set this; if you need to know the
200 last frame specified in a FocusIn or FocusOut event, use
201 x_focus_event_frame. */
202 struct frame
*x_focus_frame
;
204 /* The last frame mentioned in a FocusIn or FocusOut event. This is
205 separate from x_focus_frame, because whether or not LeaveNotify
206 events cause us to lose focus depends on whether or not we have
207 received a FocusIn event for it. */
208 struct frame
*x_focus_event_frame
;
210 /* The frame which currently has the visual highlight, and should get
211 keyboard input (other sorts of input have the frame encoded in the
212 event). It points to the X focus frame's selected window's
213 frame. It differs from x_focus_frame when we're using a global
215 static struct frame
*x_highlight_frame
;
217 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
218 mouse is moved to inside of frame when frame is de-iconified. */
220 static int warp_mouse_on_deiconify
;
222 /* During an update, maximum vpos for ins/del line operations to affect. */
224 static int flexlines
;
226 /* During an update, nonzero if chars output now should be highlighted. */
228 static int highlight
;
230 /* Nominal cursor position -- where to draw output.
231 During an update, these are different from the cursor-box position. */
238 In order to avoid asking for motion events and then throwing most
239 of them away or busy-polling the server for mouse positions, we ask
240 the server for pointer motion hints. This means that we get only
241 one event per group of mouse movements. "Groups" are delimited by
242 other kinds of events (focus changes and button clicks, for
243 example), or by XQueryPointer calls; when one of these happens, we
244 get another MotionNotify event the next time the mouse moves. This
245 is at least as efficient as getting motion events when mouse
246 tracking is on, and I suspect only negligibly worse when tracking
249 The silly O'Reilly & Associates Nutshell guides barely document
250 pointer motion hints at all (I think you have to infer how they
251 work from an example), and the description of XQueryPointer doesn't
252 mention that calling it causes you to get another motion hint from
253 the server, which is very important. */
255 /* Where the mouse was last time we reported a mouse event. */
256 static FRAME_PTR last_mouse_frame
;
257 static XRectangle last_mouse_glyph
;
259 /* The scroll bar in which the last X motion event occurred.
261 If the last X motion event occurred in a scroll bar, we set this
262 so XTmouse_position can know whether to report a scroll bar motion or
265 If the last X motion event didn't occur in a scroll bar, we set this
266 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
267 static Lisp_Object last_mouse_scroll_bar
;
269 /* Record which buttons are currently pressed. */
270 unsigned int x_mouse_grabbed
;
272 /* This is a hack. We would really prefer that XTmouse_position would
273 return the time associated with the position it returns, but there
274 doesn't seem to be any way to wrest the timestamp from the server
275 along with the position query. So, we just keep track of the time
276 of the last movement we received, and return that in hopes that
277 it's somewhat accurate. */
278 static Time last_mouse_movement_time
;
280 /* These variables describe the range of text currently shown
281 in its mouse-face, together with the window they apply to.
282 As long as the mouse stays within this range, we need not
283 redraw anything on its account. */
284 static int mouse_face_beg
, mouse_face_end
;
285 static Lisp_Object mouse_face_window
;
286 static int mouse_face_face_id
;
288 /* FRAME and X, Y position of mouse when last checked for highlighting. */
289 static FRAME_PTR mouse_face_mouse_frame
;
290 static int mouse_face_mouse_x
, mouse_face_mouse_y
;
292 /* Nonzero means defer mouse-motion highlighting. */
293 static int mouse_face_defer
;
296 /* `t' if a mouse button is depressed. */
298 extern Lisp_Object Vmouse_depressed
;
300 /* Tells if a window manager is present or not. */
302 extern Lisp_Object Vx_no_window_manager
;
304 /* Timestamp that we requested selection data was made. */
305 extern Time requestor_time
;
307 /* ID of the window requesting selection data. */
308 extern Window requestor_window
;
310 /* Nonzero enables some debugging for the X interface code. */
313 extern Qface
, Qmouse_face
;
315 #else /* ! defined (HAVE_X11) */
317 /* Bit patterns for the mouse cursor. */
319 short MouseCursor
[] = {
320 0x0000, 0x0008, 0x0018, 0x0038,
321 0x0078, 0x00f8, 0x01f8, 0x03f8,
322 0x07f8, 0x00f8, 0x00d8, 0x0188,
323 0x0180, 0x0300, 0x0300, 0x0000};
325 short MouseMask
[] = {
326 0x000c, 0x001c, 0x003c, 0x007c,
327 0x00fc, 0x01fc, 0x03fc, 0x07fc,
328 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
329 0x03cc, 0x0780, 0x0780, 0x0300};
331 static short grey_bits
[] = {
332 0x0005, 0x000a, 0x0005, 0x000a};
334 static Pixmap GreyPixmap
= 0;
335 #endif /* ! defined (HAVE_X11) */
337 /* From time to time we get info on an Emacs window, here. */
339 static WINDOWINFO_TYPE windowinfo
;
343 /* A mask of extra modifier bits to put into every keyboard char. */
344 extern int extra_keyboard_modifiers
;
346 extern Display
*XOpenDisplay ();
347 extern Window
XCreateWindow ();
349 extern Cursor
XCreateCursor ();
350 extern FONT_TYPE
*XOpenFont ();
352 static void flashback ();
353 static void redraw_previous_char ();
354 static unsigned int x_x_to_emacs_modifiers ();
356 static void note_mouse_highlight ();
357 static void clear_mouse_face ();
358 static void show_mouse_face ();
361 static void dumpqueue ();
362 #endif /* HAVE_X11 */
365 static int XTcursor_to ();
366 static int XTclear_end_of_line ();
369 /* Starting and ending updates.
371 These hooks are called by update_frame at the beginning and end
372 of a frame update. We record in `updating_frame' the identity
373 of the frame being updated, so that the XT... functions do not
374 need to take a frame as argument. Most of the XT... functions
375 should never be called except during an update, the only exceptions
376 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
378 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
389 flexlines
= f
->height
;
394 if (f
== mouse_face_mouse_frame
)
396 mouse_face_defer
= 1;
397 if (!NILP (mouse_face_window
))
402 #endif /* HAVE_X11 */
407 static void x_do_pending_expose ();
419 x_do_pending_expose ();
420 #endif /* HAVE_X11 */
422 x_display_cursor (f
, 1);
424 if (f
== mouse_face_mouse_frame
)
425 mouse_face_defer
= 0;
427 /* This fails in the case of having updated only the echo area
428 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
429 has no relation to the current contents, and its charstarts
430 have no relation to the contents of the window-buffer.
431 I don't know a clean way to check
432 for that case. window_end_valid isn't set up yet. */
433 if (f
== mouse_face_mouse_frame
)
434 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
441 /* This is called when all windows on frame F are now up to date. */
444 XTframe_up_to_date (f
)
447 if (f
== mouse_face_mouse_frame
)
448 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
451 /* External interface to control of standout mode.
452 Call this when about to modify line at position VPOS
453 and not change whether it is highlighted. */
455 XTreassert_line_highlight (new, vpos
)
461 /* Call this when about to modify line at position VPOS
462 and change whether it is highlighted. */
465 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
466 int new_highlight
, vpos
, first_unused_hpos
;
468 highlight
= new_highlight
;
469 XTcursor_to (vpos
, 0);
470 XTclear_end_of_line (updating_frame
->width
);
473 /* This is used when starting Emacs and when restarting after suspend.
474 When starting Emacs, no X window is mapped. And nothing must be done
475 to Emacs's own window if it is suspended (though that rarely happens). */
478 XTset_terminal_modes ()
482 /* This is called when exiting or suspending Emacs.
483 Exiting will make the X-windows go away, and suspending
484 requires no action. */
487 XTreset_terminal_modes ()
489 /* XTclear_frame (); */
492 /* Set the nominal cursor position of the frame.
493 This is where display update commands will take effect.
494 This does not affect the place where the cursor-box is displayed. */
497 XTcursor_to (row
, col
)
498 register int row
, col
;
506 if (updating_frame
== 0)
509 x_display_cursor (selected_frame
, 1);
515 /* Display a sequence of N glyphs found at GP.
516 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
517 HL is 1 if this text is highlighted, 2 if the cursor is on it,
518 3 if should appear in its mouse-face.
520 FONT is the default font to use (for glyphs whose font-code is 0).
522 Since the display generation code is responsible for calling
523 compute_char_face and compute_glyph_face on everything it puts in
524 the display structure, we can assume that the face code on each
525 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
526 to which we can actually apply intern_face.
527 Call this function with input blocked. */
530 /* This is the multi-face code. */
533 dumpglyphs (f
, left
, top
, gp
, n
, hl
)
536 register GLYPH
*gp
; /* Points to first GLYPH. */
537 register int n
; /* Number of glyphs to display. */
540 /* Holds characters to be displayed. */
541 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
542 register char *cp
; /* Steps through buf[]. */
543 register int tlen
= GLYPH_TABLE_LENGTH
;
544 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
545 Window window
= FRAME_X_WINDOW (f
);
549 /* Get the face-code of the next GLYPH. */
553 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
554 cf
= FAST_GLYPH_FACE (g
);
556 /* Find the run of consecutive glyphs with the same face-code.
557 Extract their character codes into BUF. */
562 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
563 if (FAST_GLYPH_FACE (g
) != cf
)
566 *cp
++ = FAST_GLYPH_CHAR (g
);
571 /* LEN gets the length of the run. */
574 /* Now output this run of chars, with the font and pixel values
575 determined by the face code CF. */
577 struct face
*face
= FRAME_DEFAULT_FACE (f
);
578 FONT_TYPE
*font
= FACE_FONT (face
);
579 GC gc
= FACE_GC (face
);
581 int gc_temporary
= 0;
583 /* HL = 3 means use a mouse face previously chosen. */
585 cf
= mouse_face_face_id
;
587 /* First look at the face of the text itself. */
590 /* It's possible for the display table to specify
591 a face code that is out of range. Use 0 in that case. */
592 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
593 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
597 face
= FRAME_MODE_LINE_FACE (f
);
599 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
600 font
= FACE_FONT (face
);
605 /* Then comes the distinction between modeline and normal text. */
610 face
= FRAME_MODE_LINE_FACE (f
);
611 font
= FACE_FONT (face
);
616 #define FACE_DEFAULT (~0)
618 /* Now override that if the cursor's on this character. */
623 || (int) face
->font
== FACE_DEFAULT
)
625 gc
= f
->display
.x
->cursor_gc
;
627 /* Cursor on non-default face: must merge. */
633 xgcv
.background
= f
->display
.x
->cursor_pixel
;
634 if (face
== FRAME_DEFAULT_FACE (f
))
635 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
637 xgcv
.foreground
= face
->foreground
;
638 /* If the glyph would be invisible,
639 try a different foreground. */
640 if (xgcv
.foreground
== xgcv
.background
)
641 xgcv
.foreground
= face
->background
;
642 if (xgcv
.foreground
== xgcv
.background
)
643 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
644 if (xgcv
.foreground
== xgcv
.background
)
645 xgcv
.foreground
= face
->foreground
;
646 /* Make sure the cursor is distinct from text in this face. */
647 if (xgcv
.background
== face
->background
648 && xgcv
.foreground
== face
->foreground
)
650 xgcv
.background
= face
->foreground
;
651 xgcv
.foreground
= face
->background
;
653 xgcv
.font
= face
->font
->fid
;
654 xgcv
.graphics_exposures
= 0;
655 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
656 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
659 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
660 XSetStipple (x_current_display
, gc
, face
->stipple
);
666 if ((int) font
== FACE_DEFAULT
)
667 font
= f
->display
.x
->font
;
669 XDrawImageString (x_current_display
, window
, gc
,
670 left
, top
+ FONT_BASE (font
), buf
, len
);
673 XFreeGC (x_current_display
, gc
);
675 /* We should probably check for XA_UNDERLINE_POSITION and
676 XA_UNDERLINE_THICKNESS properties on the font, but let's
677 just get the thing working, and come back to that. */
679 int underline_position
= 1;
681 if (font
->descent
<= underline_position
)
682 underline_position
= font
->descent
- 1;
685 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
689 + underline_position
),
690 len
* FONT_WIDTH (font
), 1);
693 left
+= len
* FONT_WIDTH (font
);
700 /* This is the old single-face code. */
703 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
706 register GLYPH
*gp
; /* Points to first GLYPH. */
707 register int n
; /* Number of glyphs to display. */
712 Window window
= FRAME_X_WINDOW (f
);
713 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
714 : (hl
? f
->display
.x
->reverse_gc
715 : f
->display
.x
->normal_gc
));
717 if (sizeof (GLYPH
) == sizeof (XChar2b
))
718 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
719 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
720 else if (sizeof (GLYPH
) == sizeof (unsigned char))
721 XDrawImageString (x_current_display
, window
, drawing_gc
,
722 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
724 /* What size of glyph ARE you using? And does X have a function to
730 /* Output some text at the nominal frame cursor position.
731 Advance the cursor over the text.
732 Output LEN glyphs at START.
734 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
735 controls the pixel values used for foreground and background. */
738 XTwrite_glyphs (start
, len
)
739 register GLYPH
*start
;
742 register int temp_length
;
752 /* If not within an update,
753 output at the frame's visible cursor. */
754 curs_x
= f
->cursor_x
;
755 curs_y
= f
->cursor_y
;
759 CHAR_TO_PIXEL_COL (f
, curs_x
),
760 CHAR_TO_PIXEL_ROW (f
, curs_y
),
761 start
, len
, highlight
);
763 /* If we drew on top of the cursor, note that it is turned off. */
764 if (curs_y
== f
->phys_cursor_y
765 && curs_x
<= f
->phys_cursor_x
766 && curs_x
+ len
> f
->phys_cursor_x
)
767 f
->phys_cursor_x
= -1;
769 if (updating_frame
== 0)
772 x_display_cursor (f
, 1);
781 /* Clear to the end of the line.
782 Erase the current text line from the nominal cursor position (inclusive)
783 to column FIRST_UNUSED (exclusive). The idea is that everything
784 from FIRST_UNUSED onward is already erased. */
787 XTclear_end_of_line (first_unused
)
788 register int first_unused
;
790 struct frame
*f
= updating_frame
;
796 if (curs_y
< 0 || curs_y
>= f
->height
)
798 if (first_unused
<= 0)
801 if (first_unused
>= f
->width
)
802 first_unused
= f
->width
;
806 /* Notice if the cursor will be cleared by this operation. */
807 if (curs_y
== f
->phys_cursor_y
808 && curs_x
<= f
->phys_cursor_x
809 && f
->phys_cursor_x
< first_unused
)
810 f
->phys_cursor_x
= -1;
813 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
814 CHAR_TO_PIXEL_COL (f
, curs_x
),
815 CHAR_TO_PIXEL_ROW (f
, curs_y
),
816 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
817 FONT_HEIGHT (f
->display
.x
->font
), False
);
819 redraw_previous_char (f
, curs_x
, curs_y
);
821 #else /* ! defined (HAVE_X11) */
822 XPixSet (FRAME_X_WINDOW (f
),
823 CHAR_TO_PIXEL_COL (f
, curs_x
),
824 CHAR_TO_PIXEL_ROW (f
, curs_y
),
825 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
826 FONT_HEIGHT (f
->display
.x
->font
),
827 f
->display
.x
->background_pixel
);
828 #endif /* ! defined (HAVE_X11) */
833 /* Erase the character (if any) at the position just before X, Y in frame F,
834 then redraw it and the character before it.
835 This is necessary when we erase starting at X,
836 in case the character after X overlaps into the one before X.
837 Call this function with input blocked. */
840 redraw_previous_char (f
, x
, y
)
844 /* Erase the character before the new ones, in case
845 what was here before overlaps it.
846 Reoutput that character, and the previous character
847 (in case the previous character overlaps it). */
853 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
854 CHAR_TO_PIXEL_COL (f
, x
- 1),
855 CHAR_TO_PIXEL_ROW (f
, y
),
856 FONT_WIDTH (f
->display
.x
->font
),
857 FONT_HEIGHT (f
->display
.x
->font
), False
);
859 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
860 CHAR_TO_PIXEL_ROW (f
, y
),
861 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
862 x
- start_x
, highlight
);
870 struct frame
*f
= updating_frame
;
875 f
->phys_cursor_x
= -1; /* Cursor not visible. */
876 curs_x
= 0; /* Nominal cursor position is top left. */
881 XClear (FRAME_X_WINDOW (f
));
883 /* We have to clear the scroll bars, too. If we have changed
884 colors or something like that, then they should be notified. */
885 x_scroll_bar_clear (f
);
889 #endif /* HAVE_X11 */
895 /* Invert the middle quarter of the frame for .15 sec. */
897 /* We use the select system call to do the waiting, so we have to make sure
898 it's available. If it isn't, we just won't do visual bells. */
899 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
901 /* Subtract the `struct timeval' values X and Y,
902 storing the result in RESULT.
903 Return 1 if the difference is negative, otherwise 0. */
906 timeval_subtract (result
, x
, y
)
907 struct timeval
*result
, x
, y
;
909 /* Perform the carry for the later subtraction by updating y.
910 This is safer because on some systems
911 the tv_sec member is unsigned. */
912 if (x
.tv_usec
< y
.tv_usec
)
914 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
915 y
.tv_usec
-= 1000000 * nsec
;
918 if (x
.tv_usec
- y
.tv_usec
> 1000000)
920 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
921 y
.tv_usec
+= 1000000 * nsec
;
925 /* Compute the time remaining to wait. tv_usec is certainly positive. */
926 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
927 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
929 /* Return indication of whether the result should be considered negative. */
930 return x
.tv_sec
< y
.tv_sec
;
941 /* Create a GC that will use the GXxor function to flip foreground pixels
942 into background pixels. */
946 values
.function
= GXxor
;
947 values
.foreground
= (f
->display
.x
->foreground_pixel
948 ^ f
->display
.x
->background_pixel
);
950 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
951 GCFunction
| GCForeground
, &values
);
955 int width
= PIXEL_WIDTH (f
);
956 int height
= PIXEL_HEIGHT (f
);
958 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
959 width
/4, height
/4, width
/2, height
/2);
960 XFlush (x_current_display
);
963 struct timeval wakeup
, now
;
965 EMACS_GET_TIME (wakeup
);
967 /* Compute time to wait until, propagating carry from usecs. */
968 wakeup
.tv_usec
+= 150000;
969 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
970 wakeup
.tv_usec
%= 1000000;
972 /* Keep waiting until past the time wakeup. */
975 struct timeval timeout
;
977 EMACS_GET_TIME (timeout
);
979 /* In effect, timeout = wakeup - timeout.
980 Break if result would be negative. */
981 if (timeval_subtract (&timeout
, wakeup
, timeout
))
984 /* Try to wait that long--but we might wake up sooner. */
985 select (0, 0, 0, 0, &timeout
);
989 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
990 width
/4, height
/4, width
/2, height
/2);
991 XFreeGC (x_current_display
, gc
);
992 XFlush (x_current_display
);
1002 /* Make audible bell. */
1005 #define XRINGBELL XBell (x_current_display, 0)
1006 #else /* ! defined (HAVE_X11) */
1007 #define XRINGBELL XFeep (0);
1008 #endif /* ! defined (HAVE_X11) */
1012 if (x_current_display
== 0)
1015 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1017 XTflash (selected_frame
);
1028 /* Insert and delete character.
1029 These are not supposed to be used because we are supposed to turn
1030 off the feature of using them. */
1033 XTinsert_glyphs (start
, len
)
1034 register char *start
;
1047 /* Specify how many text lines, from the top of the window,
1048 should be affected by insert-lines and delete-lines operations.
1049 This, and those operations, are used only within an update
1050 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1053 XTset_terminal_window (n
)
1056 if (updating_frame
== 0)
1059 if ((n
<= 0) || (n
> updating_frame
->height
))
1060 flexlines
= updating_frame
->height
;
1065 /* Perform an insert-lines operation.
1066 Insert N lines at a vertical position curs_y. */
1072 register int topregion
, bottomregion
;
1073 register int length
, newtop
, mask
;
1074 register struct frame
*f
= updating_frame
;
1075 int intborder
= f
->display
.x
->internal_border_width
;
1077 if (curs_y
>= flexlines
)
1081 bottomregion
= flexlines
- (n
+ 1);
1082 newtop
= topregion
+ n
;
1083 length
= (bottomregion
- topregion
) + 1;
1087 #endif /* HAVE_X11 */
1089 if ((length
> 0) && (newtop
<= flexlines
))
1092 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1093 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1094 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1095 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1096 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
1097 CHAR_TO_PIXEL_ROW (f
, newtop
));
1098 #else /* ! defined (HAVE_X11) */
1099 XMoveArea (FRAME_X_WINDOW (f
),
1100 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1101 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1102 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1103 length
* FONT_HEIGHT (f
->display
.x
->font
));
1104 /* Now we must process any ExposeRegion events that occur
1105 if the area being copied from is obscured.
1106 We can't let it wait because further i/d operations
1107 may want to copy this area to another area. */
1109 #endif /* ! defined (HAVE_X11) */
1112 newtop
= min (newtop
, (flexlines
- 1));
1113 length
= newtop
- topregion
;
1117 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1118 CHAR_TO_PIXEL_ROW (f
, topregion
),
1119 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1120 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
1121 #else /* ! defined (HAVE_X11) */
1122 XPixSet (FRAME_X_WINDOW (f
),
1124 CHAR_TO_PIXEL_ROW (f
, topregion
),
1125 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1126 n
* FONT_HEIGHT (f
->display
.x
->font
),
1127 f
->display
.x
->background_pixel
);
1128 #endif /* ! defined (HAVE_X11) */
1132 /* Perform a delete-lines operation, deleting N lines
1133 at a vertical position curs_y. */
1140 register struct frame
*f
= updating_frame
;
1141 int intborder
= f
->display
.x
->internal_border_width
;
1143 if (curs_y
>= flexlines
)
1148 #endif /* HAVE_X11 */
1150 if ((curs_y
+ n
) >= flexlines
)
1152 if (flexlines
>= (curs_y
+ 1))
1155 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1156 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1157 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1158 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
1159 #else /* ! defined (HAVE_X11) */
1160 XPixSet (FRAME_X_WINDOW (f
),
1161 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1162 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1163 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
1164 f
->display
.x
->background_pixel
);
1165 #endif /* ! defined (HAVE_X11) */
1171 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1172 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1174 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1175 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1176 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
1177 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1178 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1180 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1181 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1182 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
1183 #else /* ! defined (HAVE_X11) */
1184 XMoveArea (FRAME_X_WINDOW (f
),
1186 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1187 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1188 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1189 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
1190 /* Now we must process any ExposeRegion events that occur
1191 if the area being copied from is obscured.
1192 We can't let it wait because further i/d operations
1193 may want to copy this area to another area. */
1195 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1196 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1197 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1198 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
1199 #endif /* ! defined (HAVE_X11) */
1203 /* Perform an insert-lines or delete-lines operation,
1204 inserting N lines or deleting -N lines at vertical position VPOS. */
1206 XTins_del_lines (vpos
, n
)
1209 if (updating_frame
== 0)
1212 /* Hide the cursor. */
1213 x_display_cursor (updating_frame
, 0);
1215 XTcursor_to (vpos
, 0);
1226 /* Support routines for exposure events. */
1227 static void clear_cursor ();
1229 /* Output into a rectangle of an X-window (for frame F)
1230 the characters in f->phys_lines that overlap that rectangle.
1231 TOP and LEFT are the position of the upper left corner of the rectangle.
1232 ROWS and COLS are the size of the rectangle.
1233 Call this function with input blocked. */
1236 dumprectangle (f
, left
, top
, cols
, rows
)
1238 register int left
, top
, cols
, rows
;
1240 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1241 int cursor_cleared
= 0;
1245 if (FRAME_GARBAGED_P (f
))
1248 /* Express rectangle as four edges, instead of position-and-size. */
1249 bottom
= top
+ rows
;
1250 right
= left
+ cols
;
1252 #ifndef HAVE_X11 /* Window manger does this for X11. */
1254 int intborder
= f
->display
.x
->internal_border_width
;
1256 /* If the rectangle includes any of the internal border area,
1257 redisplay the border emphasis. */
1258 if (top
< intborder
|| left
< intborder
1259 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1260 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1263 #endif /* not HAVE_X11 Window manger does this for X11. */
1265 /* Convert rectangle edges in pixels to edges in chars.
1266 Round down for left and top, up for right and bottom. */
1267 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1268 left
= PIXEL_TO_CHAR_COL (f
, left
);
1269 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1270 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1271 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1272 right
= PIXEL_TO_CHAR_COL (f
, right
);
1274 /* Clip the rectangle to what can be visible. */
1279 if (right
> f
->width
)
1281 if (bottom
> f
->height
)
1284 /* Get size in chars of the rectangle. */
1285 cols
= right
- left
;
1286 rows
= bottom
- top
;
1288 /* If rectangle has zero area, return. */
1289 if (rows
<= 0) return;
1290 if (cols
<= 0) return;
1292 /* Turn off the cursor if it is in the rectangle.
1293 We will turn it back on afterward. */
1294 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1295 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1301 /* Display the text in the rectangle, one text line at a time. */
1303 for (y
= top
; y
< bottom
; y
++)
1305 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1307 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1311 CHAR_TO_PIXEL_COL (f
, left
),
1312 CHAR_TO_PIXEL_ROW (f
, y
),
1313 line
, min (cols
, active_frame
->used
[y
] - left
),
1314 active_frame
->highlight
[y
]);
1317 /* Turn the cursor on if we turned it off. */
1320 x_display_cursor (f
, 1);
1324 /* Process all queued ExposeRegion events. */
1330 XExposeRegionEvent r
;
1332 while (dequeue_event (&r
, &x_expose_queue
))
1334 struct frame
*f
= x_window_to_frame (r
.window
);
1335 if (f
->display
.x
->icon_desc
== r
.window
)
1338 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1342 #endif /* HAVE_X11 */
1344 /* Process all expose events that are pending, for X10.
1345 Redraws the cursor if necessary on any frame that
1346 is not in the process of being updated with update_frame. */
1350 x_do_pending_expose ()
1354 Lisp_Object tail
, frame
;
1356 if (expose_all_windows
)
1358 expose_all_windows
= 0;
1359 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1361 register int temp_width
, temp_height
;
1364 frame
= XCONS (tail
)->car
;
1365 if (XGCTYPE (frame
) != Lisp_Frame
)
1368 if (! FRAME_X_P (f
))
1370 if (!f
->async_visible
)
1372 if (!f
->display
.x
->needs_exposure
)
1375 intborder
= f
->display
.x
->internal_border_width
;
1378 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1379 temp_width
= ((windowinfo
.width
- 2 * intborder
1380 - f
->display
.x
->v_scroll_bar_width
)
1381 / FONT_WIDTH (f
->display
.x
->font
));
1382 temp_height
= ((windowinfo
.height
- 2 * intborder
1383 - f
->display
.x
->h_scroll_bar_height
)
1384 / FONT_HEIGHT (f
->display
.x
->font
));
1385 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1387 change_frame_size (f
, max (1, temp_height
),
1388 max (1, temp_width
), 0, 1);
1389 x_resize_scroll_bars (f
);
1391 f
->display
.x
->left_pos
= windowinfo
.x
;
1392 f
->display
.x
->top_pos
= windowinfo
.y
;
1393 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1397 f
->display
.x
->needs_exposure
= 0;
1398 if (updating_frame
!= f
)
1399 x_display_cursor (f
, 1);
1404 /* Handle any individual-rectangle expose events queued
1405 for various windows. */
1408 #else /* ! defined (HAVE_X11) */
1410 #endif /* ! defined (HAVE_X11) */
1416 frame_highlight (frame
)
1417 struct frame
*frame
;
1419 /* We used to only do this if Vx_no_window_manager was non-nil, but
1420 the ICCCM (section 4.1.6) says that the window's border pixmap
1421 and border pixel are window attributes which are "private to the
1422 client", so we can always change it to whatever we want. */
1424 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1425 frame
->display
.x
->border_pixel
);
1427 x_display_cursor (frame
, 1);
1431 frame_unhighlight (frame
)
1432 struct frame
*frame
;
1434 /* We used to only do this if Vx_no_window_manager was non-nil, but
1435 the ICCCM (section 4.1.6) says that the window's border pixmap
1436 and border pixel are window attributes which are "private to the
1437 client", so we can always change it to whatever we want. */
1439 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1440 frame
->display
.x
->border_tile
);
1442 x_display_cursor (frame
, 1);
1444 #else /* ! defined (HAVE_X11) */
1445 /* Dump the border-emphasis of frame F.
1446 If F is selected, this is a lining of the same color as the border,
1447 just within the border, occupying a portion of the internal border.
1448 If F is not selected, it is background in the same place.
1449 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1451 ALWAYS = 1 is used when a frame becomes selected or deselected.
1452 In that case, we also turn the cursor off and on again
1453 so it will appear in the proper shape (solid if selected; else hollow.) */
1456 dumpborder (f
, always
)
1460 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1461 int width
= PIXEL_WIDTH (f
);
1462 int height
= PIXEL_HEIGHT (f
);
1465 if (f
!= selected_frame
)
1470 pixel
= f
->display
.x
->background_pixel
;
1474 pixel
= f
->display
.x
->border_pixel
;
1477 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1478 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1479 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1481 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1485 x_display_cursor (f
, 1);
1487 #endif /* ! defined (HAVE_X11) */
1489 static void XTframe_rehighlight ();
1491 /* The focus has changed. Update the frames as necessary to reflect
1492 the new situation. Note that we can't change the selected frame
1493 here, because the lisp code we are interrupting might become confused.
1494 Each event gets marked with the frame in which it occurred, so the
1495 lisp code can tell when the switch took place by examining the events. */
1498 x_new_focus_frame (frame
)
1499 struct frame
*frame
;
1501 struct frame
*old_focus
= x_focus_frame
;
1502 int events_enqueued
= 0;
1504 if (frame
!= x_focus_frame
)
1506 /* Set this before calling other routines, so that they see
1507 the correct value of x_focus_frame. */
1508 x_focus_frame
= frame
;
1510 if (old_focus
&& old_focus
->auto_lower
)
1511 x_lower_frame (old_focus
);
1514 selected_frame
= frame
;
1515 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1516 Lisp_Frame
, selected_frame
);
1517 Fselect_window (selected_frame
->selected_window
);
1518 choose_minibuf_frame ();
1521 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1522 x_raise_frame (x_focus_frame
);
1525 XTframe_rehighlight ();
1529 /* The focus has changed, or we have redirected a frame's focus to
1530 another frame (this happens when a frame uses a surrogate
1531 minibuffer frame). Shift the highlight as appropriate. */
1533 XTframe_rehighlight ()
1535 struct frame
*old_highlight
= x_highlight_frame
;
1540 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1541 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1543 if (! FRAME_LIVE_P (x_highlight_frame
))
1545 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1546 x_highlight_frame
= x_focus_frame
;
1550 x_highlight_frame
= 0;
1552 if (x_highlight_frame
!= old_highlight
)
1555 frame_unhighlight (old_highlight
);
1556 if (x_highlight_frame
)
1557 frame_highlight (x_highlight_frame
);
1561 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1563 /* Which modifier keys are on which modifier bits?
1565 With each keystroke, X returns eight bits indicating which modifier
1566 keys were held down when the key was pressed. The interpretation
1567 of the top five modifier bits depends on what keys are attached
1568 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1571 x_meta_mod_mask is a mask containing the bits used for the meta key.
1572 It may have more than one bit set, if more than one modifier bit
1573 has meta keys on it. Basically, if EVENT is a KeyPress event,
1574 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1576 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1577 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1578 only be affected by the lock modifier bit if XK_Shift_Lock is in
1579 use; XK_Caps_Lock should only affect alphabetic keys. With this
1580 arrangement, the lock modifier should shift the character if
1581 (EVENT.state & x_shift_lock_mask) != 0. */
1582 static int x_meta_mod_mask
, x_shift_lock_mask
;
1584 /* These are like x_meta_mod_mask, but for different modifiers. */
1585 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1587 /* Initialize mode_switch_bit and modifier_meaning. */
1589 x_find_modifier_meanings ()
1591 int min_code
, max_code
;
1594 XModifierKeymap
*mods
;
1596 x_meta_mod_mask
= 0;
1597 x_shift_lock_mask
= 0;
1599 x_super_mod_mask
= 0;
1600 x_hyper_mod_mask
= 0;
1603 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1605 min_code
= x_current_display
->min_keycode
;
1606 max_code
= x_current_display
->max_keycode
;
1609 syms
= XGetKeyboardMapping (x_current_display
,
1610 min_code
, max_code
- min_code
+ 1,
1612 mods
= XGetModifierMapping (x_current_display
);
1614 /* Scan the modifier table to see which modifier bits the Meta and
1615 Alt keysyms are on. */
1617 int row
, col
; /* The row and column in the modifier table. */
1619 for (row
= 3; row
< 8; row
++)
1620 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1623 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1625 /* Zeroes are used for filler. Skip them. */
1629 /* Are any of this keycode's keysyms a meta key? */
1633 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1635 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1641 x_meta_mod_mask
|= (1 << row
);
1646 x_alt_mod_mask
|= (1 << row
);
1651 x_hyper_mod_mask
|= (1 << row
);
1656 x_super_mod_mask
|= (1 << row
);
1660 /* Ignore this if it's not on the lock modifier. */
1661 if ((1 << row
) == LockMask
)
1662 x_shift_lock_mask
= LockMask
;
1670 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1671 if (! x_meta_mod_mask
)
1673 x_meta_mod_mask
= x_alt_mod_mask
;
1677 /* If some keys are both alt and meta,
1678 make them just meta, not alt. */
1679 if (x_alt_mod_mask
& x_meta_mod_mask
)
1681 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1684 XFree ((char *) syms
);
1685 XFreeModifiermap (mods
);
1688 /* Convert between the modifier bits X uses and the modifier bits
1691 x_x_to_emacs_modifiers (state
)
1694 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1695 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1696 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1697 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1698 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1699 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1703 x_emacs_to_x_modifiers (state
)
1706 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1707 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1708 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1709 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1710 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1711 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1714 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1715 return as a function key. If you add a keysym to this, you should
1716 make sure that the tables make_lispy_event uses contain a suitable
1719 x_is_vendor_fkey (sym
)
1724 || (sym
== DXK_Remove
)
1730 /* Mouse clicks and mouse movement. Rah. */
1733 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1734 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1735 that the glyph at X, Y occupies, if BOUNDS != 0.
1736 If NOCLIP is nonzero, do not force the value into range. */
1739 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1741 register int pix_x
, pix_y
;
1742 register int *x
, *y
;
1746 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1747 even for negative values. */
1749 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1751 pix_y
-= FONT_HEIGHT ((f
)->display
.x
->font
) - 1;
1753 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1754 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1758 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1759 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1760 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1761 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1768 else if (pix_x
> f
->width
)
1773 else if (pix_y
> f
->height
)
1782 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1785 register int *pix_x
, *pix_y
;
1787 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1788 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1791 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1793 If the event is a button press, then note that we have grabbed
1797 construct_mouse_click (result
, event
, f
)
1798 struct input_event
*result
;
1799 XButtonEvent
*event
;
1802 /* Make the event type no_event; we'll change that when we decide
1804 result
->kind
= mouse_click
;
1805 result
->code
= event
->button
- Button1
;
1806 result
->timestamp
= event
->time
;
1807 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1808 | (event
->type
== ButtonRelease
1812 /* Notice if the mouse is still grabbed. */
1813 if (event
->type
== ButtonPress
)
1815 if (! x_mouse_grabbed
)
1816 Vmouse_depressed
= Qt
;
1817 x_mouse_grabbed
|= (1 << event
->button
);
1818 last_mouse_frame
= f
;
1820 else if (event
->type
== ButtonRelease
)
1822 x_mouse_grabbed
&= ~(1 << event
->button
);
1823 if (!x_mouse_grabbed
)
1824 Vmouse_depressed
= Qnil
;
1831 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1832 XFASTINT (result
->x
) = column
;
1833 XFASTINT (result
->y
) = row
;
1835 XSET (result
->x
, Lisp_Int
, event
->x
);
1836 XSET (result
->y
, Lisp_Int
, event
->y
);
1837 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1841 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1844 construct_menu_click (result
, event
, f
)
1845 struct input_event
*result
;
1846 XButtonEvent
*event
;
1849 /* Make the event type no_event; we'll change that when we decide
1851 result
->kind
= mouse_click
;
1852 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1853 result
->timestamp
= event
->time
;
1854 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1855 | (event
->type
== ButtonRelease
1859 XSET (result
->x
, Lisp_Int
, event
->x
);
1860 XSET (result
->y
, Lisp_Int
, -1);
1861 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1864 /* Function to report a mouse movement to the mainstream Emacs code.
1865 The input handler calls this.
1867 We have received a mouse movement event, which is given in *event.
1868 If the mouse is over a different glyph than it was last time, tell
1869 the mainstream emacs code by setting mouse_moved. If not, ask for
1870 another motion event, so we can check again the next time it moves. */
1873 note_mouse_movement (frame
, event
)
1875 XMotionEvent
*event
;
1878 last_mouse_movement_time
= event
->time
;
1880 /* Has the mouse moved off the glyph it was on at the last sighting? */
1881 if (event
->x
< last_mouse_glyph
.x
1882 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1883 || event
->y
< last_mouse_glyph
.y
1884 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1887 last_mouse_scroll_bar
= Qnil
;
1889 note_mouse_highlight (frame
, event
->x
, event
->y
);
1891 /* Ask for another mouse motion event. */
1895 XQueryPointer (event
->display
, event
->window
,
1896 (Window
*) &dummy
, (Window
*) &dummy
,
1897 &dummy
, &dummy
, &dummy
, &dummy
,
1898 (unsigned int *) &dummy
);
1903 /* It's on the same glyph. Call XQueryPointer so we'll get an
1904 event the next time the mouse moves and we can see if it's
1905 *still* on the same glyph. */
1908 XQueryPointer (event
->display
, event
->window
,
1909 (Window
*) &dummy
, (Window
*) &dummy
,
1910 &dummy
, &dummy
, &dummy
, &dummy
,
1911 (unsigned int *) &dummy
);
1915 /* Take proper action when the mouse has moved to position X, Y on frame F
1916 as regards highlighting characters that have mouse-face properties.
1917 Also dehighlighting chars where the mouse was before. */
1920 note_mouse_highlight (f
, x
, y
)
1923 int row
, column
, portion
;
1924 XRectangle new_glyph
;
1928 mouse_face_mouse_x
= x
;
1929 mouse_face_mouse_y
= y
;
1930 mouse_face_mouse_frame
= f
;
1932 if (mouse_face_defer
)
1935 /* Find out which glyph the mouse is on. */
1936 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1937 &new_glyph
, x_mouse_grabbed
);
1939 /* Which window is that in? */
1940 window
= window_from_coordinates (f
, column
, row
, &portion
);
1941 w
= XWINDOW (window
);
1943 /* If we were displaying active text in another window, clear that. */
1944 if (! EQ (window
, mouse_face_window
))
1945 clear_mouse_face ();
1947 /* Are we in a window whose display is up to date? */
1948 if (WINDOWP (window
) && portion
== 0
1949 && EQ (w
->window_end_valid
, Qt
))
1951 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1954 /* Find which buffer position the mouse corresponds to. */
1955 for (i
= column
; i
>= 0; i
--)
1959 /* Is it outside the displayed active region (if any)? */
1961 && ! (EQ (window
, mouse_face_window
)
1962 && pos
>= mouse_face_beg
&& pos
< mouse_face_end
))
1964 Lisp_Object mouse_face
, overlay
, position
;
1965 Lisp_Object
*overlay_vec
;
1966 int len
, noverlays
, ignor1
;
1968 /* Make the window's buffer temporarily current for
1969 overlays_at and compute_char_face. */
1970 struct buffer
*obuf
= current_buffer
;
1971 current_buffer
= XBUFFER (w
->buffer
);
1973 /* Yes. Clear the display of the old active region, if any. */
1974 clear_mouse_face ();
1976 /* Is this char mouse-active? */
1977 XSET (position
, Lisp_Int
, pos
);
1980 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1982 /* Put all the overlays we want in a vector in overlay_vec.
1983 Store the length in len. */
1984 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
, &ignor1
);
1985 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1987 /* Find the highest priority overlay that has a mouse-face prop. */
1989 for (i
= 0; i
< noverlays
; i
++)
1991 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1992 if (!NILP (mouse_face
))
1994 overlay
= overlay_vec
[i
];
1999 /* If no overlay applies, get a text property. */
2001 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2003 /* Handle the overlay case. */
2004 if (! NILP (overlay
))
2006 /* Find the range of text around this char that
2007 should be active. */
2008 Lisp_Object before
, after
;
2011 before
= Foverlay_start (overlay
);
2012 after
= Foverlay_end (overlay
);
2013 /* Record this as the current active region. */
2014 mouse_face_beg
= XFASTINT (before
);
2015 mouse_face_end
= XFASTINT (after
);
2016 mouse_face_window
= window
;
2017 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
2018 &ignore
, pos
+ 1, 1);
2020 /* Display it as active. */
2021 show_mouse_face (1);
2023 /* Handle the text property case. */
2024 else if (! NILP (mouse_face
))
2026 /* Find the range of text around this char that
2027 should be active. */
2028 Lisp_Object before
, after
, beginning
, end
;
2031 beginning
= Fmarker_position (w
->start
);
2032 XSET (end
, Lisp_Int
,
2033 (BUF_Z (XBUFFER (w
->buffer
))
2034 - XFASTINT (w
->window_end_pos
)));
2036 = Fprevious_single_property_change (make_number (pos
+ 1),
2038 w
->buffer
, beginning
);
2040 = Fnext_single_property_change (position
, Qmouse_face
,
2042 /* Record this as the current active region. */
2043 mouse_face_beg
= XFASTINT (before
);
2044 mouse_face_end
= XFASTINT (after
);
2045 mouse_face_window
= window
;
2047 = compute_char_face (f
, w
, pos
, 0, 0,
2048 &ignore
, pos
+ 1, 1);
2050 /* Display it as active. */
2051 show_mouse_face (1);
2053 current_buffer
= obuf
;
2056 clear_mouse_face ();
2060 /* Find the row and column of position POS in window WINDOW.
2061 Store them in *COLUMNP and *ROWP.
2062 This assumes display in WINDOW is up to date. */
2065 fast_find_position (window
, pos
, columnp
, rowp
)
2068 int *columnp
, *rowp
;
2070 struct window
*w
= XWINDOW (window
);
2071 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2076 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2077 int width
= window_internal_width (w
);
2084 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2085 if (linestart
> pos
)
2091 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2092 for (i
= 0; i
< width
; i
++)
2093 if (charstarts
[left
+ i
] == pos
)
2096 *columnp
= i
+ left
;
2103 /* Display the active region described by mouse_face_*
2104 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2107 show_mouse_face (hl
)
2110 int begcol
, begrow
, endcol
, endrow
;
2111 struct window
*w
= XWINDOW (mouse_face_window
);
2112 int width
= window_internal_width (w
);
2113 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2116 fast_find_position (mouse_face_window
, mouse_face_beg
,
2118 fast_find_position (mouse_face_window
, mouse_face_end
,
2121 x_display_cursor (f
, 0);
2123 for (i
= begrow
; i
<= endrow
; i
++)
2125 int column
= (i
== begrow
? begcol
: w
->left
);
2126 int endcolumn
= (i
== endrow
? endcol
: w
->left
+ width
);
2127 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
] - w
->left
),
2130 CHAR_TO_PIXEL_COL (f
, column
),
2131 CHAR_TO_PIXEL_ROW (f
, i
),
2132 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2134 /* Highlight with mouse face if hl > 0. */
2138 x_display_cursor (f
, 1);
2141 /* Clear out the mouse-highlighted active region.
2142 Redraw it unhighlighted first. */
2147 if (! NILP (mouse_face_window
))
2148 show_mouse_face (0);
2150 mouse_face_beg
= -1;
2151 mouse_face_end
= -1;
2152 mouse_face_window
= Qnil
;
2155 static struct scroll_bar
*x_window_to_scroll_bar ();
2156 static void x_scroll_bar_report_motion ();
2158 /* Return the current position of the mouse.
2160 If the mouse movement started in a scroll bar, set *f, *bar_window,
2161 and *part to the frame, window, and scroll bar part that the mouse
2162 is over. Set *x and *y to the portion and whole of the mouse's
2163 position on the scroll bar.
2165 If the mouse movement started elsewhere, set *f to the frame the
2166 mouse is on, *bar_window to nil, and *x and *y to the character cell
2169 Set *time to the server timestamp for the time at which the mouse
2170 was at this position.
2172 Don't store anything if we don't have a valid set of values to report.
2174 This clears the mouse_moved flag, so we can wait for the next mouse
2175 movement. This also calls XQueryPointer, which will cause the
2176 server to give us another MotionNotify when the mouse moves
2180 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
2182 Lisp_Object
*bar_window
;
2183 enum scroll_bar_part
*part
;
2185 unsigned long *time
;
2191 if (! NILP (last_mouse_scroll_bar
))
2192 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
2198 Window dummy_window
;
2202 last_mouse_scroll_bar
= Qnil
;
2204 /* Figure out which root window we're on. */
2205 XQueryPointer (x_current_display
,
2206 DefaultRootWindow (x_current_display
),
2208 /* The root window which contains the pointer. */
2211 /* Trash which we can't trust if the pointer is on
2212 a different screen. */
2215 /* The position on that root window. */
2218 /* More trash we can't trust. */
2221 /* Modifier keys and pointer buttons, about which
2223 (unsigned int *) &dummy
);
2225 /* Now we have a position on the root; find the innermost window
2226 containing the pointer. */
2230 int parent_x
, parent_y
;
2234 if (x_mouse_grabbed
)
2236 /* If mouse was grabbed on a frame, give coords for that frame
2237 even if the mouse is now outside it. */
2238 XTranslateCoordinates (x_current_display
,
2240 /* From-window, to-window. */
2241 root
, FRAME_X_WINDOW (last_mouse_frame
),
2243 /* From-position, to-position. */
2244 root_x
, root_y
, &win_x
, &win_y
,
2248 f1
= last_mouse_frame
;
2254 XTranslateCoordinates (x_current_display
,
2256 /* From-window, to-window. */
2259 /* From-position, to-position. */
2260 root_x
, root_y
, &win_x
, &win_y
,
2273 /* Now we know that:
2274 win is the innermost window containing the pointer
2275 (XTC says it has no child containing the pointer),
2276 win_x and win_y are the pointer's position in it
2277 (XTC did this the last time through), and
2278 parent_x and parent_y are the pointer's position in win's parent.
2279 (They are what win_x and win_y were when win was child.
2280 If win is the root window, it has no parent, and
2281 parent_{x,y} are invalid, but that's okay, because we'll
2282 never use them in that case.) */
2284 /* Is win one of our frames? */
2285 f1
= x_any_window_to_frame (win
);
2288 /* If not, is it one of our scroll bars? */
2291 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2295 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2303 int ignore1
, ignore2
;
2305 /* Ok, we found a frame. Store all the values. */
2307 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2308 &last_mouse_glyph
, x_mouse_grabbed
);
2313 XSET (*x
, Lisp_Int
, win_x
);
2314 XSET (*y
, Lisp_Int
, win_y
);
2315 *time
= last_mouse_movement_time
;
2323 #else /* ! defined (HAVE_X11) */
2324 #define XEvent XKeyPressedEvent
2325 #endif /* ! defined (HAVE_X11) */
2327 /* Scroll bar support. */
2329 /* Given an X window ID, find the struct scroll_bar which manages it.
2330 This can be called in GC, so we have to make sure to strip off mark
2332 static struct scroll_bar
*
2333 x_window_to_scroll_bar (window_id
)
2336 Lisp_Object tail
, frame
;
2338 for (tail
= Vframe_list
;
2339 XGCTYPE (tail
) == Lisp_Cons
;
2340 tail
= XCONS (tail
)->cdr
)
2342 Lisp_Object frame
, bar
, condemned
;
2344 frame
= XCONS (tail
)->car
;
2345 /* All elements of Vframe_list should be frames. */
2346 if (XGCTYPE (frame
) != Lisp_Frame
)
2349 /* Scan this frame's scroll bar list for a scroll bar with the
2351 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2352 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2353 /* This trick allows us to search both the ordinary and
2354 condemned scroll bar lists with one loop. */
2355 ! GC_NILP (bar
) || (bar
= condemned
,
2358 bar
= XSCROLL_BAR (bar
)->next
)
2359 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2360 return XSCROLL_BAR (bar
);
2366 /* Open a new X window to serve as a scroll bar, and return the
2367 scroll bar vector for it. */
2368 static struct scroll_bar
*
2369 x_scroll_bar_create (window
, top
, left
, width
, height
)
2370 struct window
*window
;
2371 int top
, left
, width
, height
;
2373 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2374 struct scroll_bar
*bar
=
2375 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2380 XSetWindowAttributes a
;
2382 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2383 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2384 | ButtonMotionMask
| PointerMotionHintMask
2386 a
.cursor
= x_vertical_scroll_bar_cursor
;
2388 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2393 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2394 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2395 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2396 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2397 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2398 sb_widget
= XtCreateManagedWidget ("box",
2400 frame
->display
.x
->edit_widget
, al
, ac
);
2401 SET_SCROLL_BAR_X_WINDOW
2402 (bar
, sb_widget
->core
.window
);
2404 SET_SCROLL_BAR_X_WINDOW
2406 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2408 /* Position and size of scroll bar. */
2409 left
, top
, width
, height
,
2411 /* Border width, depth, class, and visual. */
2412 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2418 XSET (bar
->window
, Lisp_Window
, window
);
2419 XSET (bar
->top
, Lisp_Int
, top
);
2420 XSET (bar
->left
, Lisp_Int
, left
);
2421 XSET (bar
->width
, Lisp_Int
, width
);
2422 XSET (bar
->height
, Lisp_Int
, height
);
2423 XSET (bar
->start
, Lisp_Int
, 0);
2424 XSET (bar
->end
, Lisp_Int
, 0);
2425 bar
->dragging
= Qnil
;
2427 /* Add bar to its frame's list of scroll bars. */
2428 bar
->next
= FRAME_SCROLL_BARS (frame
);
2430 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2431 if (! NILP (bar
->next
))
2432 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2434 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2441 /* Draw BAR's handle in the proper position.
2442 If the handle is already drawn from START to END, don't bother
2443 redrawing it, unless REBUILD is non-zero; in that case, always
2444 redraw it. (REBUILD is handy for drawing the handle after expose
2447 Normally, we want to constrain the start and end of the handle to
2448 fit inside its rectangle, but if the user is dragging the scroll bar
2449 handle, we want to let them drag it down all the way, so that the
2450 bar's top is as far down as it goes; otherwise, there's no way to
2451 move to the very end of the buffer. */
2453 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2454 struct scroll_bar
*bar
;
2458 int dragging
= ! NILP (bar
->dragging
);
2459 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2460 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2462 /* If the display is already accurate, do nothing. */
2464 && start
== XINT (bar
->start
)
2465 && end
== XINT (bar
->end
))
2471 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2472 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2473 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2475 /* Make sure the values are reasonable, and try to preserve
2476 the distance between start and end. */
2478 int length
= end
- start
;
2482 else if (start
> top_range
)
2484 end
= start
+ length
;
2488 else if (end
> top_range
&& ! dragging
)
2492 /* Store the adjusted setting in the scroll bar. */
2493 XSET (bar
->start
, Lisp_Int
, start
);
2494 XSET (bar
->end
, Lisp_Int
, end
);
2496 /* Clip the end position, just for display. */
2497 if (end
> top_range
)
2500 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2501 below top positions, to make sure the handle is always at least
2502 that many pixels tall. */
2503 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2505 /* Draw the empty space above the handle. Note that we can't clear
2506 zero-height areas; that means "clear to end of window." */
2508 XClearArea (x_current_display
, w
,
2510 /* x, y, width, height, and exposures. */
2511 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2512 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2513 inside_width
, start
,
2516 /* Draw the handle itself. */
2517 XFillRectangle (x_current_display
, w
, gc
,
2519 /* x, y, width, height */
2520 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2521 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2522 inside_width
, end
- start
);
2525 /* Draw the empty space below the handle. Note that we can't
2526 clear zero-height areas; that means "clear to end of window." */
2527 if (end
< inside_height
)
2528 XClearArea (x_current_display
, w
,
2530 /* x, y, width, height, and exposures. */
2531 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2532 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2533 inside_width
, inside_height
- end
,
2541 /* Move a scroll bar around on the screen, to accommodate changing
2542 window configurations. */
2544 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2545 struct scroll_bar
*bar
;
2546 int top
, left
, width
, height
;
2552 unsigned int mask
= 0;
2559 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2560 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2561 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2562 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2565 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2569 XSET (bar
->left
, Lisp_Int
, left
);
2570 XSET (bar
->top
, Lisp_Int
, top
);
2571 XSET (bar
->width
, Lisp_Int
, width
);
2572 XSET (bar
->height
, Lisp_Int
, height
);
2577 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2580 x_scroll_bar_remove (bar
)
2581 struct scroll_bar
*bar
;
2583 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2587 /* Destroy the window. */
2588 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2590 /* Disassociate this scroll bar from its window. */
2591 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2596 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2597 that we are displaying PORTION characters out of a total of WHOLE
2598 characters, starting at POSITION. If WINDOW has no scroll bar,
2601 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2602 struct window
*window
;
2603 int portion
, whole
, position
;
2605 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2606 int top
= XINT (window
->top
);
2607 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2608 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2610 /* Where should this scroll bar be, pixelwise? */
2611 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2612 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2613 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2614 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2616 struct scroll_bar
*bar
;
2618 /* Does the scroll bar exist yet? */
2619 if (NILP (window
->vertical_scroll_bar
))
2620 bar
= x_scroll_bar_create (window
,
2621 pixel_top
, pixel_left
,
2622 pixel_width
, pixel_height
);
2625 /* It may just need to be moved and resized. */
2626 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2627 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2630 /* Set the scroll bar's current state, unless we're currently being
2632 if (NILP (bar
->dragging
))
2635 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2638 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2641 int start
= ((double) position
* top_range
) / whole
;
2642 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2644 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2648 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2652 /* The following three hooks are used when we're doing a thorough
2653 redisplay of the frame. We don't explicitly know which scroll bars
2654 are going to be deleted, because keeping track of when windows go
2655 away is a real pain - "Can you say set-window-configuration, boys
2656 and girls?" Instead, we just assert at the beginning of redisplay
2657 that *all* scroll bars are to be removed, and then save a scroll bar
2658 from the fiery pit when we actually redisplay its window. */
2660 /* Arrange for all scroll bars on FRAME to be removed at the next call
2661 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2662 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2664 XTcondemn_scroll_bars (frame
)
2667 /* The condemned list should be empty at this point; if it's not,
2668 then the rest of Emacs isn't using the condemn/redeem/judge
2669 protocol correctly. */
2670 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2673 /* Move them all to the "condemned" list. */
2674 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2675 FRAME_SCROLL_BARS (frame
) = Qnil
;
2678 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2679 Note that WINDOW isn't necessarily condemned at all. */
2681 XTredeem_scroll_bar (window
)
2682 struct window
*window
;
2684 struct scroll_bar
*bar
;
2686 /* We can't redeem this window's scroll bar if it doesn't have one. */
2687 if (NILP (window
->vertical_scroll_bar
))
2690 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2692 /* Unlink it from the condemned list. */
2694 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2696 if (NILP (bar
->prev
))
2698 /* If the prev pointer is nil, it must be the first in one of
2700 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2701 /* It's not condemned. Everything's fine. */
2703 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2704 window
->vertical_scroll_bar
))
2705 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2707 /* If its prev pointer is nil, it must be at the front of
2708 one or the other! */
2712 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2714 if (! NILP (bar
->next
))
2715 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2717 bar
->next
= FRAME_SCROLL_BARS (f
);
2719 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2720 if (! NILP (bar
->next
))
2721 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2725 /* Remove all scroll bars on FRAME that haven't been saved since the
2726 last call to `*condemn_scroll_bars_hook'. */
2728 XTjudge_scroll_bars (f
)
2731 Lisp_Object bar
, next
;
2733 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2735 /* Clear out the condemned list now so we won't try to process any
2736 more events on the hapless scroll bars. */
2737 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2739 for (; ! NILP (bar
); bar
= next
)
2741 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2743 x_scroll_bar_remove (b
);
2746 b
->next
= b
->prev
= Qnil
;
2749 /* Now there should be no references to the condemned scroll bars,
2750 and they should get garbage-collected. */
2754 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2756 This may be called from a signal handler, so we have to ignore GC
2759 x_scroll_bar_expose (bar
, event
)
2760 struct scroll_bar
*bar
;
2763 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2764 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2768 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2770 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2771 XDrawRectangle (x_current_display
, w
, gc
,
2773 /* x, y, width, height */
2774 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2779 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2780 is set to something other than no_event, it is enqueued.
2782 This may be called from a signal handler, so we have to ignore GC
2785 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2786 struct scroll_bar
*bar
;
2788 struct input_event
*emacs_event
;
2790 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2793 emacs_event
->kind
= scroll_bar_click
;
2794 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2795 emacs_event
->modifiers
=
2796 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2797 | (event
->type
== ButtonRelease
2800 emacs_event
->frame_or_window
= bar
->window
;
2801 emacs_event
->timestamp
= event
->xbutton
.time
;
2803 int internal_height
=
2804 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2806 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2807 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2810 if (y
> top_range
) y
= top_range
;
2812 if (y
< XINT (bar
->start
))
2813 emacs_event
->part
= scroll_bar_above_handle
;
2814 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2815 emacs_event
->part
= scroll_bar_handle
;
2817 emacs_event
->part
= scroll_bar_below_handle
;
2819 /* Just because the user has clicked on the handle doesn't mean
2820 they want to drag it. Lisp code needs to be able to decide
2821 whether or not we're dragging. */
2823 /* If the user has just clicked on the handle, record where they're
2825 if (event
->type
== ButtonPress
2826 && emacs_event
->part
== scroll_bar_handle
)
2827 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2830 /* If the user has released the handle, set it to its final position. */
2831 if (event
->type
== ButtonRelease
2832 && ! NILP (bar
->dragging
))
2834 int new_start
= y
- XINT (bar
->dragging
);
2835 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2837 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2838 bar
->dragging
= Qnil
;
2841 /* Same deal here as the other #if 0. */
2843 /* Clicks on the handle are always reported as occurring at the top of
2845 if (emacs_event
->part
== scroll_bar_handle
)
2846 emacs_event
->x
= bar
->start
;
2848 XSET (emacs_event
->x
, Lisp_Int
, y
);
2850 XSET (emacs_event
->x
, Lisp_Int
, y
);
2853 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2857 /* Handle some mouse motion while someone is dragging the scroll bar.
2859 This may be called from a signal handler, so we have to ignore GC
2862 x_scroll_bar_note_movement (bar
, event
)
2863 struct scroll_bar
*bar
;
2866 last_mouse_movement_time
= event
->xmotion
.time
;
2869 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2871 /* If we're dragging the bar, display it. */
2872 if (! GC_NILP (bar
->dragging
))
2874 /* Where should the handle be now? */
2875 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2877 if (new_start
!= XINT (bar
->start
))
2879 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2881 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2885 /* Call XQueryPointer so we'll get an event the next time the mouse
2886 moves and we can see *still* on the same position. */
2890 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2891 (Window
*) &dummy
, (Window
*) &dummy
,
2892 &dummy
, &dummy
, &dummy
, &dummy
,
2893 (unsigned int *) &dummy
);
2897 /* Return information to the user about the current position of the mouse
2898 on the scroll bar. */
2900 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2902 Lisp_Object
*bar_window
;
2903 enum scroll_bar_part
*part
;
2905 unsigned long *time
;
2907 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2909 Window dummy_window
;
2911 unsigned int dummy_mask
;
2915 /* Get the mouse's position relative to the scroll bar window, and
2917 if (! XQueryPointer (x_current_display
,
2918 SCROLL_BAR_X_WINDOW (bar
),
2920 /* Root, child, root x and root y. */
2921 &dummy_window
, &dummy_window
,
2922 &dummy_coord
, &dummy_coord
,
2924 /* Position relative to scroll bar. */
2927 /* Mouse buttons and modifier keys. */
2933 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2935 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2937 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2939 if (! NILP (bar
->dragging
))
2940 win_y
-= XINT (bar
->dragging
);
2944 if (win_y
> top_range
)
2947 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2948 *bar_window
= bar
->window
;
2950 if (! NILP (bar
->dragging
))
2951 *part
= scroll_bar_handle
;
2952 else if (win_y
< XINT (bar
->start
))
2953 *part
= scroll_bar_above_handle
;
2954 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2955 *part
= scroll_bar_handle
;
2957 *part
= scroll_bar_below_handle
;
2959 XSET (*x
, Lisp_Int
, win_y
);
2960 XSET (*y
, Lisp_Int
, top_range
);
2963 last_mouse_scroll_bar
= Qnil
;
2966 *time
= last_mouse_movement_time
;
2972 /* The screen has been cleared so we may have changed foreground or
2973 background colors, and the scroll bars may need to be redrawn.
2974 Clear out the scroll bars, and ask for expose events, so we can
2977 x_scroll_bar_clear (f
)
2982 for (bar
= FRAME_SCROLL_BARS (f
);
2983 XTYPE (bar
) == Lisp_Vector
;
2984 bar
= XSCROLL_BAR (bar
)->next
)
2985 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2989 /* This processes Expose events from the menubar specific X event
2990 loop in menubar.c. This allows to redisplay the frame if necessary
2991 when handling menubar or popup items. */
2994 process_expose_from_menu (event
)
3001 f
= x_window_to_frame (event
.xexpose
.window
);
3004 if (f
->async_visible
== 0)
3006 f
->async_visible
= 1;
3007 f
->async_iconified
= 0;
3008 SET_FRAME_GARBAGED (f
);
3012 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3013 event
.xexpose
.x
, event
.xexpose
.y
,
3014 event
.xexpose
.width
, event
.xexpose
.height
);
3019 struct scroll_bar
*bar
3020 = x_window_to_scroll_bar (event
.xexpose
.window
);
3023 x_scroll_bar_expose (bar
, &event
);
3030 /* The main X event-reading loop - XTread_socket. */
3032 /* Timestamp of enter window event. This is only used by XTread_socket,
3033 but we have to put it out here, since static variables within functions
3034 sometimes don't work. */
3035 static Time enter_timestamp
;
3037 /* This holds the state XLookupString needs to implement dead keys
3038 and other tricks known as "compose processing". _X Window System_
3039 says that a portable program can't use this, but Stephen Gildea assures
3040 me that letting the compiler initialize it to zeros will work okay.
3042 This must be defined outside of XTread_socket, for the same reasons
3043 given for enter_timestamp, above. */
3044 static XComposeStatus compose_status
;
3046 /* Communication with window managers. */
3047 Atom Xatom_wm_protocols
;
3049 /* Kinds of protocol things we may receive. */
3050 Atom Xatom_wm_take_focus
;
3051 Atom Xatom_wm_save_yourself
;
3052 Atom Xatom_wm_delete_window
;
3054 /* Other WM communication */
3055 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3056 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3058 /* Window manager communication. */
3059 Atom Xatom_wm_change_state
;
3061 /* Record the last 100 characters stored
3062 to help debug the loss-of-chars-during-GC problem. */
3064 short temp_buffer
[100];
3066 /* Read events coming from the X server.
3067 This routine is called by the SIGIO handler.
3068 We return as soon as there are no more events to be read.
3070 Events representing keys are stored in buffer BUFP,
3071 which can hold up to NUMCHARS characters.
3072 We return the number of characters stored into the buffer,
3073 thus pretending to be `read'.
3075 WAITP is nonzero if we should block until input arrives.
3076 EXPECTED is nonzero if the caller knows input is available. */
3079 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3081 register struct input_event
*bufp
;
3082 register int numchars
;
3089 int items_pending
; /* How many items are in the X queue. */
3092 int event_found
= 0;
3096 if (interrupt_input_blocked
)
3098 interrupt_input_pending
= 1;
3102 interrupt_input_pending
= 0;
3106 abort (); /* Don't think this happens. */
3109 /* If available, Xlib uses FIOSNBIO to make the socket
3110 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3111 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3112 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3113 fcntl (fileno (stdin
), F_SETFL
, 0);
3114 #endif /* ! defined (FIOSNBIO) */
3118 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3120 extern int read_alarm_should_throw
;
3121 read_alarm_should_throw
= 1;
3122 XPeekEvent (XDISPLAY
&event
);
3123 read_alarm_should_throw
= 0;
3125 #endif /* HAVE_SELECT */
3128 while (XStuffPending () != 0)
3130 XNextEvent (XDISPLAY
&event
);
3138 if (event
.xclient
.message_type
== Xatom_wm_protocols
3139 && event
.xclient
.format
== 32)
3141 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3143 #ifdef USE_X_TOOLKIT
3144 /* f = x_any_window_to_frame (event.xclient.window); */
3145 f
= x_window_to_frame (event
.xclient
.window
);
3147 f
= x_window_to_frame (event
.xclient
.window
);
3150 x_focus_on_frame (f
);
3151 /* Not certain about handling scroll bars here */
3153 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3155 /* Save state modify the WM_COMMAND property to
3156 something which can reinstate us. This notifies
3157 the session manager, who's looking for such a
3158 PropertyNotify. Can restart processing when
3159 a keyboard or mouse event arrives. */
3164 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3166 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3173 bufp
->kind
= delete_window_event
;
3174 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3182 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3185 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3188 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3190 new_x
= event
.xclient
.data
.s
[0];
3191 new_y
= event
.xclient
.data
.s
[1];
3195 f
->display
.x
->left_pos
= new_x
;
3196 f
->display
.x
->top_pos
= new_y
;
3202 #ifdef NEW_SELECTIONS
3203 case SelectionNotify
:
3204 #ifdef USE_X_TOOLKIT
3205 if (x_window_to_frame (event
.xselection
.requestor
))
3206 x_handle_selection_notify (&event
);
3209 #else /* not USE_X_TOOLKIT */
3210 x_handle_selection_notify (&event
);
3211 #endif /* not USE_X_TOOLKIT */
3213 #endif /* NEW_SELECTIONS */
3215 case SelectionClear
: /* Someone has grabbed ownership. */
3216 #ifdef NEW_SELECTIONS
3218 #ifdef USE_X_TOOLKIT
3219 if (x_window_to_frame (event
.xselectionclear
.window
))
3221 #endif /* USE_X_TOOLKIT */
3222 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3227 bufp
->kind
= selection_clear_event
;
3228 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3229 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3230 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3235 #ifdef USE_X_TOOLKIT
3239 #endif /* USE_X_TOOLKIT */
3241 #else /* not NEW_SELECTIONS */
3242 x_disown_selection (event
.xselectionclear
.window
,
3243 event
.xselectionclear
.selection
,
3244 event
.xselectionclear
.time
);
3245 #endif /* not NEW_SELECTIONS */
3248 case SelectionRequest
: /* Someone wants our selection. */
3249 #ifdef NEW_SELECTIONS
3251 #ifdef USE_X_TOOLKIT
3252 if (x_window_to_frame (event
.xselectionrequest
.owner
))
3254 #endif /* USE_X_TOOLKIT */
3255 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3260 bufp
->kind
= selection_request_event
;
3261 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3262 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3263 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3264 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3265 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3266 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3271 #ifdef USE_X_TOOLKIT
3275 #endif /* USE_X_TOOLKIT */
3277 #else /* not NEW_SELECTIONS */
3278 x_answer_selection_request (event
);
3279 #endif /* not NEW_SELECTIONS */
3282 case PropertyNotify
:
3283 #ifdef NEW_SELECTIONS
3284 #ifdef USE_X_TOOLKIT
3285 if (x_any_window_to_frame (event
.xproperty
.window
))
3286 x_handle_property_notify (&event
);
3289 #else /* not USE_X_TOOLKIT */
3290 x_handle_property_notify (&event
);
3291 #endif /* not USE_X_TOOLKIT */
3292 #else /* not NEW_SELECTIONS */
3293 /* If we're being told about a root window property, then it's
3294 a cut buffer change. */
3295 if (event
.xproperty
.window
== ROOT_WINDOW
)
3296 x_invalidate_cut_buffer_cache (&event
.xproperty
);
3298 /* Otherwise, we're probably handling an incremental
3299 selection transmission. */
3302 /* If we were to do this synchronously, there'd be no worry
3303 about re-selecting. */
3304 x_send_incremental (event
);
3306 #endif /* not NEW_SELECTIONS */
3309 case ReparentNotify
:
3310 f
= x_window_to_frame (event
.xreparent
.window
);
3312 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3316 f
= x_window_to_frame (event
.xexpose
.window
);
3319 if (f
->async_visible
== 0)
3321 f
->async_visible
= 1;
3322 f
->async_iconified
= 0;
3323 SET_FRAME_GARBAGED (f
);
3327 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3328 event
.xexpose
.x
, event
.xexpose
.y
,
3329 event
.xexpose
.width
, event
.xexpose
.height
);
3334 struct scroll_bar
*bar
3335 = x_window_to_scroll_bar (event
.xexpose
.window
);
3338 x_scroll_bar_expose (bar
, &event
);
3339 #ifdef USE_X_TOOLKIT
3342 #endif /* USE_X_TOOLKIT */
3346 case GraphicsExpose
: /* This occurs when an XCopyArea's
3347 source area was obscured or not
3349 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3353 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3354 event
.xgraphicsexpose
.width
,
3355 event
.xgraphicsexpose
.height
);
3357 #ifdef USE_X_TOOLKIT
3360 #endif /* USE_X_TOOLKIT */
3363 case NoExpose
: /* This occurs when an XCopyArea's
3364 source area was completely
3367 #else /* ! defined (HAVE_X11) */
3369 if (event
.subwindow
!= 0)
3370 break; /* duplicate event */
3371 f
= x_window_to_frame (event
.window
);
3372 if (event
.window
== f
->display
.x
->icon_desc
)
3375 f
->async_iconified
= 1;
3377 if (event
.window
== FRAME_X_WINDOW (f
))
3379 /* Say must check all windows' needs_exposure flags. */
3380 expose_all_windows
= 1;
3381 f
->display
.x
->needs_exposure
= 1;
3382 f
->async_visible
= 1;
3387 if (event
.subwindow
!= 0)
3388 break; /* duplicate event */
3389 f
= x_window_to_frame (event
.window
);
3390 if (event
.window
== f
->display
.x
->icon_desc
)
3395 /* If window already needs full redraw, ignore this rectangle. */
3396 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3398 /* Put the event on the queue of rectangles to redraw. */
3399 if (enqueue_event (&event
, &x_expose_queue
))
3400 /* If it is full, we can't record the rectangle,
3401 so redraw this entire window. */
3403 /* Say must check all windows' needs_exposure flags. */
3404 expose_all_windows
= 1;
3405 f
->display
.x
->needs_exposure
= 1;
3410 /* This should happen only when we are expecting it,
3411 in x_read_exposes. */
3413 #endif /* ! defined (HAVE_X11) */
3417 f
= x_window_to_frame (event
.xunmap
.window
);
3418 if (f
) /* F may no longer exist if
3419 the frame was deleted. */
3421 /* While a frame is unmapped, display generation is
3422 disabled; you don't want to spend time updating a
3423 display that won't ever be seen. */
3424 f
->async_visible
= 0;
3425 /* The window manager never makes a window invisible
3426 ("withdrawn"); all it does is switch between visible
3427 and iconified. Frames get into the invisible state
3428 only through x_make_frame_invisible. */
3429 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3430 f
->async_iconified
= 1;
3432 #ifdef USE_X_TOOLKIT
3434 #endif /* USE_X_TOOLKIT */
3438 #ifdef USE_X_TOOLKIT
3439 f
= x_any_window_to_frame (event
.xmap
.window
);
3440 #else /* not USE_X_TOOLKIT */
3441 f
= x_window_to_frame (event
.xmap
.window
);
3442 #endif /* not USE_X_TOOLKIT */
3445 f
->async_visible
= 1;
3446 f
->async_iconified
= 0;
3448 /* wait_reading_process_input will notice this and update
3449 the frame's display structures. */
3450 SET_FRAME_GARBAGED (f
);
3452 #ifdef USE_X_TOOLKIT
3454 #endif /* USE_X_TOOLKIT */
3457 /* Turn off processing if we become fully obscured. */
3458 case VisibilityNotify
:
3461 #else /* ! defined (HAVE_X11) */
3463 f
= x_window_to_frame (event
.window
);
3464 if (event
.window
== f
->display
.x
->icon_desc
)
3465 f
->async_iconified
= 0;
3466 if (event
.window
== FRAME_X_WINDOW (f
))
3467 f
->async_visible
= 0;
3469 #endif /* ! defined (HAVE_X11) */
3473 f
= x_any_window_to_frame (event
.xkey
.window
);
3477 KeySym keysym
, orig_keysym
;
3478 /* al%imercury@uunet.uu.net says that making this 81 instead of
3479 80 fixed a bug whereby meta chars made his Emacs hang. */
3480 unsigned char copy_buffer
[81];
3484 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3485 modifiers
= event
.xkey
.state
;
3487 /* This will have to go some day... */
3489 /* make_lispy_event turns chars into control chars.
3490 Don't do it here because XLookupString is too eager. */
3491 event
.xkey
.state
&= ~ControlMask
;
3493 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3496 /* Strip off the vendor-specific keysym bit, and take a shot
3497 at recognizing the codes. HP servers have extra keysyms
3498 that fit into the MiscFunctionKey category. */
3499 orig_keysym
= keysym
;
3504 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3505 || keysym
== XK_Delete
3506 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3507 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3509 /* This recognizes the "extended function keys".
3510 It seems there's no cleaner way.
3511 Test IsModifierKey to avoid handling mode_switch
3513 || ((unsigned) (keysym
) >= XK_Select
3514 && (unsigned)(keysym
) < XK_KP_Space
)
3516 #ifdef XK_dead_circumflex
3517 || orig_keysym
== XK_dead_circumflex
3519 #ifdef XK_dead_grave
3520 || orig_keysym
== XK_dead_grave
3522 #ifdef XK_dead_tilde
3523 || orig_keysym
== XK_dead_tilde
3525 #ifdef XK_dead_diaeresis
3526 || orig_keysym
== XK_dead_diaeresis
3528 #ifdef XK_dead_macron
3529 || orig_keysym
== XK_dead_macron
3531 #ifdef XK_dead_degree
3532 || orig_keysym
== XK_dead_degree
3534 #ifdef XK_dead_acute
3535 || orig_keysym
== XK_dead_acute
3537 #ifdef XK_dead_cedilla
3538 || orig_keysym
== XK_dead_cedilla
3540 #ifdef XK_dead_breve
3541 || orig_keysym
== XK_dead_breve
3543 #ifdef XK_dead_ogonek
3544 || orig_keysym
== XK_dead_ogonek
3546 #ifdef XK_dead_caron
3547 || orig_keysym
== XK_dead_caron
3549 #ifdef XK_dead_doubleacute
3550 || orig_keysym
== XK_dead_doubleacute
3552 #ifdef XK_dead_abovedot
3553 || orig_keysym
== XK_dead_abovedot
3555 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3556 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3557 || x_is_vendor_fkey (orig_keysym
))
3558 && ! (IsModifierKey (orig_keysym
)
3560 #ifdef XK_Mode_switch
3561 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3564 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3566 #endif /* not HAVE_X11R5 */
3569 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3571 temp_buffer
[temp_index
++] = keysym
;
3572 bufp
->kind
= non_ascii_keystroke
;
3573 bufp
->code
= keysym
;
3574 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3575 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3576 bufp
->timestamp
= event
.xkey
.time
;
3581 else if (numchars
> nbytes
)
3585 for (i
= 0; i
< nbytes
; i
++)
3587 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3589 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3590 bufp
->kind
= ascii_keystroke
;
3591 bufp
->code
= copy_buffer
[i
];
3592 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3593 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3594 bufp
->timestamp
= event
.xkey
.time
;
3608 #else /* ! defined (HAVE_X11) */
3611 register char *where_mapping
;
3613 f
= x_window_to_frame (event
.window
);
3614 /* Ignore keys typed on icon windows. */
3615 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3617 where_mapping
= XLookupMapping (&event
, &nbytes
);
3618 /* Nasty fix for arrow keys */
3619 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3621 switch (event
.detail
& 0xff)
3623 case KC_CURSOR_LEFT
:
3624 where_mapping
= "\002";
3626 case KC_CURSOR_RIGHT
:
3627 where_mapping
= "\006";
3630 where_mapping
= "\020";
3632 case KC_CURSOR_DOWN
:
3633 where_mapping
= "\016";
3638 if (numchars
- nbytes
> 0)
3642 for (i
= 0; i
< nbytes
; i
++)
3644 bufp
->kind
= ascii_keystroke
;
3645 bufp
->code
= where_mapping
[i
];
3646 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3647 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3655 #endif /* ! defined (HAVE_X11) */
3659 /* Here's a possible interpretation of the whole
3660 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3661 FocusIn event, you have to get a FocusOut event before you
3662 relinquish the focus. If you haven't received a FocusIn event,
3663 then a mere LeaveNotify is enough to free you. */
3666 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3668 if (event
.xcrossing
.focus
) /* Entered Window */
3670 /* Avoid nasty pop/raise loops. */
3671 if (f
&& (!(f
->auto_raise
)
3673 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3675 x_new_focus_frame (f
);
3676 enter_timestamp
= event
.xcrossing
.time
;
3679 else if (f
== x_focus_frame
)
3680 x_new_focus_frame (0);
3681 #ifdef USE_X_TOOLKIT
3683 #endif /* USE_X_TOOLKIT */
3687 f
= x_any_window_to_frame (event
.xfocus
.window
);
3688 if (event
.xfocus
.detail
!= NotifyPointer
)
3689 x_focus_event_frame
= f
;
3691 x_new_focus_frame (f
);
3692 #ifdef USE_X_TOOLKIT
3694 #endif /* USE_X_TOOLKIT */
3699 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3701 if (f
== mouse_face_mouse_frame
)
3702 /* If we move outside the frame,
3703 then we're certainly no longer on any text in the frame. */
3704 clear_mouse_face ();
3706 if (event
.xcrossing
.focus
)
3708 if (! x_focus_event_frame
)
3709 x_new_focus_frame (0);
3711 x_new_focus_frame (f
);
3715 if (f
== x_focus_event_frame
)
3716 x_focus_event_frame
= 0;
3717 if (f
== x_focus_frame
)
3718 x_new_focus_frame (0);
3720 #ifdef USE_X_TOOLKIT
3722 #endif /* USE_X_TOOLKIT */
3726 f
= x_any_window_to_frame (event
.xfocus
.window
);
3727 if (event
.xfocus
.detail
!= NotifyPointer
3728 && f
== x_focus_event_frame
)
3729 x_focus_event_frame
= 0;
3730 if (f
&& f
== x_focus_frame
)
3731 x_new_focus_frame (0);
3732 #ifdef USE_X_TOOLKIT
3734 #endif /* USE_X_TOOLKIT */
3737 #else /* ! defined (HAVE_X11) */
3740 if ((event
.detail
& 0xFF) == 1)
3741 break; /* Coming from our own subwindow */
3742 if (event
.subwindow
!= 0)
3743 break; /* Entering our own subwindow. */
3746 f
= x_window_to_frame (event
.window
);
3749 x_new_focus_frame (f
);
3754 if ((event
.detail
& 0xFF) == 1)
3755 break; /* Entering our own subwindow */
3756 if (event
.subwindow
!= 0)
3757 break; /* Leaving our own subwindow. */
3760 if (x_focus_frame
== 0
3761 && x_input_frame
!= 0
3762 && x_input_frame
== x_window_to_frame (event
.window
)
3763 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3768 frame_unhighlight (f
);
3771 #endif /* ! defined (HAVE_X11) */
3776 if (x_mouse_grabbed
)
3777 f
= last_mouse_frame
;
3779 f
= x_window_to_frame (event
.xmotion
.window
);
3781 note_mouse_movement (f
, &event
.xmotion
);
3784 struct scroll_bar
*bar
3785 = x_window_to_scroll_bar (event
.xmotion
.window
);
3788 x_scroll_bar_note_movement (bar
, &event
);
3790 /* If we move outside the frame,
3791 then we're certainly no longer on any text in the frame. */
3792 clear_mouse_face ();
3795 #ifdef USE_X_TOOLKIT
3797 #endif /* USE_X_TOOLKIT */
3800 case ConfigureNotify
:
3801 f
= x_any_window_to_frame (event
.xconfigure
.window
);
3802 #ifdef USE_X_TOOLKIT
3804 && ! event
.xconfigure
.send_event
3805 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
3810 /* Find the position of the outside upper-left corner of
3811 the window, in the root coordinate system. Don't
3812 refer to the parent window here; we may be processing
3813 this event after the window manager has changed our
3814 parent, but before we have reached the ReparentNotify. */
3815 XTranslateCoordinates (x_current_display
,
3817 /* From-window, to-window. */
3818 XtWindow (f
->display
.x
->widget
),
3821 /* From-position, to-position. */
3822 -event
.xconfigure
.border_width
,
3823 -event
.xconfigure
.border_width
,
3828 event
.xconfigure
.x
= win_x
;
3829 event
.xconfigure
.y
= win_y
;
3831 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3832 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3833 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3834 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3837 #else /* not USE_X_TOOLKIT */
3840 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3841 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3843 /* Even if the number of character rows and columns has
3844 not changed, the font size may have changed, so we need
3845 to check the pixel dimensions as well. */
3846 if (columns
!= f
->width
3847 || rows
!= f
->height
3848 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3849 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3851 change_frame_size (f
, rows
, columns
, 0, 1);
3852 SET_FRAME_GARBAGED (f
);
3855 if (! event
.xconfigure
.send_event
)
3860 /* Find the position of the outside upper-left corner of
3861 the window, in the root coordinate system. Don't
3862 refer to the parent window here; we may be processing
3863 this event after the window manager has changed our
3864 parent, but before we have reached the ReparentNotify. */
3865 XTranslateCoordinates (x_current_display
,
3867 /* From-window, to-window. */
3868 f
->display
.x
->window_desc
,
3871 /* From-position, to-position. */
3872 -event
.xconfigure
.border_width
,
3873 -event
.xconfigure
.border_width
,
3878 event
.xconfigure
.x
= win_x
;
3879 event
.xconfigure
.y
= win_y
;
3882 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3883 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3884 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3885 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3887 #endif /* not USE_X_TOOLKIT */
3893 /* If we decide we want to generate an event to be seen
3894 by the rest of Emacs, we put it here. */
3895 struct input_event emacs_event
;
3896 emacs_event
.kind
= no_event
;
3898 f
= x_window_to_frame (event
.xbutton
.window
);
3901 if (!x_focus_frame
|| (f
== x_focus_frame
))
3902 construct_mouse_click (&emacs_event
, &event
, f
);
3906 struct scroll_bar
*bar
=
3907 x_window_to_scroll_bar (event
.xbutton
.window
);
3910 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3911 #ifdef USE_X_TOOLKIT
3914 f
= x_any_window_to_frame (event
.xbutton
.window
);
3915 if (f
&& event
.type
== ButtonPress
)
3916 construct_menu_click (&emacs_event
,
3919 #endif /* USE_X_TOOLKIT */
3922 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3924 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3930 #ifdef USE_X_TOOLKIT
3932 #endif /* USE_X_TOOLKIT */
3936 #else /* ! defined (HAVE_X11) */
3938 case ButtonReleased
:
3939 f
= x_window_to_frame (event
.window
);
3942 if (event
.window
== f
->display
.x
->icon_desc
)
3944 x_make_frame_visible (f
);
3946 if (warp_mouse_on_deiconify
)
3947 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3950 if (event
.window
== FRAME_X_WINDOW (f
))
3956 enqueue_event (&event
, &x_mouse_queue
);
3959 bufp
->kind
= ascii_keystroke
;
3960 bufp
->code
= 'X' & 037; /* C-x */
3961 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3962 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3965 bufp
->kind
= ascii_keystroke
;
3966 bufp
->code
= 0; /* C-@ */
3967 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3968 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3975 #endif /* ! defined (HAVE_X11) */
3979 case CirculateNotify
:
3981 case CirculateRequest
:
3984 #endif /* ! defined (HAVE_X11) */
3987 /* Someone has changed the keyboard mapping - update the
3989 switch (event
.xmapping
.request
)
3991 case MappingModifier
:
3992 x_find_modifier_meanings ();
3993 /* This is meant to fall through. */
3994 case MappingKeyboard
:
3995 XRefreshKeyboardMapping (&event
.xmapping
);
3997 #ifdef USE_X_TOOLKIT
3999 #endif /* USE_X_TOOLKIT */
4003 #ifdef USE_X_TOOLKIT
4006 XtDispatchEvent (&event
);
4008 #endif /* USE_X_TOOLKIT */
4015 /* On some systems, an X bug causes Emacs to get no more events
4016 when the window is destroyed. Detect that. (1994.) */
4017 XNoOp (x_current_display
);
4018 #endif /* X_IO_BUG */
4020 #if 0 /* This fails for serial-line connections to the X server,
4021 because the characters arrive one by one, and a partial
4022 command makes select return but gives nothing to read.
4023 We'll have to hope that the bug that this tried to fix
4024 in 1988 has been fixed in Xlib or the X server. */
4026 if (expected
&& ! event_found
)
4028 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4029 there is an EOF condition; in other words, that X has died.
4030 Act as if there had been a hangup. */
4031 int fd
= ConnectionNumber (x_current_display
);
4032 SELECT_TYPE mask
, junk1
, junk2
;
4037 EMACS_SET_SECS_USECS (timeout
, 0, 0);
4040 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
4041 && !XStuffPending ())
4042 kill (getpid (), SIGHUP
);
4044 #endif /* HAVE_SELECT */
4048 if (updating_frame
== 0)
4049 x_do_pending_expose ();
4057 /* Read and process only Expose events
4058 until we get an ExposeCopy event; then return.
4059 This is used in insert/delete line.
4060 We assume input is already blocked. */
4066 XKeyPressedEvent event
;
4070 /* while there are more events*/
4071 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
4075 if (event
.subwindow
!= 0)
4076 break; /* duplicate event */
4077 f
= x_window_to_frame (event
.window
);
4078 if (event
.window
== f
->display
.x
->icon_desc
)
4083 if (event
.window
== FRAME_X_WINDOW (f
))
4085 expose_all_windows
= 1;
4086 f
->display
.x
->needs_exposure
= 1;
4092 if (event
.subwindow
!= 0)
4093 break; /* duplicate event */
4094 f
= x_window_to_frame (event
.window
);
4095 if (event
.window
== f
->display
.x
->icon_desc
)
4100 /* If window already needs full redraw, ignore this rectangle. */
4101 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
4103 /* Put the event on the queue of rectangles to redraw. */
4104 if (enqueue_event (&event
, &x_expose_queue
))
4105 /* If it is full, we can't record the rectangle,
4106 so redraw this entire window. */
4108 /* Say must check all windows' needs_exposure flags. */
4109 expose_all_windows
= 1;
4110 f
->display
.x
->needs_exposure
= 1;
4119 #endif /* HAVE_X11 */
4122 /* Drawing the cursor. */
4125 /* Draw a hollow box cursor. Don't change the inside of the box. */
4131 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
4132 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
4133 int width
= FONT_WIDTH (f
->display
.x
->font
);
4134 int height
= FONT_HEIGHT (f
->display
.x
->font
);
4137 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4138 f
->display
.x
->cursor_gc
,
4139 left
, top
, width
- 1, height
- 1);
4140 #else /* ! defined (HAVE_X11) */
4141 XPixSet (FRAME_X_WINDOW (f
),
4142 left
, top
, width
, 1,
4143 f
->display
.x
->cursor_pixel
);
4145 XPixSet (FRAME_X_WINDOW (f
),
4146 left
, top
, 1, height
,
4147 f
->display
.x
->cursor_pixel
);
4149 XPixSet (FRAME_X_WINDOW (f
),
4150 left
+width
-1, top
, 1, height
,
4151 f
->display
.x
->cursor_pixel
);
4153 XPixSet (FRAME_X_WINDOW (f
),
4154 left
, top
+height
-1, width
, 1,
4155 f
->display
.x
->cursor_pixel
);
4156 #endif /* ! defined (HAVE_X11) */
4159 /* Clear the cursor of frame F to background color,
4160 and mark the cursor as not shown.
4161 This is used when the text where the cursor is
4162 is about to be rewritten. */
4170 if (! FRAME_VISIBLE_P (f
)
4171 || f
->phys_cursor_x
< 0)
4175 x_display_cursor (f
, 0);
4176 #else /* ! defined (HAVE_X11) */
4177 XPixSet (FRAME_X_WINDOW (f
),
4178 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4179 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4180 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
4181 f
->display
.x
->background_pixel
);
4182 #endif /* ! defined (HAVE_X11) */
4183 f
->phys_cursor_x
= -1;
4186 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4187 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4191 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4198 CHAR_TO_PIXEL_COL (f
, column
),
4199 CHAR_TO_PIXEL_ROW (f
, row
),
4200 &glyph
, 1, highlight
);
4204 x_display_bar_cursor (f
, on
)
4208 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4210 /* This is pointless on invisible frames, and dangerous on garbaged
4211 frames; in the latter case, the frame may be in the midst of
4212 changing its size, and curs_x and curs_y may be off the frame. */
4213 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4216 if (! on
&& f
->phys_cursor_x
< 0)
4219 /* If we're not updating, then we want to use the current frame's
4220 cursor position, not our local idea of where the cursor ought to be. */
4221 if (f
!= updating_frame
)
4223 curs_x
= FRAME_CURSOR_X (f
);
4224 curs_y
= FRAME_CURSOR_Y (f
);
4227 /* If there is anything wrong with the current cursor state, remove it. */
4228 if (f
->phys_cursor_x
>= 0
4230 || f
->phys_cursor_x
!= curs_x
4231 || f
->phys_cursor_y
!= curs_y
4232 || f
->display
.x
->current_cursor
!= bar_cursor
))
4234 /* Erase the cursor by redrawing the character underneath it. */
4235 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4236 f
->phys_cursor_glyph
,
4237 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4238 f
->phys_cursor_x
= -1;
4241 /* If we now need a cursor in the new place or in the new form, do it so. */
4243 && (f
->phys_cursor_x
< 0
4244 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4246 f
->phys_cursor_glyph
4247 = ((current_glyphs
->enable
[curs_y
]
4248 && curs_x
< current_glyphs
->used
[curs_y
])
4249 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4251 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4252 f
->display
.x
->cursor_gc
,
4253 CHAR_TO_PIXEL_COL (f
, curs_x
),
4254 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4255 1, FONT_HEIGHT (f
->display
.x
->font
));
4257 f
->phys_cursor_x
= curs_x
;
4258 f
->phys_cursor_y
= curs_y
;
4260 f
->display
.x
->current_cursor
= bar_cursor
;
4263 if (updating_frame
!= f
)
4268 /* Turn the displayed cursor of frame F on or off according to ON.
4269 If ON is nonzero, where to put the cursor is specified
4270 by F->cursor_x and F->cursor_y. */
4273 x_display_box_cursor (f
, on
)
4277 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4279 /* This is pointless on invisible frames, and dangerous on garbaged
4280 frames; in the latter case, the frame may be in the midst of
4281 changing its size, and curs_x and curs_y may be off the frame. */
4282 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4285 /* If cursor is off and we want it off, return quickly. */
4286 if (!on
&& f
->phys_cursor_x
< 0)
4289 /* If we're not updating, then we want to use the current frame's
4290 cursor position, not our local idea of where the cursor ought to be. */
4291 if (f
!= updating_frame
)
4293 curs_x
= FRAME_CURSOR_X (f
);
4294 curs_y
= FRAME_CURSOR_Y (f
);
4297 /* If cursor is currently being shown and we don't want it to be
4298 or it is in the wrong place,
4299 or we want a hollow box and it's not so, (pout!)
4301 if (f
->phys_cursor_x
>= 0
4303 || f
->phys_cursor_x
!= curs_x
4304 || f
->phys_cursor_y
!= curs_y
4305 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4306 && (f
!= x_highlight_frame
))))
4308 /* Erase the cursor by redrawing the character underneath it. */
4309 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4310 f
->phys_cursor_glyph
,
4311 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4312 f
->phys_cursor_x
= -1;
4315 /* If we want to show a cursor,
4316 or we want a box cursor and it's not so,
4317 write it in the right place. */
4319 && (f
->phys_cursor_x
< 0
4320 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4321 && f
== x_highlight_frame
)))
4323 f
->phys_cursor_glyph
4324 = ((current_glyphs
->enable
[curs_y
]
4325 && curs_x
< current_glyphs
->used
[curs_y
])
4326 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4328 if (f
!= x_highlight_frame
)
4331 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4335 x_draw_single_glyph (f
, curs_y
, curs_x
,
4336 f
->phys_cursor_glyph
, 2);
4337 f
->display
.x
->current_cursor
= filled_box_cursor
;
4340 f
->phys_cursor_x
= curs_x
;
4341 f
->phys_cursor_y
= curs_y
;
4344 if (updating_frame
!= f
)
4348 x_display_cursor (f
, on
)
4354 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4355 x_display_box_cursor (f
, on
);
4356 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4357 x_display_bar_cursor (f
, on
);
4359 /* Those are the only two we have implemented! */
4367 /* Refresh bitmap kitchen sink icon for frame F
4368 when we get an expose event for it. */
4374 /* Normally, the window manager handles this function. */
4375 #else /* ! defined (HAVE_X11) */
4378 if (f
->display
.x
->icon_bitmap_flag
)
4379 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
4380 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
4381 icon_bitmap
, GXcopy
, AllPlanes
);
4384 extern struct frame
*selected_frame
;
4385 struct Lisp_String
*str
;
4386 unsigned char *string
;
4389 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
4391 if (f
->display
.x
->icon_label
!= string
)
4393 f
->display
.x
->icon_label
= string
;
4394 XChangeWindow (f
->display
.x
->icon_desc
,
4395 XQueryWidth (string
, icon_font_info
->id
) + 10,
4396 icon_font_info
->height
+ 10);
4399 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4400 str
->size
, icon_font_info
->id
,
4401 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4404 #endif /* ! defined (HAVE_X11) */
4407 /* Make the x-window of frame F use the gnu icon bitmap. */
4416 if (FRAME_X_WINDOW (f
) == 0)
4422 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4423 gnu_bits
, gnu_width
, gnu_height
);
4424 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4425 f
->display
.x
->icon_bitmap_flag
= 1;
4426 #else /* ! defined (HAVE_X11) */
4427 if (f
->display
.x
->icon_desc
)
4429 XClearIconWindow (FRAME_X_WINDOW (f
));
4430 XDestroyWindow (f
->display
.x
->icon_desc
);
4433 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4434 0, 0, sink_width
, sink_height
,
4435 2, WhitePixmap
, (Pixmap
) NULL
);
4437 if (icon_window
== 0)
4440 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4441 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4443 f
->display
.x
->icon_desc
= icon_window
;
4444 f
->display
.x
->icon_bitmap_flag
= 1;
4446 if (icon_bitmap
== 0)
4448 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4449 #endif /* ! defined (HAVE_X11) */
4455 /* Make the x-window of frame F use a rectangle with text. */
4458 x_text_icon (f
, icon_name
)
4466 char *X_DefaultValue
;
4470 #define WhitePixel 1
4471 #endif /* WhitePixel */
4474 #define BlackPixel 0
4475 #endif /* BlackPixel */
4476 #endif /* HAVE_X11 */
4478 if (FRAME_X_WINDOW (f
) == 0)
4483 f
->display
.x
->icon_label
= icon_name
;
4485 if (! f
->display
.x
->icon_label
)
4486 f
->display
.x
->icon_label
= " *emacs* ";
4489 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4490 (char *) f
->display
.x
->icon_label
);
4493 f
->display
.x
->icon_bitmap_flag
= 0;
4494 x_wm_set_icon_pixmap (f
, 0);
4495 #else /* ! defined (HAVE_X11) */
4496 if (icon_font_info
== 0)
4498 = XGetFont (XGetDefault (XDISPLAY
4499 (char *) XSTRING (Vinvocation_name
)->data
,
4502 if (f
->display
.x
->icon_desc
)
4504 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4505 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4509 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4511 if (! f
->display
.x
->icon_label
)
4512 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4514 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4515 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4516 f
->display
.x
->left_pos
,
4517 f
->display
.x
->top_pos
,
4518 width
+ 10, icon_font_info
->height
+ 10,
4519 2, BlackPixmap
, WhitePixmap
);
4521 if (icon_window
== 0)
4524 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4525 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4527 f
->display
.x
->icon_desc
= icon_window
;
4528 f
->display
.x
->icon_bitmap_flag
= 0;
4529 f
->display
.x
->icon_label
= 0;
4530 #endif /* ! defined (HAVE_X11) */
4535 /* Handling X errors. */
4537 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4538 X server's connection, or an error reported via the X protocol. */
4541 x_connection_closed ()
4546 shut_down_emacs (0, 1, Qnil
);
4551 /* An X error handler which prints an error message and then kills
4552 Emacs. This is what's normally installed as Xlib's handler for
4555 x_error_quitter (display
, error
)
4561 /* Note that there is no real way portable across R3/R4 to get the
4562 original error handler. */
4564 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4565 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4566 buf
, error
->request_code
);
4569 /* While we're testing Emacs 19, we'll just dump core whenever we
4570 get an X error, so we can figure out why it happened. */
4574 x_connection_closed ();
4577 /* A handler for X IO errors which prints an error message and then
4578 kills Emacs. This is what is always installed as Xlib's handler
4581 x_io_error_quitter (display
)
4584 fprintf (stderr
, "Connection to X server %s lost.\n",
4585 XDisplayName (DisplayString (display
)));
4588 /* While we're testing Emacs 19, we'll just dump core whenever we
4589 get an X error, so we can figure out why it happened. */
4593 x_connection_closed ();
4596 /* A buffer for storing X error messages. */
4597 static char *x_caught_error_message
;
4598 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4600 /* An X error handler which stores the error message in
4601 x_caught_error_message. This is what's installed when
4602 x_catch_errors is in effect. */
4604 x_error_catcher (display
, error
)
4608 XGetErrorText (display
, error
->error_code
,
4609 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4613 /* Begin trapping X errors.
4615 After calling this function, X protocol errors no longer cause
4616 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4618 Calling x_check_errors signals an Emacs error if an X error has
4619 occurred since the last call to x_catch_errors or x_check_errors.
4621 Calling x_uncatch_errors resumes the normal error handling. */
4623 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4628 /* Make sure any errors from previous requests have been dealt with. */
4629 XSync (x_current_display
, False
);
4631 /* Set up the error buffer. */
4632 x_caught_error_message
4633 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4634 x_caught_error_message
[0] = '\0';
4636 /* Install our little error handler. */
4637 XHandleError (x_error_catcher
);
4640 /* If any X protocol errors have arrived since the last call to
4641 x_catch_errors or x_check_errors, signal an Emacs error using
4642 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4645 x_check_errors (format
)
4648 /* Make sure to catch any errors incurred so far. */
4649 XSync (x_current_display
, False
);
4651 if (x_caught_error_message
[0])
4653 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4655 sprintf (buf
, format
, x_caught_error_message
);
4656 x_uncatch_errors ();
4661 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4666 /* Make sure to catch any errors incurred so far. */
4667 XSync (x_current_display
, False
);
4669 return x_caught_error_message
[0] != 0;
4672 /* Stop catching X protocol errors and let them make Emacs die. */
4677 xfree (x_caught_error_message
);
4678 x_caught_error_message
= 0;
4679 XHandleError (x_error_quitter
);
4683 static unsigned int x_wire_count
;
4686 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4691 /* Changing the font of the frame. */
4693 /* Set the font of the x-window specified by frame F
4694 to the font named NEWNAME. This is safe to use
4695 even before F has an actual x-window. */
4705 /* A table of all the fonts we have already loaded. */
4706 static struct font_info
*x_font_table
;
4708 /* The current capacity of x_font_table. */
4709 static int x_font_table_size
;
4711 /* The number of fonts actually stored in x_font_table.
4712 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4713 0 <= n_fonts <= x_font_table_size. */
4717 x_new_font (f
, fontname
)
4719 register char *fontname
;
4722 int n_matching_fonts
;
4723 XFontStruct
*font_info
;
4726 /* Get a list of all the fonts that match this name. Once we
4727 have a list of matching fonts, we compare them against the fonts
4728 we already have by comparing font ids. */
4729 font_names
= (char **) XListFonts (x_current_display
, fontname
,
4730 1024, &n_matching_fonts
);
4731 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4732 find any matches; font_names == 0 is the only clue. */
4734 n_matching_fonts
= 0;
4736 /* Don't just give up if n_matching_fonts is 0.
4737 Apparently there's a bug on Suns: XListFontsWithInfo can
4738 fail to find a font, but XLoadQueryFont may still find it. */
4740 /* See if we've already loaded a matching font. */
4741 already_loaded
= -1;
4742 if (n_matching_fonts
!= 0)
4746 for (i
= 0; i
< n_fonts
; i
++)
4747 for (j
= 0; j
< n_matching_fonts
; j
++)
4748 if (!strcmp (x_font_table
[i
].name
, font_names
[j
]))
4751 fontname
= font_names
[j
];
4757 /* If we have, just return it from the table. */
4758 if (already_loaded
>= 0)
4759 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
4761 /* Otherwise, load the font and add it to the table. */
4767 /* Try to find a character-cell font in the list. */
4769 /* A laudable goal, but this isn't how to do it. */
4770 for (i
= 0; i
< n_matching_fonts
; i
++)
4771 if (! font_info
[i
].per_char
)
4777 /* See comment above. */
4778 if (n_matching_fonts
!= 0)
4779 fontname
= font_names
[i
];
4781 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
4784 /* Free the information from XListFonts. */
4785 if (n_matching_fonts
)
4786 XFreeFontNames (font_names
);
4790 /* Do we need to create the table? */
4791 if (x_font_table_size
== 0)
4793 x_font_table_size
= 16;
4795 = (struct font_info
*) xmalloc (x_font_table_size
4796 * sizeof (x_font_table
[0]));
4798 /* Do we need to grow the table? */
4799 else if (n_fonts
>= x_font_table_size
)
4801 x_font_table_size
*= 2;
4803 = (struct font_info
*) xrealloc (x_font_table
,
4805 * sizeof (x_font_table
[0])));
4808 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4809 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4810 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
4813 /* Now make the frame display the given font. */
4814 if (FRAME_X_WINDOW (f
) != 0)
4816 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
4817 f
->display
.x
->font
->fid
);
4818 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
4819 f
->display
.x
->font
->fid
);
4820 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
4821 f
->display
.x
->font
->fid
);
4823 x_set_window_size (f
, 0, f
->width
, f
->height
);
4827 Lisp_Object lispy_name
;
4829 lispy_name
= build_string (fontname
);
4831 /* Free the information from XListFonts. The data
4832 we actually retain comes from XLoadQueryFont. */
4833 XFreeFontNames (font_names
);
4838 #else /* ! defined (HAVE_X11) */
4839 x_new_font (f
, newname
)
4841 register char *newname
;
4846 temp
= XGetFont (newname
);
4847 if (temp
== (FONT_TYPE
*) 0)
4850 if (f
->display
.x
->font
)
4851 XLoseFont (f
->display
.x
->font
);
4853 f
->display
.x
->font
= temp
;
4855 if (FRAME_X_WINDOW (f
) != 0)
4856 x_set_window_size (f
, 0, f
->width
, f
->height
);
4860 #endif /* ! defined (HAVE_X11) */
4862 x_calc_absolute_position (f
)
4867 int win_x
= 0, win_y
= 0;
4869 /* Find the position of the outside upper-left corner of
4870 the inner window, with respect to the outer window. */
4871 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
4874 XTranslateCoordinates (x_current_display
,
4876 /* From-window, to-window. */
4877 f
->display
.x
->window_desc
,
4878 f
->display
.x
->parent_desc
,
4880 /* From-position, to-position. */
4881 0, 0, &win_x
, &win_y
,
4888 /* Treat negative positions as relative to the leftmost bottommost
4889 position that fits on the screen. */
4890 if (f
->display
.x
->left_pos
< 0)
4891 f
->display
.x
->left_pos
= (x_screen_width
4892 - 2 * f
->display
.x
->border_width
- win_x
4894 + f
->display
.x
->left_pos
);
4896 if (f
->display
.x
->top_pos
< 0)
4897 f
->display
.x
->top_pos
= (x_screen_height
4898 - 2 * f
->display
.x
->border_width
- win_y
4900 + f
->display
.x
->top_pos
);
4902 #else /* ! defined (HAVE_X11) */
4903 WINDOWINFO_TYPE parentinfo
;
4905 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
4907 if (f
->display
.x
->left_pos
< 0)
4908 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
4909 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
4911 if (f
->display
.x
->top_pos
< 0)
4912 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
4913 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
4914 #endif /* ! defined (HAVE_X11) */
4917 x_set_offset (f
, xoff
, yoff
)
4919 register int xoff
, yoff
;
4921 f
->display
.x
->top_pos
= yoff
;
4922 f
->display
.x
->left_pos
= xoff
;
4923 x_calc_absolute_position (f
);
4926 #ifdef USE_X_TOOLKIT
4927 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
4928 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4929 #else /* not USE_X_TOOLKIT */
4930 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4931 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4932 #endif /* not USE_X_TOOLKIT */
4934 x_wm_set_size_hint (f
, 0, 1, xoff
, yoff
);
4935 #endif /* ! defined (HAVE_X11) */
4939 /* Call this to change the size of frame F's x-window.
4940 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4941 for this size change and subsequent size changes.
4942 Otherwise we leave the window gravity unchanged. */
4944 x_set_window_size (f
, change_gravity
, cols
, rows
)
4949 int pixelwidth
, pixelheight
;
4952 #ifdef USE_X_TOOLKIT
4954 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4957 #else /* not USE_X_TOOLKIT */
4961 check_frame_size (f
, &rows
, &cols
);
4962 f
->display
.x
->vertical_scroll_bar_extra
4963 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4964 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
4966 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4967 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4970 x_wm_set_size_hint (f
, 0, change_gravity
, 0, 0);
4971 #endif /* ! defined (HAVE_X11) */
4972 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4974 /* Now, strictly speaking, we can't be sure that this is accurate,
4975 but the window manager will get around to dealing with the size
4976 change request eventually, and we'll hear how it went when the
4977 ConfigureNotify event gets here.
4979 We could just not bother storing any of this information here,
4980 and let the ConfigureNotify event set everything up, but that
4981 might be kind of confusing to the lisp code, since size changes
4982 wouldn't be reported in the frame parameters until some random
4983 point in the future when the ConfigureNotify event arrives. */
4984 change_frame_size (f
, rows
, cols
, 0, 0);
4985 PIXEL_WIDTH (f
) = pixelwidth
;
4986 PIXEL_HEIGHT (f
) = pixelheight
;
4988 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4989 receive in the ConfigureNotify event; if we get what we asked
4990 for, then the event won't cause the screen to become garbaged, so
4991 we have to make sure to do it here. */
4992 SET_FRAME_GARBAGED (f
);
4996 #endif /* not USE_X_TOOLKIT */
5000 x_set_resize_hint (f
)
5003 XSetResizeHint (FRAME_X_WINDOW (f
),
5004 2 * f
->display
.x
->internal_border_width
,
5005 2 * f
->display
.x
->internal_border_width
,
5006 FONT_WIDTH (f
->display
.x
->font
),
5007 FONT_HEIGHT (f
->display
.x
->font
));
5009 #endif /* HAVE_X11 */
5011 /* Mouse warping, focus shifting, raising and lowering. */
5013 x_set_mouse_position (f
, x
, y
)
5019 #if 0 /* Let the user ask for this if he wants it. */
5023 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
5024 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
5026 if (pix_x
< 0) pix_x
= 0;
5027 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5029 if (pix_y
< 0) pix_y
= 0;
5030 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5034 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5039 x_focus_on_frame (f
)
5042 #if 0 /* This proves to be unpleasant. */
5046 /* I don't think that the ICCCM allows programs to do things like this
5047 without the interaction of the window manager. Whatever you end up
5048 doing with this code, do it to x_unfocus_frame too. */
5049 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
5050 RevertToPointerRoot
, CurrentTime
);
5058 /* Look at the remarks in x_focus_on_frame. */
5059 if (x_focus_frame
== f
)
5060 XSetInputFocus (x_current_display
, PointerRoot
,
5061 RevertToPointerRoot
, CurrentTime
);
5065 #endif /* ! defined (HAVE_X11) */
5067 /* Raise frame F. */
5072 if (f
->async_visible
)
5075 #ifdef USE_X_TOOLKIT
5076 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5077 #else /* not USE_X_TOOLKIT */
5078 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5079 #endif /* not USE_X_TOOLKIT */
5085 /* Lower frame F. */
5090 if (f
->async_visible
)
5093 #ifdef USE_X_TOOLKIT
5094 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5095 #else /* not USE_X_TOOLKIT */
5096 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5097 #endif /* not USE_X_TOOLKIT */
5104 XTframe_raise_lower (f
, raise
)
5115 /* Change from withdrawn state to mapped state. */
5117 x_make_frame_visible (f
)
5124 if (! FRAME_VISIBLE_P (f
))
5127 if (! EQ (Vx_no_window_manager
, Qt
))
5128 x_wm_set_window_state (f
, NormalState
);
5129 #ifdef USE_X_TOOLKIT
5130 XtPopup (f
->display
.x
->widget
, XtGrabNone
);
5131 #else /* not USE_X_TOOLKIT */
5132 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5133 #endif /* not USE_X_TOOLKIT */
5134 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5135 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5136 #else /* ! defined (HAVE_X11) */
5137 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5138 if (f
->display
.x
->icon_desc
!= 0)
5139 XUnmapWindow (f
->display
.x
->icon_desc
);
5141 /* Handled by the MapNotify event for X11 */
5142 f
->async_visible
= 1;
5143 f
->async_iconified
= 0;
5145 /* NOTE: this may cause problems for the first frame. */
5147 #endif /* ! defined (HAVE_X11) */
5155 /* Change from mapped state to withdrawn state. */
5157 x_make_frame_invisible (f
)
5162 /* Don't keep the highlight on an invisible frame. */
5163 if (x_highlight_frame
== f
)
5164 x_highlight_frame
= 0;
5166 if (! f
->async_visible
&& ! f
->async_iconified
)
5173 #ifdef USE_X_TOOLKIT
5174 if (! XWithdrawWindow (x_current_display
, XtWindow (f
->display
.x
->widget
),
5175 DefaultScreen (x_current_display
)))
5176 #else /* not USE_X_TOOLKIT */
5177 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
5178 DefaultScreen (x_current_display
)))
5179 #endif /* not USE_X_TOOLKIT */
5181 UNBLOCK_INPUT_RESIGNAL
;
5182 error ("can't notify window manager of window withdrawal");
5185 #else /* ! defined (HAVE_X11R4) */
5188 /* Tell the window manager what we're going to do. */
5189 if (! EQ (Vx_no_window_manager
, Qt
))
5193 unmap
.xunmap
.type
= UnmapNotify
;
5194 #ifdef USE_X_TOOLKIT
5195 unmap
.xunmap
.window
= XtWindow (f
->display
.x
->widget
);
5196 #else /* not USE_X_TOOLKIT */
5197 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
5198 #endif /* not USE_X_TOOLKIT */
5199 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5200 unmap
.xunmap
.from_configure
= False
;
5201 if (! XSendEvent (x_current_display
,
5202 DefaultRootWindow (x_current_display
),
5204 SubstructureRedirectMask
|SubstructureNotifyMask
,
5207 UNBLOCK_INPUT_RESIGNAL
;
5208 error ("can't notify window manager of withdrawal");
5212 /* Unmap the window ourselves. Cheeky! */
5213 #ifdef USE_X_TOOLKIT
5214 XUnmapWindow (x_current_display
, XtWindow (f
->display
.x
->widget
));
5215 #else /* not USE_X_TOOLKIT */
5216 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
5217 #endif /* not USE_X_TOOLKIT */
5218 #else /* ! defined (HAVE_X11) */
5220 XUnmapWindow (FRAME_X_WINDOW (f
));
5221 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
5222 if (f
->display
.x
->icon_desc
!= 0)
5223 XUnmapWindow (f
->display
.x
->icon_desc
);
5225 #endif /* ! defined (HAVE_X11) */
5226 #endif /* ! defined (HAVE_X11R4) */
5232 /* Change window state from mapped to iconified. */
5240 /* Don't keep the highlight on an invisible frame. */
5241 if (x_highlight_frame
== f
)
5242 x_highlight_frame
= 0;
5244 if (f
->async_iconified
)
5247 #ifdef USE_X_TOOLKIT
5249 result
= XIconifyWindow (x_current_display
,
5250 XtWindow (f
->display
.x
->widget
),
5251 DefaultScreen (x_current_display
));
5255 error ("Can't notify window manager of iconification.");
5257 f
->async_iconified
= 1;
5262 #else /* not USE_X_TOOLKIT */
5267 /* Since we don't know which revision of X we're running, we'll use both
5268 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5270 /* X11R4: send a ClientMessage to the window manager using the
5271 WM_CHANGE_STATE type. */
5275 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5276 message
.xclient
.type
= ClientMessage
;
5277 message
.xclient
.message_type
= Xatom_wm_change_state
;
5278 message
.xclient
.format
= 32;
5279 message
.xclient
.data
.l
[0] = IconicState
;
5281 if (! XSendEvent (x_current_display
,
5282 DefaultRootWindow (x_current_display
),
5284 SubstructureRedirectMask
| SubstructureNotifyMask
,
5287 UNBLOCK_INPUT_RESIGNAL
;
5288 error ("Can't notify window manager of iconification.");
5292 /* X11R3: set the initial_state field of the window manager hints to
5294 x_wm_set_window_state (f
, IconicState
);
5296 if (!FRAME_VISIBLE_P (f
))
5298 /* If the frame was withdrawn, before, we must map it. */
5299 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5300 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5301 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5304 f
->async_iconified
= 1;
5305 #else /* ! defined (HAVE_X11) */
5306 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5308 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
5309 if (f
->display
.x
->icon_desc
!= 0)
5311 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
5314 #endif /* ! defined (HAVE_X11) */
5318 #endif /* not USE_X_TOOLKIT */
5321 /* Destroy the X window of frame F. */
5323 x_destroy_window (f
)
5328 if (f
->display
.x
->icon_desc
!= 0)
5329 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5330 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5331 #ifdef USE_X_TOOLKIT
5332 XtDestroyWidget (f
->display
.x
->widget
);
5333 free_frame_menubar (f
);
5334 #endif /* USE_X_TOOLKIT */
5336 free_frame_faces (f
);
5339 xfree (f
->display
.x
);
5341 if (f
== x_focus_frame
)
5343 if (f
== x_highlight_frame
)
5344 x_highlight_frame
= 0;
5349 /* Manage event queues for X10. */
5353 /* Manage event queues.
5355 This code is only used by the X10 support.
5357 We cannot leave events in the X queue and get them when we are ready
5358 because X does not provide a subroutine to get only a certain kind
5359 of event but not block if there are no queued events of that kind.
5361 Therefore, we must examine events as they come in and copy events
5362 of certain kinds into our private queues.
5364 All ExposeRegion events are put in x_expose_queue.
5365 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5368 /* Write the event *P_XREP into the event queue *QUEUE.
5369 If the queue is full, do nothing, but return nonzero. */
5372 enqueue_event (p_xrep
, queue
)
5373 register XEvent
*p_xrep
;
5374 register struct event_queue
*queue
;
5376 int newindex
= queue
->windex
+ 1;
5377 if (newindex
== EVENT_BUFFER_SIZE
)
5379 if (newindex
== queue
->rindex
)
5381 queue
->xrep
[queue
->windex
] = *p_xrep
;
5382 queue
->windex
= newindex
;
5386 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5387 If *QUEUE is empty, do nothing and return 0. */
5390 dequeue_event (p_xrep
, queue
)
5391 register XEvent
*p_xrep
;
5392 register struct event_queue
*queue
;
5394 if (queue
->windex
== queue
->rindex
)
5396 *p_xrep
= queue
->xrep
[queue
->rindex
++];
5397 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
5402 /* Return the number of events buffered in *QUEUE. */
5405 queue_event_count (queue
)
5406 register struct event_queue
*queue
;
5408 int tem
= queue
->windex
- queue
->rindex
;
5411 return EVENT_BUFFER_SIZE
+ tem
;
5414 /* Return nonzero if mouse input is pending. */
5417 mouse_event_pending_p ()
5419 return queue_event_count (&x_mouse_queue
);
5421 #endif /* HAVE_X11 */
5423 /* Setting window manager hints. */
5427 /* Record the gravity used previously, in case CHANGE_GRAVITY is 0. */
5428 static int previous_gravity
;
5430 /* SPEC_X and SPEC_Y are the specified positions.
5431 We look only at their sign, to decide the gravity.
5432 If CHANGE_GRAVITY is 0, we ignore SPEC_X and SPEC_Y
5433 and leave the gravity unchanged. */
5435 x_wm_set_size_hint (f
, prompting
, change_gravity
, spec_x
, spec_y
)
5441 XSizeHints size_hints
;
5443 #ifdef USE_X_TOOLKIT
5444 Window window
= XtWindow (f
->display
.x
->widget
);
5445 #else /* not USE_X_TOOLKIT */
5446 Window window
= FRAME_X_WINDOW (f
);
5447 #endif /* not USE_X_TOOLKIT */
5449 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5451 flexlines
= f
->height
;
5453 size_hints
.x
= f
->display
.x
->left_pos
;
5454 size_hints
.y
= f
->display
.x
->top_pos
;
5455 size_hints
.height
= PIXEL_HEIGHT (f
);
5456 size_hints
.width
= PIXEL_WIDTH (f
);
5457 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5458 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
5460 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5461 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5464 int base_width
, base_height
;
5466 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5467 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5470 int min_rows
= 0, min_cols
= 0;
5471 check_frame_size (f
, &min_rows
, &min_cols
);
5473 /* The window manager uses the base width hints to calculate the
5474 current number of rows and columns in the frame while
5475 resizing; min_width and min_height aren't useful for this
5476 purpose, since they might not give the dimensions for a
5477 zero-row, zero-column frame.
5479 We use the base_width and base_height members if we have
5480 them; otherwise, we set the min_width and min_height members
5481 to the size for a zero x zero frame. */
5484 size_hints
.flags
|= PBaseSize
;
5485 size_hints
.base_width
= base_width
;
5486 size_hints
.base_height
= base_height
;
5487 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5488 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5490 size_hints
.min_width
= base_width
;
5491 size_hints
.min_height
= base_height
;
5498 size_hints
.flags
|= prompting
;
5501 XSizeHints hints
; /* Sometimes I hate X Windows... */
5503 if (XGetNormalHints (x_current_display
, window
, &hints
) == 0)
5505 if (hints
.flags
& PSize
)
5506 size_hints
.flags
|= PSize
;
5507 if (hints
.flags
& PPosition
)
5508 size_hints
.flags
|= PPosition
;
5509 if (hints
.flags
& USPosition
)
5510 size_hints
.flags
|= USPosition
;
5511 if (hints
.flags
& USSize
)
5512 size_hints
.flags
|= USSize
;
5514 #if defined (PWinGravity)
5517 switch (((spec_x
< 0) << 1) + (spec_y
< 0))
5520 size_hints
.win_gravity
= NorthWestGravity
;
5523 size_hints
.win_gravity
= NorthEastGravity
;
5526 size_hints
.win_gravity
= SouthWestGravity
;
5529 size_hints
.win_gravity
= SouthEastGravity
;
5532 previous_gravity
= size_hints
.win_gravity
;
5535 size_hints
.win_gravity
= previous_gravity
;
5537 size_hints
.flags
|= PWinGravity
;
5538 #endif /* PWinGravity */
5541 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
5543 XSetNormalHints (x_current_display
, window
, &size_hints
);
5547 /* Used for IconicState or NormalState */
5548 x_wm_set_window_state (f
, state
)
5552 #ifdef USE_X_TOOLKIT
5553 Window window
= XtWindow (f
->display
.x
->widget
);
5554 #else /* not USE_X_TOOLKIT */
5555 Window window
= FRAME_X_WINDOW (f
);
5556 #endif /* not USE_X_TOOLKIT */
5558 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5559 f
->display
.x
->wm_hints
.initial_state
= state
;
5561 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5564 x_wm_set_icon_pixmap (f
, icon_pixmap
)
5568 Window window
= FRAME_X_WINDOW (f
);
5572 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5573 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5576 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5578 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5581 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5585 Window window
= FRAME_X_WINDOW (f
);
5587 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5588 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5589 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5591 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5595 /* Initialization. */
5597 #ifdef USE_X_TOOLKIT
5598 static XrmOptionDescRec emacs_options
[] = {
5599 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5600 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5602 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5603 XrmoptionSepArg
, NULL
},
5604 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5606 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5607 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5608 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5609 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5610 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5611 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5612 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5614 #endif /* USE_X_TOOLKIT */
5617 x_term_init (display_name
)
5624 #ifndef F_SETOWN_BUG
5626 extern int old_fcntl_owner
;
5627 #endif /* ! defined (F_SETOWN) */
5628 #endif /* F_SETOWN_BUG */
5630 x_focus_frame
= x_highlight_frame
= 0;
5632 #ifdef USE_X_TOOLKIT
5633 argv
= (char **) XtMalloc (3 * sizeof (char *));
5635 argv
[1] = "-display";
5636 argv
[2] = display_name
;
5638 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
5639 emacs_options
, XtNumber (emacs_options
),
5643 x_current_display
= XtDisplay (Xt_app_shell
);
5645 #else /* not USE_X_TOOLKIT */
5646 x_current_display
= XOpenDisplay (display_name
);
5647 #endif /* not USE_X_TOOLKIT */
5648 if (x_current_display
== 0)
5649 fatal ("X server %s not responding.\n\
5650 Check the DISPLAY environment variable or use \"-d\"\n",
5656 XSetAfterFunction (x_current_display
, x_trace_wire
);
5658 hostname
= get_system_name ();
5659 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5662 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
5665 /* Figure out which modifier bits mean what. */
5666 x_find_modifier_meanings ();
5668 /* Get the scroll bar cursor. */
5669 x_vertical_scroll_bar_cursor
5670 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
5673 /* Watch for PropertyNotify events on the root window; we use them
5674 to figure out when to invalidate our cache of the cut buffers. */
5675 x_watch_cut_buffer_cache ();
5678 if (ConnectionNumber (x_current_display
) != 0)
5679 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
5680 change_input_fd (ConnectionNumber (x_current_display
));
5682 #endif /* ! defined (HAVE_X11) */
5684 #ifndef F_SETOWN_BUG
5686 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
5687 #ifdef F_SETOWN_SOCK_NEG
5688 /* stdin is a socket here */
5689 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
5690 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5691 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
5692 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5693 #endif /* ! defined (F_SETOWN) */
5694 #endif /* F_SETOWN_BUG */
5698 #endif /* ! defined (SIGIO) */
5700 expose_all_windows
= 0;
5702 clear_frame_hook
= XTclear_frame
;
5703 clear_end_of_line_hook
= XTclear_end_of_line
;
5704 ins_del_lines_hook
= XTins_del_lines
;
5705 change_line_highlight_hook
= XTchange_line_highlight
;
5706 insert_glyphs_hook
= XTinsert_glyphs
;
5707 write_glyphs_hook
= XTwrite_glyphs
;
5708 delete_glyphs_hook
= XTdelete_glyphs
;
5709 ring_bell_hook
= XTring_bell
;
5710 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5711 set_terminal_modes_hook
= XTset_terminal_modes
;
5712 update_begin_hook
= XTupdate_begin
;
5713 update_end_hook
= XTupdate_end
;
5714 set_terminal_window_hook
= XTset_terminal_window
;
5715 read_socket_hook
= XTread_socket
;
5716 frame_up_to_date_hook
= XTframe_up_to_date
;
5717 cursor_to_hook
= XTcursor_to
;
5718 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5719 mouse_position_hook
= XTmouse_position
;
5720 frame_rehighlight_hook
= XTframe_rehighlight
;
5721 frame_raise_lower_hook
= XTframe_raise_lower
;
5722 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5723 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5724 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5725 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5727 scroll_region_ok
= 1; /* we'll scroll partial frames */
5728 char_ins_del_ok
= 0; /* just as fast to write the line */
5729 line_ins_del_ok
= 1; /* we'll just blt 'em */
5730 fast_clear_end_of_line
= 1; /* X does this well */
5731 memory_below_frame
= 0; /* we don't remember what scrolls
5735 /* Try to use interrupt input; if we can't, then start polling. */
5736 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5738 /* Note that there is no real way portable across R3/R4 to get the
5739 original error handler. */
5740 XHandleError (x_error_quitter
);
5741 XHandleIOError (x_io_error_quitter
);
5743 /* Disable Window Change signals; they are handled by X events. */
5745 signal (SIGWINCH
, SIG_DFL
);
5746 #endif /* ! defined (SIGWINCH) */
5748 signal (SIGPIPE
, x_connection_closed
);
5754 staticpro (&last_mouse_scroll_bar
);
5755 last_mouse_scroll_bar
= Qnil
;
5756 staticpro (&mouse_face_window
);
5757 mouse_face_window
= Qnil
;
5759 #endif /* ! defined (HAVE_X11) */
5760 #endif /* ! defined (HAVE_X_WINDOWS) */