1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995 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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Xt features made by Fred Pierresteguy. */
23 /* On 4.3 these lose if they come after xterm.h. */
24 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
25 /* Putting these at the beginning seems to be standard for other .c files. */
32 /* Need syssignal.h for various externs and definitions that may be required
33 by some configurations for calls to signal later in this source file. */
34 #include "syssignal.h"
39 #include "blockinput.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
44 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
55 #include <sys/ioctl.h>
56 #endif /* ! defined (BSD) */
61 #ifndef INCLUDED_FCNTL
68 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
69 /* #include <sys/param.h> */
72 #include "dispextern.h"
73 #include "termhooks.h"
85 #include "intervals.h"
88 extern void free_frame_menubar ();
89 extern FRAME_PTR
x_menubar_window_to_frame ();
90 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
92 extern void _XEditResCheckMessages ();
93 #endif /* not NO_EDITRES */
94 #endif /* USE_X_TOOLKIT */
97 #define x_any_window_to_frame x_window_to_frame
98 #define x_top_window_to_frame x_window_to_frame
103 #ifndef XtNinitialState
104 #define XtNinitialState "initialState"
109 /* So we can do setlocale. */
114 /* For XlibDisplayWriting */
115 #include <X11/Xlibint.h>
119 #define min(a,b) ((a)<(b) ? (a) : (b))
122 #define max(a,b) ((a)>(b) ? (a) : (b))
125 /* This is a chain of structures for all the X displays currently in use. */
126 struct x_display_info
*x_display_list
;
128 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
129 one for each element of x_display_list and in the same order.
130 NAME is the name of the frame.
131 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
132 Lisp_Object x_display_name_list
;
134 /* Frame being updated by update_frame. This is declared in term.c.
135 This is set by update_begin and looked at by all the
136 XT functions. It is zero while not inside an update.
137 In that case, the XT functions assume that `selected_frame'
138 is the frame to apply to. */
139 extern struct frame
*updating_frame
;
141 /* This is a frame waiting to be autoraised, within XTread_socket. */
142 struct frame
*pending_autoraise_frame
;
145 /* The application context for Xt use. */
146 XtAppContext Xt_app_con
;
148 static String Xt_default_resources
[] =
154 /* During an update, maximum vpos for ins/del line operations to affect. */
156 static int flexlines
;
158 /* During an update, nonzero if chars output now should be highlighted. */
160 static int highlight
;
162 /* Nominal cursor position -- where to draw output.
163 During an update, these are different from the cursor-box position. */
170 In order to avoid asking for motion events and then throwing most
171 of them away or busy-polling the server for mouse positions, we ask
172 the server for pointer motion hints. This means that we get only
173 one event per group of mouse movements. "Groups" are delimited by
174 other kinds of events (focus changes and button clicks, for
175 example), or by XQueryPointer calls; when one of these happens, we
176 get another MotionNotify event the next time the mouse moves. This
177 is at least as efficient as getting motion events when mouse
178 tracking is on, and I suspect only negligibly worse when tracking
181 The silly O'Reilly & Associates Nutshell guides barely document
182 pointer motion hints at all (I think you have to infer how they
183 work from an example), and the description of XQueryPointer doesn't
184 mention that calling it causes you to get another motion hint from
185 the server, which is very important. */
187 /* Where the mouse was last time we reported a mouse event. */
188 static FRAME_PTR last_mouse_frame
;
189 static XRectangle last_mouse_glyph
;
191 /* The scroll bar in which the last X motion event occurred.
193 If the last X motion event occurred in a scroll bar, we set this
194 so XTmouse_position can know whether to report a scroll bar motion or
197 If the last X motion event didn't occur in a scroll bar, we set this
198 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
199 static Lisp_Object last_mouse_scroll_bar
;
201 /* This is a hack. We would really prefer that XTmouse_position would
202 return the time associated with the position it returns, but there
203 doesn't seem to be any way to wrest the timestamp from the server
204 along with the position query. So, we just keep track of the time
205 of the last movement we received, and return that in hopes that
206 it's somewhat accurate. */
207 static Time last_mouse_movement_time
;
209 /* Incremented by XTread_socket whenever it really tries to read events. */
211 static int volatile input_signal_count
;
213 static int input_signal_count
;
216 /* Used locally within XTread_socket. */
217 static int x_noop_count
;
219 /* Initial values of argv and argc. */
220 extern char **initial_argv
;
221 extern int initial_argc
;
223 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
225 /* Tells if a window manager is present or not. */
227 extern Lisp_Object Vx_no_window_manager
;
229 /* Nonzero enables some debugging for the X interface code. */
232 extern Lisp_Object Qface
, Qmouse_face
;
236 /* A mask of extra modifier bits to put into every keyboard char. */
237 extern int extra_keyboard_modifiers
;
239 static Lisp_Object Qvendor_specific_keysyms
;
241 extern XrmDatabase
x_load_resources ();
243 extern Lisp_Object
x_icon_type ();
245 void x_delete_display ();
247 static void redraw_previous_char ();
248 static void redraw_following_char ();
249 static unsigned int x_x_to_emacs_modifiers ();
251 static int fast_find_position ();
252 static void note_mouse_highlight ();
253 static void clear_mouse_face ();
254 static void show_mouse_face ();
255 static void do_line_dance ();
257 static int XTcursor_to ();
258 static int XTclear_end_of_line ();
259 static int x_io_error_quitter ();
260 void x_catch_errors ();
261 void x_uncatch_errors ();
264 /* This is a function useful for recording debugging information
265 about the sequence of occurrences in this file. */
273 struct record event_record
[100];
275 int event_record_index
;
277 record_event (locus
, type
)
281 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
282 event_record_index
= 0;
284 event_record
[event_record_index
].locus
= locus
;
285 event_record
[event_record_index
].type
= type
;
286 event_record_index
++;
291 /* Return the struct x_display_info corresponding to DPY. */
293 struct x_display_info
*
294 x_display_info_for_display (dpy
)
297 struct x_display_info
*dpyinfo
;
299 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
300 if (dpyinfo
->display
== dpy
)
306 /* Starting and ending updates.
308 These hooks are called by update_frame at the beginning and end
309 of a frame update. We record in `updating_frame' the identity
310 of the frame being updated, so that the XT... functions do not
311 need to take a frame as argument. Most of the XT... functions
312 should never be called except during an update, the only exceptions
313 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
324 flexlines
= f
->height
;
329 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
331 /* Don't do highlighting for mouse motion during the update. */
332 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
334 /* If the frame needs to be redrawn,
335 simply forget about any prior mouse highlighting. */
336 if (FRAME_GARBAGED_P (f
))
337 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
339 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
341 int firstline
, lastline
, i
;
342 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
344 /* Find the first, and the last+1, lines affected by redisplay. */
345 for (firstline
= 0; firstline
< f
->height
; firstline
++)
346 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
349 lastline
= f
->height
;
350 for (i
= f
->height
- 1; i
>= 0; i
--)
352 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
358 /* Can we tell that this update does not affect the window
359 where the mouse highlight is? If so, no need to turn off.
360 Likewise, don't do anything if the frame is garbaged;
361 in that case, the FRAME_CURRENT_GLYPHS that we would use
362 are all wrong, and we will redisplay that line anyway. */
363 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
364 || lastline
< XFASTINT (w
->top
)))
365 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
381 x_display_cursor (f
, 1);
383 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
384 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
386 /* This fails in the case of having updated only the echo area
387 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
388 has no relation to the current contents, and its charstarts
389 have no relation to the contents of the window-buffer.
390 I don't know a clean way to check
391 for that case. window_end_valid isn't set up yet. */
392 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
393 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
394 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
397 XFlush (FRAME_X_DISPLAY (f
));
401 /* This is called after a redisplay on frame F. */
404 XTframe_up_to_date (f
)
408 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
409 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
411 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
412 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
413 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
414 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
419 /* External interface to control of standout mode.
420 Call this when about to modify line at position VPOS
421 and not change whether it is highlighted. */
423 XTreassert_line_highlight (new, vpos
)
429 /* Call this when about to modify line at position VPOS
430 and change whether it is highlighted. */
433 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
434 int new_highlight
, vpos
, first_unused_hpos
;
436 highlight
= new_highlight
;
437 XTcursor_to (vpos
, 0);
438 XTclear_end_of_line (updating_frame
->width
);
441 /* This is used when starting Emacs and when restarting after suspend.
442 When starting Emacs, no X window is mapped. And nothing must be done
443 to Emacs's own window if it is suspended (though that rarely happens). */
446 XTset_terminal_modes ()
450 /* This is called when exiting or suspending Emacs.
451 Exiting will make the X-windows go away, and suspending
452 requires no action. */
455 XTreset_terminal_modes ()
457 /* XTclear_frame (); */
460 /* Set the nominal cursor position of the frame.
461 This is where display update commands will take effect.
462 This does not affect the place where the cursor-box is displayed. */
465 XTcursor_to (row
, col
)
466 register int row
, col
;
474 if (updating_frame
== 0)
477 x_display_cursor (selected_frame
, 1);
478 XFlush (FRAME_X_DISPLAY (selected_frame
));
483 /* Display a sequence of N glyphs found at GP.
484 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
485 HL is 1 if this text is highlighted, 2 if the cursor is on it,
486 3 if should appear in its mouse-face.
487 JUST_FOREGROUND if 1 means draw only the foreground;
488 don't alter the background.
490 FONT is the default font to use (for glyphs whose font-code is 0).
492 Since the display generation code is responsible for calling
493 compute_char_face and compute_glyph_face on everything it puts in
494 the display structure, we can assume that the face code on each
495 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
496 to which we can actually apply intern_face.
497 Call this function with input blocked. */
500 /* This is the multi-face code. */
503 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
506 register GLYPH
*gp
; /* Points to first GLYPH. */
507 register int n
; /* Number of glyphs to display. */
511 /* Holds characters to be displayed. */
512 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
513 register char *cp
; /* Steps through buf[]. */
514 register int tlen
= GLYPH_TABLE_LENGTH
;
515 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
516 Window window
= FRAME_X_WINDOW (f
);
517 int orig_left
= left
;
521 /* Get the face-code of the next GLYPH. */
525 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
526 cf
= FAST_GLYPH_FACE (g
);
528 /* Find the run of consecutive glyphs with the same face-code.
529 Extract their character codes into BUF. */
534 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
535 if (FAST_GLYPH_FACE (g
) != cf
)
538 *cp
++ = FAST_GLYPH_CHAR (g
);
543 /* LEN gets the length of the run. */
546 /* Now output this run of chars, with the font and pixel values
547 determined by the face code CF. */
549 struct face
*face
= FRAME_DEFAULT_FACE (f
);
550 XFontStruct
*font
= FACE_FONT (face
);
551 GC gc
= FACE_GC (face
);
554 /* HL = 3 means use a mouse face previously chosen. */
556 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
558 /* First look at the face of the text itself. */
561 /* It's possible for the display table to specify
562 a face code that is out of range. Use 0 in that case. */
563 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
564 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
568 face
= FRAME_MODE_LINE_FACE (f
);
570 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
571 font
= FACE_FONT (face
);
573 if (FACE_STIPPLE (face
))
577 /* Then comes the distinction between modeline and normal text. */
582 face
= FRAME_MODE_LINE_FACE (f
);
583 font
= FACE_FONT (face
);
585 if (FACE_STIPPLE (face
))
589 #define FACE_DEFAULT (~0)
591 /* Now override that if the cursor's on this character. */
594 /* The cursor overrides stippling. */
598 || face
->font
== (XFontStruct
*) FACE_DEFAULT
599 || face
->font
== f
->output_data
.x
->font
)
600 && face
->background
== f
->output_data
.x
->background_pixel
601 && face
->foreground
== f
->output_data
.x
->foreground_pixel
)
603 gc
= f
->output_data
.x
->cursor_gc
;
605 /* Cursor on non-default face: must merge. */
611 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
612 xgcv
.foreground
= face
->background
;
613 /* If the glyph would be invisible,
614 try a different foreground. */
615 if (xgcv
.foreground
== xgcv
.background
)
616 xgcv
.foreground
= face
->foreground
;
617 if (xgcv
.foreground
== xgcv
.background
)
618 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
619 if (xgcv
.foreground
== xgcv
.background
)
620 xgcv
.foreground
= face
->foreground
;
621 /* Make sure the cursor is distinct from text in this face. */
622 if (xgcv
.background
== face
->background
623 && xgcv
.foreground
== face
->foreground
)
625 xgcv
.background
= face
->foreground
;
626 xgcv
.foreground
= face
->background
;
628 xgcv
.font
= face
->font
->fid
;
629 xgcv
.graphics_exposures
= 0;
630 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
631 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
632 XChangeGC (FRAME_X_DISPLAY (f
),
633 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
636 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
637 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
638 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
640 /* If this code is restored, it must also reset to the default stipple
642 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
643 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
648 if (font
== (XFontStruct
*) FACE_DEFAULT
)
649 font
= f
->output_data
.x
->font
;
652 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
653 left
, top
+ FONT_BASE (font
), buf
, len
);
658 /* Turn stipple on. */
659 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
661 /* Draw stipple on background. */
662 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
664 FONT_WIDTH (font
) * len
,
667 /* Turn stipple off. */
668 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
670 /* Draw the text, solidly, onto the stipple pattern. */
671 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
672 left
, top
+ FONT_BASE (font
), buf
, len
);
675 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
676 left
, top
+ FONT_BASE (font
), buf
, len
);
678 /* Clear the rest of the line's height. */
679 if (f
->output_data
.x
->line_height
!= FONT_HEIGHT (font
))
680 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
681 top
+ FONT_HEIGHT (font
),
682 FONT_WIDTH (font
) * len
,
683 /* This is how many pixels of height
685 f
->output_data
.x
->line_height
- FONT_HEIGHT (font
),
689 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
690 which often is not up to date yet. */
691 if (!just_foreground
)
693 if (left
== orig_left
)
694 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
695 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
697 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
698 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
702 /* We should probably check for XA_UNDERLINE_POSITION and
703 XA_UNDERLINE_THICKNESS properties on the font, but let's
704 just get the thing working, and come back to that. */
706 int underline_position
= 1;
708 if (font
->descent
<= underline_position
)
709 underline_position
= font
->descent
- 1;
712 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
716 + underline_position
),
717 len
* FONT_WIDTH (font
), 1);
720 left
+= len
* FONT_WIDTH (font
);
727 /* This is the old single-face code. */
730 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
733 register GLYPH
*gp
; /* Points to first GLYPH. */
734 register int n
; /* Number of glyphs to display. */
739 Window window
= FRAME_X_WINDOW (f
);
740 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
741 : (hl
? f
->output_data
.x
->reverse_gc
742 : f
->output_data
.x
->normal_gc
));
744 if (sizeof (GLYPH
) == sizeof (XChar2b
))
745 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
746 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
747 else if (sizeof (GLYPH
) == sizeof (unsigned char))
748 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
749 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
751 /* What size of glyph ARE you using? And does X have a function to
757 /* Output some text at the nominal frame cursor position.
758 Advance the cursor over the text.
759 Output LEN glyphs at START.
761 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
762 controls the pixel values used for foreground and background. */
765 XTwrite_glyphs (start
, len
)
766 register GLYPH
*start
;
769 register int temp_length
;
780 /* If not within an update,
781 output at the frame's visible cursor. */
782 curs_x
= f
->cursor_x
;
783 curs_y
= f
->cursor_y
;
787 CHAR_TO_PIXEL_COL (f
, curs_x
),
788 CHAR_TO_PIXEL_ROW (f
, curs_y
),
789 start
, len
, highlight
, 0);
791 /* If we drew on top of the cursor, note that it is turned off. */
792 if (curs_y
== f
->phys_cursor_y
793 && curs_x
<= f
->phys_cursor_x
794 && curs_x
+ len
> f
->phys_cursor_x
)
795 f
->phys_cursor_x
= -1;
797 if (updating_frame
== 0)
800 x_display_cursor (f
, 1);
809 /* Clear to the end of the line.
810 Erase the current text line from the nominal cursor position (inclusive)
811 to column FIRST_UNUSED (exclusive). The idea is that everything
812 from FIRST_UNUSED onward is already erased. */
815 XTclear_end_of_line (first_unused
)
816 register int first_unused
;
818 struct frame
*f
= updating_frame
;
824 if (curs_y
< 0 || curs_y
>= f
->height
)
826 if (first_unused
<= 0)
829 if (first_unused
>= f
->width
)
830 first_unused
= f
->width
;
836 /* Notice if the cursor will be cleared by this operation. */
837 if (curs_y
== f
->phys_cursor_y
838 && curs_x
<= f
->phys_cursor_x
839 && f
->phys_cursor_x
< first_unused
)
840 f
->phys_cursor_x
= -1;
842 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
843 CHAR_TO_PIXEL_COL (f
, curs_x
),
844 CHAR_TO_PIXEL_ROW (f
, curs_y
),
845 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
846 f
->output_data
.x
->line_height
, False
);
848 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
858 struct frame
*f
= updating_frame
;
863 f
->phys_cursor_x
= -1; /* Cursor not visible. */
864 curs_x
= 0; /* Nominal cursor position is top left. */
869 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
871 /* We have to clear the scroll bars, too. If we have changed
872 colors or something like that, then they should be notified. */
873 x_scroll_bar_clear (f
);
875 XFlush (FRAME_X_DISPLAY (f
));
880 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
881 always contain the right glyphs to use.
883 It also needs to be changed to look at the details of the font and
884 see whether there is really overlap, and do nothing when there is
885 not. This can use font_char_overlap_left and font_char_overlap_right,
886 but just how to use them is not clear. */
888 /* Erase the character (if any) at the position just before X, Y in frame F,
889 then redraw it and the character before it.
890 This is necessary when we erase starting at X,
891 in case the character after X overlaps into the one before X.
892 Call this function with input blocked. */
895 redraw_previous_char (f
, x
, y
, highlight_flag
)
900 /* Erase the character before the new ones, in case
901 what was here before overlaps it.
902 Reoutput that character, and the previous character
903 (in case the previous character overlaps it). */
909 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
910 CHAR_TO_PIXEL_COL (f
, x
- 1),
911 CHAR_TO_PIXEL_ROW (f
, y
),
912 FONT_WIDTH (f
->output_data
.x
->font
),
913 f
->output_data
.x
->line_height
, False
);
915 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
916 CHAR_TO_PIXEL_ROW (f
, y
),
917 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
918 x
- start_x
, highlight_flag
, 1);
922 /* Erase the character (if any) at the position X, Y in frame F,
923 then redraw it and the character after it.
924 This is necessary when we erase endng at X,
925 in case the character after X overlaps into the one before X.
926 Call this function with input blocked. */
929 redraw_following_char (f
, x
, y
, highlight_flag
)
934 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
935 /* Erase the character after the new ones, in case
936 what was here before overlaps it.
937 Reoutput that character, and the following character
938 (in case the following character overlaps it). */
940 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
945 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
946 CHAR_TO_PIXEL_COL (f
, x
),
947 CHAR_TO_PIXEL_ROW (f
, y
),
948 FONT_WIDTH (f
->output_data
.x
->font
),
949 f
->output_data
.x
->line_height
, False
);
951 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
952 CHAR_TO_PIXEL_ROW (f
, y
),
953 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
954 end_x
- x
, highlight_flag
, 1);
959 #if 0 /* Not in use yet */
961 /* Return 1 if character C in font F extends past its left edge. */
964 font_char_overlap_left (font
, c
)
970 /* Find the bounding-box info for C. */
971 if (font
->per_char
== 0)
972 s
= &font
->max_bounds
;
975 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
978 /* Decode char into row number (byte 1) and code within row (byte 2). */
981 if (!(within
>= font
->min_char_or_byte2
982 && within
<= font
->max_char_or_byte2
983 && row
>= font
->min_byte1
984 && row
<= font
->max_byte1
))
986 /* If char is out of range, try the font's default char instead. */
987 c
= font
->default_char
;
988 row
= c
>> (BITS_PER_INT
- 8);
991 if (!(within
>= font
->min_char_or_byte2
992 && within
<= font
->max_char_or_byte2
993 && row
>= font
->min_byte1
994 && row
<= font
->max_byte1
))
995 /* Still out of range means this char does not overlap. */
998 /* We found the info for this char. */
999 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1003 return (s
&& s
->lbearing
< 0);
1006 /* Return 1 if character C in font F extends past its right edge. */
1009 font_char_overlap_right (font
, c
)
1015 /* Find the bounding-box info for C. */
1016 if (font
->per_char
== 0)
1017 s
= &font
->max_bounds
;
1020 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1023 /* Decode char into row number (byte 1) and code within row (byte 2). */
1026 if (!(within
>= font
->min_char_or_byte2
1027 && within
<= font
->max_char_or_byte2
1028 && row
>= font
->min_byte1
1029 && row
<= font
->max_byte1
))
1031 /* If char is out of range, try the font's default char instead. */
1032 c
= font
->default_char
;
1033 row
= c
>> (BITS_PER_INT
- 8);
1036 if (!(within
>= font
->min_char_or_byte2
1037 && within
<= font
->max_char_or_byte2
1038 && row
>= font
->min_byte1
1039 && row
<= font
->max_byte1
))
1040 /* Still out of range means this char does not overlap. */
1043 /* We found the info for this char. */
1044 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1048 return (s
&& s
->rbearing
>= s
->width
);
1052 /* Invert the middle quarter of the frame for .15 sec. */
1054 /* We use the select system call to do the waiting, so we have to make sure
1055 it's available. If it isn't, we just won't do visual bells. */
1056 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1058 /* Subtract the `struct timeval' values X and Y,
1059 storing the result in RESULT.
1060 Return 1 if the difference is negative, otherwise 0. */
1063 timeval_subtract (result
, x
, y
)
1064 struct timeval
*result
, x
, y
;
1066 /* Perform the carry for the later subtraction by updating y.
1067 This is safer because on some systems
1068 the tv_sec member is unsigned. */
1069 if (x
.tv_usec
< y
.tv_usec
)
1071 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1072 y
.tv_usec
-= 1000000 * nsec
;
1075 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1077 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1078 y
.tv_usec
+= 1000000 * nsec
;
1082 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1083 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1084 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1086 /* Return indication of whether the result should be considered negative. */
1087 return x
.tv_sec
< y
.tv_sec
;
1098 /* Create a GC that will use the GXxor function to flip foreground pixels
1099 into background pixels. */
1103 values
.function
= GXxor
;
1104 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1105 ^ f
->output_data
.x
->background_pixel
);
1107 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1108 GCFunction
| GCForeground
, &values
);
1112 int width
= PIXEL_WIDTH (f
);
1113 int height
= PIXEL_HEIGHT (f
);
1115 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1116 width
/4, height
/4, width
/2, height
/2);
1117 XFlush (FRAME_X_DISPLAY (f
));
1120 struct timeval wakeup
, now
;
1122 EMACS_GET_TIME (wakeup
);
1124 /* Compute time to wait until, propagating carry from usecs. */
1125 wakeup
.tv_usec
+= 150000;
1126 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1127 wakeup
.tv_usec
%= 1000000;
1129 /* Keep waiting until past the time wakeup. */
1132 struct timeval timeout
;
1134 EMACS_GET_TIME (timeout
);
1136 /* In effect, timeout = wakeup - timeout.
1137 Break if result would be negative. */
1138 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1141 /* Try to wait that long--but we might wake up sooner. */
1142 select (0, NULL
, NULL
, NULL
, &timeout
);
1146 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1147 width
/4, height
/4, width
/2, height
/2);
1148 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1149 XFlush (FRAME_X_DISPLAY (f
));
1159 /* Make audible bell. */
1161 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1165 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1168 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1170 XTflash (selected_frame
);
1176 XFlush (FRAME_X_DISPLAY (selected_frame
));
1181 /* Insert and delete character.
1182 These are not supposed to be used because we are supposed to turn
1183 off the feature of using them. */
1186 XTinsert_glyphs (start
, len
)
1187 register char *start
;
1200 /* Specify how many text lines, from the top of the window,
1201 should be affected by insert-lines and delete-lines operations.
1202 This, and those operations, are used only within an update
1203 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1206 XTset_terminal_window (n
)
1209 if (updating_frame
== 0)
1212 if ((n
<= 0) || (n
> updating_frame
->height
))
1213 flexlines
= updating_frame
->height
;
1218 /* These variables need not be per frame
1219 because redisplay is done on a frame-by-frame basis
1220 and the line dance for one frame is finished before
1221 anything is done for anoter frame. */
1223 /* Array of line numbers from cached insert/delete operations.
1224 line_dance[i] is the old position of the line that we want
1225 to move to line i, or -1 if we want a blank line there. */
1226 static int *line_dance
;
1228 /* Allocated length of that array. */
1229 static int line_dance_len
;
1231 /* Flag indicating whether we've done any work. */
1232 static int line_dance_in_progress
;
1234 /* Perform an insert-lines or delete-lines operation,
1235 inserting N lines or deleting -N lines at vertical position VPOS. */
1236 XTins_del_lines (vpos
, n
)
1239 register int fence
, i
;
1241 if (vpos
>= flexlines
)
1244 if (!line_dance_in_progress
)
1246 int ht
= updating_frame
->height
;
1247 if (ht
> line_dance_len
)
1249 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1250 line_dance_len
= ht
;
1252 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1253 line_dance_in_progress
= 1;
1257 if (n
> flexlines
- vpos
)
1258 n
= flexlines
- vpos
;
1260 for (i
= flexlines
; --i
>= fence
;)
1261 line_dance
[i
] = line_dance
[i
-n
];
1262 for (i
= fence
; --i
>= vpos
;)
1268 if (n
> flexlines
- vpos
)
1269 n
= flexlines
- vpos
;
1270 fence
= flexlines
- n
;
1271 for (i
= vpos
; i
< fence
; ++i
)
1272 line_dance
[i
] = line_dance
[i
+ n
];
1273 for (i
= fence
; i
< flexlines
; ++i
)
1278 /* Here's where we actually move the pixels around.
1279 Must be called with input blocked. */
1283 register int i
, j
, distance
;
1284 register struct frame
*f
;
1288 /* Must check this flag first. If it's not set, then not only is the
1289 array uninitialized, but we might not even have a frame. */
1290 if (!line_dance_in_progress
)
1298 intborder
= f
->output_data
.x
->internal_border_width
;
1300 x_display_cursor (updating_frame
, 0);
1302 for (i
= 0; i
< ht
; ++i
)
1303 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1305 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1306 && line_dance
[j
]-j
== distance
); ++j
);
1307 /* Copy [i,j) upward from [i+distance,j+distance) */
1308 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1309 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1310 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1311 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1312 (j
-i
) * f
->output_data
.x
->line_height
,
1313 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1317 for (i
= ht
; --i
>=0; )
1318 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1320 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1321 && line_dance
[j
]-j
== distance
););
1322 /* Copy (j,i] downward from (j+distance, i+distance] */
1323 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1324 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1325 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1326 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1327 (i
-j
) * f
->output_data
.x
->line_height
,
1328 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1332 for (i
= 0; i
< ht
; ++i
)
1333 if (line_dance
[i
] == -1)
1335 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1337 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1338 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1339 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1340 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1343 line_dance_in_progress
= 0;
1346 /* Support routines for exposure events. */
1347 static void clear_cursor ();
1349 /* Output into a rectangle of an X-window (for frame F)
1350 the characters in f->phys_lines that overlap that rectangle.
1351 TOP and LEFT are the position of the upper left corner of the rectangle.
1352 ROWS and COLS are the size of the rectangle.
1353 Call this function with input blocked. */
1356 dumprectangle (f
, left
, top
, cols
, rows
)
1358 register int left
, top
, cols
, rows
;
1360 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1361 int cursor_cleared
= 0;
1365 if (FRAME_GARBAGED_P (f
))
1368 /* Express rectangle as four edges, instead of position-and-size. */
1369 bottom
= top
+ rows
;
1370 right
= left
+ cols
;
1372 /* Convert rectangle edges in pixels to edges in chars.
1373 Round down for left and top, up for right and bottom. */
1374 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1375 left
= PIXEL_TO_CHAR_COL (f
, left
);
1376 bottom
+= (f
->output_data
.x
->line_height
- 1);
1377 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1378 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1379 right
= PIXEL_TO_CHAR_COL (f
, right
);
1381 /* Clip the rectangle to what can be visible. */
1386 if (right
> f
->width
)
1388 if (bottom
> f
->height
)
1391 /* Get size in chars of the rectangle. */
1392 cols
= right
- left
;
1393 rows
= bottom
- top
;
1395 /* If rectangle has zero area, return. */
1396 if (rows
<= 0) return;
1397 if (cols
<= 0) return;
1399 /* Turn off the cursor if it is in the rectangle.
1400 We will turn it back on afterward. */
1401 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1402 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1408 /* Display the text in the rectangle, one text line at a time. */
1410 for (y
= top
; y
< bottom
; y
++)
1412 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1414 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1418 CHAR_TO_PIXEL_COL (f
, left
),
1419 CHAR_TO_PIXEL_ROW (f
, y
),
1420 line
, min (cols
, active_frame
->used
[y
] - left
),
1421 active_frame
->highlight
[y
], 0);
1424 /* Turn the cursor on if we turned it off. */
1427 x_display_cursor (f
, 1);
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 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1440 f
->output_data
.x
->border_pixel
);
1442 x_update_cursor (f
, 1);
1446 frame_unhighlight (f
)
1449 /* We used to only do this if Vx_no_window_manager was non-nil, but
1450 the ICCCM (section 4.1.6) says that the window's border pixmap
1451 and border pixel are window attributes which are "private to the
1452 client", so we can always change it to whatever we want. */
1454 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1455 f
->output_data
.x
->border_tile
);
1457 x_update_cursor (f
, 1);
1460 static void XTframe_rehighlight ();
1461 static void x_frame_rehighlight ();
1463 /* The focus has changed. Update the frames as necessary to reflect
1464 the new situation. Note that we can't change the selected frame
1465 here, because the Lisp code we are interrupting might become confused.
1466 Each event gets marked with the frame in which it occurred, so the
1467 Lisp code can tell when the switch took place by examining the events. */
1470 x_new_focus_frame (dpyinfo
, frame
)
1471 struct x_display_info
*dpyinfo
;
1472 struct frame
*frame
;
1474 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1475 int events_enqueued
= 0;
1477 if (frame
!= dpyinfo
->x_focus_frame
)
1479 /* Set this before calling other routines, so that they see
1480 the correct value of x_focus_frame. */
1481 dpyinfo
->x_focus_frame
= frame
;
1483 if (old_focus
&& old_focus
->auto_lower
)
1484 x_lower_frame (old_focus
);
1487 selected_frame
= frame
;
1488 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1490 Fselect_window (selected_frame
->selected_window
);
1491 choose_minibuf_frame ();
1494 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1495 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1497 pending_autoraise_frame
= 0;
1500 x_frame_rehighlight (dpyinfo
);
1503 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1506 x_mouse_leave (dpyinfo
)
1507 struct x_display_info
*dpyinfo
;
1509 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1512 /* The focus has changed, or we have redirected a frame's focus to
1513 another frame (this happens when a frame uses a surrogate
1514 minibuffer frame). Shift the highlight as appropriate.
1516 The FRAME argument doesn't necessarily have anything to do with which
1517 frame is being highlighted or unhighlighted; we only use it to find
1518 the appropriate X display info. */
1520 XTframe_rehighlight (frame
)
1521 struct frame
*frame
;
1523 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
1527 x_frame_rehighlight (dpyinfo
)
1528 struct x_display_info
*dpyinfo
;
1530 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1532 if (dpyinfo
->x_focus_frame
)
1534 dpyinfo
->x_highlight_frame
1535 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
1536 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
1537 : dpyinfo
->x_focus_frame
);
1538 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
1540 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
1541 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1545 dpyinfo
->x_highlight_frame
= 0;
1547 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
1550 frame_unhighlight (old_highlight
);
1551 if (dpyinfo
->x_highlight_frame
)
1552 frame_highlight (dpyinfo
->x_highlight_frame
);
1556 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1558 /* Initialize mode_switch_bit and modifier_meaning. */
1560 x_find_modifier_meanings (dpyinfo
)
1561 struct x_display_info
*dpyinfo
;
1563 int min_code
, max_code
;
1566 XModifierKeymap
*mods
;
1568 dpyinfo
->meta_mod_mask
= 0;
1569 dpyinfo
->shift_lock_mask
= 0;
1570 dpyinfo
->alt_mod_mask
= 0;
1571 dpyinfo
->super_mod_mask
= 0;
1572 dpyinfo
->hyper_mod_mask
= 0;
1575 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1577 min_code
= dpyinfo
->display
->min_keycode
;
1578 max_code
= dpyinfo
->display
->max_keycode
;
1581 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1582 min_code
, max_code
- min_code
+ 1,
1584 mods
= XGetModifierMapping (dpyinfo
->display
);
1586 /* Scan the modifier table to see which modifier bits the Meta and
1587 Alt keysyms are on. */
1589 int row
, col
; /* The row and column in the modifier table. */
1591 for (row
= 3; row
< 8; row
++)
1592 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1595 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1597 /* Zeroes are used for filler. Skip them. */
1601 /* Are any of this keycode's keysyms a meta key? */
1605 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1607 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1613 dpyinfo
->meta_mod_mask
|= (1 << row
);
1618 dpyinfo
->alt_mod_mask
|= (1 << row
);
1623 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1628 dpyinfo
->super_mod_mask
|= (1 << row
);
1632 /* Ignore this if it's not on the lock modifier. */
1633 if ((1 << row
) == LockMask
)
1634 dpyinfo
->shift_lock_mask
= LockMask
;
1642 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1643 if (! dpyinfo
->meta_mod_mask
)
1645 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1646 dpyinfo
->alt_mod_mask
= 0;
1649 /* If some keys are both alt and meta,
1650 make them just meta, not alt. */
1651 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1653 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1656 XFree ((char *) syms
);
1657 XFreeModifiermap (mods
);
1660 /* Convert between the modifier bits X uses and the modifier bits
1663 x_x_to_emacs_modifiers (dpyinfo
, state
)
1664 struct x_display_info
*dpyinfo
;
1667 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1668 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1669 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1670 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1671 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1672 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1676 x_emacs_to_x_modifiers (dpyinfo
, state
)
1677 struct x_display_info
*dpyinfo
;
1680 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1681 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1682 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1683 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1684 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1685 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1688 /* Convert a keysym to its name. */
1691 x_get_keysym_name (keysym
)
1697 value
= XKeysymToString (keysym
);
1703 /* Mouse clicks and mouse movement. Rah. */
1705 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1706 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1707 that the glyph at X, Y occupies, if BOUNDS != 0.
1708 If NOCLIP is nonzero, do not force the value into range. */
1711 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1713 register int pix_x
, pix_y
;
1714 register int *x
, *y
;
1718 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1719 even for negative values. */
1721 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
1723 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
1725 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1726 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1730 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
1731 bounds
->height
= f
->output_data
.x
->line_height
;
1732 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1733 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1740 else if (pix_x
> f
->width
)
1745 else if (pix_y
> f
->height
)
1754 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1757 register int *pix_x
, *pix_y
;
1759 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1760 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1763 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1765 If the event is a button press, then note that we have grabbed
1769 construct_mouse_click (result
, event
, f
)
1770 struct input_event
*result
;
1771 XButtonEvent
*event
;
1774 /* Make the event type no_event; we'll change that when we decide
1776 result
->kind
= mouse_click
;
1777 result
->code
= event
->button
- Button1
;
1778 result
->timestamp
= event
->time
;
1779 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1781 | (event
->type
== ButtonRelease
1789 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1790 XSETFASTINT (result
->x
, column
);
1791 XSETFASTINT (result
->y
, row
);
1793 XSETINT (result
->x
, event
->x
);
1794 XSETINT (result
->y
, event
->y
);
1795 XSETFRAME (result
->frame_or_window
, f
);
1799 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1802 construct_menu_click (result
, event
, f
)
1803 struct input_event
*result
;
1804 XButtonEvent
*event
;
1807 /* Make the event type no_event; we'll change that when we decide
1809 result
->kind
= mouse_click
;
1810 XSETINT (result
->code
, event
->button
- Button1
);
1811 result
->timestamp
= event
->time
;
1812 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1814 | (event
->type
== ButtonRelease
1818 XSETINT (result
->x
, event
->x
);
1819 XSETINT (result
->y
, -1);
1820 XSETFRAME (result
->frame_or_window
, f
);
1823 /* Function to report a mouse movement to the mainstream Emacs code.
1824 The input handler calls this.
1826 We have received a mouse movement event, which is given in *event.
1827 If the mouse is over a different glyph than it was last time, tell
1828 the mainstream emacs code by setting mouse_moved. If not, ask for
1829 another motion event, so we can check again the next time it moves. */
1832 note_mouse_movement (frame
, event
)
1834 XMotionEvent
*event
;
1836 last_mouse_movement_time
= event
->time
;
1838 if (event
->window
!= FRAME_X_WINDOW (frame
))
1840 frame
->mouse_moved
= 1;
1841 last_mouse_scroll_bar
= Qnil
;
1843 note_mouse_highlight (frame
, -1, -1);
1845 /* Ask for another mouse motion event. */
1848 Window dummy_window
;
1850 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1851 &dummy_window
, &dummy_window
,
1852 &dummy
, &dummy
, &dummy
, &dummy
,
1853 (unsigned int *) &dummy
);
1857 /* Has the mouse moved off the glyph it was on at the last sighting? */
1858 else if (event
->x
< last_mouse_glyph
.x
1859 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1860 || event
->y
< last_mouse_glyph
.y
1861 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1863 frame
->mouse_moved
= 1;
1864 last_mouse_scroll_bar
= Qnil
;
1866 note_mouse_highlight (frame
, event
->x
, event
->y
);
1868 /* Ask for another mouse motion event. */
1871 Window dummy_window
;
1873 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1874 &dummy_window
, &dummy_window
,
1875 &dummy
, &dummy
, &dummy
, &dummy
,
1876 (unsigned int *) &dummy
);
1881 /* It's on the same glyph. Call XQueryPointer so we'll get an
1882 event the next time the mouse moves and we can see if it's
1883 *still* on the same glyph. */
1885 Window dummy_window
;
1887 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1888 &dummy_window
, &dummy_window
,
1889 &dummy
, &dummy
, &dummy
, &dummy
,
1890 (unsigned int *) &dummy
);
1894 /* This is used for debugging, to turn off note_mouse_highlight. */
1895 static int disable_mouse_highlight
;
1897 /* Take proper action when the mouse has moved to position X, Y on frame F
1898 as regards highlighting characters that have mouse-face properties.
1899 Also dehighlighting chars where the mouse was before.
1900 X and Y can be negative or out of range. */
1903 note_mouse_highlight (f
, x
, y
)
1907 int row
, column
, portion
;
1908 XRectangle new_glyph
;
1912 if (disable_mouse_highlight
)
1915 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1916 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1917 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1919 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1924 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1928 /* Find out which glyph the mouse is on. */
1929 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1930 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1932 /* Which window is that in? */
1933 window
= window_from_coordinates (f
, column
, row
, &portion
);
1934 w
= XWINDOW (window
);
1936 /* If we were displaying active text in another window, clear that. */
1937 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1938 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1940 /* Are we in a window whose display is up to date?
1941 And verify the buffer's text has not changed. */
1942 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1943 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1944 && EQ (w
->window_end_valid
, w
->buffer
)
1945 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1947 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1950 /* Find which buffer position the mouse corresponds to. */
1951 for (i
= column
; i
>= 0; i
--)
1955 /* Is it outside the displayed active region (if any)? */
1957 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1958 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1959 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1960 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1961 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1962 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1963 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1964 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1965 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1967 Lisp_Object mouse_face
, overlay
, position
;
1968 Lisp_Object
*overlay_vec
;
1969 int len
, noverlays
, ignor1
;
1970 struct buffer
*obuf
;
1973 /* If we get an out-of-range value, return now; avoid an error. */
1974 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1977 /* Make the window's buffer temporarily current for
1978 overlays_at and compute_char_face. */
1979 obuf
= current_buffer
;
1980 current_buffer
= XBUFFER (w
->buffer
);
1986 /* Yes. Clear the display of the old active region, if any. */
1987 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1989 /* Is this char mouse-active? */
1990 XSETINT (position
, pos
);
1993 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1995 /* Put all the overlays we want in a vector in overlay_vec.
1996 Store the length in len. */
1997 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1999 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2001 /* Find the highest priority overlay that has a mouse-face prop. */
2003 for (i
= 0; i
< noverlays
; i
++)
2005 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2006 if (!NILP (mouse_face
))
2008 overlay
= overlay_vec
[i
];
2013 /* If no overlay applies, get a text property. */
2015 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2017 /* Handle the overlay case. */
2018 if (! NILP (overlay
))
2020 /* Find the range of text around this char that
2021 should be active. */
2022 Lisp_Object before
, after
;
2025 before
= Foverlay_start (overlay
);
2026 after
= Foverlay_end (overlay
);
2027 /* Record this as the current active region. */
2028 fast_find_position (window
, before
,
2029 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2030 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2031 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2032 = !fast_find_position (window
, after
,
2033 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2034 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2035 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2036 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2037 = compute_char_face (f
, w
, pos
, 0, 0,
2038 &ignore
, pos
+ 1, 1);
2040 /* Display it as active. */
2041 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2043 /* Handle the text property case. */
2044 else if (! NILP (mouse_face
))
2046 /* Find the range of text around this char that
2047 should be active. */
2048 Lisp_Object before
, after
, beginning
, end
;
2051 beginning
= Fmarker_position (w
->start
);
2052 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2053 - XFASTINT (w
->window_end_pos
)));
2055 = Fprevious_single_property_change (make_number (pos
+ 1),
2057 w
->buffer
, beginning
);
2059 = Fnext_single_property_change (position
, Qmouse_face
,
2061 /* Record this as the current active region. */
2062 fast_find_position (window
, before
,
2063 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2064 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2065 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2066 = !fast_find_position (window
, after
,
2067 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2068 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2069 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2070 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2071 = compute_char_face (f
, w
, pos
, 0, 0,
2072 &ignore
, pos
+ 1, 1);
2074 /* Display it as active. */
2075 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2079 current_buffer
= obuf
;
2084 /* Find the row and column of position POS in window WINDOW.
2085 Store them in *COLUMNP and *ROWP.
2086 This assumes display in WINDOW is up to date.
2087 If POS is above start of WINDOW, return coords
2088 of start of first screen line.
2089 If POS is after end of WINDOW, return coords of end of last screen line.
2091 Value is 1 if POS is in range, 0 if it was off screen. */
2094 fast_find_position (window
, pos
, columnp
, rowp
)
2097 int *columnp
, *rowp
;
2099 struct window
*w
= XWINDOW (window
);
2100 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2105 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2106 int width
= window_internal_width (w
);
2109 int maybe_next_line
= 0;
2111 /* Find the right row. */
2116 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2117 if (linestart
> pos
)
2119 /* If the position sought is the end of the buffer,
2120 don't include the blank lines at the bottom of the window. */
2121 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2123 maybe_next_line
= 1;
2130 /* Find the right column with in it. */
2131 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2133 for (i
= 0; i
< width
; i
++)
2135 if (charstarts
[left
+ i
] == pos
)
2138 *columnp
= i
+ left
;
2141 else if (charstarts
[left
+ i
] > pos
)
2143 else if (charstarts
[left
+ i
] > 0)
2147 /* If we're looking for the end of the buffer,
2148 and we didn't find it in the line we scanned,
2149 use the start of the following line. */
2150 if (maybe_next_line
)
2161 /* Display the active region described by mouse_face_*
2162 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2165 show_mouse_face (dpyinfo
, hl
)
2166 struct x_display_info
*dpyinfo
;
2169 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2170 int width
= window_internal_width (w
);
2171 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2174 int old_curs_x
= curs_x
;
2175 int old_curs_y
= curs_y
;
2177 /* Set these variables temporarily
2178 so that if we have to turn the cursor off and on again
2179 we will put it back at the same place. */
2180 curs_x
= f
->phys_cursor_x
;
2181 curs_y
= f
->phys_cursor_y
;
2183 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2184 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2186 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2187 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2189 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2190 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2192 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2194 /* If the cursor's in the text we are about to rewrite,
2195 turn the cursor off. */
2197 && curs_x
>= column
- 1
2198 && curs_x
<= endcolumn
)
2200 x_display_cursor (f
, 0);
2205 CHAR_TO_PIXEL_COL (f
, column
),
2206 CHAR_TO_PIXEL_ROW (f
, i
),
2207 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2209 /* Highlight with mouse face if hl > 0. */
2213 /* If we turned the cursor off, turn it back on. */
2215 x_display_cursor (f
, 1);
2217 curs_x
= old_curs_x
;
2218 curs_y
= old_curs_y
;
2220 /* Change the mouse cursor according to the value of HL. */
2222 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2223 f
->output_data
.x
->cross_cursor
);
2225 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2226 f
->output_data
.x
->text_cursor
);
2229 /* Clear out the mouse-highlighted active region.
2230 Redraw it unhighlighted first. */
2233 clear_mouse_face (dpyinfo
)
2234 struct x_display_info
*dpyinfo
;
2236 if (! NILP (dpyinfo
->mouse_face_window
))
2237 show_mouse_face (dpyinfo
, 0);
2239 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2240 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2241 dpyinfo
->mouse_face_window
= Qnil
;
2244 static struct scroll_bar
*x_window_to_scroll_bar ();
2245 static void x_scroll_bar_report_motion ();
2247 /* Return the current position of the mouse.
2248 *fp should be a frame which indicates which display to ask about.
2250 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2251 and *part to the frame, window, and scroll bar part that the mouse
2252 is over. Set *x and *y to the portion and whole of the mouse's
2253 position on the scroll bar.
2255 If the mouse movement started elsewhere, set *fp to the frame the
2256 mouse is on, *bar_window to nil, and *x and *y to the character cell
2259 Set *time to the server timestamp for the time at which the mouse
2260 was at this position.
2262 Don't store anything if we don't have a valid set of values to report.
2264 This clears the mouse_moved flag, so we can wait for the next mouse
2265 movement. This also calls XQueryPointer, which will cause the
2266 server to give us another MotionNotify when the mouse moves
2270 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2273 Lisp_Object
*bar_window
;
2274 enum scroll_bar_part
*part
;
2276 unsigned long *time
;
2282 if (! NILP (last_mouse_scroll_bar
))
2283 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2289 Window dummy_window
;
2292 Lisp_Object frame
, tail
;
2294 /* Clear the mouse-moved flag for every frame on this display. */
2295 FOR_EACH_FRAME (tail
, frame
)
2296 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2297 XFRAME (frame
)->mouse_moved
= 0;
2299 last_mouse_scroll_bar
= Qnil
;
2301 /* Figure out which root window we're on. */
2302 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2303 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2305 /* The root window which contains the pointer. */
2308 /* Trash which we can't trust if the pointer is on
2309 a different screen. */
2312 /* The position on that root window. */
2315 /* More trash we can't trust. */
2318 /* Modifier keys and pointer buttons, about which
2320 (unsigned int *) &dummy
);
2322 /* Now we have a position on the root; find the innermost window
2323 containing the pointer. */
2327 int parent_x
, parent_y
;
2331 /* XTranslateCoordinates can get errors if the window
2332 structure is changing at the same time this function
2333 is running. So at least we must not crash from them. */
2335 x_catch_errors (FRAME_X_DISPLAY (*fp
));
2337 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2338 && FRAME_LIVE_P (last_mouse_frame
))
2340 /* If mouse was grabbed on a frame, give coords for that frame
2341 even if the mouse is now outside it. */
2342 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2344 /* From-window, to-window. */
2345 root
, FRAME_X_WINDOW (last_mouse_frame
),
2347 /* From-position, to-position. */
2348 root_x
, root_y
, &win_x
, &win_y
,
2352 f1
= last_mouse_frame
;
2358 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2360 /* From-window, to-window. */
2363 /* From-position, to-position. */
2364 root_x
, root_y
, &win_x
, &win_y
,
2369 if (child
== None
|| child
== win
)
2377 /* Now we know that:
2378 win is the innermost window containing the pointer
2379 (XTC says it has no child containing the pointer),
2380 win_x and win_y are the pointer's position in it
2381 (XTC did this the last time through), and
2382 parent_x and parent_y are the pointer's position in win's parent.
2383 (They are what win_x and win_y were when win was child.
2384 If win is the root window, it has no parent, and
2385 parent_{x,y} are invalid, but that's okay, because we'll
2386 never use them in that case.) */
2388 /* Is win one of our frames? */
2389 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2392 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2395 x_uncatch_errors (FRAME_X_DISPLAY (*fp
));
2397 /* If not, is it one of our scroll bars? */
2400 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2404 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2410 if (f1
== 0 && insist
)
2411 f1
= selected_frame
;
2415 int ignore1
, ignore2
;
2417 /* Ok, we found a frame. Store all the values. */
2419 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2421 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2427 XSETINT (*x
, win_x
);
2428 XSETINT (*y
, win_y
);
2429 *time
= last_mouse_movement_time
;
2437 /* Scroll bar support. */
2439 /* Given an X window ID, find the struct scroll_bar which manages it.
2440 This can be called in GC, so we have to make sure to strip off mark
2442 static struct scroll_bar
*
2443 x_window_to_scroll_bar (window_id
)
2446 Lisp_Object tail
, frame
;
2448 for (tail
= Vframe_list
;
2449 XGCTYPE (tail
) == Lisp_Cons
;
2450 tail
= XCONS (tail
)->cdr
)
2452 Lisp_Object frame
, bar
, condemned
;
2454 frame
= XCONS (tail
)->car
;
2455 /* All elements of Vframe_list should be frames. */
2456 if (! GC_FRAMEP (frame
))
2459 /* Scan this frame's scroll bar list for a scroll bar with the
2461 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2462 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2463 /* This trick allows us to search both the ordinary and
2464 condemned scroll bar lists with one loop. */
2465 ! GC_NILP (bar
) || (bar
= condemned
,
2468 bar
= XSCROLL_BAR (bar
)->next
)
2469 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2470 return XSCROLL_BAR (bar
);
2476 /* Open a new X window to serve as a scroll bar, and return the
2477 scroll bar vector for it. */
2478 static struct scroll_bar
*
2479 x_scroll_bar_create (window
, top
, left
, width
, height
)
2480 struct window
*window
;
2481 int top
, left
, width
, height
;
2483 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2484 struct scroll_bar
*bar
2485 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2490 XSetWindowAttributes a
;
2492 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2493 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2494 | ButtonMotionMask
| PointerMotionHintMask
2496 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2498 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2503 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2504 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2505 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2506 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2507 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2508 sb_widget
= XtCreateManagedWidget ("box",
2510 f
->output_data
.x
->edit_widget
, al
, ac
);
2511 SET_SCROLL_BAR_X_WINDOW
2512 (bar
, sb_widget
->core
.window
);
2514 SET_SCROLL_BAR_X_WINDOW
2516 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2518 /* Position and size of scroll bar. */
2519 left
, top
, width
, height
,
2521 /* Border width, depth, class, and visual. */
2522 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2528 XSETWINDOW (bar
->window
, window
);
2529 XSETINT (bar
->top
, top
);
2530 XSETINT (bar
->left
, left
);
2531 XSETINT (bar
->width
, width
);
2532 XSETINT (bar
->height
, height
);
2533 XSETINT (bar
->start
, 0);
2534 XSETINT (bar
->end
, 0);
2535 bar
->dragging
= Qnil
;
2537 /* Add bar to its frame's list of scroll bars. */
2538 bar
->next
= FRAME_SCROLL_BARS (f
);
2540 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2541 if (! NILP (bar
->next
))
2542 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2544 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2551 /* Draw BAR's handle in the proper position.
2552 If the handle is already drawn from START to END, don't bother
2553 redrawing it, unless REBUILD is non-zero; in that case, always
2554 redraw it. (REBUILD is handy for drawing the handle after expose
2557 Normally, we want to constrain the start and end of the handle to
2558 fit inside its rectangle, but if the user is dragging the scroll bar
2559 handle, we want to let them drag it down all the way, so that the
2560 bar's top is as far down as it goes; otherwise, there's no way to
2561 move to the very end of the buffer. */
2563 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2564 struct scroll_bar
*bar
;
2568 int dragging
= ! NILP (bar
->dragging
);
2569 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2570 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2571 GC gc
= f
->output_data
.x
->normal_gc
;
2573 /* If the display is already accurate, do nothing. */
2575 && start
== XINT (bar
->start
)
2576 && end
== XINT (bar
->end
))
2582 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2583 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2584 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2586 /* Make sure the values are reasonable, and try to preserve
2587 the distance between start and end. */
2589 int length
= end
- start
;
2593 else if (start
> top_range
)
2595 end
= start
+ length
;
2599 else if (end
> top_range
&& ! dragging
)
2603 /* Store the adjusted setting in the scroll bar. */
2604 XSETINT (bar
->start
, start
);
2605 XSETINT (bar
->end
, end
);
2607 /* Clip the end position, just for display. */
2608 if (end
> top_range
)
2611 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2612 below top positions, to make sure the handle is always at least
2613 that many pixels tall. */
2614 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2616 /* Draw the empty space above the handle. Note that we can't clear
2617 zero-height areas; that means "clear to end of window." */
2619 XClearArea (FRAME_X_DISPLAY (f
), w
,
2621 /* x, y, width, height, and exposures. */
2622 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2623 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2624 inside_width
, start
,
2627 /* Draw the handle itself. */
2628 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2630 /* x, y, width, height */
2631 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2632 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2633 inside_width
, end
- start
);
2636 /* Draw the empty space below the handle. Note that we can't
2637 clear zero-height areas; that means "clear to end of window." */
2638 if (end
< inside_height
)
2639 XClearArea (FRAME_X_DISPLAY (f
), w
,
2641 /* x, y, width, height, and exposures. */
2642 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2643 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2644 inside_width
, inside_height
- end
,
2652 /* Move a scroll bar around on the screen, to accommodate changing
2653 window configurations. */
2655 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2656 struct scroll_bar
*bar
;
2657 int top
, left
, width
, height
;
2659 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2660 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2666 unsigned int mask
= 0;
2673 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2674 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2675 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2676 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2679 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2683 XSETINT (bar
->left
, left
);
2684 XSETINT (bar
->top
, top
);
2685 XSETINT (bar
->width
, width
);
2686 XSETINT (bar
->height
, height
);
2691 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2694 x_scroll_bar_remove (bar
)
2695 struct scroll_bar
*bar
;
2697 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2701 /* Destroy the window. */
2702 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2704 /* Disassociate this scroll bar from its window. */
2705 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2710 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2711 that we are displaying PORTION characters out of a total of WHOLE
2712 characters, starting at POSITION. If WINDOW has no scroll bar,
2715 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2716 struct window
*window
;
2717 int portion
, whole
, position
;
2719 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2720 int top
= XINT (window
->top
);
2721 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2722 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2724 /* Where should this scroll bar be, pixelwise? */
2725 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2726 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2728 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2729 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2730 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2731 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2733 struct scroll_bar
*bar
;
2735 /* Does the scroll bar exist yet? */
2736 if (NILP (window
->vertical_scroll_bar
))
2737 bar
= x_scroll_bar_create (window
,
2738 pixel_top
, pixel_left
,
2739 pixel_width
, pixel_height
);
2742 /* It may just need to be moved and resized. */
2743 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2744 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2747 /* Set the scroll bar's current state, unless we're currently being
2749 if (NILP (bar
->dragging
))
2751 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2754 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2757 int start
= ((double) position
* top_range
) / whole
;
2758 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2760 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2764 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2768 /* The following three hooks are used when we're doing a thorough
2769 redisplay of the frame. We don't explicitly know which scroll bars
2770 are going to be deleted, because keeping track of when windows go
2771 away is a real pain - "Can you say set-window-configuration, boys
2772 and girls?" Instead, we just assert at the beginning of redisplay
2773 that *all* scroll bars are to be removed, and then save a scroll bar
2774 from the fiery pit when we actually redisplay its window. */
2776 /* Arrange for all scroll bars on FRAME to be removed at the next call
2777 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2778 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2780 XTcondemn_scroll_bars (frame
)
2783 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2784 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2787 bar
= FRAME_SCROLL_BARS (frame
);
2788 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2789 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2790 XSCROLL_BAR (bar
)->prev
= Qnil
;
2791 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2792 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2793 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2797 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2798 Note that WINDOW isn't necessarily condemned at all. */
2800 XTredeem_scroll_bar (window
)
2801 struct window
*window
;
2803 struct scroll_bar
*bar
;
2805 /* We can't redeem this window's scroll bar if it doesn't have one. */
2806 if (NILP (window
->vertical_scroll_bar
))
2809 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2811 /* Unlink it from the condemned list. */
2813 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2815 if (NILP (bar
->prev
))
2817 /* If the prev pointer is nil, it must be the first in one of
2819 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2820 /* It's not condemned. Everything's fine. */
2822 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2823 window
->vertical_scroll_bar
))
2824 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2826 /* If its prev pointer is nil, it must be at the front of
2827 one or the other! */
2831 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2833 if (! NILP (bar
->next
))
2834 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2836 bar
->next
= FRAME_SCROLL_BARS (f
);
2838 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2839 if (! NILP (bar
->next
))
2840 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2844 /* Remove all scroll bars on FRAME that haven't been saved since the
2845 last call to `*condemn_scroll_bars_hook'. */
2847 XTjudge_scroll_bars (f
)
2850 Lisp_Object bar
, next
;
2852 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2854 /* Clear out the condemned list now so we won't try to process any
2855 more events on the hapless scroll bars. */
2856 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2858 for (; ! NILP (bar
); bar
= next
)
2860 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2862 x_scroll_bar_remove (b
);
2865 b
->next
= b
->prev
= Qnil
;
2868 /* Now there should be no references to the condemned scroll bars,
2869 and they should get garbage-collected. */
2873 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2875 This may be called from a signal handler, so we have to ignore GC
2878 x_scroll_bar_expose (bar
, event
)
2879 struct scroll_bar
*bar
;
2882 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2883 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2884 GC gc
= f
->output_data
.x
->normal_gc
;
2888 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2890 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2891 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2893 /* x, y, width, height */
2894 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2899 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2900 is set to something other than no_event, it is enqueued.
2902 This may be called from a signal handler, so we have to ignore GC
2905 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2906 struct scroll_bar
*bar
;
2908 struct input_event
*emacs_event
;
2910 if (! GC_WINDOWP (bar
->window
))
2913 emacs_event
->kind
= scroll_bar_click
;
2914 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2915 emacs_event
->modifiers
2916 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2917 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2918 event
->xbutton
.state
)
2919 | (event
->type
== ButtonRelease
2922 emacs_event
->frame_or_window
= bar
->window
;
2923 emacs_event
->timestamp
= event
->xbutton
.time
;
2926 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2928 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2929 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2932 if (y
> top_range
) y
= top_range
;
2934 if (y
< XINT (bar
->start
))
2935 emacs_event
->part
= scroll_bar_above_handle
;
2936 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2937 emacs_event
->part
= scroll_bar_handle
;
2939 emacs_event
->part
= scroll_bar_below_handle
;
2941 /* Just because the user has clicked on the handle doesn't mean
2942 they want to drag it. Lisp code needs to be able to decide
2943 whether or not we're dragging. */
2945 /* If the user has just clicked on the handle, record where they're
2947 if (event
->type
== ButtonPress
2948 && emacs_event
->part
== scroll_bar_handle
)
2949 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2952 /* If the user has released the handle, set it to its final position. */
2953 if (event
->type
== ButtonRelease
2954 && ! NILP (bar
->dragging
))
2956 int new_start
= y
- XINT (bar
->dragging
);
2957 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2959 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2960 bar
->dragging
= Qnil
;
2963 /* Same deal here as the other #if 0. */
2965 /* Clicks on the handle are always reported as occurring at the top of
2967 if (emacs_event
->part
== scroll_bar_handle
)
2968 emacs_event
->x
= bar
->start
;
2970 XSETINT (emacs_event
->x
, y
);
2972 XSETINT (emacs_event
->x
, y
);
2975 XSETINT (emacs_event
->y
, top_range
);
2979 /* Handle some mouse motion while someone is dragging the scroll bar.
2981 This may be called from a signal handler, so we have to ignore GC
2984 x_scroll_bar_note_movement (bar
, event
)
2985 struct scroll_bar
*bar
;
2988 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
2990 last_mouse_movement_time
= event
->xmotion
.time
;
2993 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2995 /* If we're dragging the bar, display it. */
2996 if (! GC_NILP (bar
->dragging
))
2998 /* Where should the handle be now? */
2999 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3001 if (new_start
!= XINT (bar
->start
))
3003 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3005 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3009 /* Call XQueryPointer so we'll get an event the next time the mouse
3010 moves and we can see *still* on the same position. */
3013 Window dummy_window
;
3015 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3016 &dummy_window
, &dummy_window
,
3017 &dummy
, &dummy
, &dummy
, &dummy
,
3018 (unsigned int *) &dummy
);
3022 /* Return information to the user about the current position of the mouse
3023 on the scroll bar. */
3025 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3027 Lisp_Object
*bar_window
;
3028 enum scroll_bar_part
*part
;
3030 unsigned long *time
;
3032 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3033 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3034 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3036 Window dummy_window
;
3038 unsigned int dummy_mask
;
3042 /* Get the mouse's position relative to the scroll bar window, and
3044 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3046 /* Root, child, root x and root y. */
3047 &dummy_window
, &dummy_window
,
3048 &dummy_coord
, &dummy_coord
,
3050 /* Position relative to scroll bar. */
3053 /* Mouse buttons and modifier keys. */
3059 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3061 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3063 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3065 if (! NILP (bar
->dragging
))
3066 win_y
-= XINT (bar
->dragging
);
3070 if (win_y
> top_range
)
3074 *bar_window
= bar
->window
;
3076 if (! NILP (bar
->dragging
))
3077 *part
= scroll_bar_handle
;
3078 else if (win_y
< XINT (bar
->start
))
3079 *part
= scroll_bar_above_handle
;
3080 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3081 *part
= scroll_bar_handle
;
3083 *part
= scroll_bar_below_handle
;
3085 XSETINT (*x
, win_y
);
3086 XSETINT (*y
, top_range
);
3089 last_mouse_scroll_bar
= Qnil
;
3092 *time
= last_mouse_movement_time
;
3098 /* The screen has been cleared so we may have changed foreground or
3099 background colors, and the scroll bars may need to be redrawn.
3100 Clear out the scroll bars, and ask for expose events, so we can
3103 x_scroll_bar_clear (f
)
3108 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3109 bar
= XSCROLL_BAR (bar
)->next
)
3110 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3114 /* This processes Expose events from the menubar specific X event
3115 loop in xmenu.c. This allows to redisplay the frame if necessary
3116 when handling menubar or popup items. */
3119 process_expose_from_menu (event
)
3123 struct x_display_info
*dpyinfo
;
3127 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3128 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3131 if (f
->async_visible
== 0)
3133 f
->async_visible
= 1;
3134 f
->async_iconified
= 0;
3135 SET_FRAME_GARBAGED (f
);
3139 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3140 event
.xexpose
.x
, event
.xexpose
.y
,
3141 event
.xexpose
.width
, event
.xexpose
.height
);
3146 struct scroll_bar
*bar
3147 = x_window_to_scroll_bar (event
.xexpose
.window
);
3150 x_scroll_bar_expose (bar
, &event
);
3156 /* Define a queue to save up SelectionRequest events for later handling. */
3158 struct selection_event_queue
3161 struct selection_event_queue
*next
;
3164 static struct selection_event_queue
*queue
;
3166 /* Nonzero means queue up certain events--don't process them yet. */
3167 static int x_queue_selection_requests
;
3169 /* Queue up an X event *EVENT, to be processed later. */
3172 x_queue_event (f
, event
)
3176 struct selection_event_queue
*queue_tmp
3177 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3179 if (queue_tmp
!= NULL
)
3181 queue_tmp
->event
= *event
;
3182 queue_tmp
->next
= queue
;
3187 /* Take all the queued events and put them back
3188 so that they get processed afresh. */
3191 x_unqueue_events (display
)
3194 while (queue
!= NULL
)
3196 struct selection_event_queue
*queue_tmp
= queue
;
3197 XPutBackEvent (display
, &queue_tmp
->event
);
3198 queue
= queue_tmp
->next
;
3199 free ((char *)queue_tmp
);
3203 /* Start queuing SelectionRequest events. */
3206 x_start_queuing_selection_requests (display
)
3209 x_queue_selection_requests
++;
3212 /* Stop queuing SelectionRequest events. */
3215 x_stop_queuing_selection_requests (display
)
3218 x_queue_selection_requests
--;
3219 x_unqueue_events (display
);
3222 /* The main X event-reading loop - XTread_socket. */
3224 /* Timestamp of enter window event. This is only used by XTread_socket,
3225 but we have to put it out here, since static variables within functions
3226 sometimes don't work. */
3227 static Time enter_timestamp
;
3229 /* This holds the state XLookupString needs to implement dead keys
3230 and other tricks known as "compose processing". _X Window System_
3231 says that a portable program can't use this, but Stephen Gildea assures
3232 me that letting the compiler initialize it to zeros will work okay.
3234 This must be defined outside of XTread_socket, for the same reasons
3235 given for enter_timestamp, above. */
3236 static XComposeStatus compose_status
;
3238 /* Record the last 100 characters stored
3239 to help debug the loss-of-chars-during-GC problem. */
3240 static int temp_index
;
3241 static short temp_buffer
[100];
3243 /* Set this to nonzero to fake an "X I/O error"
3244 on a particular display. */
3245 struct x_display_info
*XTread_socket_fake_io_error
;
3247 /* When we find no input here, we occasionally do a no-op command
3248 to verify that the X server is still running and we can still talk with it.
3249 We try all the open displays, one by one.
3250 This variable is used for cycling thru the displays. */
3251 static struct x_display_info
*next_noop_dpyinfo
;
3253 /* Read events coming from the X server.
3254 This routine is called by the SIGIO handler.
3255 We return as soon as there are no more events to be read.
3257 Events representing keys are stored in buffer BUFP,
3258 which can hold up to NUMCHARS characters.
3259 We return the number of characters stored into the buffer,
3260 thus pretending to be `read'.
3262 WAITP is nonzero if we should block until input arrives.
3263 EXPECTED is nonzero if the caller knows input is available. */
3266 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3268 register struct input_event
*bufp
;
3269 register int numchars
;
3276 int items_pending
; /* How many items are in the X queue. */
3279 int event_found
= 0;
3282 struct x_display_info
*dpyinfo
;
3284 Status status_return
;
3287 if (interrupt_input_blocked
)
3289 interrupt_input_pending
= 1;
3293 interrupt_input_pending
= 0;
3296 /* So people can tell when we have read the available input. */
3297 input_signal_count
++;
3300 abort (); /* Don't think this happens. */
3302 /* Find the display we are supposed to read input for.
3303 It's the one communicating on descriptor SD. */
3304 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3306 #if 0 /* This ought to be unnecessary; let's verify it. */
3308 /* If available, Xlib uses FIOSNBIO to make the socket
3309 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3310 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3311 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3312 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3313 #endif /* ! defined (FIOSNBIO) */
3316 #if 0 /* This code can't be made to work, with multiple displays,
3317 and appears not to be used on any system any more.
3318 Also keyboard.c doesn't turn O_NDELAY on and off
3319 for X connections. */
3322 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3324 extern int read_alarm_should_throw
;
3325 read_alarm_should_throw
= 1;
3326 XPeekEvent (dpyinfo
->display
, &event
);
3327 read_alarm_should_throw
= 0;
3329 #endif /* HAVE_SELECT */
3333 /* For debugging, this gives a way to fake an I/O error. */
3334 if (dpyinfo
== XTread_socket_fake_io_error
)
3336 XTread_socket_fake_io_error
= 0;
3337 x_io_error_quitter (dpyinfo
->display
);
3340 while (XPending (dpyinfo
->display
) != 0)
3342 XNextEvent (dpyinfo
->display
, &event
);
3349 if (event
.xclient
.message_type
3350 == dpyinfo
->Xatom_wm_protocols
3351 && event
.xclient
.format
== 32)
3353 if (event
.xclient
.data
.l
[0]
3354 == dpyinfo
->Xatom_wm_take_focus
)
3356 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3357 /* Since we set WM_TAKE_FOCUS, we must call
3358 XSetInputFocus explicitly. But not if f is null,
3359 since that might be an event for a deleted frame. */
3361 /* Not quite sure this is needed -pd */
3363 XSetICFocus (FRAME_XIC (f
));
3366 XSetInputFocus (event
.xclient
.display
,
3367 event
.xclient
.window
,
3368 RevertToPointerRoot
,
3369 event
.xclient
.data
.l
[1]);
3370 /* Not certain about handling scroll bars here */
3372 else if (event
.xclient
.data
.l
[0]
3373 == dpyinfo
->Xatom_wm_save_yourself
)
3375 /* Save state modify the WM_COMMAND property to
3376 something which can reinstate us. This notifies
3377 the session manager, who's looking for such a
3378 PropertyNotify. Can restart processing when
3379 a keyboard or mouse event arrives. */
3382 f
= x_top_window_to_frame (dpyinfo
,
3383 event
.xclient
.window
);
3385 /* This is just so we only give real data once
3386 for a single Emacs process. */
3387 if (f
== selected_frame
)
3388 XSetCommand (FRAME_X_DISPLAY (f
),
3389 event
.xclient
.window
,
3390 initial_argv
, initial_argc
);
3392 XSetCommand (FRAME_X_DISPLAY (f
),
3393 event
.xclient
.window
,
3397 else if (event
.xclient
.data
.l
[0]
3398 == dpyinfo
->Xatom_wm_delete_window
)
3401 = x_any_window_to_frame (dpyinfo
,
3402 event
.xclient
.window
);
3409 bufp
->kind
= delete_window_event
;
3410 XSETFRAME (bufp
->frame_or_window
, f
);
3418 else if (event
.xclient
.message_type
3419 == dpyinfo
->Xatom_wm_configure_denied
)
3422 else if (event
.xclient
.message_type
3423 == dpyinfo
->Xatom_wm_window_moved
)
3427 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3429 new_x
= event
.xclient
.data
.s
[0];
3430 new_y
= event
.xclient
.data
.s
[1];
3434 f
->output_data
.x
->left_pos
= new_x
;
3435 f
->output_data
.x
->top_pos
= new_y
;
3439 else if (event
.xclient
.message_type
3440 == dpyinfo
->Xatom_editres
)
3443 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3444 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3447 #endif /* HACK_EDITRES */
3451 case SelectionNotify
:
3452 #ifdef USE_X_TOOLKIT
3453 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3455 #endif /* not USE_X_TOOLKIT */
3456 x_handle_selection_notify (&event
);
3459 case SelectionClear
: /* Someone has grabbed ownership. */
3460 #ifdef USE_X_TOOLKIT
3461 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3463 #endif /* USE_X_TOOLKIT */
3465 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3470 bufp
->kind
= selection_clear_event
;
3471 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3472 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3473 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3474 bufp
->frame_or_window
= Qnil
;
3482 case SelectionRequest
: /* Someone wants our selection. */
3483 #ifdef USE_X_TOOLKIT
3484 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3486 #endif /* USE_X_TOOLKIT */
3487 if (x_queue_selection_requests
)
3488 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3492 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3497 bufp
->kind
= selection_request_event
;
3498 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3499 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3500 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3501 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3502 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3503 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3504 bufp
->frame_or_window
= Qnil
;
3512 case PropertyNotify
:
3513 #ifdef USE_X_TOOLKIT
3514 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3516 #endif /* not USE_X_TOOLKIT */
3517 x_handle_property_notify (&event
);
3520 case ReparentNotify
:
3521 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3525 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
3526 x_real_positions (f
, &x
, &y
);
3527 f
->output_data
.x
->left_pos
= x
;
3528 f
->output_data
.x
->top_pos
= y
;
3533 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3536 if (f
->async_visible
== 0)
3538 f
->async_visible
= 1;
3539 f
->async_iconified
= 0;
3540 SET_FRAME_GARBAGED (f
);
3543 dumprectangle (x_window_to_frame (dpyinfo
,
3544 event
.xexpose
.window
),
3545 event
.xexpose
.x
, event
.xexpose
.y
,
3546 event
.xexpose
.width
, event
.xexpose
.height
);
3550 struct scroll_bar
*bar
3551 = x_window_to_scroll_bar (event
.xexpose
.window
);
3554 x_scroll_bar_expose (bar
, &event
);
3555 #ifdef USE_X_TOOLKIT
3558 #endif /* USE_X_TOOLKIT */
3562 case GraphicsExpose
: /* This occurs when an XCopyArea's
3563 source area was obscured or not
3565 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3569 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3570 event
.xgraphicsexpose
.width
,
3571 event
.xgraphicsexpose
.height
);
3573 #ifdef USE_X_TOOLKIT
3576 #endif /* USE_X_TOOLKIT */
3579 case NoExpose
: /* This occurs when an XCopyArea's
3580 source area was completely
3585 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3586 if (f
) /* F may no longer exist if
3587 the frame was deleted. */
3589 /* While a frame is unmapped, display generation is
3590 disabled; you don't want to spend time updating a
3591 display that won't ever be seen. */
3592 f
->async_visible
= 0;
3593 /* We can't distinguish, from the event, whether the window
3594 has become iconified or invisible. So assume, if it
3595 was previously visible, than now it is iconified.
3596 We depend on x_make_frame_invisible to mark it iconified. */
3597 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3598 f
->async_iconified
= 1;
3600 bufp
->kind
= iconify_event
;
3601 XSETFRAME (bufp
->frame_or_window
, f
);
3609 /* We use x_top_window_to_frame because map events can come
3610 for subwindows and they don't mean that the frame is visible. */
3611 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
3614 f
->async_visible
= 1;
3615 f
->async_iconified
= 0;
3617 /* wait_reading_process_input will notice this and update
3618 the frame's display structures. */
3619 SET_FRAME_GARBAGED (f
);
3623 bufp
->kind
= deiconify_event
;
3624 XSETFRAME (bufp
->frame_or_window
, f
);
3630 /* Force a redisplay sooner or later
3631 to update the frame titles
3632 in case this is the second frame. */
3633 record_asynch_buffer_change ();
3637 /* Turn off processing if we become fully obscured. */
3638 case VisibilityNotify
:
3642 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
3646 KeySym keysym
, orig_keysym
;
3647 /* al%imercury@uunet.uu.net says that making this 81 instead of
3648 80 fixed a bug whereby meta chars made his Emacs hang. */
3649 unsigned char copy_buffer
[81];
3653 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3654 extra_keyboard_modifiers
);
3655 modifiers
= event
.xkey
.state
;
3657 /* This will have to go some day... */
3659 /* make_lispy_event turns chars into control chars.
3660 Don't do it here because XLookupString is too eager. */
3661 event
.xkey
.state
&= ~ControlMask
;
3662 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
3663 | dpyinfo
->super_mod_mask
3664 | dpyinfo
->hyper_mod_mask
3665 | dpyinfo
->alt_mod_mask
);
3670 /* The necessity of the following line took me
3671 a full work-day to decipher from the docs!! */
3672 if (XFilterEvent (&event
, None
))
3674 nbytes
= XmbLookupString (FRAME_XIC (f
),
3675 &event
.xkey
, copy_buffer
,
3680 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3681 80, &keysym
, &compose_status
);
3683 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3684 80, &keysym
, &compose_status
);
3687 orig_keysym
= keysym
;
3691 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3692 || keysym
== XK_Delete
3693 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3694 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3696 /* This recognizes the "extended function keys".
3697 It seems there's no cleaner way.
3698 Test IsModifierKey to avoid handling mode_switch
3700 || ((unsigned) (keysym
) >= XK_Select
3701 && (unsigned)(keysym
) < XK_KP_Space
)
3703 #ifdef XK_dead_circumflex
3704 || orig_keysym
== XK_dead_circumflex
3706 #ifdef XK_dead_grave
3707 || orig_keysym
== XK_dead_grave
3709 #ifdef XK_dead_tilde
3710 || orig_keysym
== XK_dead_tilde
3712 #ifdef XK_dead_diaeresis
3713 || orig_keysym
== XK_dead_diaeresis
3715 #ifdef XK_dead_macron
3716 || orig_keysym
== XK_dead_macron
3718 #ifdef XK_dead_degree
3719 || orig_keysym
== XK_dead_degree
3721 #ifdef XK_dead_acute
3722 || orig_keysym
== XK_dead_acute
3724 #ifdef XK_dead_cedilla
3725 || orig_keysym
== XK_dead_cedilla
3727 #ifdef XK_dead_breve
3728 || orig_keysym
== XK_dead_breve
3730 #ifdef XK_dead_ogonek
3731 || orig_keysym
== XK_dead_ogonek
3733 #ifdef XK_dead_caron
3734 || orig_keysym
== XK_dead_caron
3736 #ifdef XK_dead_doubleacute
3737 || orig_keysym
== XK_dead_doubleacute
3739 #ifdef XK_dead_abovedot
3740 || orig_keysym
== XK_dead_abovedot
3742 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3743 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3744 /* Any "vendor-specific" key is ok. */
3745 || (orig_keysym
& (1 << 28)))
3746 && ! (IsModifierKey (orig_keysym
)
3748 #ifdef XK_Mode_switch
3749 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3752 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3754 #endif /* not HAVE_X11R5 */
3757 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3759 temp_buffer
[temp_index
++] = keysym
;
3760 bufp
->kind
= non_ascii_keystroke
;
3761 bufp
->code
= keysym
;
3762 XSETFRAME (bufp
->frame_or_window
, f
);
3764 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3766 bufp
->timestamp
= event
.xkey
.time
;
3771 else if (numchars
> nbytes
)
3775 for (i
= 0; i
< nbytes
; i
++)
3777 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3779 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3780 bufp
->kind
= ascii_keystroke
;
3781 bufp
->code
= copy_buffer
[i
];
3782 XSETFRAME (bufp
->frame_or_window
, f
);
3784 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3786 bufp
->timestamp
= event
.xkey
.time
;
3801 /* Here's a possible interpretation of the whole
3802 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3803 FocusIn event, you have to get a FocusOut event before you
3804 relinquish the focus. If you haven't received a FocusIn event,
3805 then a mere LeaveNotify is enough to free you. */
3808 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3810 if (event
.xcrossing
.focus
) /* Entered Window */
3812 /* Avoid nasty pop/raise loops. */
3813 if (f
&& (!(f
->auto_raise
)
3815 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3817 x_new_focus_frame (dpyinfo
, f
);
3818 enter_timestamp
= event
.xcrossing
.time
;
3821 else if (f
== dpyinfo
->x_focus_frame
)
3822 x_new_focus_frame (dpyinfo
, 0);
3823 /* EnterNotify counts as mouse movement,
3824 so update things that depend on mouse position. */
3826 note_mouse_movement (f
, &event
.xmotion
);
3830 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3831 if (event
.xfocus
.detail
!= NotifyPointer
)
3832 dpyinfo
->x_focus_event_frame
= f
;
3834 x_new_focus_frame (dpyinfo
, f
);
3837 if (f
&& FRAME_XIC (f
))
3838 XSetICFocus (FRAME_XIC (f
));
3844 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3847 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3848 /* If we move outside the frame,
3849 then we're certainly no longer on any text in the frame. */
3850 clear_mouse_face (dpyinfo
);
3852 if (event
.xcrossing
.focus
)
3853 x_mouse_leave (dpyinfo
);
3856 if (f
== dpyinfo
->x_focus_event_frame
)
3857 dpyinfo
->x_focus_event_frame
= 0;
3858 if (f
== dpyinfo
->x_focus_frame
)
3859 x_new_focus_frame (dpyinfo
, 0);
3865 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3866 if (event
.xfocus
.detail
!= NotifyPointer
3867 && f
== dpyinfo
->x_focus_event_frame
)
3868 dpyinfo
->x_focus_event_frame
= 0;
3869 if (f
&& f
== dpyinfo
->x_focus_frame
)
3870 x_new_focus_frame (dpyinfo
, 0);
3873 if (f
&& FRAME_XIC (f
))
3874 XUnsetICFocus (FRAME_XIC (f
));
3881 if (dpyinfo
->grabbed
&& last_mouse_frame
3882 && FRAME_LIVE_P (last_mouse_frame
))
3883 f
= last_mouse_frame
;
3885 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3887 note_mouse_movement (f
, &event
.xmotion
);
3890 struct scroll_bar
*bar
3891 = x_window_to_scroll_bar (event
.xmotion
.window
);
3894 x_scroll_bar_note_movement (bar
, &event
);
3896 /* If we move outside the frame,
3897 then we're certainly no longer on any text in the frame. */
3898 clear_mouse_face (dpyinfo
);
3903 case ConfigureNotify
:
3904 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
3906 #ifdef USE_X_TOOLKIT
3907 && (event
.xconfigure
.window
== XtWindow (f
->output_data
.x
->widget
))
3911 #ifndef USE_X_TOOLKIT
3912 /* In the toolkit version, change_frame_size
3913 is called by the code that handles resizing
3914 of the EmacsFrame widget. */
3916 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3917 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3919 /* Even if the number of character rows and columns has
3920 not changed, the font size may have changed, so we need
3921 to check the pixel dimensions as well. */
3922 if (columns
!= f
->width
3923 || rows
!= f
->height
3924 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
3925 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
3927 change_frame_size (f
, rows
, columns
, 0, 1);
3928 SET_FRAME_GARBAGED (f
);
3932 /* Formerly, in the USE_X_TOOLKIT version,
3933 we did not test send_event here. */
3935 #ifndef USE_X_TOOLKIT
3936 && ! event
.xconfigure
.send_event
3943 /* Find the position of the outside upper-left corner of
3944 the window, in the root coordinate system. Don't
3945 refer to the parent window here; we may be processing
3946 this event after the window manager has changed our
3947 parent, but before we have reached the ReparentNotify. */
3948 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3950 /* From-window, to-window. */
3951 event
.xconfigure
.window
,
3952 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3954 /* From-position, to-position. */
3955 -event
.xconfigure
.border_width
,
3956 -event
.xconfigure
.border_width
,
3961 event
.xconfigure
.x
= win_x
;
3962 event
.xconfigure
.y
= win_y
;
3965 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
3966 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
3967 f
->output_data
.x
->left_pos
= event
.xconfigure
.x
;
3968 f
->output_data
.x
->top_pos
= event
.xconfigure
.y
;
3970 /* What we have now is the position of Emacs's own window.
3971 Convert that to the position of the window manager window. */
3974 x_real_positions (f
, &x
, &y
);
3975 f
->output_data
.x
->left_pos
= x
;
3976 f
->output_data
.x
->top_pos
= y
;
3977 /* Formerly we did not do this in the USE_X_TOOLKIT
3978 version. Let's try making them the same. */
3979 /* #ifndef USE_X_TOOLKIT */
3980 if (y
!= event
.xconfigure
.y
)
3982 /* Since the WM decorations come below top_pos now,
3983 we must put them below top_pos in the future. */
3984 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3985 x_wm_set_size_hint (f
, (long) 0, 0);
3995 /* If we decide we want to generate an event to be seen
3996 by the rest of Emacs, we put it here. */
3997 struct input_event emacs_event
;
3998 emacs_event
.kind
= no_event
;
4000 bzero (&compose_status
, sizeof (compose_status
));
4002 if (dpyinfo
->grabbed
&& last_mouse_frame
4003 && FRAME_LIVE_P (last_mouse_frame
))
4004 f
= last_mouse_frame
;
4006 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4010 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4011 construct_mouse_click (&emacs_event
, &event
, f
);
4015 struct scroll_bar
*bar
4016 = x_window_to_scroll_bar (event
.xbutton
.window
);
4019 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4022 if (event
.type
== ButtonPress
)
4024 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4025 last_mouse_frame
= f
;
4029 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4032 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4034 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4040 #ifdef USE_X_TOOLKIT
4041 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4042 /* For a down-event in the menu bar,
4043 don't pass it to Xt right now.
4044 Instead, save it away
4045 and we will pass it to Xt from kbd_buffer_get_event.
4046 That way, we can run some Lisp code first. */
4047 if (f
&& event
.type
== ButtonPress
4048 /* Verify the event is really within the menu bar
4049 and not just sent to it due to grabbing. */
4050 && event
.xbutton
.x
>= 0
4051 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4052 && event
.xbutton
.y
>= 0
4053 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4054 && event
.xbutton
.same_screen
)
4056 if (f
->output_data
.x
->saved_button_event
== 0)
4057 f
->output_data
.x
->saved_button_event
4058 = (XButtonEvent
*) xmalloc (sizeof (XButtonEvent
));
4059 bcopy (&event
, f
->output_data
.x
->saved_button_event
,
4060 sizeof (XButtonEvent
));
4063 bufp
->kind
= menu_bar_activate_event
;
4064 XSETFRAME (bufp
->frame_or_window
, f
);
4072 #endif /* USE_X_TOOLKIT */
4076 case CirculateNotify
:
4078 case CirculateRequest
:
4082 /* Someone has changed the keyboard mapping - update the
4084 switch (event
.xmapping
.request
)
4086 case MappingModifier
:
4087 x_find_modifier_meanings (dpyinfo
);
4088 /* This is meant to fall through. */
4089 case MappingKeyboard
:
4090 XRefreshKeyboardMapping (&event
.xmapping
);
4096 #ifdef USE_X_TOOLKIT
4098 XtDispatchEvent (&event
);
4100 #endif /* USE_X_TOOLKIT */
4106 /* On some systems, an X bug causes Emacs to get no more events
4107 when the window is destroyed. Detect that. (1994.) */
4110 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4111 One XNOOP in 100 loops will make Emacs terminate.
4112 B. Bretthauer, 1994 */
4114 if (x_noop_count
>= 100)
4118 if (next_noop_dpyinfo
== 0)
4119 next_noop_dpyinfo
= x_display_list
;
4121 XNoOp (next_noop_dpyinfo
->display
);
4123 /* Each time we get here, cycle through the displays now open. */
4124 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4128 /* If the focus was just given to an autoraising frame,
4130 /* ??? This ought to be able to handle more than one such frame. */
4131 if (pending_autoraise_frame
)
4133 x_raise_frame (pending_autoraise_frame
);
4134 pending_autoraise_frame
= 0;
4141 /* Drawing the cursor. */
4144 /* Draw a hollow box cursor on frame F at X, Y.
4145 Don't change the inside of the box. */
4148 x_draw_box (f
, x
, y
)
4152 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4153 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4154 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4155 int height
= f
->output_data
.x
->line_height
;
4157 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4158 f
->output_data
.x
->cursor_gc
,
4159 left
, top
, width
- 1, height
- 1);
4162 /* Clear the cursor of frame F to background color,
4163 and mark the cursor as not shown.
4164 This is used when the text where the cursor is
4165 is about to be rewritten. */
4173 if (! FRAME_VISIBLE_P (f
)
4174 || f
->phys_cursor_x
< 0)
4177 x_display_cursor (f
, 0);
4178 f
->phys_cursor_x
= -1;
4181 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4182 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4186 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4193 CHAR_TO_PIXEL_COL (f
, column
),
4194 CHAR_TO_PIXEL_ROW (f
, row
),
4195 &glyph
, 1, highlight
, 0);
4199 x_display_bar_cursor (f
, on
, x
, y
)
4204 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4206 /* This is pointless on invisible frames, and dangerous on garbaged
4207 frames; in the latter case, the frame may be in the midst of
4208 changing its size, and x and y may be off the frame. */
4209 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4212 if (! on
&& f
->phys_cursor_x
< 0)
4215 /* If there is anything wrong with the current cursor state, remove it. */
4216 if (f
->phys_cursor_x
>= 0
4218 || f
->phys_cursor_x
!= x
4219 || f
->phys_cursor_y
!= y
4220 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4222 /* Erase the cursor by redrawing the character underneath it. */
4223 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4224 f
->phys_cursor_glyph
,
4225 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4226 f
->phys_cursor_x
= -1;
4229 /* If we now need a cursor in the new place or in the new form, do it so. */
4231 && (f
->phys_cursor_x
< 0
4232 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4234 f
->phys_cursor_glyph
4235 = ((current_glyphs
->enable
[y
]
4236 && x
< current_glyphs
->used
[y
])
4237 ? current_glyphs
->glyphs
[y
][x
]
4239 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4240 f
->output_data
.x
->cursor_gc
,
4241 CHAR_TO_PIXEL_COL (f
, x
),
4242 CHAR_TO_PIXEL_ROW (f
, y
),
4243 max (f
->output_data
.x
->cursor_width
, 1),
4244 f
->output_data
.x
->line_height
);
4246 f
->phys_cursor_x
= x
;
4247 f
->phys_cursor_y
= y
;
4249 f
->output_data
.x
->current_cursor
= bar_cursor
;
4252 if (updating_frame
!= f
)
4253 XFlush (FRAME_X_DISPLAY (f
));
4257 /* Turn the displayed cursor of frame F on or off according to ON.
4258 If ON is nonzero, where to put the cursor is specified by X and Y. */
4261 x_display_box_cursor (f
, on
, x
, y
)
4266 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4268 /* This is pointless on invisible frames, and dangerous on garbaged
4269 frames; in the latter case, the frame may be in the midst of
4270 changing its size, and x and y may be off the frame. */
4271 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4274 /* If cursor is off and we want it off, return quickly. */
4275 if (!on
&& f
->phys_cursor_x
< 0)
4278 /* If cursor is currently being shown and we don't want it to be
4279 or it is in the wrong place,
4280 or we want a hollow box and it's not so, (pout!)
4282 if (f
->phys_cursor_x
>= 0
4284 || f
->phys_cursor_x
!= x
4285 || f
->phys_cursor_y
!= y
4286 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4287 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4289 int mouse_face_here
= 0;
4290 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4292 /* If the cursor is in the mouse face area, redisplay that when
4293 we clear the cursor. */
4294 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4296 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4297 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4298 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4300 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4301 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4302 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4303 /* Don't redraw the cursor's spot in mouse face
4304 if it is at the end of a line (on a newline).
4305 The cursor appears there, but mouse highlighting does not. */
4306 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4307 mouse_face_here
= 1;
4309 /* If the font is not as tall as a whole line,
4310 we must explicitly clear the line's whole height. */
4311 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4312 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4313 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4314 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4315 FONT_WIDTH (f
->output_data
.x
->font
),
4316 f
->output_data
.x
->line_height
, False
);
4317 /* Erase the cursor by redrawing the character underneath it. */
4318 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4319 f
->phys_cursor_glyph
,
4322 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4323 f
->phys_cursor_x
= -1;
4326 /* If we want to show a cursor,
4327 or we want a box cursor and it's not so,
4328 write it in the right place. */
4330 && (f
->phys_cursor_x
< 0
4331 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4332 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4334 f
->phys_cursor_glyph
4335 = ((current_glyphs
->enable
[y
]
4336 && x
< current_glyphs
->used
[y
])
4337 ? current_glyphs
->glyphs
[y
][x
]
4339 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4341 x_draw_box (f
, x
, y
);
4342 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4346 x_draw_single_glyph (f
, y
, x
,
4347 f
->phys_cursor_glyph
, 2);
4348 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4351 f
->phys_cursor_x
= x
;
4352 f
->phys_cursor_y
= y
;
4355 if (updating_frame
!= f
)
4356 XFlush (FRAME_X_DISPLAY (f
));
4359 /* Display the cursor on frame F, or clear it, according to ON.
4360 Use the position specified by curs_x and curs_y
4361 if we are doing an update of frame F now.
4362 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4365 x_display_cursor (f
, on
)
4371 /* If we're not updating, then don't change the physical cursor
4372 position. Just change (if appropriate) the style of display. */
4373 if (f
!= updating_frame
)
4375 curs_x
= FRAME_CURSOR_X (f
);
4376 curs_y
= FRAME_CURSOR_Y (f
);
4379 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4380 x_display_box_cursor (f
, on
, curs_x
, curs_y
);
4381 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4382 x_display_bar_cursor (f
, on
, curs_x
, curs_y
);
4384 /* Those are the only two we have implemented! */
4390 /* Display the cursor on frame F, or clear it, according to ON.
4391 Don't change the cursor's position. */
4393 x_update_cursor (f
, on
)
4399 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4400 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4401 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4402 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4404 /* Those are the only two we have implemented! */
4412 /* Refresh bitmap kitchen sink icon for frame F
4413 when we get an expose event for it. */
4418 /* Normally, the window manager handles this function. */
4421 /* Make the x-window of frame F use the gnu icon bitmap. */
4424 x_bitmap_icon (f
, file
)
4428 int mask
, bitmap_id
;
4431 if (FRAME_X_WINDOW (f
) == 0)
4434 /* Free up our existing icon bitmap if any. */
4435 if (f
->output_data
.x
->icon_bitmap
> 0)
4436 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4437 f
->output_data
.x
->icon_bitmap
= 0;
4440 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4443 /* Create the GNU bitmap if necessary. */
4444 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4445 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4446 = x_create_bitmap_from_data (f
, gnu_bits
,
4447 gnu_width
, gnu_height
);
4449 /* The first time we create the GNU bitmap,
4450 this increments the refcount one extra time.
4451 As a result, the GNU bitmap is never freed.
4452 That way, we don't have to worry about allocating it again. */
4453 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4455 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4458 x_wm_set_icon_pixmap (f
, bitmap_id
);
4459 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4465 /* Make the x-window of frame F use a rectangle with text.
4466 Use ICON_NAME as the text. */
4469 x_text_icon (f
, icon_name
)
4473 if (FRAME_X_WINDOW (f
) == 0)
4479 text
.value
= (unsigned char *) icon_name
;
4480 text
.encoding
= XA_STRING
;
4482 text
.nitems
= strlen (icon_name
);
4483 #ifdef USE_X_TOOLKIT
4484 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4486 #else /* not USE_X_TOOLKIT */
4487 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
4488 #endif /* not USE_X_TOOLKIT */
4490 #else /* not HAVE_X11R4 */
4491 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
4492 #endif /* not HAVE_X11R4 */
4494 if (f
->output_data
.x
->icon_bitmap
> 0)
4495 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4496 f
->output_data
.x
->icon_bitmap
= 0;
4497 x_wm_set_icon_pixmap (f
, 0);
4502 /* Handling X errors. */
4504 /* Handle the loss of connection to display DISPLAY. */
4507 x_connection_closed (display
, error_message
)
4509 char *error_message
;
4511 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4512 Lisp_Object frame
, tail
;
4514 /* Whatever we were in the middle of, we are going to throw out of it,
4515 so reassure various things that have error checks about being
4516 called with input blocked. */
4517 TOTALLY_UNBLOCK_INPUT
;
4522 /* Indicate that this display is dead. */
4524 dpyinfo
->display
= 0;
4526 /* First delete frames whose minibuffers are on frames
4527 that are on the dead display. */
4528 FOR_EACH_FRAME (tail
, frame
)
4530 Lisp_Object minibuf_frame
;
4532 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4533 if (FRAME_X_P (XFRAME (frame
))
4534 && FRAME_X_P (XFRAME (minibuf_frame
))
4535 && ! EQ (frame
, minibuf_frame
)
4536 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4537 Fdelete_frame (frame
, Qt
);
4540 /* Now delete all remaining frames on the dead display.
4541 We are now sure none of these is used as the minibuffer
4542 for another frame that we need to delete. */
4543 FOR_EACH_FRAME (tail
, frame
)
4544 if (FRAME_X_P (XFRAME (frame
))
4545 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4547 /* Set this to t so that Fdelete_frame won't get confused
4548 trying to find a replacement. */
4549 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
4550 Fdelete_frame (frame
, Qt
);
4554 x_delete_display (dpyinfo
);
4556 if (x_display_list
== 0)
4558 fprintf (stderr
, "%s", error_message
);
4559 shut_down_emacs (0, 0, Qnil
);
4563 /* Ordinary stack unwind doesn't deal with these. */
4565 sigunblock (sigmask (SIGIO
));
4567 sigunblock (sigmask (SIGALRM
));
4568 TOTALLY_UNBLOCK_INPUT
;
4570 error ("%s", error_message
);
4573 /* This is the usual handler for X protocol errors.
4574 It kills all frames on the display that we got the error for.
4575 If that was the only one, it prints an error message and kills Emacs. */
4578 x_error_quitter (display
, error
)
4582 char buf
[256], buf1
[356];
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 sprintf (buf1
, "X protocol error: %s on protocol request %d\n",
4589 buf
, error
->request_code
);
4590 x_connection_closed (display
, buf1
);
4593 /* This is the handler for X IO errors, always.
4594 It kills all frames on the display that we lost touch with.
4595 If that was the only one, it prints an error message and kills Emacs. */
4598 x_io_error_quitter (display
)
4603 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4604 x_connection_closed (display
, buf
);
4607 /* Handle SIGPIPE, which can happen when the connection to a server
4608 simply goes away. SIGPIPE is handled by x_connection_signal.
4609 It works by sending a no-op command to each X server connection.
4610 When we try a connection that has closed, we get SIGPIPE again.
4611 But this time, it is handled by x_connection_signal_1.
4612 That function knows which connection we were testing,
4613 so it closes that one.
4615 x_connection_closed never returns,
4616 so if more than one connection was lost at once,
4617 we only find one. But XTread_socket keeps trying them all,
4618 so it will notice the other closed one sooner or later. */
4621 static struct x_display_info
*x_connection_signal_dpyinfo
;
4623 static SIGTYPE
x_connection_signal ();
4626 x_connection_signal_1 (signalnum
) /* If we don't have an argument, */
4627 int signalnum
; /* some compilers complain in signal calls. */
4629 signal (SIGPIPE
, x_connection_signal
);
4630 x_connection_closed (x_connection_signal_dpyinfo
,
4631 "connection was lost");
4635 x_connection_signal (signalnum
) /* If we don't have an argument, */
4636 int signalnum
; /* some compilers complain in signal calls. */
4638 x_connection_signal_dpyinfo
= x_display_list
;
4640 sigunblock (SIGPIPE
);
4642 while (x_connection_signal_dpyinfo
)
4644 signal (SIGPIPE
, x_connection_signal_1
);
4647 #ifdef XlibDisplayWriting
4648 /* If the thread-interlock is locked, assume this connection is dead.
4649 This assumes that the library does not make other threads
4650 that can be locking the display legitimately. */
4651 if (x_connection_signal_dpyinfo
->display
->flags
& XlibDisplayWriting
)
4653 x_connection_signal_dpyinfo
->display
->flags
&= ~XlibDisplayWriting
;
4654 x_connection_closed (x_connection_signal_dpyinfo
->display
,
4655 "connection was lost");
4660 XNoOp (x_connection_signal_dpyinfo
->display
);
4662 XSync (x_connection_signal_dpyinfo
->display
, False
);
4664 /* Each time we get here, cycle through the displays now open. */
4665 x_connection_signal_dpyinfo
= x_connection_signal_dpyinfo
->next
;
4668 /* We should have found some closed connection. */
4672 /* A buffer for storing X error messages. */
4673 static char *x_caught_error_message
;
4674 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4676 /* An X error handler which stores the error message in
4677 x_caught_error_message. This is what's installed when
4678 x_catch_errors is in effect. */
4681 x_error_catcher (display
, error
)
4685 XGetErrorText (display
, error
->error_code
,
4686 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4690 /* Begin trapping X errors for display DPY. Actually we trap X errors
4691 for all displays, but DPY should be the display you are actually
4694 After calling this function, X protocol errors no longer cause
4695 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4697 Calling x_check_errors signals an Emacs error if an X error has
4698 occurred since the last call to x_catch_errors or x_check_errors.
4700 Calling x_uncatch_errors resumes the normal error handling. */
4702 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4705 x_catch_errors (dpy
)
4708 /* Make sure any errors from previous requests have been dealt with. */
4711 /* Set up the error buffer. */
4712 x_caught_error_message
4713 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4714 x_caught_error_message
[0] = '\0';
4716 /* Install our little error handler. */
4717 XSetErrorHandler (x_error_catcher
);
4720 /* If any X protocol errors have arrived since the last call to
4721 x_catch_errors or x_check_errors, signal an Emacs error using
4722 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4725 x_check_errors (dpy
, format
)
4729 /* Make sure to catch any errors incurred so far. */
4732 if (x_caught_error_message
[0])
4734 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4736 sprintf (buf
, format
, x_caught_error_message
);
4737 x_uncatch_errors (dpy
);
4742 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4745 x_had_errors_p (dpy
)
4748 /* Make sure to catch any errors incurred so far. */
4751 return x_caught_error_message
[0] != 0;
4754 /* Stop catching X protocol errors and let them make Emacs die. */
4757 x_uncatch_errors (dpy
)
4760 xfree (x_caught_error_message
);
4761 x_caught_error_message
= 0;
4762 XSetErrorHandler (x_error_quitter
);
4766 static unsigned int x_wire_count
;
4769 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4774 /* Changing the font of the frame. */
4776 /* Give frame F the font named FONTNAME as its default font, and
4777 return the full name of that font. FONTNAME may be a wildcard
4778 pattern; in that case, we choose some font that fits the pattern.
4779 The return value shows which font we chose. */
4782 x_new_font (f
, fontname
)
4784 register char *fontname
;
4787 int n_matching_fonts
;
4788 XFontStruct
*font_info
;
4791 /* Get a list of all the fonts that match this name. Once we
4792 have a list of matching fonts, we compare them against the fonts
4793 we already have by comparing font ids. */
4794 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4795 1024, &n_matching_fonts
);
4796 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4797 find any matches; font_names == 0 is the only clue. */
4799 n_matching_fonts
= 0;
4801 /* Don't just give up if n_matching_fonts is 0.
4802 Apparently there's a bug on Suns: XListFontsWithInfo can
4803 fail to find a font, but XLoadQueryFont may still find it. */
4805 /* See if we've already loaded a matching font. */
4806 already_loaded
= -1;
4807 if (n_matching_fonts
!= 0)
4811 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4812 for (j
= 0; j
< n_matching_fonts
; j
++)
4813 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4814 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4817 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4823 /* If we have, just return it from the table. */
4824 if (already_loaded
>= 0)
4825 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4826 /* Otherwise, load the font and add it to the table. */
4834 /* Try to find a character-cell font in the list. */
4836 /* A laudable goal, but this isn't how to do it. */
4837 for (i
= 0; i
< n_matching_fonts
; i
++)
4838 if (! font_info
[i
].per_char
)
4844 /* See comment above. */
4845 if (n_matching_fonts
!= 0)
4846 fontname
= font_names
[i
];
4848 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4851 /* Free the information from XListFonts. */
4852 if (n_matching_fonts
)
4853 XFreeFontNames (font_names
);
4857 /* Do we need to create the table? */
4858 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4860 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4861 FRAME_X_DISPLAY_INFO (f
)->font_table
4862 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4863 * sizeof (struct font_info
));
4865 /* Do we need to grow the table? */
4866 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4867 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4869 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4870 FRAME_X_DISPLAY_INFO (f
)->font_table
4871 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4872 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4873 * sizeof (struct font_info
)));
4876 /* Try to get the full name of FONT. Put it in full_name. */
4878 for (i
= 0; i
< font
->n_properties
; i
++)
4881 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4882 if (!strcmp (atom
, "FONT"))
4884 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4885 (Atom
) (font
->properties
[i
].card32
));
4889 /* Count the number of dashes in the "full name".
4890 If it is too few, this isn't really the font's full name,
4892 In X11R4, the fonts did not come with their canonical names
4910 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4911 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4912 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4914 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4916 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4917 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4918 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4921 fontname
= full_name
;
4924 /* Compute the scroll bar width in character columns. */
4925 if (f
->scroll_bar_pixel_width
> 0)
4927 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
4928 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4931 f
->scroll_bar_cols
= 2;
4933 /* Now make the frame display the given font. */
4934 if (FRAME_X_WINDOW (f
) != 0)
4936 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
4937 f
->output_data
.x
->font
->fid
);
4938 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
4939 f
->output_data
.x
->font
->fid
);
4940 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
4941 f
->output_data
.x
->font
->fid
);
4943 frame_update_line_height (f
);
4944 x_set_window_size (f
, 0, f
->width
, f
->height
);
4947 /* If we are setting a new frame's font for the first time,
4948 there are no faces yet, so this font's height is the line height. */
4949 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
4952 Lisp_Object lispy_name
;
4954 lispy_name
= build_string (fontname
);
4956 /* Free the information from XListFonts. The data
4957 we actually retain comes from XLoadQueryFont. */
4958 XFreeFontNames (font_names
);
4964 x_calc_absolute_position (f
)
4968 int win_x
= 0, win_y
= 0;
4969 int flags
= f
->output_data
.x
->size_hint_flags
;
4972 #ifdef USE_X_TOOLKIT
4973 this_window
= XtWindow (f
->output_data
.x
->widget
);
4975 this_window
= FRAME_X_WINDOW (f
);
4978 /* Find the position of the outside upper-left corner of
4979 the inner window, with respect to the outer window. */
4980 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4983 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4985 /* From-window, to-window. */
4987 f
->output_data
.x
->parent_desc
,
4989 /* From-position, to-position. */
4990 0, 0, &win_x
, &win_y
,
4997 /* Treat negative positions as relative to the leftmost bottommost
4998 position that fits on the screen. */
4999 if (flags
& XNegative
)
5000 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
5001 - 2 * f
->output_data
.x
->border_width
- win_x
5003 + f
->output_data
.x
->left_pos
);
5005 if (flags
& YNegative
)
5006 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
5007 - 2 * f
->output_data
.x
->border_width
- win_y
5009 - (FRAME_EXTERNAL_MENU_BAR (f
)
5010 ? f
->output_data
.x
->menubar_height
: 0)
5011 + f
->output_data
.x
->top_pos
);
5012 /* The left_pos and top_pos
5013 are now relative to the top and left screen edges,
5014 so the flags should correspond. */
5015 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5018 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5019 to really change the position, and 0 when calling from
5020 x_make_frame_visible (in that case, XOFF and YOFF are the current
5021 position values). It is -1 when calling from x_set_frame_parameters,
5022 which means, do adjust for borders but don't change the gravity. */
5024 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5026 register int xoff
, yoff
;
5029 int modified_top
, modified_left
;
5031 if (change_gravity
> 0)
5033 f
->output_data
.x
->top_pos
= yoff
;
5034 f
->output_data
.x
->left_pos
= xoff
;
5035 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5037 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5039 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5040 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5042 x_calc_absolute_position (f
);
5045 x_wm_set_size_hint (f
, (long) 0, 0);
5047 /* It is a mystery why we need to add the border_width here
5048 when the frame is already visible, but experiment says we do. */
5049 modified_left
= f
->output_data
.x
->left_pos
;
5050 modified_top
= f
->output_data
.x
->top_pos
;
5051 if (change_gravity
!= 0)
5053 modified_left
+= f
->output_data
.x
->border_width
;
5054 modified_top
+= f
->output_data
.x
->border_width
;
5057 #ifdef USE_X_TOOLKIT
5058 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5059 modified_left
, modified_top
);
5060 #else /* not USE_X_TOOLKIT */
5061 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5062 modified_left
, modified_top
);
5063 #endif /* not USE_X_TOOLKIT */
5067 /* Call this to change the size of frame F's x-window.
5068 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5069 for this size change and subsequent size changes.
5070 Otherwise we leave the window gravity unchanged. */
5072 x_set_window_size (f
, change_gravity
, cols
, rows
)
5077 int pixelwidth
, pixelheight
;
5080 #ifdef USE_X_TOOLKIT
5083 /* The x and y position of the widget is clobbered by the
5084 call to XtSetValues within EmacsFrameSetCharSize.
5085 This is a real kludge, but I don't understand Xt so I can't
5086 figure out a correct fix. Can anyone else tell me? -- rms. */
5087 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5088 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5089 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5090 f
->output_data
.x
->widget
->core
.x
= xpos
;
5091 f
->output_data
.x
->widget
->core
.y
= ypos
;
5095 #else /* not USE_X_TOOLKIT */
5099 check_frame_size (f
, &rows
, &cols
);
5100 f
->output_data
.x
->vertical_scroll_bar_extra
5101 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5103 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5104 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5105 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5106 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5107 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5109 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5110 x_wm_set_size_hint (f
, (long) 0, 0);
5112 XSync (FRAME_X_DISPLAY (f
), False
);
5113 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5114 pixelwidth
, pixelheight
);
5116 /* Now, strictly speaking, we can't be sure that this is accurate,
5117 but the window manager will get around to dealing with the size
5118 change request eventually, and we'll hear how it went when the
5119 ConfigureNotify event gets here.
5121 We could just not bother storing any of this information here,
5122 and let the ConfigureNotify event set everything up, but that
5123 might be kind of confusing to the lisp code, since size changes
5124 wouldn't be reported in the frame parameters until some random
5125 point in the future when the ConfigureNotify event arrives. */
5126 change_frame_size (f
, rows
, cols
, 0, 0);
5127 PIXEL_WIDTH (f
) = pixelwidth
;
5128 PIXEL_HEIGHT (f
) = pixelheight
;
5130 /* If cursor was outside the new size, mark it as off. */
5131 if (f
->phys_cursor_y
>= rows
5132 || f
->phys_cursor_x
>= cols
)
5134 f
->phys_cursor_x
= -1;
5135 f
->phys_cursor_y
= -1;
5138 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5139 receive in the ConfigureNotify event; if we get what we asked
5140 for, then the event won't cause the screen to become garbaged, so
5141 we have to make sure to do it here. */
5142 SET_FRAME_GARBAGED (f
);
5144 XFlush (FRAME_X_DISPLAY (f
));
5146 #endif /* not USE_X_TOOLKIT */
5149 /* Mouse warping. */
5152 x_set_mouse_position (f
, x
, y
)
5158 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5159 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5161 if (pix_x
< 0) pix_x
= 0;
5162 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5164 if (pix_y
< 0) pix_y
= 0;
5165 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5169 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5170 0, 0, 0, 0, pix_x
, pix_y
);
5174 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5177 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5183 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5184 0, 0, 0, 0, pix_x
, pix_y
);
5188 /* focus shifting, raising and lowering. */
5190 x_focus_on_frame (f
)
5193 #if 0 /* This proves to be unpleasant. */
5197 /* I don't think that the ICCCM allows programs to do things like this
5198 without the interaction of the window manager. Whatever you end up
5199 doing with this code, do it to x_unfocus_frame too. */
5200 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5201 RevertToPointerRoot
, CurrentTime
);
5209 /* Look at the remarks in x_focus_on_frame. */
5210 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5211 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5212 RevertToPointerRoot
, CurrentTime
);
5216 /* Raise frame F. */
5221 if (f
->async_visible
)
5224 #ifdef USE_X_TOOLKIT
5225 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5226 #else /* not USE_X_TOOLKIT */
5227 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5228 #endif /* not USE_X_TOOLKIT */
5229 XFlush (FRAME_X_DISPLAY (f
));
5234 /* Lower frame F. */
5239 if (f
->async_visible
)
5242 #ifdef USE_X_TOOLKIT
5243 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5244 #else /* not USE_X_TOOLKIT */
5245 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5246 #endif /* not USE_X_TOOLKIT */
5247 XFlush (FRAME_X_DISPLAY (f
));
5253 XTframe_raise_lower (f
, raise_flag
)
5263 /* Change of visibility. */
5265 /* This tries to wait until the frame is really visible.
5266 However, if the window manager asks the user where to position
5267 the frame, this will return before the user finishes doing that.
5268 The frame will not actually be visible at that time,
5269 but it will become visible later when the window manager
5270 finishes with it. */
5272 x_make_frame_visible (f
)
5280 type
= x_icon_type (f
);
5282 x_bitmap_icon (f
, type
);
5284 if (! FRAME_VISIBLE_P (f
))
5286 /* We test FRAME_GARBAGED_P here to make sure we don't
5287 call x_set_offset a second time
5288 if we get to x_make_frame_visible a second time
5289 before the window gets really visible. */
5290 if (! FRAME_ICONIFIED_P (f
)
5291 && ! f
->output_data
.x
->asked_for_visible
)
5292 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5294 f
->output_data
.x
->asked_for_visible
= 1;
5296 if (! EQ (Vx_no_window_manager
, Qt
))
5297 x_wm_set_window_state (f
, NormalState
);
5298 #ifdef USE_X_TOOLKIT
5299 /* This was XtPopup, but that did nothing for an iconified frame. */
5300 XtMapWidget (f
->output_data
.x
->widget
);
5301 #else /* not USE_X_TOOLKIT */
5302 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5303 #endif /* not USE_X_TOOLKIT */
5304 #if 0 /* This seems to bring back scroll bars in the wrong places
5305 if the window configuration has changed. They seem
5306 to come back ok without this. */
5307 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5308 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5312 XFlush (FRAME_X_DISPLAY (f
));
5314 /* Synchronize to ensure Emacs knows the frame is visible
5315 before we do anything else. We do this loop with input not blocked
5316 so that incoming events are handled. */
5319 int count
= input_signal_count
;
5321 /* This must come after we set COUNT. */
5324 XSETFRAME (frame
, f
);
5329 /* Once we have handled input events,
5330 we should have received the MapNotify if one is coming.
5331 So if we have not got it yet, stop looping.
5332 Some window managers make their own decisions
5333 about visibility. */
5334 if (input_signal_count
!= count
)
5336 /* Machines that do polling rather than SIGIO have been observed
5337 to go into a busy-wait here. So we'll fake an alarm signal
5338 to let the handler know that there's something to be read.
5339 We used to raise a real alarm, but it seems that the handler
5340 isn't always enabled here. This is probably a bug. */
5341 if (input_polling_used ())
5343 /* It could be confusing if a real alarm arrives while processing
5344 the fake one. Turn it off and let the handler reset it. */
5346 input_poll_signal ();
5348 /* Once we have handled input events,
5349 we should have received the MapNotify if one is coming.
5350 So if we have not got it yet, stop looping.
5351 Some window managers make their own decisions
5352 about visibility. */
5353 if (input_signal_count
!= count
)
5356 FRAME_SAMPLE_VISIBILITY (f
);
5360 /* Change from mapped state to withdrawn state. */
5362 /* Make the frame visible (mapped and not iconified). */
5364 x_make_frame_invisible (f
)
5370 #ifdef USE_X_TOOLKIT
5371 /* Use the frame's outermost window, not the one we normally draw on. */
5372 window
= XtWindow (f
->output_data
.x
->widget
);
5373 #else /* not USE_X_TOOLKIT */
5374 window
= FRAME_X_WINDOW (f
);
5375 #endif /* not USE_X_TOOLKIT */
5377 /* Don't keep the highlight on an invisible frame. */
5378 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5379 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5381 #if 0/* This might add unreliability; I don't trust it -- rms. */
5382 if (! f
->async_visible
&& ! f
->async_iconified
)
5388 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5389 that the current position of the window is user-specified, rather than
5390 program-specified, so that when the window is mapped again, it will be
5391 placed at the same location, without forcing the user to position it
5392 by hand again (they have already done that once for this window.) */
5393 x_wm_set_size_hint (f
, (long) 0, 1);
5397 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5398 DefaultScreen (FRAME_X_DISPLAY (f
))))
5400 UNBLOCK_INPUT_RESIGNAL
;
5401 error ("Can't notify window manager of window withdrawal");
5403 #else /* ! defined (HAVE_X11R4) */
5405 /* Tell the window manager what we're going to do. */
5406 if (! EQ (Vx_no_window_manager
, Qt
))
5410 unmap
.xunmap
.type
= UnmapNotify
;
5411 unmap
.xunmap
.window
= window
;
5412 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5413 unmap
.xunmap
.from_configure
= False
;
5414 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5415 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5417 SubstructureRedirectMask
|SubstructureNotifyMask
,
5420 UNBLOCK_INPUT_RESIGNAL
;
5421 error ("Can't notify window manager of withdrawal");
5425 /* Unmap the window ourselves. Cheeky! */
5426 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5427 #endif /* ! defined (HAVE_X11R4) */
5429 /* We can't distinguish this from iconification
5430 just by the event that we get from the server.
5431 So we can't win using the usual strategy of letting
5432 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5433 and synchronize with the server to make sure we agree. */
5435 FRAME_ICONIFIED_P (f
) = 0;
5436 f
->async_visible
= 0;
5437 f
->async_iconified
= 0;
5444 /* Change window state from mapped to iconified. */
5453 /* Don't keep the highlight on an invisible frame. */
5454 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5455 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5457 if (f
->async_iconified
)
5462 FRAME_SAMPLE_VISIBILITY (f
);
5464 type
= x_icon_type (f
);
5466 x_bitmap_icon (f
, type
);
5468 #ifdef USE_X_TOOLKIT
5470 if (! FRAME_VISIBLE_P (f
))
5472 if (! EQ (Vx_no_window_manager
, Qt
))
5473 x_wm_set_window_state (f
, IconicState
);
5474 /* This was XtPopup, but that did nothing for an iconified frame. */
5475 XtMapWidget (f
->output_data
.x
->widget
);
5480 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5481 XtWindow (f
->output_data
.x
->widget
),
5482 DefaultScreen (FRAME_X_DISPLAY (f
)));
5486 error ("Can't notify window manager of iconification");
5488 f
->async_iconified
= 1;
5491 XFlush (FRAME_X_DISPLAY (f
));
5493 #else /* not USE_X_TOOLKIT */
5495 /* Make sure the X server knows where the window should be positioned,
5496 in case the user deiconifies with the window manager. */
5497 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5498 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5500 /* Since we don't know which revision of X we're running, we'll use both
5501 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5503 /* X11R4: send a ClientMessage to the window manager using the
5504 WM_CHANGE_STATE type. */
5508 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5509 message
.xclient
.type
= ClientMessage
;
5510 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5511 message
.xclient
.format
= 32;
5512 message
.xclient
.data
.l
[0] = IconicState
;
5514 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5515 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5517 SubstructureRedirectMask
| SubstructureNotifyMask
,
5520 UNBLOCK_INPUT_RESIGNAL
;
5521 error ("Can't notify window manager of iconification");
5525 /* X11R3: set the initial_state field of the window manager hints to
5527 x_wm_set_window_state (f
, IconicState
);
5529 if (!FRAME_VISIBLE_P (f
))
5531 /* If the frame was withdrawn, before, we must map it. */
5532 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5535 f
->async_iconified
= 1;
5537 XFlush (FRAME_X_DISPLAY (f
));
5539 #endif /* not USE_X_TOOLKIT */
5542 /* Destroy the X window of frame F. */
5544 x_destroy_window (f
)
5547 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5551 /* If a display connection is dead, don't try sending more
5552 commands to the X server. */
5553 if (dpyinfo
->display
!= 0)
5555 if (f
->output_data
.x
->icon_desc
!= 0)
5556 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
5557 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
5558 #ifdef USE_X_TOOLKIT
5559 XtDestroyWidget (f
->output_data
.x
->widget
);
5560 free_frame_menubar (f
);
5561 #endif /* USE_X_TOOLKIT */
5563 free_frame_faces (f
);
5564 XFlush (FRAME_X_DISPLAY (f
));
5567 xfree (f
->output_data
.x
);
5568 f
->output_data
.x
= 0;
5569 if (f
== dpyinfo
->x_focus_frame
)
5570 dpyinfo
->x_focus_frame
= 0;
5571 if (f
== dpyinfo
->x_focus_event_frame
)
5572 dpyinfo
->x_focus_event_frame
= 0;
5573 if (f
== dpyinfo
->x_highlight_frame
)
5574 dpyinfo
->x_highlight_frame
= 0;
5576 dpyinfo
->reference_count
--;
5578 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5580 dpyinfo
->mouse_face_beg_row
5581 = dpyinfo
->mouse_face_beg_col
= -1;
5582 dpyinfo
->mouse_face_end_row
5583 = dpyinfo
->mouse_face_end_col
= -1;
5584 dpyinfo
->mouse_face_window
= Qnil
;
5590 /* Setting window manager hints. */
5592 /* Set the normal size hints for the window manager, for frame F.
5593 FLAGS is the flags word to use--or 0 meaning preserve the flags
5594 that the window now has.
5595 If USER_POSITION is nonzero, we set the USPosition
5596 flag (this is useful when FLAGS is 0). */
5598 x_wm_set_size_hint (f
, flags
, user_position
)
5603 XSizeHints size_hints
;
5605 #ifdef USE_X_TOOLKIT
5608 Dimension widget_width
, widget_height
;
5609 Window window
= XtWindow (f
->output_data
.x
->widget
);
5610 #else /* not USE_X_TOOLKIT */
5611 Window window
= FRAME_X_WINDOW (f
);
5612 #endif /* not USE_X_TOOLKIT */
5614 /* Setting PMaxSize caused various problems. */
5615 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5617 flexlines
= f
->height
;
5619 size_hints
.x
= f
->output_data
.x
->left_pos
;
5620 size_hints
.y
= f
->output_data
.x
->top_pos
;
5622 #ifdef USE_X_TOOLKIT
5623 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5624 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5625 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5626 size_hints
.height
= widget_height
;
5627 size_hints
.width
= widget_width
;
5628 #else /* not USE_X_TOOLKIT */
5629 size_hints
.height
= PIXEL_HEIGHT (f
);
5630 size_hints
.width
= PIXEL_WIDTH (f
);
5631 #endif /* not USE_X_TOOLKIT */
5633 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
5634 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
5635 size_hints
.max_width
5636 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5637 size_hints
.max_height
5638 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5640 /* Calculate the base and minimum sizes.
5642 (When we use the X toolkit, we don't do it here.
5643 Instead we copy the values that the widgets are using, below.) */
5644 #ifndef USE_X_TOOLKIT
5646 int base_width
, base_height
;
5647 int min_rows
= 0, min_cols
= 0;
5649 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5650 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5652 check_frame_size (f
, &min_rows
, &min_cols
);
5654 /* The window manager uses the base width hints to calculate the
5655 current number of rows and columns in the frame while
5656 resizing; min_width and min_height aren't useful for this
5657 purpose, since they might not give the dimensions for a
5658 zero-row, zero-column frame.
5660 We use the base_width and base_height members if we have
5661 them; otherwise, we set the min_width and min_height members
5662 to the size for a zero x zero frame. */
5665 size_hints
.flags
|= PBaseSize
;
5666 size_hints
.base_width
= base_width
;
5667 size_hints
.base_height
= base_height
;
5668 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5669 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5671 size_hints
.min_width
= base_width
;
5672 size_hints
.min_height
= base_height
;
5676 /* If we don't need the old flags, we don't need the old hint at all. */
5679 size_hints
.flags
|= flags
;
5682 #endif /* not USE_X_TOOLKIT */
5685 XSizeHints hints
; /* Sometimes I hate X Windows... */
5686 long supplied_return
;
5690 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5693 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5696 #ifdef USE_X_TOOLKIT
5697 size_hints
.base_height
= hints
.base_height
;
5698 size_hints
.base_width
= hints
.base_width
;
5699 size_hints
.min_height
= hints
.min_height
;
5700 size_hints
.min_width
= hints
.min_width
;
5704 size_hints
.flags
|= flags
;
5709 if (hints
.flags
& PSize
)
5710 size_hints
.flags
|= PSize
;
5711 if (hints
.flags
& PPosition
)
5712 size_hints
.flags
|= PPosition
;
5713 if (hints
.flags
& USPosition
)
5714 size_hints
.flags
|= USPosition
;
5715 if (hints
.flags
& USSize
)
5716 size_hints
.flags
|= USSize
;
5723 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
5724 size_hints
.flags
|= PWinGravity
;
5728 size_hints
.flags
&= ~ PPosition
;
5729 size_hints
.flags
|= USPosition
;
5731 #endif /* PWinGravity */
5734 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5736 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5740 /* Used for IconicState or NormalState */
5741 x_wm_set_window_state (f
, state
)
5745 #ifdef USE_X_TOOLKIT
5748 XtSetArg (al
[0], XtNinitialState
, state
);
5749 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5750 #else /* not USE_X_TOOLKIT */
5751 Window window
= FRAME_X_WINDOW (f
);
5753 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5754 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5756 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5757 #endif /* not USE_X_TOOLKIT */
5760 x_wm_set_icon_pixmap (f
, pixmap_id
)
5764 #ifdef USE_X_TOOLKIT
5765 Window window
= XtWindow (f
->output_data
.x
->widget
);
5767 Window window
= FRAME_X_WINDOW (f
);
5772 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5773 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5777 /* It seems there is no way to turn off use of an icon pixmap.
5778 The following line does it, only if no icon has yet been created,
5779 for some window managers. But with mwm it crashes.
5780 Some people say it should clear the IconPixmapHint bit in this case,
5781 but that doesn't work, and the X consortium said it isn't the
5782 right thing at all. Since there is no way to win,
5783 best to explicitly give up. */
5785 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5791 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5792 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5795 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5799 #ifdef USE_X_TOOLKIT
5800 Window window
= XtWindow (f
->output_data
.x
->widget
);
5802 Window window
= FRAME_X_WINDOW (f
);
5805 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5806 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5807 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5809 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5813 /* Initialization. */
5815 #ifdef USE_X_TOOLKIT
5816 static XrmOptionDescRec emacs_options
[] = {
5817 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5818 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5820 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5821 XrmoptionSepArg
, NULL
},
5822 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5824 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5825 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5826 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5827 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5828 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5829 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5830 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5832 #endif /* USE_X_TOOLKIT */
5834 static int x_initialized
;
5837 /* Test whether two display-name strings agree up to the dot that separates
5838 the screen number from the server number. */
5840 same_x_server (name1
, name2
)
5841 char *name1
, *name2
;
5844 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5848 if (seen_colon
&& *name1
== '.')
5852 && (*name1
== '.' || *name1
== '\0')
5853 && (*name2
== '.' || *name2
== '\0'));
5857 struct x_display_info
*
5858 x_term_init (display_name
, xrm_option
, resource_name
)
5859 Lisp_Object display_name
;
5861 char *resource_name
;
5867 struct x_display_info
*dpyinfo
;
5879 setlocale (LC_ALL
, "");
5882 #ifdef USE_X_TOOLKIT
5883 /* weiner@footloose.sps.mot.com reports that this causes
5885 X protocol error: BadAtom (invalid Atom parameter)
5886 on protocol request 18skiloaf.
5887 So let's not use it until R6. */
5889 XtSetLanguageProc (NULL
, NULL
, NULL
);
5900 argv
[argc
++] = "-xrm";
5901 argv
[argc
++] = xrm_option
;
5903 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5904 resource_name
, EMACS_CLASS
,
5905 emacs_options
, XtNumber (emacs_options
),
5909 setlocale (LC_NUMERIC
, "C");
5910 setlocale (LC_TIME
, "C");
5914 #else /* not USE_X_TOOLKIT */
5916 XSetLocaleModifiers ("");
5918 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5919 #endif /* not USE_X_TOOLKIT */
5921 /* Detect failure. */
5928 /* We have definitely succeeded. Record the new connection. */
5930 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5934 struct x_display_info
*share
;
5937 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5938 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5939 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5940 XSTRING (display_name
)->data
))
5943 dpyinfo
->kboard
= share
->kboard
;
5946 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5947 init_kboard (dpyinfo
->kboard
);
5948 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
5950 char *vendor
= ServerVendor (dpy
);
5951 dpyinfo
->kboard
->Vsystem_key_alist
5952 = call1 (Qvendor_specific_keysyms
,
5953 build_string (vendor
? vendor
: ""));
5956 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5957 all_kboards
= dpyinfo
->kboard
;
5958 /* Don't let the initial kboard remain current longer than necessary.
5959 That would cause problems if a file loaded on startup tries to
5960 prompt in the minibuffer. */
5961 if (current_kboard
== initial_kboard
)
5962 current_kboard
= dpyinfo
->kboard
;
5964 dpyinfo
->kboard
->reference_count
++;
5968 /* Put this display on the chain. */
5969 dpyinfo
->next
= x_display_list
;
5970 x_display_list
= dpyinfo
;
5972 /* Put it on x_display_name_list as well, to keep them parallel. */
5973 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5974 x_display_name_list
);
5975 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5977 dpyinfo
->display
= dpy
;
5980 XSetAfterFunction (x_current_display
, x_trace_wire
);
5984 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5985 + XSTRING (Vsystem_name
)->size
5987 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5988 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5990 /* Figure out which modifier bits mean what. */
5991 x_find_modifier_meanings (dpyinfo
);
5993 /* Get the scroll bar cursor. */
5994 dpyinfo
->vertical_scroll_bar_cursor
5995 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5997 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5998 resource_name
, EMACS_CLASS
);
5999 #ifdef HAVE_XRMSETDATABASE
6000 XrmSetDatabase (dpyinfo
->display
, xrdb
);
6002 dpyinfo
->display
->db
= xrdb
;
6004 /* Put the rdb where we can find it in a way that works on
6006 dpyinfo
->xrdb
= xrdb
;
6008 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
6009 DefaultScreen (dpyinfo
->display
));
6010 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
6011 &dpyinfo
->n_planes
);
6012 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
6013 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
6014 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
6015 dpyinfo
->grabbed
= 0;
6016 dpyinfo
->reference_count
= 0;
6017 dpyinfo
->icon_bitmap_id
= -1;
6018 dpyinfo
->n_fonts
= 0;
6019 dpyinfo
->font_table_size
= 0;
6020 dpyinfo
->bitmaps
= 0;
6021 dpyinfo
->bitmaps_size
= 0;
6022 dpyinfo
->bitmaps_last
= 0;
6023 dpyinfo
->scratch_cursor_gc
= 0;
6024 dpyinfo
->mouse_face_mouse_frame
= 0;
6025 dpyinfo
->mouse_face_deferred_gc
= 0;
6026 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6027 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6028 dpyinfo
->mouse_face_face_id
= 0;
6029 dpyinfo
->mouse_face_window
= Qnil
;
6030 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
6031 dpyinfo
->mouse_face_defer
= 0;
6032 dpyinfo
->x_focus_frame
= 0;
6033 dpyinfo
->x_focus_event_frame
= 0;
6034 dpyinfo
->x_highlight_frame
= 0;
6036 dpyinfo
->Xatom_wm_protocols
6037 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
6038 dpyinfo
->Xatom_wm_take_focus
6039 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
6040 dpyinfo
->Xatom_wm_save_yourself
6041 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
6042 dpyinfo
->Xatom_wm_delete_window
6043 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
6044 dpyinfo
->Xatom_wm_change_state
6045 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
6046 dpyinfo
->Xatom_wm_configure_denied
6047 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
6048 dpyinfo
->Xatom_wm_window_moved
6049 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
6050 dpyinfo
->Xatom_editres
6051 = XInternAtom (dpyinfo
->display
, "Editres", False
);
6052 dpyinfo
->Xatom_CLIPBOARD
6053 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
6054 dpyinfo
->Xatom_TIMESTAMP
6055 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
6057 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
6058 dpyinfo
->Xatom_DELETE
6059 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
6060 dpyinfo
->Xatom_MULTIPLE
6061 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
6063 = XInternAtom (dpyinfo
->display
, "INCR", False
);
6064 dpyinfo
->Xatom_EMACS_TMP
6065 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
6066 dpyinfo
->Xatom_TARGETS
6067 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
6069 = XInternAtom (dpyinfo
->display
, "NULL", False
);
6070 dpyinfo
->Xatom_ATOM_PAIR
6071 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
6073 dpyinfo
->cut_buffers_initialized
= 0;
6075 connection
= ConnectionNumber (dpyinfo
->display
);
6076 dpyinfo
->connection
= connection
;
6079 /* This is only needed for distinguishing keyboard and process input. */
6080 if (connection
!= 0)
6081 add_keyboard_wait_descriptor (connection
);
6084 #ifndef F_SETOWN_BUG
6086 #ifdef F_SETOWN_SOCK_NEG
6087 /* stdin is a socket here */
6088 fcntl (connection
, F_SETOWN
, -getpid ());
6089 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6090 fcntl (connection
, F_SETOWN
, getpid ());
6091 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6092 #endif /* ! defined (F_SETOWN) */
6093 #endif /* F_SETOWN_BUG */
6096 if (interrupt_input
)
6097 init_sigio (connection
);
6098 #endif /* ! defined (SIGIO) */
6105 /* Get rid of display DPYINFO, assuming all frames are already gone,
6106 and without sending any more commands to the X server. */
6109 x_delete_display (dpyinfo
)
6110 struct x_display_info
*dpyinfo
;
6112 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
6114 /* Discard this display from x_display_name_list and x_display_list.
6115 We can't use Fdelq because that can quit. */
6116 if (! NILP (x_display_name_list
)
6117 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
6118 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
6123 tail
= x_display_name_list
;
6124 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
6126 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
6127 dpyinfo
->name_list_element
))
6129 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
6132 tail
= XCONS (tail
)->cdr
;
6136 if (x_display_list
== dpyinfo
)
6137 x_display_list
= dpyinfo
->next
;
6140 struct x_display_info
*tail
;
6142 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
6143 if (tail
->next
== dpyinfo
)
6144 tail
->next
= tail
->next
->next
;
6147 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6148 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6149 XrmDestroyDatabase (dpyinfo
->xrdb
);
6153 if (--dpyinfo
->kboard
->reference_count
== 0)
6154 delete_kboard (dpyinfo
->kboard
);
6156 xfree (dpyinfo
->font_table
);
6157 xfree (dpyinfo
->x_id_name
);
6161 /* Set up use of X before we make the first connection. */
6165 clear_frame_hook
= XTclear_frame
;
6166 clear_end_of_line_hook
= XTclear_end_of_line
;
6167 ins_del_lines_hook
= XTins_del_lines
;
6168 change_line_highlight_hook
= XTchange_line_highlight
;
6169 insert_glyphs_hook
= XTinsert_glyphs
;
6170 write_glyphs_hook
= XTwrite_glyphs
;
6171 delete_glyphs_hook
= XTdelete_glyphs
;
6172 ring_bell_hook
= XTring_bell
;
6173 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6174 set_terminal_modes_hook
= XTset_terminal_modes
;
6175 update_begin_hook
= XTupdate_begin
;
6176 update_end_hook
= XTupdate_end
;
6177 set_terminal_window_hook
= XTset_terminal_window
;
6178 read_socket_hook
= XTread_socket
;
6179 frame_up_to_date_hook
= XTframe_up_to_date
;
6180 cursor_to_hook
= XTcursor_to
;
6181 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6182 mouse_position_hook
= XTmouse_position
;
6183 frame_rehighlight_hook
= XTframe_rehighlight
;
6184 frame_raise_lower_hook
= XTframe_raise_lower
;
6185 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6186 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6187 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6188 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6190 scroll_region_ok
= 1; /* we'll scroll partial frames */
6191 char_ins_del_ok
= 0; /* just as fast to write the line */
6192 line_ins_del_ok
= 1; /* we'll just blt 'em */
6193 fast_clear_end_of_line
= 1; /* X does this well */
6194 memory_below_frame
= 0; /* we don't remember what scrolls
6200 /* Try to use interrupt input; if we can't, then start polling. */
6201 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6203 #ifdef USE_X_TOOLKIT
6204 XtToolkitInitialize ();
6205 Xt_app_con
= XtCreateApplicationContext ();
6206 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
6209 /* Note that there is no real way portable across R3/R4 to get the
6210 original error handler. */
6211 XSetErrorHandler (x_error_quitter
);
6212 XSetIOErrorHandler (x_io_error_quitter
);
6214 /* Disable Window Change signals; they are handled by X events. */
6216 signal (SIGWINCH
, SIG_DFL
);
6217 #endif /* ! defined (SIGWINCH) */
6219 signal (SIGPIPE
, x_connection_signal
);
6225 staticpro (&x_display_name_list
);
6226 x_display_name_list
= Qnil
;
6228 staticpro (&last_mouse_scroll_bar
);
6229 last_mouse_scroll_bar
= Qnil
;
6231 staticpro (&Qvendor_specific_keysyms
);
6232 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6234 #endif /* ! defined (HAVE_X_WINDOWS) */