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
= display
->min_keycode
;
1568 max_code
= 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 signalling 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
;
3471 case SelectionRequest
: /* Someone wants our selection. */
3472 #ifdef USE_X_TOOLKIT
3473 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3475 #endif /* USE_X_TOOLKIT */
3476 if (x_queue_selection_requests
)
3477 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3481 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3486 bufp
->kind
= selection_request_event
;
3487 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3488 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3489 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3490 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3491 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3492 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3500 case PropertyNotify
:
3501 #ifdef USE_X_TOOLKIT
3502 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3504 #endif /* not USE_X_TOOLKIT */
3505 x_handle_property_notify (&event
);
3508 case ReparentNotify
:
3509 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3513 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
3514 x_real_positions (f
, &x
, &y
);
3515 f
->output_data
.x
->left_pos
= x
;
3516 f
->output_data
.x
->top_pos
= y
;
3521 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3524 if (f
->async_visible
== 0)
3526 f
->async_visible
= 1;
3527 f
->async_iconified
= 0;
3528 SET_FRAME_GARBAGED (f
);
3531 dumprectangle (x_window_to_frame (dpyinfo
,
3532 event
.xexpose
.window
),
3533 event
.xexpose
.x
, event
.xexpose
.y
,
3534 event
.xexpose
.width
, event
.xexpose
.height
);
3538 struct scroll_bar
*bar
3539 = x_window_to_scroll_bar (event
.xexpose
.window
);
3542 x_scroll_bar_expose (bar
, &event
);
3543 #ifdef USE_X_TOOLKIT
3546 #endif /* USE_X_TOOLKIT */
3550 case GraphicsExpose
: /* This occurs when an XCopyArea's
3551 source area was obscured or not
3553 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3557 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3558 event
.xgraphicsexpose
.width
,
3559 event
.xgraphicsexpose
.height
);
3561 #ifdef USE_X_TOOLKIT
3564 #endif /* USE_X_TOOLKIT */
3567 case NoExpose
: /* This occurs when an XCopyArea's
3568 source area was completely
3573 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3574 if (f
) /* F may no longer exist if
3575 the frame was deleted. */
3577 /* While a frame is unmapped, display generation is
3578 disabled; you don't want to spend time updating a
3579 display that won't ever be seen. */
3580 f
->async_visible
= 0;
3581 /* We can't distinguish, from the event, whether the window
3582 has become iconified or invisible. So assume, if it
3583 was previously visible, than now it is iconified.
3584 We depend on x_make_frame_invisible to mark it iconified. */
3585 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3586 f
->async_iconified
= 1;
3588 bufp
->kind
= iconify_event
;
3589 XSETFRAME (bufp
->frame_or_window
, f
);
3594 #ifdef USE_X_TOOLKIT
3596 #endif /* USE_X_TOOLKIT */
3600 /* We use x_top_window_to_frame because map events can come
3601 for subwindows and they don't mean that the frame is visible. */
3602 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
3605 f
->async_visible
= 1;
3606 f
->async_iconified
= 0;
3608 /* wait_reading_process_input will notice this and update
3609 the frame's display structures. */
3610 SET_FRAME_GARBAGED (f
);
3614 bufp
->kind
= deiconify_event
;
3615 XSETFRAME (bufp
->frame_or_window
, f
);
3621 /* Force a redisplay sooner or later
3622 to update the frame titles
3623 in case this is the second frame. */
3624 record_asynch_buffer_change ();
3626 #ifdef USE_X_TOOLKIT
3628 #endif /* USE_X_TOOLKIT */
3631 /* Turn off processing if we become fully obscured. */
3632 case VisibilityNotify
:
3636 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
3640 KeySym keysym
, orig_keysym
;
3641 /* al%imercury@uunet.uu.net says that making this 81 instead of
3642 80 fixed a bug whereby meta chars made his Emacs hang. */
3643 unsigned char copy_buffer
[81];
3647 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3648 extra_keyboard_modifiers
);
3649 modifiers
= event
.xkey
.state
;
3651 /* This will have to go some day... */
3653 /* make_lispy_event turns chars into control chars.
3654 Don't do it here because XLookupString is too eager. */
3655 event
.xkey
.state
&= ~ControlMask
;
3656 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
3657 | dpyinfo
->super_mod_mask
3658 | dpyinfo
->hyper_mod_mask
3659 | dpyinfo
->alt_mod_mask
);
3664 /* The necessity of the following line took me
3665 a full work-day to decipher from the docs!! */
3666 if (XFilterEvent (&event
, None
))
3668 nbytes
= XmbLookupString (FRAME_XIC (f
),
3669 &event
.xkey
, copy_buffer
,
3674 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3675 80, &keysym
, &compose_status
);
3677 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3678 80, &keysym
, &compose_status
);
3681 orig_keysym
= keysym
;
3685 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3686 || keysym
== XK_Delete
3687 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3688 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3690 /* This recognizes the "extended function keys".
3691 It seems there's no cleaner way.
3692 Test IsModifierKey to avoid handling mode_switch
3694 || ((unsigned) (keysym
) >= XK_Select
3695 && (unsigned)(keysym
) < XK_KP_Space
)
3697 #ifdef XK_dead_circumflex
3698 || orig_keysym
== XK_dead_circumflex
3700 #ifdef XK_dead_grave
3701 || orig_keysym
== XK_dead_grave
3703 #ifdef XK_dead_tilde
3704 || orig_keysym
== XK_dead_tilde
3706 #ifdef XK_dead_diaeresis
3707 || orig_keysym
== XK_dead_diaeresis
3709 #ifdef XK_dead_macron
3710 || orig_keysym
== XK_dead_macron
3712 #ifdef XK_dead_degree
3713 || orig_keysym
== XK_dead_degree
3715 #ifdef XK_dead_acute
3716 || orig_keysym
== XK_dead_acute
3718 #ifdef XK_dead_cedilla
3719 || orig_keysym
== XK_dead_cedilla
3721 #ifdef XK_dead_breve
3722 || orig_keysym
== XK_dead_breve
3724 #ifdef XK_dead_ogonek
3725 || orig_keysym
== XK_dead_ogonek
3727 #ifdef XK_dead_caron
3728 || orig_keysym
== XK_dead_caron
3730 #ifdef XK_dead_doubleacute
3731 || orig_keysym
== XK_dead_doubleacute
3733 #ifdef XK_dead_abovedot
3734 || orig_keysym
== XK_dead_abovedot
3736 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3737 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3738 /* Any "vendor-specific" key is ok. */
3739 || (orig_keysym
& (1 << 28)))
3740 && ! (IsModifierKey (orig_keysym
)
3742 #ifdef XK_Mode_switch
3743 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3746 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3748 #endif /* not HAVE_X11R5 */
3751 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3753 temp_buffer
[temp_index
++] = keysym
;
3754 bufp
->kind
= non_ascii_keystroke
;
3755 bufp
->code
= keysym
;
3756 XSETFRAME (bufp
->frame_or_window
, f
);
3758 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3760 bufp
->timestamp
= event
.xkey
.time
;
3765 else if (numchars
> nbytes
)
3769 for (i
= 0; i
< nbytes
; i
++)
3771 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3773 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3774 bufp
->kind
= ascii_keystroke
;
3775 bufp
->code
= copy_buffer
[i
];
3776 XSETFRAME (bufp
->frame_or_window
, f
);
3778 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3780 bufp
->timestamp
= event
.xkey
.time
;
3795 /* Here's a possible interpretation of the whole
3796 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3797 FocusIn event, you have to get a FocusOut event before you
3798 relinquish the focus. If you haven't received a FocusIn event,
3799 then a mere LeaveNotify is enough to free you. */
3802 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3804 if (event
.xcrossing
.focus
) /* Entered Window */
3806 /* Avoid nasty pop/raise loops. */
3807 if (f
&& (!(f
->auto_raise
)
3809 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3811 x_new_focus_frame (dpyinfo
, f
);
3812 enter_timestamp
= event
.xcrossing
.time
;
3815 else if (f
== dpyinfo
->x_focus_frame
)
3816 x_new_focus_frame (dpyinfo
, 0);
3817 /* EnterNotify counts as mouse movement,
3818 so update things that depend on mouse position. */
3820 note_mouse_movement (f
, &event
.xmotion
);
3821 #ifdef USE_X_TOOLKIT
3823 #endif /* USE_X_TOOLKIT */
3827 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3828 if (event
.xfocus
.detail
!= NotifyPointer
)
3829 dpyinfo
->x_focus_event_frame
= f
;
3831 x_new_focus_frame (dpyinfo
, f
);
3834 if (f
&& FRAME_XIC (f
))
3835 XSetICFocus (FRAME_XIC (f
));
3838 #ifdef USE_X_TOOLKIT
3840 #endif /* USE_X_TOOLKIT */
3845 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3848 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3849 /* If we move outside the frame,
3850 then we're certainly no longer on any text in the frame. */
3851 clear_mouse_face (dpyinfo
);
3853 if (event
.xcrossing
.focus
)
3854 x_mouse_leave (dpyinfo
);
3857 if (f
== dpyinfo
->x_focus_event_frame
)
3858 dpyinfo
->x_focus_event_frame
= 0;
3859 if (f
== dpyinfo
->x_focus_frame
)
3860 x_new_focus_frame (dpyinfo
, 0);
3863 #ifdef USE_X_TOOLKIT
3865 #endif /* USE_X_TOOLKIT */
3869 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3870 if (event
.xfocus
.detail
!= NotifyPointer
3871 && f
== dpyinfo
->x_focus_event_frame
)
3872 dpyinfo
->x_focus_event_frame
= 0;
3873 if (f
&& f
== dpyinfo
->x_focus_frame
)
3874 x_new_focus_frame (dpyinfo
, 0);
3877 if (f
&& FRAME_XIC (f
))
3878 XUnsetICFocus (FRAME_XIC (f
));
3881 #ifdef USE_X_TOOLKIT
3883 #endif /* USE_X_TOOLKIT */
3888 if (dpyinfo
->grabbed
&& last_mouse_frame
3889 && FRAME_LIVE_P (last_mouse_frame
))
3890 f
= last_mouse_frame
;
3892 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3894 note_mouse_movement (f
, &event
.xmotion
);
3897 struct scroll_bar
*bar
3898 = x_window_to_scroll_bar (event
.xmotion
.window
);
3901 x_scroll_bar_note_movement (bar
, &event
);
3903 /* If we move outside the frame,
3904 then we're certainly no longer on any text in the frame. */
3905 clear_mouse_face (dpyinfo
);
3908 #ifdef USE_X_TOOLKIT
3910 #endif /* USE_X_TOOLKIT */
3913 case ConfigureNotify
:
3914 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
3916 #ifdef USE_X_TOOLKIT
3917 && (event
.xconfigure
.window
== XtWindow (f
->output_data
.x
->widget
))
3921 #ifndef USE_X_TOOLKIT
3922 /* In the toolkit version, change_frame_size
3923 is called by the code that handles resizing
3924 of the EmacsFrame widget. */
3926 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3927 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3929 /* Even if the number of character rows and columns has
3930 not changed, the font size may have changed, so we need
3931 to check the pixel dimensions as well. */
3932 if (columns
!= f
->width
3933 || rows
!= f
->height
3934 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
3935 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
3937 change_frame_size (f
, rows
, columns
, 0, 1);
3938 SET_FRAME_GARBAGED (f
);
3942 /* Formerly, in the USE_X_TOOLKIT version,
3943 we did not test send_event here. */
3945 #ifndef USE_X_TOOLKIT
3946 && ! event
.xconfigure
.send_event
3953 /* Find the position of the outside upper-left corner of
3954 the window, in the root coordinate system. Don't
3955 refer to the parent window here; we may be processing
3956 this event after the window manager has changed our
3957 parent, but before we have reached the ReparentNotify. */
3958 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3960 /* From-window, to-window. */
3961 event
.xconfigure
.window
,
3962 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3964 /* From-position, to-position. */
3965 -event
.xconfigure
.border_width
,
3966 -event
.xconfigure
.border_width
,
3971 event
.xconfigure
.x
= win_x
;
3972 event
.xconfigure
.y
= win_y
;
3975 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
3976 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
3977 f
->output_data
.x
->left_pos
= event
.xconfigure
.x
;
3978 f
->output_data
.x
->top_pos
= event
.xconfigure
.y
;
3980 /* What we have now is the position of Emacs's own window.
3981 Convert that to the position of the window manager window. */
3984 x_real_positions (f
, &x
, &y
);
3985 f
->output_data
.x
->left_pos
= x
;
3986 f
->output_data
.x
->top_pos
= y
;
3987 /* Formerly we did not do this in the USE_X_TOOLKIT
3988 version. Let's try making them the same. */
3989 /* #ifndef USE_X_TOOLKIT */
3990 if (y
!= event
.xconfigure
.y
)
3992 /* Since the WM decorations come below top_pos now,
3993 we must put them below top_pos in the future. */
3994 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3995 x_wm_set_size_hint (f
, (long) 0, 0);
4000 #ifdef USE_X_TOOLKIT
4009 /* If we decide we want to generate an event to be seen
4010 by the rest of Emacs, we put it here. */
4011 struct input_event emacs_event
;
4012 emacs_event
.kind
= no_event
;
4014 bzero (&compose_status
, sizeof (compose_status
));
4016 if (dpyinfo
->grabbed
&& last_mouse_frame
4017 && FRAME_LIVE_P (last_mouse_frame
))
4018 f
= last_mouse_frame
;
4020 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4024 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4025 construct_mouse_click (&emacs_event
, &event
, f
);
4029 struct scroll_bar
*bar
4030 = x_window_to_scroll_bar (event
.xbutton
.window
);
4033 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4036 if (event
.type
== ButtonPress
)
4038 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4039 last_mouse_frame
= f
;
4043 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4046 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4048 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4054 #ifdef USE_X_TOOLKIT
4055 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4056 /* For a down-event in the menu bar,
4057 don't pass it to Xt right now.
4058 Instead, save it away
4059 and we will pass it to Xt from kbd_buffer_get_event.
4060 That way, we can run some Lisp code first. */
4061 if (f
&& event
.type
== ButtonPress
4062 /* Verify the event is really within the menu bar
4063 and not just sent to it due to grabbing. */
4064 && event
.xbutton
.x
>= 0
4065 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4066 && event
.xbutton
.y
>= 0
4067 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4068 && event
.xbutton
.same_screen
)
4070 if (f
->output_data
.x
->saved_button_event
== 0)
4071 f
->output_data
.x
->saved_button_event
4072 = (XButtonEvent
*) xmalloc (sizeof (XButtonEvent
));
4073 bcopy (&event
, f
->output_data
.x
->saved_button_event
,
4074 sizeof (XButtonEvent
));
4077 bufp
->kind
= menu_bar_activate_event
;
4078 XSETFRAME (bufp
->frame_or_window
, f
);
4086 #endif /* USE_X_TOOLKIT */
4090 case CirculateNotify
:
4092 case CirculateRequest
:
4096 /* Someone has changed the keyboard mapping - update the
4098 switch (event
.xmapping
.request
)
4100 case MappingModifier
:
4101 x_find_modifier_meanings (dpyinfo
);
4102 /* This is meant to fall through. */
4103 case MappingKeyboard
:
4104 XRefreshKeyboardMapping (&event
.xmapping
);
4106 #ifdef USE_X_TOOLKIT
4108 #endif /* USE_X_TOOLKIT */
4112 #ifdef USE_X_TOOLKIT
4115 XtDispatchEvent (&event
);
4117 #endif /* USE_X_TOOLKIT */
4123 /* On some systems, an X bug causes Emacs to get no more events
4124 when the window is destroyed. Detect that. (1994.) */
4127 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4128 One XNOOP in 100 loops will make Emacs terminate.
4129 B. Bretthauer, 1994 */
4131 if (x_noop_count
>= 100)
4135 if (next_noop_dpyinfo
== 0)
4136 next_noop_dpyinfo
= x_display_list
;
4138 XNoOp (next_noop_dpyinfo
->display
);
4140 /* Each time we get here, cycle through the displays now open. */
4141 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4145 /* If the focus was just given to an autoraising frame,
4147 /* ??? This ought to be able to handle more than one such frame. */
4148 if (pending_autoraise_frame
)
4150 x_raise_frame (pending_autoraise_frame
);
4151 pending_autoraise_frame
= 0;
4158 /* Drawing the cursor. */
4161 /* Draw a hollow box cursor on frame F at X, Y.
4162 Don't change the inside of the box. */
4165 x_draw_box (f
, x
, y
)
4169 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4170 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4171 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4172 int height
= f
->output_data
.x
->line_height
;
4174 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4175 f
->output_data
.x
->cursor_gc
,
4176 left
, top
, width
- 1, height
- 1);
4179 /* Clear the cursor of frame F to background color,
4180 and mark the cursor as not shown.
4181 This is used when the text where the cursor is
4182 is about to be rewritten. */
4190 if (! FRAME_VISIBLE_P (f
)
4191 || f
->phys_cursor_x
< 0)
4194 x_display_cursor (f
, 0);
4195 f
->phys_cursor_x
= -1;
4198 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4199 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4203 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4210 CHAR_TO_PIXEL_COL (f
, column
),
4211 CHAR_TO_PIXEL_ROW (f
, row
),
4212 &glyph
, 1, highlight
, 0);
4216 x_display_bar_cursor (f
, on
, x
, y
)
4221 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4223 /* This is pointless on invisible frames, and dangerous on garbaged
4224 frames; in the latter case, the frame may be in the midst of
4225 changing its size, and x and y may be off the frame. */
4226 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4229 if (! on
&& f
->phys_cursor_x
< 0)
4232 /* If there is anything wrong with the current cursor state, remove it. */
4233 if (f
->phys_cursor_x
>= 0
4235 || f
->phys_cursor_x
!= x
4236 || f
->phys_cursor_y
!= y
4237 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4239 /* Erase the cursor by redrawing the character underneath it. */
4240 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4241 f
->phys_cursor_glyph
,
4242 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4243 f
->phys_cursor_x
= -1;
4246 /* If we now need a cursor in the new place or in the new form, do it so. */
4248 && (f
->phys_cursor_x
< 0
4249 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4251 f
->phys_cursor_glyph
4252 = ((current_glyphs
->enable
[y
]
4253 && x
< current_glyphs
->used
[y
])
4254 ? current_glyphs
->glyphs
[y
][x
]
4256 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4257 f
->output_data
.x
->cursor_gc
,
4258 CHAR_TO_PIXEL_COL (f
, x
),
4259 CHAR_TO_PIXEL_ROW (f
, y
),
4260 max (f
->output_data
.x
->cursor_width
, 1),
4261 f
->output_data
.x
->line_height
);
4263 f
->phys_cursor_x
= x
;
4264 f
->phys_cursor_y
= y
;
4266 f
->output_data
.x
->current_cursor
= bar_cursor
;
4269 if (updating_frame
!= f
)
4270 XFlush (FRAME_X_DISPLAY (f
));
4274 /* Turn the displayed cursor of frame F on or off according to ON.
4275 If ON is nonzero, where to put the cursor is specified by X and Y. */
4278 x_display_box_cursor (f
, on
, x
, y
)
4283 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4285 /* This is pointless on invisible frames, and dangerous on garbaged
4286 frames; in the latter case, the frame may be in the midst of
4287 changing its size, and x and y may be off the frame. */
4288 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4291 /* If cursor is off and we want it off, return quickly. */
4292 if (!on
&& f
->phys_cursor_x
< 0)
4295 /* If cursor is currently being shown and we don't want it to be
4296 or it is in the wrong place,
4297 or we want a hollow box and it's not so, (pout!)
4299 if (f
->phys_cursor_x
>= 0
4301 || f
->phys_cursor_x
!= x
4302 || f
->phys_cursor_y
!= y
4303 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4304 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4306 int mouse_face_here
= 0;
4307 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4309 /* If the cursor is in the mouse face area, redisplay that when
4310 we clear the cursor. */
4311 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4313 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4314 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4315 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4317 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4318 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4319 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4320 /* Don't redraw the cursor's spot in mouse face
4321 if it is at the end of a line (on a newline).
4322 The cursor appears there, but mouse highlighting does not. */
4323 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4324 mouse_face_here
= 1;
4326 /* If the font is not as tall as a whole line,
4327 we must explicitly clear the line's whole height. */
4328 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4329 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4330 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4331 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4332 FONT_WIDTH (f
->output_data
.x
->font
),
4333 f
->output_data
.x
->line_height
, False
);
4334 /* Erase the cursor by redrawing the character underneath it. */
4335 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4336 f
->phys_cursor_glyph
,
4339 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4340 f
->phys_cursor_x
= -1;
4343 /* If we want to show a cursor,
4344 or we want a box cursor and it's not so,
4345 write it in the right place. */
4347 && (f
->phys_cursor_x
< 0
4348 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4349 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4351 f
->phys_cursor_glyph
4352 = ((current_glyphs
->enable
[y
]
4353 && x
< current_glyphs
->used
[y
])
4354 ? current_glyphs
->glyphs
[y
][x
]
4356 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4358 x_draw_box (f
, x
, y
);
4359 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4363 x_draw_single_glyph (f
, y
, x
,
4364 f
->phys_cursor_glyph
, 2);
4365 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4368 f
->phys_cursor_x
= x
;
4369 f
->phys_cursor_y
= y
;
4372 if (updating_frame
!= f
)
4373 XFlush (FRAME_X_DISPLAY (f
));
4376 /* Display the cursor on frame F, or clear it, according to ON.
4377 Use the position specified by curs_x and curs_y
4378 if we are doing an update of frame F now.
4379 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4382 x_display_cursor (f
, on
)
4388 /* If we're not updating, then don't change the physical cursor
4389 position. Just change (if appropriate) the style of display. */
4390 if (f
!= updating_frame
)
4392 curs_x
= FRAME_CURSOR_X (f
);
4393 curs_y
= FRAME_CURSOR_Y (f
);
4396 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4397 x_display_box_cursor (f
, on
, curs_x
, curs_y
);
4398 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4399 x_display_bar_cursor (f
, on
, curs_x
, curs_y
);
4401 /* Those are the only two we have implemented! */
4407 /* Display the cursor on frame F, or clear it, according to ON.
4408 Don't change the cursor's position. */
4410 x_update_cursor (f
, on
)
4416 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4417 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4418 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4419 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4421 /* Those are the only two we have implemented! */
4429 /* Refresh bitmap kitchen sink icon for frame F
4430 when we get an expose event for it. */
4435 /* Normally, the window manager handles this function. */
4438 /* Make the x-window of frame F use the gnu icon bitmap. */
4441 x_bitmap_icon (f
, file
)
4445 int mask
, bitmap_id
;
4448 if (FRAME_X_WINDOW (f
) == 0)
4451 /* Free up our existing icon bitmap if any. */
4452 if (f
->output_data
.x
->icon_bitmap
> 0)
4453 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4454 f
->output_data
.x
->icon_bitmap
= 0;
4457 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4460 /* Create the GNU bitmap if necessary. */
4461 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4462 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4463 = x_create_bitmap_from_data (f
, gnu_bits
,
4464 gnu_width
, gnu_height
);
4466 /* The first time we create the GNU bitmap,
4467 this increments the refcount one extra time.
4468 As a result, the GNU bitmap is never freed.
4469 That way, we don't have to worry about allocating it again. */
4470 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4472 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4475 x_wm_set_icon_pixmap (f
, bitmap_id
);
4476 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4482 /* Make the x-window of frame F use a rectangle with text.
4483 Use ICON_NAME as the text. */
4486 x_text_icon (f
, icon_name
)
4490 if (FRAME_X_WINDOW (f
) == 0)
4496 text
.value
= (unsigned char *) icon_name
;
4497 text
.encoding
= XA_STRING
;
4499 text
.nitems
= strlen (icon_name
);
4500 #ifdef USE_X_TOOLKIT
4501 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4503 #else /* not USE_X_TOOLKIT */
4504 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
4505 #endif /* not USE_X_TOOLKIT */
4507 #else /* not HAVE_X11R4 */
4508 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
4509 #endif /* not HAVE_X11R4 */
4511 if (f
->output_data
.x
->icon_bitmap
> 0)
4512 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4513 f
->output_data
.x
->icon_bitmap
= 0;
4514 x_wm_set_icon_pixmap (f
, 0);
4519 /* Handling X errors. */
4521 /* Handle the loss of connection to display DISPLAY. */
4524 x_connection_closed (display
, error_message
)
4526 char *error_message
;
4528 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4529 Lisp_Object frame
, tail
;
4531 /* Whatever we were in the middle of, we are going to throw out of it,
4532 so reassure various things that have error checks about being
4533 called with input blocked. */
4534 TOTALLY_UNBLOCK_INPUT
;
4539 /* First delete frames whose minibuffers are on frames
4540 that are on the dead display. */
4541 FOR_EACH_FRAME (tail
, frame
)
4543 Lisp_Object minibuf_frame
;
4545 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4546 if (FRAME_X_P (XFRAME (frame
))
4547 && FRAME_X_P (XFRAME (minibuf_frame
))
4548 && ! EQ (frame
, minibuf_frame
)
4549 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4550 Fdelete_frame (frame
, Qt
);
4553 /* Now delete all remaining frames on the dead display.
4554 We are now sure none of these is used as the minibuffer
4555 for another frame that we need to delete. */
4556 FOR_EACH_FRAME (tail
, frame
)
4557 if (FRAME_X_P (XFRAME (frame
))
4558 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4560 /* Set this to t so that Fdelete_frame won't get confused
4561 trying to find a replacement. */
4562 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
4563 Fdelete_frame (frame
, Qt
);
4567 x_delete_display (dpyinfo
);
4569 if (x_display_list
== 0)
4571 fprintf (stderr
, "%s", error_message
);
4572 shut_down_emacs (0, 0, Qnil
);
4576 /* Ordinary stack unwind doesn't deal with these. */
4578 sigunblock (sigmask (SIGIO
));
4580 sigunblock (sigmask (SIGALRM
));
4581 TOTALLY_UNBLOCK_INPUT
;
4583 error ("%s", error_message
);
4586 /* This is the usual handler for X protocol errors.
4587 It kills all frames on the display that we got the error for.
4588 If that was the only one, it prints an error message and kills Emacs. */
4591 x_error_quitter (display
, error
)
4595 char buf
[256], buf1
[356];
4597 /* Note that there is no real way portable across R3/R4 to get the
4598 original error handler. */
4600 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4601 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4602 buf
, error
->request_code
);
4603 x_connection_closed (display
, buf1
);
4606 /* This is the handler for X IO errors, always.
4607 It kills all frames on the display that we lost touch with.
4608 If that was the only one, it prints an error message and kills Emacs. */
4611 x_io_error_quitter (display
)
4616 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4617 x_connection_closed (display
, buf
);
4620 /* Handle SIGPIPE, which can happen when the connection to a server
4621 simply goes away. SIGPIPE is handled by x_connection_signal.
4622 It works by sending a no-op command to each X server connection.
4623 When we try a connection that has closed, we get SIGPIPE again.
4624 But this time, it is handled by x_connection_signal_1.
4625 That function knows which connection we were testing,
4626 so it closes that one.
4628 x_connection_closed never returns,
4629 so if more than one connection was lost at once,
4630 we only find one. But XTread_socket keeps trying them all,
4631 so it will notice the other closed one sooner or later. */
4634 static struct x_display_info
*x_connection_signal_dpyinfo
;
4636 static SIGTYPE
x_connection_signal ();
4639 x_connection_signal_1 (signalnum
) /* If we don't have an argument, */
4640 int signalnum
; /* some compilers complain in signal calls. */
4642 signal (SIGPIPE
, x_connection_signal
);
4643 x_connection_closed (x_connection_signal_dpyinfo
,
4644 "connection was lost");
4648 x_connection_signal (signalnum
) /* If we don't have an argument, */
4649 int signalnum
; /* some compilers complain in signal calls. */
4651 x_connection_signal_dpyinfo
= x_display_list
;
4654 sigunblock (SIGPIPE
);
4656 while (x_connection_signal_dpyinfo
)
4658 signal (SIGPIPE
, x_connection_signal_1
);
4659 signal (SIGALRM
, x_connection_signal_1
);
4661 /* According to Jim Campbell <jec@murzim.ca.boeing.com>,
4662 On Solaris 2.4, XNoOp can hang when the connection
4663 has already died. Since XNoOp should not wait,
4664 let's assume that if it hangs for 3 seconds
4665 that means the connection is dead.
4666 This is a kludge, but I don't see any other way that works. */
4668 XNoOp (x_connection_signal_dpyinfo
->display
);
4671 XSync (x_connection_signal_dpyinfo
->display
, False
);
4673 /* Each time we get here, cycle through the displays now open. */
4674 x_connection_signal_dpyinfo
= x_connection_signal_dpyinfo
->next
;
4677 /* We should have found some closed connection. */
4681 /* A buffer for storing X error messages. */
4682 static char *x_caught_error_message
;
4683 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4685 /* An X error handler which stores the error message in
4686 x_caught_error_message. This is what's installed when
4687 x_catch_errors is in effect. */
4690 x_error_catcher (display
, error
)
4694 XGetErrorText (display
, error
->error_code
,
4695 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4699 /* Begin trapping X errors for display DPY. Actually we trap X errors
4700 for all displays, but DPY should be the display you are actually
4703 After calling this function, X protocol errors no longer cause
4704 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4706 Calling x_check_errors signals an Emacs error if an X error has
4707 occurred since the last call to x_catch_errors or x_check_errors.
4709 Calling x_uncatch_errors resumes the normal error handling. */
4711 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4714 x_catch_errors (dpy
)
4717 /* Make sure any errors from previous requests have been dealt with. */
4720 /* Set up the error buffer. */
4721 x_caught_error_message
4722 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4723 x_caught_error_message
[0] = '\0';
4725 /* Install our little error handler. */
4726 XSetErrorHandler (x_error_catcher
);
4729 /* If any X protocol errors have arrived since the last call to
4730 x_catch_errors or x_check_errors, signal an Emacs error using
4731 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4734 x_check_errors (dpy
, format
)
4738 /* Make sure to catch any errors incurred so far. */
4741 if (x_caught_error_message
[0])
4743 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4745 sprintf (buf
, format
, x_caught_error_message
);
4746 x_uncatch_errors (dpy
);
4751 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4754 x_had_errors_p (dpy
)
4757 /* Make sure to catch any errors incurred so far. */
4760 return x_caught_error_message
[0] != 0;
4763 /* Stop catching X protocol errors and let them make Emacs die. */
4766 x_uncatch_errors (dpy
)
4769 xfree (x_caught_error_message
);
4770 x_caught_error_message
= 0;
4771 XSetErrorHandler (x_error_quitter
);
4775 static unsigned int x_wire_count
;
4778 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4783 /* Changing the font of the frame. */
4785 /* Give frame F the font named FONTNAME as its default font, and
4786 return the full name of that font. FONTNAME may be a wildcard
4787 pattern; in that case, we choose some font that fits the pattern.
4788 The return value shows which font we chose. */
4791 x_new_font (f
, fontname
)
4793 register char *fontname
;
4796 int n_matching_fonts
;
4797 XFontStruct
*font_info
;
4800 /* Get a list of all the fonts that match this name. Once we
4801 have a list of matching fonts, we compare them against the fonts
4802 we already have by comparing font ids. */
4803 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4804 1024, &n_matching_fonts
);
4805 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4806 find any matches; font_names == 0 is the only clue. */
4808 n_matching_fonts
= 0;
4810 /* Don't just give up if n_matching_fonts is 0.
4811 Apparently there's a bug on Suns: XListFontsWithInfo can
4812 fail to find a font, but XLoadQueryFont may still find it. */
4814 /* See if we've already loaded a matching font. */
4815 already_loaded
= -1;
4816 if (n_matching_fonts
!= 0)
4820 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4821 for (j
= 0; j
< n_matching_fonts
; j
++)
4822 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4823 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4826 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4832 /* If we have, just return it from the table. */
4833 if (already_loaded
>= 0)
4834 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4835 /* Otherwise, load the font and add it to the table. */
4843 /* Try to find a character-cell font in the list. */
4845 /* A laudable goal, but this isn't how to do it. */
4846 for (i
= 0; i
< n_matching_fonts
; i
++)
4847 if (! font_info
[i
].per_char
)
4853 /* See comment above. */
4854 if (n_matching_fonts
!= 0)
4855 fontname
= font_names
[i
];
4857 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4860 /* Free the information from XListFonts. */
4861 if (n_matching_fonts
)
4862 XFreeFontNames (font_names
);
4866 /* Do we need to create the table? */
4867 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4869 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4870 FRAME_X_DISPLAY_INFO (f
)->font_table
4871 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4872 * sizeof (struct font_info
));
4874 /* Do we need to grow the table? */
4875 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4876 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4878 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4879 FRAME_X_DISPLAY_INFO (f
)->font_table
4880 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4881 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4882 * sizeof (struct font_info
)));
4885 /* Try to get the full name of FONT. Put it in full_name. */
4887 for (i
= 0; i
< font
->n_properties
; i
++)
4890 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4891 if (!strcmp (atom
, "FONT"))
4893 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4894 (Atom
) (font
->properties
[i
].card32
));
4898 /* Count the number of dashes in the "full name".
4899 If it is too few, this isn't really the font's full name,
4901 In X11R4, the fonts did not come with their canonical names
4919 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4920 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4921 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4923 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4925 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4926 f
->output_data
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4927 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4930 fontname
= full_name
;
4933 /* Compute the scroll bar width in character columns. */
4934 if (f
->scroll_bar_pixel_width
> 0)
4936 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
4937 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4940 f
->scroll_bar_cols
= 2;
4942 /* Now make the frame display the given font. */
4943 if (FRAME_X_WINDOW (f
) != 0)
4945 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
4946 f
->output_data
.x
->font
->fid
);
4947 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
4948 f
->output_data
.x
->font
->fid
);
4949 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
4950 f
->output_data
.x
->font
->fid
);
4952 frame_update_line_height (f
);
4953 x_set_window_size (f
, 0, f
->width
, f
->height
);
4956 /* If we are setting a new frame's font for the first time,
4957 there are no faces yet, so this font's height is the line height. */
4958 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
4961 Lisp_Object lispy_name
;
4963 lispy_name
= build_string (fontname
);
4965 /* Free the information from XListFonts. The data
4966 we actually retain comes from XLoadQueryFont. */
4967 XFreeFontNames (font_names
);
4973 x_calc_absolute_position (f
)
4977 int win_x
= 0, win_y
= 0;
4978 int flags
= f
->output_data
.x
->size_hint_flags
;
4981 #ifdef USE_X_TOOLKIT
4982 this_window
= XtWindow (f
->output_data
.x
->widget
);
4984 this_window
= FRAME_X_WINDOW (f
);
4987 /* Find the position of the outside upper-left corner of
4988 the inner window, with respect to the outer window. */
4989 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4992 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4994 /* From-window, to-window. */
4996 f
->output_data
.x
->parent_desc
,
4998 /* From-position, to-position. */
4999 0, 0, &win_x
, &win_y
,
5006 /* Treat negative positions as relative to the leftmost bottommost
5007 position that fits on the screen. */
5008 if (flags
& XNegative
)
5009 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
5010 - 2 * f
->output_data
.x
->border_width
- win_x
5012 + f
->output_data
.x
->left_pos
);
5014 if (flags
& YNegative
)
5015 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
5016 - 2 * f
->output_data
.x
->border_width
- win_y
5018 - (FRAME_EXTERNAL_MENU_BAR (f
)
5019 ? f
->output_data
.x
->menubar_height
: 0)
5020 + f
->output_data
.x
->top_pos
);
5021 /* The left_pos and top_pos
5022 are now relative to the top and left screen edges,
5023 so the flags should correspond. */
5024 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5027 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5028 to really change the position, and 0 when calling from
5029 x_make_frame_visible (in that case, XOFF and YOFF are the current
5030 position values). It is -1 when calling from x_set_frame_parameters,
5031 which means, do adjust for borders but don't change the gravity. */
5033 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5035 register int xoff
, yoff
;
5038 int modified_top
, modified_left
;
5040 if (change_gravity
> 0)
5042 f
->output_data
.x
->top_pos
= yoff
;
5043 f
->output_data
.x
->left_pos
= xoff
;
5044 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5046 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5048 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5049 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5051 x_calc_absolute_position (f
);
5054 x_wm_set_size_hint (f
, (long) 0, 0);
5056 /* It is a mystery why we need to add the border_width here
5057 when the frame is already visible, but experiment says we do. */
5058 modified_left
= f
->output_data
.x
->left_pos
;
5059 modified_top
= f
->output_data
.x
->top_pos
;
5060 if (change_gravity
!= 0)
5062 modified_left
+= f
->output_data
.x
->border_width
;
5063 modified_top
+= f
->output_data
.x
->border_width
;
5066 #ifdef USE_X_TOOLKIT
5067 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5068 modified_left
, modified_top
);
5069 #else /* not USE_X_TOOLKIT */
5070 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5071 modified_left
, modified_top
);
5072 #endif /* not USE_X_TOOLKIT */
5076 /* Call this to change the size of frame F's x-window.
5077 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5078 for this size change and subsequent size changes.
5079 Otherwise we leave the window gravity unchanged. */
5081 x_set_window_size (f
, change_gravity
, cols
, rows
)
5086 int pixelwidth
, pixelheight
;
5089 #ifdef USE_X_TOOLKIT
5092 /* The x and y position of the widget is clobbered by the
5093 call to XtSetValues within EmacsFrameSetCharSize.
5094 This is a real kludge, but I don't understand Xt so I can't
5095 figure out a correct fix. Can anyone else tell me? -- rms. */
5096 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5097 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5098 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5099 f
->output_data
.x
->widget
->core
.x
= xpos
;
5100 f
->output_data
.x
->widget
->core
.y
= ypos
;
5104 #else /* not USE_X_TOOLKIT */
5108 check_frame_size (f
, &rows
, &cols
);
5109 f
->output_data
.x
->vertical_scroll_bar_extra
5110 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5112 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5113 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5114 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5115 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5116 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5118 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5119 x_wm_set_size_hint (f
, (long) 0, 0);
5121 XSync (FRAME_X_DISPLAY (f
), False
);
5122 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5123 pixelwidth
, pixelheight
);
5125 /* Now, strictly speaking, we can't be sure that this is accurate,
5126 but the window manager will get around to dealing with the size
5127 change request eventually, and we'll hear how it went when the
5128 ConfigureNotify event gets here.
5130 We could just not bother storing any of this information here,
5131 and let the ConfigureNotify event set everything up, but that
5132 might be kind of confusing to the lisp code, since size changes
5133 wouldn't be reported in the frame parameters until some random
5134 point in the future when the ConfigureNotify event arrives. */
5135 change_frame_size (f
, rows
, cols
, 0, 0);
5136 PIXEL_WIDTH (f
) = pixelwidth
;
5137 PIXEL_HEIGHT (f
) = pixelheight
;
5139 /* If cursor was outside the new size, mark it as off. */
5140 if (f
->phys_cursor_y
>= rows
5141 || f
->phys_cursor_x
>= cols
)
5143 f
->phys_cursor_x
= -1;
5144 f
->phys_cursor_y
= -1;
5147 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5148 receive in the ConfigureNotify event; if we get what we asked
5149 for, then the event won't cause the screen to become garbaged, so
5150 we have to make sure to do it here. */
5151 SET_FRAME_GARBAGED (f
);
5153 XFlush (FRAME_X_DISPLAY (f
));
5155 #endif /* not USE_X_TOOLKIT */
5158 /* Mouse warping. */
5161 x_set_mouse_position (f
, x
, y
)
5167 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5168 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5170 if (pix_x
< 0) pix_x
= 0;
5171 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5173 if (pix_y
< 0) pix_y
= 0;
5174 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5178 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5179 0, 0, 0, 0, pix_x
, pix_y
);
5183 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5186 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5192 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5193 0, 0, 0, 0, pix_x
, pix_y
);
5197 /* focus shifting, raising and lowering. */
5199 x_focus_on_frame (f
)
5202 #if 0 /* This proves to be unpleasant. */
5206 /* I don't think that the ICCCM allows programs to do things like this
5207 without the interaction of the window manager. Whatever you end up
5208 doing with this code, do it to x_unfocus_frame too. */
5209 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5210 RevertToPointerRoot
, CurrentTime
);
5218 /* Look at the remarks in x_focus_on_frame. */
5219 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5220 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5221 RevertToPointerRoot
, CurrentTime
);
5225 /* Raise frame F. */
5230 if (f
->async_visible
)
5233 #ifdef USE_X_TOOLKIT
5234 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5235 #else /* not USE_X_TOOLKIT */
5236 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5237 #endif /* not USE_X_TOOLKIT */
5238 XFlush (FRAME_X_DISPLAY (f
));
5243 /* Lower frame F. */
5248 if (f
->async_visible
)
5251 #ifdef USE_X_TOOLKIT
5252 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5253 #else /* not USE_X_TOOLKIT */
5254 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5255 #endif /* not USE_X_TOOLKIT */
5256 XFlush (FRAME_X_DISPLAY (f
));
5262 XTframe_raise_lower (f
, raise
)
5272 /* Change of visibility. */
5274 /* This tries to wait until the frame is really visible.
5275 However, if the window manager asks the user where to position
5276 the frame, this will return before the user finishes doing that.
5277 The frame will not actually be visible at that time,
5278 but it will become visible later when the window manager
5279 finishes with it. */
5281 x_make_frame_visible (f
)
5289 type
= x_icon_type (f
);
5291 x_bitmap_icon (f
, type
);
5293 if (! FRAME_VISIBLE_P (f
))
5295 /* We test FRAME_GARBAGED_P here to make sure we don't
5296 call x_set_offset a second time
5297 if we get to x_make_frame_visible a second time
5298 before the window gets really visible. */
5299 if (! FRAME_ICONIFIED_P (f
)
5300 && ! f
->output_data
.x
->asked_for_visible
)
5301 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5303 f
->output_data
.x
->asked_for_visible
= 1;
5305 if (! EQ (Vx_no_window_manager
, Qt
))
5306 x_wm_set_window_state (f
, NormalState
);
5307 #ifdef USE_X_TOOLKIT
5308 /* This was XtPopup, but that did nothing for an iconified frame. */
5309 XtMapWidget (f
->output_data
.x
->widget
);
5310 #else /* not USE_X_TOOLKIT */
5311 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5312 #endif /* not USE_X_TOOLKIT */
5313 #if 0 /* This seems to bring back scroll bars in the wrong places
5314 if the window configuration has changed. They seem
5315 to come back ok without this. */
5316 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5317 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5321 XFlush (FRAME_X_DISPLAY (f
));
5323 /* Synchronize to ensure Emacs knows the frame is visible
5324 before we do anything else. We do this loop with input not blocked
5325 so that incoming events are handled. */
5328 int count
= input_signal_count
;
5330 /* This must come after we set COUNT. */
5333 XSETFRAME (frame
, f
);
5338 /* Once we have handled input events,
5339 we should have received the MapNotify if one is coming.
5340 So if we have not got it yet, stop looping.
5341 Some window managers make their own decisions
5342 about visibility. */
5343 if (input_signal_count
!= count
)
5345 /* Machines that do polling rather than SIGIO have been observed
5346 to go into a busy-wait here. So we'll fake an alarm signal
5347 to let the handler know that there's something to be read.
5348 We used to raise a real alarm, but it seems that the handler
5349 isn't always enabled here. This is probably a bug. */
5350 if (input_polling_used ())
5352 /* It could be confusing if a real alarm arrives while processing
5353 the fake one. Turn it off and let the handler reset it. */
5355 input_poll_signal ();
5357 /* Once we have handled input events,
5358 we should have received the MapNotify if one is coming.
5359 So if we have not got it yet, stop looping.
5360 Some window managers make their own decisions
5361 about visibility. */
5362 if (input_signal_count
!= count
)
5365 FRAME_SAMPLE_VISIBILITY (f
);
5369 /* Change from mapped state to withdrawn state. */
5371 /* Make the frame visible (mapped and not iconified). */
5373 x_make_frame_invisible (f
)
5379 #ifdef USE_X_TOOLKIT
5380 /* Use the frame's outermost window, not the one we normally draw on. */
5381 window
= XtWindow (f
->output_data
.x
->widget
);
5382 #else /* not USE_X_TOOLKIT */
5383 window
= FRAME_X_WINDOW (f
);
5384 #endif /* not USE_X_TOOLKIT */
5386 /* Don't keep the highlight on an invisible frame. */
5387 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5388 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5390 #if 0/* This might add unreliability; I don't trust it -- rms. */
5391 if (! f
->async_visible
&& ! f
->async_iconified
)
5397 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5398 that the current position of the window is user-specified, rather than
5399 program-specified, so that when the window is mapped again, it will be
5400 placed at the same location, without forcing the user to position it
5401 by hand again (they have already done that once for this window.) */
5402 x_wm_set_size_hint (f
, (long) 0, 1);
5406 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5407 DefaultScreen (FRAME_X_DISPLAY (f
))))
5409 UNBLOCK_INPUT_RESIGNAL
;
5410 error ("Can't notify window manager of window withdrawal");
5412 #else /* ! defined (HAVE_X11R4) */
5414 /* Tell the window manager what we're going to do. */
5415 if (! EQ (Vx_no_window_manager
, Qt
))
5419 unmap
.xunmap
.type
= UnmapNotify
;
5420 unmap
.xunmap
.window
= window
;
5421 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5422 unmap
.xunmap
.from_configure
= False
;
5423 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5424 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5426 SubstructureRedirectMask
|SubstructureNotifyMask
,
5429 UNBLOCK_INPUT_RESIGNAL
;
5430 error ("Can't notify window manager of withdrawal");
5434 /* Unmap the window ourselves. Cheeky! */
5435 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5436 #endif /* ! defined (HAVE_X11R4) */
5438 /* We can't distinguish this from iconification
5439 just by the event that we get from the server.
5440 So we can't win using the usual strategy of letting
5441 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5442 and synchronize with the server to make sure we agree. */
5444 FRAME_ICONIFIED_P (f
) = 0;
5445 f
->async_visible
= 0;
5446 f
->async_iconified
= 0;
5453 /* Change window state from mapped to iconified. */
5462 /* Don't keep the highlight on an invisible frame. */
5463 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5464 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5466 if (f
->async_iconified
)
5471 FRAME_SAMPLE_VISIBILITY (f
);
5473 type
= x_icon_type (f
);
5475 x_bitmap_icon (f
, type
);
5477 #ifdef USE_X_TOOLKIT
5479 if (! FRAME_VISIBLE_P (f
))
5481 if (! EQ (Vx_no_window_manager
, Qt
))
5482 x_wm_set_window_state (f
, IconicState
);
5483 /* This was XtPopup, but that did nothing for an iconified frame. */
5484 XtMapWidget (f
->output_data
.x
->widget
);
5489 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5490 XtWindow (f
->output_data
.x
->widget
),
5491 DefaultScreen (FRAME_X_DISPLAY (f
)));
5495 error ("Can't notify window manager of iconification");
5497 f
->async_iconified
= 1;
5500 XFlush (FRAME_X_DISPLAY (f
));
5502 #else /* not USE_X_TOOLKIT */
5504 /* Make sure the X server knows where the window should be positioned,
5505 in case the user deiconifies with the window manager. */
5506 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5507 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5509 /* Since we don't know which revision of X we're running, we'll use both
5510 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5512 /* X11R4: send a ClientMessage to the window manager using the
5513 WM_CHANGE_STATE type. */
5517 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5518 message
.xclient
.type
= ClientMessage
;
5519 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5520 message
.xclient
.format
= 32;
5521 message
.xclient
.data
.l
[0] = IconicState
;
5523 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5524 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5526 SubstructureRedirectMask
| SubstructureNotifyMask
,
5529 UNBLOCK_INPUT_RESIGNAL
;
5530 error ("Can't notify window manager of iconification");
5534 /* X11R3: set the initial_state field of the window manager hints to
5536 x_wm_set_window_state (f
, IconicState
);
5538 if (!FRAME_VISIBLE_P (f
))
5540 /* If the frame was withdrawn, before, we must map it. */
5541 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5544 f
->async_iconified
= 1;
5546 XFlush (FRAME_X_DISPLAY (f
));
5548 #endif /* not USE_X_TOOLKIT */
5551 /* Destroy the X window of frame F. */
5553 x_destroy_window (f
)
5556 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5560 if (f
->output_data
.x
->icon_desc
!= 0)
5561 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
5562 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
5563 #ifdef USE_X_TOOLKIT
5564 XtDestroyWidget (f
->output_data
.x
->widget
);
5565 free_frame_menubar (f
);
5566 #endif /* USE_X_TOOLKIT */
5568 free_frame_faces (f
);
5569 XFlush (FRAME_X_DISPLAY (f
));
5571 xfree (f
->output_data
.x
);
5572 f
->output_data
.x
= 0;
5573 if (f
== dpyinfo
->x_focus_frame
)
5574 dpyinfo
->x_focus_frame
= 0;
5575 if (f
== dpyinfo
->x_focus_event_frame
)
5576 dpyinfo
->x_focus_event_frame
= 0;
5577 if (f
== dpyinfo
->x_highlight_frame
)
5578 dpyinfo
->x_highlight_frame
= 0;
5580 dpyinfo
->reference_count
--;
5582 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5584 dpyinfo
->mouse_face_beg_row
5585 = dpyinfo
->mouse_face_beg_col
= -1;
5586 dpyinfo
->mouse_face_end_row
5587 = dpyinfo
->mouse_face_end_col
= -1;
5588 dpyinfo
->mouse_face_window
= Qnil
;
5594 /* Setting window manager hints. */
5596 /* Set the normal size hints for the window manager, for frame F.
5597 FLAGS is the flags word to use--or 0 meaning preserve the flags
5598 that the window now has.
5599 If USER_POSITION is nonzero, we set the USPosition
5600 flag (this is useful when FLAGS is 0). */
5602 x_wm_set_size_hint (f
, flags
, user_position
)
5607 XSizeHints size_hints
;
5609 #ifdef USE_X_TOOLKIT
5612 Dimension widget_width
, widget_height
;
5613 Window window
= XtWindow (f
->output_data
.x
->widget
);
5614 #else /* not USE_X_TOOLKIT */
5615 Window window
= FRAME_X_WINDOW (f
);
5616 #endif /* not USE_X_TOOLKIT */
5618 /* Setting PMaxSize caused various problems. */
5619 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5621 flexlines
= f
->height
;
5623 size_hints
.x
= f
->output_data
.x
->left_pos
;
5624 size_hints
.y
= f
->output_data
.x
->top_pos
;
5626 #ifdef USE_X_TOOLKIT
5627 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5628 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5629 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5630 size_hints
.height
= widget_height
;
5631 size_hints
.width
= widget_width
;
5632 #else /* not USE_X_TOOLKIT */
5633 size_hints
.height
= PIXEL_HEIGHT (f
);
5634 size_hints
.width
= PIXEL_WIDTH (f
);
5635 #endif /* not USE_X_TOOLKIT */
5637 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
5638 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
5639 size_hints
.max_width
5640 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5641 size_hints
.max_height
5642 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5644 /* Calculate the base and minimum sizes.
5646 (When we use the X toolkit, we don't do it here.
5647 Instead we copy the values that the widgets are using, below.) */
5648 #ifndef USE_X_TOOLKIT
5650 int base_width
, base_height
;
5651 int min_rows
= 0, min_cols
= 0;
5653 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5654 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5656 check_frame_size (f
, &min_rows
, &min_cols
);
5658 /* The window manager uses the base width hints to calculate the
5659 current number of rows and columns in the frame while
5660 resizing; min_width and min_height aren't useful for this
5661 purpose, since they might not give the dimensions for a
5662 zero-row, zero-column frame.
5664 We use the base_width and base_height members if we have
5665 them; otherwise, we set the min_width and min_height members
5666 to the size for a zero x zero frame. */
5669 size_hints
.flags
|= PBaseSize
;
5670 size_hints
.base_width
= base_width
;
5671 size_hints
.base_height
= base_height
;
5672 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5673 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5675 size_hints
.min_width
= base_width
;
5676 size_hints
.min_height
= base_height
;
5680 /* If we don't need the old flags, we don't need the old hint at all. */
5683 size_hints
.flags
|= flags
;
5686 #endif /* not USE_X_TOOLKIT */
5689 XSizeHints hints
; /* Sometimes I hate X Windows... */
5690 long supplied_return
;
5694 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5697 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5700 #ifdef USE_X_TOOLKIT
5701 size_hints
.base_height
= hints
.base_height
;
5702 size_hints
.base_width
= hints
.base_width
;
5703 size_hints
.min_height
= hints
.min_height
;
5704 size_hints
.min_width
= hints
.min_width
;
5708 size_hints
.flags
|= flags
;
5713 if (hints
.flags
& PSize
)
5714 size_hints
.flags
|= PSize
;
5715 if (hints
.flags
& PPosition
)
5716 size_hints
.flags
|= PPosition
;
5717 if (hints
.flags
& USPosition
)
5718 size_hints
.flags
|= USPosition
;
5719 if (hints
.flags
& USSize
)
5720 size_hints
.flags
|= USSize
;
5727 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
5728 size_hints
.flags
|= PWinGravity
;
5732 size_hints
.flags
&= ~ PPosition
;
5733 size_hints
.flags
|= USPosition
;
5735 #endif /* PWinGravity */
5738 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5740 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5744 /* Used for IconicState or NormalState */
5745 x_wm_set_window_state (f
, state
)
5749 #ifdef USE_X_TOOLKIT
5752 XtSetArg (al
[0], XtNinitialState
, state
);
5753 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5754 #else /* not USE_X_TOOLKIT */
5755 Window window
= FRAME_X_WINDOW (f
);
5757 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5758 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5760 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5761 #endif /* not USE_X_TOOLKIT */
5764 x_wm_set_icon_pixmap (f
, pixmap_id
)
5768 #ifdef USE_X_TOOLKIT
5769 Window window
= XtWindow (f
->output_data
.x
->widget
);
5771 Window window
= FRAME_X_WINDOW (f
);
5776 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5777 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5781 /* It seems there is no way to turn off use of an icon pixmap.
5782 The following line does it, only if no icon has yet been created,
5783 for some window managers. But with mwm it crashes.
5784 Some people say it should clear the IconPixmapHint bit in this case,
5785 but that doesn't work, and the X consortium said it isn't the
5786 right thing at all. Since there is no way to win,
5787 best to explicitly give up. */
5789 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5795 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5796 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5799 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5803 #ifdef USE_X_TOOLKIT
5804 Window window
= XtWindow (f
->output_data
.x
->widget
);
5806 Window window
= FRAME_X_WINDOW (f
);
5809 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5810 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5811 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5813 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5817 /* Initialization. */
5819 #ifdef USE_X_TOOLKIT
5820 static XrmOptionDescRec emacs_options
[] = {
5821 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5822 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5824 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5825 XrmoptionSepArg
, NULL
},
5826 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5828 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5829 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5830 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5831 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5832 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5833 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5834 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5836 #endif /* USE_X_TOOLKIT */
5838 static int x_initialized
;
5841 /* Test whether two display-name strings agree up to the dot that separates
5842 the screen number from the server number. */
5844 same_x_server (name1
, name2
)
5845 char *name1
, *name2
;
5848 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5852 if (seen_colon
&& *name1
== '.')
5856 && (*name1
== '.' || *name1
== '\0')
5857 && (*name2
== '.' || *name2
== '\0'));
5861 struct x_display_info
*
5862 x_term_init (display_name
, xrm_option
, resource_name
)
5863 Lisp_Object display_name
;
5865 char *resource_name
;
5871 struct x_display_info
*dpyinfo
;
5883 setlocale (LC_ALL
, NULL
);
5886 #ifdef USE_X_TOOLKIT
5887 /* weiner@footloose.sps.mot.com reports that this causes
5889 X protocol error: BadAtom (invalid Atom parameter)
5890 on protocol request 18skiloaf.
5891 So let's not use it until R6. */
5893 XtSetLanguageProc (NULL
, NULL
, NULL
);
5904 argv
[argc
++] = "-xrm";
5905 argv
[argc
++] = xrm_option
;
5907 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5908 resource_name
, EMACS_CLASS
,
5909 emacs_options
, XtNumber (emacs_options
),
5913 setlocale (LC_NUMERIC
, "C");
5914 setlocale (LC_TIME
, "C");
5918 #else /* not USE_X_TOOLKIT */
5920 XSetLocaleModifiers ("");
5922 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5923 #endif /* not USE_X_TOOLKIT */
5925 /* Detect failure. */
5932 /* We have definitely succeeded. Record the new connection. */
5934 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5938 struct x_display_info
*share
;
5941 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5942 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5943 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5944 XSTRING (display_name
)->data
))
5947 dpyinfo
->kboard
= share
->kboard
;
5950 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5951 init_kboard (dpyinfo
->kboard
);
5952 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
5954 char *vendor
= ServerVendor (dpy
);
5955 dpyinfo
->kboard
->Vsystem_key_alist
5956 = call1 (Qvendor_specific_keysyms
,
5957 build_string (vendor
? vendor
: ""));
5960 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5961 all_kboards
= dpyinfo
->kboard
;
5962 /* Don't let the initial kboard remain current longer than necessary.
5963 That would cause problems if a file loaded on startup tries to
5964 prompt in the minibuffer. */
5965 if (current_kboard
== initial_kboard
)
5966 current_kboard
= dpyinfo
->kboard
;
5968 dpyinfo
->kboard
->reference_count
++;
5972 /* Put this display on the chain. */
5973 dpyinfo
->next
= x_display_list
;
5974 x_display_list
= dpyinfo
;
5976 /* Put it on x_display_name_list as well, to keep them parallel. */
5977 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5978 x_display_name_list
);
5979 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5981 dpyinfo
->display
= dpy
;
5984 XSetAfterFunction (x_current_display
, x_trace_wire
);
5988 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5989 + XSTRING (Vsystem_name
)->size
5991 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5992 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5994 /* Figure out which modifier bits mean what. */
5995 x_find_modifier_meanings (dpyinfo
);
5997 /* Get the scroll bar cursor. */
5998 dpyinfo
->vertical_scroll_bar_cursor
5999 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
6001 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
6002 resource_name
, EMACS_CLASS
);
6003 #ifdef HAVE_XRMSETDATABASE
6004 XrmSetDatabase (dpyinfo
->display
, xrdb
);
6006 dpyinfo
->display
->db
= xrdb
;
6008 /* Put the rdb where we can find it in a way that works on
6010 dpyinfo
->xrdb
= xrdb
;
6012 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
6013 DefaultScreen (dpyinfo
->display
));
6014 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
6015 &dpyinfo
->n_planes
);
6016 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
6017 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
6018 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
6019 dpyinfo
->grabbed
= 0;
6020 dpyinfo
->reference_count
= 0;
6021 dpyinfo
->icon_bitmap_id
= -1;
6022 dpyinfo
->n_fonts
= 0;
6023 dpyinfo
->font_table_size
= 0;
6024 dpyinfo
->bitmaps
= 0;
6025 dpyinfo
->bitmaps_size
= 0;
6026 dpyinfo
->bitmaps_last
= 0;
6027 dpyinfo
->scratch_cursor_gc
= 0;
6028 dpyinfo
->mouse_face_mouse_frame
= 0;
6029 dpyinfo
->mouse_face_deferred_gc
= 0;
6030 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6031 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6032 dpyinfo
->mouse_face_face_id
= 0;
6033 dpyinfo
->mouse_face_window
= Qnil
;
6034 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
6035 dpyinfo
->mouse_face_defer
= 0;
6036 dpyinfo
->x_focus_frame
= 0;
6037 dpyinfo
->x_focus_event_frame
= 0;
6038 dpyinfo
->x_highlight_frame
= 0;
6040 dpyinfo
->Xatom_wm_protocols
6041 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
6042 dpyinfo
->Xatom_wm_take_focus
6043 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
6044 dpyinfo
->Xatom_wm_save_yourself
6045 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
6046 dpyinfo
->Xatom_wm_delete_window
6047 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
6048 dpyinfo
->Xatom_wm_change_state
6049 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
6050 dpyinfo
->Xatom_wm_configure_denied
6051 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
6052 dpyinfo
->Xatom_wm_window_moved
6053 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
6054 dpyinfo
->Xatom_editres
6055 = XInternAtom (dpyinfo
->display
, "Editres", False
);
6056 dpyinfo
->Xatom_CLIPBOARD
6057 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
6058 dpyinfo
->Xatom_TIMESTAMP
6059 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
6061 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
6062 dpyinfo
->Xatom_DELETE
6063 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
6064 dpyinfo
->Xatom_MULTIPLE
6065 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
6067 = XInternAtom (dpyinfo
->display
, "INCR", False
);
6068 dpyinfo
->Xatom_EMACS_TMP
6069 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
6070 dpyinfo
->Xatom_TARGETS
6071 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
6073 = XInternAtom (dpyinfo
->display
, "NULL", False
);
6074 dpyinfo
->Xatom_ATOM_PAIR
6075 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
6077 dpyinfo
->cut_buffers_initialized
= 0;
6079 connection
= ConnectionNumber (dpyinfo
->display
);
6080 dpyinfo
->connection
= connection
;
6083 /* This is only needed for distinguishing keyboard and process input. */
6084 if (connection
!= 0)
6085 add_keyboard_wait_descriptor (connection
);
6088 #ifndef F_SETOWN_BUG
6090 #ifdef F_SETOWN_SOCK_NEG
6091 /* stdin is a socket here */
6092 fcntl (connection
, F_SETOWN
, -getpid ());
6093 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6094 fcntl (connection
, F_SETOWN
, getpid ());
6095 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6096 #endif /* ! defined (F_SETOWN) */
6097 #endif /* F_SETOWN_BUG */
6100 if (interrupt_input
)
6101 init_sigio (connection
);
6102 #endif /* ! defined (SIGIO) */
6109 /* Get rid of display DPYINFO, assuming all frames are already gone,
6110 and without sending any more commands to the X server. */
6113 x_delete_display (dpyinfo
)
6114 struct x_display_info
*dpyinfo
;
6116 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
6118 /* Discard this display from x_display_name_list and x_display_list.
6119 We can't use Fdelq because that can quit. */
6120 if (! NILP (x_display_name_list
)
6121 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
6122 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
6127 tail
= x_display_name_list
;
6128 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
6130 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
6131 dpyinfo
->name_list_element
))
6133 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
6136 tail
= XCONS (tail
)->cdr
;
6140 if (x_display_list
== dpyinfo
)
6141 x_display_list
= dpyinfo
->next
;
6144 struct x_display_info
*tail
;
6146 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
6147 if (tail
->next
== dpyinfo
)
6148 tail
->next
= tail
->next
->next
;
6151 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6152 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6153 XrmDestroyDatabase (dpyinfo
->xrdb
);
6157 if (--dpyinfo
->kboard
->reference_count
== 0)
6158 delete_kboard (dpyinfo
->kboard
);
6160 xfree (dpyinfo
->font_table
);
6161 xfree (dpyinfo
->x_id_name
);
6165 /* Set up use of X before we make the first connection. */
6169 clear_frame_hook
= XTclear_frame
;
6170 clear_end_of_line_hook
= XTclear_end_of_line
;
6171 ins_del_lines_hook
= XTins_del_lines
;
6172 change_line_highlight_hook
= XTchange_line_highlight
;
6173 insert_glyphs_hook
= XTinsert_glyphs
;
6174 write_glyphs_hook
= XTwrite_glyphs
;
6175 delete_glyphs_hook
= XTdelete_glyphs
;
6176 ring_bell_hook
= XTring_bell
;
6177 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6178 set_terminal_modes_hook
= XTset_terminal_modes
;
6179 update_begin_hook
= XTupdate_begin
;
6180 update_end_hook
= XTupdate_end
;
6181 set_terminal_window_hook
= XTset_terminal_window
;
6182 read_socket_hook
= XTread_socket
;
6183 frame_up_to_date_hook
= XTframe_up_to_date
;
6184 cursor_to_hook
= XTcursor_to
;
6185 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6186 mouse_position_hook
= XTmouse_position
;
6187 frame_rehighlight_hook
= XTframe_rehighlight
;
6188 frame_raise_lower_hook
= XTframe_raise_lower
;
6189 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6190 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6191 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6192 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6194 scroll_region_ok
= 1; /* we'll scroll partial frames */
6195 char_ins_del_ok
= 0; /* just as fast to write the line */
6196 line_ins_del_ok
= 1; /* we'll just blt 'em */
6197 fast_clear_end_of_line
= 1; /* X does this well */
6198 memory_below_frame
= 0; /* we don't remember what scrolls
6204 /* Try to use interrupt input; if we can't, then start polling. */
6205 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6207 #ifdef USE_X_TOOLKIT
6208 XtToolkitInitialize ();
6209 Xt_app_con
= XtCreateApplicationContext ();
6210 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
6213 /* Note that there is no real way portable across R3/R4 to get the
6214 original error handler. */
6215 XSetErrorHandler (x_error_quitter
);
6216 XSetIOErrorHandler (x_io_error_quitter
);
6218 /* Disable Window Change signals; they are handled by X events. */
6220 signal (SIGWINCH
, SIG_DFL
);
6221 #endif /* ! defined (SIGWINCH) */
6223 signal (SIGPIPE
, x_connection_signal
);
6229 staticpro (&x_display_name_list
);
6230 x_display_name_list
= Qnil
;
6232 staticpro (&last_mouse_scroll_bar
);
6233 last_mouse_scroll_bar
= Qnil
;
6235 staticpro (&Qvendor_specific_keysyms
);
6236 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6238 #endif /* ! defined (HAVE_X_WINDOWS) */