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 /* This is used for debugging, to turn off note_mouse_highlight. */
1916 static int disable_mouse_highlight
;
1918 /* Take proper action when the mouse has moved to position X, Y on frame F
1919 as regards highlighting characters that have mouse-face properties.
1920 Also dehighlighting chars where the mouse was before. */
1923 note_mouse_highlight (f
, x
, y
)
1926 int row
, column
, portion
;
1927 XRectangle new_glyph
;
1931 if (disable_mouse_highlight
)
1934 mouse_face_mouse_x
= x
;
1935 mouse_face_mouse_y
= y
;
1936 mouse_face_mouse_frame
= f
;
1938 if (mouse_face_defer
)
1941 /* Find out which glyph the mouse is on. */
1942 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1943 &new_glyph
, x_mouse_grabbed
);
1945 /* Which window is that in? */
1946 window
= window_from_coordinates (f
, column
, row
, &portion
);
1947 w
= XWINDOW (window
);
1949 /* If we were displaying active text in another window, clear that. */
1950 if (! EQ (window
, mouse_face_window
))
1951 clear_mouse_face ();
1953 /* Are we in a window whose display is up to date? */
1954 if (WINDOWP (window
) && portion
== 0
1955 && EQ (w
->window_end_valid
, Qt
))
1957 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1960 /* Find which buffer position the mouse corresponds to. */
1961 for (i
= column
; i
>= 0; i
--)
1965 /* Is it outside the displayed active region (if any)? */
1967 && ! (EQ (window
, mouse_face_window
)
1968 && pos
>= mouse_face_beg
&& pos
< mouse_face_end
))
1970 Lisp_Object mouse_face
, overlay
, position
;
1971 Lisp_Object
*overlay_vec
;
1972 int len
, noverlays
, ignor1
;
1973 struct buffer
*obuf
;
1975 /* If we get an out-of-range value, return now;
1976 don't get an error. */
1977 if (pos
> BUF_ZV (XBUFFER (w
->buffer
)))
1980 /* Make the window's buffer temporarily current for
1981 overlays_at and compute_char_face. */
1982 obuf
= current_buffer
;
1983 current_buffer
= XBUFFER (w
->buffer
);
1985 /* Yes. Clear the display of the old active region, if any. */
1986 clear_mouse_face ();
1988 /* Is this char mouse-active? */
1989 XSET (position
, Lisp_Int
, pos
);
1992 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1994 /* Put all the overlays we want in a vector in overlay_vec.
1995 Store the length in len. */
1996 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
, &ignor1
);
1997 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1999 /* Find the highest priority overlay that has a mouse-face prop. */
2001 for (i
= 0; i
< noverlays
; i
++)
2003 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2004 if (!NILP (mouse_face
))
2006 overlay
= overlay_vec
[i
];
2011 /* If no overlay applies, get a text property. */
2013 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2015 /* Handle the overlay case. */
2016 if (! NILP (overlay
))
2018 /* Find the range of text around this char that
2019 should be active. */
2020 Lisp_Object before
, after
;
2023 before
= Foverlay_start (overlay
);
2024 after
= Foverlay_end (overlay
);
2025 /* Record this as the current active region. */
2026 mouse_face_beg
= XFASTINT (before
);
2027 mouse_face_end
= XFASTINT (after
);
2028 mouse_face_window
= window
;
2029 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
2030 &ignore
, pos
+ 1, 1);
2032 /* Display it as active. */
2033 show_mouse_face (1);
2035 /* Handle the text property case. */
2036 else if (! NILP (mouse_face
))
2038 /* Find the range of text around this char that
2039 should be active. */
2040 Lisp_Object before
, after
, beginning
, end
;
2043 beginning
= Fmarker_position (w
->start
);
2044 XSET (end
, Lisp_Int
,
2045 (BUF_Z (XBUFFER (w
->buffer
))
2046 - XFASTINT (w
->window_end_pos
)));
2048 = Fprevious_single_property_change (make_number (pos
+ 1),
2050 w
->buffer
, beginning
);
2052 = Fnext_single_property_change (position
, Qmouse_face
,
2054 /* Record this as the current active region. */
2055 mouse_face_beg
= XFASTINT (before
);
2056 mouse_face_end
= XFASTINT (after
);
2057 mouse_face_window
= window
;
2059 = compute_char_face (f
, w
, pos
, 0, 0,
2060 &ignore
, pos
+ 1, 1);
2062 /* Display it as active. */
2063 show_mouse_face (1);
2065 current_buffer
= obuf
;
2068 clear_mouse_face ();
2072 /* Find the row and column of position POS in window WINDOW.
2073 Store them in *COLUMNP and *ROWP.
2074 This assumes display in WINDOW is up to date.
2075 If POS is above start of WINDOW, return coords
2076 of start of first screen line.
2077 If POS is after end of WINDOW, return coords of end of last screen line. */
2080 fast_find_position (window
, pos
, columnp
, rowp
)
2083 int *columnp
, *rowp
;
2085 struct window
*w
= XWINDOW (window
);
2086 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2091 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2092 int width
= window_internal_width (w
);
2100 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2101 if (linestart
> pos
)
2107 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2109 for (i
= 0; i
< width
; i
++)
2111 if (charstarts
[left
+ i
] == pos
)
2114 *columnp
= i
+ left
;
2117 else if (charstarts
[left
+ i
] > pos
)
2126 /* Display the active region described by mouse_face_*
2127 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2130 show_mouse_face (hl
)
2133 int begcol
, begrow
, endcol
, endrow
;
2134 struct window
*w
= XWINDOW (mouse_face_window
);
2135 int width
= window_internal_width (w
);
2136 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2139 fast_find_position (mouse_face_window
, mouse_face_beg
,
2141 fast_find_position (mouse_face_window
, mouse_face_end
,
2144 x_display_cursor (f
, 0);
2146 for (i
= begrow
; i
<= endrow
; i
++)
2148 int column
= (i
== begrow
? begcol
: w
->left
);
2149 int endcolumn
= (i
== endrow
? endcol
: w
->left
+ width
);
2150 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
] - w
->left
),
2153 CHAR_TO_PIXEL_COL (f
, column
),
2154 CHAR_TO_PIXEL_ROW (f
, i
),
2155 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2157 /* Highlight with mouse face if hl > 0. */
2161 x_display_cursor (f
, 1);
2164 /* Clear out the mouse-highlighted active region.
2165 Redraw it unhighlighted first. */
2170 if (! NILP (mouse_face_window
))
2171 show_mouse_face (0);
2173 mouse_face_beg
= -1;
2174 mouse_face_end
= -1;
2175 mouse_face_window
= Qnil
;
2178 static struct scroll_bar
*x_window_to_scroll_bar ();
2179 static void x_scroll_bar_report_motion ();
2181 /* Return the current position of the mouse.
2183 If the mouse movement started in a scroll bar, set *f, *bar_window,
2184 and *part to the frame, window, and scroll bar part that the mouse
2185 is over. Set *x and *y to the portion and whole of the mouse's
2186 position on the scroll bar.
2188 If the mouse movement started elsewhere, set *f to the frame the
2189 mouse is on, *bar_window to nil, and *x and *y to the character cell
2192 Set *time to the server timestamp for the time at which the mouse
2193 was at this position.
2195 Don't store anything if we don't have a valid set of values to report.
2197 This clears the mouse_moved flag, so we can wait for the next mouse
2198 movement. This also calls XQueryPointer, which will cause the
2199 server to give us another MotionNotify when the mouse moves
2203 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
2205 Lisp_Object
*bar_window
;
2206 enum scroll_bar_part
*part
;
2208 unsigned long *time
;
2214 if (! NILP (last_mouse_scroll_bar
))
2215 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
2221 Window dummy_window
;
2225 last_mouse_scroll_bar
= Qnil
;
2227 /* Figure out which root window we're on. */
2228 XQueryPointer (x_current_display
,
2229 DefaultRootWindow (x_current_display
),
2231 /* The root window which contains the pointer. */
2234 /* Trash which we can't trust if the pointer is on
2235 a different screen. */
2238 /* The position on that root window. */
2241 /* More trash we can't trust. */
2244 /* Modifier keys and pointer buttons, about which
2246 (unsigned int *) &dummy
);
2248 /* Now we have a position on the root; find the innermost window
2249 containing the pointer. */
2253 int parent_x
, parent_y
;
2257 if (x_mouse_grabbed
)
2259 /* If mouse was grabbed on a frame, give coords for that frame
2260 even if the mouse is now outside it. */
2261 XTranslateCoordinates (x_current_display
,
2263 /* From-window, to-window. */
2264 root
, FRAME_X_WINDOW (last_mouse_frame
),
2266 /* From-position, to-position. */
2267 root_x
, root_y
, &win_x
, &win_y
,
2271 f1
= last_mouse_frame
;
2277 XTranslateCoordinates (x_current_display
,
2279 /* From-window, to-window. */
2282 /* From-position, to-position. */
2283 root_x
, root_y
, &win_x
, &win_y
,
2296 /* Now we know that:
2297 win is the innermost window containing the pointer
2298 (XTC says it has no child containing the pointer),
2299 win_x and win_y are the pointer's position in it
2300 (XTC did this the last time through), and
2301 parent_x and parent_y are the pointer's position in win's parent.
2302 (They are what win_x and win_y were when win was child.
2303 If win is the root window, it has no parent, and
2304 parent_{x,y} are invalid, but that's okay, because we'll
2305 never use them in that case.) */
2307 /* Is win one of our frames? */
2308 f1
= x_any_window_to_frame (win
);
2311 /* If not, is it one of our scroll bars? */
2314 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2318 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2326 int ignore1
, ignore2
;
2328 /* Ok, we found a frame. Store all the values. */
2330 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2331 &last_mouse_glyph
, x_mouse_grabbed
);
2336 XSET (*x
, Lisp_Int
, win_x
);
2337 XSET (*y
, Lisp_Int
, win_y
);
2338 *time
= last_mouse_movement_time
;
2346 #else /* ! defined (HAVE_X11) */
2347 #define XEvent XKeyPressedEvent
2348 #endif /* ! defined (HAVE_X11) */
2350 /* Scroll bar support. */
2352 /* Given an X window ID, find the struct scroll_bar which manages it.
2353 This can be called in GC, so we have to make sure to strip off mark
2355 static struct scroll_bar
*
2356 x_window_to_scroll_bar (window_id
)
2359 Lisp_Object tail
, frame
;
2361 for (tail
= Vframe_list
;
2362 XGCTYPE (tail
) == Lisp_Cons
;
2363 tail
= XCONS (tail
)->cdr
)
2365 Lisp_Object frame
, bar
, condemned
;
2367 frame
= XCONS (tail
)->car
;
2368 /* All elements of Vframe_list should be frames. */
2369 if (XGCTYPE (frame
) != Lisp_Frame
)
2372 /* Scan this frame's scroll bar list for a scroll bar with the
2374 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2375 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2376 /* This trick allows us to search both the ordinary and
2377 condemned scroll bar lists with one loop. */
2378 ! GC_NILP (bar
) || (bar
= condemned
,
2381 bar
= XSCROLL_BAR (bar
)->next
)
2382 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2383 return XSCROLL_BAR (bar
);
2389 /* Open a new X window to serve as a scroll bar, and return the
2390 scroll bar vector for it. */
2391 static struct scroll_bar
*
2392 x_scroll_bar_create (window
, top
, left
, width
, height
)
2393 struct window
*window
;
2394 int top
, left
, width
, height
;
2396 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2397 struct scroll_bar
*bar
=
2398 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2403 XSetWindowAttributes a
;
2405 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2406 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2407 | ButtonMotionMask
| PointerMotionHintMask
2409 a
.cursor
= x_vertical_scroll_bar_cursor
;
2411 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2416 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2417 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2418 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2419 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2420 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2421 sb_widget
= XtCreateManagedWidget ("box",
2423 frame
->display
.x
->edit_widget
, al
, ac
);
2424 SET_SCROLL_BAR_X_WINDOW
2425 (bar
, sb_widget
->core
.window
);
2427 SET_SCROLL_BAR_X_WINDOW
2429 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2431 /* Position and size of scroll bar. */
2432 left
, top
, width
, height
,
2434 /* Border width, depth, class, and visual. */
2435 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2441 XSET (bar
->window
, Lisp_Window
, window
);
2442 XSET (bar
->top
, Lisp_Int
, top
);
2443 XSET (bar
->left
, Lisp_Int
, left
);
2444 XSET (bar
->width
, Lisp_Int
, width
);
2445 XSET (bar
->height
, Lisp_Int
, height
);
2446 XSET (bar
->start
, Lisp_Int
, 0);
2447 XSET (bar
->end
, Lisp_Int
, 0);
2448 bar
->dragging
= Qnil
;
2450 /* Add bar to its frame's list of scroll bars. */
2451 bar
->next
= FRAME_SCROLL_BARS (frame
);
2453 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2454 if (! NILP (bar
->next
))
2455 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2457 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2464 /* Draw BAR's handle in the proper position.
2465 If the handle is already drawn from START to END, don't bother
2466 redrawing it, unless REBUILD is non-zero; in that case, always
2467 redraw it. (REBUILD is handy for drawing the handle after expose
2470 Normally, we want to constrain the start and end of the handle to
2471 fit inside its rectangle, but if the user is dragging the scroll bar
2472 handle, we want to let them drag it down all the way, so that the
2473 bar's top is as far down as it goes; otherwise, there's no way to
2474 move to the very end of the buffer. */
2476 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2477 struct scroll_bar
*bar
;
2481 int dragging
= ! NILP (bar
->dragging
);
2482 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2483 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2485 /* If the display is already accurate, do nothing. */
2487 && start
== XINT (bar
->start
)
2488 && end
== XINT (bar
->end
))
2494 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2495 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2496 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2498 /* Make sure the values are reasonable, and try to preserve
2499 the distance between start and end. */
2501 int length
= end
- start
;
2505 else if (start
> top_range
)
2507 end
= start
+ length
;
2511 else if (end
> top_range
&& ! dragging
)
2515 /* Store the adjusted setting in the scroll bar. */
2516 XSET (bar
->start
, Lisp_Int
, start
);
2517 XSET (bar
->end
, Lisp_Int
, end
);
2519 /* Clip the end position, just for display. */
2520 if (end
> top_range
)
2523 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2524 below top positions, to make sure the handle is always at least
2525 that many pixels tall. */
2526 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2528 /* Draw the empty space above the handle. Note that we can't clear
2529 zero-height areas; that means "clear to end of window." */
2531 XClearArea (x_current_display
, w
,
2533 /* x, y, width, height, and exposures. */
2534 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2535 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2536 inside_width
, start
,
2539 /* Draw the handle itself. */
2540 XFillRectangle (x_current_display
, w
, gc
,
2542 /* x, y, width, height */
2543 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2544 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2545 inside_width
, end
- start
);
2548 /* Draw the empty space below the handle. Note that we can't
2549 clear zero-height areas; that means "clear to end of window." */
2550 if (end
< inside_height
)
2551 XClearArea (x_current_display
, w
,
2553 /* x, y, width, height, and exposures. */
2554 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2555 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2556 inside_width
, inside_height
- end
,
2564 /* Move a scroll bar around on the screen, to accommodate changing
2565 window configurations. */
2567 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2568 struct scroll_bar
*bar
;
2569 int top
, left
, width
, height
;
2575 unsigned int mask
= 0;
2582 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2583 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2584 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2585 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2588 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2592 XSET (bar
->left
, Lisp_Int
, left
);
2593 XSET (bar
->top
, Lisp_Int
, top
);
2594 XSET (bar
->width
, Lisp_Int
, width
);
2595 XSET (bar
->height
, Lisp_Int
, height
);
2600 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2603 x_scroll_bar_remove (bar
)
2604 struct scroll_bar
*bar
;
2606 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2610 /* Destroy the window. */
2611 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2613 /* Disassociate this scroll bar from its window. */
2614 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2619 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2620 that we are displaying PORTION characters out of a total of WHOLE
2621 characters, starting at POSITION. If WINDOW has no scroll bar,
2624 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2625 struct window
*window
;
2626 int portion
, whole
, position
;
2628 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2629 int top
= XINT (window
->top
);
2630 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2631 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2633 /* Where should this scroll bar be, pixelwise? */
2634 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2635 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2636 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2637 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2639 struct scroll_bar
*bar
;
2641 /* Does the scroll bar exist yet? */
2642 if (NILP (window
->vertical_scroll_bar
))
2643 bar
= x_scroll_bar_create (window
,
2644 pixel_top
, pixel_left
,
2645 pixel_width
, pixel_height
);
2648 /* It may just need to be moved and resized. */
2649 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2650 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2653 /* Set the scroll bar's current state, unless we're currently being
2655 if (NILP (bar
->dragging
))
2658 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2661 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2664 int start
= ((double) position
* top_range
) / whole
;
2665 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2667 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2671 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2675 /* The following three hooks are used when we're doing a thorough
2676 redisplay of the frame. We don't explicitly know which scroll bars
2677 are going to be deleted, because keeping track of when windows go
2678 away is a real pain - "Can you say set-window-configuration, boys
2679 and girls?" Instead, we just assert at the beginning of redisplay
2680 that *all* scroll bars are to be removed, and then save a scroll bar
2681 from the fiery pit when we actually redisplay its window. */
2683 /* Arrange for all scroll bars on FRAME to be removed at the next call
2684 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2685 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2687 XTcondemn_scroll_bars (frame
)
2690 /* The condemned list should be empty at this point; if it's not,
2691 then the rest of Emacs isn't using the condemn/redeem/judge
2692 protocol correctly. */
2693 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2696 /* Move them all to the "condemned" list. */
2697 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2698 FRAME_SCROLL_BARS (frame
) = Qnil
;
2701 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2702 Note that WINDOW isn't necessarily condemned at all. */
2704 XTredeem_scroll_bar (window
)
2705 struct window
*window
;
2707 struct scroll_bar
*bar
;
2709 /* We can't redeem this window's scroll bar if it doesn't have one. */
2710 if (NILP (window
->vertical_scroll_bar
))
2713 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2715 /* Unlink it from the condemned list. */
2717 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2719 if (NILP (bar
->prev
))
2721 /* If the prev pointer is nil, it must be the first in one of
2723 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2724 /* It's not condemned. Everything's fine. */
2726 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2727 window
->vertical_scroll_bar
))
2728 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2730 /* If its prev pointer is nil, it must be at the front of
2731 one or the other! */
2735 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2737 if (! NILP (bar
->next
))
2738 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2740 bar
->next
= FRAME_SCROLL_BARS (f
);
2742 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2743 if (! NILP (bar
->next
))
2744 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2748 /* Remove all scroll bars on FRAME that haven't been saved since the
2749 last call to `*condemn_scroll_bars_hook'. */
2751 XTjudge_scroll_bars (f
)
2754 Lisp_Object bar
, next
;
2756 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2758 /* Clear out the condemned list now so we won't try to process any
2759 more events on the hapless scroll bars. */
2760 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2762 for (; ! NILP (bar
); bar
= next
)
2764 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2766 x_scroll_bar_remove (b
);
2769 b
->next
= b
->prev
= Qnil
;
2772 /* Now there should be no references to the condemned scroll bars,
2773 and they should get garbage-collected. */
2777 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2779 This may be called from a signal handler, so we have to ignore GC
2782 x_scroll_bar_expose (bar
, event
)
2783 struct scroll_bar
*bar
;
2786 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2787 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2791 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2793 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2794 XDrawRectangle (x_current_display
, w
, gc
,
2796 /* x, y, width, height */
2797 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2802 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2803 is set to something other than no_event, it is enqueued.
2805 This may be called from a signal handler, so we have to ignore GC
2808 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2809 struct scroll_bar
*bar
;
2811 struct input_event
*emacs_event
;
2813 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2816 emacs_event
->kind
= scroll_bar_click
;
2817 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2818 emacs_event
->modifiers
=
2819 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2820 | (event
->type
== ButtonRelease
2823 emacs_event
->frame_or_window
= bar
->window
;
2824 emacs_event
->timestamp
= event
->xbutton
.time
;
2826 int internal_height
=
2827 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2829 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2830 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2833 if (y
> top_range
) y
= top_range
;
2835 if (y
< XINT (bar
->start
))
2836 emacs_event
->part
= scroll_bar_above_handle
;
2837 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2838 emacs_event
->part
= scroll_bar_handle
;
2840 emacs_event
->part
= scroll_bar_below_handle
;
2842 /* Just because the user has clicked on the handle doesn't mean
2843 they want to drag it. Lisp code needs to be able to decide
2844 whether or not we're dragging. */
2846 /* If the user has just clicked on the handle, record where they're
2848 if (event
->type
== ButtonPress
2849 && emacs_event
->part
== scroll_bar_handle
)
2850 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2853 /* If the user has released the handle, set it to its final position. */
2854 if (event
->type
== ButtonRelease
2855 && ! NILP (bar
->dragging
))
2857 int new_start
= y
- XINT (bar
->dragging
);
2858 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2860 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2861 bar
->dragging
= Qnil
;
2864 /* Same deal here as the other #if 0. */
2866 /* Clicks on the handle are always reported as occurring at the top of
2868 if (emacs_event
->part
== scroll_bar_handle
)
2869 emacs_event
->x
= bar
->start
;
2871 XSET (emacs_event
->x
, Lisp_Int
, y
);
2873 XSET (emacs_event
->x
, Lisp_Int
, y
);
2876 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2880 /* Handle some mouse motion while someone is dragging the scroll bar.
2882 This may be called from a signal handler, so we have to ignore GC
2885 x_scroll_bar_note_movement (bar
, event
)
2886 struct scroll_bar
*bar
;
2889 last_mouse_movement_time
= event
->xmotion
.time
;
2892 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2894 /* If we're dragging the bar, display it. */
2895 if (! GC_NILP (bar
->dragging
))
2897 /* Where should the handle be now? */
2898 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2900 if (new_start
!= XINT (bar
->start
))
2902 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2904 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2908 /* Call XQueryPointer so we'll get an event the next time the mouse
2909 moves and we can see *still* on the same position. */
2913 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2914 (Window
*) &dummy
, (Window
*) &dummy
,
2915 &dummy
, &dummy
, &dummy
, &dummy
,
2916 (unsigned int *) &dummy
);
2920 /* Return information to the user about the current position of the mouse
2921 on the scroll bar. */
2923 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2925 Lisp_Object
*bar_window
;
2926 enum scroll_bar_part
*part
;
2928 unsigned long *time
;
2930 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2932 Window dummy_window
;
2934 unsigned int dummy_mask
;
2938 /* Get the mouse's position relative to the scroll bar window, and
2940 if (! XQueryPointer (x_current_display
,
2941 SCROLL_BAR_X_WINDOW (bar
),
2943 /* Root, child, root x and root y. */
2944 &dummy_window
, &dummy_window
,
2945 &dummy_coord
, &dummy_coord
,
2947 /* Position relative to scroll bar. */
2950 /* Mouse buttons and modifier keys. */
2956 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2958 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2960 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2962 if (! NILP (bar
->dragging
))
2963 win_y
-= XINT (bar
->dragging
);
2967 if (win_y
> top_range
)
2970 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2971 *bar_window
= bar
->window
;
2973 if (! NILP (bar
->dragging
))
2974 *part
= scroll_bar_handle
;
2975 else if (win_y
< XINT (bar
->start
))
2976 *part
= scroll_bar_above_handle
;
2977 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2978 *part
= scroll_bar_handle
;
2980 *part
= scroll_bar_below_handle
;
2982 XSET (*x
, Lisp_Int
, win_y
);
2983 XSET (*y
, Lisp_Int
, top_range
);
2986 last_mouse_scroll_bar
= Qnil
;
2989 *time
= last_mouse_movement_time
;
2995 /* The screen has been cleared so we may have changed foreground or
2996 background colors, and the scroll bars may need to be redrawn.
2997 Clear out the scroll bars, and ask for expose events, so we can
3000 x_scroll_bar_clear (f
)
3005 for (bar
= FRAME_SCROLL_BARS (f
);
3006 XTYPE (bar
) == Lisp_Vector
;
3007 bar
= XSCROLL_BAR (bar
)->next
)
3008 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3012 /* This processes Expose events from the menubar specific X event
3013 loop in menubar.c. This allows to redisplay the frame if necessary
3014 when handling menubar or popup items. */
3017 process_expose_from_menu (event
)
3024 f
= x_window_to_frame (event
.xexpose
.window
);
3027 if (f
->async_visible
== 0)
3029 f
->async_visible
= 1;
3030 f
->async_iconified
= 0;
3031 SET_FRAME_GARBAGED (f
);
3035 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3036 event
.xexpose
.x
, event
.xexpose
.y
,
3037 event
.xexpose
.width
, event
.xexpose
.height
);
3042 struct scroll_bar
*bar
3043 = x_window_to_scroll_bar (event
.xexpose
.window
);
3046 x_scroll_bar_expose (bar
, &event
);
3053 /* The main X event-reading loop - XTread_socket. */
3055 /* Timestamp of enter window event. This is only used by XTread_socket,
3056 but we have to put it out here, since static variables within functions
3057 sometimes don't work. */
3058 static Time enter_timestamp
;
3060 /* This holds the state XLookupString needs to implement dead keys
3061 and other tricks known as "compose processing". _X Window System_
3062 says that a portable program can't use this, but Stephen Gildea assures
3063 me that letting the compiler initialize it to zeros will work okay.
3065 This must be defined outside of XTread_socket, for the same reasons
3066 given for enter_timestamp, above. */
3067 static XComposeStatus compose_status
;
3069 /* Communication with window managers. */
3070 Atom Xatom_wm_protocols
;
3072 /* Kinds of protocol things we may receive. */
3073 Atom Xatom_wm_take_focus
;
3074 Atom Xatom_wm_save_yourself
;
3075 Atom Xatom_wm_delete_window
;
3077 /* Other WM communication */
3078 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3079 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3081 /* Window manager communication. */
3082 Atom Xatom_wm_change_state
;
3084 /* Record the last 100 characters stored
3085 to help debug the loss-of-chars-during-GC problem. */
3087 short temp_buffer
[100];
3089 /* Read events coming from the X server.
3090 This routine is called by the SIGIO handler.
3091 We return as soon as there are no more events to be read.
3093 Events representing keys are stored in buffer BUFP,
3094 which can hold up to NUMCHARS characters.
3095 We return the number of characters stored into the buffer,
3096 thus pretending to be `read'.
3098 WAITP is nonzero if we should block until input arrives.
3099 EXPECTED is nonzero if the caller knows input is available. */
3102 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3104 register struct input_event
*bufp
;
3105 register int numchars
;
3112 int items_pending
; /* How many items are in the X queue. */
3115 int event_found
= 0;
3119 if (interrupt_input_blocked
)
3121 interrupt_input_pending
= 1;
3125 interrupt_input_pending
= 0;
3129 abort (); /* Don't think this happens. */
3132 /* If available, Xlib uses FIOSNBIO to make the socket
3133 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3134 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3135 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3136 fcntl (fileno (stdin
), F_SETFL
, 0);
3137 #endif /* ! defined (FIOSNBIO) */
3141 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3143 extern int read_alarm_should_throw
;
3144 read_alarm_should_throw
= 1;
3145 XPeekEvent (XDISPLAY
&event
);
3146 read_alarm_should_throw
= 0;
3148 #endif /* HAVE_SELECT */
3151 while (XStuffPending () != 0)
3153 XNextEvent (XDISPLAY
&event
);
3161 if (event
.xclient
.message_type
== Xatom_wm_protocols
3162 && event
.xclient
.format
== 32)
3164 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3166 #ifdef USE_X_TOOLKIT
3167 /* f = x_any_window_to_frame (event.xclient.window); */
3168 f
= x_window_to_frame (event
.xclient
.window
);
3170 f
= x_window_to_frame (event
.xclient
.window
);
3173 x_focus_on_frame (f
);
3174 /* Not certain about handling scroll bars here */
3176 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3178 /* Save state modify the WM_COMMAND property to
3179 something which can reinstate us. This notifies
3180 the session manager, who's looking for such a
3181 PropertyNotify. Can restart processing when
3182 a keyboard or mouse event arrives. */
3187 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3189 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3196 bufp
->kind
= delete_window_event
;
3197 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3205 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3208 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3211 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3213 new_x
= event
.xclient
.data
.s
[0];
3214 new_y
= event
.xclient
.data
.s
[1];
3218 f
->display
.x
->left_pos
= new_x
;
3219 f
->display
.x
->top_pos
= new_y
;
3225 #ifdef NEW_SELECTIONS
3226 case SelectionNotify
:
3227 #ifdef USE_X_TOOLKIT
3228 if (x_window_to_frame (event
.xselection
.requestor
))
3229 x_handle_selection_notify (&event
);
3232 #else /* not USE_X_TOOLKIT */
3233 x_handle_selection_notify (&event
);
3234 #endif /* not USE_X_TOOLKIT */
3236 #endif /* NEW_SELECTIONS */
3238 case SelectionClear
: /* Someone has grabbed ownership. */
3239 #ifdef NEW_SELECTIONS
3241 #ifdef USE_X_TOOLKIT
3242 if (x_window_to_frame (event
.xselectionclear
.window
))
3244 #endif /* USE_X_TOOLKIT */
3245 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3250 bufp
->kind
= selection_clear_event
;
3251 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3252 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3253 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3258 #ifdef USE_X_TOOLKIT
3262 #endif /* USE_X_TOOLKIT */
3264 #else /* not NEW_SELECTIONS */
3265 x_disown_selection (event
.xselectionclear
.window
,
3266 event
.xselectionclear
.selection
,
3267 event
.xselectionclear
.time
);
3268 #endif /* not NEW_SELECTIONS */
3271 case SelectionRequest
: /* Someone wants our selection. */
3272 #ifdef NEW_SELECTIONS
3274 #ifdef USE_X_TOOLKIT
3275 if (x_window_to_frame (event
.xselectionrequest
.owner
))
3277 #endif /* USE_X_TOOLKIT */
3278 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3283 bufp
->kind
= selection_request_event
;
3284 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3285 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3286 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3287 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3288 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3289 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3294 #ifdef USE_X_TOOLKIT
3298 #endif /* USE_X_TOOLKIT */
3300 #else /* not NEW_SELECTIONS */
3301 x_answer_selection_request (event
);
3302 #endif /* not NEW_SELECTIONS */
3305 case PropertyNotify
:
3306 #ifdef NEW_SELECTIONS
3307 #ifdef USE_X_TOOLKIT
3308 if (x_any_window_to_frame (event
.xproperty
.window
))
3309 x_handle_property_notify (&event
);
3312 #else /* not USE_X_TOOLKIT */
3313 x_handle_property_notify (&event
);
3314 #endif /* not USE_X_TOOLKIT */
3315 #else /* not NEW_SELECTIONS */
3316 /* If we're being told about a root window property, then it's
3317 a cut buffer change. */
3318 if (event
.xproperty
.window
== ROOT_WINDOW
)
3319 x_invalidate_cut_buffer_cache (&event
.xproperty
);
3321 /* Otherwise, we're probably handling an incremental
3322 selection transmission. */
3325 /* If we were to do this synchronously, there'd be no worry
3326 about re-selecting. */
3327 x_send_incremental (event
);
3329 #endif /* not NEW_SELECTIONS */
3332 case ReparentNotify
:
3333 f
= x_window_to_frame (event
.xreparent
.window
);
3335 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3339 f
= x_window_to_frame (event
.xexpose
.window
);
3342 if (f
->async_visible
== 0)
3344 f
->async_visible
= 1;
3345 f
->async_iconified
= 0;
3346 SET_FRAME_GARBAGED (f
);
3350 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3351 event
.xexpose
.x
, event
.xexpose
.y
,
3352 event
.xexpose
.width
, event
.xexpose
.height
);
3357 struct scroll_bar
*bar
3358 = x_window_to_scroll_bar (event
.xexpose
.window
);
3361 x_scroll_bar_expose (bar
, &event
);
3362 #ifdef USE_X_TOOLKIT
3365 #endif /* USE_X_TOOLKIT */
3369 case GraphicsExpose
: /* This occurs when an XCopyArea's
3370 source area was obscured or not
3372 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3376 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3377 event
.xgraphicsexpose
.width
,
3378 event
.xgraphicsexpose
.height
);
3380 #ifdef USE_X_TOOLKIT
3383 #endif /* USE_X_TOOLKIT */
3386 case NoExpose
: /* This occurs when an XCopyArea's
3387 source area was completely
3390 #else /* ! defined (HAVE_X11) */
3392 if (event
.subwindow
!= 0)
3393 break; /* duplicate event */
3394 f
= x_window_to_frame (event
.window
);
3395 if (event
.window
== f
->display
.x
->icon_desc
)
3398 f
->async_iconified
= 1;
3400 if (event
.window
== FRAME_X_WINDOW (f
))
3402 /* Say must check all windows' needs_exposure flags. */
3403 expose_all_windows
= 1;
3404 f
->display
.x
->needs_exposure
= 1;
3405 f
->async_visible
= 1;
3410 if (event
.subwindow
!= 0)
3411 break; /* duplicate event */
3412 f
= x_window_to_frame (event
.window
);
3413 if (event
.window
== f
->display
.x
->icon_desc
)
3418 /* If window already needs full redraw, ignore this rectangle. */
3419 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3421 /* Put the event on the queue of rectangles to redraw. */
3422 if (enqueue_event (&event
, &x_expose_queue
))
3423 /* If it is full, we can't record the rectangle,
3424 so redraw this entire window. */
3426 /* Say must check all windows' needs_exposure flags. */
3427 expose_all_windows
= 1;
3428 f
->display
.x
->needs_exposure
= 1;
3433 /* This should happen only when we are expecting it,
3434 in x_read_exposes. */
3436 #endif /* ! defined (HAVE_X11) */
3440 f
= x_window_to_frame (event
.xunmap
.window
);
3441 if (f
) /* F may no longer exist if
3442 the frame was deleted. */
3444 /* While a frame is unmapped, display generation is
3445 disabled; you don't want to spend time updating a
3446 display that won't ever be seen. */
3447 f
->async_visible
= 0;
3448 /* The window manager never makes a window invisible
3449 ("withdrawn"); all it does is switch between visible
3450 and iconified. Frames get into the invisible state
3451 only through x_make_frame_invisible. */
3452 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3453 f
->async_iconified
= 1;
3455 #ifdef USE_X_TOOLKIT
3457 #endif /* USE_X_TOOLKIT */
3461 #ifdef USE_X_TOOLKIT
3462 f
= x_any_window_to_frame (event
.xmap
.window
);
3463 #else /* not USE_X_TOOLKIT */
3464 f
= x_window_to_frame (event
.xmap
.window
);
3465 #endif /* not USE_X_TOOLKIT */
3468 f
->async_visible
= 1;
3469 f
->async_iconified
= 0;
3471 /* wait_reading_process_input will notice this and update
3472 the frame's display structures. */
3473 SET_FRAME_GARBAGED (f
);
3475 #ifdef USE_X_TOOLKIT
3477 #endif /* USE_X_TOOLKIT */
3480 /* Turn off processing if we become fully obscured. */
3481 case VisibilityNotify
:
3484 #else /* ! defined (HAVE_X11) */
3486 f
= x_window_to_frame (event
.window
);
3487 if (event
.window
== f
->display
.x
->icon_desc
)
3488 f
->async_iconified
= 0;
3489 if (event
.window
== FRAME_X_WINDOW (f
))
3490 f
->async_visible
= 0;
3492 #endif /* ! defined (HAVE_X11) */
3496 f
= x_any_window_to_frame (event
.xkey
.window
);
3500 KeySym keysym
, orig_keysym
;
3501 /* al%imercury@uunet.uu.net says that making this 81 instead of
3502 80 fixed a bug whereby meta chars made his Emacs hang. */
3503 unsigned char copy_buffer
[81];
3507 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3508 modifiers
= event
.xkey
.state
;
3510 /* This will have to go some day... */
3512 /* make_lispy_event turns chars into control chars.
3513 Don't do it here because XLookupString is too eager. */
3514 event
.xkey
.state
&= ~ControlMask
;
3516 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3519 /* Strip off the vendor-specific keysym bit, and take a shot
3520 at recognizing the codes. HP servers have extra keysyms
3521 that fit into the MiscFunctionKey category. */
3522 orig_keysym
= keysym
;
3527 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3528 || keysym
== XK_Delete
3529 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3530 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3532 /* This recognizes the "extended function keys".
3533 It seems there's no cleaner way.
3534 Test IsModifierKey to avoid handling mode_switch
3536 || ((unsigned) (keysym
) >= XK_Select
3537 && (unsigned)(keysym
) < XK_KP_Space
)
3539 #ifdef XK_dead_circumflex
3540 || orig_keysym
== XK_dead_circumflex
3542 #ifdef XK_dead_grave
3543 || orig_keysym
== XK_dead_grave
3545 #ifdef XK_dead_tilde
3546 || orig_keysym
== XK_dead_tilde
3548 #ifdef XK_dead_diaeresis
3549 || orig_keysym
== XK_dead_diaeresis
3551 #ifdef XK_dead_macron
3552 || orig_keysym
== XK_dead_macron
3554 #ifdef XK_dead_degree
3555 || orig_keysym
== XK_dead_degree
3557 #ifdef XK_dead_acute
3558 || orig_keysym
== XK_dead_acute
3560 #ifdef XK_dead_cedilla
3561 || orig_keysym
== XK_dead_cedilla
3563 #ifdef XK_dead_breve
3564 || orig_keysym
== XK_dead_breve
3566 #ifdef XK_dead_ogonek
3567 || orig_keysym
== XK_dead_ogonek
3569 #ifdef XK_dead_caron
3570 || orig_keysym
== XK_dead_caron
3572 #ifdef XK_dead_doubleacute
3573 || orig_keysym
== XK_dead_doubleacute
3575 #ifdef XK_dead_abovedot
3576 || orig_keysym
== XK_dead_abovedot
3578 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3579 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3580 || x_is_vendor_fkey (orig_keysym
))
3581 && ! (IsModifierKey (orig_keysym
)
3583 #ifdef XK_Mode_switch
3584 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3587 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3589 #endif /* not HAVE_X11R5 */
3592 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3594 temp_buffer
[temp_index
++] = keysym
;
3595 bufp
->kind
= non_ascii_keystroke
;
3596 bufp
->code
= keysym
;
3597 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3598 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3599 bufp
->timestamp
= event
.xkey
.time
;
3604 else if (numchars
> nbytes
)
3608 for (i
= 0; i
< nbytes
; i
++)
3610 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3612 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3613 bufp
->kind
= ascii_keystroke
;
3614 bufp
->code
= copy_buffer
[i
];
3615 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3616 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3617 bufp
->timestamp
= event
.xkey
.time
;
3631 #else /* ! defined (HAVE_X11) */
3634 register char *where_mapping
;
3636 f
= x_window_to_frame (event
.window
);
3637 /* Ignore keys typed on icon windows. */
3638 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3640 where_mapping
= XLookupMapping (&event
, &nbytes
);
3641 /* Nasty fix for arrow keys */
3642 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3644 switch (event
.detail
& 0xff)
3646 case KC_CURSOR_LEFT
:
3647 where_mapping
= "\002";
3649 case KC_CURSOR_RIGHT
:
3650 where_mapping
= "\006";
3653 where_mapping
= "\020";
3655 case KC_CURSOR_DOWN
:
3656 where_mapping
= "\016";
3661 if (numchars
- nbytes
> 0)
3665 for (i
= 0; i
< nbytes
; i
++)
3667 bufp
->kind
= ascii_keystroke
;
3668 bufp
->code
= where_mapping
[i
];
3669 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3670 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3678 #endif /* ! defined (HAVE_X11) */
3682 /* Here's a possible interpretation of the whole
3683 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3684 FocusIn event, you have to get a FocusOut event before you
3685 relinquish the focus. If you haven't received a FocusIn event,
3686 then a mere LeaveNotify is enough to free you. */
3689 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3691 if (event
.xcrossing
.focus
) /* Entered Window */
3693 /* Avoid nasty pop/raise loops. */
3694 if (f
&& (!(f
->auto_raise
)
3696 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3698 x_new_focus_frame (f
);
3699 enter_timestamp
= event
.xcrossing
.time
;
3702 else if (f
== x_focus_frame
)
3703 x_new_focus_frame (0);
3704 #ifdef USE_X_TOOLKIT
3706 #endif /* USE_X_TOOLKIT */
3710 f
= x_any_window_to_frame (event
.xfocus
.window
);
3711 if (event
.xfocus
.detail
!= NotifyPointer
)
3712 x_focus_event_frame
= f
;
3714 x_new_focus_frame (f
);
3715 #ifdef USE_X_TOOLKIT
3717 #endif /* USE_X_TOOLKIT */
3722 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3724 if (f
== mouse_face_mouse_frame
)
3725 /* If we move outside the frame,
3726 then we're certainly no longer on any text in the frame. */
3727 clear_mouse_face ();
3729 if (event
.xcrossing
.focus
)
3731 if (! x_focus_event_frame
)
3732 x_new_focus_frame (0);
3734 x_new_focus_frame (f
);
3738 if (f
== x_focus_event_frame
)
3739 x_focus_event_frame
= 0;
3740 if (f
== x_focus_frame
)
3741 x_new_focus_frame (0);
3743 #ifdef USE_X_TOOLKIT
3745 #endif /* USE_X_TOOLKIT */
3749 f
= x_any_window_to_frame (event
.xfocus
.window
);
3750 if (event
.xfocus
.detail
!= NotifyPointer
3751 && f
== x_focus_event_frame
)
3752 x_focus_event_frame
= 0;
3753 if (f
&& f
== x_focus_frame
)
3754 x_new_focus_frame (0);
3755 #ifdef USE_X_TOOLKIT
3757 #endif /* USE_X_TOOLKIT */
3760 #else /* ! defined (HAVE_X11) */
3763 if ((event
.detail
& 0xFF) == 1)
3764 break; /* Coming from our own subwindow */
3765 if (event
.subwindow
!= 0)
3766 break; /* Entering our own subwindow. */
3769 f
= x_window_to_frame (event
.window
);
3772 x_new_focus_frame (f
);
3777 if ((event
.detail
& 0xFF) == 1)
3778 break; /* Entering our own subwindow */
3779 if (event
.subwindow
!= 0)
3780 break; /* Leaving our own subwindow. */
3783 if (x_focus_frame
== 0
3784 && x_input_frame
!= 0
3785 && x_input_frame
== x_window_to_frame (event
.window
)
3786 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3791 frame_unhighlight (f
);
3794 #endif /* ! defined (HAVE_X11) */
3799 if (x_mouse_grabbed
)
3800 f
= last_mouse_frame
;
3802 f
= x_window_to_frame (event
.xmotion
.window
);
3804 note_mouse_movement (f
, &event
.xmotion
);
3807 struct scroll_bar
*bar
3808 = x_window_to_scroll_bar (event
.xmotion
.window
);
3811 x_scroll_bar_note_movement (bar
, &event
);
3813 /* If we move outside the frame,
3814 then we're certainly no longer on any text in the frame. */
3815 clear_mouse_face ();
3818 #ifdef USE_X_TOOLKIT
3820 #endif /* USE_X_TOOLKIT */
3823 case ConfigureNotify
:
3824 f
= x_any_window_to_frame (event
.xconfigure
.window
);
3825 #ifdef USE_X_TOOLKIT
3827 && ! event
.xconfigure
.send_event
3828 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
3833 /* Find the position of the outside upper-left corner of
3834 the window, in the root coordinate system. Don't
3835 refer to the parent window here; we may be processing
3836 this event after the window manager has changed our
3837 parent, but before we have reached the ReparentNotify. */
3838 XTranslateCoordinates (x_current_display
,
3840 /* From-window, to-window. */
3841 XtWindow (f
->display
.x
->widget
),
3844 /* From-position, to-position. */
3845 -event
.xconfigure
.border_width
,
3846 -event
.xconfigure
.border_width
,
3851 event
.xconfigure
.x
= win_x
;
3852 event
.xconfigure
.y
= win_y
;
3854 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3855 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3856 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3857 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3860 #else /* not USE_X_TOOLKIT */
3863 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3864 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3866 /* Even if the number of character rows and columns has
3867 not changed, the font size may have changed, so we need
3868 to check the pixel dimensions as well. */
3869 if (columns
!= f
->width
3870 || rows
!= f
->height
3871 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3872 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3874 change_frame_size (f
, rows
, columns
, 0, 1);
3875 SET_FRAME_GARBAGED (f
);
3878 if (! event
.xconfigure
.send_event
)
3883 /* Find the position of the outside upper-left corner of
3884 the window, in the root coordinate system. Don't
3885 refer to the parent window here; we may be processing
3886 this event after the window manager has changed our
3887 parent, but before we have reached the ReparentNotify. */
3888 XTranslateCoordinates (x_current_display
,
3890 /* From-window, to-window. */
3891 f
->display
.x
->window_desc
,
3894 /* From-position, to-position. */
3895 -event
.xconfigure
.border_width
,
3896 -event
.xconfigure
.border_width
,
3901 event
.xconfigure
.x
= win_x
;
3902 event
.xconfigure
.y
= win_y
;
3905 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3906 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3907 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3908 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3910 #endif /* not USE_X_TOOLKIT */
3916 /* If we decide we want to generate an event to be seen
3917 by the rest of Emacs, we put it here. */
3918 struct input_event emacs_event
;
3919 emacs_event
.kind
= no_event
;
3921 f
= x_window_to_frame (event
.xbutton
.window
);
3924 if (!x_focus_frame
|| (f
== x_focus_frame
))
3925 construct_mouse_click (&emacs_event
, &event
, f
);
3929 struct scroll_bar
*bar
=
3930 x_window_to_scroll_bar (event
.xbutton
.window
);
3933 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3934 #ifdef USE_X_TOOLKIT
3937 f
= x_any_window_to_frame (event
.xbutton
.window
);
3938 if (f
&& event
.type
== ButtonPress
)
3939 construct_menu_click (&emacs_event
,
3942 #endif /* USE_X_TOOLKIT */
3945 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3947 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3953 #ifdef USE_X_TOOLKIT
3955 #endif /* USE_X_TOOLKIT */
3959 #else /* ! defined (HAVE_X11) */
3961 case ButtonReleased
:
3962 f
= x_window_to_frame (event
.window
);
3965 if (event
.window
== f
->display
.x
->icon_desc
)
3967 x_make_frame_visible (f
);
3969 if (warp_mouse_on_deiconify
)
3970 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3973 if (event
.window
== FRAME_X_WINDOW (f
))
3979 enqueue_event (&event
, &x_mouse_queue
);
3982 bufp
->kind
= ascii_keystroke
;
3983 bufp
->code
= 'X' & 037; /* C-x */
3984 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3985 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3988 bufp
->kind
= ascii_keystroke
;
3989 bufp
->code
= 0; /* C-@ */
3990 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3991 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3998 #endif /* ! defined (HAVE_X11) */
4002 case CirculateNotify
:
4004 case CirculateRequest
:
4007 #endif /* ! defined (HAVE_X11) */
4010 /* Someone has changed the keyboard mapping - update the
4012 switch (event
.xmapping
.request
)
4014 case MappingModifier
:
4015 x_find_modifier_meanings ();
4016 /* This is meant to fall through. */
4017 case MappingKeyboard
:
4018 XRefreshKeyboardMapping (&event
.xmapping
);
4020 #ifdef USE_X_TOOLKIT
4022 #endif /* USE_X_TOOLKIT */
4026 #ifdef USE_X_TOOLKIT
4029 XtDispatchEvent (&event
);
4031 #endif /* USE_X_TOOLKIT */
4038 /* On some systems, an X bug causes Emacs to get no more events
4039 when the window is destroyed. Detect that. (1994.) */
4040 XNoOp (x_current_display
);
4041 #endif /* X_IO_BUG */
4043 #if 0 /* This fails for serial-line connections to the X server,
4044 because the characters arrive one by one, and a partial
4045 command makes select return but gives nothing to read.
4046 We'll have to hope that the bug that this tried to fix
4047 in 1988 has been fixed in Xlib or the X server. */
4049 if (expected
&& ! event_found
)
4051 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4052 there is an EOF condition; in other words, that X has died.
4053 Act as if there had been a hangup. */
4054 int fd
= ConnectionNumber (x_current_display
);
4055 SELECT_TYPE mask
, junk1
, junk2
;
4060 EMACS_SET_SECS_USECS (timeout
, 0, 0);
4063 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
4064 && !XStuffPending ())
4065 kill (getpid (), SIGHUP
);
4067 #endif /* HAVE_SELECT */
4071 if (updating_frame
== 0)
4072 x_do_pending_expose ();
4080 /* Read and process only Expose events
4081 until we get an ExposeCopy event; then return.
4082 This is used in insert/delete line.
4083 We assume input is already blocked. */
4089 XKeyPressedEvent event
;
4093 /* while there are more events*/
4094 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
4098 if (event
.subwindow
!= 0)
4099 break; /* duplicate event */
4100 f
= x_window_to_frame (event
.window
);
4101 if (event
.window
== f
->display
.x
->icon_desc
)
4106 if (event
.window
== FRAME_X_WINDOW (f
))
4108 expose_all_windows
= 1;
4109 f
->display
.x
->needs_exposure
= 1;
4115 if (event
.subwindow
!= 0)
4116 break; /* duplicate event */
4117 f
= x_window_to_frame (event
.window
);
4118 if (event
.window
== f
->display
.x
->icon_desc
)
4123 /* If window already needs full redraw, ignore this rectangle. */
4124 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
4126 /* Put the event on the queue of rectangles to redraw. */
4127 if (enqueue_event (&event
, &x_expose_queue
))
4128 /* If it is full, we can't record the rectangle,
4129 so redraw this entire window. */
4131 /* Say must check all windows' needs_exposure flags. */
4132 expose_all_windows
= 1;
4133 f
->display
.x
->needs_exposure
= 1;
4142 #endif /* HAVE_X11 */
4145 /* Drawing the cursor. */
4148 /* Draw a hollow box cursor. Don't change the inside of the box. */
4154 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
4155 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
4156 int width
= FONT_WIDTH (f
->display
.x
->font
);
4157 int height
= FONT_HEIGHT (f
->display
.x
->font
);
4160 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4161 f
->display
.x
->cursor_gc
,
4162 left
, top
, width
- 1, height
- 1);
4163 #else /* ! defined (HAVE_X11) */
4164 XPixSet (FRAME_X_WINDOW (f
),
4165 left
, top
, width
, 1,
4166 f
->display
.x
->cursor_pixel
);
4168 XPixSet (FRAME_X_WINDOW (f
),
4169 left
, top
, 1, height
,
4170 f
->display
.x
->cursor_pixel
);
4172 XPixSet (FRAME_X_WINDOW (f
),
4173 left
+width
-1, top
, 1, height
,
4174 f
->display
.x
->cursor_pixel
);
4176 XPixSet (FRAME_X_WINDOW (f
),
4177 left
, top
+height
-1, width
, 1,
4178 f
->display
.x
->cursor_pixel
);
4179 #endif /* ! defined (HAVE_X11) */
4182 /* Clear the cursor of frame F to background color,
4183 and mark the cursor as not shown.
4184 This is used when the text where the cursor is
4185 is about to be rewritten. */
4193 if (! FRAME_VISIBLE_P (f
)
4194 || f
->phys_cursor_x
< 0)
4198 x_display_cursor (f
, 0);
4199 #else /* ! defined (HAVE_X11) */
4200 XPixSet (FRAME_X_WINDOW (f
),
4201 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4202 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4203 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
4204 f
->display
.x
->background_pixel
);
4205 #endif /* ! defined (HAVE_X11) */
4206 f
->phys_cursor_x
= -1;
4209 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4210 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4214 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4221 CHAR_TO_PIXEL_COL (f
, column
),
4222 CHAR_TO_PIXEL_ROW (f
, row
),
4223 &glyph
, 1, highlight
);
4227 x_display_bar_cursor (f
, on
)
4231 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4233 /* This is pointless on invisible frames, and dangerous on garbaged
4234 frames; in the latter case, the frame may be in the midst of
4235 changing its size, and curs_x and curs_y may be off the frame. */
4236 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4239 if (! on
&& f
->phys_cursor_x
< 0)
4242 /* If we're not updating, then we want to use the current frame's
4243 cursor position, not our local idea of where the cursor ought to be. */
4244 if (f
!= updating_frame
)
4246 curs_x
= FRAME_CURSOR_X (f
);
4247 curs_y
= FRAME_CURSOR_Y (f
);
4250 /* If there is anything wrong with the current cursor state, remove it. */
4251 if (f
->phys_cursor_x
>= 0
4253 || f
->phys_cursor_x
!= curs_x
4254 || f
->phys_cursor_y
!= curs_y
4255 || f
->display
.x
->current_cursor
!= bar_cursor
))
4257 /* Erase the cursor by redrawing the character underneath it. */
4258 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4259 f
->phys_cursor_glyph
,
4260 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4261 f
->phys_cursor_x
= -1;
4264 /* If we now need a cursor in the new place or in the new form, do it so. */
4266 && (f
->phys_cursor_x
< 0
4267 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4269 f
->phys_cursor_glyph
4270 = ((current_glyphs
->enable
[curs_y
]
4271 && curs_x
< current_glyphs
->used
[curs_y
])
4272 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4274 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4275 f
->display
.x
->cursor_gc
,
4276 CHAR_TO_PIXEL_COL (f
, curs_x
),
4277 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4278 1, FONT_HEIGHT (f
->display
.x
->font
));
4280 f
->phys_cursor_x
= curs_x
;
4281 f
->phys_cursor_y
= curs_y
;
4283 f
->display
.x
->current_cursor
= bar_cursor
;
4286 if (updating_frame
!= f
)
4291 /* Turn the displayed cursor of frame F on or off according to ON.
4292 If ON is nonzero, where to put the cursor is specified
4293 by F->cursor_x and F->cursor_y. */
4296 x_display_box_cursor (f
, on
)
4300 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4302 /* This is pointless on invisible frames, and dangerous on garbaged
4303 frames; in the latter case, the frame may be in the midst of
4304 changing its size, and curs_x and curs_y may be off the frame. */
4305 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4308 /* If cursor is off and we want it off, return quickly. */
4309 if (!on
&& f
->phys_cursor_x
< 0)
4312 /* If we're not updating, then we want to use the current frame's
4313 cursor position, not our local idea of where the cursor ought to be. */
4314 if (f
!= updating_frame
)
4316 curs_x
= FRAME_CURSOR_X (f
);
4317 curs_y
= FRAME_CURSOR_Y (f
);
4320 /* If cursor is currently being shown and we don't want it to be
4321 or it is in the wrong place,
4322 or we want a hollow box and it's not so, (pout!)
4324 if (f
->phys_cursor_x
>= 0
4326 || f
->phys_cursor_x
!= curs_x
4327 || f
->phys_cursor_y
!= curs_y
4328 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4329 && (f
!= x_highlight_frame
))))
4331 /* Erase the cursor by redrawing the character underneath it. */
4332 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4333 f
->phys_cursor_glyph
,
4334 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4335 f
->phys_cursor_x
= -1;
4338 /* If we want to show a cursor,
4339 or we want a box cursor and it's not so,
4340 write it in the right place. */
4342 && (f
->phys_cursor_x
< 0
4343 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4344 && f
== x_highlight_frame
)))
4346 f
->phys_cursor_glyph
4347 = ((current_glyphs
->enable
[curs_y
]
4348 && curs_x
< current_glyphs
->used
[curs_y
])
4349 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4351 if (f
!= x_highlight_frame
)
4354 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4358 x_draw_single_glyph (f
, curs_y
, curs_x
,
4359 f
->phys_cursor_glyph
, 2);
4360 f
->display
.x
->current_cursor
= filled_box_cursor
;
4363 f
->phys_cursor_x
= curs_x
;
4364 f
->phys_cursor_y
= curs_y
;
4367 if (updating_frame
!= f
)
4371 x_display_cursor (f
, on
)
4377 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4378 x_display_box_cursor (f
, on
);
4379 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4380 x_display_bar_cursor (f
, on
);
4382 /* Those are the only two we have implemented! */
4390 /* Refresh bitmap kitchen sink icon for frame F
4391 when we get an expose event for it. */
4397 /* Normally, the window manager handles this function. */
4398 #else /* ! defined (HAVE_X11) */
4401 if (f
->display
.x
->icon_bitmap_flag
)
4402 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
4403 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
4404 icon_bitmap
, GXcopy
, AllPlanes
);
4407 extern struct frame
*selected_frame
;
4408 struct Lisp_String
*str
;
4409 unsigned char *string
;
4412 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
4414 if (f
->display
.x
->icon_label
!= string
)
4416 f
->display
.x
->icon_label
= string
;
4417 XChangeWindow (f
->display
.x
->icon_desc
,
4418 XQueryWidth (string
, icon_font_info
->id
) + 10,
4419 icon_font_info
->height
+ 10);
4422 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4423 str
->size
, icon_font_info
->id
,
4424 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4427 #endif /* ! defined (HAVE_X11) */
4430 /* Make the x-window of frame F use the gnu icon bitmap. */
4439 if (FRAME_X_WINDOW (f
) == 0)
4445 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4446 gnu_bits
, gnu_width
, gnu_height
);
4447 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4448 f
->display
.x
->icon_bitmap_flag
= 1;
4449 #else /* ! defined (HAVE_X11) */
4450 if (f
->display
.x
->icon_desc
)
4452 XClearIconWindow (FRAME_X_WINDOW (f
));
4453 XDestroyWindow (f
->display
.x
->icon_desc
);
4456 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4457 0, 0, sink_width
, sink_height
,
4458 2, WhitePixmap
, (Pixmap
) NULL
);
4460 if (icon_window
== 0)
4463 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4464 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4466 f
->display
.x
->icon_desc
= icon_window
;
4467 f
->display
.x
->icon_bitmap_flag
= 1;
4469 if (icon_bitmap
== 0)
4471 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4472 #endif /* ! defined (HAVE_X11) */
4478 /* Make the x-window of frame F use a rectangle with text. */
4481 x_text_icon (f
, icon_name
)
4489 char *X_DefaultValue
;
4493 #define WhitePixel 1
4494 #endif /* WhitePixel */
4497 #define BlackPixel 0
4498 #endif /* BlackPixel */
4499 #endif /* HAVE_X11 */
4501 if (FRAME_X_WINDOW (f
) == 0)
4506 f
->display
.x
->icon_label
= icon_name
;
4508 if (! f
->display
.x
->icon_label
)
4509 f
->display
.x
->icon_label
= " *emacs* ";
4512 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4513 (char *) f
->display
.x
->icon_label
);
4516 f
->display
.x
->icon_bitmap_flag
= 0;
4517 x_wm_set_icon_pixmap (f
, 0);
4518 #else /* ! defined (HAVE_X11) */
4519 if (icon_font_info
== 0)
4521 = XGetFont (XGetDefault (XDISPLAY
4522 (char *) XSTRING (Vinvocation_name
)->data
,
4525 if (f
->display
.x
->icon_desc
)
4527 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4528 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4532 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4534 if (! f
->display
.x
->icon_label
)
4535 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4537 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4538 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4539 f
->display
.x
->left_pos
,
4540 f
->display
.x
->top_pos
,
4541 width
+ 10, icon_font_info
->height
+ 10,
4542 2, BlackPixmap
, WhitePixmap
);
4544 if (icon_window
== 0)
4547 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4548 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4550 f
->display
.x
->icon_desc
= icon_window
;
4551 f
->display
.x
->icon_bitmap_flag
= 0;
4552 f
->display
.x
->icon_label
= 0;
4553 #endif /* ! defined (HAVE_X11) */
4558 /* Handling X errors. */
4560 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4561 X server's connection, or an error reported via the X protocol. */
4564 x_connection_closed ()
4569 shut_down_emacs (0, 1, Qnil
);
4574 /* An X error handler which prints an error message and then kills
4575 Emacs. This is what's normally installed as Xlib's handler for
4578 x_error_quitter (display
, error
)
4584 /* Note that there is no real way portable across R3/R4 to get the
4585 original error handler. */
4587 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4588 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4589 buf
, error
->request_code
);
4592 /* While we're testing Emacs 19, we'll just dump core whenever we
4593 get an X error, so we can figure out why it happened. */
4597 x_connection_closed ();
4600 /* A handler for X IO errors which prints an error message and then
4601 kills Emacs. This is what is always installed as Xlib's handler
4604 x_io_error_quitter (display
)
4607 fprintf (stderr
, "Connection to X server %s lost.\n",
4608 XDisplayName (DisplayString (display
)));
4611 /* While we're testing Emacs 19, we'll just dump core whenever we
4612 get an X error, so we can figure out why it happened. */
4616 x_connection_closed ();
4619 /* A buffer for storing X error messages. */
4620 static char *x_caught_error_message
;
4621 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4623 /* An X error handler which stores the error message in
4624 x_caught_error_message. This is what's installed when
4625 x_catch_errors is in effect. */
4627 x_error_catcher (display
, error
)
4631 XGetErrorText (display
, error
->error_code
,
4632 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4636 /* Begin trapping X errors.
4638 After calling this function, X protocol errors no longer cause
4639 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4641 Calling x_check_errors signals an Emacs error if an X error has
4642 occurred since the last call to x_catch_errors or x_check_errors.
4644 Calling x_uncatch_errors resumes the normal error handling. */
4646 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4651 /* Make sure any errors from previous requests have been dealt with. */
4652 XSync (x_current_display
, False
);
4654 /* Set up the error buffer. */
4655 x_caught_error_message
4656 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4657 x_caught_error_message
[0] = '\0';
4659 /* Install our little error handler. */
4660 XHandleError (x_error_catcher
);
4663 /* If any X protocol errors have arrived since the last call to
4664 x_catch_errors or x_check_errors, signal an Emacs error using
4665 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4668 x_check_errors (format
)
4671 /* Make sure to catch any errors incurred so far. */
4672 XSync (x_current_display
, False
);
4674 if (x_caught_error_message
[0])
4676 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4678 sprintf (buf
, format
, x_caught_error_message
);
4679 x_uncatch_errors ();
4684 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4689 /* Make sure to catch any errors incurred so far. */
4690 XSync (x_current_display
, False
);
4692 return x_caught_error_message
[0] != 0;
4695 /* Stop catching X protocol errors and let them make Emacs die. */
4700 xfree (x_caught_error_message
);
4701 x_caught_error_message
= 0;
4702 XHandleError (x_error_quitter
);
4706 static unsigned int x_wire_count
;
4709 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4714 /* Changing the font of the frame. */
4716 /* Set the font of the x-window specified by frame F
4717 to the font named NEWNAME. This is safe to use
4718 even before F has an actual x-window. */
4728 /* A table of all the fonts we have already loaded. */
4729 static struct font_info
*x_font_table
;
4731 /* The current capacity of x_font_table. */
4732 static int x_font_table_size
;
4734 /* The number of fonts actually stored in x_font_table.
4735 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4736 0 <= n_fonts <= x_font_table_size. */
4740 x_new_font (f
, fontname
)
4742 register char *fontname
;
4745 int n_matching_fonts
;
4746 XFontStruct
*font_info
;
4749 /* Get a list of all the fonts that match this name. Once we
4750 have a list of matching fonts, we compare them against the fonts
4751 we already have by comparing font ids. */
4752 font_names
= (char **) XListFonts (x_current_display
, fontname
,
4753 1024, &n_matching_fonts
);
4754 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4755 find any matches; font_names == 0 is the only clue. */
4757 n_matching_fonts
= 0;
4759 /* Don't just give up if n_matching_fonts is 0.
4760 Apparently there's a bug on Suns: XListFontsWithInfo can
4761 fail to find a font, but XLoadQueryFont may still find it. */
4763 /* See if we've already loaded a matching font. */
4764 already_loaded
= -1;
4765 if (n_matching_fonts
!= 0)
4769 for (i
= 0; i
< n_fonts
; i
++)
4770 for (j
= 0; j
< n_matching_fonts
; j
++)
4771 if (!strcmp (x_font_table
[i
].name
, font_names
[j
]))
4774 fontname
= font_names
[j
];
4780 /* If we have, just return it from the table. */
4781 if (already_loaded
>= 0)
4782 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
4784 /* Otherwise, load the font and add it to the table. */
4790 /* Try to find a character-cell font in the list. */
4792 /* A laudable goal, but this isn't how to do it. */
4793 for (i
= 0; i
< n_matching_fonts
; i
++)
4794 if (! font_info
[i
].per_char
)
4800 /* See comment above. */
4801 if (n_matching_fonts
!= 0)
4802 fontname
= font_names
[i
];
4804 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
4807 /* Free the information from XListFonts. */
4808 if (n_matching_fonts
)
4809 XFreeFontNames (font_names
);
4813 /* Do we need to create the table? */
4814 if (x_font_table_size
== 0)
4816 x_font_table_size
= 16;
4818 = (struct font_info
*) xmalloc (x_font_table_size
4819 * sizeof (x_font_table
[0]));
4821 /* Do we need to grow the table? */
4822 else if (n_fonts
>= x_font_table_size
)
4824 x_font_table_size
*= 2;
4826 = (struct font_info
*) xrealloc (x_font_table
,
4828 * sizeof (x_font_table
[0])));
4831 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4832 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4833 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
4836 /* Now make the frame display the given font. */
4837 if (FRAME_X_WINDOW (f
) != 0)
4839 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
4840 f
->display
.x
->font
->fid
);
4841 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
4842 f
->display
.x
->font
->fid
);
4843 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
4844 f
->display
.x
->font
->fid
);
4846 x_set_window_size (f
, 0, f
->width
, f
->height
);
4850 Lisp_Object lispy_name
;
4852 lispy_name
= build_string (fontname
);
4854 /* Free the information from XListFonts. The data
4855 we actually retain comes from XLoadQueryFont. */
4856 XFreeFontNames (font_names
);
4861 #else /* ! defined (HAVE_X11) */
4862 x_new_font (f
, newname
)
4864 register char *newname
;
4869 temp
= XGetFont (newname
);
4870 if (temp
== (FONT_TYPE
*) 0)
4873 if (f
->display
.x
->font
)
4874 XLoseFont (f
->display
.x
->font
);
4876 f
->display
.x
->font
= temp
;
4878 if (FRAME_X_WINDOW (f
) != 0)
4879 x_set_window_size (f
, 0, f
->width
, f
->height
);
4883 #endif /* ! defined (HAVE_X11) */
4885 x_calc_absolute_position (f
)
4890 int win_x
= 0, win_y
= 0;
4892 /* Find the position of the outside upper-left corner of
4893 the inner window, with respect to the outer window. */
4894 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
4897 XTranslateCoordinates (x_current_display
,
4899 /* From-window, to-window. */
4900 f
->display
.x
->window_desc
,
4901 f
->display
.x
->parent_desc
,
4903 /* From-position, to-position. */
4904 0, 0, &win_x
, &win_y
,
4911 /* Treat negative positions as relative to the leftmost bottommost
4912 position that fits on the screen. */
4913 if (f
->display
.x
->left_pos
< 0)
4914 f
->display
.x
->left_pos
= (x_screen_width
4915 - 2 * f
->display
.x
->border_width
- win_x
4917 + f
->display
.x
->left_pos
);
4919 if (f
->display
.x
->top_pos
< 0)
4920 f
->display
.x
->top_pos
= (x_screen_height
4921 - 2 * f
->display
.x
->border_width
- win_y
4923 + f
->display
.x
->top_pos
);
4925 #else /* ! defined (HAVE_X11) */
4926 WINDOWINFO_TYPE parentinfo
;
4928 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
4930 if (f
->display
.x
->left_pos
< 0)
4931 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
4932 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
4934 if (f
->display
.x
->top_pos
< 0)
4935 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
4936 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
4937 #endif /* ! defined (HAVE_X11) */
4940 x_set_offset (f
, xoff
, yoff
)
4942 register int xoff
, yoff
;
4944 f
->display
.x
->top_pos
= yoff
;
4945 f
->display
.x
->left_pos
= xoff
;
4946 x_calc_absolute_position (f
);
4949 #ifdef USE_X_TOOLKIT
4950 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
4951 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4952 #else /* not USE_X_TOOLKIT */
4953 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4954 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4955 #endif /* not USE_X_TOOLKIT */
4957 x_wm_set_size_hint (f
, 0, 1, xoff
, yoff
);
4958 #endif /* ! defined (HAVE_X11) */
4962 /* Call this to change the size of frame F's x-window.
4963 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4964 for this size change and subsequent size changes.
4965 Otherwise we leave the window gravity unchanged. */
4967 x_set_window_size (f
, change_gravity
, cols
, rows
)
4972 int pixelwidth
, pixelheight
;
4975 #ifdef USE_X_TOOLKIT
4977 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4980 #else /* not USE_X_TOOLKIT */
4984 check_frame_size (f
, &rows
, &cols
);
4985 f
->display
.x
->vertical_scroll_bar_extra
4986 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4987 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
4989 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4990 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4993 x_wm_set_size_hint (f
, 0, change_gravity
, 0, 0);
4994 #endif /* ! defined (HAVE_X11) */
4995 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4997 /* Now, strictly speaking, we can't be sure that this is accurate,
4998 but the window manager will get around to dealing with the size
4999 change request eventually, and we'll hear how it went when the
5000 ConfigureNotify event gets here.
5002 We could just not bother storing any of this information here,
5003 and let the ConfigureNotify event set everything up, but that
5004 might be kind of confusing to the lisp code, since size changes
5005 wouldn't be reported in the frame parameters until some random
5006 point in the future when the ConfigureNotify event arrives. */
5007 change_frame_size (f
, rows
, cols
, 0, 0);
5008 PIXEL_WIDTH (f
) = pixelwidth
;
5009 PIXEL_HEIGHT (f
) = pixelheight
;
5011 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5012 receive in the ConfigureNotify event; if we get what we asked
5013 for, then the event won't cause the screen to become garbaged, so
5014 we have to make sure to do it here. */
5015 SET_FRAME_GARBAGED (f
);
5019 #endif /* not USE_X_TOOLKIT */
5023 x_set_resize_hint (f
)
5026 XSetResizeHint (FRAME_X_WINDOW (f
),
5027 2 * f
->display
.x
->internal_border_width
,
5028 2 * f
->display
.x
->internal_border_width
,
5029 FONT_WIDTH (f
->display
.x
->font
),
5030 FONT_HEIGHT (f
->display
.x
->font
));
5032 #endif /* HAVE_X11 */
5034 /* Mouse warping, focus shifting, raising and lowering. */
5036 x_set_mouse_position (f
, x
, y
)
5042 #if 0 /* Let the user ask for this if he wants it. */
5046 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
5047 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
5049 if (pix_x
< 0) pix_x
= 0;
5050 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5052 if (pix_y
< 0) pix_y
= 0;
5053 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5057 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5062 x_focus_on_frame (f
)
5065 #if 0 /* This proves to be unpleasant. */
5069 /* I don't think that the ICCCM allows programs to do things like this
5070 without the interaction of the window manager. Whatever you end up
5071 doing with this code, do it to x_unfocus_frame too. */
5072 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
5073 RevertToPointerRoot
, CurrentTime
);
5081 /* Look at the remarks in x_focus_on_frame. */
5082 if (x_focus_frame
== f
)
5083 XSetInputFocus (x_current_display
, PointerRoot
,
5084 RevertToPointerRoot
, CurrentTime
);
5088 #endif /* ! defined (HAVE_X11) */
5090 /* Raise frame F. */
5095 if (f
->async_visible
)
5098 #ifdef USE_X_TOOLKIT
5099 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5100 #else /* not USE_X_TOOLKIT */
5101 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5102 #endif /* not USE_X_TOOLKIT */
5108 /* Lower frame F. */
5113 if (f
->async_visible
)
5116 #ifdef USE_X_TOOLKIT
5117 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5118 #else /* not USE_X_TOOLKIT */
5119 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5120 #endif /* not USE_X_TOOLKIT */
5127 XTframe_raise_lower (f
, raise
)
5138 /* Change from withdrawn state to mapped state. */
5140 x_make_frame_visible (f
)
5147 if (! FRAME_VISIBLE_P (f
))
5150 if (! EQ (Vx_no_window_manager
, Qt
))
5151 x_wm_set_window_state (f
, NormalState
);
5152 #ifdef USE_X_TOOLKIT
5153 XtPopup (f
->display
.x
->widget
, XtGrabNone
);
5154 #else /* not USE_X_TOOLKIT */
5155 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5156 #endif /* not USE_X_TOOLKIT */
5157 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5158 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5159 #else /* ! defined (HAVE_X11) */
5160 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5161 if (f
->display
.x
->icon_desc
!= 0)
5162 XUnmapWindow (f
->display
.x
->icon_desc
);
5164 /* Handled by the MapNotify event for X11 */
5165 f
->async_visible
= 1;
5166 f
->async_iconified
= 0;
5168 /* NOTE: this may cause problems for the first frame. */
5170 #endif /* ! defined (HAVE_X11) */
5178 /* Change from mapped state to withdrawn state. */
5180 x_make_frame_invisible (f
)
5185 /* Don't keep the highlight on an invisible frame. */
5186 if (x_highlight_frame
== f
)
5187 x_highlight_frame
= 0;
5189 if (! f
->async_visible
&& ! f
->async_iconified
)
5196 #ifdef USE_X_TOOLKIT
5197 if (! XWithdrawWindow (x_current_display
, XtWindow (f
->display
.x
->widget
),
5198 DefaultScreen (x_current_display
)))
5199 #else /* not USE_X_TOOLKIT */
5200 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
5201 DefaultScreen (x_current_display
)))
5202 #endif /* not USE_X_TOOLKIT */
5204 UNBLOCK_INPUT_RESIGNAL
;
5205 error ("can't notify window manager of window withdrawal");
5208 #else /* ! defined (HAVE_X11R4) */
5211 /* Tell the window manager what we're going to do. */
5212 if (! EQ (Vx_no_window_manager
, Qt
))
5216 unmap
.xunmap
.type
= UnmapNotify
;
5217 #ifdef USE_X_TOOLKIT
5218 unmap
.xunmap
.window
= XtWindow (f
->display
.x
->widget
);
5219 #else /* not USE_X_TOOLKIT */
5220 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
5221 #endif /* not USE_X_TOOLKIT */
5222 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5223 unmap
.xunmap
.from_configure
= False
;
5224 if (! XSendEvent (x_current_display
,
5225 DefaultRootWindow (x_current_display
),
5227 SubstructureRedirectMask
|SubstructureNotifyMask
,
5230 UNBLOCK_INPUT_RESIGNAL
;
5231 error ("can't notify window manager of withdrawal");
5235 /* Unmap the window ourselves. Cheeky! */
5236 #ifdef USE_X_TOOLKIT
5237 XUnmapWindow (x_current_display
, XtWindow (f
->display
.x
->widget
));
5238 #else /* not USE_X_TOOLKIT */
5239 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
5240 #endif /* not USE_X_TOOLKIT */
5241 #else /* ! defined (HAVE_X11) */
5243 XUnmapWindow (FRAME_X_WINDOW (f
));
5244 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
5245 if (f
->display
.x
->icon_desc
!= 0)
5246 XUnmapWindow (f
->display
.x
->icon_desc
);
5248 #endif /* ! defined (HAVE_X11) */
5249 #endif /* ! defined (HAVE_X11R4) */
5255 /* Change window state from mapped to iconified. */
5263 /* Don't keep the highlight on an invisible frame. */
5264 if (x_highlight_frame
== f
)
5265 x_highlight_frame
= 0;
5267 if (f
->async_iconified
)
5270 #ifdef USE_X_TOOLKIT
5272 result
= XIconifyWindow (x_current_display
,
5273 XtWindow (f
->display
.x
->widget
),
5274 DefaultScreen (x_current_display
));
5278 error ("Can't notify window manager of iconification.");
5280 f
->async_iconified
= 1;
5285 #else /* not USE_X_TOOLKIT */
5290 /* Since we don't know which revision of X we're running, we'll use both
5291 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5293 /* X11R4: send a ClientMessage to the window manager using the
5294 WM_CHANGE_STATE type. */
5298 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5299 message
.xclient
.type
= ClientMessage
;
5300 message
.xclient
.message_type
= Xatom_wm_change_state
;
5301 message
.xclient
.format
= 32;
5302 message
.xclient
.data
.l
[0] = IconicState
;
5304 if (! XSendEvent (x_current_display
,
5305 DefaultRootWindow (x_current_display
),
5307 SubstructureRedirectMask
| SubstructureNotifyMask
,
5310 UNBLOCK_INPUT_RESIGNAL
;
5311 error ("Can't notify window manager of iconification.");
5315 /* X11R3: set the initial_state field of the window manager hints to
5317 x_wm_set_window_state (f
, IconicState
);
5319 if (!FRAME_VISIBLE_P (f
))
5321 /* If the frame was withdrawn, before, we must map it. */
5322 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5323 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5324 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5327 f
->async_iconified
= 1;
5328 #else /* ! defined (HAVE_X11) */
5329 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5331 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
5332 if (f
->display
.x
->icon_desc
!= 0)
5334 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
5337 #endif /* ! defined (HAVE_X11) */
5341 #endif /* not USE_X_TOOLKIT */
5344 /* Destroy the X window of frame F. */
5346 x_destroy_window (f
)
5351 if (f
->display
.x
->icon_desc
!= 0)
5352 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5353 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5354 #ifdef USE_X_TOOLKIT
5355 XtDestroyWidget (f
->display
.x
->widget
);
5356 free_frame_menubar (f
);
5357 #endif /* USE_X_TOOLKIT */
5359 free_frame_faces (f
);
5362 xfree (f
->display
.x
);
5364 if (f
== x_focus_frame
)
5366 if (f
== x_highlight_frame
)
5367 x_highlight_frame
= 0;
5372 /* Manage event queues for X10. */
5376 /* Manage event queues.
5378 This code is only used by the X10 support.
5380 We cannot leave events in the X queue and get them when we are ready
5381 because X does not provide a subroutine to get only a certain kind
5382 of event but not block if there are no queued events of that kind.
5384 Therefore, we must examine events as they come in and copy events
5385 of certain kinds into our private queues.
5387 All ExposeRegion events are put in x_expose_queue.
5388 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5391 /* Write the event *P_XREP into the event queue *QUEUE.
5392 If the queue is full, do nothing, but return nonzero. */
5395 enqueue_event (p_xrep
, queue
)
5396 register XEvent
*p_xrep
;
5397 register struct event_queue
*queue
;
5399 int newindex
= queue
->windex
+ 1;
5400 if (newindex
== EVENT_BUFFER_SIZE
)
5402 if (newindex
== queue
->rindex
)
5404 queue
->xrep
[queue
->windex
] = *p_xrep
;
5405 queue
->windex
= newindex
;
5409 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5410 If *QUEUE is empty, do nothing and return 0. */
5413 dequeue_event (p_xrep
, queue
)
5414 register XEvent
*p_xrep
;
5415 register struct event_queue
*queue
;
5417 if (queue
->windex
== queue
->rindex
)
5419 *p_xrep
= queue
->xrep
[queue
->rindex
++];
5420 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
5425 /* Return the number of events buffered in *QUEUE. */
5428 queue_event_count (queue
)
5429 register struct event_queue
*queue
;
5431 int tem
= queue
->windex
- queue
->rindex
;
5434 return EVENT_BUFFER_SIZE
+ tem
;
5437 /* Return nonzero if mouse input is pending. */
5440 mouse_event_pending_p ()
5442 return queue_event_count (&x_mouse_queue
);
5444 #endif /* HAVE_X11 */
5446 /* Setting window manager hints. */
5450 /* Record the gravity used previously, in case CHANGE_GRAVITY is 0. */
5451 static int previous_gravity
;
5453 /* SPEC_X and SPEC_Y are the specified positions.
5454 We look only at their sign, to decide the gravity.
5455 If CHANGE_GRAVITY is 0, we ignore SPEC_X and SPEC_Y
5456 and leave the gravity unchanged. */
5458 x_wm_set_size_hint (f
, prompting
, change_gravity
, spec_x
, spec_y
)
5464 XSizeHints size_hints
;
5466 #ifdef USE_X_TOOLKIT
5469 Dimension widget_width
, widget_height
;
5470 Window window
= XtWindow (f
->display
.x
->widget
);
5471 #else /* not USE_X_TOOLKIT */
5472 Window window
= FRAME_X_WINDOW (f
);
5473 #endif /* not USE_X_TOOLKIT */
5475 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5477 flexlines
= f
->height
;
5479 size_hints
.x
= f
->display
.x
->left_pos
;
5480 size_hints
.y
= f
->display
.x
->top_pos
;
5481 #ifdef USE_X_TOOLKIT
5482 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5483 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5484 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5485 size_hints
.height
= widget_height
;
5486 size_hints
.width
= widget_width
;
5487 #else /* not USE_X_TOOLKIT */
5488 size_hints
.height
= PIXEL_HEIGHT (f
);
5489 size_hints
.width
= PIXEL_WIDTH (f
);
5490 #endif /* not USE_X_TOOLKIT */
5491 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5492 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
5494 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5495 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5498 int base_width
, base_height
;
5500 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5501 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5504 int min_rows
= 0, min_cols
= 0;
5505 check_frame_size (f
, &min_rows
, &min_cols
);
5507 /* The window manager uses the base width hints to calculate the
5508 current number of rows and columns in the frame while
5509 resizing; min_width and min_height aren't useful for this
5510 purpose, since they might not give the dimensions for a
5511 zero-row, zero-column frame.
5513 We use the base_width and base_height members if we have
5514 them; otherwise, we set the min_width and min_height members
5515 to the size for a zero x zero frame. */
5518 size_hints
.flags
|= PBaseSize
;
5519 size_hints
.base_width
= base_width
;
5520 size_hints
.base_height
= base_height
;
5521 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5522 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5524 size_hints
.min_width
= base_width
;
5525 size_hints
.min_height
= base_height
;
5532 size_hints
.flags
|= prompting
;
5535 XSizeHints hints
; /* Sometimes I hate X Windows... */
5537 if (XGetNormalHints (x_current_display
, window
, &hints
) == 0)
5539 if (hints
.flags
& PSize
)
5540 size_hints
.flags
|= PSize
;
5541 if (hints
.flags
& PPosition
)
5542 size_hints
.flags
|= PPosition
;
5543 if (hints
.flags
& USPosition
)
5544 size_hints
.flags
|= USPosition
;
5545 if (hints
.flags
& USSize
)
5546 size_hints
.flags
|= USSize
;
5548 #if defined (PWinGravity)
5551 switch (((spec_x
< 0) << 1) + (spec_y
< 0))
5554 size_hints
.win_gravity
= NorthWestGravity
;
5557 size_hints
.win_gravity
= NorthEastGravity
;
5560 size_hints
.win_gravity
= SouthWestGravity
;
5563 size_hints
.win_gravity
= SouthEastGravity
;
5566 previous_gravity
= size_hints
.win_gravity
;
5569 size_hints
.win_gravity
= previous_gravity
;
5571 size_hints
.flags
|= PWinGravity
;
5572 #endif /* PWinGravity */
5575 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
5577 XSetNormalHints (x_current_display
, window
, &size_hints
);
5581 /* Used for IconicState or NormalState */
5582 x_wm_set_window_state (f
, state
)
5586 #ifdef USE_X_TOOLKIT
5587 Window window
= XtWindow (f
->display
.x
->widget
);
5588 #else /* not USE_X_TOOLKIT */
5589 Window window
= FRAME_X_WINDOW (f
);
5590 #endif /* not USE_X_TOOLKIT */
5592 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5593 f
->display
.x
->wm_hints
.initial_state
= state
;
5595 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5598 x_wm_set_icon_pixmap (f
, icon_pixmap
)
5602 Window window
= FRAME_X_WINDOW (f
);
5606 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5607 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5610 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5612 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5615 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5619 Window window
= FRAME_X_WINDOW (f
);
5621 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5622 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5623 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5625 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5629 /* Initialization. */
5631 #ifdef USE_X_TOOLKIT
5632 static XrmOptionDescRec emacs_options
[] = {
5633 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5634 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5636 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5637 XrmoptionSepArg
, NULL
},
5638 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5640 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5641 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5642 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5643 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5644 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5645 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5646 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5648 #endif /* USE_X_TOOLKIT */
5651 x_term_init (display_name
)
5658 #ifndef F_SETOWN_BUG
5660 extern int old_fcntl_owner
;
5661 #endif /* ! defined (F_SETOWN) */
5662 #endif /* F_SETOWN_BUG */
5664 x_focus_frame
= x_highlight_frame
= 0;
5666 #ifdef USE_X_TOOLKIT
5667 argv
= (char **) XtMalloc (3 * sizeof (char *));
5669 argv
[1] = "-display";
5670 argv
[2] = display_name
;
5672 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
5673 emacs_options
, XtNumber (emacs_options
),
5677 x_current_display
= XtDisplay (Xt_app_shell
);
5679 #else /* not USE_X_TOOLKIT */
5680 x_current_display
= XOpenDisplay (display_name
);
5681 #endif /* not USE_X_TOOLKIT */
5682 if (x_current_display
== 0)
5683 fatal ("X server %s not responding.\n\
5684 Check the DISPLAY environment variable or use \"-d\"\n",
5690 XSetAfterFunction (x_current_display
, x_trace_wire
);
5692 hostname
= get_system_name ();
5693 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5696 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
5699 /* Figure out which modifier bits mean what. */
5700 x_find_modifier_meanings ();
5702 /* Get the scroll bar cursor. */
5703 x_vertical_scroll_bar_cursor
5704 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
5707 /* Watch for PropertyNotify events on the root window; we use them
5708 to figure out when to invalidate our cache of the cut buffers. */
5709 x_watch_cut_buffer_cache ();
5712 if (ConnectionNumber (x_current_display
) != 0)
5713 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
5714 change_input_fd (ConnectionNumber (x_current_display
));
5716 #endif /* ! defined (HAVE_X11) */
5718 #ifndef F_SETOWN_BUG
5720 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
5721 #ifdef F_SETOWN_SOCK_NEG
5722 /* stdin is a socket here */
5723 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
5724 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5725 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
5726 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5727 #endif /* ! defined (F_SETOWN) */
5728 #endif /* F_SETOWN_BUG */
5732 #endif /* ! defined (SIGIO) */
5734 expose_all_windows
= 0;
5736 clear_frame_hook
= XTclear_frame
;
5737 clear_end_of_line_hook
= XTclear_end_of_line
;
5738 ins_del_lines_hook
= XTins_del_lines
;
5739 change_line_highlight_hook
= XTchange_line_highlight
;
5740 insert_glyphs_hook
= XTinsert_glyphs
;
5741 write_glyphs_hook
= XTwrite_glyphs
;
5742 delete_glyphs_hook
= XTdelete_glyphs
;
5743 ring_bell_hook
= XTring_bell
;
5744 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5745 set_terminal_modes_hook
= XTset_terminal_modes
;
5746 update_begin_hook
= XTupdate_begin
;
5747 update_end_hook
= XTupdate_end
;
5748 set_terminal_window_hook
= XTset_terminal_window
;
5749 read_socket_hook
= XTread_socket
;
5750 frame_up_to_date_hook
= XTframe_up_to_date
;
5751 cursor_to_hook
= XTcursor_to
;
5752 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5753 mouse_position_hook
= XTmouse_position
;
5754 frame_rehighlight_hook
= XTframe_rehighlight
;
5755 frame_raise_lower_hook
= XTframe_raise_lower
;
5756 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5757 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5758 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5759 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5761 scroll_region_ok
= 1; /* we'll scroll partial frames */
5762 char_ins_del_ok
= 0; /* just as fast to write the line */
5763 line_ins_del_ok
= 1; /* we'll just blt 'em */
5764 fast_clear_end_of_line
= 1; /* X does this well */
5765 memory_below_frame
= 0; /* we don't remember what scrolls
5769 /* Try to use interrupt input; if we can't, then start polling. */
5770 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5772 /* Note that there is no real way portable across R3/R4 to get the
5773 original error handler. */
5774 XHandleError (x_error_quitter
);
5775 XHandleIOError (x_io_error_quitter
);
5777 /* Disable Window Change signals; they are handled by X events. */
5779 signal (SIGWINCH
, SIG_DFL
);
5780 #endif /* ! defined (SIGWINCH) */
5782 signal (SIGPIPE
, x_connection_closed
);
5788 staticpro (&last_mouse_scroll_bar
);
5789 last_mouse_scroll_bar
= Qnil
;
5790 staticpro (&mouse_face_window
);
5791 mouse_face_window
= Qnil
;
5793 #endif /* ! defined (HAVE_X11) */
5794 #endif /* ! defined (HAVE_X_WINDOWS) */