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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
60 #ifndef INCLUDED_FCNTL
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
71 #include "dispextern.h"
72 #include "termhooks.h"
84 #include "intervals.h"
87 extern void free_frame_menubar ();
88 extern FRAME_PTR
x_menubar_window_to_frame ();
89 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
91 extern void _XEditResCheckMessages ();
92 #endif /* not NO_EDITRES */
93 #endif /* USE_X_TOOLKIT */
96 #define x_any_window_to_frame x_window_to_frame
97 #define x_top_window_to_frame x_window_to_frame
102 #ifndef XtNinitialState
103 #define XtNinitialState "initialState"
108 /* So we can do setlocale. */
112 #define min(a,b) ((a)<(b) ? (a) : (b))
113 #define max(a,b) ((a)>(b) ? (a) : (b))
115 /* This is a chain of structures for all the X displays currently in use. */
116 struct x_display_info
*x_display_list
;
118 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
119 one for each element of x_display_list and in the same order.
120 NAME is the name of the frame.
121 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
122 Lisp_Object x_display_name_list
;
124 /* Frame being updated by update_frame. This is declared in term.c.
125 This is set by update_begin and looked at by all the
126 XT functions. It is zero while not inside an update.
127 In that case, the XT functions assume that `selected_frame'
128 is the frame to apply to. */
129 extern struct frame
*updating_frame
;
131 /* This is a frame waiting to be autoraised, within XTread_socket. */
132 struct frame
*pending_autoraise_frame
;
135 /* The application context for Xt use. */
136 XtAppContext Xt_app_con
;
138 static String Xt_default_resources
[] =
144 /* During an update, maximum vpos for ins/del line operations to affect. */
146 static int flexlines
;
148 /* During an update, nonzero if chars output now should be highlighted. */
150 static int highlight
;
152 /* Nominal cursor position -- where to draw output.
153 During an update, these are different from the cursor-box position. */
160 In order to avoid asking for motion events and then throwing most
161 of them away or busy-polling the server for mouse positions, we ask
162 the server for pointer motion hints. This means that we get only
163 one event per group of mouse movements. "Groups" are delimited by
164 other kinds of events (focus changes and button clicks, for
165 example), or by XQueryPointer calls; when one of these happens, we
166 get another MotionNotify event the next time the mouse moves. This
167 is at least as efficient as getting motion events when mouse
168 tracking is on, and I suspect only negligibly worse when tracking
171 The silly O'Reilly & Associates Nutshell guides barely document
172 pointer motion hints at all (I think you have to infer how they
173 work from an example), and the description of XQueryPointer doesn't
174 mention that calling it causes you to get another motion hint from
175 the server, which is very important. */
177 /* Where the mouse was last time we reported a mouse event. */
178 static FRAME_PTR last_mouse_frame
;
179 static XRectangle last_mouse_glyph
;
181 /* The scroll bar in which the last X motion event occurred.
183 If the last X motion event occurred in a scroll bar, we set this
184 so XTmouse_position can know whether to report a scroll bar motion or
187 If the last X motion event didn't occur in a scroll bar, we set this
188 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
189 static Lisp_Object last_mouse_scroll_bar
;
191 /* This is a hack. We would really prefer that XTmouse_position would
192 return the time associated with the position it returns, but there
193 doesn't seem to be any way to wrest the timestamp from the server
194 along with the position query. So, we just keep track of the time
195 of the last movement we received, and return that in hopes that
196 it's somewhat accurate. */
197 static Time last_mouse_movement_time
;
199 /* Incremented by XTread_socket whenever it really tries to read events. */
201 static int volatile input_signal_count
;
203 static int input_signal_count
;
206 /* Used locally within XTread_socket. */
207 static int x_noop_count
;
209 /* Initial values of argv and argc. */
210 extern char **initial_argv
;
211 extern int initial_argc
;
213 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
215 /* Tells if a window manager is present or not. */
217 extern Lisp_Object Vx_no_window_manager
;
219 /* Nonzero enables some debugging for the X interface code. */
222 extern Lisp_Object Qface
, Qmouse_face
;
226 /* A mask of extra modifier bits to put into every keyboard char. */
227 extern int extra_keyboard_modifiers
;
229 static Lisp_Object Qvendor_specific_keysyms
;
231 extern XrmDatabase
x_load_resources ();
233 extern Lisp_Object
x_icon_type ();
235 void x_delete_display ();
237 static void redraw_previous_char ();
238 static void redraw_following_char ();
239 static unsigned int x_x_to_emacs_modifiers ();
241 static int fast_find_position ();
242 static void note_mouse_highlight ();
243 static void clear_mouse_face ();
244 static void show_mouse_face ();
245 static void do_line_dance ();
247 static int XTcursor_to ();
248 static int XTclear_end_of_line ();
249 static int x_io_error_quitter ();
250 void x_catch_errors ();
251 void x_uncatch_errors ();
254 /* This is a function useful for recording debugging information
255 about the sequence of occurrences in this file. */
263 struct record event_record
[100];
265 int event_record_index
;
267 record_event (locus
, type
)
271 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
272 event_record_index
= 0;
274 event_record
[event_record_index
].locus
= locus
;
275 event_record
[event_record_index
].type
= type
;
276 event_record_index
++;
281 /* Return the struct x_display_info corresponding to DPY. */
283 struct x_display_info
*
284 x_display_info_for_display (dpy
)
287 struct x_display_info
*dpyinfo
;
289 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
290 if (dpyinfo
->display
== dpy
)
296 /* Starting and ending updates.
298 These hooks are called by update_frame at the beginning and end
299 of a frame update. We record in `updating_frame' the identity
300 of the frame being updated, so that the XT... functions do not
301 need to take a frame as argument. Most of the XT... functions
302 should never be called except during an update, the only exceptions
303 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
314 flexlines
= f
->height
;
319 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
321 /* Don't do highlighting for mouse motion during the update. */
322 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
324 /* If the frame needs to be redrawn,
325 simply forget about any prior mouse highlighting. */
326 if (FRAME_GARBAGED_P (f
))
327 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
329 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
331 int firstline
, lastline
, i
;
332 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
334 /* Find the first, and the last+1, lines affected by redisplay. */
335 for (firstline
= 0; firstline
< f
->height
; firstline
++)
336 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
339 lastline
= f
->height
;
340 for (i
= f
->height
- 1; i
>= 0; i
--)
342 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
348 /* Can we tell that this update does not affect the window
349 where the mouse highlight is? If so, no need to turn off.
350 Likewise, don't do anything if the frame is garbaged;
351 in that case, the FRAME_CURRENT_GLYPHS that we would use
352 are all wrong, and we will redisplay that line anyway. */
353 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
354 || lastline
< XFASTINT (w
->top
)))
355 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
371 x_display_cursor (f
, 1);
373 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
374 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
376 /* This fails in the case of having updated only the echo area
377 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
378 has no relation to the current contents, and its charstarts
379 have no relation to the contents of the window-buffer.
380 I don't know a clean way to check
381 for that case. window_end_valid isn't set up yet. */
382 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
383 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
384 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
387 XFlush (FRAME_X_DISPLAY (f
));
391 /* This is called after a redisplay on frame F. */
394 XTframe_up_to_date (f
)
397 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
398 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
400 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
401 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
402 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
403 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
407 /* External interface to control of standout mode.
408 Call this when about to modify line at position VPOS
409 and not change whether it is highlighted. */
411 XTreassert_line_highlight (new, vpos
)
417 /* Call this when about to modify line at position VPOS
418 and change whether it is highlighted. */
421 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
422 int new_highlight
, vpos
, first_unused_hpos
;
424 highlight
= new_highlight
;
425 XTcursor_to (vpos
, 0);
426 XTclear_end_of_line (updating_frame
->width
);
429 /* This is used when starting Emacs and when restarting after suspend.
430 When starting Emacs, no X window is mapped. And nothing must be done
431 to Emacs's own window if it is suspended (though that rarely happens). */
434 XTset_terminal_modes ()
438 /* This is called when exiting or suspending Emacs.
439 Exiting will make the X-windows go away, and suspending
440 requires no action. */
443 XTreset_terminal_modes ()
445 /* XTclear_frame (); */
448 /* Set the nominal cursor position of the frame.
449 This is where display update commands will take effect.
450 This does not affect the place where the cursor-box is displayed. */
453 XTcursor_to (row
, col
)
454 register int row
, col
;
462 if (updating_frame
== 0)
465 x_display_cursor (selected_frame
, 1);
466 XFlush (FRAME_X_DISPLAY (selected_frame
));
471 /* Display a sequence of N glyphs found at GP.
472 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
473 HL is 1 if this text is highlighted, 2 if the cursor is on it,
474 3 if should appear in its mouse-face.
475 JUST_FOREGROUND if 1 means draw only the foreground;
476 don't alter the background.
478 FONT is the default font to use (for glyphs whose font-code is 0).
480 Since the display generation code is responsible for calling
481 compute_char_face and compute_glyph_face on everything it puts in
482 the display structure, we can assume that the face code on each
483 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
484 to which we can actually apply intern_face.
485 Call this function with input blocked. */
488 /* This is the multi-face code. */
491 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
494 register GLYPH
*gp
; /* Points to first GLYPH. */
495 register int n
; /* Number of glyphs to display. */
499 /* Holds characters to be displayed. */
500 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
501 register char *cp
; /* Steps through buf[]. */
502 register int tlen
= GLYPH_TABLE_LENGTH
;
503 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
504 Window window
= FRAME_X_WINDOW (f
);
505 int orig_left
= left
;
509 /* Get the face-code of the next GLYPH. */
513 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
514 cf
= FAST_GLYPH_FACE (g
);
516 /* Find the run of consecutive glyphs with the same face-code.
517 Extract their character codes into BUF. */
522 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
523 if (FAST_GLYPH_FACE (g
) != cf
)
526 *cp
++ = FAST_GLYPH_CHAR (g
);
531 /* LEN gets the length of the run. */
534 /* Now output this run of chars, with the font and pixel values
535 determined by the face code CF. */
537 struct face
*face
= FRAME_DEFAULT_FACE (f
);
538 XFontStruct
*font
= FACE_FONT (face
);
539 GC gc
= FACE_GC (face
);
542 /* HL = 3 means use a mouse face previously chosen. */
544 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
546 /* First look at the face of the text itself. */
549 /* It's possible for the display table to specify
550 a face code that is out of range. Use 0 in that case. */
551 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
552 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
556 face
= FRAME_MODE_LINE_FACE (f
);
558 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
559 font
= FACE_FONT (face
);
561 if (FACE_STIPPLE (face
))
565 /* Then comes the distinction between modeline and normal text. */
570 face
= FRAME_MODE_LINE_FACE (f
);
571 font
= FACE_FONT (face
);
573 if (FACE_STIPPLE (face
))
577 #define FACE_DEFAULT (~0)
579 /* Now override that if the cursor's on this character. */
582 /* The cursor overrides stippling. */
586 || face
->font
== (XFontStruct
*) FACE_DEFAULT
587 || face
->font
== f
->output_data
.x
->font
)
588 && face
->background
== f
->output_data
.x
->background_pixel
589 && face
->foreground
== f
->output_data
.x
->foreground_pixel
)
591 gc
= f
->output_data
.x
->cursor_gc
;
593 /* Cursor on non-default face: must merge. */
599 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
600 xgcv
.foreground
= face
->background
;
601 /* If the glyph would be invisible,
602 try a different foreground. */
603 if (xgcv
.foreground
== xgcv
.background
)
604 xgcv
.foreground
= face
->foreground
;
605 if (xgcv
.foreground
== xgcv
.background
)
606 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
607 if (xgcv
.foreground
== xgcv
.background
)
608 xgcv
.foreground
= face
->foreground
;
609 /* Make sure the cursor is distinct from text in this face. */
610 if (xgcv
.background
== face
->background
611 && xgcv
.foreground
== face
->foreground
)
613 xgcv
.background
= face
->foreground
;
614 xgcv
.foreground
= face
->background
;
616 xgcv
.font
= face
->font
->fid
;
617 xgcv
.graphics_exposures
= 0;
618 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
619 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
620 XChangeGC (FRAME_X_DISPLAY (f
),
621 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
624 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
625 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
626 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
628 /* If this code is restored, it must also reset to the default stipple
630 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
631 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
636 if (font
== (XFontStruct
*) FACE_DEFAULT
)
637 font
= f
->output_data
.x
->font
;
640 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
641 left
, top
+ FONT_BASE (font
), buf
, len
);
646 /* Turn stipple on. */
647 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
649 /* Draw stipple on background. */
650 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
652 FONT_WIDTH (font
) * len
,
655 /* Turn stipple off. */
656 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
658 /* Draw the text, solidly, onto the stipple pattern. */
659 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
660 left
, top
+ FONT_BASE (font
), buf
, len
);
663 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
664 left
, top
+ FONT_BASE (font
), buf
, len
);
666 /* Clear the rest of the line's height. */
667 if (f
->output_data
.x
->line_height
!= FONT_HEIGHT (font
))
668 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
669 top
+ FONT_HEIGHT (font
),
670 FONT_WIDTH (font
) * len
,
671 /* This is how many pixels of height
673 f
->output_data
.x
->line_height
- FONT_HEIGHT (font
),
677 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
678 which often is not up to date yet. */
679 if (!just_foreground
)
681 if (left
== orig_left
)
682 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
683 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
685 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
686 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
690 /* We should probably check for XA_UNDERLINE_POSITION and
691 XA_UNDERLINE_THICKNESS properties on the font, but let's
692 just get the thing working, and come back to that. */
694 int underline_position
= 1;
696 if (font
->descent
<= underline_position
)
697 underline_position
= font
->descent
- 1;
700 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
704 + underline_position
),
705 len
* FONT_WIDTH (font
), 1);
708 left
+= len
* FONT_WIDTH (font
);
715 /* This is the old single-face code. */
718 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
721 register GLYPH
*gp
; /* Points to first GLYPH. */
722 register int n
; /* Number of glyphs to display. */
727 Window window
= FRAME_X_WINDOW (f
);
728 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
729 : (hl
? f
->output_data
.x
->reverse_gc
730 : f
->output_data
.x
->normal_gc
));
732 if (sizeof (GLYPH
) == sizeof (XChar2b
))
733 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
734 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
735 else if (sizeof (GLYPH
) == sizeof (unsigned char))
736 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
737 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
739 /* What size of glyph ARE you using? And does X have a function to
745 /* Output some text at the nominal frame cursor position.
746 Advance the cursor over the text.
747 Output LEN glyphs at START.
749 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
750 controls the pixel values used for foreground and background. */
753 XTwrite_glyphs (start
, len
)
754 register GLYPH
*start
;
757 register int temp_length
;
768 /* If not within an update,
769 output at the frame's visible cursor. */
770 curs_x
= f
->cursor_x
;
771 curs_y
= f
->cursor_y
;
775 CHAR_TO_PIXEL_COL (f
, curs_x
),
776 CHAR_TO_PIXEL_ROW (f
, curs_y
),
777 start
, len
, highlight
, 0);
779 /* If we drew on top of the cursor, note that it is turned off. */
780 if (curs_y
== f
->phys_cursor_y
781 && curs_x
<= f
->phys_cursor_x
782 && curs_x
+ len
> f
->phys_cursor_x
)
783 f
->phys_cursor_x
= -1;
785 if (updating_frame
== 0)
788 x_display_cursor (f
, 1);
797 /* Clear to the end of the line.
798 Erase the current text line from the nominal cursor position (inclusive)
799 to column FIRST_UNUSED (exclusive). The idea is that everything
800 from FIRST_UNUSED onward is already erased. */
803 XTclear_end_of_line (first_unused
)
804 register int first_unused
;
806 struct frame
*f
= updating_frame
;
812 if (curs_y
< 0 || curs_y
>= f
->height
)
814 if (first_unused
<= 0)
817 if (first_unused
>= f
->width
)
818 first_unused
= f
->width
;
824 /* Notice if the cursor will be cleared by this operation. */
825 if (curs_y
== f
->phys_cursor_y
826 && curs_x
<= f
->phys_cursor_x
827 && f
->phys_cursor_x
< first_unused
)
828 f
->phys_cursor_x
= -1;
830 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
831 CHAR_TO_PIXEL_COL (f
, curs_x
),
832 CHAR_TO_PIXEL_ROW (f
, curs_y
),
833 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
834 f
->output_data
.x
->line_height
, False
);
836 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
846 struct frame
*f
= updating_frame
;
851 f
->phys_cursor_x
= -1; /* Cursor not visible. */
852 curs_x
= 0; /* Nominal cursor position is top left. */
857 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
859 /* We have to clear the scroll bars, too. If we have changed
860 colors or something like that, then they should be notified. */
861 x_scroll_bar_clear (f
);
863 XFlush (FRAME_X_DISPLAY (f
));
868 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
869 always contain the right glyphs to use.
871 It also needs to be changed to look at the details of the font and
872 see whether there is really overlap, and do nothing when there is
873 not. This can use font_char_overlap_left and font_char_overlap_right,
874 but just how to use them is not clear. */
876 /* Erase the character (if any) at the position just before X, Y in frame F,
877 then redraw it and the character before it.
878 This is necessary when we erase starting at X,
879 in case the character after X overlaps into the one before X.
880 Call this function with input blocked. */
883 redraw_previous_char (f
, x
, y
, highlight_flag
)
888 /* Erase the character before the new ones, in case
889 what was here before overlaps it.
890 Reoutput that character, and the previous character
891 (in case the previous character overlaps it). */
897 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
898 CHAR_TO_PIXEL_COL (f
, x
- 1),
899 CHAR_TO_PIXEL_ROW (f
, y
),
900 FONT_WIDTH (f
->output_data
.x
->font
),
901 f
->output_data
.x
->line_height
, False
);
903 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
904 CHAR_TO_PIXEL_ROW (f
, y
),
905 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
906 x
- start_x
, highlight_flag
, 1);
910 /* Erase the character (if any) at the position X, Y in frame F,
911 then redraw it and the character after it.
912 This is necessary when we erase endng at X,
913 in case the character after X overlaps into the one before X.
914 Call this function with input blocked. */
917 redraw_following_char (f
, x
, y
, highlight_flag
)
922 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
923 /* Erase the character after the new ones, in case
924 what was here before overlaps it.
925 Reoutput that character, and the following character
926 (in case the following character overlaps it). */
928 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
933 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
934 CHAR_TO_PIXEL_COL (f
, x
),
935 CHAR_TO_PIXEL_ROW (f
, y
),
936 FONT_WIDTH (f
->output_data
.x
->font
),
937 f
->output_data
.x
->line_height
, False
);
939 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
940 CHAR_TO_PIXEL_ROW (f
, y
),
941 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
942 end_x
- x
, highlight_flag
, 1);
947 #if 0 /* Not in use yet */
949 /* Return 1 if character C in font F extends past its left edge. */
952 font_char_overlap_left (font
, c
)
958 /* Find the bounding-box info for C. */
959 if (font
->per_char
== 0)
960 s
= &font
->max_bounds
;
963 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
966 /* Decode char into row number (byte 1) and code within row (byte 2). */
969 if (!(within
>= font
->min_char_or_byte2
970 && within
<= font
->max_char_or_byte2
971 && row
>= font
->min_byte1
972 && row
<= font
->max_byte1
))
974 /* If char is out of range, try the font's default char instead. */
975 c
= font
->default_char
;
976 row
= c
>> (BITS_PER_INT
- 8);
979 if (!(within
>= font
->min_char_or_byte2
980 && within
<= font
->max_char_or_byte2
981 && row
>= font
->min_byte1
982 && row
<= font
->max_byte1
))
983 /* Still out of range means this char does not overlap. */
986 /* We found the info for this char. */
987 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
991 return (s
&& s
->lbearing
< 0);
994 /* Return 1 if character C in font F extends past its right edge. */
997 font_char_overlap_right (font
, c
)
1003 /* Find the bounding-box info for C. */
1004 if (font
->per_char
== 0)
1005 s
= &font
->max_bounds
;
1008 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1011 /* Decode char into row number (byte 1) and code within row (byte 2). */
1014 if (!(within
>= font
->min_char_or_byte2
1015 && within
<= font
->max_char_or_byte2
1016 && row
>= font
->min_byte1
1017 && row
<= font
->max_byte1
))
1019 /* If char is out of range, try the font's default char instead. */
1020 c
= font
->default_char
;
1021 row
= c
>> (BITS_PER_INT
- 8);
1024 if (!(within
>= font
->min_char_or_byte2
1025 && within
<= font
->max_char_or_byte2
1026 && row
>= font
->min_byte1
1027 && row
<= font
->max_byte1
))
1028 /* Still out of range means this char does not overlap. */
1031 /* We found the info for this char. */
1032 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1036 return (s
&& s
->rbearing
>= s
->width
);
1040 /* Invert the middle quarter of the frame for .15 sec. */
1042 /* We use the select system call to do the waiting, so we have to make sure
1043 it's available. If it isn't, we just won't do visual bells. */
1044 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1046 /* Subtract the `struct timeval' values X and Y,
1047 storing the result in RESULT.
1048 Return 1 if the difference is negative, otherwise 0. */
1051 timeval_subtract (result
, x
, y
)
1052 struct timeval
*result
, x
, y
;
1054 /* Perform the carry for the later subtraction by updating y.
1055 This is safer because on some systems
1056 the tv_sec member is unsigned. */
1057 if (x
.tv_usec
< y
.tv_usec
)
1059 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1060 y
.tv_usec
-= 1000000 * nsec
;
1063 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1065 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1066 y
.tv_usec
+= 1000000 * nsec
;
1070 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1071 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1072 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1074 /* Return indication of whether the result should be considered negative. */
1075 return x
.tv_sec
< y
.tv_sec
;
1086 /* Create a GC that will use the GXxor function to flip foreground pixels
1087 into background pixels. */
1091 values
.function
= GXxor
;
1092 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1093 ^ f
->output_data
.x
->background_pixel
);
1095 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1096 GCFunction
| GCForeground
, &values
);
1100 int width
= PIXEL_WIDTH (f
);
1101 int height
= PIXEL_HEIGHT (f
);
1103 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1104 width
/4, height
/4, width
/2, height
/2);
1105 XFlush (FRAME_X_DISPLAY (f
));
1108 struct timeval wakeup
, now
;
1110 EMACS_GET_TIME (wakeup
);
1112 /* Compute time to wait until, propagating carry from usecs. */
1113 wakeup
.tv_usec
+= 150000;
1114 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1115 wakeup
.tv_usec
%= 1000000;
1117 /* Keep waiting until past the time wakeup. */
1120 struct timeval timeout
;
1122 EMACS_GET_TIME (timeout
);
1124 /* In effect, timeout = wakeup - timeout.
1125 Break if result would be negative. */
1126 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1129 /* Try to wait that long--but we might wake up sooner. */
1130 select (0, NULL
, NULL
, NULL
, &timeout
);
1134 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1135 width
/4, height
/4, width
/2, height
/2);
1136 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1137 XFlush (FRAME_X_DISPLAY (f
));
1147 /* Make audible bell. */
1149 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1153 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1156 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1158 XTflash (selected_frame
);
1164 XFlush (FRAME_X_DISPLAY (selected_frame
));
1169 /* Insert and delete character.
1170 These are not supposed to be used because we are supposed to turn
1171 off the feature of using them. */
1174 XTinsert_glyphs (start
, len
)
1175 register char *start
;
1188 /* Specify how many text lines, from the top of the window,
1189 should be affected by insert-lines and delete-lines operations.
1190 This, and those operations, are used only within an update
1191 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1194 XTset_terminal_window (n
)
1197 if (updating_frame
== 0)
1200 if ((n
<= 0) || (n
> updating_frame
->height
))
1201 flexlines
= updating_frame
->height
;
1206 /* These variables need not be per frame
1207 because redisplay is done on a frame-by-frame basis
1208 and the line dance for one frame is finished before
1209 anything is done for anoter frame. */
1211 /* Array of line numbers from cached insert/delete operations.
1212 line_dance[i] is the old position of the line that we want
1213 to move to line i, or -1 if we want a blank line there. */
1214 static int *line_dance
;
1216 /* Allocated length of that array. */
1217 static int line_dance_len
;
1219 /* Flag indicating whether we've done any work. */
1220 static int line_dance_in_progress
;
1222 /* Perform an insert-lines or delete-lines operation,
1223 inserting N lines or deleting -N lines at vertical position VPOS. */
1224 XTins_del_lines (vpos
, n
)
1227 register int fence
, i
;
1229 if (vpos
>= flexlines
)
1232 if (!line_dance_in_progress
)
1234 int ht
= updating_frame
->height
;
1235 if (ht
> line_dance_len
)
1237 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1238 line_dance_len
= ht
;
1240 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1241 line_dance_in_progress
= 1;
1245 if (n
> flexlines
- vpos
)
1246 n
= flexlines
- vpos
;
1248 for (i
= flexlines
; --i
>= fence
;)
1249 line_dance
[i
] = line_dance
[i
-n
];
1250 for (i
= fence
; --i
>= vpos
;)
1256 if (n
> flexlines
- vpos
)
1257 n
= flexlines
- vpos
;
1258 fence
= flexlines
- n
;
1259 for (i
= vpos
; i
< fence
; ++i
)
1260 line_dance
[i
] = line_dance
[i
+ n
];
1261 for (i
= fence
; i
< flexlines
; ++i
)
1266 /* Here's where we actually move the pixels around.
1267 Must be called with input blocked. */
1271 register int i
, j
, distance
;
1272 register struct frame
*f
;
1276 /* Must check this flag first. If it's not set, then not only is the
1277 array uninitialized, but we might not even have a frame. */
1278 if (!line_dance_in_progress
)
1286 intborder
= f
->output_data
.x
->internal_border_width
;
1288 x_display_cursor (updating_frame
, 0);
1290 for (i
= 0; i
< ht
; ++i
)
1291 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1293 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1294 && line_dance
[j
]-j
== distance
); ++j
);
1295 /* Copy [i,j) upward from [i+distance,j+distance) */
1296 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1297 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1298 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1299 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1300 (j
-i
) * f
->output_data
.x
->line_height
,
1301 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1305 for (i
= ht
; --i
>=0; )
1306 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1308 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1309 && line_dance
[j
]-j
== distance
););
1310 /* Copy (j,i] downward from (j+distance, i+distance] */
1311 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1312 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1313 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1314 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1315 (i
-j
) * f
->output_data
.x
->line_height
,
1316 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1320 for (i
= 0; i
< ht
; ++i
)
1321 if (line_dance
[i
] == -1)
1323 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1325 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1326 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1327 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1328 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1331 line_dance_in_progress
= 0;
1334 /* Support routines for exposure events. */
1335 static void clear_cursor ();
1337 /* Output into a rectangle of an X-window (for frame F)
1338 the characters in f->phys_lines that overlap that rectangle.
1339 TOP and LEFT are the position of the upper left corner of the rectangle.
1340 ROWS and COLS are the size of the rectangle.
1341 Call this function with input blocked. */
1344 dumprectangle (f
, left
, top
, cols
, rows
)
1346 register int left
, top
, cols
, rows
;
1348 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1349 int cursor_cleared
= 0;
1353 if (FRAME_GARBAGED_P (f
))
1356 /* Express rectangle as four edges, instead of position-and-size. */
1357 bottom
= top
+ rows
;
1358 right
= left
+ cols
;
1360 /* Convert rectangle edges in pixels to edges in chars.
1361 Round down for left and top, up for right and bottom. */
1362 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1363 left
= PIXEL_TO_CHAR_COL (f
, left
);
1364 bottom
+= (f
->output_data
.x
->line_height
- 1);
1365 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1366 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1367 right
= PIXEL_TO_CHAR_COL (f
, right
);
1369 /* Clip the rectangle to what can be visible. */
1374 if (right
> f
->width
)
1376 if (bottom
> f
->height
)
1379 /* Get size in chars of the rectangle. */
1380 cols
= right
- left
;
1381 rows
= bottom
- top
;
1383 /* If rectangle has zero area, return. */
1384 if (rows
<= 0) return;
1385 if (cols
<= 0) return;
1387 /* Turn off the cursor if it is in the rectangle.
1388 We will turn it back on afterward. */
1389 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1390 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1396 /* Display the text in the rectangle, one text line at a time. */
1398 for (y
= top
; y
< bottom
; y
++)
1400 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1402 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1406 CHAR_TO_PIXEL_COL (f
, left
),
1407 CHAR_TO_PIXEL_ROW (f
, y
),
1408 line
, min (cols
, active_frame
->used
[y
] - left
),
1409 active_frame
->highlight
[y
], 0);
1412 /* Turn the cursor on if we turned it off. */
1415 x_display_cursor (f
, 1);
1422 /* We used to only do this if Vx_no_window_manager was non-nil, but
1423 the ICCCM (section 4.1.6) says that the window's border pixmap
1424 and border pixel are window attributes which are "private to the
1425 client", so we can always change it to whatever we want. */
1427 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1428 f
->output_data
.x
->border_pixel
);
1430 x_update_cursor (f
, 1);
1434 frame_unhighlight (f
)
1437 /* We used to only do this if Vx_no_window_manager was non-nil, but
1438 the ICCCM (section 4.1.6) says that the window's border pixmap
1439 and border pixel are window attributes which are "private to the
1440 client", so we can always change it to whatever we want. */
1442 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1443 f
->output_data
.x
->border_tile
);
1445 x_update_cursor (f
, 1);
1448 static void XTframe_rehighlight ();
1449 static void x_frame_rehighlight ();
1451 /* The focus has changed. Update the frames as necessary to reflect
1452 the new situation. Note that we can't change the selected frame
1453 here, because the Lisp code we are interrupting might become confused.
1454 Each event gets marked with the frame in which it occurred, so the
1455 Lisp code can tell when the switch took place by examining the events. */
1458 x_new_focus_frame (dpyinfo
, frame
)
1459 struct x_display_info
*dpyinfo
;
1460 struct frame
*frame
;
1462 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1463 int events_enqueued
= 0;
1465 if (frame
!= dpyinfo
->x_focus_frame
)
1467 /* Set this before calling other routines, so that they see
1468 the correct value of x_focus_frame. */
1469 dpyinfo
->x_focus_frame
= frame
;
1471 if (old_focus
&& old_focus
->auto_lower
)
1472 x_lower_frame (old_focus
);
1475 selected_frame
= frame
;
1476 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1478 Fselect_window (selected_frame
->selected_window
);
1479 choose_minibuf_frame ();
1482 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1483 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1485 pending_autoraise_frame
= 0;
1488 x_frame_rehighlight (dpyinfo
);
1491 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1494 x_mouse_leave (dpyinfo
)
1495 struct x_display_info
*dpyinfo
;
1497 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1500 /* The focus has changed, or we have redirected a frame's focus to
1501 another frame (this happens when a frame uses a surrogate
1502 minibuffer frame). Shift the highlight as appropriate.
1504 The FRAME argument doesn't necessarily have anything to do with which
1505 frame is being highlighted or unhighlighted; we only use it to find
1506 the appropriate X display info. */
1508 XTframe_rehighlight (frame
)
1509 struct frame
*frame
;
1511 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
1515 x_frame_rehighlight (dpyinfo
)
1516 struct x_display_info
*dpyinfo
;
1518 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1520 if (dpyinfo
->x_focus_frame
)
1522 dpyinfo
->x_highlight_frame
1523 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
1524 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
1525 : dpyinfo
->x_focus_frame
);
1526 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
1528 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
1529 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1533 dpyinfo
->x_highlight_frame
= 0;
1535 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
1538 frame_unhighlight (old_highlight
);
1539 if (dpyinfo
->x_highlight_frame
)
1540 frame_highlight (dpyinfo
->x_highlight_frame
);
1544 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1546 /* Initialize mode_switch_bit and modifier_meaning. */
1548 x_find_modifier_meanings (dpyinfo
)
1549 struct x_display_info
*dpyinfo
;
1551 int min_code
, max_code
;
1554 XModifierKeymap
*mods
;
1556 dpyinfo
->meta_mod_mask
= 0;
1557 dpyinfo
->shift_lock_mask
= 0;
1558 dpyinfo
->alt_mod_mask
= 0;
1559 dpyinfo
->super_mod_mask
= 0;
1560 dpyinfo
->hyper_mod_mask
= 0;
1563 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1565 min_code
= display
->min_keycode
;
1566 max_code
= display
->max_keycode
;
1569 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1570 min_code
, max_code
- min_code
+ 1,
1572 mods
= XGetModifierMapping (dpyinfo
->display
);
1574 /* Scan the modifier table to see which modifier bits the Meta and
1575 Alt keysyms are on. */
1577 int row
, col
; /* The row and column in the modifier table. */
1579 for (row
= 3; row
< 8; row
++)
1580 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1583 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1585 /* Zeroes are used for filler. Skip them. */
1589 /* Are any of this keycode's keysyms a meta key? */
1593 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1595 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1601 dpyinfo
->meta_mod_mask
|= (1 << row
);
1606 dpyinfo
->alt_mod_mask
|= (1 << row
);
1611 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1616 dpyinfo
->super_mod_mask
|= (1 << row
);
1620 /* Ignore this if it's not on the lock modifier. */
1621 if ((1 << row
) == LockMask
)
1622 dpyinfo
->shift_lock_mask
= LockMask
;
1630 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1631 if (! dpyinfo
->meta_mod_mask
)
1633 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1634 dpyinfo
->alt_mod_mask
= 0;
1637 /* If some keys are both alt and meta,
1638 make them just meta, not alt. */
1639 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1641 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1644 XFree ((char *) syms
);
1645 XFreeModifiermap (mods
);
1648 /* Convert between the modifier bits X uses and the modifier bits
1651 x_x_to_emacs_modifiers (dpyinfo
, state
)
1652 struct x_display_info
*dpyinfo
;
1655 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1656 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1657 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1658 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1659 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1660 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1664 x_emacs_to_x_modifiers (dpyinfo
, state
)
1665 struct x_display_info
*dpyinfo
;
1668 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1669 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1670 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1671 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1672 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1673 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1676 /* Convert a keysym to its name. */
1679 x_get_keysym_name (keysym
)
1685 value
= XKeysymToString (keysym
);
1691 /* Mouse clicks and mouse movement. Rah. */
1693 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1694 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1695 that the glyph at X, Y occupies, if BOUNDS != 0.
1696 If NOCLIP is nonzero, do not force the value into range. */
1699 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1701 register int pix_x
, pix_y
;
1702 register int *x
, *y
;
1706 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1707 even for negative values. */
1709 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
1711 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
1713 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1714 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1718 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
1719 bounds
->height
= f
->output_data
.x
->line_height
;
1720 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1721 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1728 else if (pix_x
> f
->width
)
1733 else if (pix_y
> f
->height
)
1742 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1745 register int *pix_x
, *pix_y
;
1747 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1748 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1751 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1753 If the event is a button press, then note that we have grabbed
1757 construct_mouse_click (result
, event
, f
)
1758 struct input_event
*result
;
1759 XButtonEvent
*event
;
1762 /* Make the event type no_event; we'll change that when we decide
1764 result
->kind
= mouse_click
;
1765 result
->code
= event
->button
- Button1
;
1766 result
->timestamp
= event
->time
;
1767 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1769 | (event
->type
== ButtonRelease
1777 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1778 XSETFASTINT (result
->x
, column
);
1779 XSETFASTINT (result
->y
, row
);
1781 XSETINT (result
->x
, event
->x
);
1782 XSETINT (result
->y
, event
->y
);
1783 XSETFRAME (result
->frame_or_window
, f
);
1787 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1790 construct_menu_click (result
, event
, f
)
1791 struct input_event
*result
;
1792 XButtonEvent
*event
;
1795 /* Make the event type no_event; we'll change that when we decide
1797 result
->kind
= mouse_click
;
1798 XSETINT (result
->code
, event
->button
- Button1
);
1799 result
->timestamp
= event
->time
;
1800 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1802 | (event
->type
== ButtonRelease
1806 XSETINT (result
->x
, event
->x
);
1807 XSETINT (result
->y
, -1);
1808 XSETFRAME (result
->frame_or_window
, f
);
1811 /* Function to report a mouse movement to the mainstream Emacs code.
1812 The input handler calls this.
1814 We have received a mouse movement event, which is given in *event.
1815 If the mouse is over a different glyph than it was last time, tell
1816 the mainstream emacs code by setting mouse_moved. If not, ask for
1817 another motion event, so we can check again the next time it moves. */
1820 note_mouse_movement (frame
, event
)
1822 XMotionEvent
*event
;
1824 last_mouse_movement_time
= event
->time
;
1826 if (event
->window
!= FRAME_X_WINDOW (frame
))
1828 frame
->mouse_moved
= 1;
1829 last_mouse_scroll_bar
= Qnil
;
1831 note_mouse_highlight (frame
, -1, -1);
1833 /* Ask for another mouse motion event. */
1836 Window dummy_window
;
1838 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1839 &dummy_window
, &dummy_window
,
1840 &dummy
, &dummy
, &dummy
, &dummy
,
1841 (unsigned int *) &dummy
);
1845 /* Has the mouse moved off the glyph it was on at the last sighting? */
1846 else if (event
->x
< last_mouse_glyph
.x
1847 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1848 || event
->y
< last_mouse_glyph
.y
1849 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1851 frame
->mouse_moved
= 1;
1852 last_mouse_scroll_bar
= Qnil
;
1854 note_mouse_highlight (frame
, event
->x
, event
->y
);
1856 /* Ask for another mouse motion event. */
1859 Window dummy_window
;
1861 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1862 &dummy_window
, &dummy_window
,
1863 &dummy
, &dummy
, &dummy
, &dummy
,
1864 (unsigned int *) &dummy
);
1869 /* It's on the same glyph. Call XQueryPointer so we'll get an
1870 event the next time the mouse moves and we can see if it's
1871 *still* on the same glyph. */
1873 Window dummy_window
;
1875 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1876 &dummy_window
, &dummy_window
,
1877 &dummy
, &dummy
, &dummy
, &dummy
,
1878 (unsigned int *) &dummy
);
1882 /* This is used for debugging, to turn off note_mouse_highlight. */
1883 static int disable_mouse_highlight
;
1885 /* Take proper action when the mouse has moved to position X, Y on frame F
1886 as regards highlighting characters that have mouse-face properties.
1887 Also dehighlighting chars where the mouse was before.
1888 X and Y can be negative or out of range. */
1891 note_mouse_highlight (f
, x
, y
)
1895 int row
, column
, portion
;
1896 XRectangle new_glyph
;
1900 if (disable_mouse_highlight
)
1903 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1904 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1905 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1907 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1912 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1916 /* Find out which glyph the mouse is on. */
1917 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1918 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1920 /* Which window is that in? */
1921 window
= window_from_coordinates (f
, column
, row
, &portion
);
1922 w
= XWINDOW (window
);
1924 /* If we were displaying active text in another window, clear that. */
1925 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1926 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1928 /* Are we in a window whose display is up to date?
1929 And verify the buffer's text has not changed. */
1930 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1931 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1932 && EQ (w
->window_end_valid
, w
->buffer
)
1933 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1935 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1938 /* Find which buffer position the mouse corresponds to. */
1939 for (i
= column
; i
>= 0; i
--)
1943 /* Is it outside the displayed active region (if any)? */
1945 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1946 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1947 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1948 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1949 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1950 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1951 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1952 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1953 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1955 Lisp_Object mouse_face
, overlay
, position
;
1956 Lisp_Object
*overlay_vec
;
1957 int len
, noverlays
, ignor1
;
1958 struct buffer
*obuf
;
1961 /* If we get an out-of-range value, return now; avoid an error. */
1962 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1965 /* Make the window's buffer temporarily current for
1966 overlays_at and compute_char_face. */
1967 obuf
= current_buffer
;
1968 current_buffer
= XBUFFER (w
->buffer
);
1974 /* Yes. Clear the display of the old active region, if any. */
1975 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1977 /* Is this char mouse-active? */
1978 XSETINT (position
, pos
);
1981 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1983 /* Put all the overlays we want in a vector in overlay_vec.
1984 Store the length in len. */
1985 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1987 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1989 /* Find the highest priority overlay that has a mouse-face prop. */
1991 for (i
= 0; i
< noverlays
; i
++)
1993 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1994 if (!NILP (mouse_face
))
1996 overlay
= overlay_vec
[i
];
2001 /* If no overlay applies, get a text property. */
2003 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2005 /* Handle the overlay case. */
2006 if (! NILP (overlay
))
2008 /* Find the range of text around this char that
2009 should be active. */
2010 Lisp_Object before
, after
;
2013 before
= Foverlay_start (overlay
);
2014 after
= Foverlay_end (overlay
);
2015 /* Record this as the current active region. */
2016 fast_find_position (window
, before
,
2017 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2018 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2019 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2020 = !fast_find_position (window
, after
,
2021 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2022 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2023 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2024 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2025 = compute_char_face (f
, w
, pos
, 0, 0,
2026 &ignore
, pos
+ 1, 1);
2028 /* Display it as active. */
2029 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2031 /* Handle the text property case. */
2032 else if (! NILP (mouse_face
))
2034 /* Find the range of text around this char that
2035 should be active. */
2036 Lisp_Object before
, after
, beginning
, end
;
2039 beginning
= Fmarker_position (w
->start
);
2040 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2041 - XFASTINT (w
->window_end_pos
)));
2043 = Fprevious_single_property_change (make_number (pos
+ 1),
2045 w
->buffer
, beginning
);
2047 = Fnext_single_property_change (position
, Qmouse_face
,
2049 /* Record this as the current active region. */
2050 fast_find_position (window
, before
,
2051 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2052 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2053 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2054 = !fast_find_position (window
, after
,
2055 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2056 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2057 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2058 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2059 = compute_char_face (f
, w
, pos
, 0, 0,
2060 &ignore
, pos
+ 1, 1);
2062 /* Display it as active. */
2063 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2067 current_buffer
= obuf
;
2072 /* Find the row and column of position POS in window WINDOW.
2073 Store them in *COLUMNP and *ROWP.
2074 This assumes display in WINDOW is up to date.
2075 If POS is above start of WINDOW, return coords
2076 of start of first screen line.
2077 If POS is after end of WINDOW, return coords of end of last screen line.
2079 Value is 1 if POS is in range, 0 if it was off screen. */
2082 fast_find_position (window
, pos
, columnp
, rowp
)
2085 int *columnp
, *rowp
;
2087 struct window
*w
= XWINDOW (window
);
2088 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2093 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2094 int width
= window_internal_width (w
);
2097 int maybe_next_line
= 0;
2099 /* Find the right row. */
2104 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2105 if (linestart
> pos
)
2107 /* If the position sought is the end of the buffer,
2108 don't include the blank lines at the bottom of the window. */
2109 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2111 maybe_next_line
= 1;
2118 /* Find the right column with in it. */
2119 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2121 for (i
= 0; i
< width
; i
++)
2123 if (charstarts
[left
+ i
] == pos
)
2126 *columnp
= i
+ left
;
2129 else if (charstarts
[left
+ i
] > pos
)
2131 else if (charstarts
[left
+ i
] > 0)
2135 /* If we're looking for the end of the buffer,
2136 and we didn't find it in the line we scanned,
2137 use the start of the following line. */
2138 if (maybe_next_line
)
2149 /* Display the active region described by mouse_face_*
2150 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2153 show_mouse_face (dpyinfo
, hl
)
2154 struct x_display_info
*dpyinfo
;
2157 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2158 int width
= window_internal_width (w
);
2159 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2162 int old_curs_x
= curs_x
;
2163 int old_curs_y
= curs_y
;
2165 /* Set these variables temporarily
2166 so that if we have to turn the cursor off and on again
2167 we will put it back at the same place. */
2168 curs_x
= f
->phys_cursor_x
;
2169 curs_y
= f
->phys_cursor_y
;
2171 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2172 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2174 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2175 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2177 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2178 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2180 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2182 /* If the cursor's in the text we are about to rewrite,
2183 turn the cursor off. */
2185 && curs_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
2186 && curs_x
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
)
2188 x_display_cursor (f
, 0);
2193 CHAR_TO_PIXEL_COL (f
, column
),
2194 CHAR_TO_PIXEL_ROW (f
, i
),
2195 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2197 /* Highlight with mouse face if hl > 0. */
2201 /* If we turned the cursor off, turn it back on. */
2203 x_display_cursor (f
, 1);
2205 curs_x
= old_curs_x
;
2206 curs_y
= old_curs_y
;
2208 /* Change the mouse cursor according to the value of HL. */
2210 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2211 f
->output_data
.x
->cross_cursor
);
2213 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2214 f
->output_data
.x
->text_cursor
);
2217 /* Clear out the mouse-highlighted active region.
2218 Redraw it unhighlighted first. */
2221 clear_mouse_face (dpyinfo
)
2222 struct x_display_info
*dpyinfo
;
2224 if (! NILP (dpyinfo
->mouse_face_window
))
2225 show_mouse_face (dpyinfo
, 0);
2227 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2228 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2229 dpyinfo
->mouse_face_window
= Qnil
;
2232 static struct scroll_bar
*x_window_to_scroll_bar ();
2233 static void x_scroll_bar_report_motion ();
2235 /* Return the current position of the mouse.
2236 *fp should be a frame which indicates which display to ask about.
2238 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2239 and *part to the frame, window, and scroll bar part that the mouse
2240 is over. Set *x and *y to the portion and whole of the mouse's
2241 position on the scroll bar.
2243 If the mouse movement started elsewhere, set *fp to the frame the
2244 mouse is on, *bar_window to nil, and *x and *y to the character cell
2247 Set *time to the server timestamp for the time at which the mouse
2248 was at this position.
2250 Don't store anything if we don't have a valid set of values to report.
2252 This clears the mouse_moved flag, so we can wait for the next mouse
2253 movement. This also calls XQueryPointer, which will cause the
2254 server to give us another MotionNotify when the mouse moves
2258 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2261 Lisp_Object
*bar_window
;
2262 enum scroll_bar_part
*part
;
2264 unsigned long *time
;
2270 if (! NILP (last_mouse_scroll_bar
))
2271 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2277 Window dummy_window
;
2280 Lisp_Object frame
, tail
;
2282 /* Clear the mouse-moved flag for every frame on this display. */
2283 FOR_EACH_FRAME (tail
, frame
)
2284 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2285 XFRAME (frame
)->mouse_moved
= 0;
2287 last_mouse_scroll_bar
= Qnil
;
2289 /* Figure out which root window we're on. */
2290 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2291 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2293 /* The root window which contains the pointer. */
2296 /* Trash which we can't trust if the pointer is on
2297 a different screen. */
2300 /* The position on that root window. */
2303 /* More trash we can't trust. */
2306 /* Modifier keys and pointer buttons, about which
2308 (unsigned int *) &dummy
);
2310 /* Now we have a position on the root; find the innermost window
2311 containing the pointer. */
2315 int parent_x
, parent_y
;
2319 /* XTranslateCoordinates can get errors if the window
2320 structure is changing at the same time this function
2321 is running. So at least we must not crash from them. */
2323 x_catch_errors (FRAME_X_DISPLAY (*fp
));
2325 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2326 && FRAME_LIVE_P (last_mouse_frame
))
2328 /* If mouse was grabbed on a frame, give coords for that frame
2329 even if the mouse is now outside it. */
2330 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2332 /* From-window, to-window. */
2333 root
, FRAME_X_WINDOW (last_mouse_frame
),
2335 /* From-position, to-position. */
2336 root_x
, root_y
, &win_x
, &win_y
,
2340 f1
= last_mouse_frame
;
2346 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2348 /* From-window, to-window. */
2351 /* From-position, to-position. */
2352 root_x
, root_y
, &win_x
, &win_y
,
2365 /* Now we know that:
2366 win is the innermost window containing the pointer
2367 (XTC says it has no child containing the pointer),
2368 win_x and win_y are the pointer's position in it
2369 (XTC did this the last time through), and
2370 parent_x and parent_y are the pointer's position in win's parent.
2371 (They are what win_x and win_y were when win was child.
2372 If win is the root window, it has no parent, and
2373 parent_{x,y} are invalid, but that's okay, because we'll
2374 never use them in that case.) */
2376 /* Is win one of our frames? */
2377 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2380 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2383 x_uncatch_errors (FRAME_X_DISPLAY (*fp
));
2385 /* If not, is it one of our scroll bars? */
2388 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2392 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2398 if (f1
== 0 && insist
)
2399 f1
= selected_frame
;
2403 int ignore1
, ignore2
;
2405 /* Ok, we found a frame. Store all the values. */
2407 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2409 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2415 XSETINT (*x
, win_x
);
2416 XSETINT (*y
, win_y
);
2417 *time
= last_mouse_movement_time
;
2425 /* Scroll bar support. */
2427 /* Given an X window ID, find the struct scroll_bar which manages it.
2428 This can be called in GC, so we have to make sure to strip off mark
2430 static struct scroll_bar
*
2431 x_window_to_scroll_bar (window_id
)
2434 Lisp_Object tail
, frame
;
2436 for (tail
= Vframe_list
;
2437 XGCTYPE (tail
) == Lisp_Cons
;
2438 tail
= XCONS (tail
)->cdr
)
2440 Lisp_Object frame
, bar
, condemned
;
2442 frame
= XCONS (tail
)->car
;
2443 /* All elements of Vframe_list should be frames. */
2444 if (! GC_FRAMEP (frame
))
2447 /* Scan this frame's scroll bar list for a scroll bar with the
2449 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2450 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2451 /* This trick allows us to search both the ordinary and
2452 condemned scroll bar lists with one loop. */
2453 ! GC_NILP (bar
) || (bar
= condemned
,
2456 bar
= XSCROLL_BAR (bar
)->next
)
2457 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2458 return XSCROLL_BAR (bar
);
2464 /* Open a new X window to serve as a scroll bar, and return the
2465 scroll bar vector for it. */
2466 static struct scroll_bar
*
2467 x_scroll_bar_create (window
, top
, left
, width
, height
)
2468 struct window
*window
;
2469 int top
, left
, width
, height
;
2471 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2472 struct scroll_bar
*bar
2473 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2478 XSetWindowAttributes a
;
2480 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2481 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2482 | ButtonMotionMask
| PointerMotionHintMask
2484 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2486 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2491 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2492 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2493 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2494 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2495 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2496 sb_widget
= XtCreateManagedWidget ("box",
2498 f
->output_data
.x
->edit_widget
, al
, ac
);
2499 SET_SCROLL_BAR_X_WINDOW
2500 (bar
, sb_widget
->core
.window
);
2502 SET_SCROLL_BAR_X_WINDOW
2504 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2506 /* Position and size of scroll bar. */
2507 left
, top
, width
, height
,
2509 /* Border width, depth, class, and visual. */
2510 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2516 XSETWINDOW (bar
->window
, window
);
2517 XSETINT (bar
->top
, top
);
2518 XSETINT (bar
->left
, left
);
2519 XSETINT (bar
->width
, width
);
2520 XSETINT (bar
->height
, height
);
2521 XSETINT (bar
->start
, 0);
2522 XSETINT (bar
->end
, 0);
2523 bar
->dragging
= Qnil
;
2525 /* Add bar to its frame's list of scroll bars. */
2526 bar
->next
= FRAME_SCROLL_BARS (f
);
2528 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2529 if (! NILP (bar
->next
))
2530 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2532 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2539 /* Draw BAR's handle in the proper position.
2540 If the handle is already drawn from START to END, don't bother
2541 redrawing it, unless REBUILD is non-zero; in that case, always
2542 redraw it. (REBUILD is handy for drawing the handle after expose
2545 Normally, we want to constrain the start and end of the handle to
2546 fit inside its rectangle, but if the user is dragging the scroll bar
2547 handle, we want to let them drag it down all the way, so that the
2548 bar's top is as far down as it goes; otherwise, there's no way to
2549 move to the very end of the buffer. */
2551 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2552 struct scroll_bar
*bar
;
2556 int dragging
= ! NILP (bar
->dragging
);
2557 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2558 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2559 GC gc
= f
->output_data
.x
->normal_gc
;
2561 /* If the display is already accurate, do nothing. */
2563 && start
== XINT (bar
->start
)
2564 && end
== XINT (bar
->end
))
2570 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2571 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2572 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2574 /* Make sure the values are reasonable, and try to preserve
2575 the distance between start and end. */
2577 int length
= end
- start
;
2581 else if (start
> top_range
)
2583 end
= start
+ length
;
2587 else if (end
> top_range
&& ! dragging
)
2591 /* Store the adjusted setting in the scroll bar. */
2592 XSETINT (bar
->start
, start
);
2593 XSETINT (bar
->end
, end
);
2595 /* Clip the end position, just for display. */
2596 if (end
> top_range
)
2599 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2600 below top positions, to make sure the handle is always at least
2601 that many pixels tall. */
2602 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2604 /* Draw the empty space above the handle. Note that we can't clear
2605 zero-height areas; that means "clear to end of window." */
2607 XClearArea (FRAME_X_DISPLAY (f
), w
,
2609 /* x, y, width, height, and exposures. */
2610 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2611 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2612 inside_width
, start
,
2615 /* Draw the handle itself. */
2616 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2618 /* x, y, width, height */
2619 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2620 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2621 inside_width
, end
- start
);
2624 /* Draw the empty space below the handle. Note that we can't
2625 clear zero-height areas; that means "clear to end of window." */
2626 if (end
< inside_height
)
2627 XClearArea (FRAME_X_DISPLAY (f
), w
,
2629 /* x, y, width, height, and exposures. */
2630 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2631 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2632 inside_width
, inside_height
- end
,
2640 /* Move a scroll bar around on the screen, to accommodate changing
2641 window configurations. */
2643 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2644 struct scroll_bar
*bar
;
2645 int top
, left
, width
, height
;
2647 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2648 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2654 unsigned int mask
= 0;
2661 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2662 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2663 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2664 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2667 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2671 XSETINT (bar
->left
, left
);
2672 XSETINT (bar
->top
, top
);
2673 XSETINT (bar
->width
, width
);
2674 XSETINT (bar
->height
, height
);
2679 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2682 x_scroll_bar_remove (bar
)
2683 struct scroll_bar
*bar
;
2685 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2689 /* Destroy the window. */
2690 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2692 /* Disassociate this scroll bar from its window. */
2693 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2698 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2699 that we are displaying PORTION characters out of a total of WHOLE
2700 characters, starting at POSITION. If WINDOW has no scroll bar,
2703 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2704 struct window
*window
;
2705 int portion
, whole
, position
;
2707 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2708 int top
= XINT (window
->top
);
2709 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2710 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2712 /* Where should this scroll bar be, pixelwise? */
2713 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2714 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2716 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2717 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2718 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2719 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2721 struct scroll_bar
*bar
;
2723 /* Does the scroll bar exist yet? */
2724 if (NILP (window
->vertical_scroll_bar
))
2725 bar
= x_scroll_bar_create (window
,
2726 pixel_top
, pixel_left
,
2727 pixel_width
, pixel_height
);
2730 /* It may just need to be moved and resized. */
2731 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2732 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2735 /* Set the scroll bar's current state, unless we're currently being
2737 if (NILP (bar
->dragging
))
2739 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2742 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2745 int start
= ((double) position
* top_range
) / whole
;
2746 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2748 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2752 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2756 /* The following three hooks are used when we're doing a thorough
2757 redisplay of the frame. We don't explicitly know which scroll bars
2758 are going to be deleted, because keeping track of when windows go
2759 away is a real pain - "Can you say set-window-configuration, boys
2760 and girls?" Instead, we just assert at the beginning of redisplay
2761 that *all* scroll bars are to be removed, and then save a scroll bar
2762 from the fiery pit when we actually redisplay its window. */
2764 /* Arrange for all scroll bars on FRAME to be removed at the next call
2765 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2766 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2768 XTcondemn_scroll_bars (frame
)
2771 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2772 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2775 bar
= FRAME_SCROLL_BARS (frame
);
2776 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2777 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2778 XSCROLL_BAR (bar
)->prev
= Qnil
;
2779 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2780 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2781 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2785 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2786 Note that WINDOW isn't necessarily condemned at all. */
2788 XTredeem_scroll_bar (window
)
2789 struct window
*window
;
2791 struct scroll_bar
*bar
;
2793 /* We can't redeem this window's scroll bar if it doesn't have one. */
2794 if (NILP (window
->vertical_scroll_bar
))
2797 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2799 /* Unlink it from the condemned list. */
2801 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2803 if (NILP (bar
->prev
))
2805 /* If the prev pointer is nil, it must be the first in one of
2807 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2808 /* It's not condemned. Everything's fine. */
2810 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2811 window
->vertical_scroll_bar
))
2812 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2814 /* If its prev pointer is nil, it must be at the front of
2815 one or the other! */
2819 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2821 if (! NILP (bar
->next
))
2822 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2824 bar
->next
= FRAME_SCROLL_BARS (f
);
2826 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2827 if (! NILP (bar
->next
))
2828 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2832 /* Remove all scroll bars on FRAME that haven't been saved since the
2833 last call to `*condemn_scroll_bars_hook'. */
2835 XTjudge_scroll_bars (f
)
2838 Lisp_Object bar
, next
;
2840 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2842 /* Clear out the condemned list now so we won't try to process any
2843 more events on the hapless scroll bars. */
2844 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2846 for (; ! NILP (bar
); bar
= next
)
2848 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2850 x_scroll_bar_remove (b
);
2853 b
->next
= b
->prev
= Qnil
;
2856 /* Now there should be no references to the condemned scroll bars,
2857 and they should get garbage-collected. */
2861 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2863 This may be called from a signal handler, so we have to ignore GC
2866 x_scroll_bar_expose (bar
, event
)
2867 struct scroll_bar
*bar
;
2870 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2871 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2872 GC gc
= f
->output_data
.x
->normal_gc
;
2876 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2878 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2879 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2881 /* x, y, width, height */
2882 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2887 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2888 is set to something other than no_event, it is enqueued.
2890 This may be called from a signal handler, so we have to ignore GC
2893 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2894 struct scroll_bar
*bar
;
2896 struct input_event
*emacs_event
;
2898 if (! GC_WINDOWP (bar
->window
))
2901 emacs_event
->kind
= scroll_bar_click
;
2902 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2903 emacs_event
->modifiers
2904 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2905 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2906 event
->xbutton
.state
)
2907 | (event
->type
== ButtonRelease
2910 emacs_event
->frame_or_window
= bar
->window
;
2911 emacs_event
->timestamp
= event
->xbutton
.time
;
2914 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2916 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2917 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2920 if (y
> top_range
) y
= top_range
;
2922 if (y
< XINT (bar
->start
))
2923 emacs_event
->part
= scroll_bar_above_handle
;
2924 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2925 emacs_event
->part
= scroll_bar_handle
;
2927 emacs_event
->part
= scroll_bar_below_handle
;
2929 /* Just because the user has clicked on the handle doesn't mean
2930 they want to drag it. Lisp code needs to be able to decide
2931 whether or not we're dragging. */
2933 /* If the user has just clicked on the handle, record where they're
2935 if (event
->type
== ButtonPress
2936 && emacs_event
->part
== scroll_bar_handle
)
2937 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2940 /* If the user has released the handle, set it to its final position. */
2941 if (event
->type
== ButtonRelease
2942 && ! NILP (bar
->dragging
))
2944 int new_start
= y
- XINT (bar
->dragging
);
2945 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2947 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2948 bar
->dragging
= Qnil
;
2951 /* Same deal here as the other #if 0. */
2953 /* Clicks on the handle are always reported as occurring at the top of
2955 if (emacs_event
->part
== scroll_bar_handle
)
2956 emacs_event
->x
= bar
->start
;
2958 XSETINT (emacs_event
->x
, y
);
2960 XSETINT (emacs_event
->x
, y
);
2963 XSETINT (emacs_event
->y
, top_range
);
2967 /* Handle some mouse motion while someone is dragging the scroll bar.
2969 This may be called from a signal handler, so we have to ignore GC
2972 x_scroll_bar_note_movement (bar
, event
)
2973 struct scroll_bar
*bar
;
2976 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
2978 last_mouse_movement_time
= event
->xmotion
.time
;
2981 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2983 /* If we're dragging the bar, display it. */
2984 if (! GC_NILP (bar
->dragging
))
2986 /* Where should the handle be now? */
2987 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2989 if (new_start
!= XINT (bar
->start
))
2991 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2993 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2997 /* Call XQueryPointer so we'll get an event the next time the mouse
2998 moves and we can see *still* on the same position. */
3001 Window dummy_window
;
3003 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3004 &dummy_window
, &dummy_window
,
3005 &dummy
, &dummy
, &dummy
, &dummy
,
3006 (unsigned int *) &dummy
);
3010 /* Return information to the user about the current position of the mouse
3011 on the scroll bar. */
3013 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3015 Lisp_Object
*bar_window
;
3016 enum scroll_bar_part
*part
;
3018 unsigned long *time
;
3020 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3021 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3022 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3024 Window dummy_window
;
3026 unsigned int dummy_mask
;
3030 /* Get the mouse's position relative to the scroll bar window, and
3032 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3034 /* Root, child, root x and root y. */
3035 &dummy_window
, &dummy_window
,
3036 &dummy_coord
, &dummy_coord
,
3038 /* Position relative to scroll bar. */
3041 /* Mouse buttons and modifier keys. */
3047 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3049 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3051 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3053 if (! NILP (bar
->dragging
))
3054 win_y
-= XINT (bar
->dragging
);
3058 if (win_y
> top_range
)
3062 *bar_window
= bar
->window
;
3064 if (! NILP (bar
->dragging
))
3065 *part
= scroll_bar_handle
;
3066 else if (win_y
< XINT (bar
->start
))
3067 *part
= scroll_bar_above_handle
;
3068 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3069 *part
= scroll_bar_handle
;
3071 *part
= scroll_bar_below_handle
;
3073 XSETINT (*x
, win_y
);
3074 XSETINT (*y
, top_range
);
3077 last_mouse_scroll_bar
= Qnil
;
3080 *time
= last_mouse_movement_time
;
3086 /* The screen has been cleared so we may have changed foreground or
3087 background colors, and the scroll bars may need to be redrawn.
3088 Clear out the scroll bars, and ask for expose events, so we can
3091 x_scroll_bar_clear (f
)
3096 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3097 bar
= XSCROLL_BAR (bar
)->next
)
3098 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3102 /* This processes Expose events from the menubar specific X event
3103 loop in xmenu.c. This allows to redisplay the frame if necessary
3104 when handling menubar or popup items. */
3107 process_expose_from_menu (event
)
3111 struct x_display_info
*dpyinfo
;
3115 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3116 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3119 if (f
->async_visible
== 0)
3121 f
->async_visible
= 1;
3122 f
->async_iconified
= 0;
3123 SET_FRAME_GARBAGED (f
);
3127 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3128 event
.xexpose
.x
, event
.xexpose
.y
,
3129 event
.xexpose
.width
, event
.xexpose
.height
);
3134 struct scroll_bar
*bar
3135 = x_window_to_scroll_bar (event
.xexpose
.window
);
3138 x_scroll_bar_expose (bar
, &event
);
3144 /* Define a queue to save up SelectionRequest events for later handling. */
3146 struct selection_event_queue
3149 struct selection_event_queue
*next
;
3152 static struct selection_event_queue
*queue
;
3154 /* Nonzero means queue up certain events--don't process them yet. */
3155 static int x_queue_selection_requests
;
3157 /* Queue up an X event *EVENT, to be processed later. */
3160 x_queue_event (f
, event
)
3164 struct selection_event_queue
*queue_tmp
3165 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3167 if (queue_tmp
!= NULL
)
3169 queue_tmp
->event
= *event
;
3170 queue_tmp
->next
= queue
;
3175 /* Take all the queued events and put them back
3176 so that they get processed afresh. */
3179 x_unqueue_events (display
)
3182 while (queue
!= NULL
)
3184 struct selection_event_queue
*queue_tmp
= queue
;
3185 XPutBackEvent (display
, &queue_tmp
->event
);
3186 queue
= queue_tmp
->next
;
3187 free ((char *)queue_tmp
);
3191 /* Start queuing SelectionRequest events. */
3194 x_start_queuing_selection_requests (display
)
3197 x_queue_selection_requests
++;
3200 /* Stop queuing SelectionRequest events. */
3203 x_stop_queuing_selection_requests (display
)
3206 x_queue_selection_requests
--;
3207 x_unqueue_events (display
);
3210 /* The main X event-reading loop - XTread_socket. */
3212 /* Timestamp of enter window event. This is only used by XTread_socket,
3213 but we have to put it out here, since static variables within functions
3214 sometimes don't work. */
3215 static Time enter_timestamp
;
3217 /* This holds the state XLookupString needs to implement dead keys
3218 and other tricks known as "compose processing". _X Window System_
3219 says that a portable program can't use this, but Stephen Gildea assures
3220 me that letting the compiler initialize it to zeros will work okay.
3222 This must be defined outside of XTread_socket, for the same reasons
3223 given for enter_timestamp, above. */
3224 static XComposeStatus compose_status
;
3226 /* Record the last 100 characters stored
3227 to help debug the loss-of-chars-during-GC problem. */
3228 static int temp_index
;
3229 static short temp_buffer
[100];
3231 /* Set this to nonzero to fake an "X I/O error"
3232 on a particular display. */
3233 struct x_display_info
*XTread_socket_fake_io_error
;
3235 /* When we find no input here, we occasionally do a no-op command
3236 to verify that the X server is still running and we can still talk with it.
3237 We try all the open displays, one by one.
3238 This variable is used for cycling thru the displays. */
3239 static struct x_display_info
*next_noop_dpyinfo
;
3241 /* Read events coming from the X server.
3242 This routine is called by the SIGIO handler.
3243 We return as soon as there are no more events to be read.
3245 Events representing keys are stored in buffer BUFP,
3246 which can hold up to NUMCHARS characters.
3247 We return the number of characters stored into the buffer,
3248 thus pretending to be `read'.
3250 WAITP is nonzero if we should block until input arrives.
3251 EXPECTED is nonzero if the caller knows input is available. */
3254 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3256 register struct input_event
*bufp
;
3257 register int numchars
;
3264 int items_pending
; /* How many items are in the X queue. */
3267 int event_found
= 0;
3270 struct x_display_info
*dpyinfo
;
3272 Status status_return
;
3275 if (interrupt_input_blocked
)
3277 interrupt_input_pending
= 1;
3281 interrupt_input_pending
= 0;
3284 /* So people can tell when we have read the available input. */
3285 input_signal_count
++;
3288 abort (); /* Don't think this happens. */
3290 /* Find the display we are supposed to read input for.
3291 It's the one communicating on descriptor SD. */
3292 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3294 #if 0 /* This ought to be unnecessary; let's verify it. */
3296 /* If available, Xlib uses FIOSNBIO to make the socket
3297 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3298 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3299 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3300 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3301 #endif /* ! defined (FIOSNBIO) */
3304 #if 0 /* This code can't be made to work, with multiple displays,
3305 and appears not to be used on any system any more.
3306 Also keyboard.c doesn't turn O_NDELAY on and off
3307 for X connections. */
3310 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3312 extern int read_alarm_should_throw
;
3313 read_alarm_should_throw
= 1;
3314 XPeekEvent (dpyinfo
->display
, &event
);
3315 read_alarm_should_throw
= 0;
3317 #endif /* HAVE_SELECT */
3321 /* For debugging, this gives a way to fake an I/O error. */
3322 if (dpyinfo
== XTread_socket_fake_io_error
)
3324 XTread_socket_fake_io_error
= 0;
3325 x_io_error_quitter (dpyinfo
->display
);
3328 while (XPending (dpyinfo
->display
) != 0)
3330 XNextEvent (dpyinfo
->display
, &event
);
3337 if (event
.xclient
.message_type
3338 == dpyinfo
->Xatom_wm_protocols
3339 && event
.xclient
.format
== 32)
3341 if (event
.xclient
.data
.l
[0]
3342 == dpyinfo
->Xatom_wm_take_focus
)
3344 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3345 /* Since we set WM_TAKE_FOCUS, we must call
3346 XSetInputFocus explicitly. But not if f is null,
3347 since that might be an event for a deleted frame. */
3349 /* Not quite sure this is needed -pd */
3351 XSetICFocus (FRAME_XIC (f
));
3354 XSetInputFocus (event
.xclient
.display
,
3355 event
.xclient
.window
,
3356 RevertToPointerRoot
,
3357 event
.xclient
.data
.l
[1]);
3358 /* Not certain about handling scroll bars here */
3360 else if (event
.xclient
.data
.l
[0]
3361 == dpyinfo
->Xatom_wm_save_yourself
)
3363 /* Save state modify the WM_COMMAND property to
3364 something which can reinstate us. This notifies
3365 the session manager, who's looking for such a
3366 PropertyNotify. Can restart processing when
3367 a keyboard or mouse event arrives. */
3370 f
= x_top_window_to_frame (dpyinfo
,
3371 event
.xclient
.window
);
3373 /* This is just so we only give real data once
3374 for a single Emacs process. */
3375 if (f
== selected_frame
)
3376 XSetCommand (FRAME_X_DISPLAY (f
),
3377 event
.xclient
.window
,
3378 initial_argv
, initial_argc
);
3380 XSetCommand (FRAME_X_DISPLAY (f
),
3381 event
.xclient
.window
,
3385 else if (event
.xclient
.data
.l
[0]
3386 == dpyinfo
->Xatom_wm_delete_window
)
3389 = x_any_window_to_frame (dpyinfo
,
3390 event
.xclient
.window
);
3397 bufp
->kind
= delete_window_event
;
3398 XSETFRAME (bufp
->frame_or_window
, f
);
3406 else if (event
.xclient
.message_type
3407 == dpyinfo
->Xatom_wm_configure_denied
)
3410 else if (event
.xclient
.message_type
3411 == dpyinfo
->Xatom_wm_window_moved
)
3415 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3417 new_x
= event
.xclient
.data
.s
[0];
3418 new_y
= event
.xclient
.data
.s
[1];
3422 f
->output_data
.x
->left_pos
= new_x
;
3423 f
->output_data
.x
->top_pos
= new_y
;
3427 else if (event
.xclient
.message_type
3428 == dpyinfo
->Xatom_editres
)
3431 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3432 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3435 #endif /* HACK_EDITRES */
3439 case SelectionNotify
:
3440 #ifdef USE_X_TOOLKIT
3441 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3443 #endif /* not USE_X_TOOLKIT */
3444 x_handle_selection_notify (&event
);
3447 case SelectionClear
: /* Someone has grabbed ownership. */
3448 #ifdef USE_X_TOOLKIT
3449 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3451 #endif /* USE_X_TOOLKIT */
3453 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3458 bufp
->kind
= selection_clear_event
;
3459 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3460 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3461 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3469 case SelectionRequest
: /* Someone wants our selection. */
3470 #ifdef USE_X_TOOLKIT
3471 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3473 #endif /* USE_X_TOOLKIT */
3474 if (x_queue_selection_requests
)
3475 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3479 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3484 bufp
->kind
= selection_request_event
;
3485 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3486 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3487 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3488 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3489 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3490 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3498 case PropertyNotify
:
3499 #ifdef USE_X_TOOLKIT
3500 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3502 #endif /* not USE_X_TOOLKIT */
3503 x_handle_property_notify (&event
);
3506 case ReparentNotify
:
3507 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3511 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
3512 x_real_positions (f
, &x
, &y
);
3513 f
->output_data
.x
->left_pos
= x
;
3514 f
->output_data
.x
->top_pos
= y
;
3519 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3522 if (f
->async_visible
== 0)
3524 f
->async_visible
= 1;
3525 f
->async_iconified
= 0;
3526 SET_FRAME_GARBAGED (f
);
3529 dumprectangle (x_window_to_frame (dpyinfo
,
3530 event
.xexpose
.window
),
3531 event
.xexpose
.x
, event
.xexpose
.y
,
3532 event
.xexpose
.width
, event
.xexpose
.height
);
3536 struct scroll_bar
*bar
3537 = x_window_to_scroll_bar (event
.xexpose
.window
);
3540 x_scroll_bar_expose (bar
, &event
);
3541 #ifdef USE_X_TOOLKIT
3544 #endif /* USE_X_TOOLKIT */
3548 case GraphicsExpose
: /* This occurs when an XCopyArea's
3549 source area was obscured or not
3551 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3555 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3556 event
.xgraphicsexpose
.width
,
3557 event
.xgraphicsexpose
.height
);
3559 #ifdef USE_X_TOOLKIT
3562 #endif /* USE_X_TOOLKIT */
3565 case NoExpose
: /* This occurs when an XCopyArea's
3566 source area was completely
3571 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3572 if (f
) /* F may no longer exist if
3573 the frame was deleted. */
3575 /* While a frame is unmapped, display generation is
3576 disabled; you don't want to spend time updating a
3577 display that won't ever be seen. */
3578 f
->async_visible
= 0;
3579 /* We can't distinguish, from the event, whether the window
3580 has become iconified or invisible. So assume, if it
3581 was previously visible, than now it is iconified.
3582 We depend on x_make_frame_invisible to mark it iconified. */
3583 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3584 f
->async_iconified
= 1;
3586 bufp
->kind
= iconify_event
;
3587 XSETFRAME (bufp
->frame_or_window
, f
);
3592 #ifdef USE_X_TOOLKIT
3594 #endif /* USE_X_TOOLKIT */
3598 /* We use x_top_window_to_frame because map events can come
3599 for subwindows and they don't mean that the frame is visible. */
3600 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
3603 f
->async_visible
= 1;
3604 f
->async_iconified
= 0;
3606 /* wait_reading_process_input will notice this and update
3607 the frame's display structures. */
3608 SET_FRAME_GARBAGED (f
);
3612 bufp
->kind
= deiconify_event
;
3613 XSETFRAME (bufp
->frame_or_window
, f
);
3619 /* Force a redisplay sooner or later
3620 to update the frame titles
3621 in case this is the second frame. */
3622 record_asynch_buffer_change ();
3624 #ifdef USE_X_TOOLKIT
3626 #endif /* USE_X_TOOLKIT */
3629 /* Turn off processing if we become fully obscured. */
3630 case VisibilityNotify
:
3634 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
3638 KeySym keysym
, orig_keysym
;
3639 /* al%imercury@uunet.uu.net says that making this 81 instead of
3640 80 fixed a bug whereby meta chars made his Emacs hang. */
3641 unsigned char copy_buffer
[81];
3645 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3646 extra_keyboard_modifiers
);
3647 modifiers
= event
.xkey
.state
;
3649 /* This will have to go some day... */
3651 /* make_lispy_event turns chars into control chars.
3652 Don't do it here because XLookupString is too eager. */
3653 event
.xkey
.state
&= ~ControlMask
;
3654 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
3655 | dpyinfo
->super_mod_mask
3656 | dpyinfo
->hyper_mod_mask
3657 | dpyinfo
->alt_mod_mask
);
3662 /* The necessity of the following line took me
3663 a full work-day to decipher from the docs!! */
3664 if (XFilterEvent (&event
, None
))
3666 nbytes
= XmbLookupString (FRAME_XIC (f
),
3667 &event
.xkey
, copy_buffer
,
3672 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3673 80, &keysym
, &compose_status
);
3675 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3676 80, &keysym
, &compose_status
);
3679 orig_keysym
= keysym
;
3683 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3684 || keysym
== XK_Delete
3685 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3686 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3688 /* This recognizes the "extended function keys".
3689 It seems there's no cleaner way.
3690 Test IsModifierKey to avoid handling mode_switch
3692 || ((unsigned) (keysym
) >= XK_Select
3693 && (unsigned)(keysym
) < XK_KP_Space
)
3695 #ifdef XK_dead_circumflex
3696 || orig_keysym
== XK_dead_circumflex
3698 #ifdef XK_dead_grave
3699 || orig_keysym
== XK_dead_grave
3701 #ifdef XK_dead_tilde
3702 || orig_keysym
== XK_dead_tilde
3704 #ifdef XK_dead_diaeresis
3705 || orig_keysym
== XK_dead_diaeresis
3707 #ifdef XK_dead_macron
3708 || orig_keysym
== XK_dead_macron
3710 #ifdef XK_dead_degree
3711 || orig_keysym
== XK_dead_degree
3713 #ifdef XK_dead_acute
3714 || orig_keysym
== XK_dead_acute
3716 #ifdef XK_dead_cedilla
3717 || orig_keysym
== XK_dead_cedilla
3719 #ifdef XK_dead_breve
3720 || orig_keysym
== XK_dead_breve
3722 #ifdef XK_dead_ogonek
3723 || orig_keysym
== XK_dead_ogonek
3725 #ifdef XK_dead_caron
3726 || orig_keysym
== XK_dead_caron
3728 #ifdef XK_dead_doubleacute
3729 || orig_keysym
== XK_dead_doubleacute
3731 #ifdef XK_dead_abovedot
3732 || orig_keysym
== XK_dead_abovedot
3734 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3735 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3736 /* Any "vendor-specific" key is ok. */
3737 || (orig_keysym
& (1 << 28)))
3738 && ! (IsModifierKey (orig_keysym
)
3740 #ifdef XK_Mode_switch
3741 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3744 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3746 #endif /* not HAVE_X11R5 */
3749 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3751 temp_buffer
[temp_index
++] = keysym
;
3752 bufp
->kind
= non_ascii_keystroke
;
3753 bufp
->code
= keysym
;
3754 XSETFRAME (bufp
->frame_or_window
, f
);
3756 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3758 bufp
->timestamp
= event
.xkey
.time
;
3763 else if (numchars
> nbytes
)
3767 for (i
= 0; i
< nbytes
; i
++)
3769 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3771 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3772 bufp
->kind
= ascii_keystroke
;
3773 bufp
->code
= copy_buffer
[i
];
3774 XSETFRAME (bufp
->frame_or_window
, f
);
3776 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3778 bufp
->timestamp
= event
.xkey
.time
;
3793 /* Here's a possible interpretation of the whole
3794 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3795 FocusIn event, you have to get a FocusOut event before you
3796 relinquish the focus. If you haven't received a FocusIn event,
3797 then a mere LeaveNotify is enough to free you. */
3800 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3802 if (event
.xcrossing
.focus
) /* Entered Window */
3804 /* Avoid nasty pop/raise loops. */
3805 if (f
&& (!(f
->auto_raise
)
3807 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3809 x_new_focus_frame (dpyinfo
, f
);
3810 enter_timestamp
= event
.xcrossing
.time
;
3813 else if (f
== dpyinfo
->x_focus_frame
)
3814 x_new_focus_frame (dpyinfo
, 0);
3815 /* EnterNotify counts as mouse movement,
3816 so update things that depend on mouse position. */
3818 note_mouse_movement (f
, &event
.xmotion
);
3819 #ifdef USE_X_TOOLKIT
3821 #endif /* USE_X_TOOLKIT */
3825 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3826 if (event
.xfocus
.detail
!= NotifyPointer
)
3827 dpyinfo
->x_focus_event_frame
= f
;
3829 x_new_focus_frame (dpyinfo
, f
);
3832 if (f
&& FRAME_XIC (f
))
3833 XSetICFocus (FRAME_XIC (f
));
3836 #ifdef USE_X_TOOLKIT
3838 #endif /* USE_X_TOOLKIT */
3843 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3846 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3847 /* If we move outside the frame,
3848 then we're certainly no longer on any text in the frame. */
3849 clear_mouse_face (dpyinfo
);
3851 if (event
.xcrossing
.focus
)
3852 x_mouse_leave (dpyinfo
);
3855 if (f
== dpyinfo
->x_focus_event_frame
)
3856 dpyinfo
->x_focus_event_frame
= 0;
3857 if (f
== dpyinfo
->x_focus_frame
)
3858 x_new_focus_frame (dpyinfo
, 0);
3861 #ifdef USE_X_TOOLKIT
3863 #endif /* USE_X_TOOLKIT */
3867 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3868 if (event
.xfocus
.detail
!= NotifyPointer
3869 && f
== dpyinfo
->x_focus_event_frame
)
3870 dpyinfo
->x_focus_event_frame
= 0;
3871 if (f
&& f
== dpyinfo
->x_focus_frame
)
3872 x_new_focus_frame (dpyinfo
, 0);
3875 if (f
&& FRAME_XIC (f
))
3876 XUnsetICFocus (FRAME_XIC (f
));
3879 #ifdef USE_X_TOOLKIT
3881 #endif /* USE_X_TOOLKIT */
3886 if (dpyinfo
->grabbed
&& last_mouse_frame
3887 && FRAME_LIVE_P (last_mouse_frame
))
3888 f
= last_mouse_frame
;
3890 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3892 note_mouse_movement (f
, &event
.xmotion
);
3895 struct scroll_bar
*bar
3896 = x_window_to_scroll_bar (event
.xmotion
.window
);
3899 x_scroll_bar_note_movement (bar
, &event
);
3901 /* If we move outside the frame,
3902 then we're certainly no longer on any text in the frame. */
3903 clear_mouse_face (dpyinfo
);
3906 #ifdef USE_X_TOOLKIT
3908 #endif /* USE_X_TOOLKIT */
3911 case ConfigureNotify
:
3912 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
3914 #ifdef USE_X_TOOLKIT
3915 && (event
.xconfigure
.window
== XtWindow (f
->output_data
.x
->widget
))
3919 #ifndef USE_X_TOOLKIT
3920 /* In the toolkit version, change_frame_size
3921 is called by the code that handles resizing
3922 of the EmacsFrame widget. */
3924 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3925 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3927 /* Even if the number of character rows and columns has
3928 not changed, the font size may have changed, so we need
3929 to check the pixel dimensions as well. */
3930 if (columns
!= f
->width
3931 || rows
!= f
->height
3932 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
3933 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
3935 change_frame_size (f
, rows
, columns
, 0, 1);
3936 SET_FRAME_GARBAGED (f
);
3940 /* Formerly, in the USE_X_TOOLKIT version,
3941 we did not test send_event here. */
3943 #ifndef USE_X_TOOLKIT
3944 && ! event
.xconfigure
.send_event
3951 /* Find the position of the outside upper-left corner of
3952 the window, in the root coordinate system. Don't
3953 refer to the parent window here; we may be processing
3954 this event after the window manager has changed our
3955 parent, but before we have reached the ReparentNotify. */
3956 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3958 /* From-window, to-window. */
3959 event
.xconfigure
.window
,
3960 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3962 /* From-position, to-position. */
3963 -event
.xconfigure
.border_width
,
3964 -event
.xconfigure
.border_width
,
3969 event
.xconfigure
.x
= win_x
;
3970 event
.xconfigure
.y
= win_y
;
3973 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
3974 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
3975 f
->output_data
.x
->left_pos
= event
.xconfigure
.x
;
3976 f
->output_data
.x
->top_pos
= event
.xconfigure
.y
;
3978 /* What we have now is the position of Emacs's own window.
3979 Convert that to the position of the window manager window. */
3982 x_real_positions (f
, &x
, &y
);
3983 f
->output_data
.x
->left_pos
= x
;
3984 f
->output_data
.x
->top_pos
= y
;
3985 /* Formerly we did not do this in the USE_X_TOOLKIT
3986 version. Let's try making them the same. */
3987 /* #ifndef USE_X_TOOLKIT */
3988 if (y
!= event
.xconfigure
.y
)
3990 /* Since the WM decorations come below top_pos now,
3991 we must put them below top_pos in the future. */
3992 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3993 x_wm_set_size_hint (f
, (long) 0, 0);
3998 #ifdef USE_X_TOOLKIT
4007 /* If we decide we want to generate an event to be seen
4008 by the rest of Emacs, we put it here. */
4009 struct input_event emacs_event
;
4010 emacs_event
.kind
= no_event
;
4012 bzero (&compose_status
, sizeof (compose_status
));
4014 if (dpyinfo
->grabbed
&& last_mouse_frame
4015 && FRAME_LIVE_P (last_mouse_frame
))
4016 f
= last_mouse_frame
;
4018 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4022 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4023 construct_mouse_click (&emacs_event
, &event
, f
);
4027 struct scroll_bar
*bar
4028 = x_window_to_scroll_bar (event
.xbutton
.window
);
4031 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4034 if (event
.type
== ButtonPress
)
4036 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4037 last_mouse_frame
= f
;
4041 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4044 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4046 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4052 #ifdef USE_X_TOOLKIT
4053 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4054 /* For a down-event in the menu bar,
4055 don't pass it to Xt right now.
4056 Instead, save it away
4057 and we will pass it to Xt from kbd_buffer_get_event.
4058 That way, we can run some Lisp code first. */
4059 if (f
&& event
.type
== ButtonPress
4060 /* Verify the event is really within the menu bar
4061 and not just sent to it due to grabbing. */
4062 && event
.xbutton
.x
>= 0
4063 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4064 && event
.xbutton
.y
>= 0
4065 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4066 && event
.xbutton
.same_screen
)
4068 if (f
->output_data
.x
->saved_button_event
== 0)
4069 f
->output_data
.x
->saved_button_event
4070 = (XButtonEvent
*) xmalloc (sizeof (XButtonEvent
));
4071 bcopy (&event
, f
->output_data
.x
->saved_button_event
,
4072 sizeof (XButtonEvent
));
4075 bufp
->kind
= menu_bar_activate_event
;
4076 XSETFRAME (bufp
->frame_or_window
, f
);
4084 #endif /* USE_X_TOOLKIT */
4088 case CirculateNotify
:
4090 case CirculateRequest
:
4094 /* Someone has changed the keyboard mapping - update the
4096 switch (event
.xmapping
.request
)
4098 case MappingModifier
:
4099 x_find_modifier_meanings (dpyinfo
);
4100 /* This is meant to fall through. */
4101 case MappingKeyboard
:
4102 XRefreshKeyboardMapping (&event
.xmapping
);
4104 #ifdef USE_X_TOOLKIT
4106 #endif /* USE_X_TOOLKIT */
4110 #ifdef USE_X_TOOLKIT
4113 XtDispatchEvent (&event
);
4115 #endif /* USE_X_TOOLKIT */
4121 /* On some systems, an X bug causes Emacs to get no more events
4122 when the window is destroyed. Detect that. (1994.) */
4125 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4126 One XNOOP in 100 loops will make Emacs terminate.
4127 B. Bretthauer, 1994 */
4129 if (x_noop_count
>= 100)
4133 if (next_noop_dpyinfo
== 0)
4134 next_noop_dpyinfo
= x_display_list
;
4136 XNoOp (next_noop_dpyinfo
->display
);
4138 /* Each time we get here, cycle through the displays now open. */
4139 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4143 /* If the focus was just given to an autoraising frame,
4145 /* ??? This ought to be able to handle more than one such frame. */
4146 if (pending_autoraise_frame
)
4148 x_raise_frame (pending_autoraise_frame
);
4149 pending_autoraise_frame
= 0;
4156 /* Drawing the cursor. */
4159 /* Draw a hollow box cursor on frame F at X, Y.
4160 Don't change the inside of the box. */
4163 x_draw_box (f
, x
, y
)
4167 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4168 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4169 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4170 int height
= f
->output_data
.x
->line_height
;
4172 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4173 f
->output_data
.x
->cursor_gc
,
4174 left
, top
, width
- 1, height
- 1);
4177 /* Clear the cursor of frame F to background color,
4178 and mark the cursor as not shown.
4179 This is used when the text where the cursor is
4180 is about to be rewritten. */
4188 if (! FRAME_VISIBLE_P (f
)
4189 || f
->phys_cursor_x
< 0)
4192 x_display_cursor (f
, 0);
4193 f
->phys_cursor_x
= -1;
4196 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4197 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4201 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4208 CHAR_TO_PIXEL_COL (f
, column
),
4209 CHAR_TO_PIXEL_ROW (f
, row
),
4210 &glyph
, 1, highlight
, 0);
4214 x_display_bar_cursor (f
, on
, x
, y
)
4219 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4221 /* This is pointless on invisible frames, and dangerous on garbaged
4222 frames; in the latter case, the frame may be in the midst of
4223 changing its size, and x and y may be off the frame. */
4224 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4227 if (! on
&& f
->phys_cursor_x
< 0)
4230 /* If there is anything wrong with the current cursor state, remove it. */
4231 if (f
->phys_cursor_x
>= 0
4233 || f
->phys_cursor_x
!= x
4234 || f
->phys_cursor_y
!= y
4235 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4237 /* Erase the cursor by redrawing the character underneath it. */
4238 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4239 f
->phys_cursor_glyph
,
4240 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4241 f
->phys_cursor_x
= -1;
4244 /* If we now need a cursor in the new place or in the new form, do it so. */
4246 && (f
->phys_cursor_x
< 0
4247 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4249 f
->phys_cursor_glyph
4250 = ((current_glyphs
->enable
[y
]
4251 && x
< current_glyphs
->used
[y
])
4252 ? current_glyphs
->glyphs
[y
][x
]
4254 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4255 f
->output_data
.x
->cursor_gc
,
4256 CHAR_TO_PIXEL_COL (f
, x
),
4257 CHAR_TO_PIXEL_ROW (f
, y
),
4258 max (f
->output_data
.x
->cursor_width
, 1),
4259 f
->output_data
.x
->line_height
);
4261 f
->phys_cursor_x
= x
;
4262 f
->phys_cursor_y
= y
;
4264 f
->output_data
.x
->current_cursor
= bar_cursor
;
4267 if (updating_frame
!= f
)
4268 XFlush (FRAME_X_DISPLAY (f
));
4272 /* Turn the displayed cursor of frame F on or off according to ON.
4273 If ON is nonzero, where to put the cursor is specified by X and Y. */
4276 x_display_box_cursor (f
, on
, x
, y
)
4281 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4283 /* This is pointless on invisible frames, and dangerous on garbaged
4284 frames; in the latter case, the frame may be in the midst of
4285 changing its size, and x and y may be off the frame. */
4286 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4289 /* If cursor is off and we want it off, return quickly. */
4290 if (!on
&& f
->phys_cursor_x
< 0)
4293 /* If cursor is currently being shown and we don't want it to be
4294 or it is in the wrong place,
4295 or we want a hollow box and it's not so, (pout!)
4297 if (f
->phys_cursor_x
>= 0
4299 || f
->phys_cursor_x
!= x
4300 || f
->phys_cursor_y
!= y
4301 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4302 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4304 int mouse_face_here
= 0;
4305 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4307 /* If the cursor is in the mouse face area, redisplay that when
4308 we clear the cursor. */
4309 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4311 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4312 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4313 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4315 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4316 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4317 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4318 /* Don't redraw the cursor's spot in mouse face
4319 if it is at the end of a line (on a newline).
4320 The cursor appears there, but mouse highlighting does not. */
4321 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4322 mouse_face_here
= 1;
4324 /* If the font is not as tall as a whole line,
4325 we must explicitly clear the line's whole height. */
4326 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4327 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4328 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4329 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4330 FONT_WIDTH (f
->output_data
.x
->font
),
4331 f
->output_data
.x
->line_height
, False
);
4332 /* Erase the cursor by redrawing the character underneath it. */
4333 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4334 f
->phys_cursor_glyph
,
4337 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4338 f
->phys_cursor_x
= -1;
4341 /* If we want to show a cursor,
4342 or we want a box cursor and it's not so,
4343 write it in the right place. */
4345 && (f
->phys_cursor_x
< 0
4346 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4347 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4349 f
->phys_cursor_glyph
4350 = ((current_glyphs
->enable
[y
]
4351 && x
< current_glyphs
->used
[y
])
4352 ? current_glyphs
->glyphs
[y
][x
]
4354 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4356 x_draw_box (f
, x
, y
);
4357 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4361 x_draw_single_glyph (f
, y
, x
,
4362 f
->phys_cursor_glyph
, 2);
4363 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4366 f
->phys_cursor_x
= x
;
4367 f
->phys_cursor_y
= y
;
4370 if (updating_frame
!= f
)
4371 XFlush (FRAME_X_DISPLAY (f
));
4374 /* Display the cursor on frame F, or clear it, according to ON.
4375 Use the position specified by curs_x and curs_y
4376 if we are doing an update of frame F now.
4377 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4380 x_display_cursor (f
, on
)
4386 /* If we're not updating, then don't change the physical cursor
4387 position. Just change (if appropriate) the style of display. */
4388 if (f
!= updating_frame
)
4390 curs_x
= FRAME_CURSOR_X (f
);
4391 curs_y
= FRAME_CURSOR_Y (f
);
4394 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4395 x_display_box_cursor (f
, on
, curs_x
, curs_y
);
4396 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4397 x_display_bar_cursor (f
, on
, curs_x
, curs_y
);
4399 /* Those are the only two we have implemented! */
4405 /* Display the cursor on frame F, or clear it, according to ON.
4406 Don't change the cursor's position. */
4408 x_update_cursor (f
, on
)
4414 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4415 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4416 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4417 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4419 /* Those are the only two we have implemented! */
4427 /* Refresh bitmap kitchen sink icon for frame F
4428 when we get an expose event for it. */
4433 /* Normally, the window manager handles this function. */
4436 /* Make the x-window of frame F use the gnu icon bitmap. */
4439 x_bitmap_icon (f
, file
)
4443 int mask
, bitmap_id
;
4446 if (FRAME_X_WINDOW (f
) == 0)
4449 /* Free up our existing icon bitmap if any. */
4450 if (f
->output_data
.x
->icon_bitmap
> 0)
4451 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4452 f
->output_data
.x
->icon_bitmap
= 0;
4455 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4458 /* Create the GNU bitmap if necessary. */
4459 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4460 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4461 = x_create_bitmap_from_data (f
, gnu_bits
,
4462 gnu_width
, gnu_height
);
4464 /* The first time we create the GNU bitmap,
4465 this increments the refcount one extra time.
4466 As a result, the GNU bitmap is never freed.
4467 That way, we don't have to worry about allocating it again. */
4468 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4470 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4473 x_wm_set_icon_pixmap (f
, bitmap_id
);
4474 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4480 /* Make the x-window of frame F use a rectangle with text.
4481 Use ICON_NAME as the text. */
4484 x_text_icon (f
, icon_name
)
4488 if (FRAME_X_WINDOW (f
) == 0)
4494 text
.value
= (unsigned char *) icon_name
;
4495 text
.encoding
= XA_STRING
;
4497 text
.nitems
= strlen (icon_name
);
4498 #ifdef USE_X_TOOLKIT
4499 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4501 #else /* not USE_X_TOOLKIT */
4502 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
4503 #endif /* not USE_X_TOOLKIT */
4505 #else /* not HAVE_X11R4 */
4506 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
4507 #endif /* not HAVE_X11R4 */
4509 if (f
->output_data
.x
->icon_bitmap
> 0)
4510 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4511 f
->output_data
.x
->icon_bitmap
= 0;
4512 x_wm_set_icon_pixmap (f
, 0);
4517 /* Handling X errors. */
4519 /* Handle the loss of connection to display DISPLAY. */
4522 x_connection_closed (display
, error_message
)
4524 char *error_message
;
4526 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4527 Lisp_Object frame
, tail
;
4529 /* Whatever we were in the middle of, we are going to throw out of it,
4530 so reassure various things that have error checks about being
4531 called with input blocked. */
4532 TOTALLY_UNBLOCK_INPUT
;
4537 /* First delete frames whose minibuffers are on frames
4538 that are on the dead display. */
4539 FOR_EACH_FRAME (tail
, frame
)
4541 Lisp_Object minibuf_frame
;
4543 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4544 if (FRAME_X_P (XFRAME (frame
))
4545 && FRAME_X_P (XFRAME (minibuf_frame
))
4546 && ! EQ (frame
, minibuf_frame
)
4547 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4548 Fdelete_frame (frame
, Qt
);
4551 /* Now delete all remaining frames on the dead display.
4552 We are now sure none of these is used as the minibuffer
4553 for another frame that we need to delete. */
4554 FOR_EACH_FRAME (tail
, frame
)
4555 if (FRAME_X_P (XFRAME (frame
))
4556 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4558 /* Set this to t so that Fdelete_frame won't get confused
4559 trying to find a replacement. */
4560 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
4561 Fdelete_frame (frame
, Qt
);
4564 x_delete_display (dpyinfo
);
4566 if (x_display_list
== 0)
4568 fprintf (stderr
, "%s", error_message
);
4569 shut_down_emacs (0, 0, Qnil
);
4573 /* Ordinary stack unwind doesn't deal with these. */
4575 sigunblock (sigmask (SIGIO
));
4577 sigunblock (sigmask (SIGALRM
));
4578 TOTALLY_UNBLOCK_INPUT
;
4580 error ("%s", error_message
);
4583 /* This is the usual handler for X protocol errors.
4584 It kills all frames on the display that we got the error for.
4585 If that was the only one, it prints an error message and kills Emacs. */
4588 x_error_quitter (display
, error
)
4592 char buf
[256], buf1
[356];
4594 /* Note that there is no real way portable across R3/R4 to get the
4595 original error handler. */
4597 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4598 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4599 buf
, error
->request_code
);
4600 x_connection_closed (display
, buf1
);
4603 /* This is the handler for X IO errors, always.
4604 It kills all frames on the display that we lost touch with.
4605 If that was the only one, it prints an error message and kills Emacs. */
4608 x_io_error_quitter (display
)
4613 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4614 x_connection_closed (display
, buf
);
4617 /* Handle SIGPIPE, which can happen when the connection to a server
4618 simply goes away. SIGPIPE is handled by x_connection_signal.
4619 It works by sending a no-op command to each X server connection.
4620 When we try a connection that has closed, we get SIGPIPE again.
4621 But this time, it is handled by x_connection_signal_1.
4622 That function knows which connection we were testing,
4623 so it closes that one.
4625 x_connection_closed never returns,
4626 so if more than one connection was lost at once,
4627 we only find one. But XTread_socket keeps trying them all,
4628 so it will notice the other closed one sooner or later. */
4631 static struct x_display_info
*x_connection_signal_dpyinfo
;
4633 static SIGTYPE
x_connection_signal ();
4636 x_connection_signal_1 (signalnum
) /* If we don't have an argument, */
4637 int signalnum
; /* some compilers complain in signal calls. */
4639 signal (SIGPIPE
, x_connection_signal
);
4640 x_connection_closed (x_connection_signal_dpyinfo
,
4641 "connection was lost");
4645 x_connection_signal (signalnum
) /* If we don't have an argument, */
4646 int signalnum
; /* some compilers complain in signal calls. */
4648 x_connection_signal_dpyinfo
= x_display_list
;
4650 sigunblock (SIGPIPE
);
4652 while (x_connection_signal_dpyinfo
)
4654 signal (SIGPIPE
, x_connection_signal_1
);
4656 XNoOp (x_connection_signal_dpyinfo
->display
);
4657 XSync (x_connection_signal_dpyinfo
->display
, False
);
4659 /* Each time we get here, cycle through the displays now open. */
4660 x_connection_signal_dpyinfo
= x_connection_signal_dpyinfo
->next
;
4663 /* We should have found some closed connection. */
4667 /* A buffer for storing X error messages. */
4668 static char *x_caught_error_message
;
4669 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4671 /* An X error handler which stores the error message in
4672 x_caught_error_message. This is what's installed when
4673 x_catch_errors is in effect. */
4676 x_error_catcher (display
, error
)
4680 XGetErrorText (display
, error
->error_code
,
4681 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4685 /* Begin trapping X errors for display DPY. Actually we trap X errors
4686 for all displays, but DPY should be the display you are actually
4689 After calling this function, X protocol errors no longer cause
4690 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4692 Calling x_check_errors signals an Emacs error if an X error has
4693 occurred since the last call to x_catch_errors or x_check_errors.
4695 Calling x_uncatch_errors resumes the normal error handling. */
4697 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4700 x_catch_errors (dpy
)
4703 /* Make sure any errors from previous requests have been dealt with. */
4706 /* Set up the error buffer. */
4707 x_caught_error_message
4708 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4709 x_caught_error_message
[0] = '\0';
4711 /* Install our little error handler. */
4712 XSetErrorHandler (x_error_catcher
);
4715 /* If any X protocol errors have arrived since the last call to
4716 x_catch_errors or x_check_errors, signal an Emacs error using
4717 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4720 x_check_errors (dpy
, format
)
4724 /* Make sure to catch any errors incurred so far. */
4727 if (x_caught_error_message
[0])
4729 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4731 sprintf (buf
, format
, x_caught_error_message
);
4732 x_uncatch_errors (dpy
);
4737 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4740 x_had_errors_p (dpy
)
4743 /* Make sure to catch any errors incurred so far. */
4746 return x_caught_error_message
[0] != 0;
4749 /* Stop catching X protocol errors and let them make Emacs die. */
4752 x_uncatch_errors (dpy
)
4755 xfree (x_caught_error_message
);
4756 x_caught_error_message
= 0;
4757 XSetErrorHandler (x_error_quitter
);
4761 static unsigned int x_wire_count
;
4764 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4769 /* Changing the font of the frame. */
4771 /* Give frame F the font named FONTNAME as its default font, and
4772 return the full name of that font. FONTNAME may be a wildcard
4773 pattern; in that case, we choose some font that fits the pattern.
4774 The return value shows which font we chose. */
4777 x_new_font (f
, fontname
)
4779 register char *fontname
;
4782 int n_matching_fonts
;
4783 XFontStruct
*font_info
;
4786 /* Get a list of all the fonts that match this name. Once we
4787 have a list of matching fonts, we compare them against the fonts
4788 we already have by comparing font ids. */
4789 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4790 1024, &n_matching_fonts
);
4791 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4792 find any matches; font_names == 0 is the only clue. */
4794 n_matching_fonts
= 0;
4796 /* Don't just give up if n_matching_fonts is 0.
4797 Apparently there's a bug on Suns: XListFontsWithInfo can
4798 fail to find a font, but XLoadQueryFont may still find it. */
4800 /* See if we've already loaded a matching font. */
4801 already_loaded
= -1;
4802 if (n_matching_fonts
!= 0)
4806 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4807 for (j
= 0; j
< n_matching_fonts
; j
++)
4808 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4809 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4812 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4818 /* If we have, just return it from the table. */
4819 if (already_loaded
>= 0)
4820 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4821 /* Otherwise, load the font and add it to the table. */
4829 /* Try to find a character-cell font in the list. */
4831 /* A laudable goal, but this isn't how to do it. */
4832 for (i
= 0; i
< n_matching_fonts
; i
++)
4833 if (! font_info
[i
].per_char
)
4839 /* See comment above. */
4840 if (n_matching_fonts
!= 0)
4841 fontname
= font_names
[i
];
4843 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4846 /* Free the information from XListFonts. */
4847 if (n_matching_fonts
)
4848 XFreeFontNames (font_names
);
4852 /* Do we need to create the table? */
4853 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4855 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4856 FRAME_X_DISPLAY_INFO (f
)->font_table
4857 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4858 * sizeof (struct font_info
));
4860 /* Do we need to grow the table? */
4861 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4862 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4864 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4865 FRAME_X_DISPLAY_INFO (f
)->font_table
4866 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4867 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4868 * sizeof (struct font_info
)));
4871 /* Try to get the full name of FONT. Put it in full_name. */
4873 for (i
= 0; i
< font
->n_properties
; i
++)
4876 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4877 if (!strcmp (atom
, "FONT"))
4879 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4880 (Atom
) (font
->properties
[i
].card32
));
4884 /* Count the number of dashes in the "full name".
4885 If it is too few, this isn't really the font's full name,
4887 In X11R4, the fonts did not come with their canonical names
4905 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4906 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4907 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4909 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4911 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4912 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4913 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4916 fontname
= full_name
;
4919 /* Compute the scroll bar width in character columns. */
4920 if (f
->scroll_bar_pixel_width
> 0)
4922 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
4923 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4926 f
->scroll_bar_cols
= 2;
4928 /* Now make the frame display the given font. */
4929 if (FRAME_X_WINDOW (f
) != 0)
4931 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
4932 f
->output_data
.x
->font
->fid
);
4933 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
4934 f
->output_data
.x
->font
->fid
);
4935 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
4936 f
->output_data
.x
->font
->fid
);
4938 frame_update_line_height (f
);
4939 x_set_window_size (f
, 0, f
->width
, f
->height
);
4942 /* If we are setting a new frame's font for the first time,
4943 there are no faces yet, so this font's height is the line height. */
4944 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
4947 Lisp_Object lispy_name
;
4949 lispy_name
= build_string (fontname
);
4951 /* Free the information from XListFonts. The data
4952 we actually retain comes from XLoadQueryFont. */
4953 XFreeFontNames (font_names
);
4959 x_calc_absolute_position (f
)
4963 int win_x
= 0, win_y
= 0;
4964 int flags
= f
->output_data
.x
->size_hint_flags
;
4967 #ifdef USE_X_TOOLKIT
4968 this_window
= XtWindow (f
->output_data
.x
->widget
);
4970 this_window
= FRAME_X_WINDOW (f
);
4973 /* Find the position of the outside upper-left corner of
4974 the inner window, with respect to the outer window. */
4975 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4978 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4980 /* From-window, to-window. */
4982 f
->output_data
.x
->parent_desc
,
4984 /* From-position, to-position. */
4985 0, 0, &win_x
, &win_y
,
4992 /* Treat negative positions as relative to the leftmost bottommost
4993 position that fits on the screen. */
4994 if (flags
& XNegative
)
4995 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4996 - 2 * f
->output_data
.x
->border_width
- win_x
4998 + f
->output_data
.x
->left_pos
);
5000 if (flags
& YNegative
)
5001 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
5002 - 2 * f
->output_data
.x
->border_width
- win_y
5004 - (FRAME_EXTERNAL_MENU_BAR (f
)
5005 ? f
->output_data
.x
->menubar_height
: 0)
5006 + f
->output_data
.x
->top_pos
);
5007 /* The left_pos and top_pos
5008 are now relative to the top and left screen edges,
5009 so the flags should correspond. */
5010 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5013 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5014 to really change the position, and 0 when calling from
5015 x_make_frame_visible (in that case, XOFF and YOFF are the current
5016 position values). It is -1 when calling from x_set_frame_parameters,
5017 which means, do adjust for borders but don't change the gravity. */
5019 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5021 register int xoff
, yoff
;
5024 int modified_top
, modified_left
;
5026 if (change_gravity
> 0)
5028 f
->output_data
.x
->top_pos
= yoff
;
5029 f
->output_data
.x
->left_pos
= xoff
;
5030 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5032 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5034 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5035 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5037 x_calc_absolute_position (f
);
5040 x_wm_set_size_hint (f
, (long) 0, 0);
5042 /* It is a mystery why we need to add the border_width here
5043 when the frame is already visible, but experiment says we do. */
5044 modified_left
= f
->output_data
.x
->left_pos
;
5045 modified_top
= f
->output_data
.x
->top_pos
;
5046 if (change_gravity
!= 0)
5048 modified_left
+= f
->output_data
.x
->border_width
;
5049 modified_top
+= f
->output_data
.x
->border_width
;
5052 #ifdef USE_X_TOOLKIT
5053 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5054 modified_left
, modified_top
);
5055 #else /* not USE_X_TOOLKIT */
5056 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5057 modified_left
, modified_top
);
5058 #endif /* not USE_X_TOOLKIT */
5062 /* Call this to change the size of frame F's x-window.
5063 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5064 for this size change and subsequent size changes.
5065 Otherwise we leave the window gravity unchanged. */
5067 x_set_window_size (f
, change_gravity
, cols
, rows
)
5072 int pixelwidth
, pixelheight
;
5075 #ifdef USE_X_TOOLKIT
5078 /* The x and y position of the widget is clobbered by the
5079 call to XtSetValues within EmacsFrameSetCharSize.
5080 This is a real kludge, but I don't understand Xt so I can't
5081 figure out a correct fix. Can anyone else tell me? -- rms. */
5082 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5083 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5084 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5085 f
->output_data
.x
->widget
->core
.x
= xpos
;
5086 f
->output_data
.x
->widget
->core
.y
= ypos
;
5090 #else /* not USE_X_TOOLKIT */
5094 check_frame_size (f
, &rows
, &cols
);
5095 f
->output_data
.x
->vertical_scroll_bar_extra
5096 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5098 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5099 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5100 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5101 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5102 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5104 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5105 x_wm_set_size_hint (f
, (long) 0, 0);
5107 XSync (FRAME_X_DISPLAY (f
), False
);
5108 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5109 pixelwidth
, pixelheight
);
5111 /* Now, strictly speaking, we can't be sure that this is accurate,
5112 but the window manager will get around to dealing with the size
5113 change request eventually, and we'll hear how it went when the
5114 ConfigureNotify event gets here.
5116 We could just not bother storing any of this information here,
5117 and let the ConfigureNotify event set everything up, but that
5118 might be kind of confusing to the lisp code, since size changes
5119 wouldn't be reported in the frame parameters until some random
5120 point in the future when the ConfigureNotify event arrives. */
5121 change_frame_size (f
, rows
, cols
, 0, 0);
5122 PIXEL_WIDTH (f
) = pixelwidth
;
5123 PIXEL_HEIGHT (f
) = pixelheight
;
5125 /* If cursor was outside the new size, mark it as off. */
5126 if (f
->phys_cursor_y
>= rows
5127 || f
->phys_cursor_x
>= cols
)
5129 f
->phys_cursor_x
= -1;
5130 f
->phys_cursor_y
= -1;
5133 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5134 receive in the ConfigureNotify event; if we get what we asked
5135 for, then the event won't cause the screen to become garbaged, so
5136 we have to make sure to do it here. */
5137 SET_FRAME_GARBAGED (f
);
5139 XFlush (FRAME_X_DISPLAY (f
));
5141 #endif /* not USE_X_TOOLKIT */
5144 /* Mouse warping. */
5147 x_set_mouse_position (f
, x
, y
)
5153 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5154 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5156 if (pix_x
< 0) pix_x
= 0;
5157 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5159 if (pix_y
< 0) pix_y
= 0;
5160 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5164 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5165 0, 0, 0, 0, pix_x
, pix_y
);
5169 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5172 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5178 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5179 0, 0, 0, 0, pix_x
, pix_y
);
5183 /* focus shifting, raising and lowering. */
5185 x_focus_on_frame (f
)
5188 #if 0 /* This proves to be unpleasant. */
5192 /* I don't think that the ICCCM allows programs to do things like this
5193 without the interaction of the window manager. Whatever you end up
5194 doing with this code, do it to x_unfocus_frame too. */
5195 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5196 RevertToPointerRoot
, CurrentTime
);
5204 /* Look at the remarks in x_focus_on_frame. */
5205 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5206 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5207 RevertToPointerRoot
, CurrentTime
);
5211 /* Raise frame F. */
5216 if (f
->async_visible
)
5219 #ifdef USE_X_TOOLKIT
5220 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5221 #else /* not USE_X_TOOLKIT */
5222 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5223 #endif /* not USE_X_TOOLKIT */
5224 XFlush (FRAME_X_DISPLAY (f
));
5229 /* Lower frame F. */
5234 if (f
->async_visible
)
5237 #ifdef USE_X_TOOLKIT
5238 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5239 #else /* not USE_X_TOOLKIT */
5240 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5241 #endif /* not USE_X_TOOLKIT */
5242 XFlush (FRAME_X_DISPLAY (f
));
5248 XTframe_raise_lower (f
, raise
)
5258 /* Change of visibility. */
5260 /* This tries to wait until the frame is really visible.
5261 However, if the window manager asks the user where to position
5262 the frame, this will return before the user finishes doing that.
5263 The frame will not actually be visible at that time,
5264 but it will become visible later when the window manager
5265 finishes with it. */
5267 x_make_frame_visible (f
)
5275 type
= x_icon_type (f
);
5277 x_bitmap_icon (f
, type
);
5279 if (! FRAME_VISIBLE_P (f
))
5281 /* We test FRAME_GARBAGED_P here to make sure we don't
5282 call x_set_offset a second time
5283 if we get to x_make_frame_visible a second time
5284 before the window gets really visible. */
5285 if (! FRAME_ICONIFIED_P (f
)
5286 && ! f
->output_data
.x
->asked_for_visible
)
5287 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5289 f
->output_data
.x
->asked_for_visible
= 1;
5291 if (! EQ (Vx_no_window_manager
, Qt
))
5292 x_wm_set_window_state (f
, NormalState
);
5293 #ifdef USE_X_TOOLKIT
5294 /* This was XtPopup, but that did nothing for an iconified frame. */
5295 XtMapWidget (f
->output_data
.x
->widget
);
5296 #else /* not USE_X_TOOLKIT */
5297 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5298 #endif /* not USE_X_TOOLKIT */
5299 #if 0 /* This seems to bring back scroll bars in the wrong places
5300 if the window configuration has changed. They seem
5301 to come back ok without this. */
5302 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5303 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5307 XFlush (FRAME_X_DISPLAY (f
));
5309 /* Synchronize to ensure Emacs knows the frame is visible
5310 before we do anything else. We do this loop with input not blocked
5311 so that incoming events are handled. */
5314 int count
= input_signal_count
;
5316 /* This must come after we set COUNT. */
5319 XSETFRAME (frame
, f
);
5324 /* Once we have handled input events,
5325 we should have received the MapNotify if one is coming.
5326 So if we have not got it yet, stop looping.
5327 Some window managers make their own decisions
5328 about visibility. */
5329 if (input_signal_count
!= count
)
5331 /* Machines that do polling rather than SIGIO have been observed
5332 to go into a busy-wait here. So we'll fake an alarm signal
5333 to let the handler know that there's something to be read.
5334 We used to raise a real alarm, but it seems that the handler
5335 isn't always enabled here. This is probably a bug. */
5336 if (input_polling_used ())
5338 /* It could be confusing if a real alarm arrives while processing
5339 the fake one. Turn it off and let the handler reset it. */
5341 input_poll_signal ();
5343 /* Once we have handled input events,
5344 we should have received the MapNotify if one is coming.
5345 So if we have not got it yet, stop looping.
5346 Some window managers make their own decisions
5347 about visibility. */
5348 if (input_signal_count
!= count
)
5351 FRAME_SAMPLE_VISIBILITY (f
);
5355 /* Change from mapped state to withdrawn state. */
5357 /* Make the frame visible (mapped and not iconified). */
5359 x_make_frame_invisible (f
)
5365 #ifdef USE_X_TOOLKIT
5366 /* Use the frame's outermost window, not the one we normally draw on. */
5367 window
= XtWindow (f
->output_data
.x
->widget
);
5368 #else /* not USE_X_TOOLKIT */
5369 window
= FRAME_X_WINDOW (f
);
5370 #endif /* not USE_X_TOOLKIT */
5372 /* Don't keep the highlight on an invisible frame. */
5373 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5374 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5376 #if 0/* This might add unreliability; I don't trust it -- rms. */
5377 if (! f
->async_visible
&& ! f
->async_iconified
)
5383 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5384 that the current position of the window is user-specified, rather than
5385 program-specified, so that when the window is mapped again, it will be
5386 placed at the same location, without forcing the user to position it
5387 by hand again (they have already done that once for this window.) */
5388 x_wm_set_size_hint (f
, (long) 0, 1);
5392 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5393 DefaultScreen (FRAME_X_DISPLAY (f
))))
5395 UNBLOCK_INPUT_RESIGNAL
;
5396 error ("Can't notify window manager of window withdrawal");
5398 #else /* ! defined (HAVE_X11R4) */
5400 /* Tell the window manager what we're going to do. */
5401 if (! EQ (Vx_no_window_manager
, Qt
))
5405 unmap
.xunmap
.type
= UnmapNotify
;
5406 unmap
.xunmap
.window
= window
;
5407 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5408 unmap
.xunmap
.from_configure
= False
;
5409 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5410 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5412 SubstructureRedirectMask
|SubstructureNotifyMask
,
5415 UNBLOCK_INPUT_RESIGNAL
;
5416 error ("Can't notify window manager of withdrawal");
5420 /* Unmap the window ourselves. Cheeky! */
5421 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5422 #endif /* ! defined (HAVE_X11R4) */
5424 /* We can't distinguish this from iconification
5425 just by the event that we get from the server.
5426 So we can't win using the usual strategy of letting
5427 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5428 and synchronize with the server to make sure we agree. */
5430 FRAME_ICONIFIED_P (f
) = 0;
5431 f
->async_visible
= 0;
5432 f
->async_iconified
= 0;
5439 /* Change window state from mapped to iconified. */
5448 /* Don't keep the highlight on an invisible frame. */
5449 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5450 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5452 if (f
->async_iconified
)
5457 type
= x_icon_type (f
);
5459 x_bitmap_icon (f
, type
);
5461 #ifdef USE_X_TOOLKIT
5463 if (! FRAME_VISIBLE_P (f
))
5465 if (! EQ (Vx_no_window_manager
, Qt
))
5466 x_wm_set_window_state (f
, IconicState
);
5467 /* This was XtPopup, but that did nothing for an iconified frame. */
5468 XtMapWidget (f
->output_data
.x
->widget
);
5473 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5474 XtWindow (f
->output_data
.x
->widget
),
5475 DefaultScreen (FRAME_X_DISPLAY (f
)));
5479 error ("Can't notify window manager of iconification");
5481 f
->async_iconified
= 1;
5484 XFlush (FRAME_X_DISPLAY (f
));
5486 #else /* not USE_X_TOOLKIT */
5488 /* Make sure the X server knows where the window should be positioned,
5489 in case the user deiconifies with the window manager. */
5490 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5491 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5493 /* Since we don't know which revision of X we're running, we'll use both
5494 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5496 /* X11R4: send a ClientMessage to the window manager using the
5497 WM_CHANGE_STATE type. */
5501 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5502 message
.xclient
.type
= ClientMessage
;
5503 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5504 message
.xclient
.format
= 32;
5505 message
.xclient
.data
.l
[0] = IconicState
;
5507 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5508 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5510 SubstructureRedirectMask
| SubstructureNotifyMask
,
5513 UNBLOCK_INPUT_RESIGNAL
;
5514 error ("Can't notify window manager of iconification");
5518 /* X11R3: set the initial_state field of the window manager hints to
5520 x_wm_set_window_state (f
, IconicState
);
5522 if (!FRAME_VISIBLE_P (f
))
5524 /* If the frame was withdrawn, before, we must map it. */
5525 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5528 f
->async_iconified
= 1;
5530 XFlush (FRAME_X_DISPLAY (f
));
5532 #endif /* not USE_X_TOOLKIT */
5535 /* Destroy the X window of frame F. */
5537 x_destroy_window (f
)
5540 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5544 if (f
->output_data
.x
->icon_desc
!= 0)
5545 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
5546 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
5547 #ifdef USE_X_TOOLKIT
5548 XtDestroyWidget (f
->output_data
.x
->widget
);
5549 free_frame_menubar (f
);
5550 #endif /* USE_X_TOOLKIT */
5552 free_frame_faces (f
);
5553 XFlush (FRAME_X_DISPLAY (f
));
5555 xfree (f
->output_data
.x
);
5556 f
->output_data
.x
= 0;
5557 if (f
== dpyinfo
->x_focus_frame
)
5558 dpyinfo
->x_focus_frame
= 0;
5559 if (f
== dpyinfo
->x_focus_event_frame
)
5560 dpyinfo
->x_focus_event_frame
= 0;
5561 if (f
== dpyinfo
->x_highlight_frame
)
5562 dpyinfo
->x_highlight_frame
= 0;
5564 dpyinfo
->reference_count
--;
5566 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5568 dpyinfo
->mouse_face_beg_row
5569 = dpyinfo
->mouse_face_beg_col
= -1;
5570 dpyinfo
->mouse_face_end_row
5571 = dpyinfo
->mouse_face_end_col
= -1;
5572 dpyinfo
->mouse_face_window
= Qnil
;
5578 /* Setting window manager hints. */
5580 /* Set the normal size hints for the window manager, for frame F.
5581 FLAGS is the flags word to use--or 0 meaning preserve the flags
5582 that the window now has.
5583 If USER_POSITION is nonzero, we set the USPosition
5584 flag (this is useful when FLAGS is 0). */
5586 x_wm_set_size_hint (f
, flags
, user_position
)
5591 XSizeHints size_hints
;
5593 #ifdef USE_X_TOOLKIT
5596 Dimension widget_width
, widget_height
;
5597 Window window
= XtWindow (f
->output_data
.x
->widget
);
5598 #else /* not USE_X_TOOLKIT */
5599 Window window
= FRAME_X_WINDOW (f
);
5600 #endif /* not USE_X_TOOLKIT */
5602 /* Setting PMaxSize caused various problems. */
5603 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5605 flexlines
= f
->height
;
5607 size_hints
.x
= f
->output_data
.x
->left_pos
;
5608 size_hints
.y
= f
->output_data
.x
->top_pos
;
5610 #ifdef USE_X_TOOLKIT
5611 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5612 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5613 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5614 size_hints
.height
= widget_height
;
5615 size_hints
.width
= widget_width
;
5616 #else /* not USE_X_TOOLKIT */
5617 size_hints
.height
= PIXEL_HEIGHT (f
);
5618 size_hints
.width
= PIXEL_WIDTH (f
);
5619 #endif /* not USE_X_TOOLKIT */
5621 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
5622 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
5623 size_hints
.max_width
5624 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5625 size_hints
.max_height
5626 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5628 /* Calculate the base and minimum sizes.
5630 (When we use the X toolkit, we don't do it here.
5631 Instead we copy the values that the widgets are using, below.) */
5632 #ifndef USE_X_TOOLKIT
5634 int base_width
, base_height
;
5635 int min_rows
= 0, min_cols
= 0;
5637 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5638 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5640 check_frame_size (f
, &min_rows
, &min_cols
);
5642 /* The window manager uses the base width hints to calculate the
5643 current number of rows and columns in the frame while
5644 resizing; min_width and min_height aren't useful for this
5645 purpose, since they might not give the dimensions for a
5646 zero-row, zero-column frame.
5648 We use the base_width and base_height members if we have
5649 them; otherwise, we set the min_width and min_height members
5650 to the size for a zero x zero frame. */
5653 size_hints
.flags
|= PBaseSize
;
5654 size_hints
.base_width
= base_width
;
5655 size_hints
.base_height
= base_height
;
5656 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5657 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5659 size_hints
.min_width
= base_width
;
5660 size_hints
.min_height
= base_height
;
5664 /* If we don't need the old flags, we don't need the old hint at all. */
5667 size_hints
.flags
|= flags
;
5670 #endif /* not USE_X_TOOLKIT */
5673 XSizeHints hints
; /* Sometimes I hate X Windows... */
5674 long supplied_return
;
5678 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5681 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5684 #ifdef USE_X_TOOLKIT
5685 size_hints
.base_height
= hints
.base_height
;
5686 size_hints
.base_width
= hints
.base_width
;
5687 size_hints
.min_height
= hints
.min_height
;
5688 size_hints
.min_width
= hints
.min_width
;
5692 size_hints
.flags
|= flags
;
5697 if (hints
.flags
& PSize
)
5698 size_hints
.flags
|= PSize
;
5699 if (hints
.flags
& PPosition
)
5700 size_hints
.flags
|= PPosition
;
5701 if (hints
.flags
& USPosition
)
5702 size_hints
.flags
|= USPosition
;
5703 if (hints
.flags
& USSize
)
5704 size_hints
.flags
|= USSize
;
5711 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
5712 size_hints
.flags
|= PWinGravity
;
5716 size_hints
.flags
&= ~ PPosition
;
5717 size_hints
.flags
|= USPosition
;
5719 #endif /* PWinGravity */
5722 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5724 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5728 /* Used for IconicState or NormalState */
5729 x_wm_set_window_state (f
, state
)
5733 #ifdef USE_X_TOOLKIT
5736 XtSetArg (al
[0], XtNinitialState
, state
);
5737 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5738 #else /* not USE_X_TOOLKIT */
5739 Window window
= FRAME_X_WINDOW (f
);
5741 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5742 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5744 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5745 #endif /* not USE_X_TOOLKIT */
5748 x_wm_set_icon_pixmap (f
, pixmap_id
)
5752 #ifdef USE_X_TOOLKIT
5753 Window window
= XtWindow (f
->output_data
.x
->widget
);
5755 Window window
= FRAME_X_WINDOW (f
);
5760 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5761 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5765 /* It seems there is no way to turn off use of an icon pixmap.
5766 The following line does it, only if no icon has yet been created,
5767 for some window managers. But with mwm it crashes.
5768 Some people say it should clear the IconPixmapHint bit in this case,
5769 but that doesn't work, and the X consortium said it isn't the
5770 right thing at all. Since there is no way to win,
5771 best to explicitly give up. */
5773 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5779 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5780 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5783 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5787 #ifdef USE_X_TOOLKIT
5788 Window window
= XtWindow (f
->output_data
.x
->widget
);
5790 Window window
= FRAME_X_WINDOW (f
);
5793 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5794 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5795 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5797 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5801 /* Initialization. */
5803 #ifdef USE_X_TOOLKIT
5804 static XrmOptionDescRec emacs_options
[] = {
5805 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5806 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5808 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5809 XrmoptionSepArg
, NULL
},
5810 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5812 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5813 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5814 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5815 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5816 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5817 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5818 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5820 #endif /* USE_X_TOOLKIT */
5822 static int x_initialized
;
5825 /* Test whether two display-name strings agree up to the dot that separates
5826 the screen number from the server number. */
5828 same_x_server (name1
, name2
)
5829 char *name1
, *name2
;
5832 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5836 if (seen_colon
&& *name1
== '.')
5840 && (*name1
== '.' || *name1
== '\0')
5841 && (*name2
== '.' || *name2
== '\0'));
5845 struct x_display_info
*
5846 x_term_init (display_name
, xrm_option
, resource_name
)
5847 Lisp_Object display_name
;
5849 char *resource_name
;
5855 struct x_display_info
*dpyinfo
;
5867 setlocale (LC_ALL
, NULL
);
5870 #ifdef USE_X_TOOLKIT
5871 /* weiner@footloose.sps.mot.com reports that this causes
5873 X protocol error: BadAtom (invalid Atom parameter)
5874 on protocol request 18skiloaf.
5875 So let's not use it until R6. */
5877 XtSetLanguageProc (NULL
, NULL
, NULL
);
5888 argv
[argc
++] = "-xrm";
5889 argv
[argc
++] = xrm_option
;
5891 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5892 resource_name
, EMACS_CLASS
,
5893 emacs_options
, XtNumber (emacs_options
),
5897 setlocale (LC_NUMERIC
, "C");
5898 setlocale (LC_TIME
, "C");
5902 #else /* not USE_X_TOOLKIT */
5904 XSetLocaleModifiers ("");
5906 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5907 #endif /* not USE_X_TOOLKIT */
5909 /* Detect failure. */
5916 /* We have definitely succeeded. Record the new connection. */
5918 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5922 struct x_display_info
*share
;
5925 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5926 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5927 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5928 XSTRING (display_name
)->data
))
5931 dpyinfo
->kboard
= share
->kboard
;
5934 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5935 init_kboard (dpyinfo
->kboard
);
5936 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
5938 char *vendor
= ServerVendor (dpy
);
5939 dpyinfo
->kboard
->Vsystem_key_alist
5940 = call1 (Qvendor_specific_keysyms
,
5941 build_string (vendor
? vendor
: ""));
5944 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5945 all_kboards
= dpyinfo
->kboard
;
5946 /* Don't let the initial kboard remain current longer than necessary.
5947 That would cause problems if a file loaded on startup tries to
5948 prompt in the minibuffer. */
5949 if (current_kboard
== initial_kboard
)
5950 current_kboard
= dpyinfo
->kboard
;
5952 dpyinfo
->kboard
->reference_count
++;
5956 /* Put this display on the chain. */
5957 dpyinfo
->next
= x_display_list
;
5958 x_display_list
= dpyinfo
;
5960 /* Put it on x_display_name_list as well, to keep them parallel. */
5961 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5962 x_display_name_list
);
5963 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5965 dpyinfo
->display
= dpy
;
5968 XSetAfterFunction (x_current_display
, x_trace_wire
);
5972 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5973 + XSTRING (Vsystem_name
)->size
5975 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5976 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5978 /* Figure out which modifier bits mean what. */
5979 x_find_modifier_meanings (dpyinfo
);
5981 /* Get the scroll bar cursor. */
5982 dpyinfo
->vertical_scroll_bar_cursor
5983 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5985 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5986 resource_name
, EMACS_CLASS
);
5987 #ifdef HAVE_XRMSETDATABASE
5988 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5990 dpyinfo
->display
->db
= xrdb
;
5992 /* Put the rdb where we can find it in a way that works on
5994 dpyinfo
->xrdb
= xrdb
;
5996 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5997 DefaultScreen (dpyinfo
->display
));
5998 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5999 &dpyinfo
->n_planes
);
6000 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
6001 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
6002 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
6003 dpyinfo
->grabbed
= 0;
6004 dpyinfo
->reference_count
= 0;
6005 dpyinfo
->icon_bitmap_id
= -1;
6006 dpyinfo
->n_fonts
= 0;
6007 dpyinfo
->font_table_size
= 0;
6008 dpyinfo
->bitmaps
= 0;
6009 dpyinfo
->bitmaps_size
= 0;
6010 dpyinfo
->bitmaps_last
= 0;
6011 dpyinfo
->scratch_cursor_gc
= 0;
6012 dpyinfo
->mouse_face_mouse_frame
= 0;
6013 dpyinfo
->mouse_face_deferred_gc
= 0;
6014 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6015 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6016 dpyinfo
->mouse_face_face_id
= 0;
6017 dpyinfo
->mouse_face_window
= Qnil
;
6018 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
6019 dpyinfo
->mouse_face_defer
= 0;
6020 dpyinfo
->x_focus_frame
= 0;
6021 dpyinfo
->x_focus_event_frame
= 0;
6022 dpyinfo
->x_highlight_frame
= 0;
6024 dpyinfo
->Xatom_wm_protocols
6025 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
6026 dpyinfo
->Xatom_wm_take_focus
6027 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
6028 dpyinfo
->Xatom_wm_save_yourself
6029 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
6030 dpyinfo
->Xatom_wm_delete_window
6031 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
6032 dpyinfo
->Xatom_wm_change_state
6033 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
6034 dpyinfo
->Xatom_wm_configure_denied
6035 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
6036 dpyinfo
->Xatom_wm_window_moved
6037 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
6038 dpyinfo
->Xatom_editres
6039 = XInternAtom (dpyinfo
->display
, "Editres", False
);
6040 dpyinfo
->Xatom_CLIPBOARD
6041 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
6042 dpyinfo
->Xatom_TIMESTAMP
6043 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
6045 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
6046 dpyinfo
->Xatom_DELETE
6047 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
6048 dpyinfo
->Xatom_MULTIPLE
6049 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
6051 = XInternAtom (dpyinfo
->display
, "INCR", False
);
6052 dpyinfo
->Xatom_EMACS_TMP
6053 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
6054 dpyinfo
->Xatom_TARGETS
6055 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
6057 = XInternAtom (dpyinfo
->display
, "NULL", False
);
6058 dpyinfo
->Xatom_ATOM_PAIR
6059 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
6061 dpyinfo
->cut_buffers_initialized
= 0;
6063 connection
= ConnectionNumber (dpyinfo
->display
);
6064 dpyinfo
->connection
= connection
;
6067 /* This is only needed for distinguishing keyboard and process input. */
6068 if (connection
!= 0)
6069 add_keyboard_wait_descriptor (connection
);
6072 #ifndef F_SETOWN_BUG
6074 #ifdef F_SETOWN_SOCK_NEG
6075 /* stdin is a socket here */
6076 fcntl (connection
, F_SETOWN
, -getpid ());
6077 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6078 fcntl (connection
, F_SETOWN
, getpid ());
6079 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6080 #endif /* ! defined (F_SETOWN) */
6081 #endif /* F_SETOWN_BUG */
6084 if (interrupt_input
)
6085 init_sigio (connection
);
6086 #endif /* ! defined (SIGIO) */
6093 /* Get rid of display DPYINFO, assuming all frames are already gone,
6094 and without sending any more commands to the X server. */
6097 x_delete_display (dpyinfo
)
6098 struct x_display_info
*dpyinfo
;
6100 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
6102 /* Discard this display from x_display_name_list and x_display_list.
6103 We can't use Fdelq because that can quit. */
6104 if (! NILP (x_display_name_list
)
6105 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
6106 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
6111 tail
= x_display_name_list
;
6112 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
6114 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
6115 dpyinfo
->name_list_element
))
6117 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
6120 tail
= XCONS (tail
)->cdr
;
6124 if (x_display_list
== dpyinfo
)
6125 x_display_list
= dpyinfo
->next
;
6128 struct x_display_info
*tail
;
6130 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
6131 if (tail
->next
== dpyinfo
)
6132 tail
->next
= tail
->next
->next
;
6135 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6136 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6137 XrmDestroyDatabase (dpyinfo
->xrdb
);
6141 if (--dpyinfo
->kboard
->reference_count
== 0)
6142 delete_kboard (dpyinfo
->kboard
);
6144 xfree (dpyinfo
->font_table
);
6145 xfree (dpyinfo
->x_id_name
);
6149 /* Set up use of X before we make the first connection. */
6153 clear_frame_hook
= XTclear_frame
;
6154 clear_end_of_line_hook
= XTclear_end_of_line
;
6155 ins_del_lines_hook
= XTins_del_lines
;
6156 change_line_highlight_hook
= XTchange_line_highlight
;
6157 insert_glyphs_hook
= XTinsert_glyphs
;
6158 write_glyphs_hook
= XTwrite_glyphs
;
6159 delete_glyphs_hook
= XTdelete_glyphs
;
6160 ring_bell_hook
= XTring_bell
;
6161 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6162 set_terminal_modes_hook
= XTset_terminal_modes
;
6163 update_begin_hook
= XTupdate_begin
;
6164 update_end_hook
= XTupdate_end
;
6165 set_terminal_window_hook
= XTset_terminal_window
;
6166 read_socket_hook
= XTread_socket
;
6167 frame_up_to_date_hook
= XTframe_up_to_date
;
6168 cursor_to_hook
= XTcursor_to
;
6169 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6170 mouse_position_hook
= XTmouse_position
;
6171 frame_rehighlight_hook
= XTframe_rehighlight
;
6172 frame_raise_lower_hook
= XTframe_raise_lower
;
6173 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6174 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6175 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6176 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6178 scroll_region_ok
= 1; /* we'll scroll partial frames */
6179 char_ins_del_ok
= 0; /* just as fast to write the line */
6180 line_ins_del_ok
= 1; /* we'll just blt 'em */
6181 fast_clear_end_of_line
= 1; /* X does this well */
6182 memory_below_frame
= 0; /* we don't remember what scrolls
6188 /* Try to use interrupt input; if we can't, then start polling. */
6189 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6191 #ifdef USE_X_TOOLKIT
6192 XtToolkitInitialize ();
6193 Xt_app_con
= XtCreateApplicationContext ();
6194 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
6197 /* Note that there is no real way portable across R3/R4 to get the
6198 original error handler. */
6199 XSetErrorHandler (x_error_quitter
);
6200 XSetIOErrorHandler (x_io_error_quitter
);
6202 /* Disable Window Change signals; they are handled by X events. */
6204 signal (SIGWINCH
, SIG_DFL
);
6205 #endif /* ! defined (SIGWINCH) */
6207 signal (SIGPIPE
, x_connection_signal
);
6213 staticpro (&x_display_name_list
);
6214 x_display_name_list
= Qnil
;
6216 staticpro (&last_mouse_scroll_bar
);
6217 last_mouse_scroll_bar
= Qnil
;
6219 staticpro (&Qvendor_specific_keysyms
);
6220 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6222 #endif /* ! defined (HAVE_X_WINDOWS) */