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 void _XEditResCheckMessages ();
89 extern FRAME_PTR
x_menubar_window_to_frame ();
90 #endif /* USE_X_TOOLKIT */
93 #define x_any_window_to_frame x_window_to_frame
94 #define x_top_window_to_frame x_window_to_frame
99 #ifndef XtNinitialState
100 #define XtNinitialState "initialState"
105 /* So we can do setlocale. */
109 #define min(a,b) ((a)<(b) ? (a) : (b))
110 #define max(a,b) ((a)>(b) ? (a) : (b))
112 /* This is a chain of structures for all the X displays currently in use. */
113 struct x_display_info
*x_display_list
;
115 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
116 one for each element of x_display_list and in the same order.
117 NAME is the name of the frame.
118 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
119 Lisp_Object x_display_name_list
;
121 /* Frame being updated by update_frame. This is declared in term.c.
122 This is set by update_begin and looked at by all the
123 XT functions. It is zero while not inside an update.
124 In that case, the XT functions assume that `selected_frame'
125 is the frame to apply to. */
126 extern struct frame
*updating_frame
;
128 /* This is a frame waiting to be autoraised, within XTread_socket. */
129 struct frame
*pending_autoraise_frame
;
132 /* The application context for Xt use. */
133 XtAppContext Xt_app_con
;
135 static String Xt_default_resources
[] =
141 /* During an update, maximum vpos for ins/del line operations to affect. */
143 static int flexlines
;
145 /* During an update, nonzero if chars output now should be highlighted. */
147 static int highlight
;
149 /* Nominal cursor position -- where to draw output.
150 During an update, these are different from the cursor-box position. */
157 In order to avoid asking for motion events and then throwing most
158 of them away or busy-polling the server for mouse positions, we ask
159 the server for pointer motion hints. This means that we get only
160 one event per group of mouse movements. "Groups" are delimited by
161 other kinds of events (focus changes and button clicks, for
162 example), or by XQueryPointer calls; when one of these happens, we
163 get another MotionNotify event the next time the mouse moves. This
164 is at least as efficient as getting motion events when mouse
165 tracking is on, and I suspect only negligibly worse when tracking
168 The silly O'Reilly & Associates Nutshell guides barely document
169 pointer motion hints at all (I think you have to infer how they
170 work from an example), and the description of XQueryPointer doesn't
171 mention that calling it causes you to get another motion hint from
172 the server, which is very important. */
174 /* Where the mouse was last time we reported a mouse event. */
175 static FRAME_PTR last_mouse_frame
;
176 static XRectangle last_mouse_glyph
;
178 /* The scroll bar in which the last X motion event occurred.
180 If the last X motion event occurred in a scroll bar, we set this
181 so XTmouse_position can know whether to report a scroll bar motion or
184 If the last X motion event didn't occur in a scroll bar, we set this
185 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
186 static Lisp_Object last_mouse_scroll_bar
;
188 /* This is a hack. We would really prefer that XTmouse_position would
189 return the time associated with the position it returns, but there
190 doesn't seem to be any way to wrest the timestamp from the server
191 along with the position query. So, we just keep track of the time
192 of the last movement we received, and return that in hopes that
193 it's somewhat accurate. */
194 static Time last_mouse_movement_time
;
196 /* Incremented by XTread_socket whenever it really tries to read events. */
198 static int volatile input_signal_count
;
200 static int input_signal_count
;
203 /* Used locally within XTread_socket. */
204 static int x_noop_count
;
206 /* Initial values of argv and argc. */
207 extern char **initial_argv
;
208 extern int initial_argc
;
210 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
212 /* Tells if a window manager is present or not. */
214 extern Lisp_Object Vx_no_window_manager
;
216 /* Nonzero enables some debugging for the X interface code. */
219 extern Lisp_Object Qface
, Qmouse_face
;
223 /* A mask of extra modifier bits to put into every keyboard char. */
224 extern int extra_keyboard_modifiers
;
226 static Lisp_Object Qvendor_specific_keysyms
;
228 extern XrmDatabase
x_load_resources ();
230 extern Lisp_Object
x_icon_type ();
232 void x_delete_display ();
234 static void redraw_previous_char ();
235 static void redraw_following_char ();
236 static unsigned int x_x_to_emacs_modifiers ();
238 static int fast_find_position ();
239 static void note_mouse_highlight ();
240 static void clear_mouse_face ();
241 static void show_mouse_face ();
242 static void do_line_dance ();
244 static int XTcursor_to ();
245 static int XTclear_end_of_line ();
246 static int x_io_error_quitter ();
247 void x_catch_errors ();
248 void x_uncatch_errors ();
251 /* This is a function useful for recording debugging information
252 about the sequence of occurrences in this file. */
260 struct record event_record
[100];
262 int event_record_index
;
264 record_event (locus
, type
)
268 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
269 event_record_index
= 0;
271 event_record
[event_record_index
].locus
= locus
;
272 event_record
[event_record_index
].type
= type
;
273 event_record_index
++;
278 /* Return the struct x_display_info corresponding to DPY. */
280 struct x_display_info
*
281 x_display_info_for_display (dpy
)
284 struct x_display_info
*dpyinfo
;
286 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
287 if (dpyinfo
->display
== dpy
)
293 /* Starting and ending updates.
295 These hooks are called by update_frame at the beginning and end
296 of a frame update. We record in `updating_frame' the identity
297 of the frame being updated, so that the XT... functions do not
298 need to take a frame as argument. Most of the XT... functions
299 should never be called except during an update, the only exceptions
300 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
311 flexlines
= f
->height
;
316 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
318 /* Don't do highlighting for mouse motion during the update. */
319 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
321 /* If the frame needs to be redrawn,
322 simply forget about any prior mouse highlighting. */
323 if (FRAME_GARBAGED_P (f
))
324 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
326 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
328 int firstline
, lastline
, i
;
329 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
331 /* Find the first, and the last+1, lines affected by redisplay. */
332 for (firstline
= 0; firstline
< f
->height
; firstline
++)
333 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
336 lastline
= f
->height
;
337 for (i
= f
->height
- 1; i
>= 0; i
--)
339 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
345 /* Can we tell that this update does not affect the window
346 where the mouse highlight is? If so, no need to turn off.
347 Likewise, don't do anything if the frame is garbaged;
348 in that case, the FRAME_CURRENT_GLYPHS that we would use
349 are all wrong, and we will redisplay that line anyway. */
350 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
351 || lastline
< XFASTINT (w
->top
)))
352 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
368 x_display_cursor (f
, 1);
370 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
371 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
373 /* This fails in the case of having updated only the echo area
374 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
375 has no relation to the current contents, and its charstarts
376 have no relation to the contents of the window-buffer.
377 I don't know a clean way to check
378 for that case. window_end_valid isn't set up yet. */
379 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
380 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
381 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
384 XFlush (FRAME_X_DISPLAY (f
));
388 /* This is called after a redisplay on frame F. */
391 XTframe_up_to_date (f
)
394 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
395 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
397 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
398 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
399 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
400 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
404 /* External interface to control of standout mode.
405 Call this when about to modify line at position VPOS
406 and not change whether it is highlighted. */
408 XTreassert_line_highlight (new, vpos
)
414 /* Call this when about to modify line at position VPOS
415 and change whether it is highlighted. */
418 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
419 int new_highlight
, vpos
, first_unused_hpos
;
421 highlight
= new_highlight
;
422 XTcursor_to (vpos
, 0);
423 XTclear_end_of_line (updating_frame
->width
);
426 /* This is used when starting Emacs and when restarting after suspend.
427 When starting Emacs, no X window is mapped. And nothing must be done
428 to Emacs's own window if it is suspended (though that rarely happens). */
431 XTset_terminal_modes ()
435 /* This is called when exiting or suspending Emacs.
436 Exiting will make the X-windows go away, and suspending
437 requires no action. */
440 XTreset_terminal_modes ()
442 /* XTclear_frame (); */
445 /* Set the nominal cursor position of the frame.
446 This is where display update commands will take effect.
447 This does not affect the place where the cursor-box is displayed. */
450 XTcursor_to (row
, col
)
451 register int row
, col
;
459 if (updating_frame
== 0)
462 x_display_cursor (selected_frame
, 1);
463 XFlush (FRAME_X_DISPLAY (selected_frame
));
468 /* Display a sequence of N glyphs found at GP.
469 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
470 HL is 1 if this text is highlighted, 2 if the cursor is on it,
471 3 if should appear in its mouse-face.
472 JUST_FOREGROUND if 1 means draw only the foreground;
473 don't alter the background.
475 FONT is the default font to use (for glyphs whose font-code is 0).
477 Since the display generation code is responsible for calling
478 compute_char_face and compute_glyph_face on everything it puts in
479 the display structure, we can assume that the face code on each
480 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
481 to which we can actually apply intern_face.
482 Call this function with input blocked. */
485 /* This is the multi-face code. */
488 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
491 register GLYPH
*gp
; /* Points to first GLYPH. */
492 register int n
; /* Number of glyphs to display. */
496 /* Holds characters to be displayed. */
497 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
498 register char *cp
; /* Steps through buf[]. */
499 register int tlen
= GLYPH_TABLE_LENGTH
;
500 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
501 Window window
= FRAME_X_WINDOW (f
);
502 int orig_left
= left
;
506 /* Get the face-code of the next GLYPH. */
510 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
511 cf
= FAST_GLYPH_FACE (g
);
513 /* Find the run of consecutive glyphs with the same face-code.
514 Extract their character codes into BUF. */
519 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
520 if (FAST_GLYPH_FACE (g
) != cf
)
523 *cp
++ = FAST_GLYPH_CHAR (g
);
528 /* LEN gets the length of the run. */
531 /* Now output this run of chars, with the font and pixel values
532 determined by the face code CF. */
534 struct face
*face
= FRAME_DEFAULT_FACE (f
);
535 XFontStruct
*font
= FACE_FONT (face
);
536 GC gc
= FACE_GC (face
);
539 /* HL = 3 means use a mouse face previously chosen. */
541 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
543 /* First look at the face of the text itself. */
546 /* It's possible for the display table to specify
547 a face code that is out of range. Use 0 in that case. */
548 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
549 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
553 face
= FRAME_MODE_LINE_FACE (f
);
555 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
556 font
= FACE_FONT (face
);
558 if (FACE_STIPPLE (face
))
562 /* Then comes the distinction between modeline and normal text. */
567 face
= FRAME_MODE_LINE_FACE (f
);
568 font
= FACE_FONT (face
);
570 if (FACE_STIPPLE (face
))
574 #define FACE_DEFAULT (~0)
576 /* Now override that if the cursor's on this character. */
579 /* The cursor overrides stippling. */
583 || face
->font
== (XFontStruct
*) FACE_DEFAULT
584 || face
->font
== f
->output_data
.x
->font
)
585 && face
->background
== f
->output_data
.x
->background_pixel
586 && face
->foreground
== f
->output_data
.x
->foreground_pixel
)
588 gc
= f
->output_data
.x
->cursor_gc
;
590 /* Cursor on non-default face: must merge. */
596 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
597 xgcv
.foreground
= face
->background
;
598 /* If the glyph would be invisible,
599 try a different foreground. */
600 if (xgcv
.foreground
== xgcv
.background
)
601 xgcv
.foreground
= face
->foreground
;
602 if (xgcv
.foreground
== xgcv
.background
)
603 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
604 if (xgcv
.foreground
== xgcv
.background
)
605 xgcv
.foreground
= face
->foreground
;
606 /* Make sure the cursor is distinct from text in this face. */
607 if (xgcv
.background
== face
->background
608 && xgcv
.foreground
== face
->foreground
)
610 xgcv
.background
= face
->foreground
;
611 xgcv
.foreground
= face
->background
;
613 xgcv
.font
= face
->font
->fid
;
614 xgcv
.graphics_exposures
= 0;
615 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
616 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
617 XChangeGC (FRAME_X_DISPLAY (f
),
618 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
621 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
622 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
623 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
625 /* If this code is restored, it must also reset to the default stipple
627 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
628 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
633 if (font
== (XFontStruct
*) FACE_DEFAULT
)
634 font
= f
->output_data
.x
->font
;
637 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
638 left
, top
+ FONT_BASE (font
), buf
, len
);
643 /* Turn stipple on. */
644 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
646 /* Draw stipple on background. */
647 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
649 FONT_WIDTH (font
) * len
,
652 /* Turn stipple off. */
653 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
655 /* Draw the text, solidly, onto the stipple pattern. */
656 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
657 left
, top
+ FONT_BASE (font
), buf
, len
);
660 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
661 left
, top
+ FONT_BASE (font
), buf
, len
);
663 /* Clear the rest of the line's height. */
664 if (f
->output_data
.x
->line_height
!= FONT_HEIGHT (font
))
665 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
666 top
+ FONT_HEIGHT (font
),
667 FONT_WIDTH (font
) * len
,
668 /* This is how many pixels of height
670 f
->output_data
.x
->line_height
- FONT_HEIGHT (font
),
674 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
675 which often is not up to date yet. */
676 if (!just_foreground
)
678 if (left
== orig_left
)
679 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
680 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
682 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
683 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
687 /* We should probably check for XA_UNDERLINE_POSITION and
688 XA_UNDERLINE_THICKNESS properties on the font, but let's
689 just get the thing working, and come back to that. */
691 int underline_position
= 1;
693 if (font
->descent
<= underline_position
)
694 underline_position
= font
->descent
- 1;
697 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
701 + underline_position
),
702 len
* FONT_WIDTH (font
), 1);
705 left
+= len
* FONT_WIDTH (font
);
712 /* This is the old single-face code. */
715 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
718 register GLYPH
*gp
; /* Points to first GLYPH. */
719 register int n
; /* Number of glyphs to display. */
724 Window window
= FRAME_X_WINDOW (f
);
725 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
726 : (hl
? f
->output_data
.x
->reverse_gc
727 : f
->output_data
.x
->normal_gc
));
729 if (sizeof (GLYPH
) == sizeof (XChar2b
))
730 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
731 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
732 else if (sizeof (GLYPH
) == sizeof (unsigned char))
733 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
734 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
736 /* What size of glyph ARE you using? And does X have a function to
742 /* Output some text at the nominal frame cursor position.
743 Advance the cursor over the text.
744 Output LEN glyphs at START.
746 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
747 controls the pixel values used for foreground and background. */
750 XTwrite_glyphs (start
, len
)
751 register GLYPH
*start
;
754 register int temp_length
;
765 /* If not within an update,
766 output at the frame's visible cursor. */
767 curs_x
= f
->cursor_x
;
768 curs_y
= f
->cursor_y
;
772 CHAR_TO_PIXEL_COL (f
, curs_x
),
773 CHAR_TO_PIXEL_ROW (f
, curs_y
),
774 start
, len
, highlight
, 0);
776 /* If we drew on top of the cursor, note that it is turned off. */
777 if (curs_y
== f
->phys_cursor_y
778 && curs_x
<= f
->phys_cursor_x
779 && curs_x
+ len
> f
->phys_cursor_x
)
780 f
->phys_cursor_x
= -1;
782 if (updating_frame
== 0)
785 x_display_cursor (f
, 1);
794 /* Clear to the end of the line.
795 Erase the current text line from the nominal cursor position (inclusive)
796 to column FIRST_UNUSED (exclusive). The idea is that everything
797 from FIRST_UNUSED onward is already erased. */
800 XTclear_end_of_line (first_unused
)
801 register int first_unused
;
803 struct frame
*f
= updating_frame
;
809 if (curs_y
< 0 || curs_y
>= f
->height
)
811 if (first_unused
<= 0)
814 if (first_unused
>= f
->width
)
815 first_unused
= f
->width
;
821 /* Notice if the cursor will be cleared by this operation. */
822 if (curs_y
== f
->phys_cursor_y
823 && curs_x
<= f
->phys_cursor_x
824 && f
->phys_cursor_x
< first_unused
)
825 f
->phys_cursor_x
= -1;
827 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
828 CHAR_TO_PIXEL_COL (f
, curs_x
),
829 CHAR_TO_PIXEL_ROW (f
, curs_y
),
830 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
831 f
->output_data
.x
->line_height
, False
);
833 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
843 struct frame
*f
= updating_frame
;
848 f
->phys_cursor_x
= -1; /* Cursor not visible. */
849 curs_x
= 0; /* Nominal cursor position is top left. */
854 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
856 /* We have to clear the scroll bars, too. If we have changed
857 colors or something like that, then they should be notified. */
858 x_scroll_bar_clear (f
);
860 XFlush (FRAME_X_DISPLAY (f
));
865 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
866 always contain the right glyphs to use.
868 It also needs to be changed to look at the details of the font and
869 see whether there is really overlap, and do nothing when there is
870 not. This can use font_char_overlap_left and font_char_overlap_right,
871 but just how to use them is not clear. */
873 /* Erase the character (if any) at the position just before X, Y in frame F,
874 then redraw it and the character before it.
875 This is necessary when we erase starting at X,
876 in case the character after X overlaps into the one before X.
877 Call this function with input blocked. */
880 redraw_previous_char (f
, x
, y
, highlight_flag
)
885 /* Erase the character before the new ones, in case
886 what was here before overlaps it.
887 Reoutput that character, and the previous character
888 (in case the previous character overlaps it). */
894 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
895 CHAR_TO_PIXEL_COL (f
, x
- 1),
896 CHAR_TO_PIXEL_ROW (f
, y
),
897 FONT_WIDTH (f
->output_data
.x
->font
),
898 f
->output_data
.x
->line_height
, False
);
900 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
901 CHAR_TO_PIXEL_ROW (f
, y
),
902 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
903 x
- start_x
, highlight_flag
, 1);
907 /* Erase the character (if any) at the position X, Y in frame F,
908 then redraw it and the character after it.
909 This is necessary when we erase endng at X,
910 in case the character after X overlaps into the one before X.
911 Call this function with input blocked. */
914 redraw_following_char (f
, x
, y
, highlight_flag
)
919 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
920 /* Erase the character after the new ones, in case
921 what was here before overlaps it.
922 Reoutput that character, and the following character
923 (in case the following character overlaps it). */
925 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
930 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
931 CHAR_TO_PIXEL_COL (f
, x
),
932 CHAR_TO_PIXEL_ROW (f
, y
),
933 FONT_WIDTH (f
->output_data
.x
->font
),
934 f
->output_data
.x
->line_height
, False
);
936 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
937 CHAR_TO_PIXEL_ROW (f
, y
),
938 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
939 end_x
- x
, highlight_flag
, 1);
944 #if 0 /* Not in use yet */
946 /* Return 1 if character C in font F extends past its left edge. */
949 font_char_overlap_left (font
, c
)
955 /* Find the bounding-box info for C. */
956 if (font
->per_char
== 0)
957 s
= &font
->max_bounds
;
960 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
963 /* Decode char into row number (byte 1) and code within row (byte 2). */
966 if (!(within
>= font
->min_char_or_byte2
967 && within
<= font
->max_char_or_byte2
968 && row
>= font
->min_byte1
969 && row
<= font
->max_byte1
))
971 /* If char is out of range, try the font's default char instead. */
972 c
= font
->default_char
;
973 row
= c
>> (INTBITS
- 8);
976 if (!(within
>= font
->min_char_or_byte2
977 && within
<= font
->max_char_or_byte2
978 && row
>= font
->min_byte1
979 && row
<= font
->max_byte1
))
980 /* Still out of range means this char does not overlap. */
983 /* We found the info for this char. */
984 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
988 return (s
&& s
->lbearing
< 0);
991 /* Return 1 if character C in font F extends past its right edge. */
994 font_char_overlap_right (font
, c
)
1000 /* Find the bounding-box info for C. */
1001 if (font
->per_char
== 0)
1002 s
= &font
->max_bounds
;
1005 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1008 /* Decode char into row number (byte 1) and code within row (byte 2). */
1011 if (!(within
>= font
->min_char_or_byte2
1012 && within
<= font
->max_char_or_byte2
1013 && row
>= font
->min_byte1
1014 && row
<= font
->max_byte1
))
1016 /* If char is out of range, try the font's default char instead. */
1017 c
= font
->default_char
;
1018 row
= c
>> (INTBITS
- 8);
1021 if (!(within
>= font
->min_char_or_byte2
1022 && within
<= font
->max_char_or_byte2
1023 && row
>= font
->min_byte1
1024 && row
<= font
->max_byte1
))
1025 /* Still out of range means this char does not overlap. */
1028 /* We found the info for this char. */
1029 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1033 return (s
&& s
->rbearing
>= s
->width
);
1037 /* Invert the middle quarter of the frame for .15 sec. */
1039 /* We use the select system call to do the waiting, so we have to make sure
1040 it's available. If it isn't, we just won't do visual bells. */
1041 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1043 /* Subtract the `struct timeval' values X and Y,
1044 storing the result in RESULT.
1045 Return 1 if the difference is negative, otherwise 0. */
1048 timeval_subtract (result
, x
, y
)
1049 struct timeval
*result
, x
, y
;
1051 /* Perform the carry for the later subtraction by updating y.
1052 This is safer because on some systems
1053 the tv_sec member is unsigned. */
1054 if (x
.tv_usec
< y
.tv_usec
)
1056 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1057 y
.tv_usec
-= 1000000 * nsec
;
1060 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1062 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1063 y
.tv_usec
+= 1000000 * nsec
;
1067 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1068 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1069 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1071 /* Return indication of whether the result should be considered negative. */
1072 return x
.tv_sec
< y
.tv_sec
;
1083 /* Create a GC that will use the GXxor function to flip foreground pixels
1084 into background pixels. */
1088 values
.function
= GXxor
;
1089 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1090 ^ f
->output_data
.x
->background_pixel
);
1092 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1093 GCFunction
| GCForeground
, &values
);
1097 int width
= PIXEL_WIDTH (f
);
1098 int height
= PIXEL_HEIGHT (f
);
1100 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1101 width
/4, height
/4, width
/2, height
/2);
1102 XFlush (FRAME_X_DISPLAY (f
));
1105 struct timeval wakeup
, now
;
1107 EMACS_GET_TIME (wakeup
);
1109 /* Compute time to wait until, propagating carry from usecs. */
1110 wakeup
.tv_usec
+= 150000;
1111 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1112 wakeup
.tv_usec
%= 1000000;
1114 /* Keep waiting until past the time wakeup. */
1117 struct timeval timeout
;
1119 EMACS_GET_TIME (timeout
);
1121 /* In effect, timeout = wakeup - timeout.
1122 Break if result would be negative. */
1123 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1126 /* Try to wait that long--but we might wake up sooner. */
1127 select (0, NULL
, NULL
, NULL
, &timeout
);
1131 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1132 width
/4, height
/4, width
/2, height
/2);
1133 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1134 XFlush (FRAME_X_DISPLAY (f
));
1144 /* Make audible bell. */
1146 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1150 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1153 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1155 XTflash (selected_frame
);
1161 XFlush (FRAME_X_DISPLAY (selected_frame
));
1166 /* Insert and delete character.
1167 These are not supposed to be used because we are supposed to turn
1168 off the feature of using them. */
1171 XTinsert_glyphs (start
, len
)
1172 register char *start
;
1185 /* Specify how many text lines, from the top of the window,
1186 should be affected by insert-lines and delete-lines operations.
1187 This, and those operations, are used only within an update
1188 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1191 XTset_terminal_window (n
)
1194 if (updating_frame
== 0)
1197 if ((n
<= 0) || (n
> updating_frame
->height
))
1198 flexlines
= updating_frame
->height
;
1203 /* These variables need not be per frame
1204 because redisplay is done on a frame-by-frame basis
1205 and the line dance for one frame is finished before
1206 anything is done for anoter frame. */
1208 /* Array of line numbers from cached insert/delete operations.
1209 line_dance[i] is the old position of the line that we want
1210 to move to line i, or -1 if we want a blank line there. */
1211 static int *line_dance
;
1213 /* Allocated length of that array. */
1214 static int line_dance_len
;
1216 /* Flag indicating whether we've done any work. */
1217 static int line_dance_in_progress
;
1219 /* Perform an insert-lines or delete-lines operation,
1220 inserting N lines or deleting -N lines at vertical position VPOS. */
1221 XTins_del_lines (vpos
, n
)
1224 register int fence
, i
;
1226 if (vpos
>= flexlines
)
1229 if (!line_dance_in_progress
)
1231 int ht
= updating_frame
->height
;
1232 if (ht
> line_dance_len
)
1234 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1235 line_dance_len
= ht
;
1237 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1238 line_dance_in_progress
= 1;
1242 if (n
> flexlines
- vpos
)
1243 n
= flexlines
- vpos
;
1245 for (i
= flexlines
; --i
>= fence
;)
1246 line_dance
[i
] = line_dance
[i
-n
];
1247 for (i
= fence
; --i
>= vpos
;)
1253 if (n
> flexlines
- vpos
)
1254 n
= flexlines
- vpos
;
1255 fence
= flexlines
- n
;
1256 for (i
= vpos
; i
< fence
; ++i
)
1257 line_dance
[i
] = line_dance
[i
+ n
];
1258 for (i
= fence
; i
< flexlines
; ++i
)
1263 /* Here's where we actually move the pixels around.
1264 Must be called with input blocked. */
1268 register int i
, j
, distance
;
1269 register struct frame
*f
;
1273 /* Must check this flag first. If it's not set, then not only is the
1274 array uninitialized, but we might not even have a frame. */
1275 if (!line_dance_in_progress
)
1283 intborder
= f
->output_data
.x
->internal_border_width
;
1285 x_display_cursor (updating_frame
, 0);
1287 for (i
= 0; i
< ht
; ++i
)
1288 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1290 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1291 && line_dance
[j
]-j
== distance
); ++j
);
1292 /* Copy [i,j) upward from [i+distance,j+distance) */
1293 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1294 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1295 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1296 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1297 (j
-i
) * f
->output_data
.x
->line_height
,
1298 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1302 for (i
= ht
; --i
>=0; )
1303 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1305 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1306 && line_dance
[j
]-j
== distance
););
1307 /* Copy (j,i] downward from (j+distance, i+distance] */
1308 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1309 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1310 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1311 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1312 (i
-j
) * f
->output_data
.x
->line_height
,
1313 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1317 for (i
= 0; i
< ht
; ++i
)
1318 if (line_dance
[i
] == -1)
1320 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1322 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1323 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1324 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1325 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1328 line_dance_in_progress
= 0;
1331 /* Support routines for exposure events. */
1332 static void clear_cursor ();
1334 /* Output into a rectangle of an X-window (for frame F)
1335 the characters in f->phys_lines that overlap that rectangle.
1336 TOP and LEFT are the position of the upper left corner of the rectangle.
1337 ROWS and COLS are the size of the rectangle.
1338 Call this function with input blocked. */
1341 dumprectangle (f
, left
, top
, cols
, rows
)
1343 register int left
, top
, cols
, rows
;
1345 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1346 int cursor_cleared
= 0;
1350 if (FRAME_GARBAGED_P (f
))
1353 /* Express rectangle as four edges, instead of position-and-size. */
1354 bottom
= top
+ rows
;
1355 right
= left
+ cols
;
1357 /* Convert rectangle edges in pixels to edges in chars.
1358 Round down for left and top, up for right and bottom. */
1359 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1360 left
= PIXEL_TO_CHAR_COL (f
, left
);
1361 bottom
+= (f
->output_data
.x
->line_height
- 1);
1362 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1363 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1364 right
= PIXEL_TO_CHAR_COL (f
, right
);
1366 /* Clip the rectangle to what can be visible. */
1371 if (right
> f
->width
)
1373 if (bottom
> f
->height
)
1376 /* Get size in chars of the rectangle. */
1377 cols
= right
- left
;
1378 rows
= bottom
- top
;
1380 /* If rectangle has zero area, return. */
1381 if (rows
<= 0) return;
1382 if (cols
<= 0) return;
1384 /* Turn off the cursor if it is in the rectangle.
1385 We will turn it back on afterward. */
1386 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1387 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1393 /* Display the text in the rectangle, one text line at a time. */
1395 for (y
= top
; y
< bottom
; y
++)
1397 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1399 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1403 CHAR_TO_PIXEL_COL (f
, left
),
1404 CHAR_TO_PIXEL_ROW (f
, y
),
1405 line
, min (cols
, active_frame
->used
[y
] - left
),
1406 active_frame
->highlight
[y
], 0);
1409 /* Turn the cursor on if we turned it off. */
1412 x_display_cursor (f
, 1);
1419 /* We used to only do this if Vx_no_window_manager was non-nil, but
1420 the ICCCM (section 4.1.6) says that the window's border pixmap
1421 and border pixel are window attributes which are "private to the
1422 client", so we can always change it to whatever we want. */
1424 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1425 f
->output_data
.x
->border_pixel
);
1427 x_update_cursor (f
, 1);
1431 frame_unhighlight (f
)
1434 /* We used to only do this if Vx_no_window_manager was non-nil, but
1435 the ICCCM (section 4.1.6) says that the window's border pixmap
1436 and border pixel are window attributes which are "private to the
1437 client", so we can always change it to whatever we want. */
1439 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1440 f
->output_data
.x
->border_tile
);
1442 x_update_cursor (f
, 1);
1445 static void XTframe_rehighlight ();
1446 static void x_frame_rehighlight ();
1448 /* The focus has changed. Update the frames as necessary to reflect
1449 the new situation. Note that we can't change the selected frame
1450 here, because the Lisp code we are interrupting might become confused.
1451 Each event gets marked with the frame in which it occurred, so the
1452 Lisp code can tell when the switch took place by examining the events. */
1455 x_new_focus_frame (dpyinfo
, frame
)
1456 struct x_display_info
*dpyinfo
;
1457 struct frame
*frame
;
1459 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1460 int events_enqueued
= 0;
1462 if (frame
!= dpyinfo
->x_focus_frame
)
1464 /* Set this before calling other routines, so that they see
1465 the correct value of x_focus_frame. */
1466 dpyinfo
->x_focus_frame
= frame
;
1468 if (old_focus
&& old_focus
->auto_lower
)
1469 x_lower_frame (old_focus
);
1472 selected_frame
= frame
;
1473 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1475 Fselect_window (selected_frame
->selected_window
);
1476 choose_minibuf_frame ();
1479 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1480 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1482 pending_autoraise_frame
= 0;
1485 x_frame_rehighlight (dpyinfo
);
1488 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1491 x_mouse_leave (dpyinfo
)
1492 struct x_display_info
*dpyinfo
;
1494 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1497 /* The focus has changed, or we have redirected a frame's focus to
1498 another frame (this happens when a frame uses a surrogate
1499 minibuffer frame). Shift the highlight as appropriate.
1501 The FRAME argument doesn't necessarily have anything to do with which
1502 frame is being highlighted or unhighlighted; we only use it to find
1503 the appropriate X display info. */
1505 XTframe_rehighlight (frame
)
1506 struct frame
*frame
;
1508 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
1512 x_frame_rehighlight (dpyinfo
)
1513 struct x_display_info
*dpyinfo
;
1515 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1517 if (dpyinfo
->x_focus_frame
)
1519 dpyinfo
->x_highlight_frame
1520 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
1521 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
1522 : dpyinfo
->x_focus_frame
);
1523 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
1525 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
1526 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1530 dpyinfo
->x_highlight_frame
= 0;
1532 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
1535 frame_unhighlight (old_highlight
);
1536 if (dpyinfo
->x_highlight_frame
)
1537 frame_highlight (dpyinfo
->x_highlight_frame
);
1541 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1543 /* Initialize mode_switch_bit and modifier_meaning. */
1545 x_find_modifier_meanings (dpyinfo
)
1546 struct x_display_info
*dpyinfo
;
1548 int min_code
, max_code
;
1551 XModifierKeymap
*mods
;
1553 dpyinfo
->meta_mod_mask
= 0;
1554 dpyinfo
->shift_lock_mask
= 0;
1555 dpyinfo
->alt_mod_mask
= 0;
1556 dpyinfo
->super_mod_mask
= 0;
1557 dpyinfo
->hyper_mod_mask
= 0;
1560 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1562 min_code
= display
->min_keycode
;
1563 max_code
= display
->max_keycode
;
1566 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1567 min_code
, max_code
- min_code
+ 1,
1569 mods
= XGetModifierMapping (dpyinfo
->display
);
1571 /* Scan the modifier table to see which modifier bits the Meta and
1572 Alt keysyms are on. */
1574 int row
, col
; /* The row and column in the modifier table. */
1576 for (row
= 3; row
< 8; row
++)
1577 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1580 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1582 /* Zeroes are used for filler. Skip them. */
1586 /* Are any of this keycode's keysyms a meta key? */
1590 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1592 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1598 dpyinfo
->meta_mod_mask
|= (1 << row
);
1603 dpyinfo
->alt_mod_mask
|= (1 << row
);
1608 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1613 dpyinfo
->super_mod_mask
|= (1 << row
);
1617 /* Ignore this if it's not on the lock modifier. */
1618 if ((1 << row
) == LockMask
)
1619 dpyinfo
->shift_lock_mask
= LockMask
;
1627 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1628 if (! dpyinfo
->meta_mod_mask
)
1630 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1631 dpyinfo
->alt_mod_mask
= 0;
1634 /* If some keys are both alt and meta,
1635 make them just meta, not alt. */
1636 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1638 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1641 XFree ((char *) syms
);
1642 XFreeModifiermap (mods
);
1645 /* Convert between the modifier bits X uses and the modifier bits
1648 x_x_to_emacs_modifiers (dpyinfo
, state
)
1649 struct x_display_info
*dpyinfo
;
1652 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1653 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1654 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1655 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1656 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1657 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1661 x_emacs_to_x_modifiers (dpyinfo
, state
)
1662 struct x_display_info
*dpyinfo
;
1665 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1666 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1667 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1668 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1669 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1670 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1673 /* Convert a keysym to its name. */
1676 x_get_keysym_name (keysym
)
1682 value
= XKeysymToString (keysym
);
1688 /* Mouse clicks and mouse movement. Rah. */
1690 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1691 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1692 that the glyph at X, Y occupies, if BOUNDS != 0.
1693 If NOCLIP is nonzero, do not force the value into range. */
1696 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1698 register int pix_x
, pix_y
;
1699 register int *x
, *y
;
1703 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1704 even for negative values. */
1706 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
1708 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
1710 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1711 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1715 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
1716 bounds
->height
= f
->output_data
.x
->line_height
;
1717 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1718 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1725 else if (pix_x
> f
->width
)
1730 else if (pix_y
> f
->height
)
1739 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1742 register int *pix_x
, *pix_y
;
1744 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1745 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1748 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1750 If the event is a button press, then note that we have grabbed
1754 construct_mouse_click (result
, event
, f
)
1755 struct input_event
*result
;
1756 XButtonEvent
*event
;
1759 /* Make the event type no_event; we'll change that when we decide
1761 result
->kind
= mouse_click
;
1762 result
->code
= event
->button
- Button1
;
1763 result
->timestamp
= event
->time
;
1764 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1766 | (event
->type
== ButtonRelease
1774 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1775 XSETFASTINT (result
->x
, column
);
1776 XSETFASTINT (result
->y
, row
);
1778 XSETINT (result
->x
, event
->x
);
1779 XSETINT (result
->y
, event
->y
);
1780 XSETFRAME (result
->frame_or_window
, f
);
1784 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1787 construct_menu_click (result
, event
, f
)
1788 struct input_event
*result
;
1789 XButtonEvent
*event
;
1792 /* Make the event type no_event; we'll change that when we decide
1794 result
->kind
= mouse_click
;
1795 XSETINT (result
->code
, event
->button
- Button1
);
1796 result
->timestamp
= event
->time
;
1797 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1799 | (event
->type
== ButtonRelease
1803 XSETINT (result
->x
, event
->x
);
1804 XSETINT (result
->y
, -1);
1805 XSETFRAME (result
->frame_or_window
, f
);
1808 /* Function to report a mouse movement to the mainstream Emacs code.
1809 The input handler calls this.
1811 We have received a mouse movement event, which is given in *event.
1812 If the mouse is over a different glyph than it was last time, tell
1813 the mainstream emacs code by setting mouse_moved. If not, ask for
1814 another motion event, so we can check again the next time it moves. */
1817 note_mouse_movement (frame
, event
)
1819 XMotionEvent
*event
;
1821 last_mouse_movement_time
= event
->time
;
1823 if (event
->window
!= FRAME_X_WINDOW (frame
))
1825 frame
->mouse_moved
= 1;
1826 last_mouse_scroll_bar
= Qnil
;
1828 note_mouse_highlight (frame
, -1, -1);
1830 /* Ask for another mouse motion event. */
1833 Window dummy_window
;
1835 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1836 &dummy_window
, &dummy_window
,
1837 &dummy
, &dummy
, &dummy
, &dummy
,
1838 (unsigned int *) &dummy
);
1842 /* Has the mouse moved off the glyph it was on at the last sighting? */
1843 else if (event
->x
< last_mouse_glyph
.x
1844 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1845 || event
->y
< last_mouse_glyph
.y
1846 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1848 frame
->mouse_moved
= 1;
1849 last_mouse_scroll_bar
= Qnil
;
1851 note_mouse_highlight (frame
, event
->x
, event
->y
);
1853 /* Ask for another mouse motion event. */
1856 Window dummy_window
;
1858 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1859 &dummy_window
, &dummy_window
,
1860 &dummy
, &dummy
, &dummy
, &dummy
,
1861 (unsigned int *) &dummy
);
1866 /* It's on the same glyph. Call XQueryPointer so we'll get an
1867 event the next time the mouse moves and we can see if it's
1868 *still* on the same glyph. */
1870 Window dummy_window
;
1872 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1873 &dummy_window
, &dummy_window
,
1874 &dummy
, &dummy
, &dummy
, &dummy
,
1875 (unsigned int *) &dummy
);
1879 /* This is used for debugging, to turn off note_mouse_highlight. */
1880 static int disable_mouse_highlight
;
1882 /* Take proper action when the mouse has moved to position X, Y on frame F
1883 as regards highlighting characters that have mouse-face properties.
1884 Also dehighlighting chars where the mouse was before.
1885 X and Y can be negative or out of range. */
1888 note_mouse_highlight (f
, x
, y
)
1892 int row
, column
, portion
;
1893 XRectangle new_glyph
;
1897 if (disable_mouse_highlight
)
1900 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1901 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1902 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1904 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1909 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1913 /* Find out which glyph the mouse is on. */
1914 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1915 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1917 /* Which window is that in? */
1918 window
= window_from_coordinates (f
, column
, row
, &portion
);
1919 w
= XWINDOW (window
);
1921 /* If we were displaying active text in another window, clear that. */
1922 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1923 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1925 /* Are we in a window whose display is up to date?
1926 And verify the buffer's text has not changed. */
1927 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1928 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1929 && EQ (w
->window_end_valid
, w
->buffer
)
1930 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1932 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1935 /* Find which buffer position the mouse corresponds to. */
1936 for (i
= column
; i
>= 0; i
--)
1940 /* Is it outside the displayed active region (if any)? */
1942 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1943 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1944 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1945 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1946 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1947 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1948 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1949 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1950 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1952 Lisp_Object mouse_face
, overlay
, position
;
1953 Lisp_Object
*overlay_vec
;
1954 int len
, noverlays
, ignor1
;
1955 struct buffer
*obuf
;
1958 /* If we get an out-of-range value, return now; avoid an error. */
1959 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1962 /* Make the window's buffer temporarily current for
1963 overlays_at and compute_char_face. */
1964 obuf
= current_buffer
;
1965 current_buffer
= XBUFFER (w
->buffer
);
1971 /* Yes. Clear the display of the old active region, if any. */
1972 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1974 /* Is this char mouse-active? */
1975 XSETINT (position
, pos
);
1978 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1980 /* Put all the overlays we want in a vector in overlay_vec.
1981 Store the length in len. */
1982 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1984 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1986 /* Find the highest priority overlay that has a mouse-face prop. */
1988 for (i
= 0; i
< noverlays
; i
++)
1990 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1991 if (!NILP (mouse_face
))
1993 overlay
= overlay_vec
[i
];
1998 /* If no overlay applies, get a text property. */
2000 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2002 /* Handle the overlay case. */
2003 if (! NILP (overlay
))
2005 /* Find the range of text around this char that
2006 should be active. */
2007 Lisp_Object before
, after
;
2010 before
= Foverlay_start (overlay
);
2011 after
= Foverlay_end (overlay
);
2012 /* Record this as the current active region. */
2013 fast_find_position (window
, before
,
2014 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2015 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2016 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2017 = !fast_find_position (window
, after
,
2018 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2019 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2020 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2021 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2022 = compute_char_face (f
, w
, pos
, 0, 0,
2023 &ignore
, pos
+ 1, 1);
2025 /* Display it as active. */
2026 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2028 /* Handle the text property case. */
2029 else if (! NILP (mouse_face
))
2031 /* Find the range of text around this char that
2032 should be active. */
2033 Lisp_Object before
, after
, beginning
, end
;
2036 beginning
= Fmarker_position (w
->start
);
2037 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2038 - XFASTINT (w
->window_end_pos
)));
2040 = Fprevious_single_property_change (make_number (pos
+ 1),
2042 w
->buffer
, beginning
);
2044 = Fnext_single_property_change (position
, Qmouse_face
,
2046 /* Record this as the current active region. */
2047 fast_find_position (window
, before
,
2048 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2049 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2050 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2051 = !fast_find_position (window
, after
,
2052 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2053 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2054 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2055 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2056 = compute_char_face (f
, w
, pos
, 0, 0,
2057 &ignore
, pos
+ 1, 1);
2059 /* Display it as active. */
2060 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2064 current_buffer
= obuf
;
2069 /* Find the row and column of position POS in window WINDOW.
2070 Store them in *COLUMNP and *ROWP.
2071 This assumes display in WINDOW is up to date.
2072 If POS is above start of WINDOW, return coords
2073 of start of first screen line.
2074 If POS is after end of WINDOW, return coords of end of last screen line.
2076 Value is 1 if POS is in range, 0 if it was off screen. */
2079 fast_find_position (window
, pos
, columnp
, rowp
)
2082 int *columnp
, *rowp
;
2084 struct window
*w
= XWINDOW (window
);
2085 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2090 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2091 int width
= window_internal_width (w
);
2094 int maybe_next_line
= 0;
2096 /* Find the right row. */
2101 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2102 if (linestart
> pos
)
2104 /* If the position sought is the end of the buffer,
2105 don't include the blank lines at the bottom of the window. */
2106 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2108 maybe_next_line
= 1;
2115 /* Find the right column with in it. */
2116 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2118 for (i
= 0; i
< width
; i
++)
2120 if (charstarts
[left
+ i
] == pos
)
2123 *columnp
= i
+ left
;
2126 else if (charstarts
[left
+ i
] > pos
)
2128 else if (charstarts
[left
+ i
] > 0)
2132 /* If we're looking for the end of the buffer,
2133 and we didn't find it in the line we scanned,
2134 use the start of the following line. */
2135 if (maybe_next_line
)
2146 /* Display the active region described by mouse_face_*
2147 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2150 show_mouse_face (dpyinfo
, hl
)
2151 struct x_display_info
*dpyinfo
;
2154 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2155 int width
= window_internal_width (w
);
2156 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2159 int old_curs_x
= curs_x
;
2160 int old_curs_y
= curs_y
;
2162 /* Set these variables temporarily
2163 so that if we have to turn the cursor off and on again
2164 we will put it back at the same place. */
2165 curs_x
= f
->phys_cursor_x
;
2166 curs_y
= f
->phys_cursor_y
;
2168 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2169 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2171 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2172 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2174 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2175 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2177 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2179 /* If the cursor's in the text we are about to rewrite,
2180 turn the cursor off. */
2182 && curs_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
2183 && curs_x
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
)
2185 x_display_cursor (f
, 0);
2190 CHAR_TO_PIXEL_COL (f
, column
),
2191 CHAR_TO_PIXEL_ROW (f
, i
),
2192 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2194 /* Highlight with mouse face if hl > 0. */
2198 /* If we turned the cursor off, turn it back on. */
2200 x_display_cursor (f
, 1);
2202 curs_x
= old_curs_x
;
2203 curs_y
= old_curs_y
;
2205 /* Change the mouse cursor according to the value of HL. */
2207 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2208 f
->output_data
.x
->cross_cursor
);
2210 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2211 f
->output_data
.x
->text_cursor
);
2214 /* Clear out the mouse-highlighted active region.
2215 Redraw it unhighlighted first. */
2218 clear_mouse_face (dpyinfo
)
2219 struct x_display_info
*dpyinfo
;
2221 if (! NILP (dpyinfo
->mouse_face_window
))
2222 show_mouse_face (dpyinfo
, 0);
2224 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2225 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2226 dpyinfo
->mouse_face_window
= Qnil
;
2229 static struct scroll_bar
*x_window_to_scroll_bar ();
2230 static void x_scroll_bar_report_motion ();
2232 /* Return the current position of the mouse.
2233 *fp should be a frame which indicates which display to ask about.
2235 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2236 and *part to the frame, window, and scroll bar part that the mouse
2237 is over. Set *x and *y to the portion and whole of the mouse's
2238 position on the scroll bar.
2240 If the mouse movement started elsewhere, set *fp to the frame the
2241 mouse is on, *bar_window to nil, and *x and *y to the character cell
2244 Set *time to the server timestamp for the time at which the mouse
2245 was at this position.
2247 Don't store anything if we don't have a valid set of values to report.
2249 This clears the mouse_moved flag, so we can wait for the next mouse
2250 movement. This also calls XQueryPointer, which will cause the
2251 server to give us another MotionNotify when the mouse moves
2255 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2258 Lisp_Object
*bar_window
;
2259 enum scroll_bar_part
*part
;
2261 unsigned long *time
;
2267 if (! NILP (last_mouse_scroll_bar
))
2268 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2274 Window dummy_window
;
2277 Lisp_Object frame
, tail
;
2279 /* Clear the mouse-moved flag for every frame on this display. */
2280 FOR_EACH_FRAME (tail
, frame
)
2281 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2282 XFRAME (frame
)->mouse_moved
= 0;
2284 last_mouse_scroll_bar
= Qnil
;
2286 /* Figure out which root window we're on. */
2287 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2288 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2290 /* The root window which contains the pointer. */
2293 /* Trash which we can't trust if the pointer is on
2294 a different screen. */
2297 /* The position on that root window. */
2300 /* More trash we can't trust. */
2303 /* Modifier keys and pointer buttons, about which
2305 (unsigned int *) &dummy
);
2307 /* Now we have a position on the root; find the innermost window
2308 containing the pointer. */
2312 int parent_x
, parent_y
;
2316 /* XTranslateCoordinates can get errors if the window
2317 structure is changing at the same time this function
2318 is running. So at least we must not crash from them. */
2320 x_catch_errors (FRAME_X_DISPLAY (*fp
));
2322 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2323 && FRAME_LIVE_P (last_mouse_frame
))
2325 /* If mouse was grabbed on a frame, give coords for that frame
2326 even if the mouse is now outside it. */
2327 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2329 /* From-window, to-window. */
2330 root
, FRAME_X_WINDOW (last_mouse_frame
),
2332 /* From-position, to-position. */
2333 root_x
, root_y
, &win_x
, &win_y
,
2337 f1
= last_mouse_frame
;
2343 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2345 /* From-window, to-window. */
2348 /* From-position, to-position. */
2349 root_x
, root_y
, &win_x
, &win_y
,
2362 /* Now we know that:
2363 win is the innermost window containing the pointer
2364 (XTC says it has no child containing the pointer),
2365 win_x and win_y are the pointer's position in it
2366 (XTC did this the last time through), and
2367 parent_x and parent_y are the pointer's position in win's parent.
2368 (They are what win_x and win_y were when win was child.
2369 If win is the root window, it has no parent, and
2370 parent_{x,y} are invalid, but that's okay, because we'll
2371 never use them in that case.) */
2373 /* Is win one of our frames? */
2374 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2377 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2380 x_uncatch_errors (FRAME_X_DISPLAY (*fp
));
2382 /* If not, is it one of our scroll bars? */
2385 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2389 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2395 if (f1
== 0 && insist
)
2396 f1
= selected_frame
;
2400 int ignore1
, ignore2
;
2402 /* Ok, we found a frame. Store all the values. */
2404 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2406 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2412 XSETINT (*x
, win_x
);
2413 XSETINT (*y
, win_y
);
2414 *time
= last_mouse_movement_time
;
2422 /* Scroll bar support. */
2424 /* Given an X window ID, find the struct scroll_bar which manages it.
2425 This can be called in GC, so we have to make sure to strip off mark
2427 static struct scroll_bar
*
2428 x_window_to_scroll_bar (window_id
)
2431 Lisp_Object tail
, frame
;
2433 for (tail
= Vframe_list
;
2434 XGCTYPE (tail
) == Lisp_Cons
;
2435 tail
= XCONS (tail
)->cdr
)
2437 Lisp_Object frame
, bar
, condemned
;
2439 frame
= XCONS (tail
)->car
;
2440 /* All elements of Vframe_list should be frames. */
2441 if (! GC_FRAMEP (frame
))
2444 /* Scan this frame's scroll bar list for a scroll bar with the
2446 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2447 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2448 /* This trick allows us to search both the ordinary and
2449 condemned scroll bar lists with one loop. */
2450 ! GC_NILP (bar
) || (bar
= condemned
,
2453 bar
= XSCROLL_BAR (bar
)->next
)
2454 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2455 return XSCROLL_BAR (bar
);
2461 /* Open a new X window to serve as a scroll bar, and return the
2462 scroll bar vector for it. */
2463 static struct scroll_bar
*
2464 x_scroll_bar_create (window
, top
, left
, width
, height
)
2465 struct window
*window
;
2466 int top
, left
, width
, height
;
2468 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2469 struct scroll_bar
*bar
2470 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2475 XSetWindowAttributes a
;
2477 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2478 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2479 | ButtonMotionMask
| PointerMotionHintMask
2481 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2483 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2488 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2489 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2490 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2491 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2492 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2493 sb_widget
= XtCreateManagedWidget ("box",
2495 f
->output_data
.x
->edit_widget
, al
, ac
);
2496 SET_SCROLL_BAR_X_WINDOW
2497 (bar
, sb_widget
->core
.window
);
2499 SET_SCROLL_BAR_X_WINDOW
2501 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2503 /* Position and size of scroll bar. */
2504 left
, top
, width
, height
,
2506 /* Border width, depth, class, and visual. */
2507 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2513 XSETWINDOW (bar
->window
, window
);
2514 XSETINT (bar
->top
, top
);
2515 XSETINT (bar
->left
, left
);
2516 XSETINT (bar
->width
, width
);
2517 XSETINT (bar
->height
, height
);
2518 XSETINT (bar
->start
, 0);
2519 XSETINT (bar
->end
, 0);
2520 bar
->dragging
= Qnil
;
2522 /* Add bar to its frame's list of scroll bars. */
2523 bar
->next
= FRAME_SCROLL_BARS (f
);
2525 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2526 if (! NILP (bar
->next
))
2527 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2529 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2536 /* Draw BAR's handle in the proper position.
2537 If the handle is already drawn from START to END, don't bother
2538 redrawing it, unless REBUILD is non-zero; in that case, always
2539 redraw it. (REBUILD is handy for drawing the handle after expose
2542 Normally, we want to constrain the start and end of the handle to
2543 fit inside its rectangle, but if the user is dragging the scroll bar
2544 handle, we want to let them drag it down all the way, so that the
2545 bar's top is as far down as it goes; otherwise, there's no way to
2546 move to the very end of the buffer. */
2548 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2549 struct scroll_bar
*bar
;
2553 int dragging
= ! NILP (bar
->dragging
);
2554 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2555 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2556 GC gc
= f
->output_data
.x
->normal_gc
;
2558 /* If the display is already accurate, do nothing. */
2560 && start
== XINT (bar
->start
)
2561 && end
== XINT (bar
->end
))
2567 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2568 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2569 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2571 /* Make sure the values are reasonable, and try to preserve
2572 the distance between start and end. */
2574 int length
= end
- start
;
2578 else if (start
> top_range
)
2580 end
= start
+ length
;
2584 else if (end
> top_range
&& ! dragging
)
2588 /* Store the adjusted setting in the scroll bar. */
2589 XSETINT (bar
->start
, start
);
2590 XSETINT (bar
->end
, end
);
2592 /* Clip the end position, just for display. */
2593 if (end
> top_range
)
2596 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2597 below top positions, to make sure the handle is always at least
2598 that many pixels tall. */
2599 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2601 /* Draw the empty space above the handle. Note that we can't clear
2602 zero-height areas; that means "clear to end of window." */
2604 XClearArea (FRAME_X_DISPLAY (f
), w
,
2606 /* x, y, width, height, and exposures. */
2607 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2608 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2609 inside_width
, start
,
2612 /* Draw the handle itself. */
2613 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2615 /* x, y, width, height */
2616 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2617 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2618 inside_width
, end
- start
);
2621 /* Draw the empty space below the handle. Note that we can't
2622 clear zero-height areas; that means "clear to end of window." */
2623 if (end
< inside_height
)
2624 XClearArea (FRAME_X_DISPLAY (f
), w
,
2626 /* x, y, width, height, and exposures. */
2627 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2628 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2629 inside_width
, inside_height
- end
,
2637 /* Move a scroll bar around on the screen, to accommodate changing
2638 window configurations. */
2640 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2641 struct scroll_bar
*bar
;
2642 int top
, left
, width
, height
;
2644 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2645 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2651 unsigned int mask
= 0;
2658 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2659 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2660 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2661 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2664 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2668 XSETINT (bar
->left
, left
);
2669 XSETINT (bar
->top
, top
);
2670 XSETINT (bar
->width
, width
);
2671 XSETINT (bar
->height
, height
);
2676 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2679 x_scroll_bar_remove (bar
)
2680 struct scroll_bar
*bar
;
2682 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2686 /* Destroy the window. */
2687 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2689 /* Disassociate this scroll bar from its window. */
2690 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2695 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2696 that we are displaying PORTION characters out of a total of WHOLE
2697 characters, starting at POSITION. If WINDOW has no scroll bar,
2700 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2701 struct window
*window
;
2702 int portion
, whole
, position
;
2704 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2705 int top
= XINT (window
->top
);
2706 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2707 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2709 /* Where should this scroll bar be, pixelwise? */
2710 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2711 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2713 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2714 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2715 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2716 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2718 struct scroll_bar
*bar
;
2720 /* Does the scroll bar exist yet? */
2721 if (NILP (window
->vertical_scroll_bar
))
2722 bar
= x_scroll_bar_create (window
,
2723 pixel_top
, pixel_left
,
2724 pixel_width
, pixel_height
);
2727 /* It may just need to be moved and resized. */
2728 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2729 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2732 /* Set the scroll bar's current state, unless we're currently being
2734 if (NILP (bar
->dragging
))
2736 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2739 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2742 int start
= ((double) position
* top_range
) / whole
;
2743 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2745 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2749 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2753 /* The following three hooks are used when we're doing a thorough
2754 redisplay of the frame. We don't explicitly know which scroll bars
2755 are going to be deleted, because keeping track of when windows go
2756 away is a real pain - "Can you say set-window-configuration, boys
2757 and girls?" Instead, we just assert at the beginning of redisplay
2758 that *all* scroll bars are to be removed, and then save a scroll bar
2759 from the fiery pit when we actually redisplay its window. */
2761 /* Arrange for all scroll bars on FRAME to be removed at the next call
2762 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2763 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2765 XTcondemn_scroll_bars (frame
)
2768 /* The condemned list should be empty at this point; if it's not,
2769 then the rest of Emacs isn't using the condemn/redeem/judge
2770 protocol correctly. */
2771 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2774 /* Move them all to the "condemned" list. */
2775 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2776 FRAME_SCROLL_BARS (frame
) = Qnil
;
2779 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2780 Note that WINDOW isn't necessarily condemned at all. */
2782 XTredeem_scroll_bar (window
)
2783 struct window
*window
;
2785 struct scroll_bar
*bar
;
2787 /* We can't redeem this window's scroll bar if it doesn't have one. */
2788 if (NILP (window
->vertical_scroll_bar
))
2791 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2793 /* Unlink it from the condemned list. */
2795 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2797 if (NILP (bar
->prev
))
2799 /* If the prev pointer is nil, it must be the first in one of
2801 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2802 /* It's not condemned. Everything's fine. */
2804 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2805 window
->vertical_scroll_bar
))
2806 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2808 /* If its prev pointer is nil, it must be at the front of
2809 one or the other! */
2813 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2815 if (! NILP (bar
->next
))
2816 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2818 bar
->next
= FRAME_SCROLL_BARS (f
);
2820 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2821 if (! NILP (bar
->next
))
2822 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2826 /* Remove all scroll bars on FRAME that haven't been saved since the
2827 last call to `*condemn_scroll_bars_hook'. */
2829 XTjudge_scroll_bars (f
)
2832 Lisp_Object bar
, next
;
2834 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2836 /* Clear out the condemned list now so we won't try to process any
2837 more events on the hapless scroll bars. */
2838 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2840 for (; ! NILP (bar
); bar
= next
)
2842 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2844 x_scroll_bar_remove (b
);
2847 b
->next
= b
->prev
= Qnil
;
2850 /* Now there should be no references to the condemned scroll bars,
2851 and they should get garbage-collected. */
2855 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2857 This may be called from a signal handler, so we have to ignore GC
2860 x_scroll_bar_expose (bar
, event
)
2861 struct scroll_bar
*bar
;
2864 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2865 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2866 GC gc
= f
->output_data
.x
->normal_gc
;
2870 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2872 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2873 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2875 /* x, y, width, height */
2876 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2881 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2882 is set to something other than no_event, it is enqueued.
2884 This may be called from a signal handler, so we have to ignore GC
2887 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2888 struct scroll_bar
*bar
;
2890 struct input_event
*emacs_event
;
2892 if (! GC_WINDOWP (bar
->window
))
2895 emacs_event
->kind
= scroll_bar_click
;
2896 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2897 emacs_event
->modifiers
2898 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2899 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2900 event
->xbutton
.state
)
2901 | (event
->type
== ButtonRelease
2904 emacs_event
->frame_or_window
= bar
->window
;
2905 emacs_event
->timestamp
= event
->xbutton
.time
;
2908 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2910 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2911 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2914 if (y
> top_range
) y
= top_range
;
2916 if (y
< XINT (bar
->start
))
2917 emacs_event
->part
= scroll_bar_above_handle
;
2918 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2919 emacs_event
->part
= scroll_bar_handle
;
2921 emacs_event
->part
= scroll_bar_below_handle
;
2923 /* Just because the user has clicked on the handle doesn't mean
2924 they want to drag it. Lisp code needs to be able to decide
2925 whether or not we're dragging. */
2927 /* If the user has just clicked on the handle, record where they're
2929 if (event
->type
== ButtonPress
2930 && emacs_event
->part
== scroll_bar_handle
)
2931 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2934 /* If the user has released the handle, set it to its final position. */
2935 if (event
->type
== ButtonRelease
2936 && ! NILP (bar
->dragging
))
2938 int new_start
= y
- XINT (bar
->dragging
);
2939 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2941 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2942 bar
->dragging
= Qnil
;
2945 /* Same deal here as the other #if 0. */
2947 /* Clicks on the handle are always reported as occurring at the top of
2949 if (emacs_event
->part
== scroll_bar_handle
)
2950 emacs_event
->x
= bar
->start
;
2952 XSETINT (emacs_event
->x
, y
);
2954 XSETINT (emacs_event
->x
, y
);
2957 XSETINT (emacs_event
->y
, top_range
);
2961 /* Handle some mouse motion while someone is dragging the scroll bar.
2963 This may be called from a signal handler, so we have to ignore GC
2966 x_scroll_bar_note_movement (bar
, event
)
2967 struct scroll_bar
*bar
;
2970 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
2972 last_mouse_movement_time
= event
->xmotion
.time
;
2975 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2977 /* If we're dragging the bar, display it. */
2978 if (! GC_NILP (bar
->dragging
))
2980 /* Where should the handle be now? */
2981 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2983 if (new_start
!= XINT (bar
->start
))
2985 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2987 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2991 /* Call XQueryPointer so we'll get an event the next time the mouse
2992 moves and we can see *still* on the same position. */
2995 Window dummy_window
;
2997 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2998 &dummy_window
, &dummy_window
,
2999 &dummy
, &dummy
, &dummy
, &dummy
,
3000 (unsigned int *) &dummy
);
3004 /* Return information to the user about the current position of the mouse
3005 on the scroll bar. */
3007 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3009 Lisp_Object
*bar_window
;
3010 enum scroll_bar_part
*part
;
3012 unsigned long *time
;
3014 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3015 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3016 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3018 Window dummy_window
;
3020 unsigned int dummy_mask
;
3024 /* Get the mouse's position relative to the scroll bar window, and
3026 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3028 /* Root, child, root x and root y. */
3029 &dummy_window
, &dummy_window
,
3030 &dummy_coord
, &dummy_coord
,
3032 /* Position relative to scroll bar. */
3035 /* Mouse buttons and modifier keys. */
3041 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3043 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3045 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3047 if (! NILP (bar
->dragging
))
3048 win_y
-= XINT (bar
->dragging
);
3052 if (win_y
> top_range
)
3056 *bar_window
= bar
->window
;
3058 if (! NILP (bar
->dragging
))
3059 *part
= scroll_bar_handle
;
3060 else if (win_y
< XINT (bar
->start
))
3061 *part
= scroll_bar_above_handle
;
3062 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3063 *part
= scroll_bar_handle
;
3065 *part
= scroll_bar_below_handle
;
3067 XSETINT (*x
, win_y
);
3068 XSETINT (*y
, top_range
);
3071 last_mouse_scroll_bar
= Qnil
;
3074 *time
= last_mouse_movement_time
;
3080 /* The screen has been cleared so we may have changed foreground or
3081 background colors, and the scroll bars may need to be redrawn.
3082 Clear out the scroll bars, and ask for expose events, so we can
3085 x_scroll_bar_clear (f
)
3090 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3091 bar
= XSCROLL_BAR (bar
)->next
)
3092 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3096 /* This processes Expose events from the menubar specific X event
3097 loop in xmenu.c. This allows to redisplay the frame if necessary
3098 when handling menubar or popup items. */
3101 process_expose_from_menu (event
)
3105 struct x_display_info
*dpyinfo
;
3109 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3110 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3113 if (f
->async_visible
== 0)
3115 f
->async_visible
= 1;
3116 f
->async_iconified
= 0;
3117 SET_FRAME_GARBAGED (f
);
3121 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3122 event
.xexpose
.x
, event
.xexpose
.y
,
3123 event
.xexpose
.width
, event
.xexpose
.height
);
3128 struct scroll_bar
*bar
3129 = x_window_to_scroll_bar (event
.xexpose
.window
);
3132 x_scroll_bar_expose (bar
, &event
);
3138 /* Define a queue to save up SelectionRequest events for later handling. */
3140 struct selection_event_queue
3143 struct selection_event_queue
*next
;
3146 static struct selection_event_queue
*queue
;
3148 /* Nonzero means queue up certain events--don't process them yet. */
3149 static int x_queue_selection_requests
;
3151 /* Queue up an X event *EVENT, to be processed later. */
3154 x_queue_event (f
, event
)
3158 struct selection_event_queue
*queue_tmp
3159 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3161 if (queue_tmp
!= NULL
)
3163 queue_tmp
->event
= *event
;
3164 queue_tmp
->next
= queue
;
3169 /* Take all the queued events and put them back
3170 so that they get processed afresh. */
3173 x_unqueue_events (display
)
3176 while (queue
!= NULL
)
3178 struct selection_event_queue
*queue_tmp
= queue
;
3179 XPutBackEvent (display
, &queue_tmp
->event
);
3180 queue
= queue_tmp
->next
;
3181 free ((char *)queue_tmp
);
3185 /* Start queuing SelectionRequest events. */
3188 x_start_queuing_selection_requests (display
)
3191 x_queue_selection_requests
++;
3194 /* Stop queuing SelectionRequest events. */
3197 x_stop_queuing_selection_requests (display
)
3200 x_queue_selection_requests
--;
3201 x_unqueue_events (display
);
3204 /* The main X event-reading loop - XTread_socket. */
3206 /* Timestamp of enter window event. This is only used by XTread_socket,
3207 but we have to put it out here, since static variables within functions
3208 sometimes don't work. */
3209 static Time enter_timestamp
;
3211 /* This holds the state XLookupString needs to implement dead keys
3212 and other tricks known as "compose processing". _X Window System_
3213 says that a portable program can't use this, but Stephen Gildea assures
3214 me that letting the compiler initialize it to zeros will work okay.
3216 This must be defined outside of XTread_socket, for the same reasons
3217 given for enter_timestamp, above. */
3218 static XComposeStatus compose_status
;
3220 /* Record the last 100 characters stored
3221 to help debug the loss-of-chars-during-GC problem. */
3222 static int temp_index
;
3223 static short temp_buffer
[100];
3225 /* Set this to nonzero to fake an "X I/O error"
3226 on a particular display. */
3227 struct x_display_info
*XTread_socket_fake_io_error
;
3229 /* When we find no input here, we occasionally do a no-op command
3230 to verify that the X server is still running and we can still talk with it.
3231 We try all the open displays, one by one.
3232 This variable is used for cycling thru the displays. */
3233 static struct x_display_info
*next_noop_dpyinfo
;
3235 /* Read events coming from the X server.
3236 This routine is called by the SIGIO handler.
3237 We return as soon as there are no more events to be read.
3239 Events representing keys are stored in buffer BUFP,
3240 which can hold up to NUMCHARS characters.
3241 We return the number of characters stored into the buffer,
3242 thus pretending to be `read'.
3244 WAITP is nonzero if we should block until input arrives.
3245 EXPECTED is nonzero if the caller knows input is available. */
3248 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3250 register struct input_event
*bufp
;
3251 register int numchars
;
3258 int items_pending
; /* How many items are in the X queue. */
3261 int event_found
= 0;
3264 struct x_display_info
*dpyinfo
;
3266 if (interrupt_input_blocked
)
3268 interrupt_input_pending
= 1;
3272 interrupt_input_pending
= 0;
3275 /* So people can tell when we have read the available input. */
3276 input_signal_count
++;
3279 abort (); /* Don't think this happens. */
3281 /* Find the display we are supposed to read input for.
3282 It's the one communicating on descriptor SD. */
3283 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3285 #if 0 /* This ought to be unnecessary; let's verify it. */
3287 /* If available, Xlib uses FIOSNBIO to make the socket
3288 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3289 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3290 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3291 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3292 #endif /* ! defined (FIOSNBIO) */
3295 #if 0 /* This code can't be made to work, with multiple displays,
3296 and appears not to be used on any system any more.
3297 Also keyboard.c doesn't turn O_NDELAY on and off
3298 for X connections. */
3301 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3303 extern int read_alarm_should_throw
;
3304 read_alarm_should_throw
= 1;
3305 XPeekEvent (dpyinfo
->display
, &event
);
3306 read_alarm_should_throw
= 0;
3308 #endif /* HAVE_SELECT */
3312 /* For debugging, this gives a way to fake an I/O error. */
3313 if (dpyinfo
== XTread_socket_fake_io_error
)
3315 XTread_socket_fake_io_error
= 0;
3316 x_io_error_quitter (dpyinfo
->display
);
3319 while (XPending (dpyinfo
->display
) != 0)
3321 XNextEvent (dpyinfo
->display
, &event
);
3328 if (event
.xclient
.message_type
3329 == dpyinfo
->Xatom_wm_protocols
3330 && event
.xclient
.format
== 32)
3332 if (event
.xclient
.data
.l
[0]
3333 == dpyinfo
->Xatom_wm_take_focus
)
3335 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3336 /* Since we set WM_TAKE_FOCUS, we must call
3337 XSetInputFocus explicitly. But not if f is null,
3338 since that might be an event for a deleted frame. */
3340 XSetInputFocus (event
.xclient
.display
,
3341 event
.xclient
.window
,
3342 RevertToPointerRoot
,
3343 event
.xclient
.data
.l
[1]);
3344 /* Not certain about handling scroll bars here */
3346 else if (event
.xclient
.data
.l
[0]
3347 == dpyinfo
->Xatom_wm_save_yourself
)
3349 /* Save state modify the WM_COMMAND property to
3350 something which can reinstate us. This notifies
3351 the session manager, who's looking for such a
3352 PropertyNotify. Can restart processing when
3353 a keyboard or mouse event arrives. */
3356 f
= x_top_window_to_frame (dpyinfo
,
3357 event
.xclient
.window
);
3359 /* This is just so we only give real data once
3360 for a single Emacs process. */
3361 if (f
== selected_frame
)
3362 XSetCommand (FRAME_X_DISPLAY (f
),
3363 event
.xclient
.window
,
3364 initial_argv
, initial_argc
);
3366 XSetCommand (FRAME_X_DISPLAY (f
),
3367 event
.xclient
.window
,
3371 else if (event
.xclient
.data
.l
[0]
3372 == dpyinfo
->Xatom_wm_delete_window
)
3375 = x_any_window_to_frame (dpyinfo
,
3376 event
.xclient
.window
);
3383 bufp
->kind
= delete_window_event
;
3384 XSETFRAME (bufp
->frame_or_window
, f
);
3392 else if (event
.xclient
.message_type
3393 == dpyinfo
->Xatom_wm_configure_denied
)
3396 else if (event
.xclient
.message_type
3397 == dpyinfo
->Xatom_wm_window_moved
)
3401 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3403 new_x
= event
.xclient
.data
.s
[0];
3404 new_y
= event
.xclient
.data
.s
[1];
3408 f
->output_data
.x
->left_pos
= new_x
;
3409 f
->output_data
.x
->top_pos
= new_y
;
3412 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3413 else if (event
.xclient
.message_type
3414 == dpyinfo
->Xatom_editres
)
3417 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3418 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3421 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3425 case SelectionNotify
:
3426 #ifdef USE_X_TOOLKIT
3427 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3429 #endif /* not USE_X_TOOLKIT */
3430 x_handle_selection_notify (&event
);
3433 case SelectionClear
: /* Someone has grabbed ownership. */
3434 #ifdef USE_X_TOOLKIT
3435 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3437 #endif /* USE_X_TOOLKIT */
3439 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3444 bufp
->kind
= selection_clear_event
;
3445 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3446 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3447 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3455 case SelectionRequest
: /* Someone wants our selection. */
3456 #ifdef USE_X_TOOLKIT
3457 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3459 #endif /* USE_X_TOOLKIT */
3460 if (x_queue_selection_requests
)
3461 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3465 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3470 bufp
->kind
= selection_request_event
;
3471 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3472 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3473 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3474 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3475 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3476 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3484 case PropertyNotify
:
3485 #ifdef USE_X_TOOLKIT
3486 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3488 #endif /* not USE_X_TOOLKIT */
3489 x_handle_property_notify (&event
);
3492 case ReparentNotify
:
3493 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3497 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
3498 x_real_positions (f
, &x
, &y
);
3499 f
->output_data
.x
->left_pos
= x
;
3500 f
->output_data
.x
->top_pos
= y
;
3505 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3508 if (f
->async_visible
== 0)
3510 f
->async_visible
= 1;
3511 f
->async_iconified
= 0;
3512 SET_FRAME_GARBAGED (f
);
3515 dumprectangle (x_window_to_frame (dpyinfo
,
3516 event
.xexpose
.window
),
3517 event
.xexpose
.x
, event
.xexpose
.y
,
3518 event
.xexpose
.width
, event
.xexpose
.height
);
3522 struct scroll_bar
*bar
3523 = x_window_to_scroll_bar (event
.xexpose
.window
);
3526 x_scroll_bar_expose (bar
, &event
);
3527 #ifdef USE_X_TOOLKIT
3530 #endif /* USE_X_TOOLKIT */
3534 case GraphicsExpose
: /* This occurs when an XCopyArea's
3535 source area was obscured or not
3537 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3541 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3542 event
.xgraphicsexpose
.width
,
3543 event
.xgraphicsexpose
.height
);
3545 #ifdef USE_X_TOOLKIT
3548 #endif /* USE_X_TOOLKIT */
3551 case NoExpose
: /* This occurs when an XCopyArea's
3552 source area was completely
3557 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3558 if (f
) /* F may no longer exist if
3559 the frame was deleted. */
3561 /* While a frame is unmapped, display generation is
3562 disabled; you don't want to spend time updating a
3563 display that won't ever be seen. */
3564 f
->async_visible
= 0;
3565 /* We can't distinguish, from the event, whether the window
3566 has become iconified or invisible. So assume, if it
3567 was previously visible, than now it is iconified.
3568 We depend on x_make_frame_invisible to mark it iconified. */
3569 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3570 f
->async_iconified
= 1;
3572 bufp
->kind
= iconify_event
;
3573 XSETFRAME (bufp
->frame_or_window
, f
);
3578 #ifdef USE_X_TOOLKIT
3580 #endif /* USE_X_TOOLKIT */
3584 /* We use x_top_window_to_frame because map events can come
3585 for subwindows and they don't mean that the frame is visible. */
3586 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
3589 f
->async_visible
= 1;
3590 f
->async_iconified
= 0;
3592 /* wait_reading_process_input will notice this and update
3593 the frame's display structures. */
3594 SET_FRAME_GARBAGED (f
);
3598 bufp
->kind
= deiconify_event
;
3599 XSETFRAME (bufp
->frame_or_window
, f
);
3605 /* Force a redisplay sooner or later
3606 to update the frame titles
3607 in case this is the second frame. */
3608 record_asynch_buffer_change ();
3610 #ifdef USE_X_TOOLKIT
3612 #endif /* USE_X_TOOLKIT */
3615 /* Turn off processing if we become fully obscured. */
3616 case VisibilityNotify
:
3620 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
3624 KeySym keysym
, orig_keysym
;
3625 /* al%imercury@uunet.uu.net says that making this 81 instead of
3626 80 fixed a bug whereby meta chars made his Emacs hang. */
3627 unsigned char copy_buffer
[81];
3631 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3632 extra_keyboard_modifiers
);
3633 modifiers
= event
.xkey
.state
;
3635 /* This will have to go some day... */
3637 /* make_lispy_event turns chars into control chars.
3638 Don't do it here because XLookupString is too eager. */
3639 event
.xkey
.state
&= ~ControlMask
;
3640 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
3641 | dpyinfo
->super_mod_mask
3642 | dpyinfo
->hyper_mod_mask
3643 | dpyinfo
->alt_mod_mask
);
3645 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3646 80, &keysym
, &compose_status
);
3648 orig_keysym
= keysym
;
3652 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3653 || keysym
== XK_Delete
3654 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3655 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3657 /* This recognizes the "extended function keys".
3658 It seems there's no cleaner way.
3659 Test IsModifierKey to avoid handling mode_switch
3661 || ((unsigned) (keysym
) >= XK_Select
3662 && (unsigned)(keysym
) < XK_KP_Space
)
3664 #ifdef XK_dead_circumflex
3665 || orig_keysym
== XK_dead_circumflex
3667 #ifdef XK_dead_grave
3668 || orig_keysym
== XK_dead_grave
3670 #ifdef XK_dead_tilde
3671 || orig_keysym
== XK_dead_tilde
3673 #ifdef XK_dead_diaeresis
3674 || orig_keysym
== XK_dead_diaeresis
3676 #ifdef XK_dead_macron
3677 || orig_keysym
== XK_dead_macron
3679 #ifdef XK_dead_degree
3680 || orig_keysym
== XK_dead_degree
3682 #ifdef XK_dead_acute
3683 || orig_keysym
== XK_dead_acute
3685 #ifdef XK_dead_cedilla
3686 || orig_keysym
== XK_dead_cedilla
3688 #ifdef XK_dead_breve
3689 || orig_keysym
== XK_dead_breve
3691 #ifdef XK_dead_ogonek
3692 || orig_keysym
== XK_dead_ogonek
3694 #ifdef XK_dead_caron
3695 || orig_keysym
== XK_dead_caron
3697 #ifdef XK_dead_doubleacute
3698 || orig_keysym
== XK_dead_doubleacute
3700 #ifdef XK_dead_abovedot
3701 || orig_keysym
== XK_dead_abovedot
3703 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3704 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3705 /* Any "vendor-specific" key is ok. */
3706 || (orig_keysym
& (1 << 28)))
3707 && ! (IsModifierKey (orig_keysym
)
3709 #ifdef XK_Mode_switch
3710 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3713 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3715 #endif /* not HAVE_X11R5 */
3718 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3720 temp_buffer
[temp_index
++] = keysym
;
3721 bufp
->kind
= non_ascii_keystroke
;
3722 bufp
->code
= keysym
;
3723 XSETFRAME (bufp
->frame_or_window
, f
);
3725 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3727 bufp
->timestamp
= event
.xkey
.time
;
3732 else if (numchars
> nbytes
)
3736 for (i
= 0; i
< nbytes
; i
++)
3738 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3740 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3741 bufp
->kind
= ascii_keystroke
;
3742 bufp
->code
= copy_buffer
[i
];
3743 XSETFRAME (bufp
->frame_or_window
, f
);
3745 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3747 bufp
->timestamp
= event
.xkey
.time
;
3762 /* Here's a possible interpretation of the whole
3763 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3764 FocusIn event, you have to get a FocusOut event before you
3765 relinquish the focus. If you haven't received a FocusIn event,
3766 then a mere LeaveNotify is enough to free you. */
3769 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3771 if (event
.xcrossing
.focus
) /* Entered Window */
3773 /* Avoid nasty pop/raise loops. */
3774 if (f
&& (!(f
->auto_raise
)
3776 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3778 x_new_focus_frame (dpyinfo
, f
);
3779 enter_timestamp
= event
.xcrossing
.time
;
3782 else if (f
== dpyinfo
->x_focus_frame
)
3783 x_new_focus_frame (dpyinfo
, 0);
3784 /* EnterNotify counts as mouse movement,
3785 so update things that depend on mouse position. */
3787 note_mouse_movement (f
, &event
.xmotion
);
3788 #ifdef USE_X_TOOLKIT
3790 #endif /* USE_X_TOOLKIT */
3794 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3795 if (event
.xfocus
.detail
!= NotifyPointer
)
3796 dpyinfo
->x_focus_event_frame
= f
;
3798 x_new_focus_frame (dpyinfo
, f
);
3799 #ifdef USE_X_TOOLKIT
3801 #endif /* USE_X_TOOLKIT */
3806 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3809 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3810 /* If we move outside the frame,
3811 then we're certainly no longer on any text in the frame. */
3812 clear_mouse_face (dpyinfo
);
3814 if (event
.xcrossing
.focus
)
3815 x_mouse_leave (dpyinfo
);
3818 if (f
== dpyinfo
->x_focus_event_frame
)
3819 dpyinfo
->x_focus_event_frame
= 0;
3820 if (f
== dpyinfo
->x_focus_frame
)
3821 x_new_focus_frame (dpyinfo
, 0);
3824 #ifdef USE_X_TOOLKIT
3826 #endif /* USE_X_TOOLKIT */
3830 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3831 if (event
.xfocus
.detail
!= NotifyPointer
3832 && f
== dpyinfo
->x_focus_event_frame
)
3833 dpyinfo
->x_focus_event_frame
= 0;
3834 if (f
&& f
== dpyinfo
->x_focus_frame
)
3835 x_new_focus_frame (dpyinfo
, 0);
3836 #ifdef USE_X_TOOLKIT
3838 #endif /* USE_X_TOOLKIT */
3843 if (dpyinfo
->grabbed
&& last_mouse_frame
3844 && FRAME_LIVE_P (last_mouse_frame
))
3845 f
= last_mouse_frame
;
3847 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3849 note_mouse_movement (f
, &event
.xmotion
);
3852 struct scroll_bar
*bar
3853 = x_window_to_scroll_bar (event
.xmotion
.window
);
3856 x_scroll_bar_note_movement (bar
, &event
);
3858 /* If we move outside the frame,
3859 then we're certainly no longer on any text in the frame. */
3860 clear_mouse_face (dpyinfo
);
3863 #ifdef USE_X_TOOLKIT
3865 #endif /* USE_X_TOOLKIT */
3868 case ConfigureNotify
:
3869 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
3871 #ifdef USE_X_TOOLKIT
3872 && (event
.xconfigure
.window
== XtWindow (f
->output_data
.x
->widget
))
3876 #ifndef USE_X_TOOLKIT
3877 /* In the toolkit version, change_frame_size
3878 is called by the code that handles resizing
3879 of the EmacsFrame widget. */
3881 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3882 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3884 /* Even if the number of character rows and columns has
3885 not changed, the font size may have changed, so we need
3886 to check the pixel dimensions as well. */
3887 if (columns
!= f
->width
3888 || rows
!= f
->height
3889 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
3890 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
3892 change_frame_size (f
, rows
, columns
, 0, 1);
3893 SET_FRAME_GARBAGED (f
);
3897 /* Formerly, in the USE_X_TOOLKIT version,
3898 we did not test send_event here. */
3900 #ifndef USE_X_TOOLKIT
3901 && ! event
.xconfigure
.send_event
3908 /* Find the position of the outside upper-left corner of
3909 the window, in the root coordinate system. Don't
3910 refer to the parent window here; we may be processing
3911 this event after the window manager has changed our
3912 parent, but before we have reached the ReparentNotify. */
3913 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3915 /* From-window, to-window. */
3916 event
.xconfigure
.window
,
3917 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3919 /* From-position, to-position. */
3920 -event
.xconfigure
.border_width
,
3921 -event
.xconfigure
.border_width
,
3926 event
.xconfigure
.x
= win_x
;
3927 event
.xconfigure
.y
= win_y
;
3930 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
3931 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
3932 f
->output_data
.x
->left_pos
= event
.xconfigure
.x
;
3933 f
->output_data
.x
->top_pos
= event
.xconfigure
.y
;
3935 /* What we have now is the position of Emacs's own window.
3936 Convert that to the position of the window manager window. */
3939 x_real_positions (f
, &x
, &y
);
3940 f
->output_data
.x
->left_pos
= x
;
3941 f
->output_data
.x
->top_pos
= y
;
3942 /* Formerly we did not do this in the USE_X_TOOLKIT
3943 version. Let's try making them the same. */
3944 /* #ifndef USE_X_TOOLKIT */
3945 if (y
!= event
.xconfigure
.y
)
3947 /* Since the WM decorations come below top_pos now,
3948 we must put them below top_pos in the future. */
3949 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3950 x_wm_set_size_hint (f
, (long) 0, 0);
3955 #ifdef USE_X_TOOLKIT
3964 /* If we decide we want to generate an event to be seen
3965 by the rest of Emacs, we put it here. */
3966 struct input_event emacs_event
;
3967 emacs_event
.kind
= no_event
;
3969 bzero (&compose_status
, sizeof (compose_status
));
3971 if (dpyinfo
->grabbed
&& last_mouse_frame
3972 && FRAME_LIVE_P (last_mouse_frame
))
3973 f
= last_mouse_frame
;
3975 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
3979 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
3980 construct_mouse_click (&emacs_event
, &event
, f
);
3984 struct scroll_bar
*bar
3985 = x_window_to_scroll_bar (event
.xbutton
.window
);
3988 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3991 if (event
.type
== ButtonPress
)
3993 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
3994 last_mouse_frame
= f
;
3998 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4001 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4003 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4009 #ifdef USE_X_TOOLKIT
4010 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4011 /* For a down-event in the menu bar,
4012 don't pass it to Xt right now.
4013 Instead, save it away
4014 and we will pass it to Xt from kbd_buffer_get_event.
4015 That way, we can run some Lisp code first. */
4016 if (f
&& event
.type
== ButtonPress
)
4018 if (f
->output_data
.x
->saved_button_event
== 0)
4019 f
->output_data
.x
->saved_button_event
4020 = (XButtonEvent
*) xmalloc (sizeof (XButtonEvent
));
4021 bcopy (&event
, f
->output_data
.x
->saved_button_event
,
4022 sizeof (XButtonEvent
));
4025 bufp
->kind
= menu_bar_activate_event
;
4026 XSETFRAME (bufp
->frame_or_window
, f
);
4034 #endif /* USE_X_TOOLKIT */
4038 case CirculateNotify
:
4040 case CirculateRequest
:
4044 /* Someone has changed the keyboard mapping - update the
4046 switch (event
.xmapping
.request
)
4048 case MappingModifier
:
4049 x_find_modifier_meanings (dpyinfo
);
4050 /* This is meant to fall through. */
4051 case MappingKeyboard
:
4052 XRefreshKeyboardMapping (&event
.xmapping
);
4054 #ifdef USE_X_TOOLKIT
4056 #endif /* USE_X_TOOLKIT */
4060 #ifdef USE_X_TOOLKIT
4063 XtDispatchEvent (&event
);
4065 #endif /* USE_X_TOOLKIT */
4071 /* On some systems, an X bug causes Emacs to get no more events
4072 when the window is destroyed. Detect that. (1994.) */
4075 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4076 One XNOOP in 100 loops will make Emacs terminate.
4077 B. Bretthauer, 1994 */
4079 if (x_noop_count
>= 100)
4083 if (next_noop_dpyinfo
== 0)
4084 next_noop_dpyinfo
= x_display_list
;
4086 XNoOp (next_noop_dpyinfo
->display
);
4088 /* Each time we get here, cycle through the displays now open. */
4089 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4093 /* If the focus was just given to an autoraising frame,
4095 /* ??? This ought to be able to handle more than one such frame. */
4096 if (pending_autoraise_frame
)
4098 x_raise_frame (pending_autoraise_frame
);
4099 pending_autoraise_frame
= 0;
4106 /* Drawing the cursor. */
4109 /* Draw a hollow box cursor on frame F at X, Y.
4110 Don't change the inside of the box. */
4113 x_draw_box (f
, x
, y
)
4117 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4118 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4119 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4120 int height
= f
->output_data
.x
->line_height
;
4122 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4123 f
->output_data
.x
->cursor_gc
,
4124 left
, top
, width
- 1, height
- 1);
4127 /* Clear the cursor of frame F to background color,
4128 and mark the cursor as not shown.
4129 This is used when the text where the cursor is
4130 is about to be rewritten. */
4138 if (! FRAME_VISIBLE_P (f
)
4139 || f
->phys_cursor_x
< 0)
4142 x_display_cursor (f
, 0);
4143 f
->phys_cursor_x
= -1;
4146 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4147 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4151 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4158 CHAR_TO_PIXEL_COL (f
, column
),
4159 CHAR_TO_PIXEL_ROW (f
, row
),
4160 &glyph
, 1, highlight
, 0);
4164 x_display_bar_cursor (f
, on
, x
, y
)
4169 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4171 /* This is pointless on invisible frames, and dangerous on garbaged
4172 frames; in the latter case, the frame may be in the midst of
4173 changing its size, and x and y may be off the frame. */
4174 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4177 if (! on
&& f
->phys_cursor_x
< 0)
4180 /* If there is anything wrong with the current cursor state, remove it. */
4181 if (f
->phys_cursor_x
>= 0
4183 || f
->phys_cursor_x
!= x
4184 || f
->phys_cursor_y
!= y
4185 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4187 /* Erase the cursor by redrawing the character underneath it. */
4188 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4189 f
->phys_cursor_glyph
,
4190 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4191 f
->phys_cursor_x
= -1;
4194 /* If we now need a cursor in the new place or in the new form, do it so. */
4196 && (f
->phys_cursor_x
< 0
4197 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4199 f
->phys_cursor_glyph
4200 = ((current_glyphs
->enable
[y
]
4201 && x
< current_glyphs
->used
[y
])
4202 ? current_glyphs
->glyphs
[y
][x
]
4204 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4205 f
->output_data
.x
->cursor_gc
,
4206 CHAR_TO_PIXEL_COL (f
, x
),
4207 CHAR_TO_PIXEL_ROW (f
, y
),
4208 max (f
->output_data
.x
->cursor_width
, 1),
4209 f
->output_data
.x
->line_height
);
4211 f
->phys_cursor_x
= x
;
4212 f
->phys_cursor_y
= y
;
4214 f
->output_data
.x
->current_cursor
= bar_cursor
;
4217 if (updating_frame
!= f
)
4218 XFlush (FRAME_X_DISPLAY (f
));
4222 /* Turn the displayed cursor of frame F on or off according to ON.
4223 If ON is nonzero, where to put the cursor is specified by X and Y. */
4226 x_display_box_cursor (f
, on
, x
, y
)
4231 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4233 /* This is pointless on invisible frames, and dangerous on garbaged
4234 frames; in the latter case, the frame may be in the midst of
4235 changing its size, and x and y may be off the frame. */
4236 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4239 /* If cursor is off and we want it off, return quickly. */
4240 if (!on
&& f
->phys_cursor_x
< 0)
4243 /* If cursor is currently being shown and we don't want it to be
4244 or it is in the wrong place,
4245 or we want a hollow box and it's not so, (pout!)
4247 if (f
->phys_cursor_x
>= 0
4249 || f
->phys_cursor_x
!= x
4250 || f
->phys_cursor_y
!= y
4251 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4252 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4254 int mouse_face_here
= 0;
4255 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4257 /* If the cursor is in the mouse face area, redisplay that when
4258 we clear the cursor. */
4259 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4261 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4262 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4263 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4265 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4266 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4267 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4268 /* Don't redraw the cursor's spot in mouse face
4269 if it is at the end of a line (on a newline).
4270 The cursor appears there, but mouse highlighting does not. */
4271 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4272 mouse_face_here
= 1;
4274 /* If the font is not as tall as a whole line,
4275 we must explicitly clear the line's whole height. */
4276 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4277 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4278 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4279 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4280 FONT_WIDTH (f
->output_data
.x
->font
),
4281 f
->output_data
.x
->line_height
, False
);
4282 /* Erase the cursor by redrawing the character underneath it. */
4283 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4284 f
->phys_cursor_glyph
,
4287 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4288 f
->phys_cursor_x
= -1;
4291 /* If we want to show a cursor,
4292 or we want a box cursor and it's not so,
4293 write it in the right place. */
4295 && (f
->phys_cursor_x
< 0
4296 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4297 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4299 f
->phys_cursor_glyph
4300 = ((current_glyphs
->enable
[y
]
4301 && x
< current_glyphs
->used
[y
])
4302 ? current_glyphs
->glyphs
[y
][x
]
4304 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4306 x_draw_box (f
, x
, y
);
4307 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4311 x_draw_single_glyph (f
, y
, x
,
4312 f
->phys_cursor_glyph
, 2);
4313 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4316 f
->phys_cursor_x
= x
;
4317 f
->phys_cursor_y
= y
;
4320 if (updating_frame
!= f
)
4321 XFlush (FRAME_X_DISPLAY (f
));
4324 /* Display the cursor on frame F, or clear it, according to ON.
4325 Use the position specified by curs_x and curs_y
4326 if we are doing an update of frame F now.
4327 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4330 x_display_cursor (f
, on
)
4336 /* If we're not updating, then don't change the physical cursor
4337 position. Just change (if appropriate) the style of display. */
4338 if (f
!= updating_frame
)
4340 curs_x
= FRAME_CURSOR_X (f
);
4341 curs_y
= FRAME_CURSOR_Y (f
);
4344 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4345 x_display_box_cursor (f
, on
, curs_x
, curs_y
);
4346 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4347 x_display_bar_cursor (f
, on
, curs_x
, curs_y
);
4349 /* Those are the only two we have implemented! */
4355 /* Display the cursor on frame F, or clear it, according to ON.
4356 Don't change the cursor's position. */
4358 x_update_cursor (f
, on
)
4364 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4365 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4366 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4367 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4369 /* Those are the only two we have implemented! */
4377 /* Refresh bitmap kitchen sink icon for frame F
4378 when we get an expose event for it. */
4383 /* Normally, the window manager handles this function. */
4386 /* Make the x-window of frame F use the gnu icon bitmap. */
4389 x_bitmap_icon (f
, file
)
4393 int mask
, bitmap_id
;
4396 if (FRAME_X_WINDOW (f
) == 0)
4399 /* Free up our existing icon bitmap if any. */
4400 if (f
->output_data
.x
->icon_bitmap
> 0)
4401 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4402 f
->output_data
.x
->icon_bitmap
= 0;
4405 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4408 /* Create the GNU bitmap if necessary. */
4409 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4410 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4411 = x_create_bitmap_from_data (f
, gnu_bits
,
4412 gnu_width
, gnu_height
);
4414 /* The first time we create the GNU bitmap,
4415 this increments the refcount one extra time.
4416 As a result, the GNU bitmap is never freed.
4417 That way, we don't have to worry about allocating it again. */
4418 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4420 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4423 x_wm_set_icon_pixmap (f
, bitmap_id
);
4424 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4430 /* Make the x-window of frame F use a rectangle with text.
4431 Use ICON_NAME as the text. */
4434 x_text_icon (f
, icon_name
)
4438 if (FRAME_X_WINDOW (f
) == 0)
4444 text
.value
= (unsigned char *) icon_name
;
4445 text
.encoding
= XA_STRING
;
4447 text
.nitems
= strlen (icon_name
);
4448 #ifdef USE_X_TOOLKIT
4449 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4451 #else /* not USE_X_TOOLKIT */
4452 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
4453 #endif /* not USE_X_TOOLKIT */
4455 #else /* not HAVE_X11R4 */
4456 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
4457 #endif /* not HAVE_X11R4 */
4459 if (f
->output_data
.x
->icon_bitmap
> 0)
4460 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4461 f
->output_data
.x
->icon_bitmap
= 0;
4462 x_wm_set_icon_pixmap (f
, 0);
4467 /* Handling X errors. */
4469 /* Handle the loss of connection to display DISPLAY. */
4472 x_connection_closed (display
, error_message
)
4474 char *error_message
;
4476 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4477 Lisp_Object frame
, tail
;
4479 /* Whatever we were in the middle of, we are going to throw out of it,
4480 so reassure various things that have error checks about being
4481 called with input blocked. */
4482 TOTALLY_UNBLOCK_INPUT
;
4487 /* First delete frames whose minibuffers are on frames
4488 that are on the dead display. */
4489 FOR_EACH_FRAME (tail
, frame
)
4491 Lisp_Object minibuf_frame
;
4493 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4494 if (FRAME_X_P (XFRAME (frame
))
4495 && FRAME_X_P (XFRAME (minibuf_frame
))
4496 && ! EQ (frame
, minibuf_frame
)
4497 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4498 Fdelete_frame (frame
, Qt
);
4501 /* Now delete all remaining frames on the dead display.
4502 We are now sure none of these is used as the minibuffer
4503 for another frame that we need to delete. */
4504 FOR_EACH_FRAME (tail
, frame
)
4505 if (FRAME_X_P (XFRAME (frame
))
4506 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4508 /* Set this to t so that Fdelete_frame won't get confused
4509 trying to find a replacement. */
4510 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
4511 Fdelete_frame (frame
, Qt
);
4514 x_delete_display (dpyinfo
);
4516 if (x_display_list
== 0)
4518 fprintf (stderr
, "%s", error_message
);
4519 shut_down_emacs (0, 0, Qnil
);
4523 /* Ordinary stack unwind doesn't deal with these. */
4525 sigunblock (sigmask (SIGIO
));
4527 sigunblock (sigmask (SIGALRM
));
4528 TOTALLY_UNBLOCK_INPUT
;
4530 error ("%s", error_message
);
4534 x_connection_signal (signalnum
) /* If we don't have an argument, */
4535 int signalnum
; /* some compilers complain in signal calls. */
4537 /* We really ought to close the connection to the display
4538 that actually failed.
4539 But do we actually get this signal ever with X11? */
4540 fprintf (stderr
, "X connection closed");
4541 shut_down_emacs (0, 0, Qnil
);
4545 /* This is the usual handler for X protocol errors.
4546 It kills all frames on the display that we got the error for.
4547 If that was the only one, it prints an error message and kills Emacs. */
4550 x_error_quitter (display
, error
)
4554 char buf
[256], buf1
[356];
4556 /* Note that there is no real way portable across R3/R4 to get the
4557 original error handler. */
4559 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4560 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4561 buf
, error
->request_code
);
4562 x_connection_closed (display
, buf1
);
4565 /* This is the handler for X IO errors, always.
4566 It kills all frames on the display that we lost touch with.
4567 If that was the only one, it prints an error message and kills Emacs. */
4570 x_io_error_quitter (display
)
4575 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4576 x_connection_closed (display
, buf
);
4579 /* A buffer for storing X error messages. */
4580 static char *x_caught_error_message
;
4581 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4583 /* An X error handler which stores the error message in
4584 x_caught_error_message. This is what's installed when
4585 x_catch_errors is in effect. */
4588 x_error_catcher (display
, error
)
4592 XGetErrorText (display
, error
->error_code
,
4593 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4597 /* Begin trapping X errors for display DPY. Actually we trap X errors
4598 for all displays, but DPY should be the display you are actually
4601 After calling this function, X protocol errors no longer cause
4602 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4604 Calling x_check_errors signals an Emacs error if an X error has
4605 occurred since the last call to x_catch_errors or x_check_errors.
4607 Calling x_uncatch_errors resumes the normal error handling. */
4609 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4612 x_catch_errors (dpy
)
4615 /* Make sure any errors from previous requests have been dealt with. */
4618 /* Set up the error buffer. */
4619 x_caught_error_message
4620 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4621 x_caught_error_message
[0] = '\0';
4623 /* Install our little error handler. */
4624 XSetErrorHandler (x_error_catcher
);
4627 /* If any X protocol errors have arrived since the last call to
4628 x_catch_errors or x_check_errors, signal an Emacs error using
4629 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4632 x_check_errors (dpy
, format
)
4636 /* Make sure to catch any errors incurred so far. */
4639 if (x_caught_error_message
[0])
4641 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4643 sprintf (buf
, format
, x_caught_error_message
);
4644 x_uncatch_errors (dpy
);
4649 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4652 x_had_errors_p (dpy
)
4655 /* Make sure to catch any errors incurred so far. */
4658 return x_caught_error_message
[0] != 0;
4661 /* Stop catching X protocol errors and let them make Emacs die. */
4664 x_uncatch_errors (dpy
)
4667 xfree (x_caught_error_message
);
4668 x_caught_error_message
= 0;
4669 XSetErrorHandler (x_error_quitter
);
4673 static unsigned int x_wire_count
;
4676 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4681 /* Changing the font of the frame. */
4683 /* Give frame F the font named FONTNAME as its default font, and
4684 return the full name of that font. FONTNAME may be a wildcard
4685 pattern; in that case, we choose some font that fits the pattern.
4686 The return value shows which font we chose. */
4689 x_new_font (f
, fontname
)
4691 register char *fontname
;
4694 int n_matching_fonts
;
4695 XFontStruct
*font_info
;
4698 /* Get a list of all the fonts that match this name. Once we
4699 have a list of matching fonts, we compare them against the fonts
4700 we already have by comparing font ids. */
4701 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4702 1024, &n_matching_fonts
);
4703 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4704 find any matches; font_names == 0 is the only clue. */
4706 n_matching_fonts
= 0;
4708 /* Don't just give up if n_matching_fonts is 0.
4709 Apparently there's a bug on Suns: XListFontsWithInfo can
4710 fail to find a font, but XLoadQueryFont may still find it. */
4712 /* See if we've already loaded a matching font. */
4713 already_loaded
= -1;
4714 if (n_matching_fonts
!= 0)
4718 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4719 for (j
= 0; j
< n_matching_fonts
; j
++)
4720 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4721 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4724 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4730 /* If we have, just return it from the table. */
4731 if (already_loaded
>= 0)
4732 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4733 /* Otherwise, load the font and add it to the table. */
4741 /* Try to find a character-cell font in the list. */
4743 /* A laudable goal, but this isn't how to do it. */
4744 for (i
= 0; i
< n_matching_fonts
; i
++)
4745 if (! font_info
[i
].per_char
)
4751 /* See comment above. */
4752 if (n_matching_fonts
!= 0)
4753 fontname
= font_names
[i
];
4755 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4758 /* Free the information from XListFonts. */
4759 if (n_matching_fonts
)
4760 XFreeFontNames (font_names
);
4764 /* Do we need to create the table? */
4765 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4767 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4768 FRAME_X_DISPLAY_INFO (f
)->font_table
4769 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4770 * sizeof (struct font_info
));
4772 /* Do we need to grow the table? */
4773 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4774 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4776 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4777 FRAME_X_DISPLAY_INFO (f
)->font_table
4778 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4779 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4780 * sizeof (struct font_info
)));
4783 /* Try to get the full name of FONT. Put it in full_name. */
4785 for (i
= 0; i
< font
->n_properties
; i
++)
4788 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4789 if (!strcmp (atom
, "FONT"))
4791 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4792 (Atom
) (font
->properties
[i
].card32
));
4796 /* Count the number of dashes in the "full name".
4797 If it is too few, this isn't really the font's full name,
4799 In X11R4, the fonts did not come with their canonical names
4817 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4818 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4819 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4821 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4823 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4824 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4825 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4828 fontname
= full_name
;
4831 /* Compute the scroll bar width in character columns. */
4832 if (f
->scroll_bar_pixel_width
> 0)
4834 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
4835 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4838 f
->scroll_bar_cols
= 2;
4840 /* Now make the frame display the given font. */
4841 if (FRAME_X_WINDOW (f
) != 0)
4843 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
4844 f
->output_data
.x
->font
->fid
);
4845 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
4846 f
->output_data
.x
->font
->fid
);
4847 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
4848 f
->output_data
.x
->font
->fid
);
4850 frame_update_line_height (f
);
4851 x_set_window_size (f
, 0, f
->width
, f
->height
);
4854 /* If we are setting a new frame's font for the first time,
4855 there are no faces yet, so this font's height is the line height. */
4856 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
4859 Lisp_Object lispy_name
;
4861 lispy_name
= build_string (fontname
);
4863 /* Free the information from XListFonts. The data
4864 we actually retain comes from XLoadQueryFont. */
4865 XFreeFontNames (font_names
);
4871 x_calc_absolute_position (f
)
4875 int win_x
= 0, win_y
= 0;
4876 int flags
= f
->output_data
.x
->size_hint_flags
;
4879 #ifdef USE_X_TOOLKIT
4880 this_window
= XtWindow (f
->output_data
.x
->widget
);
4882 this_window
= FRAME_X_WINDOW (f
);
4885 /* Find the position of the outside upper-left corner of
4886 the inner window, with respect to the outer window. */
4887 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4890 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4892 /* From-window, to-window. */
4894 f
->output_data
.x
->parent_desc
,
4896 /* From-position, to-position. */
4897 0, 0, &win_x
, &win_y
,
4904 /* Treat negative positions as relative to the leftmost bottommost
4905 position that fits on the screen. */
4906 if (flags
& XNegative
)
4907 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4908 - 2 * f
->output_data
.x
->border_width
- win_x
4910 + f
->output_data
.x
->left_pos
);
4912 if (flags
& YNegative
)
4913 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
4914 - 2 * f
->output_data
.x
->border_width
- win_y
4916 - (FRAME_EXTERNAL_MENU_BAR (f
)
4917 ? f
->output_data
.x
->menubar_height
: 0)
4918 + f
->output_data
.x
->top_pos
);
4919 /* The left_pos and top_pos
4920 are now relative to the top and left screen edges,
4921 so the flags should correspond. */
4922 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4925 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4926 to really change the position, and 0 when calling from
4927 x_make_frame_visible (in that case, XOFF and YOFF are the current
4928 position values). It is -1 when calling from x_set_frame_parameters,
4929 which means, do adjust for borders but don't change the gravity. */
4931 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4933 register int xoff
, yoff
;
4936 int modified_top
, modified_left
;
4938 if (change_gravity
> 0)
4940 f
->output_data
.x
->top_pos
= yoff
;
4941 f
->output_data
.x
->left_pos
= xoff
;
4942 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4944 f
->output_data
.x
->size_hint_flags
|= XNegative
;
4946 f
->output_data
.x
->size_hint_flags
|= YNegative
;
4947 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4949 x_calc_absolute_position (f
);
4952 x_wm_set_size_hint (f
, (long) 0, 0);
4954 /* It is a mystery why we need to add the border_width here
4955 when the frame is already visible, but experiment says we do. */
4956 modified_left
= f
->output_data
.x
->left_pos
;
4957 modified_top
= f
->output_data
.x
->top_pos
;
4958 if (change_gravity
!= 0)
4960 modified_left
+= f
->output_data
.x
->border_width
;
4961 modified_top
+= f
->output_data
.x
->border_width
;
4964 #ifdef USE_X_TOOLKIT
4965 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4966 modified_left
, modified_top
);
4967 #else /* not USE_X_TOOLKIT */
4968 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4969 modified_left
, modified_top
);
4970 #endif /* not USE_X_TOOLKIT */
4974 /* Call this to change the size of frame F's x-window.
4975 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4976 for this size change and subsequent size changes.
4977 Otherwise we leave the window gravity unchanged. */
4979 x_set_window_size (f
, change_gravity
, cols
, rows
)
4984 int pixelwidth
, pixelheight
;
4987 #ifdef USE_X_TOOLKIT
4990 /* The x and y position of the widget is clobbered by the
4991 call to XtSetValues within EmacsFrameSetCharSize.
4992 This is a real kludge, but I don't understand Xt so I can't
4993 figure out a correct fix. Can anyone else tell me? -- rms. */
4994 int xpos
= f
->output_data
.x
->widget
->core
.x
;
4995 int ypos
= f
->output_data
.x
->widget
->core
.y
;
4996 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
4997 f
->output_data
.x
->widget
->core
.x
= xpos
;
4998 f
->output_data
.x
->widget
->core
.y
= ypos
;
5002 #else /* not USE_X_TOOLKIT */
5006 check_frame_size (f
, &rows
, &cols
);
5007 f
->output_data
.x
->vertical_scroll_bar_extra
5008 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5010 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5011 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5012 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5013 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5014 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5016 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5017 x_wm_set_size_hint (f
, (long) 0, 0);
5019 XSync (FRAME_X_DISPLAY (f
), False
);
5020 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5021 pixelwidth
, pixelheight
);
5023 /* Now, strictly speaking, we can't be sure that this is accurate,
5024 but the window manager will get around to dealing with the size
5025 change request eventually, and we'll hear how it went when the
5026 ConfigureNotify event gets here.
5028 We could just not bother storing any of this information here,
5029 and let the ConfigureNotify event set everything up, but that
5030 might be kind of confusing to the lisp code, since size changes
5031 wouldn't be reported in the frame parameters until some random
5032 point in the future when the ConfigureNotify event arrives. */
5033 change_frame_size (f
, rows
, cols
, 0, 0);
5034 PIXEL_WIDTH (f
) = pixelwidth
;
5035 PIXEL_HEIGHT (f
) = pixelheight
;
5037 /* If cursor was outside the new size, mark it as off. */
5038 if (f
->phys_cursor_y
>= rows
5039 || f
->phys_cursor_x
>= cols
)
5041 f
->phys_cursor_x
= -1;
5042 f
->phys_cursor_y
= -1;
5045 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5046 receive in the ConfigureNotify event; if we get what we asked
5047 for, then the event won't cause the screen to become garbaged, so
5048 we have to make sure to do it here. */
5049 SET_FRAME_GARBAGED (f
);
5051 XFlush (FRAME_X_DISPLAY (f
));
5053 #endif /* not USE_X_TOOLKIT */
5056 /* Mouse warping. */
5059 x_set_mouse_position (f
, x
, y
)
5065 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5066 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5068 if (pix_x
< 0) pix_x
= 0;
5069 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5071 if (pix_y
< 0) pix_y
= 0;
5072 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5076 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5077 0, 0, 0, 0, pix_x
, pix_y
);
5081 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5084 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5090 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5091 0, 0, 0, 0, pix_x
, pix_y
);
5095 /* focus shifting, raising and lowering. */
5097 x_focus_on_frame (f
)
5100 #if 0 /* This proves to be unpleasant. */
5104 /* I don't think that the ICCCM allows programs to do things like this
5105 without the interaction of the window manager. Whatever you end up
5106 doing with this code, do it to x_unfocus_frame too. */
5107 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5108 RevertToPointerRoot
, CurrentTime
);
5116 /* Look at the remarks in x_focus_on_frame. */
5117 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5118 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5119 RevertToPointerRoot
, CurrentTime
);
5123 /* Raise frame F. */
5128 if (f
->async_visible
)
5131 #ifdef USE_X_TOOLKIT
5132 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5133 #else /* not USE_X_TOOLKIT */
5134 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5135 #endif /* not USE_X_TOOLKIT */
5136 XFlush (FRAME_X_DISPLAY (f
));
5141 /* Lower frame F. */
5146 if (f
->async_visible
)
5149 #ifdef USE_X_TOOLKIT
5150 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5151 #else /* not USE_X_TOOLKIT */
5152 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5153 #endif /* not USE_X_TOOLKIT */
5154 XFlush (FRAME_X_DISPLAY (f
));
5160 XTframe_raise_lower (f
, raise
)
5170 /* Change of visibility. */
5172 /* This tries to wait until the frame is really visible.
5173 However, if the window manager asks the user where to position
5174 the frame, this will return before the user finishes doing that.
5175 The frame will not actually be visible at that time,
5176 but it will become visible later when the window manager
5177 finishes with it. */
5179 x_make_frame_visible (f
)
5187 type
= x_icon_type (f
);
5189 x_bitmap_icon (f
, type
);
5191 if (! FRAME_VISIBLE_P (f
))
5193 /* We test FRAME_GARBAGED_P here to make sure we don't
5194 call x_set_offset a second time
5195 if we get to x_make_frame_visible a second time
5196 before the window gets really visible. */
5197 if (! FRAME_ICONIFIED_P (f
)
5198 && ! f
->output_data
.x
->asked_for_visible
)
5199 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5201 f
->output_data
.x
->asked_for_visible
= 1;
5203 if (! EQ (Vx_no_window_manager
, Qt
))
5204 x_wm_set_window_state (f
, NormalState
);
5205 #ifdef USE_X_TOOLKIT
5206 /* This was XtPopup, but that did nothing for an iconified frame. */
5207 XtMapWidget (f
->output_data
.x
->widget
);
5208 #else /* not USE_X_TOOLKIT */
5209 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5210 #endif /* not USE_X_TOOLKIT */
5211 #if 0 /* This seems to bring back scroll bars in the wrong places
5212 if the window configuration has changed. They seem
5213 to come back ok without this. */
5214 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5215 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5219 XFlush (FRAME_X_DISPLAY (f
));
5221 /* Synchronize to ensure Emacs knows the frame is visible
5222 before we do anything else. We do this loop with input not blocked
5223 so that incoming events are handled. */
5226 int count
= input_signal_count
;
5228 /* This must come after we set COUNT. */
5231 XSETFRAME (frame
, f
);
5236 /* Once we have handled input events,
5237 we should have received the MapNotify if one is coming.
5238 So if we have not got it yet, stop looping.
5239 Some window managers make their own decisions
5240 about visibility. */
5241 if (input_signal_count
!= count
)
5243 /* Machines that do polling rather than SIGIO have been observed
5244 to go into a busy-wait here. So we'll fake an alarm signal
5245 to let the handler know that there's something to be read.
5246 We used to raise a real alarm, but it seems that the handler
5247 isn't always enabled here. This is probably a bug. */
5248 if (input_polling_used ())
5250 /* It could be confusing if a real alarm arrives while processing
5251 the fake one. Turn it off and let the handler reset it. */
5253 input_poll_signal ();
5255 /* Once we have handled input events,
5256 we should have received the MapNotify if one is coming.
5257 So if we have not got it yet, stop looping.
5258 Some window managers make their own decisions
5259 about visibility. */
5260 if (input_signal_count
!= count
)
5263 FRAME_SAMPLE_VISIBILITY (f
);
5267 /* Change from mapped state to withdrawn state. */
5269 /* Make the frame visible (mapped and not iconified). */
5271 x_make_frame_invisible (f
)
5277 #ifdef USE_X_TOOLKIT
5278 /* Use the frame's outermost window, not the one we normally draw on. */
5279 window
= XtWindow (f
->output_data
.x
->widget
);
5280 #else /* not USE_X_TOOLKIT */
5281 window
= FRAME_X_WINDOW (f
);
5282 #endif /* not USE_X_TOOLKIT */
5284 /* Don't keep the highlight on an invisible frame. */
5285 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5286 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5288 #if 0/* This might add unreliability; I don't trust it -- rms. */
5289 if (! f
->async_visible
&& ! f
->async_iconified
)
5295 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5296 that the current position of the window is user-specified, rather than
5297 program-specified, so that when the window is mapped again, it will be
5298 placed at the same location, without forcing the user to position it
5299 by hand again (they have already done that once for this window.) */
5300 x_wm_set_size_hint (f
, (long) 0, 1);
5304 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5305 DefaultScreen (FRAME_X_DISPLAY (f
))))
5307 UNBLOCK_INPUT_RESIGNAL
;
5308 error ("Can't notify window manager of window withdrawal");
5310 #else /* ! defined (HAVE_X11R4) */
5312 /* Tell the window manager what we're going to do. */
5313 if (! EQ (Vx_no_window_manager
, Qt
))
5317 unmap
.xunmap
.type
= UnmapNotify
;
5318 unmap
.xunmap
.window
= window
;
5319 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5320 unmap
.xunmap
.from_configure
= False
;
5321 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5322 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5324 SubstructureRedirectMask
|SubstructureNotifyMask
,
5327 UNBLOCK_INPUT_RESIGNAL
;
5328 error ("Can't notify window manager of withdrawal");
5332 /* Unmap the window ourselves. Cheeky! */
5333 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5334 #endif /* ! defined (HAVE_X11R4) */
5336 /* We can't distinguish this from iconification
5337 just by the event that we get from the server.
5338 So we can't win using the usual strategy of letting
5339 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5340 and synchronize with the server to make sure we agree. */
5342 FRAME_ICONIFIED_P (f
) = 0;
5343 f
->async_visible
= 0;
5344 f
->async_iconified
= 0;
5351 /* Change window state from mapped to iconified. */
5360 /* Don't keep the highlight on an invisible frame. */
5361 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5362 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5364 if (f
->async_iconified
)
5369 type
= x_icon_type (f
);
5371 x_bitmap_icon (f
, type
);
5373 #ifdef USE_X_TOOLKIT
5375 if (! FRAME_VISIBLE_P (f
))
5377 if (! EQ (Vx_no_window_manager
, Qt
))
5378 x_wm_set_window_state (f
, IconicState
);
5379 /* This was XtPopup, but that did nothing for an iconified frame. */
5380 XtMapWidget (f
->output_data
.x
->widget
);
5385 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5386 XtWindow (f
->output_data
.x
->widget
),
5387 DefaultScreen (FRAME_X_DISPLAY (f
)));
5391 error ("Can't notify window manager of iconification");
5393 f
->async_iconified
= 1;
5396 XFlush (FRAME_X_DISPLAY (f
));
5398 #else /* not USE_X_TOOLKIT */
5400 /* Make sure the X server knows where the window should be positioned,
5401 in case the user deiconifies with the window manager. */
5402 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5403 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5405 /* Since we don't know which revision of X we're running, we'll use both
5406 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5408 /* X11R4: send a ClientMessage to the window manager using the
5409 WM_CHANGE_STATE type. */
5413 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5414 message
.xclient
.type
= ClientMessage
;
5415 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5416 message
.xclient
.format
= 32;
5417 message
.xclient
.data
.l
[0] = IconicState
;
5419 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5420 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5422 SubstructureRedirectMask
| SubstructureNotifyMask
,
5425 UNBLOCK_INPUT_RESIGNAL
;
5426 error ("Can't notify window manager of iconification");
5430 /* X11R3: set the initial_state field of the window manager hints to
5432 x_wm_set_window_state (f
, IconicState
);
5434 if (!FRAME_VISIBLE_P (f
))
5436 /* If the frame was withdrawn, before, we must map it. */
5437 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5440 f
->async_iconified
= 1;
5442 XFlush (FRAME_X_DISPLAY (f
));
5444 #endif /* not USE_X_TOOLKIT */
5447 /* Destroy the X window of frame F. */
5449 x_destroy_window (f
)
5452 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5456 if (f
->output_data
.x
->icon_desc
!= 0)
5457 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
5458 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
5459 #ifdef USE_X_TOOLKIT
5460 XtDestroyWidget (f
->output_data
.x
->widget
);
5461 free_frame_menubar (f
);
5462 #endif /* USE_X_TOOLKIT */
5464 free_frame_faces (f
);
5465 XFlush (FRAME_X_DISPLAY (f
));
5467 xfree (f
->output_data
.x
);
5468 f
->output_data
.x
= 0;
5469 if (f
== dpyinfo
->x_focus_frame
)
5470 dpyinfo
->x_focus_frame
= 0;
5471 if (f
== dpyinfo
->x_focus_event_frame
)
5472 dpyinfo
->x_focus_event_frame
= 0;
5473 if (f
== dpyinfo
->x_highlight_frame
)
5474 dpyinfo
->x_highlight_frame
= 0;
5476 dpyinfo
->reference_count
--;
5478 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5480 dpyinfo
->mouse_face_beg_row
5481 = dpyinfo
->mouse_face_beg_col
= -1;
5482 dpyinfo
->mouse_face_end_row
5483 = dpyinfo
->mouse_face_end_col
= -1;
5484 dpyinfo
->mouse_face_window
= Qnil
;
5490 /* Setting window manager hints. */
5492 /* Set the normal size hints for the window manager, for frame F.
5493 FLAGS is the flags word to use--or 0 meaning preserve the flags
5494 that the window now has.
5495 If USER_POSITION is nonzero, we set the USPosition
5496 flag (this is useful when FLAGS is 0). */
5498 x_wm_set_size_hint (f
, flags
, user_position
)
5503 XSizeHints size_hints
;
5505 #ifdef USE_X_TOOLKIT
5508 Dimension widget_width
, widget_height
;
5509 Window window
= XtWindow (f
->output_data
.x
->widget
);
5510 #else /* not USE_X_TOOLKIT */
5511 Window window
= FRAME_X_WINDOW (f
);
5512 #endif /* not USE_X_TOOLKIT */
5514 /* Setting PMaxSize caused various problems. */
5515 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5517 flexlines
= f
->height
;
5519 size_hints
.x
= f
->output_data
.x
->left_pos
;
5520 size_hints
.y
= f
->output_data
.x
->top_pos
;
5522 #ifdef USE_X_TOOLKIT
5523 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5524 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5525 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5526 size_hints
.height
= widget_height
;
5527 size_hints
.width
= widget_width
;
5528 #else /* not USE_X_TOOLKIT */
5529 size_hints
.height
= PIXEL_HEIGHT (f
);
5530 size_hints
.width
= PIXEL_WIDTH (f
);
5531 #endif /* not USE_X_TOOLKIT */
5533 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
5534 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
5535 size_hints
.max_width
5536 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5537 size_hints
.max_height
5538 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5540 /* Calculate the base and minimum sizes.
5542 (When we use the X toolkit, we don't do it here.
5543 Instead we copy the values that the widgets are using, below.) */
5544 #ifndef USE_X_TOOLKIT
5546 int base_width
, base_height
;
5547 int min_rows
= 0, min_cols
= 0;
5549 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5550 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5552 check_frame_size (f
, &min_rows
, &min_cols
);
5554 /* The window manager uses the base width hints to calculate the
5555 current number of rows and columns in the frame while
5556 resizing; min_width and min_height aren't useful for this
5557 purpose, since they might not give the dimensions for a
5558 zero-row, zero-column frame.
5560 We use the base_width and base_height members if we have
5561 them; otherwise, we set the min_width and min_height members
5562 to the size for a zero x zero frame. */
5565 size_hints
.flags
|= PBaseSize
;
5566 size_hints
.base_width
= base_width
;
5567 size_hints
.base_height
= base_height
;
5568 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5569 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5571 size_hints
.min_width
= base_width
;
5572 size_hints
.min_height
= base_height
;
5576 /* If we don't need the old flags, we don't need the old hint at all. */
5579 size_hints
.flags
|= flags
;
5582 #endif /* not USE_X_TOOLKIT */
5585 XSizeHints hints
; /* Sometimes I hate X Windows... */
5586 long supplied_return
;
5590 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5593 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5596 #ifdef USE_X_TOOLKIT
5597 size_hints
.base_height
= hints
.base_height
;
5598 size_hints
.base_width
= hints
.base_width
;
5599 size_hints
.min_height
= hints
.min_height
;
5600 size_hints
.min_width
= hints
.min_width
;
5604 size_hints
.flags
|= flags
;
5609 if (hints
.flags
& PSize
)
5610 size_hints
.flags
|= PSize
;
5611 if (hints
.flags
& PPosition
)
5612 size_hints
.flags
|= PPosition
;
5613 if (hints
.flags
& USPosition
)
5614 size_hints
.flags
|= USPosition
;
5615 if (hints
.flags
& USSize
)
5616 size_hints
.flags
|= USSize
;
5623 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
5624 size_hints
.flags
|= PWinGravity
;
5628 size_hints
.flags
&= ~ PPosition
;
5629 size_hints
.flags
|= USPosition
;
5631 #endif /* PWinGravity */
5634 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5636 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5640 /* Used for IconicState or NormalState */
5641 x_wm_set_window_state (f
, state
)
5645 #ifdef USE_X_TOOLKIT
5648 XtSetArg (al
[0], XtNinitialState
, state
);
5649 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5650 #else /* not USE_X_TOOLKIT */
5651 Window window
= FRAME_X_WINDOW (f
);
5653 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5654 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5656 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5657 #endif /* not USE_X_TOOLKIT */
5660 x_wm_set_icon_pixmap (f
, pixmap_id
)
5664 #ifdef USE_X_TOOLKIT
5665 Window window
= XtWindow (f
->output_data
.x
->widget
);
5667 Window window
= FRAME_X_WINDOW (f
);
5672 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5673 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5676 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5678 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5679 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5682 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5686 #ifdef USE_X_TOOLKIT
5687 Window window
= XtWindow (f
->output_data
.x
->widget
);
5689 Window window
= FRAME_X_WINDOW (f
);
5692 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5693 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5694 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5696 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5700 /* Initialization. */
5702 #ifdef USE_X_TOOLKIT
5703 static XrmOptionDescRec emacs_options
[] = {
5704 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5705 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5707 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5708 XrmoptionSepArg
, NULL
},
5709 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5711 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5712 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5713 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5714 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5715 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5716 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5717 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5719 #endif /* USE_X_TOOLKIT */
5721 static int x_initialized
;
5724 /* Test whether two display-name strings agree up to the dot that separates
5725 the screen number from the server number. */
5727 same_x_server (name1
, name2
)
5728 char *name1
, *name2
;
5731 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5735 if (seen_colon
&& *name1
== '.')
5739 && (*name1
== '.' || *name1
== '\0')
5740 && (*name2
== '.' || *name2
== '\0'));
5744 struct x_display_info
*
5745 x_term_init (display_name
, xrm_option
, resource_name
)
5746 Lisp_Object display_name
;
5748 char *resource_name
;
5754 struct x_display_info
*dpyinfo
;
5765 #ifdef USE_X_TOOLKIT
5766 /* weiner@footloose.sps.mot.com reports that this causes
5768 X protocol error: BadAtom (invalid Atom parameter)
5769 on protocol request 18skiloaf.
5770 So let's not use it until R6. */
5772 XtSetLanguageProc (NULL
, NULL
, NULL
);
5783 argv
[argc
++] = "-xrm";
5784 argv
[argc
++] = xrm_option
;
5786 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5787 resource_name
, EMACS_CLASS
,
5788 emacs_options
, XtNumber (emacs_options
),
5792 setlocale (LC_NUMERIC
, "C");
5793 setlocale (LC_TIME
, "C");
5797 #else /* not USE_X_TOOLKIT */
5799 XSetLocaleModifiers ("");
5801 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5802 #endif /* not USE_X_TOOLKIT */
5804 /* Detect failure. */
5811 /* We have definitely succeeded. Record the new connection. */
5813 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5817 struct x_display_info
*share
;
5820 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5821 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5822 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5823 XSTRING (display_name
)->data
))
5826 dpyinfo
->kboard
= share
->kboard
;
5829 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5830 init_kboard (dpyinfo
->kboard
);
5831 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
5833 char *vendor
= ServerVendor (dpy
);
5834 dpyinfo
->kboard
->Vsystem_key_alist
5835 = call1 (Qvendor_specific_keysyms
,
5836 build_string (vendor
? vendor
: ""));
5839 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5840 all_kboards
= dpyinfo
->kboard
;
5841 /* Don't let the initial kboard remain current longer than necessary.
5842 That would cause problems if a file loaded on startup tries to
5843 prompt in the minibuffer. */
5844 if (current_kboard
== initial_kboard
)
5845 current_kboard
= dpyinfo
->kboard
;
5847 dpyinfo
->kboard
->reference_count
++;
5851 /* Put this display on the chain. */
5852 dpyinfo
->next
= x_display_list
;
5853 x_display_list
= dpyinfo
;
5855 /* Put it on x_display_name_list as well, to keep them parallel. */
5856 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5857 x_display_name_list
);
5858 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5860 dpyinfo
->display
= dpy
;
5863 XSetAfterFunction (x_current_display
, x_trace_wire
);
5867 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5868 + XSTRING (Vsystem_name
)->size
5870 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5871 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5873 /* Figure out which modifier bits mean what. */
5874 x_find_modifier_meanings (dpyinfo
);
5876 /* Get the scroll bar cursor. */
5877 dpyinfo
->vertical_scroll_bar_cursor
5878 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5880 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5881 resource_name
, EMACS_CLASS
);
5882 #ifdef HAVE_XRMSETDATABASE
5883 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5885 dpyinfo
->display
->db
= xrdb
;
5887 /* Put the rdb where we can find it in a way that works on
5889 dpyinfo
->xrdb
= xrdb
;
5891 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5892 DefaultScreen (dpyinfo
->display
));
5893 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5894 &dpyinfo
->n_planes
);
5895 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
5896 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
5897 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
5898 dpyinfo
->grabbed
= 0;
5899 dpyinfo
->reference_count
= 0;
5900 dpyinfo
->icon_bitmap_id
= -1;
5901 dpyinfo
->n_fonts
= 0;
5902 dpyinfo
->font_table_size
= 0;
5903 dpyinfo
->bitmaps
= 0;
5904 dpyinfo
->bitmaps_size
= 0;
5905 dpyinfo
->bitmaps_last
= 0;
5906 dpyinfo
->scratch_cursor_gc
= 0;
5907 dpyinfo
->mouse_face_mouse_frame
= 0;
5908 dpyinfo
->mouse_face_deferred_gc
= 0;
5909 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5910 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5911 dpyinfo
->mouse_face_face_id
= 0;
5912 dpyinfo
->mouse_face_window
= Qnil
;
5913 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
5914 dpyinfo
->mouse_face_defer
= 0;
5915 dpyinfo
->x_focus_frame
= 0;
5916 dpyinfo
->x_focus_event_frame
= 0;
5917 dpyinfo
->x_highlight_frame
= 0;
5919 dpyinfo
->Xatom_wm_protocols
5920 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
5921 dpyinfo
->Xatom_wm_take_focus
5922 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
5923 dpyinfo
->Xatom_wm_save_yourself
5924 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
5925 dpyinfo
->Xatom_wm_delete_window
5926 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
5927 dpyinfo
->Xatom_wm_change_state
5928 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
5929 dpyinfo
->Xatom_wm_configure_denied
5930 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
5931 dpyinfo
->Xatom_wm_window_moved
5932 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
5933 dpyinfo
->Xatom_editres
5934 = XInternAtom (dpyinfo
->display
, "Editres", False
);
5935 dpyinfo
->Xatom_CLIPBOARD
5936 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
5937 dpyinfo
->Xatom_TIMESTAMP
5938 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
5940 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
5941 dpyinfo
->Xatom_DELETE
5942 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
5943 dpyinfo
->Xatom_MULTIPLE
5944 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
5946 = XInternAtom (dpyinfo
->display
, "INCR", False
);
5947 dpyinfo
->Xatom_EMACS_TMP
5948 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
5949 dpyinfo
->Xatom_TARGETS
5950 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
5952 = XInternAtom (dpyinfo
->display
, "NULL", False
);
5953 dpyinfo
->Xatom_ATOM_PAIR
5954 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
5956 dpyinfo
->cut_buffers_initialized
= 0;
5958 connection
= ConnectionNumber (dpyinfo
->display
);
5959 dpyinfo
->connection
= connection
;
5962 /* This is only needed for distinguishing keyboard and process input. */
5963 if (connection
!= 0)
5964 add_keyboard_wait_descriptor (connection
);
5967 #ifndef F_SETOWN_BUG
5969 #ifdef F_SETOWN_SOCK_NEG
5970 /* stdin is a socket here */
5971 fcntl (connection
, F_SETOWN
, -getpid ());
5972 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5973 fcntl (connection
, F_SETOWN
, getpid ());
5974 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5975 #endif /* ! defined (F_SETOWN) */
5976 #endif /* F_SETOWN_BUG */
5979 if (interrupt_input
)
5980 init_sigio (connection
);
5981 #endif /* ! defined (SIGIO) */
5988 /* Get rid of display DPYINFO, assuming all frames are already gone,
5989 and without sending any more commands to the X server. */
5992 x_delete_display (dpyinfo
)
5993 struct x_display_info
*dpyinfo
;
5995 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
5997 /* Discard this display from x_display_name_list and x_display_list.
5998 We can't use Fdelq because that can quit. */
5999 if (! NILP (x_display_name_list
)
6000 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
6001 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
6006 tail
= x_display_name_list
;
6007 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
6009 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
6010 dpyinfo
->name_list_element
))
6012 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
6015 tail
= XCONS (tail
)->cdr
;
6019 if (x_display_list
== dpyinfo
)
6020 x_display_list
= dpyinfo
->next
;
6023 struct x_display_info
*tail
;
6025 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
6026 if (tail
->next
== dpyinfo
)
6027 tail
->next
= tail
->next
->next
;
6030 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6031 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6032 XrmDestroyDatabase (dpyinfo
->xrdb
);
6036 if (--dpyinfo
->kboard
->reference_count
== 0)
6037 delete_kboard (dpyinfo
->kboard
);
6039 xfree (dpyinfo
->font_table
);
6040 xfree (dpyinfo
->x_id_name
);
6044 /* Set up use of X before we make the first connection. */
6048 clear_frame_hook
= XTclear_frame
;
6049 clear_end_of_line_hook
= XTclear_end_of_line
;
6050 ins_del_lines_hook
= XTins_del_lines
;
6051 change_line_highlight_hook
= XTchange_line_highlight
;
6052 insert_glyphs_hook
= XTinsert_glyphs
;
6053 write_glyphs_hook
= XTwrite_glyphs
;
6054 delete_glyphs_hook
= XTdelete_glyphs
;
6055 ring_bell_hook
= XTring_bell
;
6056 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6057 set_terminal_modes_hook
= XTset_terminal_modes
;
6058 update_begin_hook
= XTupdate_begin
;
6059 update_end_hook
= XTupdate_end
;
6060 set_terminal_window_hook
= XTset_terminal_window
;
6061 read_socket_hook
= XTread_socket
;
6062 frame_up_to_date_hook
= XTframe_up_to_date
;
6063 cursor_to_hook
= XTcursor_to
;
6064 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6065 mouse_position_hook
= XTmouse_position
;
6066 frame_rehighlight_hook
= XTframe_rehighlight
;
6067 frame_raise_lower_hook
= XTframe_raise_lower
;
6068 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6069 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6070 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6071 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6073 scroll_region_ok
= 1; /* we'll scroll partial frames */
6074 char_ins_del_ok
= 0; /* just as fast to write the line */
6075 line_ins_del_ok
= 1; /* we'll just blt 'em */
6076 fast_clear_end_of_line
= 1; /* X does this well */
6077 memory_below_frame
= 0; /* we don't remember what scrolls
6083 /* Try to use interrupt input; if we can't, then start polling. */
6084 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6086 #ifdef USE_X_TOOLKIT
6087 XtToolkitInitialize ();
6088 Xt_app_con
= XtCreateApplicationContext ();
6089 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
6092 /* Note that there is no real way portable across R3/R4 to get the
6093 original error handler. */
6094 XSetErrorHandler (x_error_quitter
);
6095 XSetIOErrorHandler (x_io_error_quitter
);
6097 /* Disable Window Change signals; they are handled by X events. */
6099 signal (SIGWINCH
, SIG_DFL
);
6100 #endif /* ! defined (SIGWINCH) */
6102 signal (SIGPIPE
, x_connection_signal
);
6108 staticpro (&x_display_name_list
);
6109 x_display_name_list
= Qnil
;
6111 staticpro (&last_mouse_scroll_bar
);
6112 last_mouse_scroll_bar
= Qnil
;
6114 staticpro (&Qvendor_specific_keysyms
);
6115 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6117 #endif /* ! defined (HAVE_X_WINDOWS) */