1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Xt features made by Fred Pierresteguy. */
23 /* On 4.3 these lose if they come after xterm.h. */
24 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
25 /* Putting these at the beginning seems to be standard for other .c files. */
32 /* Need syssignal.h for various externs and definitions that may be required
33 by some configurations for calls to signal later in this source file. */
34 #include "syssignal.h"
39 #include "blockinput.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
44 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
55 #include <sys/ioctl.h>
56 #endif /* ! defined (BSD) */
61 #ifndef INCLUDED_FCNTL
68 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
69 /* #include <sys/param.h> */
72 #include "dispextern.h"
73 #include "termhooks.h"
85 #include "intervals.h"
88 extern void free_frame_menubar ();
89 extern FRAME_PTR
x_menubar_window_to_frame ();
90 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
92 extern void _XEditResCheckMessages ();
93 #endif /* not NO_EDITRES */
94 #endif /* USE_X_TOOLKIT */
97 #define x_any_window_to_frame x_window_to_frame
98 #define x_top_window_to_frame x_window_to_frame
103 #ifndef XtNinitialState
104 #define XtNinitialState "initialState"
109 /* So we can do setlocale. */
113 #define min(a,b) ((a)<(b) ? (a) : (b))
114 #define max(a,b) ((a)>(b) ? (a) : (b))
116 /* This is a chain of structures for all the X displays currently in use. */
117 struct x_display_info
*x_display_list
;
119 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
120 one for each element of x_display_list and in the same order.
121 NAME is the name of the frame.
122 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
123 Lisp_Object x_display_name_list
;
125 /* Frame being updated by update_frame. This is declared in term.c.
126 This is set by update_begin and looked at by all the
127 XT functions. It is zero while not inside an update.
128 In that case, the XT functions assume that `selected_frame'
129 is the frame to apply to. */
130 extern struct frame
*updating_frame
;
132 /* This is a frame waiting to be autoraised, within XTread_socket. */
133 struct frame
*pending_autoraise_frame
;
136 /* The application context for Xt use. */
137 XtAppContext Xt_app_con
;
139 static String Xt_default_resources
[] =
145 /* During an update, maximum vpos for ins/del line operations to affect. */
147 static int flexlines
;
149 /* During an update, nonzero if chars output now should be highlighted. */
151 static int highlight
;
153 /* Nominal cursor position -- where to draw output.
154 During an update, these are different from the cursor-box position. */
161 In order to avoid asking for motion events and then throwing most
162 of them away or busy-polling the server for mouse positions, we ask
163 the server for pointer motion hints. This means that we get only
164 one event per group of mouse movements. "Groups" are delimited by
165 other kinds of events (focus changes and button clicks, for
166 example), or by XQueryPointer calls; when one of these happens, we
167 get another MotionNotify event the next time the mouse moves. This
168 is at least as efficient as getting motion events when mouse
169 tracking is on, and I suspect only negligibly worse when tracking
172 The silly O'Reilly & Associates Nutshell guides barely document
173 pointer motion hints at all (I think you have to infer how they
174 work from an example), and the description of XQueryPointer doesn't
175 mention that calling it causes you to get another motion hint from
176 the server, which is very important. */
178 /* Where the mouse was last time we reported a mouse event. */
179 static FRAME_PTR last_mouse_frame
;
180 static XRectangle last_mouse_glyph
;
182 /* The scroll bar in which the last X motion event occurred.
184 If the last X motion event occurred in a scroll bar, we set this
185 so XTmouse_position can know whether to report a scroll bar motion or
188 If the last X motion event didn't occur in a scroll bar, we set this
189 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
190 static Lisp_Object last_mouse_scroll_bar
;
192 /* This is a hack. We would really prefer that XTmouse_position would
193 return the time associated with the position it returns, but there
194 doesn't seem to be any way to wrest the timestamp from the server
195 along with the position query. So, we just keep track of the time
196 of the last movement we received, and return that in hopes that
197 it's somewhat accurate. */
198 static Time last_mouse_movement_time
;
200 /* Incremented by XTread_socket whenever it really tries to read events. */
202 static int volatile input_signal_count
;
204 static int input_signal_count
;
207 /* Used locally within XTread_socket. */
208 static int x_noop_count
;
210 /* Initial values of argv and argc. */
211 extern char **initial_argv
;
212 extern int initial_argc
;
214 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
216 /* Tells if a window manager is present or not. */
218 extern Lisp_Object Vx_no_window_manager
;
220 /* Nonzero enables some debugging for the X interface code. */
223 extern Lisp_Object Qface
, Qmouse_face
;
227 /* A mask of extra modifier bits to put into every keyboard char. */
228 extern int extra_keyboard_modifiers
;
230 static Lisp_Object Qvendor_specific_keysyms
;
232 extern XrmDatabase
x_load_resources ();
234 extern Lisp_Object
x_icon_type ();
236 void x_delete_display ();
238 static void redraw_previous_char ();
239 static void redraw_following_char ();
240 static unsigned int x_x_to_emacs_modifiers ();
242 static int fast_find_position ();
243 static void note_mouse_highlight ();
244 static void clear_mouse_face ();
245 static void show_mouse_face ();
246 static void do_line_dance ();
248 static int XTcursor_to ();
249 static int XTclear_end_of_line ();
250 static int x_io_error_quitter ();
251 void x_catch_errors ();
252 void x_uncatch_errors ();
255 /* This is a function useful for recording debugging information
256 about the sequence of occurrences in this file. */
264 struct record event_record
[100];
266 int event_record_index
;
268 record_event (locus
, type
)
272 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
273 event_record_index
= 0;
275 event_record
[event_record_index
].locus
= locus
;
276 event_record
[event_record_index
].type
= type
;
277 event_record_index
++;
282 /* Return the struct x_display_info corresponding to DPY. */
284 struct x_display_info
*
285 x_display_info_for_display (dpy
)
288 struct x_display_info
*dpyinfo
;
290 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
291 if (dpyinfo
->display
== dpy
)
297 /* Starting and ending updates.
299 These hooks are called by update_frame at the beginning and end
300 of a frame update. We record in `updating_frame' the identity
301 of the frame being updated, so that the XT... functions do not
302 need to take a frame as argument. Most of the XT... functions
303 should never be called except during an update, the only exceptions
304 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
315 flexlines
= f
->height
;
320 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
322 /* Don't do highlighting for mouse motion during the update. */
323 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
325 /* If the frame needs to be redrawn,
326 simply forget about any prior mouse highlighting. */
327 if (FRAME_GARBAGED_P (f
))
328 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
330 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
332 int firstline
, lastline
, i
;
333 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
335 /* Find the first, and the last+1, lines affected by redisplay. */
336 for (firstline
= 0; firstline
< f
->height
; firstline
++)
337 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
340 lastline
= f
->height
;
341 for (i
= f
->height
- 1; i
>= 0; i
--)
343 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
349 /* Can we tell that this update does not affect the window
350 where the mouse highlight is? If so, no need to turn off.
351 Likewise, don't do anything if the frame is garbaged;
352 in that case, the FRAME_CURRENT_GLYPHS that we would use
353 are all wrong, and we will redisplay that line anyway. */
354 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
355 || lastline
< XFASTINT (w
->top
)))
356 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
372 x_display_cursor (f
, 1);
374 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
375 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
377 /* This fails in the case of having updated only the echo area
378 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
379 has no relation to the current contents, and its charstarts
380 have no relation to the contents of the window-buffer.
381 I don't know a clean way to check
382 for that case. window_end_valid isn't set up yet. */
383 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
384 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
385 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
388 XFlush (FRAME_X_DISPLAY (f
));
392 /* This is called after a redisplay on frame F. */
395 XTframe_up_to_date (f
)
399 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
400 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
402 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
403 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
404 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
405 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
410 /* External interface to control of standout mode.
411 Call this when about to modify line at position VPOS
412 and not change whether it is highlighted. */
414 XTreassert_line_highlight (new, vpos
)
420 /* Call this when about to modify line at position VPOS
421 and change whether it is highlighted. */
424 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
425 int new_highlight
, vpos
, first_unused_hpos
;
427 highlight
= new_highlight
;
428 XTcursor_to (vpos
, 0);
429 XTclear_end_of_line (updating_frame
->width
);
432 /* This is used when starting Emacs and when restarting after suspend.
433 When starting Emacs, no X window is mapped. And nothing must be done
434 to Emacs's own window if it is suspended (though that rarely happens). */
437 XTset_terminal_modes ()
441 /* This is called when exiting or suspending Emacs.
442 Exiting will make the X-windows go away, and suspending
443 requires no action. */
446 XTreset_terminal_modes ()
448 /* XTclear_frame (); */
451 /* Set the nominal cursor position of the frame.
452 This is where display update commands will take effect.
453 This does not affect the place where the cursor-box is displayed. */
456 XTcursor_to (row
, col
)
457 register int row
, col
;
465 if (updating_frame
== 0)
468 x_display_cursor (selected_frame
, 1);
469 XFlush (FRAME_X_DISPLAY (selected_frame
));
474 /* Display a sequence of N glyphs found at GP.
475 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
476 HL is 1 if this text is highlighted, 2 if the cursor is on it,
477 3 if should appear in its mouse-face.
478 JUST_FOREGROUND if 1 means draw only the foreground;
479 don't alter the background.
481 FONT is the default font to use (for glyphs whose font-code is 0).
483 Since the display generation code is responsible for calling
484 compute_char_face and compute_glyph_face on everything it puts in
485 the display structure, we can assume that the face code on each
486 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
487 to which we can actually apply intern_face.
488 Call this function with input blocked. */
491 /* This is the multi-face code. */
494 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
497 register GLYPH
*gp
; /* Points to first GLYPH. */
498 register int n
; /* Number of glyphs to display. */
502 /* Holds characters to be displayed. */
503 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
504 register char *cp
; /* Steps through buf[]. */
505 register int tlen
= GLYPH_TABLE_LENGTH
;
506 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
507 Window window
= FRAME_X_WINDOW (f
);
508 int orig_left
= left
;
512 /* Get the face-code of the next GLYPH. */
516 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
517 cf
= FAST_GLYPH_FACE (g
);
519 /* Find the run of consecutive glyphs with the same face-code.
520 Extract their character codes into BUF. */
525 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
526 if (FAST_GLYPH_FACE (g
) != cf
)
529 *cp
++ = FAST_GLYPH_CHAR (g
);
534 /* LEN gets the length of the run. */
537 /* Now output this run of chars, with the font and pixel values
538 determined by the face code CF. */
540 struct face
*face
= FRAME_DEFAULT_FACE (f
);
541 XFontStruct
*font
= FACE_FONT (face
);
542 GC gc
= FACE_GC (face
);
545 /* HL = 3 means use a mouse face previously chosen. */
547 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
549 /* First look at the face of the text itself. */
552 /* It's possible for the display table to specify
553 a face code that is out of range. Use 0 in that case. */
554 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
555 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
559 face
= FRAME_MODE_LINE_FACE (f
);
561 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
562 font
= FACE_FONT (face
);
564 if (FACE_STIPPLE (face
))
568 /* Then comes the distinction between modeline and normal text. */
573 face
= FRAME_MODE_LINE_FACE (f
);
574 font
= FACE_FONT (face
);
576 if (FACE_STIPPLE (face
))
580 #define FACE_DEFAULT (~0)
582 /* Now override that if the cursor's on this character. */
585 /* The cursor overrides stippling. */
589 || face
->font
== (XFontStruct
*) FACE_DEFAULT
590 || face
->font
== f
->output_data
.x
->font
)
591 && face
->background
== f
->output_data
.x
->background_pixel
592 && face
->foreground
== f
->output_data
.x
->foreground_pixel
)
594 gc
= f
->output_data
.x
->cursor_gc
;
596 /* Cursor on non-default face: must merge. */
602 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
603 xgcv
.foreground
= face
->background
;
604 /* If the glyph would be invisible,
605 try a different foreground. */
606 if (xgcv
.foreground
== xgcv
.background
)
607 xgcv
.foreground
= face
->foreground
;
608 if (xgcv
.foreground
== xgcv
.background
)
609 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
610 if (xgcv
.foreground
== xgcv
.background
)
611 xgcv
.foreground
= face
->foreground
;
612 /* Make sure the cursor is distinct from text in this face. */
613 if (xgcv
.background
== face
->background
614 && xgcv
.foreground
== face
->foreground
)
616 xgcv
.background
= face
->foreground
;
617 xgcv
.foreground
= face
->background
;
619 xgcv
.font
= face
->font
->fid
;
620 xgcv
.graphics_exposures
= 0;
621 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
622 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
623 XChangeGC (FRAME_X_DISPLAY (f
),
624 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
627 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
628 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
629 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
631 /* If this code is restored, it must also reset to the default stipple
633 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
634 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
639 if (font
== (XFontStruct
*) FACE_DEFAULT
)
640 font
= f
->output_data
.x
->font
;
643 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
644 left
, top
+ FONT_BASE (font
), buf
, len
);
649 /* Turn stipple on. */
650 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
652 /* Draw stipple on background. */
653 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
655 FONT_WIDTH (font
) * len
,
658 /* Turn stipple off. */
659 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
661 /* Draw the text, solidly, onto the stipple pattern. */
662 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
663 left
, top
+ FONT_BASE (font
), buf
, len
);
666 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
667 left
, top
+ FONT_BASE (font
), buf
, len
);
669 /* Clear the rest of the line's height. */
670 if (f
->output_data
.x
->line_height
!= FONT_HEIGHT (font
))
671 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
672 top
+ FONT_HEIGHT (font
),
673 FONT_WIDTH (font
) * len
,
674 /* This is how many pixels of height
676 f
->output_data
.x
->line_height
- FONT_HEIGHT (font
),
680 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
681 which often is not up to date yet. */
682 if (!just_foreground
)
684 if (left
== orig_left
)
685 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
686 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
688 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
689 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
693 /* We should probably check for XA_UNDERLINE_POSITION and
694 XA_UNDERLINE_THICKNESS properties on the font, but let's
695 just get the thing working, and come back to that. */
697 int underline_position
= 1;
699 if (font
->descent
<= underline_position
)
700 underline_position
= font
->descent
- 1;
703 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
707 + underline_position
),
708 len
* FONT_WIDTH (font
), 1);
711 left
+= len
* FONT_WIDTH (font
);
718 /* This is the old single-face code. */
721 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
724 register GLYPH
*gp
; /* Points to first GLYPH. */
725 register int n
; /* Number of glyphs to display. */
730 Window window
= FRAME_X_WINDOW (f
);
731 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
732 : (hl
? f
->output_data
.x
->reverse_gc
733 : f
->output_data
.x
->normal_gc
));
735 if (sizeof (GLYPH
) == sizeof (XChar2b
))
736 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
737 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
738 else if (sizeof (GLYPH
) == sizeof (unsigned char))
739 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
740 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
742 /* What size of glyph ARE you using? And does X have a function to
748 /* Output some text at the nominal frame cursor position.
749 Advance the cursor over the text.
750 Output LEN glyphs at START.
752 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
753 controls the pixel values used for foreground and background. */
756 XTwrite_glyphs (start
, len
)
757 register GLYPH
*start
;
760 register int temp_length
;
771 /* If not within an update,
772 output at the frame's visible cursor. */
773 curs_x
= f
->cursor_x
;
774 curs_y
= f
->cursor_y
;
778 CHAR_TO_PIXEL_COL (f
, curs_x
),
779 CHAR_TO_PIXEL_ROW (f
, curs_y
),
780 start
, len
, highlight
, 0);
782 /* If we drew on top of the cursor, note that it is turned off. */
783 if (curs_y
== f
->phys_cursor_y
784 && curs_x
<= f
->phys_cursor_x
785 && curs_x
+ len
> f
->phys_cursor_x
)
786 f
->phys_cursor_x
= -1;
788 if (updating_frame
== 0)
791 x_display_cursor (f
, 1);
800 /* Clear to the end of the line.
801 Erase the current text line from the nominal cursor position (inclusive)
802 to column FIRST_UNUSED (exclusive). The idea is that everything
803 from FIRST_UNUSED onward is already erased. */
806 XTclear_end_of_line (first_unused
)
807 register int first_unused
;
809 struct frame
*f
= updating_frame
;
815 if (curs_y
< 0 || curs_y
>= f
->height
)
817 if (first_unused
<= 0)
820 if (first_unused
>= f
->width
)
821 first_unused
= f
->width
;
827 /* Notice if the cursor will be cleared by this operation. */
828 if (curs_y
== f
->phys_cursor_y
829 && curs_x
<= f
->phys_cursor_x
830 && f
->phys_cursor_x
< first_unused
)
831 f
->phys_cursor_x
= -1;
833 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
834 CHAR_TO_PIXEL_COL (f
, curs_x
),
835 CHAR_TO_PIXEL_ROW (f
, curs_y
),
836 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
837 f
->output_data
.x
->line_height
, False
);
839 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
849 struct frame
*f
= updating_frame
;
854 f
->phys_cursor_x
= -1; /* Cursor not visible. */
855 curs_x
= 0; /* Nominal cursor position is top left. */
860 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
862 /* We have to clear the scroll bars, too. If we have changed
863 colors or something like that, then they should be notified. */
864 x_scroll_bar_clear (f
);
866 XFlush (FRAME_X_DISPLAY (f
));
871 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
872 always contain the right glyphs to use.
874 It also needs to be changed to look at the details of the font and
875 see whether there is really overlap, and do nothing when there is
876 not. This can use font_char_overlap_left and font_char_overlap_right,
877 but just how to use them is not clear. */
879 /* Erase the character (if any) at the position just before X, Y in frame F,
880 then redraw it and the character before it.
881 This is necessary when we erase starting at X,
882 in case the character after X overlaps into the one before X.
883 Call this function with input blocked. */
886 redraw_previous_char (f
, x
, y
, highlight_flag
)
891 /* Erase the character before the new ones, in case
892 what was here before overlaps it.
893 Reoutput that character, and the previous character
894 (in case the previous character overlaps it). */
900 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
901 CHAR_TO_PIXEL_COL (f
, x
- 1),
902 CHAR_TO_PIXEL_ROW (f
, y
),
903 FONT_WIDTH (f
->output_data
.x
->font
),
904 f
->output_data
.x
->line_height
, False
);
906 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
907 CHAR_TO_PIXEL_ROW (f
, y
),
908 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
909 x
- start_x
, highlight_flag
, 1);
913 /* Erase the character (if any) at the position X, Y in frame F,
914 then redraw it and the character after it.
915 This is necessary when we erase endng at X,
916 in case the character after X overlaps into the one before X.
917 Call this function with input blocked. */
920 redraw_following_char (f
, x
, y
, highlight_flag
)
925 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
926 /* Erase the character after the new ones, in case
927 what was here before overlaps it.
928 Reoutput that character, and the following character
929 (in case the following character overlaps it). */
931 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
936 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
937 CHAR_TO_PIXEL_COL (f
, x
),
938 CHAR_TO_PIXEL_ROW (f
, y
),
939 FONT_WIDTH (f
->output_data
.x
->font
),
940 f
->output_data
.x
->line_height
, False
);
942 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
943 CHAR_TO_PIXEL_ROW (f
, y
),
944 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
945 end_x
- x
, highlight_flag
, 1);
950 #if 0 /* Not in use yet */
952 /* Return 1 if character C in font F extends past its left edge. */
955 font_char_overlap_left (font
, c
)
961 /* Find the bounding-box info for C. */
962 if (font
->per_char
== 0)
963 s
= &font
->max_bounds
;
966 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
969 /* Decode char into row number (byte 1) and code within row (byte 2). */
972 if (!(within
>= font
->min_char_or_byte2
973 && within
<= font
->max_char_or_byte2
974 && row
>= font
->min_byte1
975 && row
<= font
->max_byte1
))
977 /* If char is out of range, try the font's default char instead. */
978 c
= font
->default_char
;
979 row
= c
>> (BITS_PER_INT
- 8);
982 if (!(within
>= font
->min_char_or_byte2
983 && within
<= font
->max_char_or_byte2
984 && row
>= font
->min_byte1
985 && row
<= font
->max_byte1
))
986 /* Still out of range means this char does not overlap. */
989 /* We found the info for this char. */
990 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
994 return (s
&& s
->lbearing
< 0);
997 /* Return 1 if character C in font F extends past its right edge. */
1000 font_char_overlap_right (font
, c
)
1006 /* Find the bounding-box info for C. */
1007 if (font
->per_char
== 0)
1008 s
= &font
->max_bounds
;
1011 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1014 /* Decode char into row number (byte 1) and code within row (byte 2). */
1017 if (!(within
>= font
->min_char_or_byte2
1018 && within
<= font
->max_char_or_byte2
1019 && row
>= font
->min_byte1
1020 && row
<= font
->max_byte1
))
1022 /* If char is out of range, try the font's default char instead. */
1023 c
= font
->default_char
;
1024 row
= c
>> (BITS_PER_INT
- 8);
1027 if (!(within
>= font
->min_char_or_byte2
1028 && within
<= font
->max_char_or_byte2
1029 && row
>= font
->min_byte1
1030 && row
<= font
->max_byte1
))
1031 /* Still out of range means this char does not overlap. */
1034 /* We found the info for this char. */
1035 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1039 return (s
&& s
->rbearing
>= s
->width
);
1043 /* Invert the middle quarter of the frame for .15 sec. */
1045 /* We use the select system call to do the waiting, so we have to make sure
1046 it's available. If it isn't, we just won't do visual bells. */
1047 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1049 /* Subtract the `struct timeval' values X and Y,
1050 storing the result in RESULT.
1051 Return 1 if the difference is negative, otherwise 0. */
1054 timeval_subtract (result
, x
, y
)
1055 struct timeval
*result
, x
, y
;
1057 /* Perform the carry for the later subtraction by updating y.
1058 This is safer because on some systems
1059 the tv_sec member is unsigned. */
1060 if (x
.tv_usec
< y
.tv_usec
)
1062 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1063 y
.tv_usec
-= 1000000 * nsec
;
1066 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1068 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1069 y
.tv_usec
+= 1000000 * nsec
;
1073 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1074 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1075 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1077 /* Return indication of whether the result should be considered negative. */
1078 return x
.tv_sec
< y
.tv_sec
;
1089 /* Create a GC that will use the GXxor function to flip foreground pixels
1090 into background pixels. */
1094 values
.function
= GXxor
;
1095 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1096 ^ f
->output_data
.x
->background_pixel
);
1098 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1099 GCFunction
| GCForeground
, &values
);
1103 int width
= PIXEL_WIDTH (f
);
1104 int height
= PIXEL_HEIGHT (f
);
1106 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1107 width
/4, height
/4, width
/2, height
/2);
1108 XFlush (FRAME_X_DISPLAY (f
));
1111 struct timeval wakeup
, now
;
1113 EMACS_GET_TIME (wakeup
);
1115 /* Compute time to wait until, propagating carry from usecs. */
1116 wakeup
.tv_usec
+= 150000;
1117 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1118 wakeup
.tv_usec
%= 1000000;
1120 /* Keep waiting until past the time wakeup. */
1123 struct timeval timeout
;
1125 EMACS_GET_TIME (timeout
);
1127 /* In effect, timeout = wakeup - timeout.
1128 Break if result would be negative. */
1129 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1132 /* Try to wait that long--but we might wake up sooner. */
1133 select (0, NULL
, NULL
, NULL
, &timeout
);
1137 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1138 width
/4, height
/4, width
/2, height
/2);
1139 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1140 XFlush (FRAME_X_DISPLAY (f
));
1150 /* Make audible bell. */
1152 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1156 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1159 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1161 XTflash (selected_frame
);
1167 XFlush (FRAME_X_DISPLAY (selected_frame
));
1172 /* Insert and delete character.
1173 These are not supposed to be used because we are supposed to turn
1174 off the feature of using them. */
1177 XTinsert_glyphs (start
, len
)
1178 register char *start
;
1191 /* Specify how many text lines, from the top of the window,
1192 should be affected by insert-lines and delete-lines operations.
1193 This, and those operations, are used only within an update
1194 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1197 XTset_terminal_window (n
)
1200 if (updating_frame
== 0)
1203 if ((n
<= 0) || (n
> updating_frame
->height
))
1204 flexlines
= updating_frame
->height
;
1209 /* These variables need not be per frame
1210 because redisplay is done on a frame-by-frame basis
1211 and the line dance for one frame is finished before
1212 anything is done for anoter frame. */
1214 /* Array of line numbers from cached insert/delete operations.
1215 line_dance[i] is the old position of the line that we want
1216 to move to line i, or -1 if we want a blank line there. */
1217 static int *line_dance
;
1219 /* Allocated length of that array. */
1220 static int line_dance_len
;
1222 /* Flag indicating whether we've done any work. */
1223 static int line_dance_in_progress
;
1225 /* Perform an insert-lines or delete-lines operation,
1226 inserting N lines or deleting -N lines at vertical position VPOS. */
1227 XTins_del_lines (vpos
, n
)
1230 register int fence
, i
;
1232 if (vpos
>= flexlines
)
1235 if (!line_dance_in_progress
)
1237 int ht
= updating_frame
->height
;
1238 if (ht
> line_dance_len
)
1240 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1241 line_dance_len
= ht
;
1243 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1244 line_dance_in_progress
= 1;
1248 if (n
> flexlines
- vpos
)
1249 n
= flexlines
- vpos
;
1251 for (i
= flexlines
; --i
>= fence
;)
1252 line_dance
[i
] = line_dance
[i
-n
];
1253 for (i
= fence
; --i
>= vpos
;)
1259 if (n
> flexlines
- vpos
)
1260 n
= flexlines
- vpos
;
1261 fence
= flexlines
- n
;
1262 for (i
= vpos
; i
< fence
; ++i
)
1263 line_dance
[i
] = line_dance
[i
+ n
];
1264 for (i
= fence
; i
< flexlines
; ++i
)
1269 /* Here's where we actually move the pixels around.
1270 Must be called with input blocked. */
1274 register int i
, j
, distance
;
1275 register struct frame
*f
;
1279 /* Must check this flag first. If it's not set, then not only is the
1280 array uninitialized, but we might not even have a frame. */
1281 if (!line_dance_in_progress
)
1289 intborder
= f
->output_data
.x
->internal_border_width
;
1291 x_display_cursor (updating_frame
, 0);
1293 for (i
= 0; i
< ht
; ++i
)
1294 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1296 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1297 && line_dance
[j
]-j
== distance
); ++j
);
1298 /* Copy [i,j) upward from [i+distance,j+distance) */
1299 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1300 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1301 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1302 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1303 (j
-i
) * f
->output_data
.x
->line_height
,
1304 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1308 for (i
= ht
; --i
>=0; )
1309 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1311 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1312 && line_dance
[j
]-j
== distance
););
1313 /* Copy (j,i] downward from (j+distance, i+distance] */
1314 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1315 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1316 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1317 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1318 (i
-j
) * f
->output_data
.x
->line_height
,
1319 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1323 for (i
= 0; i
< ht
; ++i
)
1324 if (line_dance
[i
] == -1)
1326 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1328 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1329 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1330 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1331 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1334 line_dance_in_progress
= 0;
1337 /* Support routines for exposure events. */
1338 static void clear_cursor ();
1340 /* Output into a rectangle of an X-window (for frame F)
1341 the characters in f->phys_lines that overlap that rectangle.
1342 TOP and LEFT are the position of the upper left corner of the rectangle.
1343 ROWS and COLS are the size of the rectangle.
1344 Call this function with input blocked. */
1347 dumprectangle (f
, left
, top
, cols
, rows
)
1349 register int left
, top
, cols
, rows
;
1351 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1352 int cursor_cleared
= 0;
1356 if (FRAME_GARBAGED_P (f
))
1359 /* Express rectangle as four edges, instead of position-and-size. */
1360 bottom
= top
+ rows
;
1361 right
= left
+ cols
;
1363 /* Convert rectangle edges in pixels to edges in chars.
1364 Round down for left and top, up for right and bottom. */
1365 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1366 left
= PIXEL_TO_CHAR_COL (f
, left
);
1367 bottom
+= (f
->output_data
.x
->line_height
- 1);
1368 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1369 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1370 right
= PIXEL_TO_CHAR_COL (f
, right
);
1372 /* Clip the rectangle to what can be visible. */
1377 if (right
> f
->width
)
1379 if (bottom
> f
->height
)
1382 /* Get size in chars of the rectangle. */
1383 cols
= right
- left
;
1384 rows
= bottom
- top
;
1386 /* If rectangle has zero area, return. */
1387 if (rows
<= 0) return;
1388 if (cols
<= 0) return;
1390 /* Turn off the cursor if it is in the rectangle.
1391 We will turn it back on afterward. */
1392 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1393 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1399 /* Display the text in the rectangle, one text line at a time. */
1401 for (y
= top
; y
< bottom
; y
++)
1403 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1405 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1409 CHAR_TO_PIXEL_COL (f
, left
),
1410 CHAR_TO_PIXEL_ROW (f
, y
),
1411 line
, min (cols
, active_frame
->used
[y
] - left
),
1412 active_frame
->highlight
[y
], 0);
1415 /* Turn the cursor on if we turned it off. */
1418 x_display_cursor (f
, 1);
1425 /* We used to only do this if Vx_no_window_manager was non-nil, but
1426 the ICCCM (section 4.1.6) says that the window's border pixmap
1427 and border pixel are window attributes which are "private to the
1428 client", so we can always change it to whatever we want. */
1430 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1431 f
->output_data
.x
->border_pixel
);
1433 x_update_cursor (f
, 1);
1437 frame_unhighlight (f
)
1440 /* We used to only do this if Vx_no_window_manager was non-nil, but
1441 the ICCCM (section 4.1.6) says that the window's border pixmap
1442 and border pixel are window attributes which are "private to the
1443 client", so we can always change it to whatever we want. */
1445 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1446 f
->output_data
.x
->border_tile
);
1448 x_update_cursor (f
, 1);
1451 static void XTframe_rehighlight ();
1452 static void x_frame_rehighlight ();
1454 /* The focus has changed. Update the frames as necessary to reflect
1455 the new situation. Note that we can't change the selected frame
1456 here, because the Lisp code we are interrupting might become confused.
1457 Each event gets marked with the frame in which it occurred, so the
1458 Lisp code can tell when the switch took place by examining the events. */
1461 x_new_focus_frame (dpyinfo
, frame
)
1462 struct x_display_info
*dpyinfo
;
1463 struct frame
*frame
;
1465 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1466 int events_enqueued
= 0;
1468 if (frame
!= dpyinfo
->x_focus_frame
)
1470 /* Set this before calling other routines, so that they see
1471 the correct value of x_focus_frame. */
1472 dpyinfo
->x_focus_frame
= frame
;
1474 if (old_focus
&& old_focus
->auto_lower
)
1475 x_lower_frame (old_focus
);
1478 selected_frame
= frame
;
1479 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1481 Fselect_window (selected_frame
->selected_window
);
1482 choose_minibuf_frame ();
1485 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1486 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1488 pending_autoraise_frame
= 0;
1491 x_frame_rehighlight (dpyinfo
);
1494 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1497 x_mouse_leave (dpyinfo
)
1498 struct x_display_info
*dpyinfo
;
1500 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1503 /* The focus has changed, or we have redirected a frame's focus to
1504 another frame (this happens when a frame uses a surrogate
1505 minibuffer frame). Shift the highlight as appropriate.
1507 The FRAME argument doesn't necessarily have anything to do with which
1508 frame is being highlighted or unhighlighted; we only use it to find
1509 the appropriate X display info. */
1511 XTframe_rehighlight (frame
)
1512 struct frame
*frame
;
1514 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
1518 x_frame_rehighlight (dpyinfo
)
1519 struct x_display_info
*dpyinfo
;
1521 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1523 if (dpyinfo
->x_focus_frame
)
1525 dpyinfo
->x_highlight_frame
1526 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
1527 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
1528 : dpyinfo
->x_focus_frame
);
1529 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
1531 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
1532 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1536 dpyinfo
->x_highlight_frame
= 0;
1538 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
1541 frame_unhighlight (old_highlight
);
1542 if (dpyinfo
->x_highlight_frame
)
1543 frame_highlight (dpyinfo
->x_highlight_frame
);
1547 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1549 /* Initialize mode_switch_bit and modifier_meaning. */
1551 x_find_modifier_meanings (dpyinfo
)
1552 struct x_display_info
*dpyinfo
;
1554 int min_code
, max_code
;
1557 XModifierKeymap
*mods
;
1559 dpyinfo
->meta_mod_mask
= 0;
1560 dpyinfo
->shift_lock_mask
= 0;
1561 dpyinfo
->alt_mod_mask
= 0;
1562 dpyinfo
->super_mod_mask
= 0;
1563 dpyinfo
->hyper_mod_mask
= 0;
1566 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1568 min_code
= dpyinfo
->display
->min_keycode
;
1569 max_code
= dpyinfo
->display
->max_keycode
;
1572 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1573 min_code
, max_code
- min_code
+ 1,
1575 mods
= XGetModifierMapping (dpyinfo
->display
);
1577 /* Scan the modifier table to see which modifier bits the Meta and
1578 Alt keysyms are on. */
1580 int row
, col
; /* The row and column in the modifier table. */
1582 for (row
= 3; row
< 8; row
++)
1583 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1586 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1588 /* Zeroes are used for filler. Skip them. */
1592 /* Are any of this keycode's keysyms a meta key? */
1596 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1598 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1604 dpyinfo
->meta_mod_mask
|= (1 << row
);
1609 dpyinfo
->alt_mod_mask
|= (1 << row
);
1614 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1619 dpyinfo
->super_mod_mask
|= (1 << row
);
1623 /* Ignore this if it's not on the lock modifier. */
1624 if ((1 << row
) == LockMask
)
1625 dpyinfo
->shift_lock_mask
= LockMask
;
1633 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1634 if (! dpyinfo
->meta_mod_mask
)
1636 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1637 dpyinfo
->alt_mod_mask
= 0;
1640 /* If some keys are both alt and meta,
1641 make them just meta, not alt. */
1642 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1644 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1647 XFree ((char *) syms
);
1648 XFreeModifiermap (mods
);
1651 /* Convert between the modifier bits X uses and the modifier bits
1654 x_x_to_emacs_modifiers (dpyinfo
, state
)
1655 struct x_display_info
*dpyinfo
;
1658 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1659 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1660 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1661 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1662 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1663 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1667 x_emacs_to_x_modifiers (dpyinfo
, state
)
1668 struct x_display_info
*dpyinfo
;
1671 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1672 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1673 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1674 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1675 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1676 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1679 /* Convert a keysym to its name. */
1682 x_get_keysym_name (keysym
)
1688 value
= XKeysymToString (keysym
);
1694 /* Mouse clicks and mouse movement. Rah. */
1696 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1697 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1698 that the glyph at X, Y occupies, if BOUNDS != 0.
1699 If NOCLIP is nonzero, do not force the value into range. */
1702 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1704 register int pix_x
, pix_y
;
1705 register int *x
, *y
;
1709 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1710 even for negative values. */
1712 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
1714 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
1716 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1717 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1721 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
1722 bounds
->height
= f
->output_data
.x
->line_height
;
1723 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1724 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1731 else if (pix_x
> f
->width
)
1736 else if (pix_y
> f
->height
)
1745 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1748 register int *pix_x
, *pix_y
;
1750 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1751 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1754 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1756 If the event is a button press, then note that we have grabbed
1760 construct_mouse_click (result
, event
, f
)
1761 struct input_event
*result
;
1762 XButtonEvent
*event
;
1765 /* Make the event type no_event; we'll change that when we decide
1767 result
->kind
= mouse_click
;
1768 result
->code
= event
->button
- Button1
;
1769 result
->timestamp
= event
->time
;
1770 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1772 | (event
->type
== ButtonRelease
1780 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1781 XSETFASTINT (result
->x
, column
);
1782 XSETFASTINT (result
->y
, row
);
1784 XSETINT (result
->x
, event
->x
);
1785 XSETINT (result
->y
, event
->y
);
1786 XSETFRAME (result
->frame_or_window
, f
);
1790 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1793 construct_menu_click (result
, event
, f
)
1794 struct input_event
*result
;
1795 XButtonEvent
*event
;
1798 /* Make the event type no_event; we'll change that when we decide
1800 result
->kind
= mouse_click
;
1801 XSETINT (result
->code
, event
->button
- Button1
);
1802 result
->timestamp
= event
->time
;
1803 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1805 | (event
->type
== ButtonRelease
1809 XSETINT (result
->x
, event
->x
);
1810 XSETINT (result
->y
, -1);
1811 XSETFRAME (result
->frame_or_window
, f
);
1814 /* Function to report a mouse movement to the mainstream Emacs code.
1815 The input handler calls this.
1817 We have received a mouse movement event, which is given in *event.
1818 If the mouse is over a different glyph than it was last time, tell
1819 the mainstream emacs code by setting mouse_moved. If not, ask for
1820 another motion event, so we can check again the next time it moves. */
1823 note_mouse_movement (frame
, event
)
1825 XMotionEvent
*event
;
1827 last_mouse_movement_time
= event
->time
;
1829 if (event
->window
!= FRAME_X_WINDOW (frame
))
1831 frame
->mouse_moved
= 1;
1832 last_mouse_scroll_bar
= Qnil
;
1834 note_mouse_highlight (frame
, -1, -1);
1836 /* Ask for another mouse motion event. */
1839 Window dummy_window
;
1841 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1842 &dummy_window
, &dummy_window
,
1843 &dummy
, &dummy
, &dummy
, &dummy
,
1844 (unsigned int *) &dummy
);
1848 /* Has the mouse moved off the glyph it was on at the last sighting? */
1849 else if (event
->x
< last_mouse_glyph
.x
1850 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1851 || event
->y
< last_mouse_glyph
.y
1852 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1854 frame
->mouse_moved
= 1;
1855 last_mouse_scroll_bar
= Qnil
;
1857 note_mouse_highlight (frame
, event
->x
, event
->y
);
1859 /* Ask for another mouse motion event. */
1862 Window dummy_window
;
1864 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1865 &dummy_window
, &dummy_window
,
1866 &dummy
, &dummy
, &dummy
, &dummy
,
1867 (unsigned int *) &dummy
);
1872 /* It's on the same glyph. Call XQueryPointer so we'll get an
1873 event the next time the mouse moves and we can see if it's
1874 *still* on the same glyph. */
1876 Window dummy_window
;
1878 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1879 &dummy_window
, &dummy_window
,
1880 &dummy
, &dummy
, &dummy
, &dummy
,
1881 (unsigned int *) &dummy
);
1885 /* This is used for debugging, to turn off note_mouse_highlight. */
1886 static int disable_mouse_highlight
;
1888 /* Take proper action when the mouse has moved to position X, Y on frame F
1889 as regards highlighting characters that have mouse-face properties.
1890 Also dehighlighting chars where the mouse was before.
1891 X and Y can be negative or out of range. */
1894 note_mouse_highlight (f
, x
, y
)
1898 int row
, column
, portion
;
1899 XRectangle new_glyph
;
1903 if (disable_mouse_highlight
)
1906 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1907 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1908 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1910 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1915 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1919 /* Find out which glyph the mouse is on. */
1920 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1921 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1923 /* Which window is that in? */
1924 window
= window_from_coordinates (f
, column
, row
, &portion
);
1925 w
= XWINDOW (window
);
1927 /* If we were displaying active text in another window, clear that. */
1928 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1929 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1931 /* Are we in a window whose display is up to date?
1932 And verify the buffer's text has not changed. */
1933 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1934 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1935 && EQ (w
->window_end_valid
, w
->buffer
)
1936 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1938 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1941 /* Find which buffer position the mouse corresponds to. */
1942 for (i
= column
; i
>= 0; i
--)
1946 /* Is it outside the displayed active region (if any)? */
1948 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1949 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1950 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1951 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1952 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1953 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1954 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1955 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1956 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1958 Lisp_Object mouse_face
, overlay
, position
;
1959 Lisp_Object
*overlay_vec
;
1960 int len
, noverlays
, ignor1
;
1961 struct buffer
*obuf
;
1964 /* If we get an out-of-range value, return now; avoid an error. */
1965 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1968 /* Make the window's buffer temporarily current for
1969 overlays_at and compute_char_face. */
1970 obuf
= current_buffer
;
1971 current_buffer
= XBUFFER (w
->buffer
);
1977 /* Yes. Clear the display of the old active region, if any. */
1978 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1980 /* Is this char mouse-active? */
1981 XSETINT (position
, pos
);
1984 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1986 /* Put all the overlays we want in a vector in overlay_vec.
1987 Store the length in len. */
1988 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1990 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1992 /* Find the highest priority overlay that has a mouse-face prop. */
1994 for (i
= 0; i
< noverlays
; i
++)
1996 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1997 if (!NILP (mouse_face
))
1999 overlay
= overlay_vec
[i
];
2004 /* If no overlay applies, get a text property. */
2006 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2008 /* Handle the overlay case. */
2009 if (! NILP (overlay
))
2011 /* Find the range of text around this char that
2012 should be active. */
2013 Lisp_Object before
, after
;
2016 before
= Foverlay_start (overlay
);
2017 after
= Foverlay_end (overlay
);
2018 /* Record this as the current active region. */
2019 fast_find_position (window
, before
,
2020 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2021 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2022 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2023 = !fast_find_position (window
, after
,
2024 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2025 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2026 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2027 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2028 = compute_char_face (f
, w
, pos
, 0, 0,
2029 &ignore
, pos
+ 1, 1);
2031 /* Display it as active. */
2032 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2034 /* Handle the text property case. */
2035 else if (! NILP (mouse_face
))
2037 /* Find the range of text around this char that
2038 should be active. */
2039 Lisp_Object before
, after
, beginning
, end
;
2042 beginning
= Fmarker_position (w
->start
);
2043 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2044 - XFASTINT (w
->window_end_pos
)));
2046 = Fprevious_single_property_change (make_number (pos
+ 1),
2048 w
->buffer
, beginning
);
2050 = Fnext_single_property_change (position
, Qmouse_face
,
2052 /* Record this as the current active region. */
2053 fast_find_position (window
, before
,
2054 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2055 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2056 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2057 = !fast_find_position (window
, after
,
2058 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2059 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2060 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2061 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2062 = compute_char_face (f
, w
, pos
, 0, 0,
2063 &ignore
, pos
+ 1, 1);
2065 /* Display it as active. */
2066 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2070 current_buffer
= obuf
;
2075 /* Find the row and column of position POS in window WINDOW.
2076 Store them in *COLUMNP and *ROWP.
2077 This assumes display in WINDOW is up to date.
2078 If POS is above start of WINDOW, return coords
2079 of start of first screen line.
2080 If POS is after end of WINDOW, return coords of end of last screen line.
2082 Value is 1 if POS is in range, 0 if it was off screen. */
2085 fast_find_position (window
, pos
, columnp
, rowp
)
2088 int *columnp
, *rowp
;
2090 struct window
*w
= XWINDOW (window
);
2091 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2096 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2097 int width
= window_internal_width (w
);
2100 int maybe_next_line
= 0;
2102 /* Find the right row. */
2107 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2108 if (linestart
> pos
)
2110 /* If the position sought is the end of the buffer,
2111 don't include the blank lines at the bottom of the window. */
2112 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2114 maybe_next_line
= 1;
2121 /* Find the right column with in it. */
2122 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2124 for (i
= 0; i
< width
; i
++)
2126 if (charstarts
[left
+ i
] == pos
)
2129 *columnp
= i
+ left
;
2132 else if (charstarts
[left
+ i
] > pos
)
2134 else if (charstarts
[left
+ i
] > 0)
2138 /* If we're looking for the end of the buffer,
2139 and we didn't find it in the line we scanned,
2140 use the start of the following line. */
2141 if (maybe_next_line
)
2152 /* Display the active region described by mouse_face_*
2153 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2156 show_mouse_face (dpyinfo
, hl
)
2157 struct x_display_info
*dpyinfo
;
2160 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2161 int width
= window_internal_width (w
);
2162 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2165 int old_curs_x
= curs_x
;
2166 int old_curs_y
= curs_y
;
2168 /* Set these variables temporarily
2169 so that if we have to turn the cursor off and on again
2170 we will put it back at the same place. */
2171 curs_x
= f
->phys_cursor_x
;
2172 curs_y
= f
->phys_cursor_y
;
2174 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2175 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2177 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2178 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2180 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2181 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2183 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2185 /* If the cursor's in the text we are about to rewrite,
2186 turn the cursor off. */
2188 && curs_x
>= column
- 1
2189 && curs_x
<= endcolumn
)
2191 x_display_cursor (f
, 0);
2196 CHAR_TO_PIXEL_COL (f
, column
),
2197 CHAR_TO_PIXEL_ROW (f
, i
),
2198 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2200 /* Highlight with mouse face if hl > 0. */
2204 /* If we turned the cursor off, turn it back on. */
2206 x_display_cursor (f
, 1);
2208 curs_x
= old_curs_x
;
2209 curs_y
= old_curs_y
;
2211 /* Change the mouse cursor according to the value of HL. */
2213 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2214 f
->output_data
.x
->cross_cursor
);
2216 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2217 f
->output_data
.x
->text_cursor
);
2220 /* Clear out the mouse-highlighted active region.
2221 Redraw it unhighlighted first. */
2224 clear_mouse_face (dpyinfo
)
2225 struct x_display_info
*dpyinfo
;
2227 if (! NILP (dpyinfo
->mouse_face_window
))
2228 show_mouse_face (dpyinfo
, 0);
2230 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2231 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2232 dpyinfo
->mouse_face_window
= Qnil
;
2235 static struct scroll_bar
*x_window_to_scroll_bar ();
2236 static void x_scroll_bar_report_motion ();
2238 /* Return the current position of the mouse.
2239 *fp should be a frame which indicates which display to ask about.
2241 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2242 and *part to the frame, window, and scroll bar part that the mouse
2243 is over. Set *x and *y to the portion and whole of the mouse's
2244 position on the scroll bar.
2246 If the mouse movement started elsewhere, set *fp to the frame the
2247 mouse is on, *bar_window to nil, and *x and *y to the character cell
2250 Set *time to the server timestamp for the time at which the mouse
2251 was at this position.
2253 Don't store anything if we don't have a valid set of values to report.
2255 This clears the mouse_moved flag, so we can wait for the next mouse
2256 movement. This also calls XQueryPointer, which will cause the
2257 server to give us another MotionNotify when the mouse moves
2261 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2264 Lisp_Object
*bar_window
;
2265 enum scroll_bar_part
*part
;
2267 unsigned long *time
;
2273 if (! NILP (last_mouse_scroll_bar
))
2274 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2280 Window dummy_window
;
2283 Lisp_Object frame
, tail
;
2285 /* Clear the mouse-moved flag for every frame on this display. */
2286 FOR_EACH_FRAME (tail
, frame
)
2287 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2288 XFRAME (frame
)->mouse_moved
= 0;
2290 last_mouse_scroll_bar
= Qnil
;
2292 /* Figure out which root window we're on. */
2293 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2294 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2296 /* The root window which contains the pointer. */
2299 /* Trash which we can't trust if the pointer is on
2300 a different screen. */
2303 /* The position on that root window. */
2306 /* More trash we can't trust. */
2309 /* Modifier keys and pointer buttons, about which
2311 (unsigned int *) &dummy
);
2313 /* Now we have a position on the root; find the innermost window
2314 containing the pointer. */
2318 int parent_x
, parent_y
;
2322 /* XTranslateCoordinates can get errors if the window
2323 structure is changing at the same time this function
2324 is running. So at least we must not crash from them. */
2326 x_catch_errors (FRAME_X_DISPLAY (*fp
));
2328 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2329 && FRAME_LIVE_P (last_mouse_frame
))
2331 /* If mouse was grabbed on a frame, give coords for that frame
2332 even if the mouse is now outside it. */
2333 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2335 /* From-window, to-window. */
2336 root
, FRAME_X_WINDOW (last_mouse_frame
),
2338 /* From-position, to-position. */
2339 root_x
, root_y
, &win_x
, &win_y
,
2343 f1
= last_mouse_frame
;
2349 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2351 /* From-window, to-window. */
2354 /* From-position, to-position. */
2355 root_x
, root_y
, &win_x
, &win_y
,
2360 if (child
== None
|| child
== win
)
2368 /* Now we know that:
2369 win is the innermost window containing the pointer
2370 (XTC says it has no child containing the pointer),
2371 win_x and win_y are the pointer's position in it
2372 (XTC did this the last time through), and
2373 parent_x and parent_y are the pointer's position in win's parent.
2374 (They are what win_x and win_y were when win was child.
2375 If win is the root window, it has no parent, and
2376 parent_{x,y} are invalid, but that's okay, because we'll
2377 never use them in that case.) */
2379 /* Is win one of our frames? */
2380 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2383 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2386 x_uncatch_errors (FRAME_X_DISPLAY (*fp
));
2388 /* If not, is it one of our scroll bars? */
2391 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2395 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2401 if (f1
== 0 && insist
)
2402 f1
= selected_frame
;
2406 int ignore1
, ignore2
;
2408 /* Ok, we found a frame. Store all the values. */
2410 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2412 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2418 XSETINT (*x
, win_x
);
2419 XSETINT (*y
, win_y
);
2420 *time
= last_mouse_movement_time
;
2428 /* Scroll bar support. */
2430 /* Given an X window ID, find the struct scroll_bar which manages it.
2431 This can be called in GC, so we have to make sure to strip off mark
2433 static struct scroll_bar
*
2434 x_window_to_scroll_bar (window_id
)
2437 Lisp_Object tail
, frame
;
2439 for (tail
= Vframe_list
;
2440 XGCTYPE (tail
) == Lisp_Cons
;
2441 tail
= XCONS (tail
)->cdr
)
2443 Lisp_Object frame
, bar
, condemned
;
2445 frame
= XCONS (tail
)->car
;
2446 /* All elements of Vframe_list should be frames. */
2447 if (! GC_FRAMEP (frame
))
2450 /* Scan this frame's scroll bar list for a scroll bar with the
2452 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2453 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2454 /* This trick allows us to search both the ordinary and
2455 condemned scroll bar lists with one loop. */
2456 ! GC_NILP (bar
) || (bar
= condemned
,
2459 bar
= XSCROLL_BAR (bar
)->next
)
2460 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2461 return XSCROLL_BAR (bar
);
2467 /* Open a new X window to serve as a scroll bar, and return the
2468 scroll bar vector for it. */
2469 static struct scroll_bar
*
2470 x_scroll_bar_create (window
, top
, left
, width
, height
)
2471 struct window
*window
;
2472 int top
, left
, width
, height
;
2474 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2475 struct scroll_bar
*bar
2476 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2481 XSetWindowAttributes a
;
2483 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2484 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2485 | ButtonMotionMask
| PointerMotionHintMask
2487 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2489 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2494 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2495 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2496 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2497 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2498 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2499 sb_widget
= XtCreateManagedWidget ("box",
2501 f
->output_data
.x
->edit_widget
, al
, ac
);
2502 SET_SCROLL_BAR_X_WINDOW
2503 (bar
, sb_widget
->core
.window
);
2505 SET_SCROLL_BAR_X_WINDOW
2507 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2509 /* Position and size of scroll bar. */
2510 left
, top
, width
, height
,
2512 /* Border width, depth, class, and visual. */
2513 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2519 XSETWINDOW (bar
->window
, window
);
2520 XSETINT (bar
->top
, top
);
2521 XSETINT (bar
->left
, left
);
2522 XSETINT (bar
->width
, width
);
2523 XSETINT (bar
->height
, height
);
2524 XSETINT (bar
->start
, 0);
2525 XSETINT (bar
->end
, 0);
2526 bar
->dragging
= Qnil
;
2528 /* Add bar to its frame's list of scroll bars. */
2529 bar
->next
= FRAME_SCROLL_BARS (f
);
2531 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2532 if (! NILP (bar
->next
))
2533 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2535 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2542 /* Draw BAR's handle in the proper position.
2543 If the handle is already drawn from START to END, don't bother
2544 redrawing it, unless REBUILD is non-zero; in that case, always
2545 redraw it. (REBUILD is handy for drawing the handle after expose
2548 Normally, we want to constrain the start and end of the handle to
2549 fit inside its rectangle, but if the user is dragging the scroll bar
2550 handle, we want to let them drag it down all the way, so that the
2551 bar's top is as far down as it goes; otherwise, there's no way to
2552 move to the very end of the buffer. */
2554 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2555 struct scroll_bar
*bar
;
2559 int dragging
= ! NILP (bar
->dragging
);
2560 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2561 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2562 GC gc
= f
->output_data
.x
->normal_gc
;
2564 /* If the display is already accurate, do nothing. */
2566 && start
== XINT (bar
->start
)
2567 && end
== XINT (bar
->end
))
2573 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2574 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2575 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2577 /* Make sure the values are reasonable, and try to preserve
2578 the distance between start and end. */
2580 int length
= end
- start
;
2584 else if (start
> top_range
)
2586 end
= start
+ length
;
2590 else if (end
> top_range
&& ! dragging
)
2594 /* Store the adjusted setting in the scroll bar. */
2595 XSETINT (bar
->start
, start
);
2596 XSETINT (bar
->end
, end
);
2598 /* Clip the end position, just for display. */
2599 if (end
> top_range
)
2602 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2603 below top positions, to make sure the handle is always at least
2604 that many pixels tall. */
2605 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2607 /* Draw the empty space above the handle. Note that we can't clear
2608 zero-height areas; that means "clear to end of window." */
2610 XClearArea (FRAME_X_DISPLAY (f
), w
,
2612 /* x, y, width, height, and exposures. */
2613 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2614 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2615 inside_width
, start
,
2618 /* Draw the handle itself. */
2619 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2621 /* x, y, width, height */
2622 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2623 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2624 inside_width
, end
- start
);
2627 /* Draw the empty space below the handle. Note that we can't
2628 clear zero-height areas; that means "clear to end of window." */
2629 if (end
< inside_height
)
2630 XClearArea (FRAME_X_DISPLAY (f
), w
,
2632 /* x, y, width, height, and exposures. */
2633 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2634 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2635 inside_width
, inside_height
- end
,
2643 /* Move a scroll bar around on the screen, to accommodate changing
2644 window configurations. */
2646 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2647 struct scroll_bar
*bar
;
2648 int top
, left
, width
, height
;
2650 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2651 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2657 unsigned int mask
= 0;
2664 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2665 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2666 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2667 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2670 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2674 XSETINT (bar
->left
, left
);
2675 XSETINT (bar
->top
, top
);
2676 XSETINT (bar
->width
, width
);
2677 XSETINT (bar
->height
, height
);
2682 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2685 x_scroll_bar_remove (bar
)
2686 struct scroll_bar
*bar
;
2688 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2692 /* Destroy the window. */
2693 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2695 /* Disassociate this scroll bar from its window. */
2696 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2701 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2702 that we are displaying PORTION characters out of a total of WHOLE
2703 characters, starting at POSITION. If WINDOW has no scroll bar,
2706 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2707 struct window
*window
;
2708 int portion
, whole
, position
;
2710 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2711 int top
= XINT (window
->top
);
2712 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2713 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2715 /* Where should this scroll bar be, pixelwise? */
2716 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2717 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2719 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2720 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2721 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2722 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2724 struct scroll_bar
*bar
;
2726 /* Does the scroll bar exist yet? */
2727 if (NILP (window
->vertical_scroll_bar
))
2728 bar
= x_scroll_bar_create (window
,
2729 pixel_top
, pixel_left
,
2730 pixel_width
, pixel_height
);
2733 /* It may just need to be moved and resized. */
2734 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2735 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2738 /* Set the scroll bar's current state, unless we're currently being
2740 if (NILP (bar
->dragging
))
2742 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2745 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2748 int start
= ((double) position
* top_range
) / whole
;
2749 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2751 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2755 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2759 /* The following three hooks are used when we're doing a thorough
2760 redisplay of the frame. We don't explicitly know which scroll bars
2761 are going to be deleted, because keeping track of when windows go
2762 away is a real pain - "Can you say set-window-configuration, boys
2763 and girls?" Instead, we just assert at the beginning of redisplay
2764 that *all* scroll bars are to be removed, and then save a scroll bar
2765 from the fiery pit when we actually redisplay its window. */
2767 /* Arrange for all scroll bars on FRAME to be removed at the next call
2768 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2769 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2771 XTcondemn_scroll_bars (frame
)
2774 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2775 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2778 bar
= FRAME_SCROLL_BARS (frame
);
2779 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2780 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2781 XSCROLL_BAR (bar
)->prev
= Qnil
;
2782 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2783 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2784 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2788 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2789 Note that WINDOW isn't necessarily condemned at all. */
2791 XTredeem_scroll_bar (window
)
2792 struct window
*window
;
2794 struct scroll_bar
*bar
;
2796 /* We can't redeem this window's scroll bar if it doesn't have one. */
2797 if (NILP (window
->vertical_scroll_bar
))
2800 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2802 /* Unlink it from the condemned list. */
2804 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2806 if (NILP (bar
->prev
))
2808 /* If the prev pointer is nil, it must be the first in one of
2810 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2811 /* It's not condemned. Everything's fine. */
2813 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2814 window
->vertical_scroll_bar
))
2815 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2817 /* If its prev pointer is nil, it must be at the front of
2818 one or the other! */
2822 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2824 if (! NILP (bar
->next
))
2825 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2827 bar
->next
= FRAME_SCROLL_BARS (f
);
2829 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2830 if (! NILP (bar
->next
))
2831 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2835 /* Remove all scroll bars on FRAME that haven't been saved since the
2836 last call to `*condemn_scroll_bars_hook'. */
2838 XTjudge_scroll_bars (f
)
2841 Lisp_Object bar
, next
;
2843 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2845 /* Clear out the condemned list now so we won't try to process any
2846 more events on the hapless scroll bars. */
2847 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2849 for (; ! NILP (bar
); bar
= next
)
2851 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2853 x_scroll_bar_remove (b
);
2856 b
->next
= b
->prev
= Qnil
;
2859 /* Now there should be no references to the condemned scroll bars,
2860 and they should get garbage-collected. */
2864 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2866 This may be called from a signal handler, so we have to ignore GC
2869 x_scroll_bar_expose (bar
, event
)
2870 struct scroll_bar
*bar
;
2873 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2874 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2875 GC gc
= f
->output_data
.x
->normal_gc
;
2879 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2881 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2882 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2884 /* x, y, width, height */
2885 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2890 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2891 is set to something other than no_event, it is enqueued.
2893 This may be called from a signal handler, so we have to ignore GC
2896 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2897 struct scroll_bar
*bar
;
2899 struct input_event
*emacs_event
;
2901 if (! GC_WINDOWP (bar
->window
))
2904 emacs_event
->kind
= scroll_bar_click
;
2905 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2906 emacs_event
->modifiers
2907 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2908 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2909 event
->xbutton
.state
)
2910 | (event
->type
== ButtonRelease
2913 emacs_event
->frame_or_window
= bar
->window
;
2914 emacs_event
->timestamp
= event
->xbutton
.time
;
2917 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2919 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2920 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2923 if (y
> top_range
) y
= top_range
;
2925 if (y
< XINT (bar
->start
))
2926 emacs_event
->part
= scroll_bar_above_handle
;
2927 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2928 emacs_event
->part
= scroll_bar_handle
;
2930 emacs_event
->part
= scroll_bar_below_handle
;
2932 /* Just because the user has clicked on the handle doesn't mean
2933 they want to drag it. Lisp code needs to be able to decide
2934 whether or not we're dragging. */
2936 /* If the user has just clicked on the handle, record where they're
2938 if (event
->type
== ButtonPress
2939 && emacs_event
->part
== scroll_bar_handle
)
2940 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2943 /* If the user has released the handle, set it to its final position. */
2944 if (event
->type
== ButtonRelease
2945 && ! NILP (bar
->dragging
))
2947 int new_start
= y
- XINT (bar
->dragging
);
2948 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2950 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2951 bar
->dragging
= Qnil
;
2954 /* Same deal here as the other #if 0. */
2956 /* Clicks on the handle are always reported as occurring at the top of
2958 if (emacs_event
->part
== scroll_bar_handle
)
2959 emacs_event
->x
= bar
->start
;
2961 XSETINT (emacs_event
->x
, y
);
2963 XSETINT (emacs_event
->x
, y
);
2966 XSETINT (emacs_event
->y
, top_range
);
2970 /* Handle some mouse motion while someone is dragging the scroll bar.
2972 This may be called from a signal handler, so we have to ignore GC
2975 x_scroll_bar_note_movement (bar
, event
)
2976 struct scroll_bar
*bar
;
2979 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
2981 last_mouse_movement_time
= event
->xmotion
.time
;
2984 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2986 /* If we're dragging the bar, display it. */
2987 if (! GC_NILP (bar
->dragging
))
2989 /* Where should the handle be now? */
2990 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2992 if (new_start
!= XINT (bar
->start
))
2994 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2996 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3000 /* Call XQueryPointer so we'll get an event the next time the mouse
3001 moves and we can see *still* on the same position. */
3004 Window dummy_window
;
3006 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3007 &dummy_window
, &dummy_window
,
3008 &dummy
, &dummy
, &dummy
, &dummy
,
3009 (unsigned int *) &dummy
);
3013 /* Return information to the user about the current position of the mouse
3014 on the scroll bar. */
3016 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3018 Lisp_Object
*bar_window
;
3019 enum scroll_bar_part
*part
;
3021 unsigned long *time
;
3023 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3024 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3025 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3027 Window dummy_window
;
3029 unsigned int dummy_mask
;
3033 /* Get the mouse's position relative to the scroll bar window, and
3035 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3037 /* Root, child, root x and root y. */
3038 &dummy_window
, &dummy_window
,
3039 &dummy_coord
, &dummy_coord
,
3041 /* Position relative to scroll bar. */
3044 /* Mouse buttons and modifier keys. */
3050 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3052 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3054 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3056 if (! NILP (bar
->dragging
))
3057 win_y
-= XINT (bar
->dragging
);
3061 if (win_y
> top_range
)
3065 *bar_window
= bar
->window
;
3067 if (! NILP (bar
->dragging
))
3068 *part
= scroll_bar_handle
;
3069 else if (win_y
< XINT (bar
->start
))
3070 *part
= scroll_bar_above_handle
;
3071 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3072 *part
= scroll_bar_handle
;
3074 *part
= scroll_bar_below_handle
;
3076 XSETINT (*x
, win_y
);
3077 XSETINT (*y
, top_range
);
3080 last_mouse_scroll_bar
= Qnil
;
3083 *time
= last_mouse_movement_time
;
3089 /* The screen has been cleared so we may have changed foreground or
3090 background colors, and the scroll bars may need to be redrawn.
3091 Clear out the scroll bars, and ask for expose events, so we can
3094 x_scroll_bar_clear (f
)
3099 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3100 bar
= XSCROLL_BAR (bar
)->next
)
3101 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3105 /* This processes Expose events from the menubar specific X event
3106 loop in xmenu.c. This allows to redisplay the frame if necessary
3107 when handling menubar or popup items. */
3110 process_expose_from_menu (event
)
3114 struct x_display_info
*dpyinfo
;
3118 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3119 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3122 if (f
->async_visible
== 0)
3124 f
->async_visible
= 1;
3125 f
->async_iconified
= 0;
3126 SET_FRAME_GARBAGED (f
);
3130 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3131 event
.xexpose
.x
, event
.xexpose
.y
,
3132 event
.xexpose
.width
, event
.xexpose
.height
);
3137 struct scroll_bar
*bar
3138 = x_window_to_scroll_bar (event
.xexpose
.window
);
3141 x_scroll_bar_expose (bar
, &event
);
3147 /* Define a queue to save up SelectionRequest events for later handling. */
3149 struct selection_event_queue
3152 struct selection_event_queue
*next
;
3155 static struct selection_event_queue
*queue
;
3157 /* Nonzero means queue up certain events--don't process them yet. */
3158 static int x_queue_selection_requests
;
3160 /* Queue up an X event *EVENT, to be processed later. */
3163 x_queue_event (f
, event
)
3167 struct selection_event_queue
*queue_tmp
3168 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3170 if (queue_tmp
!= NULL
)
3172 queue_tmp
->event
= *event
;
3173 queue_tmp
->next
= queue
;
3178 /* Take all the queued events and put them back
3179 so that they get processed afresh. */
3182 x_unqueue_events (display
)
3185 while (queue
!= NULL
)
3187 struct selection_event_queue
*queue_tmp
= queue
;
3188 XPutBackEvent (display
, &queue_tmp
->event
);
3189 queue
= queue_tmp
->next
;
3190 free ((char *)queue_tmp
);
3194 /* Start queuing SelectionRequest events. */
3197 x_start_queuing_selection_requests (display
)
3200 x_queue_selection_requests
++;
3203 /* Stop queuing SelectionRequest events. */
3206 x_stop_queuing_selection_requests (display
)
3209 x_queue_selection_requests
--;
3210 x_unqueue_events (display
);
3213 /* The main X event-reading loop - XTread_socket. */
3215 /* Timestamp of enter window event. This is only used by XTread_socket,
3216 but we have to put it out here, since static variables within functions
3217 sometimes don't work. */
3218 static Time enter_timestamp
;
3220 /* This holds the state XLookupString needs to implement dead keys
3221 and other tricks known as "compose processing". _X Window System_
3222 says that a portable program can't use this, but Stephen Gildea assures
3223 me that letting the compiler initialize it to zeros will work okay.
3225 This must be defined outside of XTread_socket, for the same reasons
3226 given for enter_timestamp, above. */
3227 static XComposeStatus compose_status
;
3229 /* Record the last 100 characters stored
3230 to help debug the loss-of-chars-during-GC problem. */
3231 static int temp_index
;
3232 static short temp_buffer
[100];
3234 /* Set this to nonzero to fake an "X I/O error"
3235 on a particular display. */
3236 struct x_display_info
*XTread_socket_fake_io_error
;
3238 /* When we find no input here, we occasionally do a no-op command
3239 to verify that the X server is still running and we can still talk with it.
3240 We try all the open displays, one by one.
3241 This variable is used for cycling thru the displays. */
3242 static struct x_display_info
*next_noop_dpyinfo
;
3244 /* Read events coming from the X server.
3245 This routine is called by the SIGIO handler.
3246 We return as soon as there are no more events to be read.
3248 Events representing keys are stored in buffer BUFP,
3249 which can hold up to NUMCHARS characters.
3250 We return the number of characters stored into the buffer,
3251 thus pretending to be `read'.
3253 WAITP is nonzero if we should block until input arrives.
3254 EXPECTED is nonzero if the caller knows input is available. */
3257 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3259 register struct input_event
*bufp
;
3260 register int numchars
;
3267 int items_pending
; /* How many items are in the X queue. */
3270 int event_found
= 0;
3273 struct x_display_info
*dpyinfo
;
3275 Status status_return
;
3278 if (interrupt_input_blocked
)
3280 interrupt_input_pending
= 1;
3284 interrupt_input_pending
= 0;
3287 /* So people can tell when we have read the available input. */
3288 input_signal_count
++;
3291 abort (); /* Don't think this happens. */
3293 /* Find the display we are supposed to read input for.
3294 It's the one communicating on descriptor SD. */
3295 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3297 #if 0 /* This ought to be unnecessary; let's verify it. */
3299 /* If available, Xlib uses FIOSNBIO to make the socket
3300 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3301 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3302 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3303 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3304 #endif /* ! defined (FIOSNBIO) */
3307 #if 0 /* This code can't be made to work, with multiple displays,
3308 and appears not to be used on any system any more.
3309 Also keyboard.c doesn't turn O_NDELAY on and off
3310 for X connections. */
3313 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3315 extern int read_alarm_should_throw
;
3316 read_alarm_should_throw
= 1;
3317 XPeekEvent (dpyinfo
->display
, &event
);
3318 read_alarm_should_throw
= 0;
3320 #endif /* HAVE_SELECT */
3324 /* For debugging, this gives a way to fake an I/O error. */
3325 if (dpyinfo
== XTread_socket_fake_io_error
)
3327 XTread_socket_fake_io_error
= 0;
3328 x_io_error_quitter (dpyinfo
->display
);
3331 while (XPending (dpyinfo
->display
) != 0)
3333 XNextEvent (dpyinfo
->display
, &event
);
3340 if (event
.xclient
.message_type
3341 == dpyinfo
->Xatom_wm_protocols
3342 && event
.xclient
.format
== 32)
3344 if (event
.xclient
.data
.l
[0]
3345 == dpyinfo
->Xatom_wm_take_focus
)
3347 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3348 /* Since we set WM_TAKE_FOCUS, we must call
3349 XSetInputFocus explicitly. But not if f is null,
3350 since that might be an event for a deleted frame. */
3352 /* Not quite sure this is needed -pd */
3354 XSetICFocus (FRAME_XIC (f
));
3357 XSetInputFocus (event
.xclient
.display
,
3358 event
.xclient
.window
,
3359 RevertToPointerRoot
,
3360 event
.xclient
.data
.l
[1]);
3361 /* Not certain about handling scroll bars here */
3363 else if (event
.xclient
.data
.l
[0]
3364 == dpyinfo
->Xatom_wm_save_yourself
)
3366 /* Save state modify the WM_COMMAND property to
3367 something which can reinstate us. This notifies
3368 the session manager, who's looking for such a
3369 PropertyNotify. Can restart processing when
3370 a keyboard or mouse event arrives. */
3373 f
= x_top_window_to_frame (dpyinfo
,
3374 event
.xclient
.window
);
3376 /* This is just so we only give real data once
3377 for a single Emacs process. */
3378 if (f
== selected_frame
)
3379 XSetCommand (FRAME_X_DISPLAY (f
),
3380 event
.xclient
.window
,
3381 initial_argv
, initial_argc
);
3383 XSetCommand (FRAME_X_DISPLAY (f
),
3384 event
.xclient
.window
,
3388 else if (event
.xclient
.data
.l
[0]
3389 == dpyinfo
->Xatom_wm_delete_window
)
3392 = x_any_window_to_frame (dpyinfo
,
3393 event
.xclient
.window
);
3400 bufp
->kind
= delete_window_event
;
3401 XSETFRAME (bufp
->frame_or_window
, f
);
3409 else if (event
.xclient
.message_type
3410 == dpyinfo
->Xatom_wm_configure_denied
)
3413 else if (event
.xclient
.message_type
3414 == dpyinfo
->Xatom_wm_window_moved
)
3418 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3420 new_x
= event
.xclient
.data
.s
[0];
3421 new_y
= event
.xclient
.data
.s
[1];
3425 f
->output_data
.x
->left_pos
= new_x
;
3426 f
->output_data
.x
->top_pos
= new_y
;
3430 else if (event
.xclient
.message_type
3431 == dpyinfo
->Xatom_editres
)
3434 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3435 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3438 #endif /* HACK_EDITRES */
3442 case SelectionNotify
:
3443 #ifdef USE_X_TOOLKIT
3444 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3446 #endif /* not USE_X_TOOLKIT */
3447 x_handle_selection_notify (&event
);
3450 case SelectionClear
: /* Someone has grabbed ownership. */
3451 #ifdef USE_X_TOOLKIT
3452 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3454 #endif /* USE_X_TOOLKIT */
3456 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3461 bufp
->kind
= selection_clear_event
;
3462 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3463 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3464 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3465 bufp
->frame_or_window
= Qnil
;
3473 case SelectionRequest
: /* Someone wants our selection. */
3474 #ifdef USE_X_TOOLKIT
3475 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3477 #endif /* USE_X_TOOLKIT */
3478 if (x_queue_selection_requests
)
3479 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3483 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3488 bufp
->kind
= selection_request_event
;
3489 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3490 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3491 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3492 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3493 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3494 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3495 bufp
->frame_or_window
= Qnil
;
3503 case PropertyNotify
:
3504 #ifdef USE_X_TOOLKIT
3505 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3507 #endif /* not USE_X_TOOLKIT */
3508 x_handle_property_notify (&event
);
3511 case ReparentNotify
:
3512 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3516 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
3517 x_real_positions (f
, &x
, &y
);
3518 f
->output_data
.x
->left_pos
= x
;
3519 f
->output_data
.x
->top_pos
= y
;
3524 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3527 if (f
->async_visible
== 0)
3529 f
->async_visible
= 1;
3530 f
->async_iconified
= 0;
3531 SET_FRAME_GARBAGED (f
);
3534 dumprectangle (x_window_to_frame (dpyinfo
,
3535 event
.xexpose
.window
),
3536 event
.xexpose
.x
, event
.xexpose
.y
,
3537 event
.xexpose
.width
, event
.xexpose
.height
);
3541 struct scroll_bar
*bar
3542 = x_window_to_scroll_bar (event
.xexpose
.window
);
3545 x_scroll_bar_expose (bar
, &event
);
3546 #ifdef USE_X_TOOLKIT
3549 #endif /* USE_X_TOOLKIT */
3553 case GraphicsExpose
: /* This occurs when an XCopyArea's
3554 source area was obscured or not
3556 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3560 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3561 event
.xgraphicsexpose
.width
,
3562 event
.xgraphicsexpose
.height
);
3564 #ifdef USE_X_TOOLKIT
3567 #endif /* USE_X_TOOLKIT */
3570 case NoExpose
: /* This occurs when an XCopyArea's
3571 source area was completely
3576 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3577 if (f
) /* F may no longer exist if
3578 the frame was deleted. */
3580 /* While a frame is unmapped, display generation is
3581 disabled; you don't want to spend time updating a
3582 display that won't ever be seen. */
3583 f
->async_visible
= 0;
3584 /* We can't distinguish, from the event, whether the window
3585 has become iconified or invisible. So assume, if it
3586 was previously visible, than now it is iconified.
3587 We depend on x_make_frame_invisible to mark it iconified. */
3588 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3589 f
->async_iconified
= 1;
3591 bufp
->kind
= iconify_event
;
3592 XSETFRAME (bufp
->frame_or_window
, f
);
3600 /* We use x_top_window_to_frame because map events can come
3601 for subwindows and they don't mean that the frame is visible. */
3602 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
3605 f
->async_visible
= 1;
3606 f
->async_iconified
= 0;
3608 /* wait_reading_process_input will notice this and update
3609 the frame's display structures. */
3610 SET_FRAME_GARBAGED (f
);
3614 bufp
->kind
= deiconify_event
;
3615 XSETFRAME (bufp
->frame_or_window
, f
);
3621 /* Force a redisplay sooner or later
3622 to update the frame titles
3623 in case this is the second frame. */
3624 record_asynch_buffer_change ();
3628 /* Turn off processing if we become fully obscured. */
3629 case VisibilityNotify
:
3633 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
3637 KeySym keysym
, orig_keysym
;
3638 /* al%imercury@uunet.uu.net says that making this 81 instead of
3639 80 fixed a bug whereby meta chars made his Emacs hang. */
3640 unsigned char copy_buffer
[81];
3644 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3645 extra_keyboard_modifiers
);
3646 modifiers
= event
.xkey
.state
;
3648 /* This will have to go some day... */
3650 /* make_lispy_event turns chars into control chars.
3651 Don't do it here because XLookupString is too eager. */
3652 event
.xkey
.state
&= ~ControlMask
;
3653 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
3654 | dpyinfo
->super_mod_mask
3655 | dpyinfo
->hyper_mod_mask
3656 | dpyinfo
->alt_mod_mask
);
3661 /* The necessity of the following line took me
3662 a full work-day to decipher from the docs!! */
3663 if (XFilterEvent (&event
, None
))
3665 nbytes
= XmbLookupString (FRAME_XIC (f
),
3666 &event
.xkey
, copy_buffer
,
3671 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3672 80, &keysym
, &compose_status
);
3674 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3675 80, &keysym
, &compose_status
);
3678 orig_keysym
= keysym
;
3682 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3683 || keysym
== XK_Delete
3684 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3685 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3687 /* This recognizes the "extended function keys".
3688 It seems there's no cleaner way.
3689 Test IsModifierKey to avoid handling mode_switch
3691 || ((unsigned) (keysym
) >= XK_Select
3692 && (unsigned)(keysym
) < XK_KP_Space
)
3694 #ifdef XK_dead_circumflex
3695 || orig_keysym
== XK_dead_circumflex
3697 #ifdef XK_dead_grave
3698 || orig_keysym
== XK_dead_grave
3700 #ifdef XK_dead_tilde
3701 || orig_keysym
== XK_dead_tilde
3703 #ifdef XK_dead_diaeresis
3704 || orig_keysym
== XK_dead_diaeresis
3706 #ifdef XK_dead_macron
3707 || orig_keysym
== XK_dead_macron
3709 #ifdef XK_dead_degree
3710 || orig_keysym
== XK_dead_degree
3712 #ifdef XK_dead_acute
3713 || orig_keysym
== XK_dead_acute
3715 #ifdef XK_dead_cedilla
3716 || orig_keysym
== XK_dead_cedilla
3718 #ifdef XK_dead_breve
3719 || orig_keysym
== XK_dead_breve
3721 #ifdef XK_dead_ogonek
3722 || orig_keysym
== XK_dead_ogonek
3724 #ifdef XK_dead_caron
3725 || orig_keysym
== XK_dead_caron
3727 #ifdef XK_dead_doubleacute
3728 || orig_keysym
== XK_dead_doubleacute
3730 #ifdef XK_dead_abovedot
3731 || orig_keysym
== XK_dead_abovedot
3733 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3734 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3735 /* Any "vendor-specific" key is ok. */
3736 || (orig_keysym
& (1 << 28)))
3737 && ! (IsModifierKey (orig_keysym
)
3739 #ifdef XK_Mode_switch
3740 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3743 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3745 #endif /* not HAVE_X11R5 */
3748 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3750 temp_buffer
[temp_index
++] = keysym
;
3751 bufp
->kind
= non_ascii_keystroke
;
3752 bufp
->code
= keysym
;
3753 XSETFRAME (bufp
->frame_or_window
, f
);
3755 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3757 bufp
->timestamp
= event
.xkey
.time
;
3762 else if (numchars
> nbytes
)
3766 for (i
= 0; i
< nbytes
; i
++)
3768 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3770 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3771 bufp
->kind
= ascii_keystroke
;
3772 bufp
->code
= copy_buffer
[i
];
3773 XSETFRAME (bufp
->frame_or_window
, f
);
3775 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3777 bufp
->timestamp
= event
.xkey
.time
;
3792 /* Here's a possible interpretation of the whole
3793 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3794 FocusIn event, you have to get a FocusOut event before you
3795 relinquish the focus. If you haven't received a FocusIn event,
3796 then a mere LeaveNotify is enough to free you. */
3799 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3801 if (event
.xcrossing
.focus
) /* Entered Window */
3803 /* Avoid nasty pop/raise loops. */
3804 if (f
&& (!(f
->auto_raise
)
3806 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3808 x_new_focus_frame (dpyinfo
, f
);
3809 enter_timestamp
= event
.xcrossing
.time
;
3812 else if (f
== dpyinfo
->x_focus_frame
)
3813 x_new_focus_frame (dpyinfo
, 0);
3814 /* EnterNotify counts as mouse movement,
3815 so update things that depend on mouse position. */
3817 note_mouse_movement (f
, &event
.xmotion
);
3821 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3822 if (event
.xfocus
.detail
!= NotifyPointer
)
3823 dpyinfo
->x_focus_event_frame
= f
;
3825 x_new_focus_frame (dpyinfo
, f
);
3828 if (f
&& FRAME_XIC (f
))
3829 XSetICFocus (FRAME_XIC (f
));
3835 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3838 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3839 /* If we move outside the frame,
3840 then we're certainly no longer on any text in the frame. */
3841 clear_mouse_face (dpyinfo
);
3843 if (event
.xcrossing
.focus
)
3844 x_mouse_leave (dpyinfo
);
3847 if (f
== dpyinfo
->x_focus_event_frame
)
3848 dpyinfo
->x_focus_event_frame
= 0;
3849 if (f
== dpyinfo
->x_focus_frame
)
3850 x_new_focus_frame (dpyinfo
, 0);
3856 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3857 if (event
.xfocus
.detail
!= NotifyPointer
3858 && f
== dpyinfo
->x_focus_event_frame
)
3859 dpyinfo
->x_focus_event_frame
= 0;
3860 if (f
&& f
== dpyinfo
->x_focus_frame
)
3861 x_new_focus_frame (dpyinfo
, 0);
3864 if (f
&& FRAME_XIC (f
))
3865 XUnsetICFocus (FRAME_XIC (f
));
3872 if (dpyinfo
->grabbed
&& last_mouse_frame
3873 && FRAME_LIVE_P (last_mouse_frame
))
3874 f
= last_mouse_frame
;
3876 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3878 note_mouse_movement (f
, &event
.xmotion
);
3881 struct scroll_bar
*bar
3882 = x_window_to_scroll_bar (event
.xmotion
.window
);
3885 x_scroll_bar_note_movement (bar
, &event
);
3887 /* If we move outside the frame,
3888 then we're certainly no longer on any text in the frame. */
3889 clear_mouse_face (dpyinfo
);
3894 case ConfigureNotify
:
3895 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
3897 #ifdef USE_X_TOOLKIT
3898 && (event
.xconfigure
.window
== XtWindow (f
->output_data
.x
->widget
))
3902 #ifndef USE_X_TOOLKIT
3903 /* In the toolkit version, change_frame_size
3904 is called by the code that handles resizing
3905 of the EmacsFrame widget. */
3907 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3908 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3910 /* Even if the number of character rows and columns has
3911 not changed, the font size may have changed, so we need
3912 to check the pixel dimensions as well. */
3913 if (columns
!= f
->width
3914 || rows
!= f
->height
3915 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
3916 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
3918 change_frame_size (f
, rows
, columns
, 0, 1);
3919 SET_FRAME_GARBAGED (f
);
3923 /* Formerly, in the USE_X_TOOLKIT version,
3924 we did not test send_event here. */
3926 #ifndef USE_X_TOOLKIT
3927 && ! event
.xconfigure
.send_event
3934 /* Find the position of the outside upper-left corner of
3935 the window, in the root coordinate system. Don't
3936 refer to the parent window here; we may be processing
3937 this event after the window manager has changed our
3938 parent, but before we have reached the ReparentNotify. */
3939 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3941 /* From-window, to-window. */
3942 event
.xconfigure
.window
,
3943 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3945 /* From-position, to-position. */
3946 -event
.xconfigure
.border_width
,
3947 -event
.xconfigure
.border_width
,
3952 event
.xconfigure
.x
= win_x
;
3953 event
.xconfigure
.y
= win_y
;
3956 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
3957 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
3958 f
->output_data
.x
->left_pos
= event
.xconfigure
.x
;
3959 f
->output_data
.x
->top_pos
= event
.xconfigure
.y
;
3961 /* What we have now is the position of Emacs's own window.
3962 Convert that to the position of the window manager window. */
3965 x_real_positions (f
, &x
, &y
);
3966 f
->output_data
.x
->left_pos
= x
;
3967 f
->output_data
.x
->top_pos
= y
;
3968 /* Formerly we did not do this in the USE_X_TOOLKIT
3969 version. Let's try making them the same. */
3970 /* #ifndef USE_X_TOOLKIT */
3971 if (y
!= event
.xconfigure
.y
)
3973 /* Since the WM decorations come below top_pos now,
3974 we must put them below top_pos in the future. */
3975 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3976 x_wm_set_size_hint (f
, (long) 0, 0);
3986 /* If we decide we want to generate an event to be seen
3987 by the rest of Emacs, we put it here. */
3988 struct input_event emacs_event
;
3989 emacs_event
.kind
= no_event
;
3991 bzero (&compose_status
, sizeof (compose_status
));
3993 if (dpyinfo
->grabbed
&& last_mouse_frame
3994 && FRAME_LIVE_P (last_mouse_frame
))
3995 f
= last_mouse_frame
;
3997 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4001 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4002 construct_mouse_click (&emacs_event
, &event
, f
);
4006 struct scroll_bar
*bar
4007 = x_window_to_scroll_bar (event
.xbutton
.window
);
4010 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4013 if (event
.type
== ButtonPress
)
4015 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4016 last_mouse_frame
= f
;
4020 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4023 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4025 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4031 #ifdef USE_X_TOOLKIT
4032 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4033 /* For a down-event in the menu bar,
4034 don't pass it to Xt right now.
4035 Instead, save it away
4036 and we will pass it to Xt from kbd_buffer_get_event.
4037 That way, we can run some Lisp code first. */
4038 if (f
&& event
.type
== ButtonPress
4039 /* Verify the event is really within the menu bar
4040 and not just sent to it due to grabbing. */
4041 && event
.xbutton
.x
>= 0
4042 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4043 && event
.xbutton
.y
>= 0
4044 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4045 && event
.xbutton
.same_screen
)
4047 if (f
->output_data
.x
->saved_button_event
== 0)
4048 f
->output_data
.x
->saved_button_event
4049 = (XButtonEvent
*) xmalloc (sizeof (XButtonEvent
));
4050 bcopy (&event
, f
->output_data
.x
->saved_button_event
,
4051 sizeof (XButtonEvent
));
4054 bufp
->kind
= menu_bar_activate_event
;
4055 XSETFRAME (bufp
->frame_or_window
, f
);
4063 #endif /* USE_X_TOOLKIT */
4067 case CirculateNotify
:
4069 case CirculateRequest
:
4073 /* Someone has changed the keyboard mapping - update the
4075 switch (event
.xmapping
.request
)
4077 case MappingModifier
:
4078 x_find_modifier_meanings (dpyinfo
);
4079 /* This is meant to fall through. */
4080 case MappingKeyboard
:
4081 XRefreshKeyboardMapping (&event
.xmapping
);
4087 #ifdef USE_X_TOOLKIT
4089 XtDispatchEvent (&event
);
4091 #endif /* USE_X_TOOLKIT */
4097 /* On some systems, an X bug causes Emacs to get no more events
4098 when the window is destroyed. Detect that. (1994.) */
4101 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4102 One XNOOP in 100 loops will make Emacs terminate.
4103 B. Bretthauer, 1994 */
4105 if (x_noop_count
>= 100)
4109 if (next_noop_dpyinfo
== 0)
4110 next_noop_dpyinfo
= x_display_list
;
4112 XNoOp (next_noop_dpyinfo
->display
);
4114 /* Each time we get here, cycle through the displays now open. */
4115 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4119 /* If the focus was just given to an autoraising frame,
4121 /* ??? This ought to be able to handle more than one such frame. */
4122 if (pending_autoraise_frame
)
4124 x_raise_frame (pending_autoraise_frame
);
4125 pending_autoraise_frame
= 0;
4132 /* Drawing the cursor. */
4135 /* Draw a hollow box cursor on frame F at X, Y.
4136 Don't change the inside of the box. */
4139 x_draw_box (f
, x
, y
)
4143 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4144 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4145 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4146 int height
= f
->output_data
.x
->line_height
;
4148 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4149 f
->output_data
.x
->cursor_gc
,
4150 left
, top
, width
- 1, height
- 1);
4153 /* Clear the cursor of frame F to background color,
4154 and mark the cursor as not shown.
4155 This is used when the text where the cursor is
4156 is about to be rewritten. */
4164 if (! FRAME_VISIBLE_P (f
)
4165 || f
->phys_cursor_x
< 0)
4168 x_display_cursor (f
, 0);
4169 f
->phys_cursor_x
= -1;
4172 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4173 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4177 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4184 CHAR_TO_PIXEL_COL (f
, column
),
4185 CHAR_TO_PIXEL_ROW (f
, row
),
4186 &glyph
, 1, highlight
, 0);
4190 x_display_bar_cursor (f
, on
, x
, y
)
4195 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4197 /* This is pointless on invisible frames, and dangerous on garbaged
4198 frames; in the latter case, the frame may be in the midst of
4199 changing its size, and x and y may be off the frame. */
4200 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4203 if (! on
&& f
->phys_cursor_x
< 0)
4206 /* If there is anything wrong with the current cursor state, remove it. */
4207 if (f
->phys_cursor_x
>= 0
4209 || f
->phys_cursor_x
!= x
4210 || f
->phys_cursor_y
!= y
4211 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4213 /* Erase the cursor by redrawing the character underneath it. */
4214 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4215 f
->phys_cursor_glyph
,
4216 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4217 f
->phys_cursor_x
= -1;
4220 /* If we now need a cursor in the new place or in the new form, do it so. */
4222 && (f
->phys_cursor_x
< 0
4223 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4225 f
->phys_cursor_glyph
4226 = ((current_glyphs
->enable
[y
]
4227 && x
< current_glyphs
->used
[y
])
4228 ? current_glyphs
->glyphs
[y
][x
]
4230 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4231 f
->output_data
.x
->cursor_gc
,
4232 CHAR_TO_PIXEL_COL (f
, x
),
4233 CHAR_TO_PIXEL_ROW (f
, y
),
4234 max (f
->output_data
.x
->cursor_width
, 1),
4235 f
->output_data
.x
->line_height
);
4237 f
->phys_cursor_x
= x
;
4238 f
->phys_cursor_y
= y
;
4240 f
->output_data
.x
->current_cursor
= bar_cursor
;
4243 if (updating_frame
!= f
)
4244 XFlush (FRAME_X_DISPLAY (f
));
4248 /* Turn the displayed cursor of frame F on or off according to ON.
4249 If ON is nonzero, where to put the cursor is specified by X and Y. */
4252 x_display_box_cursor (f
, on
, x
, y
)
4257 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4259 /* This is pointless on invisible frames, and dangerous on garbaged
4260 frames; in the latter case, the frame may be in the midst of
4261 changing its size, and x and y may be off the frame. */
4262 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4265 /* If cursor is off and we want it off, return quickly. */
4266 if (!on
&& f
->phys_cursor_x
< 0)
4269 /* If cursor is currently being shown and we don't want it to be
4270 or it is in the wrong place,
4271 or we want a hollow box and it's not so, (pout!)
4273 if (f
->phys_cursor_x
>= 0
4275 || f
->phys_cursor_x
!= x
4276 || f
->phys_cursor_y
!= y
4277 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4278 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4280 int mouse_face_here
= 0;
4281 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4283 /* If the cursor is in the mouse face area, redisplay that when
4284 we clear the cursor. */
4285 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4287 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4288 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4289 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4291 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4292 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4293 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4294 /* Don't redraw the cursor's spot in mouse face
4295 if it is at the end of a line (on a newline).
4296 The cursor appears there, but mouse highlighting does not. */
4297 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4298 mouse_face_here
= 1;
4300 /* If the font is not as tall as a whole line,
4301 we must explicitly clear the line's whole height. */
4302 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4303 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4304 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4305 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4306 FONT_WIDTH (f
->output_data
.x
->font
),
4307 f
->output_data
.x
->line_height
, False
);
4308 /* Erase the cursor by redrawing the character underneath it. */
4309 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4310 f
->phys_cursor_glyph
,
4313 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4314 f
->phys_cursor_x
= -1;
4317 /* If we want to show a cursor,
4318 or we want a box cursor and it's not so,
4319 write it in the right place. */
4321 && (f
->phys_cursor_x
< 0
4322 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4323 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4325 f
->phys_cursor_glyph
4326 = ((current_glyphs
->enable
[y
]
4327 && x
< current_glyphs
->used
[y
])
4328 ? current_glyphs
->glyphs
[y
][x
]
4330 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4332 x_draw_box (f
, x
, y
);
4333 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4337 x_draw_single_glyph (f
, y
, x
,
4338 f
->phys_cursor_glyph
, 2);
4339 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4342 f
->phys_cursor_x
= x
;
4343 f
->phys_cursor_y
= y
;
4346 if (updating_frame
!= f
)
4347 XFlush (FRAME_X_DISPLAY (f
));
4350 /* Display the cursor on frame F, or clear it, according to ON.
4351 Use the position specified by curs_x and curs_y
4352 if we are doing an update of frame F now.
4353 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4356 x_display_cursor (f
, on
)
4362 /* If we're not updating, then don't change the physical cursor
4363 position. Just change (if appropriate) the style of display. */
4364 if (f
!= updating_frame
)
4366 curs_x
= FRAME_CURSOR_X (f
);
4367 curs_y
= FRAME_CURSOR_Y (f
);
4370 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4371 x_display_box_cursor (f
, on
, curs_x
, curs_y
);
4372 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4373 x_display_bar_cursor (f
, on
, curs_x
, curs_y
);
4375 /* Those are the only two we have implemented! */
4381 /* Display the cursor on frame F, or clear it, according to ON.
4382 Don't change the cursor's position. */
4384 x_update_cursor (f
, on
)
4390 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4391 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4392 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4393 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4395 /* Those are the only two we have implemented! */
4403 /* Refresh bitmap kitchen sink icon for frame F
4404 when we get an expose event for it. */
4409 /* Normally, the window manager handles this function. */
4412 /* Make the x-window of frame F use the gnu icon bitmap. */
4415 x_bitmap_icon (f
, file
)
4419 int mask
, bitmap_id
;
4422 if (FRAME_X_WINDOW (f
) == 0)
4425 /* Free up our existing icon bitmap if any. */
4426 if (f
->output_data
.x
->icon_bitmap
> 0)
4427 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4428 f
->output_data
.x
->icon_bitmap
= 0;
4431 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4434 /* Create the GNU bitmap if necessary. */
4435 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4436 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4437 = x_create_bitmap_from_data (f
, gnu_bits
,
4438 gnu_width
, gnu_height
);
4440 /* The first time we create the GNU bitmap,
4441 this increments the refcount one extra time.
4442 As a result, the GNU bitmap is never freed.
4443 That way, we don't have to worry about allocating it again. */
4444 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4446 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4449 x_wm_set_icon_pixmap (f
, bitmap_id
);
4450 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4456 /* Make the x-window of frame F use a rectangle with text.
4457 Use ICON_NAME as the text. */
4460 x_text_icon (f
, icon_name
)
4464 if (FRAME_X_WINDOW (f
) == 0)
4470 text
.value
= (unsigned char *) icon_name
;
4471 text
.encoding
= XA_STRING
;
4473 text
.nitems
= strlen (icon_name
);
4474 #ifdef USE_X_TOOLKIT
4475 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4477 #else /* not USE_X_TOOLKIT */
4478 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
4479 #endif /* not USE_X_TOOLKIT */
4481 #else /* not HAVE_X11R4 */
4482 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
4483 #endif /* not HAVE_X11R4 */
4485 if (f
->output_data
.x
->icon_bitmap
> 0)
4486 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4487 f
->output_data
.x
->icon_bitmap
= 0;
4488 x_wm_set_icon_pixmap (f
, 0);
4493 /* Handling X errors. */
4495 /* Handle the loss of connection to display DISPLAY. */
4498 x_connection_closed (display
, error_message
)
4500 char *error_message
;
4502 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4503 Lisp_Object frame
, tail
;
4505 /* Whatever we were in the middle of, we are going to throw out of it,
4506 so reassure various things that have error checks about being
4507 called with input blocked. */
4508 TOTALLY_UNBLOCK_INPUT
;
4513 /* First delete frames whose minibuffers are on frames
4514 that are on the dead display. */
4515 FOR_EACH_FRAME (tail
, frame
)
4517 Lisp_Object minibuf_frame
;
4519 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4520 if (FRAME_X_P (XFRAME (frame
))
4521 && FRAME_X_P (XFRAME (minibuf_frame
))
4522 && ! EQ (frame
, minibuf_frame
)
4523 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4524 Fdelete_frame (frame
, Qt
);
4527 /* Now delete all remaining frames on the dead display.
4528 We are now sure none of these is used as the minibuffer
4529 for another frame that we need to delete. */
4530 FOR_EACH_FRAME (tail
, frame
)
4531 if (FRAME_X_P (XFRAME (frame
))
4532 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4534 /* Set this to t so that Fdelete_frame won't get confused
4535 trying to find a replacement. */
4536 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
4537 Fdelete_frame (frame
, Qt
);
4541 x_delete_display (dpyinfo
);
4543 if (x_display_list
== 0)
4545 fprintf (stderr
, "%s", error_message
);
4546 shut_down_emacs (0, 0, Qnil
);
4550 /* Ordinary stack unwind doesn't deal with these. */
4552 sigunblock (sigmask (SIGIO
));
4554 sigunblock (sigmask (SIGALRM
));
4555 TOTALLY_UNBLOCK_INPUT
;
4557 error ("%s", error_message
);
4560 /* This is the usual handler for X protocol errors.
4561 It kills all frames on the display that we got the error for.
4562 If that was the only one, it prints an error message and kills Emacs. */
4565 x_error_quitter (display
, error
)
4569 char buf
[256], buf1
[356];
4571 /* Note that there is no real way portable across R3/R4 to get the
4572 original error handler. */
4574 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4575 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4576 buf
, error
->request_code
);
4577 x_connection_closed (display
, buf1
);
4580 /* This is the handler for X IO errors, always.
4581 It kills all frames on the display that we lost touch with.
4582 If that was the only one, it prints an error message and kills Emacs. */
4585 x_io_error_quitter (display
)
4590 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4591 x_connection_closed (display
, buf
);
4594 /* Handle SIGPIPE, which can happen when the connection to a server
4595 simply goes away. SIGPIPE is handled by x_connection_signal.
4596 It works by sending a no-op command to each X server connection.
4597 When we try a connection that has closed, we get SIGPIPE again.
4598 But this time, it is handled by x_connection_signal_1.
4599 That function knows which connection we were testing,
4600 so it closes that one.
4602 x_connection_closed never returns,
4603 so if more than one connection was lost at once,
4604 we only find one. But XTread_socket keeps trying them all,
4605 so it will notice the other closed one sooner or later. */
4608 static struct x_display_info
*x_connection_signal_dpyinfo
;
4610 static SIGTYPE
x_connection_signal ();
4613 x_connection_signal_1 (signalnum
) /* If we don't have an argument, */
4614 int signalnum
; /* some compilers complain in signal calls. */
4616 signal (SIGPIPE
, x_connection_signal
);
4617 x_connection_closed (x_connection_signal_dpyinfo
,
4618 "connection was lost");
4622 x_connection_signal (signalnum
) /* If we don't have an argument, */
4623 int signalnum
; /* some compilers complain in signal calls. */
4625 x_connection_signal_dpyinfo
= x_display_list
;
4628 sigunblock (SIGPIPE
);
4630 while (x_connection_signal_dpyinfo
)
4632 signal (SIGPIPE
, x_connection_signal_1
);
4633 signal (SIGALRM
, x_connection_signal_1
);
4635 /* According to Jim Campbell <jec@murzim.ca.boeing.com>,
4636 On Solaris 2.4, XNoOp can hang when the connection
4637 has already died. Since XNoOp should not wait,
4638 let's assume that if it hangs for 3 seconds
4639 that means the connection is dead.
4640 This is a kludge, but I don't see any other way that works. */
4642 XNoOp (x_connection_signal_dpyinfo
->display
);
4645 XSync (x_connection_signal_dpyinfo
->display
, False
);
4647 /* Each time we get here, cycle through the displays now open. */
4648 x_connection_signal_dpyinfo
= x_connection_signal_dpyinfo
->next
;
4651 /* We should have found some closed connection. */
4655 /* A buffer for storing X error messages. */
4656 static char *x_caught_error_message
;
4657 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4659 /* An X error handler which stores the error message in
4660 x_caught_error_message. This is what's installed when
4661 x_catch_errors is in effect. */
4664 x_error_catcher (display
, error
)
4668 XGetErrorText (display
, error
->error_code
,
4669 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4673 /* Begin trapping X errors for display DPY. Actually we trap X errors
4674 for all displays, but DPY should be the display you are actually
4677 After calling this function, X protocol errors no longer cause
4678 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4680 Calling x_check_errors signals an Emacs error if an X error has
4681 occurred since the last call to x_catch_errors or x_check_errors.
4683 Calling x_uncatch_errors resumes the normal error handling. */
4685 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4688 x_catch_errors (dpy
)
4691 /* Make sure any errors from previous requests have been dealt with. */
4694 /* Set up the error buffer. */
4695 x_caught_error_message
4696 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4697 x_caught_error_message
[0] = '\0';
4699 /* Install our little error handler. */
4700 XSetErrorHandler (x_error_catcher
);
4703 /* If any X protocol errors have arrived since the last call to
4704 x_catch_errors or x_check_errors, signal an Emacs error using
4705 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4708 x_check_errors (dpy
, format
)
4712 /* Make sure to catch any errors incurred so far. */
4715 if (x_caught_error_message
[0])
4717 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4719 sprintf (buf
, format
, x_caught_error_message
);
4720 x_uncatch_errors (dpy
);
4725 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4728 x_had_errors_p (dpy
)
4731 /* Make sure to catch any errors incurred so far. */
4734 return x_caught_error_message
[0] != 0;
4737 /* Stop catching X protocol errors and let them make Emacs die. */
4740 x_uncatch_errors (dpy
)
4743 xfree (x_caught_error_message
);
4744 x_caught_error_message
= 0;
4745 XSetErrorHandler (x_error_quitter
);
4749 static unsigned int x_wire_count
;
4752 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4757 /* Changing the font of the frame. */
4759 /* Give frame F the font named FONTNAME as its default font, and
4760 return the full name of that font. FONTNAME may be a wildcard
4761 pattern; in that case, we choose some font that fits the pattern.
4762 The return value shows which font we chose. */
4765 x_new_font (f
, fontname
)
4767 register char *fontname
;
4770 int n_matching_fonts
;
4771 XFontStruct
*font_info
;
4774 /* Get a list of all the fonts that match this name. Once we
4775 have a list of matching fonts, we compare them against the fonts
4776 we already have by comparing font ids. */
4777 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4778 1024, &n_matching_fonts
);
4779 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4780 find any matches; font_names == 0 is the only clue. */
4782 n_matching_fonts
= 0;
4784 /* Don't just give up if n_matching_fonts is 0.
4785 Apparently there's a bug on Suns: XListFontsWithInfo can
4786 fail to find a font, but XLoadQueryFont may still find it. */
4788 /* See if we've already loaded a matching font. */
4789 already_loaded
= -1;
4790 if (n_matching_fonts
!= 0)
4794 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4795 for (j
= 0; j
< n_matching_fonts
; j
++)
4796 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4797 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4800 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4806 /* If we have, just return it from the table. */
4807 if (already_loaded
>= 0)
4808 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4809 /* Otherwise, load the font and add it to the table. */
4817 /* Try to find a character-cell font in the list. */
4819 /* A laudable goal, but this isn't how to do it. */
4820 for (i
= 0; i
< n_matching_fonts
; i
++)
4821 if (! font_info
[i
].per_char
)
4827 /* See comment above. */
4828 if (n_matching_fonts
!= 0)
4829 fontname
= font_names
[i
];
4831 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4834 /* Free the information from XListFonts. */
4835 if (n_matching_fonts
)
4836 XFreeFontNames (font_names
);
4840 /* Do we need to create the table? */
4841 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4843 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4844 FRAME_X_DISPLAY_INFO (f
)->font_table
4845 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4846 * sizeof (struct font_info
));
4848 /* Do we need to grow the table? */
4849 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4850 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4852 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4853 FRAME_X_DISPLAY_INFO (f
)->font_table
4854 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4855 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4856 * sizeof (struct font_info
)));
4859 /* Try to get the full name of FONT. Put it in full_name. */
4861 for (i
= 0; i
< font
->n_properties
; i
++)
4864 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4865 if (!strcmp (atom
, "FONT"))
4867 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4868 (Atom
) (font
->properties
[i
].card32
));
4872 /* Count the number of dashes in the "full name".
4873 If it is too few, this isn't really the font's full name,
4875 In X11R4, the fonts did not come with their canonical names
4893 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4894 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4895 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4897 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4899 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4900 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4901 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4904 fontname
= full_name
;
4907 /* Compute the scroll bar width in character columns. */
4908 if (f
->scroll_bar_pixel_width
> 0)
4910 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
4911 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4914 f
->scroll_bar_cols
= 2;
4916 /* Now make the frame display the given font. */
4917 if (FRAME_X_WINDOW (f
) != 0)
4919 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
4920 f
->output_data
.x
->font
->fid
);
4921 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
4922 f
->output_data
.x
->font
->fid
);
4923 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
4924 f
->output_data
.x
->font
->fid
);
4926 frame_update_line_height (f
);
4927 x_set_window_size (f
, 0, f
->width
, f
->height
);
4930 /* If we are setting a new frame's font for the first time,
4931 there are no faces yet, so this font's height is the line height. */
4932 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
4935 Lisp_Object lispy_name
;
4937 lispy_name
= build_string (fontname
);
4939 /* Free the information from XListFonts. The data
4940 we actually retain comes from XLoadQueryFont. */
4941 XFreeFontNames (font_names
);
4947 x_calc_absolute_position (f
)
4951 int win_x
= 0, win_y
= 0;
4952 int flags
= f
->output_data
.x
->size_hint_flags
;
4955 #ifdef USE_X_TOOLKIT
4956 this_window
= XtWindow (f
->output_data
.x
->widget
);
4958 this_window
= FRAME_X_WINDOW (f
);
4961 /* Find the position of the outside upper-left corner of
4962 the inner window, with respect to the outer window. */
4963 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4966 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4968 /* From-window, to-window. */
4970 f
->output_data
.x
->parent_desc
,
4972 /* From-position, to-position. */
4973 0, 0, &win_x
, &win_y
,
4980 /* Treat negative positions as relative to the leftmost bottommost
4981 position that fits on the screen. */
4982 if (flags
& XNegative
)
4983 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4984 - 2 * f
->output_data
.x
->border_width
- win_x
4986 + f
->output_data
.x
->left_pos
);
4988 if (flags
& YNegative
)
4989 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
4990 - 2 * f
->output_data
.x
->border_width
- win_y
4992 - (FRAME_EXTERNAL_MENU_BAR (f
)
4993 ? f
->output_data
.x
->menubar_height
: 0)
4994 + f
->output_data
.x
->top_pos
);
4995 /* The left_pos and top_pos
4996 are now relative to the top and left screen edges,
4997 so the flags should correspond. */
4998 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5001 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5002 to really change the position, and 0 when calling from
5003 x_make_frame_visible (in that case, XOFF and YOFF are the current
5004 position values). It is -1 when calling from x_set_frame_parameters,
5005 which means, do adjust for borders but don't change the gravity. */
5007 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5009 register int xoff
, yoff
;
5012 int modified_top
, modified_left
;
5014 if (change_gravity
> 0)
5016 f
->output_data
.x
->top_pos
= yoff
;
5017 f
->output_data
.x
->left_pos
= xoff
;
5018 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5020 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5022 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5023 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5025 x_calc_absolute_position (f
);
5028 x_wm_set_size_hint (f
, (long) 0, 0);
5030 /* It is a mystery why we need to add the border_width here
5031 when the frame is already visible, but experiment says we do. */
5032 modified_left
= f
->output_data
.x
->left_pos
;
5033 modified_top
= f
->output_data
.x
->top_pos
;
5034 if (change_gravity
!= 0)
5036 modified_left
+= f
->output_data
.x
->border_width
;
5037 modified_top
+= f
->output_data
.x
->border_width
;
5040 #ifdef USE_X_TOOLKIT
5041 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5042 modified_left
, modified_top
);
5043 #else /* not USE_X_TOOLKIT */
5044 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5045 modified_left
, modified_top
);
5046 #endif /* not USE_X_TOOLKIT */
5050 /* Call this to change the size of frame F's x-window.
5051 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5052 for this size change and subsequent size changes.
5053 Otherwise we leave the window gravity unchanged. */
5055 x_set_window_size (f
, change_gravity
, cols
, rows
)
5060 int pixelwidth
, pixelheight
;
5063 #ifdef USE_X_TOOLKIT
5066 /* The x and y position of the widget is clobbered by the
5067 call to XtSetValues within EmacsFrameSetCharSize.
5068 This is a real kludge, but I don't understand Xt so I can't
5069 figure out a correct fix. Can anyone else tell me? -- rms. */
5070 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5071 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5072 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5073 f
->output_data
.x
->widget
->core
.x
= xpos
;
5074 f
->output_data
.x
->widget
->core
.y
= ypos
;
5078 #else /* not USE_X_TOOLKIT */
5082 check_frame_size (f
, &rows
, &cols
);
5083 f
->output_data
.x
->vertical_scroll_bar_extra
5084 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5086 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5087 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5088 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5089 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5090 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5092 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5093 x_wm_set_size_hint (f
, (long) 0, 0);
5095 XSync (FRAME_X_DISPLAY (f
), False
);
5096 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5097 pixelwidth
, pixelheight
);
5099 /* Now, strictly speaking, we can't be sure that this is accurate,
5100 but the window manager will get around to dealing with the size
5101 change request eventually, and we'll hear how it went when the
5102 ConfigureNotify event gets here.
5104 We could just not bother storing any of this information here,
5105 and let the ConfigureNotify event set everything up, but that
5106 might be kind of confusing to the lisp code, since size changes
5107 wouldn't be reported in the frame parameters until some random
5108 point in the future when the ConfigureNotify event arrives. */
5109 change_frame_size (f
, rows
, cols
, 0, 0);
5110 PIXEL_WIDTH (f
) = pixelwidth
;
5111 PIXEL_HEIGHT (f
) = pixelheight
;
5113 /* If cursor was outside the new size, mark it as off. */
5114 if (f
->phys_cursor_y
>= rows
5115 || f
->phys_cursor_x
>= cols
)
5117 f
->phys_cursor_x
= -1;
5118 f
->phys_cursor_y
= -1;
5121 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5122 receive in the ConfigureNotify event; if we get what we asked
5123 for, then the event won't cause the screen to become garbaged, so
5124 we have to make sure to do it here. */
5125 SET_FRAME_GARBAGED (f
);
5127 XFlush (FRAME_X_DISPLAY (f
));
5129 #endif /* not USE_X_TOOLKIT */
5132 /* Mouse warping. */
5135 x_set_mouse_position (f
, x
, y
)
5141 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5142 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5144 if (pix_x
< 0) pix_x
= 0;
5145 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5147 if (pix_y
< 0) pix_y
= 0;
5148 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5152 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5153 0, 0, 0, 0, pix_x
, pix_y
);
5157 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5160 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5166 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5167 0, 0, 0, 0, pix_x
, pix_y
);
5171 /* focus shifting, raising and lowering. */
5173 x_focus_on_frame (f
)
5176 #if 0 /* This proves to be unpleasant. */
5180 /* I don't think that the ICCCM allows programs to do things like this
5181 without the interaction of the window manager. Whatever you end up
5182 doing with this code, do it to x_unfocus_frame too. */
5183 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5184 RevertToPointerRoot
, CurrentTime
);
5192 /* Look at the remarks in x_focus_on_frame. */
5193 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5194 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5195 RevertToPointerRoot
, CurrentTime
);
5199 /* Raise frame F. */
5204 if (f
->async_visible
)
5207 #ifdef USE_X_TOOLKIT
5208 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5209 #else /* not USE_X_TOOLKIT */
5210 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5211 #endif /* not USE_X_TOOLKIT */
5212 XFlush (FRAME_X_DISPLAY (f
));
5217 /* Lower frame F. */
5222 if (f
->async_visible
)
5225 #ifdef USE_X_TOOLKIT
5226 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5227 #else /* not USE_X_TOOLKIT */
5228 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5229 #endif /* not USE_X_TOOLKIT */
5230 XFlush (FRAME_X_DISPLAY (f
));
5236 XTframe_raise_lower (f
, raise
)
5246 /* Change of visibility. */
5248 /* This tries to wait until the frame is really visible.
5249 However, if the window manager asks the user where to position
5250 the frame, this will return before the user finishes doing that.
5251 The frame will not actually be visible at that time,
5252 but it will become visible later when the window manager
5253 finishes with it. */
5255 x_make_frame_visible (f
)
5263 type
= x_icon_type (f
);
5265 x_bitmap_icon (f
, type
);
5267 if (! FRAME_VISIBLE_P (f
))
5269 /* We test FRAME_GARBAGED_P here to make sure we don't
5270 call x_set_offset a second time
5271 if we get to x_make_frame_visible a second time
5272 before the window gets really visible. */
5273 if (! FRAME_ICONIFIED_P (f
)
5274 && ! f
->output_data
.x
->asked_for_visible
)
5275 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5277 f
->output_data
.x
->asked_for_visible
= 1;
5279 if (! EQ (Vx_no_window_manager
, Qt
))
5280 x_wm_set_window_state (f
, NormalState
);
5281 #ifdef USE_X_TOOLKIT
5282 /* This was XtPopup, but that did nothing for an iconified frame. */
5283 XtMapWidget (f
->output_data
.x
->widget
);
5284 #else /* not USE_X_TOOLKIT */
5285 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5286 #endif /* not USE_X_TOOLKIT */
5287 #if 0 /* This seems to bring back scroll bars in the wrong places
5288 if the window configuration has changed. They seem
5289 to come back ok without this. */
5290 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5291 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5295 XFlush (FRAME_X_DISPLAY (f
));
5297 /* Synchronize to ensure Emacs knows the frame is visible
5298 before we do anything else. We do this loop with input not blocked
5299 so that incoming events are handled. */
5302 int count
= input_signal_count
;
5304 /* This must come after we set COUNT. */
5307 XSETFRAME (frame
, f
);
5312 /* Once we have handled input events,
5313 we should have received the MapNotify if one is coming.
5314 So if we have not got it yet, stop looping.
5315 Some window managers make their own decisions
5316 about visibility. */
5317 if (input_signal_count
!= count
)
5319 /* Machines that do polling rather than SIGIO have been observed
5320 to go into a busy-wait here. So we'll fake an alarm signal
5321 to let the handler know that there's something to be read.
5322 We used to raise a real alarm, but it seems that the handler
5323 isn't always enabled here. This is probably a bug. */
5324 if (input_polling_used ())
5326 /* It could be confusing if a real alarm arrives while processing
5327 the fake one. Turn it off and let the handler reset it. */
5329 input_poll_signal ();
5331 /* Once we have handled input events,
5332 we should have received the MapNotify if one is coming.
5333 So if we have not got it yet, stop looping.
5334 Some window managers make their own decisions
5335 about visibility. */
5336 if (input_signal_count
!= count
)
5339 FRAME_SAMPLE_VISIBILITY (f
);
5343 /* Change from mapped state to withdrawn state. */
5345 /* Make the frame visible (mapped and not iconified). */
5347 x_make_frame_invisible (f
)
5353 #ifdef USE_X_TOOLKIT
5354 /* Use the frame's outermost window, not the one we normally draw on. */
5355 window
= XtWindow (f
->output_data
.x
->widget
);
5356 #else /* not USE_X_TOOLKIT */
5357 window
= FRAME_X_WINDOW (f
);
5358 #endif /* not USE_X_TOOLKIT */
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 0/* This might add unreliability; I don't trust it -- rms. */
5365 if (! f
->async_visible
&& ! f
->async_iconified
)
5371 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5372 that the current position of the window is user-specified, rather than
5373 program-specified, so that when the window is mapped again, it will be
5374 placed at the same location, without forcing the user to position it
5375 by hand again (they have already done that once for this window.) */
5376 x_wm_set_size_hint (f
, (long) 0, 1);
5380 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5381 DefaultScreen (FRAME_X_DISPLAY (f
))))
5383 UNBLOCK_INPUT_RESIGNAL
;
5384 error ("Can't notify window manager of window withdrawal");
5386 #else /* ! defined (HAVE_X11R4) */
5388 /* Tell the window manager what we're going to do. */
5389 if (! EQ (Vx_no_window_manager
, Qt
))
5393 unmap
.xunmap
.type
= UnmapNotify
;
5394 unmap
.xunmap
.window
= window
;
5395 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5396 unmap
.xunmap
.from_configure
= False
;
5397 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5398 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5400 SubstructureRedirectMask
|SubstructureNotifyMask
,
5403 UNBLOCK_INPUT_RESIGNAL
;
5404 error ("Can't notify window manager of withdrawal");
5408 /* Unmap the window ourselves. Cheeky! */
5409 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5410 #endif /* ! defined (HAVE_X11R4) */
5412 /* We can't distinguish this from iconification
5413 just by the event that we get from the server.
5414 So we can't win using the usual strategy of letting
5415 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5416 and synchronize with the server to make sure we agree. */
5418 FRAME_ICONIFIED_P (f
) = 0;
5419 f
->async_visible
= 0;
5420 f
->async_iconified
= 0;
5427 /* Change window state from mapped to iconified. */
5436 /* Don't keep the highlight on an invisible frame. */
5437 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5438 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5440 if (f
->async_iconified
)
5445 FRAME_SAMPLE_VISIBILITY (f
);
5447 type
= x_icon_type (f
);
5449 x_bitmap_icon (f
, type
);
5451 #ifdef USE_X_TOOLKIT
5453 if (! FRAME_VISIBLE_P (f
))
5455 if (! EQ (Vx_no_window_manager
, Qt
))
5456 x_wm_set_window_state (f
, IconicState
);
5457 /* This was XtPopup, but that did nothing for an iconified frame. */
5458 XtMapWidget (f
->output_data
.x
->widget
);
5463 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5464 XtWindow (f
->output_data
.x
->widget
),
5465 DefaultScreen (FRAME_X_DISPLAY (f
)));
5469 error ("Can't notify window manager of iconification");
5471 f
->async_iconified
= 1;
5474 XFlush (FRAME_X_DISPLAY (f
));
5476 #else /* not USE_X_TOOLKIT */
5478 /* Make sure the X server knows where the window should be positioned,
5479 in case the user deiconifies with the window manager. */
5480 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5481 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5483 /* Since we don't know which revision of X we're running, we'll use both
5484 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5486 /* X11R4: send a ClientMessage to the window manager using the
5487 WM_CHANGE_STATE type. */
5491 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5492 message
.xclient
.type
= ClientMessage
;
5493 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5494 message
.xclient
.format
= 32;
5495 message
.xclient
.data
.l
[0] = IconicState
;
5497 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5498 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5500 SubstructureRedirectMask
| SubstructureNotifyMask
,
5503 UNBLOCK_INPUT_RESIGNAL
;
5504 error ("Can't notify window manager of iconification");
5508 /* X11R3: set the initial_state field of the window manager hints to
5510 x_wm_set_window_state (f
, IconicState
);
5512 if (!FRAME_VISIBLE_P (f
))
5514 /* If the frame was withdrawn, before, we must map it. */
5515 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5518 f
->async_iconified
= 1;
5520 XFlush (FRAME_X_DISPLAY (f
));
5522 #endif /* not USE_X_TOOLKIT */
5525 /* Destroy the X window of frame F. */
5527 x_destroy_window (f
)
5530 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5534 if (f
->output_data
.x
->icon_desc
!= 0)
5535 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
5536 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
5537 #ifdef USE_X_TOOLKIT
5538 XtDestroyWidget (f
->output_data
.x
->widget
);
5539 free_frame_menubar (f
);
5540 #endif /* USE_X_TOOLKIT */
5542 free_frame_faces (f
);
5543 XFlush (FRAME_X_DISPLAY (f
));
5545 xfree (f
->output_data
.x
);
5546 f
->output_data
.x
= 0;
5547 if (f
== dpyinfo
->x_focus_frame
)
5548 dpyinfo
->x_focus_frame
= 0;
5549 if (f
== dpyinfo
->x_focus_event_frame
)
5550 dpyinfo
->x_focus_event_frame
= 0;
5551 if (f
== dpyinfo
->x_highlight_frame
)
5552 dpyinfo
->x_highlight_frame
= 0;
5554 dpyinfo
->reference_count
--;
5556 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5558 dpyinfo
->mouse_face_beg_row
5559 = dpyinfo
->mouse_face_beg_col
= -1;
5560 dpyinfo
->mouse_face_end_row
5561 = dpyinfo
->mouse_face_end_col
= -1;
5562 dpyinfo
->mouse_face_window
= Qnil
;
5568 /* Setting window manager hints. */
5570 /* Set the normal size hints for the window manager, for frame F.
5571 FLAGS is the flags word to use--or 0 meaning preserve the flags
5572 that the window now has.
5573 If USER_POSITION is nonzero, we set the USPosition
5574 flag (this is useful when FLAGS is 0). */
5576 x_wm_set_size_hint (f
, flags
, user_position
)
5581 XSizeHints size_hints
;
5583 #ifdef USE_X_TOOLKIT
5586 Dimension widget_width
, widget_height
;
5587 Window window
= XtWindow (f
->output_data
.x
->widget
);
5588 #else /* not USE_X_TOOLKIT */
5589 Window window
= FRAME_X_WINDOW (f
);
5590 #endif /* not USE_X_TOOLKIT */
5592 /* Setting PMaxSize caused various problems. */
5593 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5595 flexlines
= f
->height
;
5597 size_hints
.x
= f
->output_data
.x
->left_pos
;
5598 size_hints
.y
= f
->output_data
.x
->top_pos
;
5600 #ifdef USE_X_TOOLKIT
5601 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5602 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5603 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5604 size_hints
.height
= widget_height
;
5605 size_hints
.width
= widget_width
;
5606 #else /* not USE_X_TOOLKIT */
5607 size_hints
.height
= PIXEL_HEIGHT (f
);
5608 size_hints
.width
= PIXEL_WIDTH (f
);
5609 #endif /* not USE_X_TOOLKIT */
5611 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
5612 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
5613 size_hints
.max_width
5614 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5615 size_hints
.max_height
5616 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5618 /* Calculate the base and minimum sizes.
5620 (When we use the X toolkit, we don't do it here.
5621 Instead we copy the values that the widgets are using, below.) */
5622 #ifndef USE_X_TOOLKIT
5624 int base_width
, base_height
;
5625 int min_rows
= 0, min_cols
= 0;
5627 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5628 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5630 check_frame_size (f
, &min_rows
, &min_cols
);
5632 /* The window manager uses the base width hints to calculate the
5633 current number of rows and columns in the frame while
5634 resizing; min_width and min_height aren't useful for this
5635 purpose, since they might not give the dimensions for a
5636 zero-row, zero-column frame.
5638 We use the base_width and base_height members if we have
5639 them; otherwise, we set the min_width and min_height members
5640 to the size for a zero x zero frame. */
5643 size_hints
.flags
|= PBaseSize
;
5644 size_hints
.base_width
= base_width
;
5645 size_hints
.base_height
= base_height
;
5646 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5647 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5649 size_hints
.min_width
= base_width
;
5650 size_hints
.min_height
= base_height
;
5654 /* If we don't need the old flags, we don't need the old hint at all. */
5657 size_hints
.flags
|= flags
;
5660 #endif /* not USE_X_TOOLKIT */
5663 XSizeHints hints
; /* Sometimes I hate X Windows... */
5664 long supplied_return
;
5668 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5671 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5674 #ifdef USE_X_TOOLKIT
5675 size_hints
.base_height
= hints
.base_height
;
5676 size_hints
.base_width
= hints
.base_width
;
5677 size_hints
.min_height
= hints
.min_height
;
5678 size_hints
.min_width
= hints
.min_width
;
5682 size_hints
.flags
|= flags
;
5687 if (hints
.flags
& PSize
)
5688 size_hints
.flags
|= PSize
;
5689 if (hints
.flags
& PPosition
)
5690 size_hints
.flags
|= PPosition
;
5691 if (hints
.flags
& USPosition
)
5692 size_hints
.flags
|= USPosition
;
5693 if (hints
.flags
& USSize
)
5694 size_hints
.flags
|= USSize
;
5701 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
5702 size_hints
.flags
|= PWinGravity
;
5706 size_hints
.flags
&= ~ PPosition
;
5707 size_hints
.flags
|= USPosition
;
5709 #endif /* PWinGravity */
5712 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5714 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5718 /* Used for IconicState or NormalState */
5719 x_wm_set_window_state (f
, state
)
5723 #ifdef USE_X_TOOLKIT
5726 XtSetArg (al
[0], XtNinitialState
, state
);
5727 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5728 #else /* not USE_X_TOOLKIT */
5729 Window window
= FRAME_X_WINDOW (f
);
5731 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5732 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5734 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5735 #endif /* not USE_X_TOOLKIT */
5738 x_wm_set_icon_pixmap (f
, pixmap_id
)
5742 #ifdef USE_X_TOOLKIT
5743 Window window
= XtWindow (f
->output_data
.x
->widget
);
5745 Window window
= FRAME_X_WINDOW (f
);
5750 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5751 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5755 /* It seems there is no way to turn off use of an icon pixmap.
5756 The following line does it, only if no icon has yet been created,
5757 for some window managers. But with mwm it crashes.
5758 Some people say it should clear the IconPixmapHint bit in this case,
5759 but that doesn't work, and the X consortium said it isn't the
5760 right thing at all. Since there is no way to win,
5761 best to explicitly give up. */
5763 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5769 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5770 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5773 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5777 #ifdef USE_X_TOOLKIT
5778 Window window
= XtWindow (f
->output_data
.x
->widget
);
5780 Window window
= FRAME_X_WINDOW (f
);
5783 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5784 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5785 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5787 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5791 /* Initialization. */
5793 #ifdef USE_X_TOOLKIT
5794 static XrmOptionDescRec emacs_options
[] = {
5795 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5796 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5798 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5799 XrmoptionSepArg
, NULL
},
5800 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5802 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5803 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5804 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5805 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5806 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5807 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5808 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5810 #endif /* USE_X_TOOLKIT */
5812 static int x_initialized
;
5815 /* Test whether two display-name strings agree up to the dot that separates
5816 the screen number from the server number. */
5818 same_x_server (name1
, name2
)
5819 char *name1
, *name2
;
5822 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5826 if (seen_colon
&& *name1
== '.')
5830 && (*name1
== '.' || *name1
== '\0')
5831 && (*name2
== '.' || *name2
== '\0'));
5835 struct x_display_info
*
5836 x_term_init (display_name
, xrm_option
, resource_name
)
5837 Lisp_Object display_name
;
5839 char *resource_name
;
5845 struct x_display_info
*dpyinfo
;
5857 setlocale (LC_ALL
, NULL
);
5860 #ifdef USE_X_TOOLKIT
5861 /* weiner@footloose.sps.mot.com reports that this causes
5863 X protocol error: BadAtom (invalid Atom parameter)
5864 on protocol request 18skiloaf.
5865 So let's not use it until R6. */
5867 XtSetLanguageProc (NULL
, NULL
, NULL
);
5878 argv
[argc
++] = "-xrm";
5879 argv
[argc
++] = xrm_option
;
5881 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5882 resource_name
, EMACS_CLASS
,
5883 emacs_options
, XtNumber (emacs_options
),
5887 setlocale (LC_NUMERIC
, "C");
5888 setlocale (LC_TIME
, "C");
5892 #else /* not USE_X_TOOLKIT */
5894 XSetLocaleModifiers ("");
5896 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5897 #endif /* not USE_X_TOOLKIT */
5899 /* Detect failure. */
5906 /* We have definitely succeeded. Record the new connection. */
5908 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5912 struct x_display_info
*share
;
5915 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5916 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5917 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5918 XSTRING (display_name
)->data
))
5921 dpyinfo
->kboard
= share
->kboard
;
5924 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5925 init_kboard (dpyinfo
->kboard
);
5926 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
5928 char *vendor
= ServerVendor (dpy
);
5929 dpyinfo
->kboard
->Vsystem_key_alist
5930 = call1 (Qvendor_specific_keysyms
,
5931 build_string (vendor
? vendor
: ""));
5934 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5935 all_kboards
= dpyinfo
->kboard
;
5936 /* Don't let the initial kboard remain current longer than necessary.
5937 That would cause problems if a file loaded on startup tries to
5938 prompt in the minibuffer. */
5939 if (current_kboard
== initial_kboard
)
5940 current_kboard
= dpyinfo
->kboard
;
5942 dpyinfo
->kboard
->reference_count
++;
5946 /* Put this display on the chain. */
5947 dpyinfo
->next
= x_display_list
;
5948 x_display_list
= dpyinfo
;
5950 /* Put it on x_display_name_list as well, to keep them parallel. */
5951 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5952 x_display_name_list
);
5953 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5955 dpyinfo
->display
= dpy
;
5958 XSetAfterFunction (x_current_display
, x_trace_wire
);
5962 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5963 + XSTRING (Vsystem_name
)->size
5965 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5966 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5968 /* Figure out which modifier bits mean what. */
5969 x_find_modifier_meanings (dpyinfo
);
5971 /* Get the scroll bar cursor. */
5972 dpyinfo
->vertical_scroll_bar_cursor
5973 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5975 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5976 resource_name
, EMACS_CLASS
);
5977 #ifdef HAVE_XRMSETDATABASE
5978 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5980 dpyinfo
->display
->db
= xrdb
;
5982 /* Put the rdb where we can find it in a way that works on
5984 dpyinfo
->xrdb
= xrdb
;
5986 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5987 DefaultScreen (dpyinfo
->display
));
5988 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5989 &dpyinfo
->n_planes
);
5990 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
5991 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
5992 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
5993 dpyinfo
->grabbed
= 0;
5994 dpyinfo
->reference_count
= 0;
5995 dpyinfo
->icon_bitmap_id
= -1;
5996 dpyinfo
->n_fonts
= 0;
5997 dpyinfo
->font_table_size
= 0;
5998 dpyinfo
->bitmaps
= 0;
5999 dpyinfo
->bitmaps_size
= 0;
6000 dpyinfo
->bitmaps_last
= 0;
6001 dpyinfo
->scratch_cursor_gc
= 0;
6002 dpyinfo
->mouse_face_mouse_frame
= 0;
6003 dpyinfo
->mouse_face_deferred_gc
= 0;
6004 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6005 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6006 dpyinfo
->mouse_face_face_id
= 0;
6007 dpyinfo
->mouse_face_window
= Qnil
;
6008 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
6009 dpyinfo
->mouse_face_defer
= 0;
6010 dpyinfo
->x_focus_frame
= 0;
6011 dpyinfo
->x_focus_event_frame
= 0;
6012 dpyinfo
->x_highlight_frame
= 0;
6014 dpyinfo
->Xatom_wm_protocols
6015 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
6016 dpyinfo
->Xatom_wm_take_focus
6017 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
6018 dpyinfo
->Xatom_wm_save_yourself
6019 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
6020 dpyinfo
->Xatom_wm_delete_window
6021 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
6022 dpyinfo
->Xatom_wm_change_state
6023 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
6024 dpyinfo
->Xatom_wm_configure_denied
6025 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
6026 dpyinfo
->Xatom_wm_window_moved
6027 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
6028 dpyinfo
->Xatom_editres
6029 = XInternAtom (dpyinfo
->display
, "Editres", False
);
6030 dpyinfo
->Xatom_CLIPBOARD
6031 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
6032 dpyinfo
->Xatom_TIMESTAMP
6033 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
6035 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
6036 dpyinfo
->Xatom_DELETE
6037 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
6038 dpyinfo
->Xatom_MULTIPLE
6039 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
6041 = XInternAtom (dpyinfo
->display
, "INCR", False
);
6042 dpyinfo
->Xatom_EMACS_TMP
6043 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
6044 dpyinfo
->Xatom_TARGETS
6045 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
6047 = XInternAtom (dpyinfo
->display
, "NULL", False
);
6048 dpyinfo
->Xatom_ATOM_PAIR
6049 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
6051 dpyinfo
->cut_buffers_initialized
= 0;
6053 connection
= ConnectionNumber (dpyinfo
->display
);
6054 dpyinfo
->connection
= connection
;
6057 /* This is only needed for distinguishing keyboard and process input. */
6058 if (connection
!= 0)
6059 add_keyboard_wait_descriptor (connection
);
6062 #ifndef F_SETOWN_BUG
6064 #ifdef F_SETOWN_SOCK_NEG
6065 /* stdin is a socket here */
6066 fcntl (connection
, F_SETOWN
, -getpid ());
6067 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6068 fcntl (connection
, F_SETOWN
, getpid ());
6069 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6070 #endif /* ! defined (F_SETOWN) */
6071 #endif /* F_SETOWN_BUG */
6074 if (interrupt_input
)
6075 init_sigio (connection
);
6076 #endif /* ! defined (SIGIO) */
6083 /* Get rid of display DPYINFO, assuming all frames are already gone,
6084 and without sending any more commands to the X server. */
6087 x_delete_display (dpyinfo
)
6088 struct x_display_info
*dpyinfo
;
6090 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
6092 /* Discard this display from x_display_name_list and x_display_list.
6093 We can't use Fdelq because that can quit. */
6094 if (! NILP (x_display_name_list
)
6095 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
6096 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
6101 tail
= x_display_name_list
;
6102 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
6104 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
6105 dpyinfo
->name_list_element
))
6107 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
6110 tail
= XCONS (tail
)->cdr
;
6114 if (x_display_list
== dpyinfo
)
6115 x_display_list
= dpyinfo
->next
;
6118 struct x_display_info
*tail
;
6120 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
6121 if (tail
->next
== dpyinfo
)
6122 tail
->next
= tail
->next
->next
;
6125 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6126 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6127 XrmDestroyDatabase (dpyinfo
->xrdb
);
6131 if (--dpyinfo
->kboard
->reference_count
== 0)
6132 delete_kboard (dpyinfo
->kboard
);
6134 xfree (dpyinfo
->font_table
);
6135 xfree (dpyinfo
->x_id_name
);
6139 /* Set up use of X before we make the first connection. */
6143 clear_frame_hook
= XTclear_frame
;
6144 clear_end_of_line_hook
= XTclear_end_of_line
;
6145 ins_del_lines_hook
= XTins_del_lines
;
6146 change_line_highlight_hook
= XTchange_line_highlight
;
6147 insert_glyphs_hook
= XTinsert_glyphs
;
6148 write_glyphs_hook
= XTwrite_glyphs
;
6149 delete_glyphs_hook
= XTdelete_glyphs
;
6150 ring_bell_hook
= XTring_bell
;
6151 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6152 set_terminal_modes_hook
= XTset_terminal_modes
;
6153 update_begin_hook
= XTupdate_begin
;
6154 update_end_hook
= XTupdate_end
;
6155 set_terminal_window_hook
= XTset_terminal_window
;
6156 read_socket_hook
= XTread_socket
;
6157 frame_up_to_date_hook
= XTframe_up_to_date
;
6158 cursor_to_hook
= XTcursor_to
;
6159 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6160 mouse_position_hook
= XTmouse_position
;
6161 frame_rehighlight_hook
= XTframe_rehighlight
;
6162 frame_raise_lower_hook
= XTframe_raise_lower
;
6163 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6164 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6165 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6166 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6168 scroll_region_ok
= 1; /* we'll scroll partial frames */
6169 char_ins_del_ok
= 0; /* just as fast to write the line */
6170 line_ins_del_ok
= 1; /* we'll just blt 'em */
6171 fast_clear_end_of_line
= 1; /* X does this well */
6172 memory_below_frame
= 0; /* we don't remember what scrolls
6178 /* Try to use interrupt input; if we can't, then start polling. */
6179 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6181 #ifdef USE_X_TOOLKIT
6182 XtToolkitInitialize ();
6183 Xt_app_con
= XtCreateApplicationContext ();
6184 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
6187 /* Note that there is no real way portable across R3/R4 to get the
6188 original error handler. */
6189 XSetErrorHandler (x_error_quitter
);
6190 XSetIOErrorHandler (x_io_error_quitter
);
6192 /* Disable Window Change signals; they are handled by X events. */
6194 signal (SIGWINCH
, SIG_DFL
);
6195 #endif /* ! defined (SIGWINCH) */
6197 signal (SIGPIPE
, x_connection_signal
);
6203 staticpro (&x_display_name_list
);
6204 x_display_name_list
= Qnil
;
6206 staticpro (&last_mouse_scroll_bar
);
6207 last_mouse_scroll_bar
= Qnil
;
6209 staticpro (&Qvendor_specific_keysyms
);
6210 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6212 #endif /* ! defined (HAVE_X_WINDOWS) */