1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
60 #ifndef INCLUDED_FCNTL
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
71 #include "dispextern.h"
72 #include "termhooks.h"
84 #include "intervals.h"
87 extern void free_frame_menubar ();
88 extern FRAME_PTR
x_menubar_window_to_frame ();
89 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
91 extern void _XEditResCheckMessages ();
92 #endif /* not NO_EDITRES */
93 #endif /* USE_X_TOOLKIT */
96 #define x_any_window_to_frame x_window_to_frame
97 #define x_top_window_to_frame x_window_to_frame
102 #ifndef XtNinitialState
103 #define XtNinitialState "initialState"
108 /* So we can do setlocale. */
112 #define min(a,b) ((a)<(b) ? (a) : (b))
113 #define max(a,b) ((a)>(b) ? (a) : (b))
115 /* This is a chain of structures for all the X displays currently in use. */
116 struct x_display_info
*x_display_list
;
118 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
119 one for each element of x_display_list and in the same order.
120 NAME is the name of the frame.
121 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
122 Lisp_Object x_display_name_list
;
124 /* Frame being updated by update_frame. This is declared in term.c.
125 This is set by update_begin and looked at by all the
126 XT functions. It is zero while not inside an update.
127 In that case, the XT functions assume that `selected_frame'
128 is the frame to apply to. */
129 extern struct frame
*updating_frame
;
131 /* This is a frame waiting to be autoraised, within XTread_socket. */
132 struct frame
*pending_autoraise_frame
;
135 /* The application context for Xt use. */
136 XtAppContext Xt_app_con
;
138 static String Xt_default_resources
[] =
144 /* During an update, maximum vpos for ins/del line operations to affect. */
146 static int flexlines
;
148 /* During an update, nonzero if chars output now should be highlighted. */
150 static int highlight
;
152 /* Nominal cursor position -- where to draw output.
153 During an update, these are different from the cursor-box position. */
160 In order to avoid asking for motion events and then throwing most
161 of them away or busy-polling the server for mouse positions, we ask
162 the server for pointer motion hints. This means that we get only
163 one event per group of mouse movements. "Groups" are delimited by
164 other kinds of events (focus changes and button clicks, for
165 example), or by XQueryPointer calls; when one of these happens, we
166 get another MotionNotify event the next time the mouse moves. This
167 is at least as efficient as getting motion events when mouse
168 tracking is on, and I suspect only negligibly worse when tracking
171 The silly O'Reilly & Associates Nutshell guides barely document
172 pointer motion hints at all (I think you have to infer how they
173 work from an example), and the description of XQueryPointer doesn't
174 mention that calling it causes you to get another motion hint from
175 the server, which is very important. */
177 /* Where the mouse was last time we reported a mouse event. */
178 static FRAME_PTR last_mouse_frame
;
179 static XRectangle last_mouse_glyph
;
181 /* The scroll bar in which the last X motion event occurred.
183 If the last X motion event occurred in a scroll bar, we set this
184 so XTmouse_position can know whether to report a scroll bar motion or
187 If the last X motion event didn't occur in a scroll bar, we set this
188 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
189 static Lisp_Object last_mouse_scroll_bar
;
191 /* This is a hack. We would really prefer that XTmouse_position would
192 return the time associated with the position it returns, but there
193 doesn't seem to be any way to wrest the timestamp from the server
194 along with the position query. So, we just keep track of the time
195 of the last movement we received, and return that in hopes that
196 it's somewhat accurate. */
197 static Time last_mouse_movement_time
;
199 /* Incremented by XTread_socket whenever it really tries to read events. */
201 static int volatile input_signal_count
;
203 static int input_signal_count
;
206 /* Used locally within XTread_socket. */
207 static int x_noop_count
;
209 /* Initial values of argv and argc. */
210 extern char **initial_argv
;
211 extern int initial_argc
;
213 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
215 /* Tells if a window manager is present or not. */
217 extern Lisp_Object Vx_no_window_manager
;
219 /* Nonzero enables some debugging for the X interface code. */
222 extern Lisp_Object Qface
, Qmouse_face
;
226 /* A mask of extra modifier bits to put into every keyboard char. */
227 extern int extra_keyboard_modifiers
;
229 static Lisp_Object Qvendor_specific_keysyms
;
231 extern XrmDatabase
x_load_resources ();
233 extern Lisp_Object
x_icon_type ();
235 void x_delete_display ();
237 static void redraw_previous_char ();
238 static void redraw_following_char ();
239 static unsigned int x_x_to_emacs_modifiers ();
241 static int fast_find_position ();
242 static void note_mouse_highlight ();
243 static void clear_mouse_face ();
244 static void show_mouse_face ();
245 static void do_line_dance ();
247 static int XTcursor_to ();
248 static int XTclear_end_of_line ();
249 static int x_io_error_quitter ();
250 void x_catch_errors ();
251 void x_uncatch_errors ();
254 /* This is a function useful for recording debugging information
255 about the sequence of occurrences in this file. */
263 struct record event_record
[100];
265 int event_record_index
;
267 record_event (locus
, type
)
271 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
272 event_record_index
= 0;
274 event_record
[event_record_index
].locus
= locus
;
275 event_record
[event_record_index
].type
= type
;
276 event_record_index
++;
281 /* Return the struct x_display_info corresponding to DPY. */
283 struct x_display_info
*
284 x_display_info_for_display (dpy
)
287 struct x_display_info
*dpyinfo
;
289 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
290 if (dpyinfo
->display
== dpy
)
296 /* Starting and ending updates.
298 These hooks are called by update_frame at the beginning and end
299 of a frame update. We record in `updating_frame' the identity
300 of the frame being updated, so that the XT... functions do not
301 need to take a frame as argument. Most of the XT... functions
302 should never be called except during an update, the only exceptions
303 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
314 flexlines
= f
->height
;
319 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
321 /* Don't do highlighting for mouse motion during the update. */
322 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
324 /* If the frame needs to be redrawn,
325 simply forget about any prior mouse highlighting. */
326 if (FRAME_GARBAGED_P (f
))
327 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
329 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
331 int firstline
, lastline
, i
;
332 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
334 /* Find the first, and the last+1, lines affected by redisplay. */
335 for (firstline
= 0; firstline
< f
->height
; firstline
++)
336 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
339 lastline
= f
->height
;
340 for (i
= f
->height
- 1; i
>= 0; i
--)
342 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
348 /* Can we tell that this update does not affect the window
349 where the mouse highlight is? If so, no need to turn off.
350 Likewise, don't do anything if the frame is garbaged;
351 in that case, the FRAME_CURRENT_GLYPHS that we would use
352 are all wrong, and we will redisplay that line anyway. */
353 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
354 || lastline
< XFASTINT (w
->top
)))
355 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
371 x_display_cursor (f
, 1);
373 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
374 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
376 /* This fails in the case of having updated only the echo area
377 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
378 has no relation to the current contents, and its charstarts
379 have no relation to the contents of the window-buffer.
380 I don't know a clean way to check
381 for that case. window_end_valid isn't set up yet. */
382 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
383 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
384 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
387 XFlush (FRAME_X_DISPLAY (f
));
391 /* This is called after a redisplay on frame F. */
394 XTframe_up_to_date (f
)
398 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
399 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
401 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
402 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
403 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
404 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
409 /* External interface to control of standout mode.
410 Call this when about to modify line at position VPOS
411 and not change whether it is highlighted. */
413 XTreassert_line_highlight (new, vpos
)
419 /* Call this when about to modify line at position VPOS
420 and change whether it is highlighted. */
423 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
424 int new_highlight
, vpos
, first_unused_hpos
;
426 highlight
= new_highlight
;
427 XTcursor_to (vpos
, 0);
428 XTclear_end_of_line (updating_frame
->width
);
431 /* This is used when starting Emacs and when restarting after suspend.
432 When starting Emacs, no X window is mapped. And nothing must be done
433 to Emacs's own window if it is suspended (though that rarely happens). */
436 XTset_terminal_modes ()
440 /* This is called when exiting or suspending Emacs.
441 Exiting will make the X-windows go away, and suspending
442 requires no action. */
445 XTreset_terminal_modes ()
447 /* XTclear_frame (); */
450 /* Set the nominal cursor position of the frame.
451 This is where display update commands will take effect.
452 This does not affect the place where the cursor-box is displayed. */
455 XTcursor_to (row
, col
)
456 register int row
, col
;
464 if (updating_frame
== 0)
467 x_display_cursor (selected_frame
, 1);
468 XFlush (FRAME_X_DISPLAY (selected_frame
));
473 /* Display a sequence of N glyphs found at GP.
474 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
475 HL is 1 if this text is highlighted, 2 if the cursor is on it,
476 3 if should appear in its mouse-face.
477 JUST_FOREGROUND if 1 means draw only the foreground;
478 don't alter the background.
480 FONT is the default font to use (for glyphs whose font-code is 0).
482 Since the display generation code is responsible for calling
483 compute_char_face and compute_glyph_face on everything it puts in
484 the display structure, we can assume that the face code on each
485 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
486 to which we can actually apply intern_face.
487 Call this function with input blocked. */
490 /* This is the multi-face code. */
493 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
496 register GLYPH
*gp
; /* Points to first GLYPH. */
497 register int n
; /* Number of glyphs to display. */
501 /* Holds characters to be displayed. */
502 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
503 register char *cp
; /* Steps through buf[]. */
504 register int tlen
= GLYPH_TABLE_LENGTH
;
505 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
506 Window window
= FRAME_X_WINDOW (f
);
507 int orig_left
= left
;
511 /* Get the face-code of the next GLYPH. */
515 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
516 cf
= FAST_GLYPH_FACE (g
);
518 /* Find the run of consecutive glyphs with the same face-code.
519 Extract their character codes into BUF. */
524 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
525 if (FAST_GLYPH_FACE (g
) != cf
)
528 *cp
++ = FAST_GLYPH_CHAR (g
);
533 /* LEN gets the length of the run. */
536 /* Now output this run of chars, with the font and pixel values
537 determined by the face code CF. */
539 struct face
*face
= FRAME_DEFAULT_FACE (f
);
540 XFontStruct
*font
= FACE_FONT (face
);
541 GC gc
= FACE_GC (face
);
544 /* HL = 3 means use a mouse face previously chosen. */
546 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
548 /* First look at the face of the text itself. */
551 /* It's possible for the display table to specify
552 a face code that is out of range. Use 0 in that case. */
553 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
554 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
558 face
= FRAME_MODE_LINE_FACE (f
);
560 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
561 font
= FACE_FONT (face
);
563 if (FACE_STIPPLE (face
))
567 /* Then comes the distinction between modeline and normal text. */
572 face
= FRAME_MODE_LINE_FACE (f
);
573 font
= FACE_FONT (face
);
575 if (FACE_STIPPLE (face
))
579 #define FACE_DEFAULT (~0)
581 /* Now override that if the cursor's on this character. */
584 /* The cursor overrides stippling. */
588 || face
->font
== (XFontStruct
*) FACE_DEFAULT
589 || face
->font
== f
->output_data
.x
->font
)
590 && face
->background
== f
->output_data
.x
->background_pixel
591 && face
->foreground
== f
->output_data
.x
->foreground_pixel
)
593 gc
= f
->output_data
.x
->cursor_gc
;
595 /* Cursor on non-default face: must merge. */
601 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
602 xgcv
.foreground
= face
->background
;
603 /* If the glyph would be invisible,
604 try a different foreground. */
605 if (xgcv
.foreground
== xgcv
.background
)
606 xgcv
.foreground
= face
->foreground
;
607 if (xgcv
.foreground
== xgcv
.background
)
608 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
609 if (xgcv
.foreground
== xgcv
.background
)
610 xgcv
.foreground
= face
->foreground
;
611 /* Make sure the cursor is distinct from text in this face. */
612 if (xgcv
.background
== face
->background
613 && xgcv
.foreground
== face
->foreground
)
615 xgcv
.background
= face
->foreground
;
616 xgcv
.foreground
= face
->background
;
618 xgcv
.font
= face
->font
->fid
;
619 xgcv
.graphics_exposures
= 0;
620 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
621 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
622 XChangeGC (FRAME_X_DISPLAY (f
),
623 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
626 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
627 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
628 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
630 /* If this code is restored, it must also reset to the default stipple
632 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
633 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
638 if (font
== (XFontStruct
*) FACE_DEFAULT
)
639 font
= f
->output_data
.x
->font
;
642 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
643 left
, top
+ FONT_BASE (font
), buf
, len
);
648 /* Turn stipple on. */
649 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
651 /* Draw stipple on background. */
652 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
654 FONT_WIDTH (font
) * len
,
657 /* Turn stipple off. */
658 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
660 /* Draw the text, solidly, onto the stipple pattern. */
661 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
662 left
, top
+ FONT_BASE (font
), buf
, len
);
665 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
666 left
, top
+ FONT_BASE (font
), buf
, len
);
668 /* Clear the rest of the line's height. */
669 if (f
->output_data
.x
->line_height
!= FONT_HEIGHT (font
))
670 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
671 top
+ FONT_HEIGHT (font
),
672 FONT_WIDTH (font
) * len
,
673 /* This is how many pixels of height
675 f
->output_data
.x
->line_height
- FONT_HEIGHT (font
),
679 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
680 which often is not up to date yet. */
681 if (!just_foreground
)
683 if (left
== orig_left
)
684 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
685 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
687 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
688 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
692 /* We should probably check for XA_UNDERLINE_POSITION and
693 XA_UNDERLINE_THICKNESS properties on the font, but let's
694 just get the thing working, and come back to that. */
696 int underline_position
= 1;
698 if (font
->descent
<= underline_position
)
699 underline_position
= font
->descent
- 1;
702 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
706 + underline_position
),
707 len
* FONT_WIDTH (font
), 1);
710 left
+= len
* FONT_WIDTH (font
);
717 /* This is the old single-face code. */
720 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
723 register GLYPH
*gp
; /* Points to first GLYPH. */
724 register int n
; /* Number of glyphs to display. */
729 Window window
= FRAME_X_WINDOW (f
);
730 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
731 : (hl
? f
->output_data
.x
->reverse_gc
732 : f
->output_data
.x
->normal_gc
));
734 if (sizeof (GLYPH
) == sizeof (XChar2b
))
735 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
736 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
737 else if (sizeof (GLYPH
) == sizeof (unsigned char))
738 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
739 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
741 /* What size of glyph ARE you using? And does X have a function to
747 /* Output some text at the nominal frame cursor position.
748 Advance the cursor over the text.
749 Output LEN glyphs at START.
751 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
752 controls the pixel values used for foreground and background. */
755 XTwrite_glyphs (start
, len
)
756 register GLYPH
*start
;
759 register int temp_length
;
770 /* If not within an update,
771 output at the frame's visible cursor. */
772 curs_x
= f
->cursor_x
;
773 curs_y
= f
->cursor_y
;
777 CHAR_TO_PIXEL_COL (f
, curs_x
),
778 CHAR_TO_PIXEL_ROW (f
, curs_y
),
779 start
, len
, highlight
, 0);
781 /* If we drew on top of the cursor, note that it is turned off. */
782 if (curs_y
== f
->phys_cursor_y
783 && curs_x
<= f
->phys_cursor_x
784 && curs_x
+ len
> f
->phys_cursor_x
)
785 f
->phys_cursor_x
= -1;
787 if (updating_frame
== 0)
790 x_display_cursor (f
, 1);
799 /* Clear to the end of the line.
800 Erase the current text line from the nominal cursor position (inclusive)
801 to column FIRST_UNUSED (exclusive). The idea is that everything
802 from FIRST_UNUSED onward is already erased. */
805 XTclear_end_of_line (first_unused
)
806 register int first_unused
;
808 struct frame
*f
= updating_frame
;
814 if (curs_y
< 0 || curs_y
>= f
->height
)
816 if (first_unused
<= 0)
819 if (first_unused
>= f
->width
)
820 first_unused
= f
->width
;
826 /* Notice if the cursor will be cleared by this operation. */
827 if (curs_y
== f
->phys_cursor_y
828 && curs_x
<= f
->phys_cursor_x
829 && f
->phys_cursor_x
< first_unused
)
830 f
->phys_cursor_x
= -1;
832 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
833 CHAR_TO_PIXEL_COL (f
, curs_x
),
834 CHAR_TO_PIXEL_ROW (f
, curs_y
),
835 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
836 f
->output_data
.x
->line_height
, False
);
838 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
848 struct frame
*f
= updating_frame
;
853 f
->phys_cursor_x
= -1; /* Cursor not visible. */
854 curs_x
= 0; /* Nominal cursor position is top left. */
859 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
861 /* We have to clear the scroll bars, too. If we have changed
862 colors or something like that, then they should be notified. */
863 x_scroll_bar_clear (f
);
865 XFlush (FRAME_X_DISPLAY (f
));
870 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
871 always contain the right glyphs to use.
873 It also needs to be changed to look at the details of the font and
874 see whether there is really overlap, and do nothing when there is
875 not. This can use font_char_overlap_left and font_char_overlap_right,
876 but just how to use them is not clear. */
878 /* Erase the character (if any) at the position just before X, Y in frame F,
879 then redraw it and the character before it.
880 This is necessary when we erase starting at X,
881 in case the character after X overlaps into the one before X.
882 Call this function with input blocked. */
885 redraw_previous_char (f
, x
, y
, highlight_flag
)
890 /* Erase the character before the new ones, in case
891 what was here before overlaps it.
892 Reoutput that character, and the previous character
893 (in case the previous character overlaps it). */
899 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
900 CHAR_TO_PIXEL_COL (f
, x
- 1),
901 CHAR_TO_PIXEL_ROW (f
, y
),
902 FONT_WIDTH (f
->output_data
.x
->font
),
903 f
->output_data
.x
->line_height
, False
);
905 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
906 CHAR_TO_PIXEL_ROW (f
, y
),
907 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
908 x
- start_x
, highlight_flag
, 1);
912 /* Erase the character (if any) at the position X, Y in frame F,
913 then redraw it and the character after it.
914 This is necessary when we erase endng at X,
915 in case the character after X overlaps into the one before X.
916 Call this function with input blocked. */
919 redraw_following_char (f
, x
, y
, highlight_flag
)
924 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
925 /* Erase the character after the new ones, in case
926 what was here before overlaps it.
927 Reoutput that character, and the following character
928 (in case the following character overlaps it). */
930 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
935 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
936 CHAR_TO_PIXEL_COL (f
, x
),
937 CHAR_TO_PIXEL_ROW (f
, y
),
938 FONT_WIDTH (f
->output_data
.x
->font
),
939 f
->output_data
.x
->line_height
, False
);
941 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
942 CHAR_TO_PIXEL_ROW (f
, y
),
943 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
944 end_x
- x
, highlight_flag
, 1);
949 #if 0 /* Not in use yet */
951 /* Return 1 if character C in font F extends past its left edge. */
954 font_char_overlap_left (font
, c
)
960 /* Find the bounding-box info for C. */
961 if (font
->per_char
== 0)
962 s
= &font
->max_bounds
;
965 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
968 /* Decode char into row number (byte 1) and code within row (byte 2). */
971 if (!(within
>= font
->min_char_or_byte2
972 && within
<= font
->max_char_or_byte2
973 && row
>= font
->min_byte1
974 && row
<= font
->max_byte1
))
976 /* If char is out of range, try the font's default char instead. */
977 c
= font
->default_char
;
978 row
= c
>> (BITS_PER_INT
- 8);
981 if (!(within
>= font
->min_char_or_byte2
982 && within
<= font
->max_char_or_byte2
983 && row
>= font
->min_byte1
984 && row
<= font
->max_byte1
))
985 /* Still out of range means this char does not overlap. */
988 /* We found the info for this char. */
989 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
993 return (s
&& s
->lbearing
< 0);
996 /* Return 1 if character C in font F extends past its right edge. */
999 font_char_overlap_right (font
, c
)
1005 /* Find the bounding-box info for C. */
1006 if (font
->per_char
== 0)
1007 s
= &font
->max_bounds
;
1010 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1013 /* Decode char into row number (byte 1) and code within row (byte 2). */
1016 if (!(within
>= font
->min_char_or_byte2
1017 && within
<= font
->max_char_or_byte2
1018 && row
>= font
->min_byte1
1019 && row
<= font
->max_byte1
))
1021 /* If char is out of range, try the font's default char instead. */
1022 c
= font
->default_char
;
1023 row
= c
>> (BITS_PER_INT
- 8);
1026 if (!(within
>= font
->min_char_or_byte2
1027 && within
<= font
->max_char_or_byte2
1028 && row
>= font
->min_byte1
1029 && row
<= font
->max_byte1
))
1030 /* Still out of range means this char does not overlap. */
1033 /* We found the info for this char. */
1034 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1038 return (s
&& s
->rbearing
>= s
->width
);
1042 /* Invert the middle quarter of the frame for .15 sec. */
1044 /* We use the select system call to do the waiting, so we have to make sure
1045 it's available. If it isn't, we just won't do visual bells. */
1046 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1048 /* Subtract the `struct timeval' values X and Y,
1049 storing the result in RESULT.
1050 Return 1 if the difference is negative, otherwise 0. */
1053 timeval_subtract (result
, x
, y
)
1054 struct timeval
*result
, x
, y
;
1056 /* Perform the carry for the later subtraction by updating y.
1057 This is safer because on some systems
1058 the tv_sec member is unsigned. */
1059 if (x
.tv_usec
< y
.tv_usec
)
1061 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1062 y
.tv_usec
-= 1000000 * nsec
;
1065 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1067 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1068 y
.tv_usec
+= 1000000 * nsec
;
1072 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1073 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1074 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1076 /* Return indication of whether the result should be considered negative. */
1077 return x
.tv_sec
< y
.tv_sec
;
1088 /* Create a GC that will use the GXxor function to flip foreground pixels
1089 into background pixels. */
1093 values
.function
= GXxor
;
1094 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1095 ^ f
->output_data
.x
->background_pixel
);
1097 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1098 GCFunction
| GCForeground
, &values
);
1102 int width
= PIXEL_WIDTH (f
);
1103 int height
= PIXEL_HEIGHT (f
);
1105 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1106 width
/4, height
/4, width
/2, height
/2);
1107 XFlush (FRAME_X_DISPLAY (f
));
1110 struct timeval wakeup
, now
;
1112 EMACS_GET_TIME (wakeup
);
1114 /* Compute time to wait until, propagating carry from usecs. */
1115 wakeup
.tv_usec
+= 150000;
1116 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1117 wakeup
.tv_usec
%= 1000000;
1119 /* Keep waiting until past the time wakeup. */
1122 struct timeval timeout
;
1124 EMACS_GET_TIME (timeout
);
1126 /* In effect, timeout = wakeup - timeout.
1127 Break if result would be negative. */
1128 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1131 /* Try to wait that long--but we might wake up sooner. */
1132 select (0, NULL
, NULL
, NULL
, &timeout
);
1136 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1137 width
/4, height
/4, width
/2, height
/2);
1138 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1139 XFlush (FRAME_X_DISPLAY (f
));
1149 /* Make audible bell. */
1151 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1155 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1158 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1160 XTflash (selected_frame
);
1166 XFlush (FRAME_X_DISPLAY (selected_frame
));
1171 /* Insert and delete character.
1172 These are not supposed to be used because we are supposed to turn
1173 off the feature of using them. */
1176 XTinsert_glyphs (start
, len
)
1177 register char *start
;
1190 /* Specify how many text lines, from the top of the window,
1191 should be affected by insert-lines and delete-lines operations.
1192 This, and those operations, are used only within an update
1193 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1196 XTset_terminal_window (n
)
1199 if (updating_frame
== 0)
1202 if ((n
<= 0) || (n
> updating_frame
->height
))
1203 flexlines
= updating_frame
->height
;
1208 /* These variables need not be per frame
1209 because redisplay is done on a frame-by-frame basis
1210 and the line dance for one frame is finished before
1211 anything is done for anoter frame. */
1213 /* Array of line numbers from cached insert/delete operations.
1214 line_dance[i] is the old position of the line that we want
1215 to move to line i, or -1 if we want a blank line there. */
1216 static int *line_dance
;
1218 /* Allocated length of that array. */
1219 static int line_dance_len
;
1221 /* Flag indicating whether we've done any work. */
1222 static int line_dance_in_progress
;
1224 /* Perform an insert-lines or delete-lines operation,
1225 inserting N lines or deleting -N lines at vertical position VPOS. */
1226 XTins_del_lines (vpos
, n
)
1229 register int fence
, i
;
1231 if (vpos
>= flexlines
)
1234 if (!line_dance_in_progress
)
1236 int ht
= updating_frame
->height
;
1237 if (ht
> line_dance_len
)
1239 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1240 line_dance_len
= ht
;
1242 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1243 line_dance_in_progress
= 1;
1247 if (n
> flexlines
- vpos
)
1248 n
= flexlines
- vpos
;
1250 for (i
= flexlines
; --i
>= fence
;)
1251 line_dance
[i
] = line_dance
[i
-n
];
1252 for (i
= fence
; --i
>= vpos
;)
1258 if (n
> flexlines
- vpos
)
1259 n
= flexlines
- vpos
;
1260 fence
= flexlines
- n
;
1261 for (i
= vpos
; i
< fence
; ++i
)
1262 line_dance
[i
] = line_dance
[i
+ n
];
1263 for (i
= fence
; i
< flexlines
; ++i
)
1268 /* Here's where we actually move the pixels around.
1269 Must be called with input blocked. */
1273 register int i
, j
, distance
;
1274 register struct frame
*f
;
1278 /* Must check this flag first. If it's not set, then not only is the
1279 array uninitialized, but we might not even have a frame. */
1280 if (!line_dance_in_progress
)
1288 intborder
= f
->output_data
.x
->internal_border_width
;
1290 x_display_cursor (updating_frame
, 0);
1292 for (i
= 0; i
< ht
; ++i
)
1293 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1295 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1296 && line_dance
[j
]-j
== distance
); ++j
);
1297 /* Copy [i,j) upward from [i+distance,j+distance) */
1298 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1299 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1300 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1301 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1302 (j
-i
) * f
->output_data
.x
->line_height
,
1303 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1307 for (i
= ht
; --i
>=0; )
1308 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1310 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1311 && line_dance
[j
]-j
== distance
););
1312 /* Copy (j,i] downward from (j+distance, i+distance] */
1313 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1314 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1315 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1316 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1317 (i
-j
) * f
->output_data
.x
->line_height
,
1318 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1322 for (i
= 0; i
< ht
; ++i
)
1323 if (line_dance
[i
] == -1)
1325 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1327 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1328 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1329 f
->width
* FONT_WIDTH (f
->output_data
.x
->font
),
1330 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1333 line_dance_in_progress
= 0;
1336 /* Support routines for exposure events. */
1337 static void clear_cursor ();
1339 /* Output into a rectangle of an X-window (for frame F)
1340 the characters in f->phys_lines that overlap that rectangle.
1341 TOP and LEFT are the position of the upper left corner of the rectangle.
1342 ROWS and COLS are the size of the rectangle.
1343 Call this function with input blocked. */
1346 dumprectangle (f
, left
, top
, cols
, rows
)
1348 register int left
, top
, cols
, rows
;
1350 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1351 int cursor_cleared
= 0;
1355 if (FRAME_GARBAGED_P (f
))
1358 /* Express rectangle as four edges, instead of position-and-size. */
1359 bottom
= top
+ rows
;
1360 right
= left
+ cols
;
1362 /* Convert rectangle edges in pixels to edges in chars.
1363 Round down for left and top, up for right and bottom. */
1364 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1365 left
= PIXEL_TO_CHAR_COL (f
, left
);
1366 bottom
+= (f
->output_data
.x
->line_height
- 1);
1367 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1368 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1369 right
= PIXEL_TO_CHAR_COL (f
, right
);
1371 /* Clip the rectangle to what can be visible. */
1376 if (right
> f
->width
)
1378 if (bottom
> f
->height
)
1381 /* Get size in chars of the rectangle. */
1382 cols
= right
- left
;
1383 rows
= bottom
- top
;
1385 /* If rectangle has zero area, return. */
1386 if (rows
<= 0) return;
1387 if (cols
<= 0) return;
1389 /* Turn off the cursor if it is in the rectangle.
1390 We will turn it back on afterward. */
1391 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1392 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1398 /* Display the text in the rectangle, one text line at a time. */
1400 for (y
= top
; y
< bottom
; y
++)
1402 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1404 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1408 CHAR_TO_PIXEL_COL (f
, left
),
1409 CHAR_TO_PIXEL_ROW (f
, y
),
1410 line
, min (cols
, active_frame
->used
[y
] - left
),
1411 active_frame
->highlight
[y
], 0);
1414 /* Turn the cursor on if we turned it off. */
1417 x_display_cursor (f
, 1);
1424 /* We used to only do this if Vx_no_window_manager was non-nil, but
1425 the ICCCM (section 4.1.6) says that the window's border pixmap
1426 and border pixel are window attributes which are "private to the
1427 client", so we can always change it to whatever we want. */
1429 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1430 f
->output_data
.x
->border_pixel
);
1432 x_update_cursor (f
, 1);
1436 frame_unhighlight (f
)
1439 /* We used to only do this if Vx_no_window_manager was non-nil, but
1440 the ICCCM (section 4.1.6) says that the window's border pixmap
1441 and border pixel are window attributes which are "private to the
1442 client", so we can always change it to whatever we want. */
1444 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1445 f
->output_data
.x
->border_tile
);
1447 x_update_cursor (f
, 1);
1450 static void XTframe_rehighlight ();
1451 static void x_frame_rehighlight ();
1453 /* The focus has changed. Update the frames as necessary to reflect
1454 the new situation. Note that we can't change the selected frame
1455 here, because the Lisp code we are interrupting might become confused.
1456 Each event gets marked with the frame in which it occurred, so the
1457 Lisp code can tell when the switch took place by examining the events. */
1460 x_new_focus_frame (dpyinfo
, frame
)
1461 struct x_display_info
*dpyinfo
;
1462 struct frame
*frame
;
1464 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1465 int events_enqueued
= 0;
1467 if (frame
!= dpyinfo
->x_focus_frame
)
1469 /* Set this before calling other routines, so that they see
1470 the correct value of x_focus_frame. */
1471 dpyinfo
->x_focus_frame
= frame
;
1473 if (old_focus
&& old_focus
->auto_lower
)
1474 x_lower_frame (old_focus
);
1477 selected_frame
= frame
;
1478 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1480 Fselect_window (selected_frame
->selected_window
);
1481 choose_minibuf_frame ();
1484 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1485 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1487 pending_autoraise_frame
= 0;
1490 x_frame_rehighlight (dpyinfo
);
1493 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1496 x_mouse_leave (dpyinfo
)
1497 struct x_display_info
*dpyinfo
;
1499 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1502 /* The focus has changed, or we have redirected a frame's focus to
1503 another frame (this happens when a frame uses a surrogate
1504 minibuffer frame). Shift the highlight as appropriate.
1506 The FRAME argument doesn't necessarily have anything to do with which
1507 frame is being highlighted or unhighlighted; we only use it to find
1508 the appropriate X display info. */
1510 XTframe_rehighlight (frame
)
1511 struct frame
*frame
;
1513 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
1517 x_frame_rehighlight (dpyinfo
)
1518 struct x_display_info
*dpyinfo
;
1520 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1522 if (dpyinfo
->x_focus_frame
)
1524 dpyinfo
->x_highlight_frame
1525 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
1526 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
1527 : dpyinfo
->x_focus_frame
);
1528 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
1530 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
1531 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1535 dpyinfo
->x_highlight_frame
= 0;
1537 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
1540 frame_unhighlight (old_highlight
);
1541 if (dpyinfo
->x_highlight_frame
)
1542 frame_highlight (dpyinfo
->x_highlight_frame
);
1546 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1548 /* Initialize mode_switch_bit and modifier_meaning. */
1550 x_find_modifier_meanings (dpyinfo
)
1551 struct x_display_info
*dpyinfo
;
1553 int min_code
, max_code
;
1556 XModifierKeymap
*mods
;
1558 dpyinfo
->meta_mod_mask
= 0;
1559 dpyinfo
->shift_lock_mask
= 0;
1560 dpyinfo
->alt_mod_mask
= 0;
1561 dpyinfo
->super_mod_mask
= 0;
1562 dpyinfo
->hyper_mod_mask
= 0;
1565 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1567 min_code
= dpyinfo
->display
->min_keycode
;
1568 max_code
= dpyinfo
->display
->max_keycode
;
1571 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1572 min_code
, max_code
- min_code
+ 1,
1574 mods
= XGetModifierMapping (dpyinfo
->display
);
1576 /* Scan the modifier table to see which modifier bits the Meta and
1577 Alt keysyms are on. */
1579 int row
, col
; /* The row and column in the modifier table. */
1581 for (row
= 3; row
< 8; row
++)
1582 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1585 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1587 /* Zeroes are used for filler. Skip them. */
1591 /* Are any of this keycode's keysyms a meta key? */
1595 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1597 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1603 dpyinfo
->meta_mod_mask
|= (1 << row
);
1608 dpyinfo
->alt_mod_mask
|= (1 << row
);
1613 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1618 dpyinfo
->super_mod_mask
|= (1 << row
);
1622 /* Ignore this if it's not on the lock modifier. */
1623 if ((1 << row
) == LockMask
)
1624 dpyinfo
->shift_lock_mask
= LockMask
;
1632 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1633 if (! dpyinfo
->meta_mod_mask
)
1635 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1636 dpyinfo
->alt_mod_mask
= 0;
1639 /* If some keys are both alt and meta,
1640 make them just meta, not alt. */
1641 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1643 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1646 XFree ((char *) syms
);
1647 XFreeModifiermap (mods
);
1650 /* Convert between the modifier bits X uses and the modifier bits
1653 x_x_to_emacs_modifiers (dpyinfo
, state
)
1654 struct x_display_info
*dpyinfo
;
1657 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1658 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1659 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1660 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1661 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1662 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1666 x_emacs_to_x_modifiers (dpyinfo
, state
)
1667 struct x_display_info
*dpyinfo
;
1670 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1671 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1672 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1673 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1674 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1675 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1678 /* Convert a keysym to its name. */
1681 x_get_keysym_name (keysym
)
1687 value
= XKeysymToString (keysym
);
1693 /* Mouse clicks and mouse movement. Rah. */
1695 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1696 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1697 that the glyph at X, Y occupies, if BOUNDS != 0.
1698 If NOCLIP is nonzero, do not force the value into range. */
1701 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1703 register int pix_x
, pix_y
;
1704 register int *x
, *y
;
1708 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1709 even for negative values. */
1711 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
1713 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
1715 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1716 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1720 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
1721 bounds
->height
= f
->output_data
.x
->line_height
;
1722 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1723 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1730 else if (pix_x
> f
->width
)
1735 else if (pix_y
> f
->height
)
1744 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1747 register int *pix_x
, *pix_y
;
1749 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1750 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1753 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1755 If the event is a button press, then note that we have grabbed
1759 construct_mouse_click (result
, event
, f
)
1760 struct input_event
*result
;
1761 XButtonEvent
*event
;
1764 /* Make the event type no_event; we'll change that when we decide
1766 result
->kind
= mouse_click
;
1767 result
->code
= event
->button
- Button1
;
1768 result
->timestamp
= event
->time
;
1769 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1771 | (event
->type
== ButtonRelease
1779 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1780 XSETFASTINT (result
->x
, column
);
1781 XSETFASTINT (result
->y
, row
);
1783 XSETINT (result
->x
, event
->x
);
1784 XSETINT (result
->y
, event
->y
);
1785 XSETFRAME (result
->frame_or_window
, f
);
1789 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1792 construct_menu_click (result
, event
, f
)
1793 struct input_event
*result
;
1794 XButtonEvent
*event
;
1797 /* Make the event type no_event; we'll change that when we decide
1799 result
->kind
= mouse_click
;
1800 XSETINT (result
->code
, event
->button
- Button1
);
1801 result
->timestamp
= event
->time
;
1802 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1804 | (event
->type
== ButtonRelease
1808 XSETINT (result
->x
, event
->x
);
1809 XSETINT (result
->y
, -1);
1810 XSETFRAME (result
->frame_or_window
, f
);
1813 /* Function to report a mouse movement to the mainstream Emacs code.
1814 The input handler calls this.
1816 We have received a mouse movement event, which is given in *event.
1817 If the mouse is over a different glyph than it was last time, tell
1818 the mainstream emacs code by setting mouse_moved. If not, ask for
1819 another motion event, so we can check again the next time it moves. */
1822 note_mouse_movement (frame
, event
)
1824 XMotionEvent
*event
;
1826 last_mouse_movement_time
= event
->time
;
1828 if (event
->window
!= FRAME_X_WINDOW (frame
))
1830 frame
->mouse_moved
= 1;
1831 last_mouse_scroll_bar
= Qnil
;
1833 note_mouse_highlight (frame
, -1, -1);
1835 /* Ask for another mouse motion event. */
1838 Window dummy_window
;
1840 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1841 &dummy_window
, &dummy_window
,
1842 &dummy
, &dummy
, &dummy
, &dummy
,
1843 (unsigned int *) &dummy
);
1847 /* Has the mouse moved off the glyph it was on at the last sighting? */
1848 else if (event
->x
< last_mouse_glyph
.x
1849 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1850 || event
->y
< last_mouse_glyph
.y
1851 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1853 frame
->mouse_moved
= 1;
1854 last_mouse_scroll_bar
= Qnil
;
1856 note_mouse_highlight (frame
, event
->x
, event
->y
);
1858 /* Ask for another mouse motion event. */
1861 Window dummy_window
;
1863 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1864 &dummy_window
, &dummy_window
,
1865 &dummy
, &dummy
, &dummy
, &dummy
,
1866 (unsigned int *) &dummy
);
1871 /* It's on the same glyph. Call XQueryPointer so we'll get an
1872 event the next time the mouse moves and we can see if it's
1873 *still* on the same glyph. */
1875 Window dummy_window
;
1877 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1878 &dummy_window
, &dummy_window
,
1879 &dummy
, &dummy
, &dummy
, &dummy
,
1880 (unsigned int *) &dummy
);
1884 /* This is used for debugging, to turn off note_mouse_highlight. */
1885 static int disable_mouse_highlight
;
1887 /* Take proper action when the mouse has moved to position X, Y on frame F
1888 as regards highlighting characters that have mouse-face properties.
1889 Also dehighlighting chars where the mouse was before.
1890 X and Y can be negative or out of range. */
1893 note_mouse_highlight (f
, x
, y
)
1897 int row
, column
, portion
;
1898 XRectangle new_glyph
;
1902 if (disable_mouse_highlight
)
1905 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1906 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1907 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1909 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1914 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1918 /* Find out which glyph the mouse is on. */
1919 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1920 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1922 /* Which window is that in? */
1923 window
= window_from_coordinates (f
, column
, row
, &portion
);
1924 w
= XWINDOW (window
);
1926 /* If we were displaying active text in another window, clear that. */
1927 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1928 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1930 /* Are we in a window whose display is up to date?
1931 And verify the buffer's text has not changed. */
1932 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1933 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1934 && EQ (w
->window_end_valid
, w
->buffer
)
1935 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1937 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1940 /* Find which buffer position the mouse corresponds to. */
1941 for (i
= column
; i
>= 0; i
--)
1945 /* Is it outside the displayed active region (if any)? */
1947 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1948 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1949 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1950 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1951 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1952 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1953 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1954 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1955 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1957 Lisp_Object mouse_face
, overlay
, position
;
1958 Lisp_Object
*overlay_vec
;
1959 int len
, noverlays
, ignor1
;
1960 struct buffer
*obuf
;
1963 /* If we get an out-of-range value, return now; avoid an error. */
1964 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1967 /* Make the window's buffer temporarily current for
1968 overlays_at and compute_char_face. */
1969 obuf
= current_buffer
;
1970 current_buffer
= XBUFFER (w
->buffer
);
1976 /* Yes. Clear the display of the old active region, if any. */
1977 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1979 /* Is this char mouse-active? */
1980 XSETINT (position
, pos
);
1983 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1985 /* Put all the overlays we want in a vector in overlay_vec.
1986 Store the length in len. */
1987 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1989 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1991 /* Find the highest priority overlay that has a mouse-face prop. */
1993 for (i
= 0; i
< noverlays
; i
++)
1995 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1996 if (!NILP (mouse_face
))
1998 overlay
= overlay_vec
[i
];
2003 /* If no overlay applies, get a text property. */
2005 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2007 /* Handle the overlay case. */
2008 if (! NILP (overlay
))
2010 /* Find the range of text around this char that
2011 should be active. */
2012 Lisp_Object before
, after
;
2015 before
= Foverlay_start (overlay
);
2016 after
= Foverlay_end (overlay
);
2017 /* Record this as the current active region. */
2018 fast_find_position (window
, before
,
2019 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2020 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2021 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2022 = !fast_find_position (window
, after
,
2023 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2024 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2025 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2026 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2027 = compute_char_face (f
, w
, pos
, 0, 0,
2028 &ignore
, pos
+ 1, 1);
2030 /* Display it as active. */
2031 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2033 /* Handle the text property case. */
2034 else if (! NILP (mouse_face
))
2036 /* Find the range of text around this char that
2037 should be active. */
2038 Lisp_Object before
, after
, beginning
, end
;
2041 beginning
= Fmarker_position (w
->start
);
2042 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2043 - XFASTINT (w
->window_end_pos
)));
2045 = Fprevious_single_property_change (make_number (pos
+ 1),
2047 w
->buffer
, beginning
);
2049 = Fnext_single_property_change (position
, Qmouse_face
,
2051 /* Record this as the current active region. */
2052 fast_find_position (window
, before
,
2053 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2054 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2055 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2056 = !fast_find_position (window
, after
,
2057 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2058 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2059 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2060 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2061 = compute_char_face (f
, w
, pos
, 0, 0,
2062 &ignore
, pos
+ 1, 1);
2064 /* Display it as active. */
2065 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2069 current_buffer
= obuf
;
2074 /* Find the row and column of position POS in window WINDOW.
2075 Store them in *COLUMNP and *ROWP.
2076 This assumes display in WINDOW is up to date.
2077 If POS is above start of WINDOW, return coords
2078 of start of first screen line.
2079 If POS is after end of WINDOW, return coords of end of last screen line.
2081 Value is 1 if POS is in range, 0 if it was off screen. */
2084 fast_find_position (window
, pos
, columnp
, rowp
)
2087 int *columnp
, *rowp
;
2089 struct window
*w
= XWINDOW (window
);
2090 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2095 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2096 int width
= window_internal_width (w
);
2099 int maybe_next_line
= 0;
2101 /* Find the right row. */
2106 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2107 if (linestart
> pos
)
2109 /* If the position sought is the end of the buffer,
2110 don't include the blank lines at the bottom of the window. */
2111 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2113 maybe_next_line
= 1;
2120 /* Find the right column with in it. */
2121 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2123 for (i
= 0; i
< width
; i
++)
2125 if (charstarts
[left
+ i
] == pos
)
2128 *columnp
= i
+ left
;
2131 else if (charstarts
[left
+ i
] > pos
)
2133 else if (charstarts
[left
+ i
] > 0)
2137 /* If we're looking for the end of the buffer,
2138 and we didn't find it in the line we scanned,
2139 use the start of the following line. */
2140 if (maybe_next_line
)
2151 /* Display the active region described by mouse_face_*
2152 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2155 show_mouse_face (dpyinfo
, hl
)
2156 struct x_display_info
*dpyinfo
;
2159 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2160 int width
= window_internal_width (w
);
2161 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2164 int old_curs_x
= curs_x
;
2165 int old_curs_y
= curs_y
;
2167 /* Set these variables temporarily
2168 so that if we have to turn the cursor off and on again
2169 we will put it back at the same place. */
2170 curs_x
= f
->phys_cursor_x
;
2171 curs_y
= f
->phys_cursor_y
;
2173 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2174 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2176 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2177 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2179 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2180 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2182 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2184 /* If the cursor's in the text we are about to rewrite,
2185 turn the cursor off. */
2187 && curs_x
>= column
- 1
2188 && curs_x
<= endcolumn
)
2190 x_display_cursor (f
, 0);
2195 CHAR_TO_PIXEL_COL (f
, column
),
2196 CHAR_TO_PIXEL_ROW (f
, i
),
2197 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2199 /* Highlight with mouse face if hl > 0. */
2203 /* If we turned the cursor off, turn it back on. */
2205 x_display_cursor (f
, 1);
2207 curs_x
= old_curs_x
;
2208 curs_y
= old_curs_y
;
2210 /* Change the mouse cursor according to the value of HL. */
2212 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2213 f
->output_data
.x
->cross_cursor
);
2215 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2216 f
->output_data
.x
->text_cursor
);
2219 /* Clear out the mouse-highlighted active region.
2220 Redraw it unhighlighted first. */
2223 clear_mouse_face (dpyinfo
)
2224 struct x_display_info
*dpyinfo
;
2226 if (! NILP (dpyinfo
->mouse_face_window
))
2227 show_mouse_face (dpyinfo
, 0);
2229 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2230 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2231 dpyinfo
->mouse_face_window
= Qnil
;
2234 static struct scroll_bar
*x_window_to_scroll_bar ();
2235 static void x_scroll_bar_report_motion ();
2237 /* Return the current position of the mouse.
2238 *fp should be a frame which indicates which display to ask about.
2240 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2241 and *part to the frame, window, and scroll bar part that the mouse
2242 is over. Set *x and *y to the portion and whole of the mouse's
2243 position on the scroll bar.
2245 If the mouse movement started elsewhere, set *fp to the frame the
2246 mouse is on, *bar_window to nil, and *x and *y to the character cell
2249 Set *time to the server timestamp for the time at which the mouse
2250 was at this position.
2252 Don't store anything if we don't have a valid set of values to report.
2254 This clears the mouse_moved flag, so we can wait for the next mouse
2255 movement. This also calls XQueryPointer, which will cause the
2256 server to give us another MotionNotify when the mouse moves
2260 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2263 Lisp_Object
*bar_window
;
2264 enum scroll_bar_part
*part
;
2266 unsigned long *time
;
2272 if (! NILP (last_mouse_scroll_bar
))
2273 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2279 Window dummy_window
;
2282 Lisp_Object frame
, tail
;
2284 /* Clear the mouse-moved flag for every frame on this display. */
2285 FOR_EACH_FRAME (tail
, frame
)
2286 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2287 XFRAME (frame
)->mouse_moved
= 0;
2289 last_mouse_scroll_bar
= Qnil
;
2291 /* Figure out which root window we're on. */
2292 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2293 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2295 /* The root window which contains the pointer. */
2298 /* Trash which we can't trust if the pointer is on
2299 a different screen. */
2302 /* The position on that root window. */
2305 /* More trash we can't trust. */
2308 /* Modifier keys and pointer buttons, about which
2310 (unsigned int *) &dummy
);
2312 /* Now we have a position on the root; find the innermost window
2313 containing the pointer. */
2317 int parent_x
, parent_y
;
2321 /* XTranslateCoordinates can get errors if the window
2322 structure is changing at the same time this function
2323 is running. So at least we must not crash from them. */
2325 x_catch_errors (FRAME_X_DISPLAY (*fp
));
2327 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2328 && FRAME_LIVE_P (last_mouse_frame
))
2330 /* If mouse was grabbed on a frame, give coords for that frame
2331 even if the mouse is now outside it. */
2332 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2334 /* From-window, to-window. */
2335 root
, FRAME_X_WINDOW (last_mouse_frame
),
2337 /* From-position, to-position. */
2338 root_x
, root_y
, &win_x
, &win_y
,
2342 f1
= last_mouse_frame
;
2348 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2350 /* From-window, to-window. */
2353 /* From-position, to-position. */
2354 root_x
, root_y
, &win_x
, &win_y
,
2359 if (child
== None
|| child
== win
)
2367 /* Now we know that:
2368 win is the innermost window containing the pointer
2369 (XTC says it has no child containing the pointer),
2370 win_x and win_y are the pointer's position in it
2371 (XTC did this the last time through), and
2372 parent_x and parent_y are the pointer's position in win's parent.
2373 (They are what win_x and win_y were when win was child.
2374 If win is the root window, it has no parent, and
2375 parent_{x,y} are invalid, but that's okay, because we'll
2376 never use them in that case.) */
2378 /* Is win one of our frames? */
2379 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2382 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2385 x_uncatch_errors (FRAME_X_DISPLAY (*fp
));
2387 /* If not, is it one of our scroll bars? */
2390 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2394 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2400 if (f1
== 0 && insist
)
2401 f1
= selected_frame
;
2405 int ignore1
, ignore2
;
2407 /* Ok, we found a frame. Store all the values. */
2409 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2411 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2417 XSETINT (*x
, win_x
);
2418 XSETINT (*y
, win_y
);
2419 *time
= last_mouse_movement_time
;
2427 /* Scroll bar support. */
2429 /* Given an X window ID, find the struct scroll_bar which manages it.
2430 This can be called in GC, so we have to make sure to strip off mark
2432 static struct scroll_bar
*
2433 x_window_to_scroll_bar (window_id
)
2436 Lisp_Object tail
, frame
;
2438 for (tail
= Vframe_list
;
2439 XGCTYPE (tail
) == Lisp_Cons
;
2440 tail
= XCONS (tail
)->cdr
)
2442 Lisp_Object frame
, bar
, condemned
;
2444 frame
= XCONS (tail
)->car
;
2445 /* All elements of Vframe_list should be frames. */
2446 if (! GC_FRAMEP (frame
))
2449 /* Scan this frame's scroll bar list for a scroll bar with the
2451 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2452 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2453 /* This trick allows us to search both the ordinary and
2454 condemned scroll bar lists with one loop. */
2455 ! GC_NILP (bar
) || (bar
= condemned
,
2458 bar
= XSCROLL_BAR (bar
)->next
)
2459 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2460 return XSCROLL_BAR (bar
);
2466 /* Open a new X window to serve as a scroll bar, and return the
2467 scroll bar vector for it. */
2468 static struct scroll_bar
*
2469 x_scroll_bar_create (window
, top
, left
, width
, height
)
2470 struct window
*window
;
2471 int top
, left
, width
, height
;
2473 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2474 struct scroll_bar
*bar
2475 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2480 XSetWindowAttributes a
;
2482 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2483 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2484 | ButtonMotionMask
| PointerMotionHintMask
2486 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2488 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2493 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2494 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2495 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2496 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2497 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2498 sb_widget
= XtCreateManagedWidget ("box",
2500 f
->output_data
.x
->edit_widget
, al
, ac
);
2501 SET_SCROLL_BAR_X_WINDOW
2502 (bar
, sb_widget
->core
.window
);
2504 SET_SCROLL_BAR_X_WINDOW
2506 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2508 /* Position and size of scroll bar. */
2509 left
, top
, width
, height
,
2511 /* Border width, depth, class, and visual. */
2512 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2518 XSETWINDOW (bar
->window
, window
);
2519 XSETINT (bar
->top
, top
);
2520 XSETINT (bar
->left
, left
);
2521 XSETINT (bar
->width
, width
);
2522 XSETINT (bar
->height
, height
);
2523 XSETINT (bar
->start
, 0);
2524 XSETINT (bar
->end
, 0);
2525 bar
->dragging
= Qnil
;
2527 /* Add bar to its frame's list of scroll bars. */
2528 bar
->next
= FRAME_SCROLL_BARS (f
);
2530 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2531 if (! NILP (bar
->next
))
2532 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2534 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2541 /* Draw BAR's handle in the proper position.
2542 If the handle is already drawn from START to END, don't bother
2543 redrawing it, unless REBUILD is non-zero; in that case, always
2544 redraw it. (REBUILD is handy for drawing the handle after expose
2547 Normally, we want to constrain the start and end of the handle to
2548 fit inside its rectangle, but if the user is dragging the scroll bar
2549 handle, we want to let them drag it down all the way, so that the
2550 bar's top is as far down as it goes; otherwise, there's no way to
2551 move to the very end of the buffer. */
2553 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2554 struct scroll_bar
*bar
;
2558 int dragging
= ! NILP (bar
->dragging
);
2559 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2560 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2561 GC gc
= f
->output_data
.x
->normal_gc
;
2563 /* If the display is already accurate, do nothing. */
2565 && start
== XINT (bar
->start
)
2566 && end
== XINT (bar
->end
))
2572 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2573 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2574 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2576 /* Make sure the values are reasonable, and try to preserve
2577 the distance between start and end. */
2579 int length
= end
- start
;
2583 else if (start
> top_range
)
2585 end
= start
+ length
;
2589 else if (end
> top_range
&& ! dragging
)
2593 /* Store the adjusted setting in the scroll bar. */
2594 XSETINT (bar
->start
, start
);
2595 XSETINT (bar
->end
, end
);
2597 /* Clip the end position, just for display. */
2598 if (end
> top_range
)
2601 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2602 below top positions, to make sure the handle is always at least
2603 that many pixels tall. */
2604 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2606 /* Draw the empty space above the handle. Note that we can't clear
2607 zero-height areas; that means "clear to end of window." */
2609 XClearArea (FRAME_X_DISPLAY (f
), w
,
2611 /* x, y, width, height, and exposures. */
2612 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2613 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2614 inside_width
, start
,
2617 /* Draw the handle itself. */
2618 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2620 /* x, y, width, height */
2621 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2622 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2623 inside_width
, end
- start
);
2626 /* Draw the empty space below the handle. Note that we can't
2627 clear zero-height areas; that means "clear to end of window." */
2628 if (end
< inside_height
)
2629 XClearArea (FRAME_X_DISPLAY (f
), w
,
2631 /* x, y, width, height, and exposures. */
2632 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2633 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2634 inside_width
, inside_height
- end
,
2642 /* Move a scroll bar around on the screen, to accommodate changing
2643 window configurations. */
2645 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2646 struct scroll_bar
*bar
;
2647 int top
, left
, width
, height
;
2649 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2650 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2656 unsigned int mask
= 0;
2663 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2664 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2665 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2666 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2669 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2673 XSETINT (bar
->left
, left
);
2674 XSETINT (bar
->top
, top
);
2675 XSETINT (bar
->width
, width
);
2676 XSETINT (bar
->height
, height
);
2681 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2684 x_scroll_bar_remove (bar
)
2685 struct scroll_bar
*bar
;
2687 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2691 /* Destroy the window. */
2692 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2694 /* Disassociate this scroll bar from its window. */
2695 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2700 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2701 that we are displaying PORTION characters out of a total of WHOLE
2702 characters, starting at POSITION. If WINDOW has no scroll bar,
2705 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2706 struct window
*window
;
2707 int portion
, whole
, position
;
2709 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2710 int top
= XINT (window
->top
);
2711 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2712 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2714 /* Where should this scroll bar be, pixelwise? */
2715 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2716 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2718 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2719 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2720 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2721 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2723 struct scroll_bar
*bar
;
2725 /* Does the scroll bar exist yet? */
2726 if (NILP (window
->vertical_scroll_bar
))
2727 bar
= x_scroll_bar_create (window
,
2728 pixel_top
, pixel_left
,
2729 pixel_width
, pixel_height
);
2732 /* It may just need to be moved and resized. */
2733 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2734 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2737 /* Set the scroll bar's current state, unless we're currently being
2739 if (NILP (bar
->dragging
))
2741 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2744 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2747 int start
= ((double) position
* top_range
) / whole
;
2748 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2750 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2754 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2758 /* The following three hooks are used when we're doing a thorough
2759 redisplay of the frame. We don't explicitly know which scroll bars
2760 are going to be deleted, because keeping track of when windows go
2761 away is a real pain - "Can you say set-window-configuration, boys
2762 and girls?" Instead, we just assert at the beginning of redisplay
2763 that *all* scroll bars are to be removed, and then save a scroll bar
2764 from the fiery pit when we actually redisplay its window. */
2766 /* Arrange for all scroll bars on FRAME to be removed at the next call
2767 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2768 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2770 XTcondemn_scroll_bars (frame
)
2773 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2774 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2777 bar
= FRAME_SCROLL_BARS (frame
);
2778 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2779 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2780 XSCROLL_BAR (bar
)->prev
= Qnil
;
2781 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2782 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2783 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2787 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2788 Note that WINDOW isn't necessarily condemned at all. */
2790 XTredeem_scroll_bar (window
)
2791 struct window
*window
;
2793 struct scroll_bar
*bar
;
2795 /* We can't redeem this window's scroll bar if it doesn't have one. */
2796 if (NILP (window
->vertical_scroll_bar
))
2799 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2801 /* Unlink it from the condemned list. */
2803 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2805 if (NILP (bar
->prev
))
2807 /* If the prev pointer is nil, it must be the first in one of
2809 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2810 /* It's not condemned. Everything's fine. */
2812 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2813 window
->vertical_scroll_bar
))
2814 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2816 /* If its prev pointer is nil, it must be at the front of
2817 one or the other! */
2821 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2823 if (! NILP (bar
->next
))
2824 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2826 bar
->next
= FRAME_SCROLL_BARS (f
);
2828 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2829 if (! NILP (bar
->next
))
2830 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2834 /* Remove all scroll bars on FRAME that haven't been saved since the
2835 last call to `*condemn_scroll_bars_hook'. */
2837 XTjudge_scroll_bars (f
)
2840 Lisp_Object bar
, next
;
2842 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2844 /* Clear out the condemned list now so we won't try to process any
2845 more events on the hapless scroll bars. */
2846 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2848 for (; ! NILP (bar
); bar
= next
)
2850 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2852 x_scroll_bar_remove (b
);
2855 b
->next
= b
->prev
= Qnil
;
2858 /* Now there should be no references to the condemned scroll bars,
2859 and they should get garbage-collected. */
2863 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2865 This may be called from a signal handler, so we have to ignore GC
2868 x_scroll_bar_expose (bar
, event
)
2869 struct scroll_bar
*bar
;
2872 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2873 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2874 GC gc
= f
->output_data
.x
->normal_gc
;
2878 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2880 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2881 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2883 /* x, y, width, height */
2884 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2889 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2890 is set to something other than no_event, it is enqueued.
2892 This may be called from a signal handler, so we have to ignore GC
2895 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2896 struct scroll_bar
*bar
;
2898 struct input_event
*emacs_event
;
2900 if (! GC_WINDOWP (bar
->window
))
2903 emacs_event
->kind
= scroll_bar_click
;
2904 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2905 emacs_event
->modifiers
2906 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2907 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2908 event
->xbutton
.state
)
2909 | (event
->type
== ButtonRelease
2912 emacs_event
->frame_or_window
= bar
->window
;
2913 emacs_event
->timestamp
= event
->xbutton
.time
;
2916 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2918 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2919 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2922 if (y
> top_range
) y
= top_range
;
2924 if (y
< XINT (bar
->start
))
2925 emacs_event
->part
= scroll_bar_above_handle
;
2926 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2927 emacs_event
->part
= scroll_bar_handle
;
2929 emacs_event
->part
= scroll_bar_below_handle
;
2931 /* Just because the user has clicked on the handle doesn't mean
2932 they want to drag it. Lisp code needs to be able to decide
2933 whether or not we're dragging. */
2935 /* If the user has just clicked on the handle, record where they're
2937 if (event
->type
== ButtonPress
2938 && emacs_event
->part
== scroll_bar_handle
)
2939 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2942 /* If the user has released the handle, set it to its final position. */
2943 if (event
->type
== ButtonRelease
2944 && ! NILP (bar
->dragging
))
2946 int new_start
= y
- XINT (bar
->dragging
);
2947 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2949 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2950 bar
->dragging
= Qnil
;
2953 /* Same deal here as the other #if 0. */
2955 /* Clicks on the handle are always reported as occurring at the top of
2957 if (emacs_event
->part
== scroll_bar_handle
)
2958 emacs_event
->x
= bar
->start
;
2960 XSETINT (emacs_event
->x
, y
);
2962 XSETINT (emacs_event
->x
, y
);
2965 XSETINT (emacs_event
->y
, top_range
);
2969 /* Handle some mouse motion while someone is dragging the scroll bar.
2971 This may be called from a signal handler, so we have to ignore GC
2974 x_scroll_bar_note_movement (bar
, event
)
2975 struct scroll_bar
*bar
;
2978 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
2980 last_mouse_movement_time
= event
->xmotion
.time
;
2983 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2985 /* If we're dragging the bar, display it. */
2986 if (! GC_NILP (bar
->dragging
))
2988 /* Where should the handle be now? */
2989 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2991 if (new_start
!= XINT (bar
->start
))
2993 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2995 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2999 /* Call XQueryPointer so we'll get an event the next time the mouse
3000 moves and we can see *still* on the same position. */
3003 Window dummy_window
;
3005 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3006 &dummy_window
, &dummy_window
,
3007 &dummy
, &dummy
, &dummy
, &dummy
,
3008 (unsigned int *) &dummy
);
3012 /* Return information to the user about the current position of the mouse
3013 on the scroll bar. */
3015 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3017 Lisp_Object
*bar_window
;
3018 enum scroll_bar_part
*part
;
3020 unsigned long *time
;
3022 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3023 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3024 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3026 Window dummy_window
;
3028 unsigned int dummy_mask
;
3032 /* Get the mouse's position relative to the scroll bar window, and
3034 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3036 /* Root, child, root x and root y. */
3037 &dummy_window
, &dummy_window
,
3038 &dummy_coord
, &dummy_coord
,
3040 /* Position relative to scroll bar. */
3043 /* Mouse buttons and modifier keys. */
3049 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3051 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3053 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3055 if (! NILP (bar
->dragging
))
3056 win_y
-= XINT (bar
->dragging
);
3060 if (win_y
> top_range
)
3064 *bar_window
= bar
->window
;
3066 if (! NILP (bar
->dragging
))
3067 *part
= scroll_bar_handle
;
3068 else if (win_y
< XINT (bar
->start
))
3069 *part
= scroll_bar_above_handle
;
3070 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3071 *part
= scroll_bar_handle
;
3073 *part
= scroll_bar_below_handle
;
3075 XSETINT (*x
, win_y
);
3076 XSETINT (*y
, top_range
);
3079 last_mouse_scroll_bar
= Qnil
;
3082 *time
= last_mouse_movement_time
;
3088 /* The screen has been cleared so we may have changed foreground or
3089 background colors, and the scroll bars may need to be redrawn.
3090 Clear out the scroll bars, and ask for expose events, so we can
3093 x_scroll_bar_clear (f
)
3098 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3099 bar
= XSCROLL_BAR (bar
)->next
)
3100 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3104 /* This processes Expose events from the menubar specific X event
3105 loop in xmenu.c. This allows to redisplay the frame if necessary
3106 when handling menubar or popup items. */
3109 process_expose_from_menu (event
)
3113 struct x_display_info
*dpyinfo
;
3117 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3118 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3121 if (f
->async_visible
== 0)
3123 f
->async_visible
= 1;
3124 f
->async_iconified
= 0;
3125 SET_FRAME_GARBAGED (f
);
3129 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3130 event
.xexpose
.x
, event
.xexpose
.y
,
3131 event
.xexpose
.width
, event
.xexpose
.height
);
3136 struct scroll_bar
*bar
3137 = x_window_to_scroll_bar (event
.xexpose
.window
);
3140 x_scroll_bar_expose (bar
, &event
);
3146 /* Define a queue to save up SelectionRequest events for later handling. */
3148 struct selection_event_queue
3151 struct selection_event_queue
*next
;
3154 static struct selection_event_queue
*queue
;
3156 /* Nonzero means queue up certain events--don't process them yet. */
3157 static int x_queue_selection_requests
;
3159 /* Queue up an X event *EVENT, to be processed later. */
3162 x_queue_event (f
, event
)
3166 struct selection_event_queue
*queue_tmp
3167 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3169 if (queue_tmp
!= NULL
)
3171 queue_tmp
->event
= *event
;
3172 queue_tmp
->next
= queue
;
3177 /* Take all the queued events and put them back
3178 so that they get processed afresh. */
3181 x_unqueue_events (display
)
3184 while (queue
!= NULL
)
3186 struct selection_event_queue
*queue_tmp
= queue
;
3187 XPutBackEvent (display
, &queue_tmp
->event
);
3188 queue
= queue_tmp
->next
;
3189 free ((char *)queue_tmp
);
3193 /* Start queuing SelectionRequest events. */
3196 x_start_queuing_selection_requests (display
)
3199 x_queue_selection_requests
++;
3202 /* Stop queuing SelectionRequest events. */
3205 x_stop_queuing_selection_requests (display
)
3208 x_queue_selection_requests
--;
3209 x_unqueue_events (display
);
3212 /* The main X event-reading loop - XTread_socket. */
3214 /* Timestamp of enter window event. This is only used by XTread_socket,
3215 but we have to put it out here, since static variables within functions
3216 sometimes don't work. */
3217 static Time enter_timestamp
;
3219 /* This holds the state XLookupString needs to implement dead keys
3220 and other tricks known as "compose processing". _X Window System_
3221 says that a portable program can't use this, but Stephen Gildea assures
3222 me that letting the compiler initialize it to zeros will work okay.
3224 This must be defined outside of XTread_socket, for the same reasons
3225 given for enter_timestamp, above. */
3226 static XComposeStatus compose_status
;
3228 /* Record the last 100 characters stored
3229 to help debug the loss-of-chars-during-GC problem. */
3230 static int temp_index
;
3231 static short temp_buffer
[100];
3233 /* Set this to nonzero to fake an "X I/O error"
3234 on a particular display. */
3235 struct x_display_info
*XTread_socket_fake_io_error
;
3237 /* When we find no input here, we occasionally do a no-op command
3238 to verify that the X server is still running and we can still talk with it.
3239 We try all the open displays, one by one.
3240 This variable is used for cycling thru the displays. */
3241 static struct x_display_info
*next_noop_dpyinfo
;
3243 /* Read events coming from the X server.
3244 This routine is called by the SIGIO handler.
3245 We return as soon as there are no more events to be read.
3247 Events representing keys are stored in buffer BUFP,
3248 which can hold up to NUMCHARS characters.
3249 We return the number of characters stored into the buffer,
3250 thus pretending to be `read'.
3252 WAITP is nonzero if we should block until input arrives.
3253 EXPECTED is nonzero if the caller knows input is available. */
3256 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3258 register struct input_event
*bufp
;
3259 register int numchars
;
3266 int items_pending
; /* How many items are in the X queue. */
3269 int event_found
= 0;
3272 struct x_display_info
*dpyinfo
;
3274 Status status_return
;
3277 if (interrupt_input_blocked
)
3279 interrupt_input_pending
= 1;
3283 interrupt_input_pending
= 0;
3286 /* So people can tell when we have read the available input. */
3287 input_signal_count
++;
3290 abort (); /* Don't think this happens. */
3292 /* Find the display we are supposed to read input for.
3293 It's the one communicating on descriptor SD. */
3294 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3296 #if 0 /* This ought to be unnecessary; let's verify it. */
3298 /* If available, Xlib uses FIOSNBIO to make the socket
3299 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3300 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3301 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3302 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3303 #endif /* ! defined (FIOSNBIO) */
3306 #if 0 /* This code can't be made to work, with multiple displays,
3307 and appears not to be used on any system any more.
3308 Also keyboard.c doesn't turn O_NDELAY on and off
3309 for X connections. */
3312 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3314 extern int read_alarm_should_throw
;
3315 read_alarm_should_throw
= 1;
3316 XPeekEvent (dpyinfo
->display
, &event
);
3317 read_alarm_should_throw
= 0;
3319 #endif /* HAVE_SELECT */
3323 /* For debugging, this gives a way to fake an I/O error. */
3324 if (dpyinfo
== XTread_socket_fake_io_error
)
3326 XTread_socket_fake_io_error
= 0;
3327 x_io_error_quitter (dpyinfo
->display
);
3330 while (XPending (dpyinfo
->display
) != 0)
3332 XNextEvent (dpyinfo
->display
, &event
);
3339 if (event
.xclient
.message_type
3340 == dpyinfo
->Xatom_wm_protocols
3341 && event
.xclient
.format
== 32)
3343 if (event
.xclient
.data
.l
[0]
3344 == dpyinfo
->Xatom_wm_take_focus
)
3346 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3347 /* Since we set WM_TAKE_FOCUS, we must call
3348 XSetInputFocus explicitly. But not if f is null,
3349 since that might be an event for a deleted frame. */
3351 /* Not quite sure this is needed -pd */
3353 XSetICFocus (FRAME_XIC (f
));
3356 XSetInputFocus (event
.xclient
.display
,
3357 event
.xclient
.window
,
3358 RevertToPointerRoot
,
3359 event
.xclient
.data
.l
[1]);
3360 /* Not certain about handling scroll bars here */
3362 else if (event
.xclient
.data
.l
[0]
3363 == dpyinfo
->Xatom_wm_save_yourself
)
3365 /* Save state modify the WM_COMMAND property to
3366 something which can reinstate us. This notifies
3367 the session manager, who's looking for such a
3368 PropertyNotify. Can restart processing when
3369 a keyboard or mouse event arrives. */
3372 f
= x_top_window_to_frame (dpyinfo
,
3373 event
.xclient
.window
);
3375 /* This is just so we only give real data once
3376 for a single Emacs process. */
3377 if (f
== selected_frame
)
3378 XSetCommand (FRAME_X_DISPLAY (f
),
3379 event
.xclient
.window
,
3380 initial_argv
, initial_argc
);
3382 XSetCommand (FRAME_X_DISPLAY (f
),
3383 event
.xclient
.window
,
3387 else if (event
.xclient
.data
.l
[0]
3388 == dpyinfo
->Xatom_wm_delete_window
)
3391 = x_any_window_to_frame (dpyinfo
,
3392 event
.xclient
.window
);
3399 bufp
->kind
= delete_window_event
;
3400 XSETFRAME (bufp
->frame_or_window
, f
);
3408 else if (event
.xclient
.message_type
3409 == dpyinfo
->Xatom_wm_configure_denied
)
3412 else if (event
.xclient
.message_type
3413 == dpyinfo
->Xatom_wm_window_moved
)
3417 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3419 new_x
= event
.xclient
.data
.s
[0];
3420 new_y
= event
.xclient
.data
.s
[1];
3424 f
->output_data
.x
->left_pos
= new_x
;
3425 f
->output_data
.x
->top_pos
= new_y
;
3429 else if (event
.xclient
.message_type
3430 == dpyinfo
->Xatom_editres
)
3433 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3434 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3437 #endif /* HACK_EDITRES */
3441 case SelectionNotify
:
3442 #ifdef USE_X_TOOLKIT
3443 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3445 #endif /* not USE_X_TOOLKIT */
3446 x_handle_selection_notify (&event
);
3449 case SelectionClear
: /* Someone has grabbed ownership. */
3450 #ifdef USE_X_TOOLKIT
3451 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3453 #endif /* USE_X_TOOLKIT */
3455 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3460 bufp
->kind
= selection_clear_event
;
3461 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3462 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3463 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3464 bufp
->frame_or_window
= Qnil
;
3472 case SelectionRequest
: /* Someone wants our selection. */
3473 #ifdef USE_X_TOOLKIT
3474 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3476 #endif /* USE_X_TOOLKIT */
3477 if (x_queue_selection_requests
)
3478 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3482 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3487 bufp
->kind
= selection_request_event
;
3488 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3489 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3490 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3491 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3492 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3493 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3494 bufp
->frame_or_window
= Qnil
;
3502 case PropertyNotify
:
3503 #ifdef USE_X_TOOLKIT
3504 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3506 #endif /* not USE_X_TOOLKIT */
3507 x_handle_property_notify (&event
);
3510 case ReparentNotify
:
3511 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3515 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
3516 x_real_positions (f
, &x
, &y
);
3517 f
->output_data
.x
->left_pos
= x
;
3518 f
->output_data
.x
->top_pos
= y
;
3523 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3526 if (f
->async_visible
== 0)
3528 f
->async_visible
= 1;
3529 f
->async_iconified
= 0;
3530 SET_FRAME_GARBAGED (f
);
3533 dumprectangle (x_window_to_frame (dpyinfo
,
3534 event
.xexpose
.window
),
3535 event
.xexpose
.x
, event
.xexpose
.y
,
3536 event
.xexpose
.width
, event
.xexpose
.height
);
3540 struct scroll_bar
*bar
3541 = x_window_to_scroll_bar (event
.xexpose
.window
);
3544 x_scroll_bar_expose (bar
, &event
);
3545 #ifdef USE_X_TOOLKIT
3548 #endif /* USE_X_TOOLKIT */
3552 case GraphicsExpose
: /* This occurs when an XCopyArea's
3553 source area was obscured or not
3555 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3559 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3560 event
.xgraphicsexpose
.width
,
3561 event
.xgraphicsexpose
.height
);
3563 #ifdef USE_X_TOOLKIT
3566 #endif /* USE_X_TOOLKIT */
3569 case NoExpose
: /* This occurs when an XCopyArea's
3570 source area was completely
3575 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3576 if (f
) /* F may no longer exist if
3577 the frame was deleted. */
3579 /* While a frame is unmapped, display generation is
3580 disabled; you don't want to spend time updating a
3581 display that won't ever be seen. */
3582 f
->async_visible
= 0;
3583 /* We can't distinguish, from the event, whether the window
3584 has become iconified or invisible. So assume, if it
3585 was previously visible, than now it is iconified.
3586 We depend on x_make_frame_invisible to mark it iconified. */
3587 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3588 f
->async_iconified
= 1;
3590 bufp
->kind
= iconify_event
;
3591 XSETFRAME (bufp
->frame_or_window
, f
);
3599 /* We use x_top_window_to_frame because map events can come
3600 for subwindows and they don't mean that the frame is visible. */
3601 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
3604 f
->async_visible
= 1;
3605 f
->async_iconified
= 0;
3607 /* wait_reading_process_input will notice this and update
3608 the frame's display structures. */
3609 SET_FRAME_GARBAGED (f
);
3613 bufp
->kind
= deiconify_event
;
3614 XSETFRAME (bufp
->frame_or_window
, f
);
3620 /* Force a redisplay sooner or later
3621 to update the frame titles
3622 in case this is the second frame. */
3623 record_asynch_buffer_change ();
3627 /* Turn off processing if we become fully obscured. */
3628 case VisibilityNotify
:
3632 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
3636 KeySym keysym
, orig_keysym
;
3637 /* al%imercury@uunet.uu.net says that making this 81 instead of
3638 80 fixed a bug whereby meta chars made his Emacs hang. */
3639 unsigned char copy_buffer
[81];
3643 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3644 extra_keyboard_modifiers
);
3645 modifiers
= event
.xkey
.state
;
3647 /* This will have to go some day... */
3649 /* make_lispy_event turns chars into control chars.
3650 Don't do it here because XLookupString is too eager. */
3651 event
.xkey
.state
&= ~ControlMask
;
3652 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
3653 | dpyinfo
->super_mod_mask
3654 | dpyinfo
->hyper_mod_mask
3655 | dpyinfo
->alt_mod_mask
);
3660 /* The necessity of the following line took me
3661 a full work-day to decipher from the docs!! */
3662 if (XFilterEvent (&event
, None
))
3664 nbytes
= XmbLookupString (FRAME_XIC (f
),
3665 &event
.xkey
, copy_buffer
,
3670 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3671 80, &keysym
, &compose_status
);
3673 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3674 80, &keysym
, &compose_status
);
3677 orig_keysym
= keysym
;
3681 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3682 || keysym
== XK_Delete
3683 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3684 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3686 /* This recognizes the "extended function keys".
3687 It seems there's no cleaner way.
3688 Test IsModifierKey to avoid handling mode_switch
3690 || ((unsigned) (keysym
) >= XK_Select
3691 && (unsigned)(keysym
) < XK_KP_Space
)
3693 #ifdef XK_dead_circumflex
3694 || orig_keysym
== XK_dead_circumflex
3696 #ifdef XK_dead_grave
3697 || orig_keysym
== XK_dead_grave
3699 #ifdef XK_dead_tilde
3700 || orig_keysym
== XK_dead_tilde
3702 #ifdef XK_dead_diaeresis
3703 || orig_keysym
== XK_dead_diaeresis
3705 #ifdef XK_dead_macron
3706 || orig_keysym
== XK_dead_macron
3708 #ifdef XK_dead_degree
3709 || orig_keysym
== XK_dead_degree
3711 #ifdef XK_dead_acute
3712 || orig_keysym
== XK_dead_acute
3714 #ifdef XK_dead_cedilla
3715 || orig_keysym
== XK_dead_cedilla
3717 #ifdef XK_dead_breve
3718 || orig_keysym
== XK_dead_breve
3720 #ifdef XK_dead_ogonek
3721 || orig_keysym
== XK_dead_ogonek
3723 #ifdef XK_dead_caron
3724 || orig_keysym
== XK_dead_caron
3726 #ifdef XK_dead_doubleacute
3727 || orig_keysym
== XK_dead_doubleacute
3729 #ifdef XK_dead_abovedot
3730 || orig_keysym
== XK_dead_abovedot
3732 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3733 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3734 /* Any "vendor-specific" key is ok. */
3735 || (orig_keysym
& (1 << 28)))
3736 && ! (IsModifierKey (orig_keysym
)
3738 #ifdef XK_Mode_switch
3739 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3742 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3744 #endif /* not HAVE_X11R5 */
3747 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3749 temp_buffer
[temp_index
++] = keysym
;
3750 bufp
->kind
= non_ascii_keystroke
;
3751 bufp
->code
= keysym
;
3752 XSETFRAME (bufp
->frame_or_window
, f
);
3754 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3756 bufp
->timestamp
= event
.xkey
.time
;
3761 else if (numchars
> nbytes
)
3765 for (i
= 0; i
< nbytes
; i
++)
3767 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3769 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3770 bufp
->kind
= ascii_keystroke
;
3771 bufp
->code
= copy_buffer
[i
];
3772 XSETFRAME (bufp
->frame_or_window
, f
);
3774 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3776 bufp
->timestamp
= event
.xkey
.time
;
3791 /* Here's a possible interpretation of the whole
3792 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3793 FocusIn event, you have to get a FocusOut event before you
3794 relinquish the focus. If you haven't received a FocusIn event,
3795 then a mere LeaveNotify is enough to free you. */
3798 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3800 if (event
.xcrossing
.focus
) /* Entered Window */
3802 /* Avoid nasty pop/raise loops. */
3803 if (f
&& (!(f
->auto_raise
)
3805 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3807 x_new_focus_frame (dpyinfo
, f
);
3808 enter_timestamp
= event
.xcrossing
.time
;
3811 else if (f
== dpyinfo
->x_focus_frame
)
3812 x_new_focus_frame (dpyinfo
, 0);
3813 /* EnterNotify counts as mouse movement,
3814 so update things that depend on mouse position. */
3816 note_mouse_movement (f
, &event
.xmotion
);
3820 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3821 if (event
.xfocus
.detail
!= NotifyPointer
)
3822 dpyinfo
->x_focus_event_frame
= f
;
3824 x_new_focus_frame (dpyinfo
, f
);
3827 if (f
&& FRAME_XIC (f
))
3828 XSetICFocus (FRAME_XIC (f
));
3834 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3837 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3838 /* If we move outside the frame,
3839 then we're certainly no longer on any text in the frame. */
3840 clear_mouse_face (dpyinfo
);
3842 if (event
.xcrossing
.focus
)
3843 x_mouse_leave (dpyinfo
);
3846 if (f
== dpyinfo
->x_focus_event_frame
)
3847 dpyinfo
->x_focus_event_frame
= 0;
3848 if (f
== dpyinfo
->x_focus_frame
)
3849 x_new_focus_frame (dpyinfo
, 0);
3855 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3856 if (event
.xfocus
.detail
!= NotifyPointer
3857 && f
== dpyinfo
->x_focus_event_frame
)
3858 dpyinfo
->x_focus_event_frame
= 0;
3859 if (f
&& f
== dpyinfo
->x_focus_frame
)
3860 x_new_focus_frame (dpyinfo
, 0);
3863 if (f
&& FRAME_XIC (f
))
3864 XUnsetICFocus (FRAME_XIC (f
));
3871 if (dpyinfo
->grabbed
&& last_mouse_frame
3872 && FRAME_LIVE_P (last_mouse_frame
))
3873 f
= last_mouse_frame
;
3875 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3877 note_mouse_movement (f
, &event
.xmotion
);
3880 struct scroll_bar
*bar
3881 = x_window_to_scroll_bar (event
.xmotion
.window
);
3884 x_scroll_bar_note_movement (bar
, &event
);
3886 /* If we move outside the frame,
3887 then we're certainly no longer on any text in the frame. */
3888 clear_mouse_face (dpyinfo
);
3893 case ConfigureNotify
:
3894 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
3896 #ifdef USE_X_TOOLKIT
3897 && (event
.xconfigure
.window
== XtWindow (f
->output_data
.x
->widget
))
3901 #ifndef USE_X_TOOLKIT
3902 /* In the toolkit version, change_frame_size
3903 is called by the code that handles resizing
3904 of the EmacsFrame widget. */
3906 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3907 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3909 /* Even if the number of character rows and columns has
3910 not changed, the font size may have changed, so we need
3911 to check the pixel dimensions as well. */
3912 if (columns
!= f
->width
3913 || rows
!= f
->height
3914 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
3915 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
3917 change_frame_size (f
, rows
, columns
, 0, 1);
3918 SET_FRAME_GARBAGED (f
);
3922 /* Formerly, in the USE_X_TOOLKIT version,
3923 we did not test send_event here. */
3925 #ifndef USE_X_TOOLKIT
3926 && ! event
.xconfigure
.send_event
3933 /* Find the position of the outside upper-left corner of
3934 the window, in the root coordinate system. Don't
3935 refer to the parent window here; we may be processing
3936 this event after the window manager has changed our
3937 parent, but before we have reached the ReparentNotify. */
3938 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3940 /* From-window, to-window. */
3941 event
.xconfigure
.window
,
3942 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3944 /* From-position, to-position. */
3945 -event
.xconfigure
.border_width
,
3946 -event
.xconfigure
.border_width
,
3951 event
.xconfigure
.x
= win_x
;
3952 event
.xconfigure
.y
= win_y
;
3955 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
3956 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
3957 f
->output_data
.x
->left_pos
= event
.xconfigure
.x
;
3958 f
->output_data
.x
->top_pos
= event
.xconfigure
.y
;
3960 /* What we have now is the position of Emacs's own window.
3961 Convert that to the position of the window manager window. */
3964 x_real_positions (f
, &x
, &y
);
3965 f
->output_data
.x
->left_pos
= x
;
3966 f
->output_data
.x
->top_pos
= y
;
3967 /* Formerly we did not do this in the USE_X_TOOLKIT
3968 version. Let's try making them the same. */
3969 /* #ifndef USE_X_TOOLKIT */
3970 if (y
!= event
.xconfigure
.y
)
3972 /* Since the WM decorations come below top_pos now,
3973 we must put them below top_pos in the future. */
3974 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3975 x_wm_set_size_hint (f
, (long) 0, 0);
3985 /* If we decide we want to generate an event to be seen
3986 by the rest of Emacs, we put it here. */
3987 struct input_event emacs_event
;
3988 emacs_event
.kind
= no_event
;
3990 bzero (&compose_status
, sizeof (compose_status
));
3992 if (dpyinfo
->grabbed
&& last_mouse_frame
3993 && FRAME_LIVE_P (last_mouse_frame
))
3994 f
= last_mouse_frame
;
3996 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4000 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4001 construct_mouse_click (&emacs_event
, &event
, f
);
4005 struct scroll_bar
*bar
4006 = x_window_to_scroll_bar (event
.xbutton
.window
);
4009 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4012 if (event
.type
== ButtonPress
)
4014 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4015 last_mouse_frame
= f
;
4019 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4022 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4024 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4030 #ifdef USE_X_TOOLKIT
4031 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4032 /* For a down-event in the menu bar,
4033 don't pass it to Xt right now.
4034 Instead, save it away
4035 and we will pass it to Xt from kbd_buffer_get_event.
4036 That way, we can run some Lisp code first. */
4037 if (f
&& event
.type
== ButtonPress
4038 /* Verify the event is really within the menu bar
4039 and not just sent to it due to grabbing. */
4040 && event
.xbutton
.x
>= 0
4041 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4042 && event
.xbutton
.y
>= 0
4043 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4044 && event
.xbutton
.same_screen
)
4046 if (f
->output_data
.x
->saved_button_event
== 0)
4047 f
->output_data
.x
->saved_button_event
4048 = (XButtonEvent
*) xmalloc (sizeof (XButtonEvent
));
4049 bcopy (&event
, f
->output_data
.x
->saved_button_event
,
4050 sizeof (XButtonEvent
));
4053 bufp
->kind
= menu_bar_activate_event
;
4054 XSETFRAME (bufp
->frame_or_window
, f
);
4062 #endif /* USE_X_TOOLKIT */
4066 case CirculateNotify
:
4068 case CirculateRequest
:
4072 /* Someone has changed the keyboard mapping - update the
4074 switch (event
.xmapping
.request
)
4076 case MappingModifier
:
4077 x_find_modifier_meanings (dpyinfo
);
4078 /* This is meant to fall through. */
4079 case MappingKeyboard
:
4080 XRefreshKeyboardMapping (&event
.xmapping
);
4086 #ifdef USE_X_TOOLKIT
4088 XtDispatchEvent (&event
);
4090 #endif /* USE_X_TOOLKIT */
4096 /* On some systems, an X bug causes Emacs to get no more events
4097 when the window is destroyed. Detect that. (1994.) */
4100 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4101 One XNOOP in 100 loops will make Emacs terminate.
4102 B. Bretthauer, 1994 */
4104 if (x_noop_count
>= 100)
4108 if (next_noop_dpyinfo
== 0)
4109 next_noop_dpyinfo
= x_display_list
;
4111 XNoOp (next_noop_dpyinfo
->display
);
4113 /* Each time we get here, cycle through the displays now open. */
4114 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4118 /* If the focus was just given to an autoraising frame,
4120 /* ??? This ought to be able to handle more than one such frame. */
4121 if (pending_autoraise_frame
)
4123 x_raise_frame (pending_autoraise_frame
);
4124 pending_autoraise_frame
= 0;
4131 /* Drawing the cursor. */
4134 /* Draw a hollow box cursor on frame F at X, Y.
4135 Don't change the inside of the box. */
4138 x_draw_box (f
, x
, y
)
4142 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4143 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4144 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4145 int height
= f
->output_data
.x
->line_height
;
4147 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4148 f
->output_data
.x
->cursor_gc
,
4149 left
, top
, width
- 1, height
- 1);
4152 /* Clear the cursor of frame F to background color,
4153 and mark the cursor as not shown.
4154 This is used when the text where the cursor is
4155 is about to be rewritten. */
4163 if (! FRAME_VISIBLE_P (f
)
4164 || f
->phys_cursor_x
< 0)
4167 x_display_cursor (f
, 0);
4168 f
->phys_cursor_x
= -1;
4171 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4172 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4176 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4183 CHAR_TO_PIXEL_COL (f
, column
),
4184 CHAR_TO_PIXEL_ROW (f
, row
),
4185 &glyph
, 1, highlight
, 0);
4189 x_display_bar_cursor (f
, on
, x
, y
)
4194 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4196 /* This is pointless on invisible frames, and dangerous on garbaged
4197 frames; in the latter case, the frame may be in the midst of
4198 changing its size, and x and y may be off the frame. */
4199 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4202 if (! on
&& f
->phys_cursor_x
< 0)
4205 /* If there is anything wrong with the current cursor state, remove it. */
4206 if (f
->phys_cursor_x
>= 0
4208 || f
->phys_cursor_x
!= x
4209 || f
->phys_cursor_y
!= y
4210 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4212 /* Erase the cursor by redrawing the character underneath it. */
4213 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4214 f
->phys_cursor_glyph
,
4215 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4216 f
->phys_cursor_x
= -1;
4219 /* If we now need a cursor in the new place or in the new form, do it so. */
4221 && (f
->phys_cursor_x
< 0
4222 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4224 f
->phys_cursor_glyph
4225 = ((current_glyphs
->enable
[y
]
4226 && x
< current_glyphs
->used
[y
])
4227 ? current_glyphs
->glyphs
[y
][x
]
4229 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4230 f
->output_data
.x
->cursor_gc
,
4231 CHAR_TO_PIXEL_COL (f
, x
),
4232 CHAR_TO_PIXEL_ROW (f
, y
),
4233 max (f
->output_data
.x
->cursor_width
, 1),
4234 f
->output_data
.x
->line_height
);
4236 f
->phys_cursor_x
= x
;
4237 f
->phys_cursor_y
= y
;
4239 f
->output_data
.x
->current_cursor
= bar_cursor
;
4242 if (updating_frame
!= f
)
4243 XFlush (FRAME_X_DISPLAY (f
));
4247 /* Turn the displayed cursor of frame F on or off according to ON.
4248 If ON is nonzero, where to put the cursor is specified by X and Y. */
4251 x_display_box_cursor (f
, on
, x
, y
)
4256 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4258 /* This is pointless on invisible frames, and dangerous on garbaged
4259 frames; in the latter case, the frame may be in the midst of
4260 changing its size, and x and y may be off the frame. */
4261 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4264 /* If cursor is off and we want it off, return quickly. */
4265 if (!on
&& f
->phys_cursor_x
< 0)
4268 /* If cursor is currently being shown and we don't want it to be
4269 or it is in the wrong place,
4270 or we want a hollow box and it's not so, (pout!)
4272 if (f
->phys_cursor_x
>= 0
4274 || f
->phys_cursor_x
!= x
4275 || f
->phys_cursor_y
!= y
4276 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4277 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4279 int mouse_face_here
= 0;
4280 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4282 /* If the cursor is in the mouse face area, redisplay that when
4283 we clear the cursor. */
4284 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4286 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4287 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4288 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4290 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4291 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4292 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4293 /* Don't redraw the cursor's spot in mouse face
4294 if it is at the end of a line (on a newline).
4295 The cursor appears there, but mouse highlighting does not. */
4296 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4297 mouse_face_here
= 1;
4299 /* If the font is not as tall as a whole line,
4300 we must explicitly clear the line's whole height. */
4301 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4302 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4303 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4304 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4305 FONT_WIDTH (f
->output_data
.x
->font
),
4306 f
->output_data
.x
->line_height
, False
);
4307 /* Erase the cursor by redrawing the character underneath it. */
4308 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4309 f
->phys_cursor_glyph
,
4312 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4313 f
->phys_cursor_x
= -1;
4316 /* If we want to show a cursor,
4317 or we want a box cursor and it's not so,
4318 write it in the right place. */
4320 && (f
->phys_cursor_x
< 0
4321 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4322 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4324 f
->phys_cursor_glyph
4325 = ((current_glyphs
->enable
[y
]
4326 && x
< current_glyphs
->used
[y
])
4327 ? current_glyphs
->glyphs
[y
][x
]
4329 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4331 x_draw_box (f
, x
, y
);
4332 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4336 x_draw_single_glyph (f
, y
, x
,
4337 f
->phys_cursor_glyph
, 2);
4338 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4341 f
->phys_cursor_x
= x
;
4342 f
->phys_cursor_y
= y
;
4345 if (updating_frame
!= f
)
4346 XFlush (FRAME_X_DISPLAY (f
));
4349 /* Display the cursor on frame F, or clear it, according to ON.
4350 Use the position specified by curs_x and curs_y
4351 if we are doing an update of frame F now.
4352 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4355 x_display_cursor (f
, on
)
4361 /* If we're not updating, then don't change the physical cursor
4362 position. Just change (if appropriate) the style of display. */
4363 if (f
!= updating_frame
)
4365 curs_x
= FRAME_CURSOR_X (f
);
4366 curs_y
= FRAME_CURSOR_Y (f
);
4369 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4370 x_display_box_cursor (f
, on
, curs_x
, curs_y
);
4371 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4372 x_display_bar_cursor (f
, on
, curs_x
, curs_y
);
4374 /* Those are the only two we have implemented! */
4380 /* Display the cursor on frame F, or clear it, according to ON.
4381 Don't change the cursor's position. */
4383 x_update_cursor (f
, on
)
4389 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4390 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4391 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4392 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4394 /* Those are the only two we have implemented! */
4402 /* Refresh bitmap kitchen sink icon for frame F
4403 when we get an expose event for it. */
4408 /* Normally, the window manager handles this function. */
4411 /* Make the x-window of frame F use the gnu icon bitmap. */
4414 x_bitmap_icon (f
, file
)
4418 int mask
, bitmap_id
;
4421 if (FRAME_X_WINDOW (f
) == 0)
4424 /* Free up our existing icon bitmap if any. */
4425 if (f
->output_data
.x
->icon_bitmap
> 0)
4426 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4427 f
->output_data
.x
->icon_bitmap
= 0;
4430 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4433 /* Create the GNU bitmap if necessary. */
4434 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4435 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4436 = x_create_bitmap_from_data (f
, gnu_bits
,
4437 gnu_width
, gnu_height
);
4439 /* The first time we create the GNU bitmap,
4440 this increments the refcount one extra time.
4441 As a result, the GNU bitmap is never freed.
4442 That way, we don't have to worry about allocating it again. */
4443 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4445 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4448 x_wm_set_icon_pixmap (f
, bitmap_id
);
4449 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4455 /* Make the x-window of frame F use a rectangle with text.
4456 Use ICON_NAME as the text. */
4459 x_text_icon (f
, icon_name
)
4463 if (FRAME_X_WINDOW (f
) == 0)
4469 text
.value
= (unsigned char *) icon_name
;
4470 text
.encoding
= XA_STRING
;
4472 text
.nitems
= strlen (icon_name
);
4473 #ifdef USE_X_TOOLKIT
4474 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4476 #else /* not USE_X_TOOLKIT */
4477 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
4478 #endif /* not USE_X_TOOLKIT */
4480 #else /* not HAVE_X11R4 */
4481 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
4482 #endif /* not HAVE_X11R4 */
4484 if (f
->output_data
.x
->icon_bitmap
> 0)
4485 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4486 f
->output_data
.x
->icon_bitmap
= 0;
4487 x_wm_set_icon_pixmap (f
, 0);
4492 /* Handling X errors. */
4494 /* Handle the loss of connection to display DISPLAY. */
4497 x_connection_closed (display
, error_message
)
4499 char *error_message
;
4501 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4502 Lisp_Object frame
, tail
;
4504 /* Whatever we were in the middle of, we are going to throw out of it,
4505 so reassure various things that have error checks about being
4506 called with input blocked. */
4507 TOTALLY_UNBLOCK_INPUT
;
4512 /* First delete frames whose minibuffers are on frames
4513 that are on the dead display. */
4514 FOR_EACH_FRAME (tail
, frame
)
4516 Lisp_Object minibuf_frame
;
4518 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4519 if (FRAME_X_P (XFRAME (frame
))
4520 && FRAME_X_P (XFRAME (minibuf_frame
))
4521 && ! EQ (frame
, minibuf_frame
)
4522 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4523 Fdelete_frame (frame
, Qt
);
4526 /* Now delete all remaining frames on the dead display.
4527 We are now sure none of these is used as the minibuffer
4528 for another frame that we need to delete. */
4529 FOR_EACH_FRAME (tail
, frame
)
4530 if (FRAME_X_P (XFRAME (frame
))
4531 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4533 /* Set this to t so that Fdelete_frame won't get confused
4534 trying to find a replacement. */
4535 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
4536 Fdelete_frame (frame
, Qt
);
4540 x_delete_display (dpyinfo
);
4542 if (x_display_list
== 0)
4544 fprintf (stderr
, "%s", error_message
);
4545 shut_down_emacs (0, 0, Qnil
);
4549 /* Ordinary stack unwind doesn't deal with these. */
4551 sigunblock (sigmask (SIGIO
));
4553 sigunblock (sigmask (SIGALRM
));
4554 TOTALLY_UNBLOCK_INPUT
;
4556 error ("%s", error_message
);
4559 /* This is the usual handler for X protocol errors.
4560 It kills all frames on the display that we got the error for.
4561 If that was the only one, it prints an error message and kills Emacs. */
4564 x_error_quitter (display
, error
)
4568 char buf
[256], buf1
[356];
4570 /* Note that there is no real way portable across R3/R4 to get the
4571 original error handler. */
4573 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4574 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4575 buf
, error
->request_code
);
4576 x_connection_closed (display
, buf1
);
4579 /* This is the handler for X IO errors, always.
4580 It kills all frames on the display that we lost touch with.
4581 If that was the only one, it prints an error message and kills Emacs. */
4584 x_io_error_quitter (display
)
4589 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4590 x_connection_closed (display
, buf
);
4593 /* Handle SIGPIPE, which can happen when the connection to a server
4594 simply goes away. SIGPIPE is handled by x_connection_signal.
4595 It works by sending a no-op command to each X server connection.
4596 When we try a connection that has closed, we get SIGPIPE again.
4597 But this time, it is handled by x_connection_signal_1.
4598 That function knows which connection we were testing,
4599 so it closes that one.
4601 x_connection_closed never returns,
4602 so if more than one connection was lost at once,
4603 we only find one. But XTread_socket keeps trying them all,
4604 so it will notice the other closed one sooner or later. */
4607 static struct x_display_info
*x_connection_signal_dpyinfo
;
4609 static SIGTYPE
x_connection_signal ();
4612 x_connection_signal_1 (signalnum
) /* If we don't have an argument, */
4613 int signalnum
; /* some compilers complain in signal calls. */
4615 signal (SIGPIPE
, x_connection_signal
);
4616 x_connection_closed (x_connection_signal_dpyinfo
,
4617 "connection was lost");
4621 x_connection_signal (signalnum
) /* If we don't have an argument, */
4622 int signalnum
; /* some compilers complain in signal calls. */
4624 x_connection_signal_dpyinfo
= x_display_list
;
4627 sigunblock (SIGPIPE
);
4629 while (x_connection_signal_dpyinfo
)
4631 signal (SIGPIPE
, x_connection_signal_1
);
4632 signal (SIGALRM
, x_connection_signal_1
);
4634 /* According to Jim Campbell <jec@murzim.ca.boeing.com>,
4635 On Solaris 2.4, XNoOp can hang when the connection
4636 has already died. Since XNoOp should not wait,
4637 let's assume that if it hangs for 3 seconds
4638 that means the connection is dead.
4639 This is a kludge, but I don't see any other way that works. */
4641 XNoOp (x_connection_signal_dpyinfo
->display
);
4644 XSync (x_connection_signal_dpyinfo
->display
, False
);
4646 /* Each time we get here, cycle through the displays now open. */
4647 x_connection_signal_dpyinfo
= x_connection_signal_dpyinfo
->next
;
4650 /* We should have found some closed connection. */
4654 /* A buffer for storing X error messages. */
4655 static char *x_caught_error_message
;
4656 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4658 /* An X error handler which stores the error message in
4659 x_caught_error_message. This is what's installed when
4660 x_catch_errors is in effect. */
4663 x_error_catcher (display
, error
)
4667 XGetErrorText (display
, error
->error_code
,
4668 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4672 /* Begin trapping X errors for display DPY. Actually we trap X errors
4673 for all displays, but DPY should be the display you are actually
4676 After calling this function, X protocol errors no longer cause
4677 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4679 Calling x_check_errors signals an Emacs error if an X error has
4680 occurred since the last call to x_catch_errors or x_check_errors.
4682 Calling x_uncatch_errors resumes the normal error handling. */
4684 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4687 x_catch_errors (dpy
)
4690 /* Make sure any errors from previous requests have been dealt with. */
4693 /* Set up the error buffer. */
4694 x_caught_error_message
4695 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4696 x_caught_error_message
[0] = '\0';
4698 /* Install our little error handler. */
4699 XSetErrorHandler (x_error_catcher
);
4702 /* If any X protocol errors have arrived since the last call to
4703 x_catch_errors or x_check_errors, signal an Emacs error using
4704 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4707 x_check_errors (dpy
, format
)
4711 /* Make sure to catch any errors incurred so far. */
4714 if (x_caught_error_message
[0])
4716 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4718 sprintf (buf
, format
, x_caught_error_message
);
4719 x_uncatch_errors (dpy
);
4724 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4727 x_had_errors_p (dpy
)
4730 /* Make sure to catch any errors incurred so far. */
4733 return x_caught_error_message
[0] != 0;
4736 /* Stop catching X protocol errors and let them make Emacs die. */
4739 x_uncatch_errors (dpy
)
4742 xfree (x_caught_error_message
);
4743 x_caught_error_message
= 0;
4744 XSetErrorHandler (x_error_quitter
);
4748 static unsigned int x_wire_count
;
4751 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4756 /* Changing the font of the frame. */
4758 /* Give frame F the font named FONTNAME as its default font, and
4759 return the full name of that font. FONTNAME may be a wildcard
4760 pattern; in that case, we choose some font that fits the pattern.
4761 The return value shows which font we chose. */
4764 x_new_font (f
, fontname
)
4766 register char *fontname
;
4769 int n_matching_fonts
;
4770 XFontStruct
*font_info
;
4773 /* Get a list of all the fonts that match this name. Once we
4774 have a list of matching fonts, we compare them against the fonts
4775 we already have by comparing font ids. */
4776 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4777 1024, &n_matching_fonts
);
4778 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4779 find any matches; font_names == 0 is the only clue. */
4781 n_matching_fonts
= 0;
4783 /* Don't just give up if n_matching_fonts is 0.
4784 Apparently there's a bug on Suns: XListFontsWithInfo can
4785 fail to find a font, but XLoadQueryFont may still find it. */
4787 /* See if we've already loaded a matching font. */
4788 already_loaded
= -1;
4789 if (n_matching_fonts
!= 0)
4793 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4794 for (j
= 0; j
< n_matching_fonts
; j
++)
4795 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4796 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4799 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4805 /* If we have, just return it from the table. */
4806 if (already_loaded
>= 0)
4807 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4808 /* Otherwise, load the font and add it to the table. */
4816 /* Try to find a character-cell font in the list. */
4818 /* A laudable goal, but this isn't how to do it. */
4819 for (i
= 0; i
< n_matching_fonts
; i
++)
4820 if (! font_info
[i
].per_char
)
4826 /* See comment above. */
4827 if (n_matching_fonts
!= 0)
4828 fontname
= font_names
[i
];
4830 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4833 /* Free the information from XListFonts. */
4834 if (n_matching_fonts
)
4835 XFreeFontNames (font_names
);
4839 /* Do we need to create the table? */
4840 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4842 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4843 FRAME_X_DISPLAY_INFO (f
)->font_table
4844 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4845 * sizeof (struct font_info
));
4847 /* Do we need to grow the table? */
4848 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4849 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4851 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4852 FRAME_X_DISPLAY_INFO (f
)->font_table
4853 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4854 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4855 * sizeof (struct font_info
)));
4858 /* Try to get the full name of FONT. Put it in full_name. */
4860 for (i
= 0; i
< font
->n_properties
; i
++)
4863 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4864 if (!strcmp (atom
, "FONT"))
4866 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4867 (Atom
) (font
->properties
[i
].card32
));
4871 /* Count the number of dashes in the "full name".
4872 If it is too few, this isn't really the font's full name,
4874 In X11R4, the fonts did not come with their canonical names
4892 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4893 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4894 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4896 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4898 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4899 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4900 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4903 fontname
= full_name
;
4906 /* Compute the scroll bar width in character columns. */
4907 if (f
->scroll_bar_pixel_width
> 0)
4909 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
4910 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4913 f
->scroll_bar_cols
= 2;
4915 /* Now make the frame display the given font. */
4916 if (FRAME_X_WINDOW (f
) != 0)
4918 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
4919 f
->output_data
.x
->font
->fid
);
4920 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
4921 f
->output_data
.x
->font
->fid
);
4922 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
4923 f
->output_data
.x
->font
->fid
);
4925 frame_update_line_height (f
);
4926 x_set_window_size (f
, 0, f
->width
, f
->height
);
4929 /* If we are setting a new frame's font for the first time,
4930 there are no faces yet, so this font's height is the line height. */
4931 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
4934 Lisp_Object lispy_name
;
4936 lispy_name
= build_string (fontname
);
4938 /* Free the information from XListFonts. The data
4939 we actually retain comes from XLoadQueryFont. */
4940 XFreeFontNames (font_names
);
4946 x_calc_absolute_position (f
)
4950 int win_x
= 0, win_y
= 0;
4951 int flags
= f
->output_data
.x
->size_hint_flags
;
4954 #ifdef USE_X_TOOLKIT
4955 this_window
= XtWindow (f
->output_data
.x
->widget
);
4957 this_window
= FRAME_X_WINDOW (f
);
4960 /* Find the position of the outside upper-left corner of
4961 the inner window, with respect to the outer window. */
4962 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4965 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4967 /* From-window, to-window. */
4969 f
->output_data
.x
->parent_desc
,
4971 /* From-position, to-position. */
4972 0, 0, &win_x
, &win_y
,
4979 /* Treat negative positions as relative to the leftmost bottommost
4980 position that fits on the screen. */
4981 if (flags
& XNegative
)
4982 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4983 - 2 * f
->output_data
.x
->border_width
- win_x
4985 + f
->output_data
.x
->left_pos
);
4987 if (flags
& YNegative
)
4988 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
4989 - 2 * f
->output_data
.x
->border_width
- win_y
4991 - (FRAME_EXTERNAL_MENU_BAR (f
)
4992 ? f
->output_data
.x
->menubar_height
: 0)
4993 + f
->output_data
.x
->top_pos
);
4994 /* The left_pos and top_pos
4995 are now relative to the top and left screen edges,
4996 so the flags should correspond. */
4997 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5000 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5001 to really change the position, and 0 when calling from
5002 x_make_frame_visible (in that case, XOFF and YOFF are the current
5003 position values). It is -1 when calling from x_set_frame_parameters,
5004 which means, do adjust for borders but don't change the gravity. */
5006 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5008 register int xoff
, yoff
;
5011 int modified_top
, modified_left
;
5013 if (change_gravity
> 0)
5015 f
->output_data
.x
->top_pos
= yoff
;
5016 f
->output_data
.x
->left_pos
= xoff
;
5017 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5019 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5021 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5022 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5024 x_calc_absolute_position (f
);
5027 x_wm_set_size_hint (f
, (long) 0, 0);
5029 /* It is a mystery why we need to add the border_width here
5030 when the frame is already visible, but experiment says we do. */
5031 modified_left
= f
->output_data
.x
->left_pos
;
5032 modified_top
= f
->output_data
.x
->top_pos
;
5033 if (change_gravity
!= 0)
5035 modified_left
+= f
->output_data
.x
->border_width
;
5036 modified_top
+= f
->output_data
.x
->border_width
;
5039 #ifdef USE_X_TOOLKIT
5040 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5041 modified_left
, modified_top
);
5042 #else /* not USE_X_TOOLKIT */
5043 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5044 modified_left
, modified_top
);
5045 #endif /* not USE_X_TOOLKIT */
5049 /* Call this to change the size of frame F's x-window.
5050 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5051 for this size change and subsequent size changes.
5052 Otherwise we leave the window gravity unchanged. */
5054 x_set_window_size (f
, change_gravity
, cols
, rows
)
5059 int pixelwidth
, pixelheight
;
5062 #ifdef USE_X_TOOLKIT
5065 /* The x and y position of the widget is clobbered by the
5066 call to XtSetValues within EmacsFrameSetCharSize.
5067 This is a real kludge, but I don't understand Xt so I can't
5068 figure out a correct fix. Can anyone else tell me? -- rms. */
5069 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5070 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5071 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5072 f
->output_data
.x
->widget
->core
.x
= xpos
;
5073 f
->output_data
.x
->widget
->core
.y
= ypos
;
5077 #else /* not USE_X_TOOLKIT */
5081 check_frame_size (f
, &rows
, &cols
);
5082 f
->output_data
.x
->vertical_scroll_bar_extra
5083 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5085 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5086 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5087 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5088 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5089 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5091 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5092 x_wm_set_size_hint (f
, (long) 0, 0);
5094 XSync (FRAME_X_DISPLAY (f
), False
);
5095 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5096 pixelwidth
, pixelheight
);
5098 /* Now, strictly speaking, we can't be sure that this is accurate,
5099 but the window manager will get around to dealing with the size
5100 change request eventually, and we'll hear how it went when the
5101 ConfigureNotify event gets here.
5103 We could just not bother storing any of this information here,
5104 and let the ConfigureNotify event set everything up, but that
5105 might be kind of confusing to the lisp code, since size changes
5106 wouldn't be reported in the frame parameters until some random
5107 point in the future when the ConfigureNotify event arrives. */
5108 change_frame_size (f
, rows
, cols
, 0, 0);
5109 PIXEL_WIDTH (f
) = pixelwidth
;
5110 PIXEL_HEIGHT (f
) = pixelheight
;
5112 /* If cursor was outside the new size, mark it as off. */
5113 if (f
->phys_cursor_y
>= rows
5114 || f
->phys_cursor_x
>= cols
)
5116 f
->phys_cursor_x
= -1;
5117 f
->phys_cursor_y
= -1;
5120 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5121 receive in the ConfigureNotify event; if we get what we asked
5122 for, then the event won't cause the screen to become garbaged, so
5123 we have to make sure to do it here. */
5124 SET_FRAME_GARBAGED (f
);
5126 XFlush (FRAME_X_DISPLAY (f
));
5128 #endif /* not USE_X_TOOLKIT */
5131 /* Mouse warping. */
5134 x_set_mouse_position (f
, x
, y
)
5140 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5141 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5143 if (pix_x
< 0) pix_x
= 0;
5144 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5146 if (pix_y
< 0) pix_y
= 0;
5147 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5151 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5152 0, 0, 0, 0, pix_x
, pix_y
);
5156 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5159 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5165 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5166 0, 0, 0, 0, pix_x
, pix_y
);
5170 /* focus shifting, raising and lowering. */
5172 x_focus_on_frame (f
)
5175 #if 0 /* This proves to be unpleasant. */
5179 /* I don't think that the ICCCM allows programs to do things like this
5180 without the interaction of the window manager. Whatever you end up
5181 doing with this code, do it to x_unfocus_frame too. */
5182 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5183 RevertToPointerRoot
, CurrentTime
);
5191 /* Look at the remarks in x_focus_on_frame. */
5192 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5193 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5194 RevertToPointerRoot
, CurrentTime
);
5198 /* Raise frame F. */
5203 if (f
->async_visible
)
5206 #ifdef USE_X_TOOLKIT
5207 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5208 #else /* not USE_X_TOOLKIT */
5209 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5210 #endif /* not USE_X_TOOLKIT */
5211 XFlush (FRAME_X_DISPLAY (f
));
5216 /* Lower frame F. */
5221 if (f
->async_visible
)
5224 #ifdef USE_X_TOOLKIT
5225 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5226 #else /* not USE_X_TOOLKIT */
5227 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5228 #endif /* not USE_X_TOOLKIT */
5229 XFlush (FRAME_X_DISPLAY (f
));
5235 XTframe_raise_lower (f
, raise
)
5245 /* Change of visibility. */
5247 /* This tries to wait until the frame is really visible.
5248 However, if the window manager asks the user where to position
5249 the frame, this will return before the user finishes doing that.
5250 The frame will not actually be visible at that time,
5251 but it will become visible later when the window manager
5252 finishes with it. */
5254 x_make_frame_visible (f
)
5262 type
= x_icon_type (f
);
5264 x_bitmap_icon (f
, type
);
5266 if (! FRAME_VISIBLE_P (f
))
5268 /* We test FRAME_GARBAGED_P here to make sure we don't
5269 call x_set_offset a second time
5270 if we get to x_make_frame_visible a second time
5271 before the window gets really visible. */
5272 if (! FRAME_ICONIFIED_P (f
)
5273 && ! f
->output_data
.x
->asked_for_visible
)
5274 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5276 f
->output_data
.x
->asked_for_visible
= 1;
5278 if (! EQ (Vx_no_window_manager
, Qt
))
5279 x_wm_set_window_state (f
, NormalState
);
5280 #ifdef USE_X_TOOLKIT
5281 /* This was XtPopup, but that did nothing for an iconified frame. */
5282 XtMapWidget (f
->output_data
.x
->widget
);
5283 #else /* not USE_X_TOOLKIT */
5284 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5285 #endif /* not USE_X_TOOLKIT */
5286 #if 0 /* This seems to bring back scroll bars in the wrong places
5287 if the window configuration has changed. They seem
5288 to come back ok without this. */
5289 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5290 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5294 XFlush (FRAME_X_DISPLAY (f
));
5296 /* Synchronize to ensure Emacs knows the frame is visible
5297 before we do anything else. We do this loop with input not blocked
5298 so that incoming events are handled. */
5301 int count
= input_signal_count
;
5303 /* This must come after we set COUNT. */
5306 XSETFRAME (frame
, f
);
5311 /* Once we have handled input events,
5312 we should have received the MapNotify if one is coming.
5313 So if we have not got it yet, stop looping.
5314 Some window managers make their own decisions
5315 about visibility. */
5316 if (input_signal_count
!= count
)
5318 /* Machines that do polling rather than SIGIO have been observed
5319 to go into a busy-wait here. So we'll fake an alarm signal
5320 to let the handler know that there's something to be read.
5321 We used to raise a real alarm, but it seems that the handler
5322 isn't always enabled here. This is probably a bug. */
5323 if (input_polling_used ())
5325 /* It could be confusing if a real alarm arrives while processing
5326 the fake one. Turn it off and let the handler reset it. */
5328 input_poll_signal ();
5330 /* Once we have handled input events,
5331 we should have received the MapNotify if one is coming.
5332 So if we have not got it yet, stop looping.
5333 Some window managers make their own decisions
5334 about visibility. */
5335 if (input_signal_count
!= count
)
5338 FRAME_SAMPLE_VISIBILITY (f
);
5342 /* Change from mapped state to withdrawn state. */
5344 /* Make the frame visible (mapped and not iconified). */
5346 x_make_frame_invisible (f
)
5352 #ifdef USE_X_TOOLKIT
5353 /* Use the frame's outermost window, not the one we normally draw on. */
5354 window
= XtWindow (f
->output_data
.x
->widget
);
5355 #else /* not USE_X_TOOLKIT */
5356 window
= FRAME_X_WINDOW (f
);
5357 #endif /* not USE_X_TOOLKIT */
5359 /* Don't keep the highlight on an invisible frame. */
5360 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5361 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5363 #if 0/* This might add unreliability; I don't trust it -- rms. */
5364 if (! f
->async_visible
&& ! f
->async_iconified
)
5370 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5371 that the current position of the window is user-specified, rather than
5372 program-specified, so that when the window is mapped again, it will be
5373 placed at the same location, without forcing the user to position it
5374 by hand again (they have already done that once for this window.) */
5375 x_wm_set_size_hint (f
, (long) 0, 1);
5379 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5380 DefaultScreen (FRAME_X_DISPLAY (f
))))
5382 UNBLOCK_INPUT_RESIGNAL
;
5383 error ("Can't notify window manager of window withdrawal");
5385 #else /* ! defined (HAVE_X11R4) */
5387 /* Tell the window manager what we're going to do. */
5388 if (! EQ (Vx_no_window_manager
, Qt
))
5392 unmap
.xunmap
.type
= UnmapNotify
;
5393 unmap
.xunmap
.window
= window
;
5394 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5395 unmap
.xunmap
.from_configure
= False
;
5396 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5397 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5399 SubstructureRedirectMask
|SubstructureNotifyMask
,
5402 UNBLOCK_INPUT_RESIGNAL
;
5403 error ("Can't notify window manager of withdrawal");
5407 /* Unmap the window ourselves. Cheeky! */
5408 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5409 #endif /* ! defined (HAVE_X11R4) */
5411 /* We can't distinguish this from iconification
5412 just by the event that we get from the server.
5413 So we can't win using the usual strategy of letting
5414 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5415 and synchronize with the server to make sure we agree. */
5417 FRAME_ICONIFIED_P (f
) = 0;
5418 f
->async_visible
= 0;
5419 f
->async_iconified
= 0;
5426 /* Change window state from mapped to iconified. */
5435 /* Don't keep the highlight on an invisible frame. */
5436 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5437 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5439 if (f
->async_iconified
)
5444 FRAME_SAMPLE_VISIBILITY (f
);
5446 type
= x_icon_type (f
);
5448 x_bitmap_icon (f
, type
);
5450 #ifdef USE_X_TOOLKIT
5452 if (! FRAME_VISIBLE_P (f
))
5454 if (! EQ (Vx_no_window_manager
, Qt
))
5455 x_wm_set_window_state (f
, IconicState
);
5456 /* This was XtPopup, but that did nothing for an iconified frame. */
5457 XtMapWidget (f
->output_data
.x
->widget
);
5462 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5463 XtWindow (f
->output_data
.x
->widget
),
5464 DefaultScreen (FRAME_X_DISPLAY (f
)));
5468 error ("Can't notify window manager of iconification");
5470 f
->async_iconified
= 1;
5473 XFlush (FRAME_X_DISPLAY (f
));
5475 #else /* not USE_X_TOOLKIT */
5477 /* Make sure the X server knows where the window should be positioned,
5478 in case the user deiconifies with the window manager. */
5479 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5480 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5482 /* Since we don't know which revision of X we're running, we'll use both
5483 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5485 /* X11R4: send a ClientMessage to the window manager using the
5486 WM_CHANGE_STATE type. */
5490 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5491 message
.xclient
.type
= ClientMessage
;
5492 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5493 message
.xclient
.format
= 32;
5494 message
.xclient
.data
.l
[0] = IconicState
;
5496 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5497 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5499 SubstructureRedirectMask
| SubstructureNotifyMask
,
5502 UNBLOCK_INPUT_RESIGNAL
;
5503 error ("Can't notify window manager of iconification");
5507 /* X11R3: set the initial_state field of the window manager hints to
5509 x_wm_set_window_state (f
, IconicState
);
5511 if (!FRAME_VISIBLE_P (f
))
5513 /* If the frame was withdrawn, before, we must map it. */
5514 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5517 f
->async_iconified
= 1;
5519 XFlush (FRAME_X_DISPLAY (f
));
5521 #endif /* not USE_X_TOOLKIT */
5524 /* Destroy the X window of frame F. */
5526 x_destroy_window (f
)
5529 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5533 if (f
->output_data
.x
->icon_desc
!= 0)
5534 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
5535 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
5536 #ifdef USE_X_TOOLKIT
5537 XtDestroyWidget (f
->output_data
.x
->widget
);
5538 free_frame_menubar (f
);
5539 #endif /* USE_X_TOOLKIT */
5541 free_frame_faces (f
);
5542 XFlush (FRAME_X_DISPLAY (f
));
5544 xfree (f
->output_data
.x
);
5545 f
->output_data
.x
= 0;
5546 if (f
== dpyinfo
->x_focus_frame
)
5547 dpyinfo
->x_focus_frame
= 0;
5548 if (f
== dpyinfo
->x_focus_event_frame
)
5549 dpyinfo
->x_focus_event_frame
= 0;
5550 if (f
== dpyinfo
->x_highlight_frame
)
5551 dpyinfo
->x_highlight_frame
= 0;
5553 dpyinfo
->reference_count
--;
5555 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5557 dpyinfo
->mouse_face_beg_row
5558 = dpyinfo
->mouse_face_beg_col
= -1;
5559 dpyinfo
->mouse_face_end_row
5560 = dpyinfo
->mouse_face_end_col
= -1;
5561 dpyinfo
->mouse_face_window
= Qnil
;
5567 /* Setting window manager hints. */
5569 /* Set the normal size hints for the window manager, for frame F.
5570 FLAGS is the flags word to use--or 0 meaning preserve the flags
5571 that the window now has.
5572 If USER_POSITION is nonzero, we set the USPosition
5573 flag (this is useful when FLAGS is 0). */
5575 x_wm_set_size_hint (f
, flags
, user_position
)
5580 XSizeHints size_hints
;
5582 #ifdef USE_X_TOOLKIT
5585 Dimension widget_width
, widget_height
;
5586 Window window
= XtWindow (f
->output_data
.x
->widget
);
5587 #else /* not USE_X_TOOLKIT */
5588 Window window
= FRAME_X_WINDOW (f
);
5589 #endif /* not USE_X_TOOLKIT */
5591 /* Setting PMaxSize caused various problems. */
5592 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5594 flexlines
= f
->height
;
5596 size_hints
.x
= f
->output_data
.x
->left_pos
;
5597 size_hints
.y
= f
->output_data
.x
->top_pos
;
5599 #ifdef USE_X_TOOLKIT
5600 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5601 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5602 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5603 size_hints
.height
= widget_height
;
5604 size_hints
.width
= widget_width
;
5605 #else /* not USE_X_TOOLKIT */
5606 size_hints
.height
= PIXEL_HEIGHT (f
);
5607 size_hints
.width
= PIXEL_WIDTH (f
);
5608 #endif /* not USE_X_TOOLKIT */
5610 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
5611 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
5612 size_hints
.max_width
5613 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5614 size_hints
.max_height
5615 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5617 /* Calculate the base and minimum sizes.
5619 (When we use the X toolkit, we don't do it here.
5620 Instead we copy the values that the widgets are using, below.) */
5621 #ifndef USE_X_TOOLKIT
5623 int base_width
, base_height
;
5624 int min_rows
= 0, min_cols
= 0;
5626 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5627 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5629 check_frame_size (f
, &min_rows
, &min_cols
);
5631 /* The window manager uses the base width hints to calculate the
5632 current number of rows and columns in the frame while
5633 resizing; min_width and min_height aren't useful for this
5634 purpose, since they might not give the dimensions for a
5635 zero-row, zero-column frame.
5637 We use the base_width and base_height members if we have
5638 them; otherwise, we set the min_width and min_height members
5639 to the size for a zero x zero frame. */
5642 size_hints
.flags
|= PBaseSize
;
5643 size_hints
.base_width
= base_width
;
5644 size_hints
.base_height
= base_height
;
5645 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5646 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5648 size_hints
.min_width
= base_width
;
5649 size_hints
.min_height
= base_height
;
5653 /* If we don't need the old flags, we don't need the old hint at all. */
5656 size_hints
.flags
|= flags
;
5659 #endif /* not USE_X_TOOLKIT */
5662 XSizeHints hints
; /* Sometimes I hate X Windows... */
5663 long supplied_return
;
5667 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5670 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5673 #ifdef USE_X_TOOLKIT
5674 size_hints
.base_height
= hints
.base_height
;
5675 size_hints
.base_width
= hints
.base_width
;
5676 size_hints
.min_height
= hints
.min_height
;
5677 size_hints
.min_width
= hints
.min_width
;
5681 size_hints
.flags
|= flags
;
5686 if (hints
.flags
& PSize
)
5687 size_hints
.flags
|= PSize
;
5688 if (hints
.flags
& PPosition
)
5689 size_hints
.flags
|= PPosition
;
5690 if (hints
.flags
& USPosition
)
5691 size_hints
.flags
|= USPosition
;
5692 if (hints
.flags
& USSize
)
5693 size_hints
.flags
|= USSize
;
5700 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
5701 size_hints
.flags
|= PWinGravity
;
5705 size_hints
.flags
&= ~ PPosition
;
5706 size_hints
.flags
|= USPosition
;
5708 #endif /* PWinGravity */
5711 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5713 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5717 /* Used for IconicState or NormalState */
5718 x_wm_set_window_state (f
, state
)
5722 #ifdef USE_X_TOOLKIT
5725 XtSetArg (al
[0], XtNinitialState
, state
);
5726 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5727 #else /* not USE_X_TOOLKIT */
5728 Window window
= FRAME_X_WINDOW (f
);
5730 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5731 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5733 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5734 #endif /* not USE_X_TOOLKIT */
5737 x_wm_set_icon_pixmap (f
, pixmap_id
)
5741 #ifdef USE_X_TOOLKIT
5742 Window window
= XtWindow (f
->output_data
.x
->widget
);
5744 Window window
= FRAME_X_WINDOW (f
);
5749 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5750 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5754 /* It seems there is no way to turn off use of an icon pixmap.
5755 The following line does it, only if no icon has yet been created,
5756 for some window managers. But with mwm it crashes.
5757 Some people say it should clear the IconPixmapHint bit in this case,
5758 but that doesn't work, and the X consortium said it isn't the
5759 right thing at all. Since there is no way to win,
5760 best to explicitly give up. */
5762 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5768 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5769 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5772 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5776 #ifdef USE_X_TOOLKIT
5777 Window window
= XtWindow (f
->output_data
.x
->widget
);
5779 Window window
= FRAME_X_WINDOW (f
);
5782 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5783 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5784 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5786 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5790 /* Initialization. */
5792 #ifdef USE_X_TOOLKIT
5793 static XrmOptionDescRec emacs_options
[] = {
5794 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5795 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5797 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5798 XrmoptionSepArg
, NULL
},
5799 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5801 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5802 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5803 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5804 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5805 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5806 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5807 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5809 #endif /* USE_X_TOOLKIT */
5811 static int x_initialized
;
5814 /* Test whether two display-name strings agree up to the dot that separates
5815 the screen number from the server number. */
5817 same_x_server (name1
, name2
)
5818 char *name1
, *name2
;
5821 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5825 if (seen_colon
&& *name1
== '.')
5829 && (*name1
== '.' || *name1
== '\0')
5830 && (*name2
== '.' || *name2
== '\0'));
5834 struct x_display_info
*
5835 x_term_init (display_name
, xrm_option
, resource_name
)
5836 Lisp_Object display_name
;
5838 char *resource_name
;
5844 struct x_display_info
*dpyinfo
;
5856 setlocale (LC_ALL
, NULL
);
5859 #ifdef USE_X_TOOLKIT
5860 /* weiner@footloose.sps.mot.com reports that this causes
5862 X protocol error: BadAtom (invalid Atom parameter)
5863 on protocol request 18skiloaf.
5864 So let's not use it until R6. */
5866 XtSetLanguageProc (NULL
, NULL
, NULL
);
5877 argv
[argc
++] = "-xrm";
5878 argv
[argc
++] = xrm_option
;
5880 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5881 resource_name
, EMACS_CLASS
,
5882 emacs_options
, XtNumber (emacs_options
),
5886 setlocale (LC_NUMERIC
, "C");
5887 setlocale (LC_TIME
, "C");
5891 #else /* not USE_X_TOOLKIT */
5893 XSetLocaleModifiers ("");
5895 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5896 #endif /* not USE_X_TOOLKIT */
5898 /* Detect failure. */
5905 /* We have definitely succeeded. Record the new connection. */
5907 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5911 struct x_display_info
*share
;
5914 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5915 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5916 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5917 XSTRING (display_name
)->data
))
5920 dpyinfo
->kboard
= share
->kboard
;
5923 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5924 init_kboard (dpyinfo
->kboard
);
5925 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
5927 char *vendor
= ServerVendor (dpy
);
5928 dpyinfo
->kboard
->Vsystem_key_alist
5929 = call1 (Qvendor_specific_keysyms
,
5930 build_string (vendor
? vendor
: ""));
5933 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5934 all_kboards
= dpyinfo
->kboard
;
5935 /* Don't let the initial kboard remain current longer than necessary.
5936 That would cause problems if a file loaded on startup tries to
5937 prompt in the minibuffer. */
5938 if (current_kboard
== initial_kboard
)
5939 current_kboard
= dpyinfo
->kboard
;
5941 dpyinfo
->kboard
->reference_count
++;
5945 /* Put this display on the chain. */
5946 dpyinfo
->next
= x_display_list
;
5947 x_display_list
= dpyinfo
;
5949 /* Put it on x_display_name_list as well, to keep them parallel. */
5950 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5951 x_display_name_list
);
5952 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5954 dpyinfo
->display
= dpy
;
5957 XSetAfterFunction (x_current_display
, x_trace_wire
);
5961 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5962 + XSTRING (Vsystem_name
)->size
5964 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5965 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5967 /* Figure out which modifier bits mean what. */
5968 x_find_modifier_meanings (dpyinfo
);
5970 /* Get the scroll bar cursor. */
5971 dpyinfo
->vertical_scroll_bar_cursor
5972 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5974 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5975 resource_name
, EMACS_CLASS
);
5976 #ifdef HAVE_XRMSETDATABASE
5977 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5979 dpyinfo
->display
->db
= xrdb
;
5981 /* Put the rdb where we can find it in a way that works on
5983 dpyinfo
->xrdb
= xrdb
;
5985 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5986 DefaultScreen (dpyinfo
->display
));
5987 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5988 &dpyinfo
->n_planes
);
5989 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
5990 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
5991 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
5992 dpyinfo
->grabbed
= 0;
5993 dpyinfo
->reference_count
= 0;
5994 dpyinfo
->icon_bitmap_id
= -1;
5995 dpyinfo
->n_fonts
= 0;
5996 dpyinfo
->font_table_size
= 0;
5997 dpyinfo
->bitmaps
= 0;
5998 dpyinfo
->bitmaps_size
= 0;
5999 dpyinfo
->bitmaps_last
= 0;
6000 dpyinfo
->scratch_cursor_gc
= 0;
6001 dpyinfo
->mouse_face_mouse_frame
= 0;
6002 dpyinfo
->mouse_face_deferred_gc
= 0;
6003 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6004 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6005 dpyinfo
->mouse_face_face_id
= 0;
6006 dpyinfo
->mouse_face_window
= Qnil
;
6007 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
6008 dpyinfo
->mouse_face_defer
= 0;
6009 dpyinfo
->x_focus_frame
= 0;
6010 dpyinfo
->x_focus_event_frame
= 0;
6011 dpyinfo
->x_highlight_frame
= 0;
6013 dpyinfo
->Xatom_wm_protocols
6014 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
6015 dpyinfo
->Xatom_wm_take_focus
6016 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
6017 dpyinfo
->Xatom_wm_save_yourself
6018 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
6019 dpyinfo
->Xatom_wm_delete_window
6020 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
6021 dpyinfo
->Xatom_wm_change_state
6022 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
6023 dpyinfo
->Xatom_wm_configure_denied
6024 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
6025 dpyinfo
->Xatom_wm_window_moved
6026 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
6027 dpyinfo
->Xatom_editres
6028 = XInternAtom (dpyinfo
->display
, "Editres", False
);
6029 dpyinfo
->Xatom_CLIPBOARD
6030 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
6031 dpyinfo
->Xatom_TIMESTAMP
6032 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
6034 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
6035 dpyinfo
->Xatom_DELETE
6036 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
6037 dpyinfo
->Xatom_MULTIPLE
6038 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
6040 = XInternAtom (dpyinfo
->display
, "INCR", False
);
6041 dpyinfo
->Xatom_EMACS_TMP
6042 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
6043 dpyinfo
->Xatom_TARGETS
6044 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
6046 = XInternAtom (dpyinfo
->display
, "NULL", False
);
6047 dpyinfo
->Xatom_ATOM_PAIR
6048 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
6050 dpyinfo
->cut_buffers_initialized
= 0;
6052 connection
= ConnectionNumber (dpyinfo
->display
);
6053 dpyinfo
->connection
= connection
;
6056 /* This is only needed for distinguishing keyboard and process input. */
6057 if (connection
!= 0)
6058 add_keyboard_wait_descriptor (connection
);
6061 #ifndef F_SETOWN_BUG
6063 #ifdef F_SETOWN_SOCK_NEG
6064 /* stdin is a socket here */
6065 fcntl (connection
, F_SETOWN
, -getpid ());
6066 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6067 fcntl (connection
, F_SETOWN
, getpid ());
6068 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6069 #endif /* ! defined (F_SETOWN) */
6070 #endif /* F_SETOWN_BUG */
6073 if (interrupt_input
)
6074 init_sigio (connection
);
6075 #endif /* ! defined (SIGIO) */
6082 /* Get rid of display DPYINFO, assuming all frames are already gone,
6083 and without sending any more commands to the X server. */
6086 x_delete_display (dpyinfo
)
6087 struct x_display_info
*dpyinfo
;
6089 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
6091 /* Discard this display from x_display_name_list and x_display_list.
6092 We can't use Fdelq because that can quit. */
6093 if (! NILP (x_display_name_list
)
6094 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
6095 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
6100 tail
= x_display_name_list
;
6101 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
6103 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
6104 dpyinfo
->name_list_element
))
6106 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
6109 tail
= XCONS (tail
)->cdr
;
6113 if (x_display_list
== dpyinfo
)
6114 x_display_list
= dpyinfo
->next
;
6117 struct x_display_info
*tail
;
6119 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
6120 if (tail
->next
== dpyinfo
)
6121 tail
->next
= tail
->next
->next
;
6124 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6125 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6126 XrmDestroyDatabase (dpyinfo
->xrdb
);
6130 if (--dpyinfo
->kboard
->reference_count
== 0)
6131 delete_kboard (dpyinfo
->kboard
);
6133 xfree (dpyinfo
->font_table
);
6134 xfree (dpyinfo
->x_id_name
);
6138 /* Set up use of X before we make the first connection. */
6142 clear_frame_hook
= XTclear_frame
;
6143 clear_end_of_line_hook
= XTclear_end_of_line
;
6144 ins_del_lines_hook
= XTins_del_lines
;
6145 change_line_highlight_hook
= XTchange_line_highlight
;
6146 insert_glyphs_hook
= XTinsert_glyphs
;
6147 write_glyphs_hook
= XTwrite_glyphs
;
6148 delete_glyphs_hook
= XTdelete_glyphs
;
6149 ring_bell_hook
= XTring_bell
;
6150 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6151 set_terminal_modes_hook
= XTset_terminal_modes
;
6152 update_begin_hook
= XTupdate_begin
;
6153 update_end_hook
= XTupdate_end
;
6154 set_terminal_window_hook
= XTset_terminal_window
;
6155 read_socket_hook
= XTread_socket
;
6156 frame_up_to_date_hook
= XTframe_up_to_date
;
6157 cursor_to_hook
= XTcursor_to
;
6158 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6159 mouse_position_hook
= XTmouse_position
;
6160 frame_rehighlight_hook
= XTframe_rehighlight
;
6161 frame_raise_lower_hook
= XTframe_raise_lower
;
6162 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6163 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6164 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6165 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6167 scroll_region_ok
= 1; /* we'll scroll partial frames */
6168 char_ins_del_ok
= 0; /* just as fast to write the line */
6169 line_ins_del_ok
= 1; /* we'll just blt 'em */
6170 fast_clear_end_of_line
= 1; /* X does this well */
6171 memory_below_frame
= 0; /* we don't remember what scrolls
6177 /* Try to use interrupt input; if we can't, then start polling. */
6178 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6180 #ifdef USE_X_TOOLKIT
6181 XtToolkitInitialize ();
6182 Xt_app_con
= XtCreateApplicationContext ();
6183 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
6186 /* Note that there is no real way portable across R3/R4 to get the
6187 original error handler. */
6188 XSetErrorHandler (x_error_quitter
);
6189 XSetIOErrorHandler (x_io_error_quitter
);
6191 /* Disable Window Change signals; they are handled by X events. */
6193 signal (SIGWINCH
, SIG_DFL
);
6194 #endif /* ! defined (SIGWINCH) */
6196 signal (SIGPIPE
, x_connection_signal
);
6202 staticpro (&x_display_name_list
);
6203 x_display_name_list
= Qnil
;
6205 staticpro (&last_mouse_scroll_bar
);
6206 last_mouse_scroll_bar
= Qnil
;
6208 staticpro (&Qvendor_specific_keysyms
);
6209 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6211 #endif /* ! defined (HAVE_X_WINDOWS) */