1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Xt features made by Fred Pierresteguy. */
23 /* On 4.3 these lose if they come after xterm.h. */
24 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
25 /* Putting these at the beginning seems to be standard for other .c files. */
32 /* Need syssignal.h for various externs and definitions that may be required
33 by some configurations for calls to signal later in this source file. */
34 #include "syssignal.h"
39 #include "blockinput.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
44 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
55 #include <sys/ioctl.h>
56 #endif /* ! defined (BSD_SYSTEM) */
61 #ifndef INCLUDED_FCNTL
68 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
69 /* #include <sys/param.h> */
75 #include "dispextern.h"
76 #include "termhooks.h"
88 #include "intervals.h"
91 #include <X11/Shell.h>
95 extern void free_frame_menubar ();
96 extern FRAME_PTR
x_menubar_window_to_frame ();
97 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
99 extern void _XEditResCheckMessages ();
100 #endif /* not NO_EDITRES */
101 #endif /* USE_X_TOOLKIT */
103 #ifndef USE_X_TOOLKIT
104 #define x_any_window_to_frame x_window_to_frame
105 #define x_top_window_to_frame x_window_to_frame
110 #ifndef XtNinitialState
111 #define XtNinitialState "initialState"
115 #ifdef HAVE_SETLOCALE
116 /* So we can do setlocale. */
121 /* memmove will be defined as a macro in Xfuncs.h unless
122 <string.h> is included beforehand. The declaration for memmove in
123 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
128 #define min(a,b) ((a)<(b) ? (a) : (b))
131 #define max(a,b) ((a)>(b) ? (a) : (b))
134 /* This is a chain of structures for all the X displays currently in use. */
135 struct x_display_info
*x_display_list
;
137 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
138 one for each element of x_display_list and in the same order.
139 NAME is the name of the frame.
140 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
141 Lisp_Object x_display_name_list
;
143 /* Frame being updated by update_frame. This is declared in term.c.
144 This is set by update_begin and looked at by all the
145 XT functions. It is zero while not inside an update.
146 In that case, the XT functions assume that `selected_frame'
147 is the frame to apply to. */
148 extern struct frame
*updating_frame
;
150 extern waiting_for_input
;
152 /* This is a frame waiting to be autoraised, within XTread_socket. */
153 struct frame
*pending_autoraise_frame
;
156 /* The application context for Xt use. */
157 XtAppContext Xt_app_con
;
159 static String Xt_default_resources
[] =
165 /* During an update, maximum vpos for ins/del line operations to affect. */
167 static int flexlines
;
169 /* During an update, nonzero if chars output now should be highlighted. */
171 static int highlight
;
173 /* Nominal cursor position -- where to draw output.
174 During an update, these are different from the cursor-box position. */
181 Formerly, we used PointerMotionHintMask (in STANDARD_EVENT_MASK)
182 so that we would have to call XQueryPointer after each MotionNotify
183 event to ask for another such event. However, this made mouse tracking
184 slow, and there was a bug that made it eventually stop.
186 Simply asking for MotionNotify all the time seems to work better.
188 In order to avoid asking for motion events and then throwing most
189 of them away or busy-polling the server for mouse positions, we ask
190 the server for pointer motion hints. This means that we get only
191 one event per group of mouse movements. "Groups" are delimited by
192 other kinds of events (focus changes and button clicks, for
193 example), or by XQueryPointer calls; when one of these happens, we
194 get another MotionNotify event the next time the mouse moves. This
195 is at least as efficient as getting motion events when mouse
196 tracking is on, and I suspect only negligibly worse when tracking
199 /* Where the mouse was last time we reported a mouse event. */
200 static FRAME_PTR last_mouse_frame
;
201 static XRectangle last_mouse_glyph
;
203 static Lisp_Object last_mouse_press_frame
;
205 /* The scroll bar in which the last X motion event occurred.
207 If the last X motion event occurred in a scroll bar, we set this
208 so XTmouse_position can know whether to report a scroll bar motion or
211 If the last X motion event didn't occur in a scroll bar, we set this
212 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
213 static Lisp_Object last_mouse_scroll_bar
;
215 /* This is a hack. We would really prefer that XTmouse_position would
216 return the time associated with the position it returns, but there
217 doesn't seem to be any way to wrest the timestamp from the server
218 along with the position query. So, we just keep track of the time
219 of the last movement we received, and return that in hopes that
220 it's somewhat accurate. */
221 static Time last_mouse_movement_time
;
223 /* Incremented by XTread_socket whenever it really tries to read events. */
225 static int volatile input_signal_count
;
227 static int input_signal_count
;
230 /* Used locally within XTread_socket. */
231 static int x_noop_count
;
233 /* Initial values of argv and argc. */
234 extern char **initial_argv
;
235 extern int initial_argc
;
237 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
239 /* Tells if a window manager is present or not. */
241 extern Lisp_Object Vx_no_window_manager
;
243 extern Lisp_Object Qface
, Qmouse_face
;
247 /* A mask of extra modifier bits to put into every keyboard char. */
248 extern int extra_keyboard_modifiers
;
250 static Lisp_Object Qvendor_specific_keysyms
;
252 extern XrmDatabase
x_load_resources ();
254 extern Lisp_Object
x_icon_type ();
256 void x_delete_display ();
258 static void redraw_previous_char ();
259 static void redraw_following_char ();
260 static unsigned int x_x_to_emacs_modifiers ();
262 static int fast_find_position ();
263 static void note_mouse_highlight ();
264 static void clear_mouse_face ();
265 static void show_mouse_face ();
266 static void do_line_dance ();
268 static int XTcursor_to ();
269 static int XTclear_end_of_line ();
270 static int x_io_error_quitter ();
271 int x_catch_errors ();
272 void x_uncatch_errors ();
275 /* This is a function useful for recording debugging information
276 about the sequence of occurrences in this file. */
284 struct record event_record
[100];
286 int event_record_index
;
288 record_event (locus
, type
)
292 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
293 event_record_index
= 0;
295 event_record
[event_record_index
].locus
= locus
;
296 event_record
[event_record_index
].type
= type
;
297 event_record_index
++;
302 /* Return the struct x_display_info corresponding to DPY. */
304 struct x_display_info
*
305 x_display_info_for_display (dpy
)
308 struct x_display_info
*dpyinfo
;
310 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
311 if (dpyinfo
->display
== dpy
)
317 /* Starting and ending updates.
319 These hooks are called by update_frame at the beginning and end
320 of a frame update. We record in `updating_frame' the identity
321 of the frame being updated, so that the XT... functions do not
322 need to take a frame as argument. Most of the XT... functions
323 should never be called except during an update, the only exceptions
324 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
335 flexlines
= f
->height
;
340 curs_x
= FRAME_CURSOR_X (f
);
341 curs_y
= FRAME_CURSOR_Y (f
);
343 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
345 /* Don't do highlighting for mouse motion during the update. */
346 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
348 /* If the frame needs to be redrawn,
349 simply forget about any prior mouse highlighting. */
350 if (FRAME_GARBAGED_P (f
))
351 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
353 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
355 int firstline
, lastline
, i
;
356 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
358 /* Find the first, and the last+1, lines affected by redisplay. */
359 for (firstline
= 0; firstline
< f
->height
; firstline
++)
360 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
363 lastline
= f
->height
;
364 for (i
= f
->height
- 1; i
>= 0; i
--)
366 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
372 /* Can we tell that this update does not affect the window
373 where the mouse highlight is? If so, no need to turn off.
374 Likewise, don't do anything if the frame is garbaged;
375 in that case, the FRAME_CURRENT_GLYPHS that we would use
376 are all wrong, and we will redisplay that line anyway. */
377 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
378 || lastline
< XFASTINT (w
->top
)))
379 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
395 x_display_cursor (f
, 1, curs_x
, curs_y
);
397 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
399 /* This fails in the case of having updated only the echo area
400 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
401 has no relation to the current contents, and its charstarts
402 have no relation to the contents of the window-buffer.
403 I don't know a clean way to check
404 for that case. window_end_valid isn't set up yet. */
405 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
406 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
407 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
410 XFlush (FRAME_X_DISPLAY (f
));
414 /* This is called after a redisplay on frame F. */
417 XTframe_up_to_date (f
)
421 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
422 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
424 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
425 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
426 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
427 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
432 /* External interface to control of standout mode.
433 Call this when about to modify line at position VPOS
434 and not change whether it is highlighted. */
436 XTreassert_line_highlight (new, vpos
)
442 /* Call this when about to modify line at position VPOS
443 and change whether it is highlighted. */
446 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
447 int new_highlight
, vpos
, first_unused_hpos
;
449 highlight
= new_highlight
;
450 XTcursor_to (vpos
, 0);
451 XTclear_end_of_line (FRAME_WINDOW_WIDTH (updating_frame
));
454 /* This is used when starting Emacs and when restarting after suspend.
455 When starting Emacs, no X window is mapped. And nothing must be done
456 to Emacs's own window if it is suspended (though that rarely happens). */
459 XTset_terminal_modes ()
463 /* This is called when exiting or suspending Emacs.
464 Exiting will make the X-windows go away, and suspending
465 requires no action. */
468 XTreset_terminal_modes ()
470 /* XTclear_frame (); */
473 /* Set the nominal cursor position of the frame.
474 This is where display update commands will take effect.
475 This does not affect the place where the cursor-box is displayed. */
478 XTcursor_to (row
, col
)
479 register int row
, col
;
487 if (updating_frame
== 0)
490 x_display_cursor (selected_frame
, 1, curs_x
, curs_y
);
491 XFlush (FRAME_X_DISPLAY (selected_frame
));
497 /* Return a pointer to per char metric information in FONT of a
498 character pointed by B (*XChar2b). */
500 #define PER_CHAR_METRIC(font, b) \
502 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
503 + (((font)->min_byte1 || (font)->max_byte1) \
504 ? (((b)->byte1 - (font)->min_byte1) \
505 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
507 : &((font)->max_bounds))
509 /* Display a sequence of N glyphs found at GP.
510 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
511 HL is 1 if this text is highlighted, 2 if the cursor is on it,
512 3 if should appear in its mouse-face.
513 JUST_FOREGROUND if 1 means draw only the foreground;
514 don't alter the background.
516 CMPCHARP if non NULL is a pointer to the struct cmpchar_info, which
517 means drawing glyphs on the same column. This is set to non NULL
518 only when recursively called within dumpglyphs to draw a composite
519 character specified by CMPCHAR.
521 FONT is the default font to use (for glyphs whose font-code is 0).
523 Since the display generation code is responsible for calling
524 compute_char_face and compute_glyph_face on everything it puts in
525 the display structure, we can assume that the face code on each
526 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
527 to which we can actually apply intern_face.
528 Call this function with input blocked.
530 Return overall pixel width of the drawn glyphs. */
533 /* This is the multi-face code. */
536 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
, cmpcharp
)
539 register GLYPH
*gp
; /* Points to first GLYPH. */
540 register int n
; /* Number of glyphs to display. */
543 struct cmpchar_info
*cmpcharp
;
545 /* Holds characters to be displayed. */
546 XChar2b
*x_2byte_buffer
547 = (XChar2b
*) alloca (FRAME_WINDOW_WIDTH (f
) * sizeof (*x_2byte_buffer
));
548 register XChar2b
*cp
; /* Steps through x_2byte_buffer[]. */
550 = (char *) alloca (FRAME_WINDOW_WIDTH (f
) * sizeof (*x_1byte_buffer
));
551 register int tlen
= GLYPH_TABLE_LENGTH
;
552 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
553 Window window
= FRAME_X_WINDOW (f
);
554 int orig_left
= left
;
560 /* Get the face-code of the next GLYPH. */
564 Lisp_Object first_ch
;
565 /* HIGHEST and LOWEST are used while drawing a composite
566 character. The meanings are described later. */
569 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
570 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
571 ch
= FAST_GLYPH_CHAR (g
);
572 if (gidx
== 0) XSETFASTINT (first_ch
, ch
);
573 charset
= CHAR_CHARSET (ch
);
574 if (charset
== CHARSET_COMPOSITION
)
576 /* We must draw components of the composite character on the
578 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
580 /* Set the face in the slot for work. */
581 cmpcharp
->face_work
= cf
;
583 /* We don't need the return value ... */
584 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
585 hl
, just_foreground
, cmpcharp
);
586 /* ... because the width of just drawn text can be
587 calculated as follows. */
588 left
+= FONT_WIDTH (f
->output_data
.x
->font
) * cmpcharp
->width
;
591 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
596 /* Find the run of consecutive glyphs which can be drawn with
597 the same GC (i.e. the same charset and the same face-code).
598 Extract their character codes into X_2BYTE_BUFFER.
599 If CMPCHARP is not NULL, face-code is not checked because we
600 use only the face specified in `cmpcharp->face_work'. */
604 int this_charset
, c1
, c2
;
607 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
608 ch
= FAST_GLYPH_CHAR (g
);
609 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
610 if (this_charset
!= charset
611 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
615 cp
->byte1
= c1
, cp
->byte2
= c2
;
617 cp
->byte1
= 0, cp
->byte2
= c1
;
620 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
624 /* LEN gets the length of the run. */
625 len
= cp
- x_2byte_buffer
;
626 /* Now output this run of chars, with the font and pixel values
627 determined by the face code CF. */
629 struct face
*face
= FRAME_DEFAULT_FACE (f
);
630 XFontStruct
*font
= NULL
;
633 int line_height
= f
->output_data
.x
->line_height
;
634 /* Pixel width of each glyph in this run. */
636 = (FONT_WIDTH (f
->output_data
.x
->font
)
637 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
638 /* Overall pixel width of this run. */
640 = (FONT_WIDTH (f
->output_data
.x
->font
)
641 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
642 /* A flag to tell if we have already filled background. We
643 fill background in advance in the following cases:
644 1) A face has stipple.
645 2) A height of font is shorter than LINE_HEIGHT.
646 3) Drawing a composite character.
647 4) Font has non-zero _MULE_BASELINE_OFFSET property.
648 After filling background, we draw glyphs by XDrawString16. */
649 int background_filled
;
650 /* Baseline position of a character, offset from TOP. */
652 /* The property value of `_MULE_RELATIVE_COMPOSE' and
653 `_MULE_DEFAULT_ASCENT'. */
654 int relative_compose
= 0, default_ascent
= 0;
655 /* 1 if we find no font or a font of inappropriate size. */
656 int require_clipping
;
658 /* HL = 3 means use a mouse face previously chosen. */
660 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
662 /* First look at the face of the text itself. */
665 /* It's possible for the display table to specify
666 a face code that is out of range. Use 0 in that case. */
667 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
668 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
672 face
= FRAME_MODE_LINE_FACE (f
);
674 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
675 if (FACE_STIPPLE (face
))
679 /* Then comes the distinction between modeline and normal text. */
684 face
= FRAME_MODE_LINE_FACE (f
);
685 if (FACE_STIPPLE (face
))
689 #define FACE_DEFAULT (~0)
691 /* Setting appropriate font and gc for this charset. */
692 if (charset
!= CHARSET_ASCII
)
695 int fontset
= FACE_FONTSET (face
);
696 struct font_info
*fontp
;
698 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
699 || !(fontp
= FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
700 charset
, NULL
, fontset
)))
703 font
= (XFontStruct
*) (fontp
->font
);
704 gc
= FACE_NON_ASCII_GC (face
);
705 XSetFont (FRAME_X_DISPLAY (f
), gc
, font
->fid
);
707 = (font
->max_byte1
!= 0
708 ? (line_height
+ font
->ascent
- font
->descent
) / 2
709 : f
->output_data
.x
->font_baseline
- fontp
->baseline_offset
);
710 if (FONT_HEIGHT (font
) <= line_height
711 && (font
->ascent
> baseline
712 || font
->descent
> line_height
- baseline
))
713 /* Adjust baseline for this font to show the whole
715 baseline
= line_height
- font
->descent
;
717 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
719 relative_compose
= fontp
->relative_compose
;
720 default_ascent
= fontp
->default_ascent
;
723 /* We have to change code points in the following cases. */
724 if (fontp
->font_encoder
)
726 /* This font requires CCL program to calculate code
727 point of characters. */
728 struct ccl_program
*ccl
= fontp
->font_encoder
;
730 if (CHARSET_DIMENSION (charset
) == 1)
731 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
733 ccl
->reg
[0] = charset
;
734 ccl
->reg
[1] = cp
->byte2
;
735 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
736 /* We assume that MSBs are appropriately
737 set/reset by CCL program. */
738 if (font
->max_byte1
== 0) /* 1-byte font */
739 cp
->byte2
= ccl
->reg
[1];
741 cp
->byte1
= ccl
->reg
[1], cp
->byte2
= ccl
->reg
[2];
744 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
746 ccl
->reg
[0] = charset
;
747 ccl
->reg
[1] = cp
->byte1
, ccl
->reg
[2] = cp
->byte2
;
748 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
749 /* We assume that MSBs are appropriately
750 set/reset by CCL program. */
751 if (font
->max_byte1
== 0) /* 1-byte font */
752 cp
->byte2
= ccl
->reg
[1];
754 cp
->byte1
= ccl
->reg
[1], cp
->byte2
= ccl
->reg
[2];
757 else if (fontp
->encoding
[charset
])
759 int enc
= fontp
->encoding
[charset
];
761 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
762 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
764 if (enc
== 1 || enc
== 3)
765 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
772 if (charset
== CHARSET_ASCII
|| charset
== charset_latin_iso8859_1
)
774 font
= FACE_FONT (face
);
775 if (font
== (XFontStruct
*) FACE_DEFAULT
)
776 font
= f
->output_data
.x
->font
;
777 baseline
= FONT_BASE (f
->output_data
.x
->font
);
778 if (charset
== charset_latin_iso8859_1
)
780 if (font
->max_char_or_byte2
< 0x80)
781 /* This font can't display Latin1 characters. */
785 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
793 /* Now override that if the cursor's on this character. */
796 /* The cursor overrides stippling. */
799 if (font
== f
->output_data
.x
->font
800 && face
->background
== f
->output_data
.x
->background_pixel
801 && face
->foreground
== f
->output_data
.x
->foreground_pixel
804 gc
= f
->output_data
.x
->cursor_gc
;
806 /* Cursor on non-default face: must merge. */
812 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
813 xgcv
.foreground
= face
->background
;
814 /* If the glyph would be invisible,
815 try a different foreground. */
816 if (xgcv
.foreground
== xgcv
.background
)
817 xgcv
.foreground
= face
->foreground
;
818 if (xgcv
.foreground
== xgcv
.background
)
819 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
820 if (xgcv
.foreground
== xgcv
.background
)
821 xgcv
.foreground
= face
->foreground
;
822 /* Make sure the cursor is distinct from text in this face. */
823 if (xgcv
.background
== face
->background
824 && xgcv
.foreground
== face
->foreground
)
826 xgcv
.background
= face
->foreground
;
827 xgcv
.foreground
= face
->background
;
830 xgcv
.font
= font
->fid
;
832 xgcv
.font
= FACE_FONT (face
)->fid
;
833 xgcv
.graphics_exposures
= 0;
834 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
835 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
836 XChangeGC (FRAME_X_DISPLAY (f
),
837 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
840 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
841 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
842 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
844 /* If this code is restored, it must also reset to the default stipple
846 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
847 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
853 require_clipping
= (!NILP (Vclip_large_size_font
)
854 && (font
->ascent
> baseline
855 || font
->descent
> line_height
- baseline
857 && FONT_WIDTH (font
) > glyph_width
)));
859 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
860 background_filled
= 1;
863 /* Turn stipple on. */
864 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
866 /* Draw stipple or background color on background. */
867 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
868 left
, top
, run_width
, line_height
);
870 /* Turn stipple off. */
871 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
873 background_filled
= 1;
876 || FONT_HEIGHT (font
) < line_height
877 || FONT_WIDTH (font
) < glyph_width
880 /* Fill a area for the current run in background pixle of GC. */
882 unsigned long mask
= GCForeground
| GCBackground
| GCFillStyle
;
884 /* The current code at first set foreground to background,
885 fill the area, then recover the original foreground.
886 Aren't there any smarter ways? */
888 XGetGCValues (FRAME_X_DISPLAY (f
), gc
, mask
, &xgcv
);
889 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.background
);
890 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
891 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
892 left
, top
, run_width
, line_height
);
893 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.foreground
);
895 background_filled
= 1;
897 /* To assure not to fill background while drawing
898 remaining components. */
902 background_filled
= 0;
906 if (require_clipping
)
908 Region region
; /* Region used for setting clip mask to GC. */
909 XPoint x
[4]; /* Data used for creating REGION. */
911 x
[0].x
= x
[3].x
= left
, x
[1].x
= x
[2].x
= left
+ glyph_width
;
912 x
[0].y
= x
[1].y
= top
, x
[2].y
= x
[3].y
= top
+ line_height
;
913 region
= XPolygonRegion (x
, 4, EvenOddRule
);
914 XSetRegion (FRAME_X_DISPLAY (f
), gc
, region
);
915 XDestroyRegion (region
);
920 if (require_clipping
|| FONT_WIDTH (font
) != glyph_width
)
921 for (i
= 0; i
< len
; i
++)
923 if (require_clipping
&& i
> 0)
924 XSetClipOrigin (FRAME_X_DISPLAY (f
), gc
,
926 if (background_filled
)
927 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
928 left
+ glyph_width
* i
,
929 top
+ baseline
, x_2byte_buffer
+ i
, 1);
931 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
932 left
+ glyph_width
* i
,
933 top
+ baseline
, x_2byte_buffer
+ i
, 1);
937 /* See if this whole buffer can be output as 8-bit chars.
938 If so, copy x_2byte_buffer to x_1byte_buffer
939 and do it as 8-bit chars. */
940 for (i
= 0; i
< len
; i
++)
942 if (x_2byte_buffer
[i
].byte1
!= 0)
944 x_1byte_buffer
[i
] = x_2byte_buffer
[i
].byte2
;
949 if (background_filled
)
950 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
951 left
, top
+ baseline
, x_1byte_buffer
, len
);
953 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
954 left
, top
+ baseline
, x_1byte_buffer
, len
);
958 /* We can't output them as 8-bit chars,
959 so do it as 16-bit chars. */
961 if (background_filled
)
962 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
963 left
, top
+ baseline
, x_2byte_buffer
, len
);
965 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
966 left
, top
+ baseline
, x_2byte_buffer
, len
);
972 /* Handle composite characters. */
973 XCharStruct
*pcm
; /* Pointer to per char metric info. */
975 if ((cmpcharp
->cmp_rule
|| relative_compose
)
978 /* This is the first character. Initialize variables.
979 HIGHEST is the highest position of glyphs ever
980 written, LOWEST the lowest position. */
984 && CHAR_TABLE_P (Vuse_default_ascent
)
985 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
987 highest
= default_ascent
;
992 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
);
993 highest
= pcm
->ascent
+ 1;
994 lowest
= - pcm
->descent
;
997 if (cmpcharp
->cmp_rule
)
998 x_offset
= (cmpcharp
->col_offset
[0]
999 * FONT_WIDTH (f
->output_data
.x
->font
));
1000 /* Draw the first character at the normal position. */
1001 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
1002 left
+ x_offset
, top
+ baseline
, x_2byte_buffer
, 1);
1009 for (; i
< len
; i
++, gidx
++)
1011 int x_offset
= 0, y_offset
= 0;
1013 if (relative_compose
)
1015 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
+ i
);
1016 if (NILP (Vignore_relative_composition
)
1017 || NILP (Faref (Vignore_relative_composition
,
1018 make_number (cmpcharp
->glyph
[gidx
]))))
1020 if (- pcm
->descent
>= relative_compose
)
1022 /* Draw above the current glyphs. */
1023 y_offset
= highest
+ pcm
->descent
;
1024 highest
+= pcm
->ascent
+ pcm
->descent
;
1026 else if (pcm
->ascent
<= 0)
1028 /* Draw beneath the current glyphs. */
1029 y_offset
= lowest
- pcm
->ascent
;
1030 lowest
-= pcm
->ascent
+ pcm
->descent
;
1035 /* Draw the glyph at normal position. If
1036 it sticks out of HIGHEST or LOWEST,
1037 update them appropriately. */
1038 if (pcm
->ascent
> highest
)
1039 highest
= pcm
->ascent
;
1040 else if (- pcm
->descent
< lowest
)
1041 lowest
= - pcm
->descent
;
1044 else if (cmpcharp
->cmp_rule
)
1046 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
1047 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
1050 /* Re-encode GREF and NREF so that they specify
1051 only Y-axis information:
1052 0:top, 1:base, 2:bottom, 3:center */
1053 gref
= gref
/ 3 + (gref
== 4) * 2;
1054 nref
= nref
/ 3 + (nref
== 4) * 2;
1056 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
+ i
);
1057 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
1058 : gref
== 2 ? lowest
1059 : (highest
+ lowest
) / 2)
1060 - (nref
== 0 ? pcm
->ascent
+ pcm
->descent
1061 : nref
== 1 ? pcm
->descent
: nref
== 2 ? 0
1062 : (pcm
->ascent
+ pcm
->descent
) / 2));
1063 top
= bottom
+ (pcm
->ascent
+ pcm
->descent
);
1066 if (bottom
< lowest
)
1068 y_offset
= bottom
+ pcm
->descent
;
1069 x_offset
= (cmpcharp
->col_offset
[gidx
]
1070 * FONT_WIDTH (f
->output_data
.x
->font
));
1072 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
1073 left
+ x_offset
, top
+ baseline
- y_offset
,
1074 x_2byte_buffer
+ i
, 1);
1077 if (require_clipping
)
1078 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
1080 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
1081 which often is not up to date yet. */
1082 if (!just_foreground
)
1084 if (left
== orig_left
)
1085 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
1086 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1088 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
1089 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1095 /* Show rectangles to indicate that we found no font. */
1096 int limit
= cmpcharp
? 1 : len
;
1098 for (i
= 0; i
< limit
; i
++)
1099 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1100 left
+ glyph_width
* i
, top
,
1101 glyph_width
- 1, line_height
- 1);
1103 else if (require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1105 /* Show ??? to indicate that we found a font of
1106 inappropriate size. */
1107 int limit
= cmpcharp
? 1 : len
;
1109 for (i
= 0; i
< limit
; i
++)
1111 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1112 left
+ glyph_width
* i
, top
+ line_height
- 1,
1113 left
+ glyph_width
* i
+ 1, top
+ line_height
- 1);
1114 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1115 left
+ glyph_width
* i
, top
+ line_height
- 3,
1116 left
+ glyph_width
* i
, top
+ line_height
- 1);
1120 /* We should probably check for XA_UNDERLINE_POSITION and
1121 XA_UNDERLINE_THICKNESS properties on the font, but let's
1122 just get the thing working, and come back to that. */
1124 /* Setting underline position based on the metric of the
1125 current font results in shaky underline if it strides
1126 over different fonts. So, we set the position based only
1127 on the default font of this frame. */
1128 int underline_position
= f
->output_data
.x
->font_baseline
+ 1;
1130 if (underline_position
>= line_height
)
1131 underline_position
= line_height
- 1;
1133 if (face
->underline
)
1134 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1136 left
, top
+ underline_position
, run_width
, 1);
1144 return (left
- orig_left
);
1149 /* This is the old single-face code. */
1152 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
1155 register GLYPH
*gp
; /* Points to first GLYPH. */
1156 register int n
; /* Number of glyphs to display. */
1161 Window window
= FRAME_X_WINDOW (f
);
1162 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
1163 : (hl
? f
->output_data
.x
->reverse_gc
1164 : f
->output_data
.x
->normal_gc
));
1166 if (sizeof (GLYPH
) == sizeof (XChar2b
))
1167 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1168 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
1169 else if (sizeof (GLYPH
) == sizeof (unsigned char))
1170 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1171 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
1173 /* What size of glyph ARE you using? And does X have a function to
1179 /* Output some text at the nominal frame cursor position.
1180 Advance the cursor over the text.
1181 Output LEN glyphs at START.
1183 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
1184 controls the pixel values used for foreground and background. */
1187 XTwrite_glyphs (start
, len
)
1188 register GLYPH
*start
;
1191 register int temp_length
;
1202 /* If not within an update,
1203 output at the frame's visible cursor. */
1204 curs_x
= f
->cursor_x
;
1205 curs_y
= f
->cursor_y
;
1209 CHAR_TO_PIXEL_COL (f
, curs_x
),
1210 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1211 start
, len
, highlight
, 0, NULL
);
1213 /* If we drew on top of the cursor, note that it is turned off. */
1214 if (curs_y
== f
->phys_cursor_y
1215 && curs_x
<= f
->phys_cursor_x
1216 && curs_x
+ len
> f
->phys_cursor_x
)
1217 f
->phys_cursor_on
= 0;
1219 if (updating_frame
== 0)
1220 x_display_cursor (f
, 1, FRAME_CURSOR_X (f
) + len
, FRAME_CURSOR_Y (f
));
1227 /* Clear to the end of the line.
1228 Erase the current text line from the nominal cursor position (inclusive)
1229 to column FIRST_UNUSED (exclusive). The idea is that everything
1230 from FIRST_UNUSED onward is already erased. */
1233 XTclear_end_of_line (first_unused
)
1234 register int first_unused
;
1236 struct frame
*f
= updating_frame
;
1242 if (curs_y
< 0 || curs_y
>= f
->height
)
1244 if (first_unused
<= 0)
1247 if (first_unused
>= FRAME_WINDOW_WIDTH (f
))
1248 first_unused
= FRAME_WINDOW_WIDTH (f
);
1250 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1256 /* Notice if the cursor will be cleared by this operation. */
1257 if (curs_y
== f
->phys_cursor_y
1258 && curs_x
<= f
->phys_cursor_x
1259 && f
->phys_cursor_x
< first_unused
)
1260 f
->phys_cursor_on
= 0;
1262 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1263 CHAR_TO_PIXEL_COL (f
, curs_x
),
1264 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1265 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
1266 f
->output_data
.x
->line_height
, False
);
1268 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
1278 struct frame
*f
= updating_frame
;
1283 f
->phys_cursor_on
= 0; /* Cursor not visible. */
1284 curs_x
= 0; /* Nominal cursor position is top left. */
1289 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
1291 /* We have to clear the scroll bars, too. If we have changed
1292 colors or something like that, then they should be notified. */
1293 x_scroll_bar_clear (f
);
1295 XFlush (FRAME_X_DISPLAY (f
));
1300 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
1301 always contain the right glyphs to use.
1303 It also needs to be changed to look at the details of the font and
1304 see whether there is really overlap, and do nothing when there is
1305 not. This can use font_char_overlap_left and font_char_overlap_right,
1306 but just how to use them is not clear. */
1308 /* Erase the character (if any) at the position just before X, Y in frame F,
1309 then redraw it and the character before it.
1310 This is necessary when we erase starting at X,
1311 in case the character after X overlaps into the one before X.
1312 Call this function with input blocked. */
1315 redraw_previous_char (f
, x
, y
, highlight_flag
)
1320 /* Erase the character before the new ones, in case
1321 what was here before overlaps it.
1322 Reoutput that character, and the previous character
1323 (in case the previous character overlaps it). */
1326 int start_x
= x
- 2;
1329 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1330 CHAR_TO_PIXEL_COL (f
, x
- 1),
1331 CHAR_TO_PIXEL_ROW (f
, y
),
1332 FONT_WIDTH (f
->output_data
.x
->font
),
1333 f
->output_data
.x
->line_height
, False
);
1335 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
1336 CHAR_TO_PIXEL_ROW (f
, y
),
1337 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
1338 x
- start_x
, highlight_flag
, 1, NULL
);
1342 /* Erase the character (if any) at the position X, Y in frame F,
1343 then redraw it and the character after it.
1344 This is necessary when we erase endng at X,
1345 in case the character after X overlaps into the one before X.
1346 Call this function with input blocked. */
1349 redraw_following_char (f
, x
, y
, highlight_flag
)
1354 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
1355 /* Erase the character after the new ones, in case
1356 what was here before overlaps it.
1357 Reoutput that character, and the following character
1358 (in case the following character overlaps it). */
1360 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1365 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1366 CHAR_TO_PIXEL_COL (f
, x
),
1367 CHAR_TO_PIXEL_ROW (f
, y
),
1368 FONT_WIDTH (f
->output_data
.x
->font
),
1369 f
->output_data
.x
->line_height
, False
);
1371 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1372 CHAR_TO_PIXEL_ROW (f
, y
),
1373 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1374 end_x
- x
, highlight_flag
, 1, NULL
);
1379 #if 0 /* Not in use yet */
1381 /* Return 1 if character C in font F extends past its left edge. */
1384 font_char_overlap_left (font
, c
)
1390 /* Find the bounding-box info for C. */
1391 if (font
->per_char
== 0)
1392 s
= &font
->max_bounds
;
1395 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1398 /* Decode char into row number (byte 1) and code within row (byte 2). */
1401 if (!(within
>= font
->min_char_or_byte2
1402 && within
<= font
->max_char_or_byte2
1403 && row
>= font
->min_byte1
1404 && row
<= font
->max_byte1
))
1406 /* If char is out of range, try the font's default char instead. */
1407 c
= font
->default_char
;
1408 row
= c
>> (BITS_PER_INT
- 8);
1411 if (!(within
>= font
->min_char_or_byte2
1412 && within
<= font
->max_char_or_byte2
1413 && row
>= font
->min_byte1
1414 && row
<= font
->max_byte1
))
1415 /* Still out of range means this char does not overlap. */
1418 /* We found the info for this char. */
1419 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1423 return (s
&& s
->lbearing
< 0);
1426 /* Return 1 if character C in font F extends past its right edge. */
1429 font_char_overlap_right (font
, c
)
1435 /* Find the bounding-box info for C. */
1436 if (font
->per_char
== 0)
1437 s
= &font
->max_bounds
;
1440 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1443 /* Decode char into row number (byte 1) and code within row (byte 2). */
1446 if (!(within
>= font
->min_char_or_byte2
1447 && within
<= font
->max_char_or_byte2
1448 && row
>= font
->min_byte1
1449 && row
<= font
->max_byte1
))
1451 /* If char is out of range, try the font's default char instead. */
1452 c
= font
->default_char
;
1453 row
= c
>> (BITS_PER_INT
- 8);
1456 if (!(within
>= font
->min_char_or_byte2
1457 && within
<= font
->max_char_or_byte2
1458 && row
>= font
->min_byte1
1459 && row
<= font
->max_byte1
))
1460 /* Still out of range means this char does not overlap. */
1463 /* We found the info for this char. */
1464 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1468 return (s
&& s
->rbearing
>= s
->width
);
1472 /* Invert the middle quarter of the frame for .15 sec. */
1474 /* We use the select system call to do the waiting, so we have to make sure
1475 it's available. If it isn't, we just won't do visual bells. */
1476 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1478 /* Subtract the `struct timeval' values X and Y,
1479 storing the result in RESULT.
1480 Return 1 if the difference is negative, otherwise 0. */
1483 timeval_subtract (result
, x
, y
)
1484 struct timeval
*result
, x
, y
;
1486 /* Perform the carry for the later subtraction by updating y.
1487 This is safer because on some systems
1488 the tv_sec member is unsigned. */
1489 if (x
.tv_usec
< y
.tv_usec
)
1491 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1492 y
.tv_usec
-= 1000000 * nsec
;
1495 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1497 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1498 y
.tv_usec
+= 1000000 * nsec
;
1502 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1503 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1504 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1506 /* Return indication of whether the result should be considered negative. */
1507 return x
.tv_sec
< y
.tv_sec
;
1518 /* Create a GC that will use the GXxor function to flip foreground pixels
1519 into background pixels. */
1523 values
.function
= GXxor
;
1524 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1525 ^ f
->output_data
.x
->background_pixel
);
1527 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1528 GCFunction
| GCForeground
, &values
);
1532 /* Get the height not including a menu bar widget. */
1533 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
1534 /* Height of each line to flash. */
1535 int flash_height
= FRAME_LINE_HEIGHT (f
);
1536 /* These will be the left and right margins of the rectangles. */
1537 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1538 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
1542 /* Don't flash the area between a scroll bar and the frame
1543 edge it is next to. */
1544 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
1546 case vertical_scroll_bar_left
:
1547 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1550 case vertical_scroll_bar_right
:
1551 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1555 width
= flash_right
- flash_left
;
1557 /* If window is tall, flash top and bottom line. */
1558 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1560 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1561 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1562 width
, flash_height
);
1563 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1565 (height
- flash_height
1566 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1567 width
, flash_height
);
1570 /* If it is short, flash it all. */
1571 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1572 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1573 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1575 XFlush (FRAME_X_DISPLAY (f
));
1578 struct timeval wakeup
, now
;
1580 EMACS_GET_TIME (wakeup
);
1582 /* Compute time to wait until, propagating carry from usecs. */
1583 wakeup
.tv_usec
+= 150000;
1584 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1585 wakeup
.tv_usec
%= 1000000;
1587 /* Keep waiting until past the time wakeup. */
1590 struct timeval timeout
;
1592 EMACS_GET_TIME (timeout
);
1594 /* In effect, timeout = wakeup - timeout.
1595 Break if result would be negative. */
1596 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1599 /* Try to wait that long--but we might wake up sooner. */
1600 select (0, NULL
, NULL
, NULL
, &timeout
);
1604 /* If window is tall, flash top and bottom line. */
1605 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1607 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1608 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1609 width
, flash_height
);
1610 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1612 (height
- flash_height
1613 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1614 width
, flash_height
);
1617 /* If it is short, flash it all. */
1618 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1619 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1620 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1622 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1623 XFlush (FRAME_X_DISPLAY (f
));
1633 /* Make audible bell. */
1635 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1639 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1642 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1644 XTflash (selected_frame
);
1650 XFlush (FRAME_X_DISPLAY (selected_frame
));
1655 /* Insert and delete character.
1656 These are not supposed to be used because we are supposed to turn
1657 off the feature of using them. */
1660 XTinsert_glyphs (start
, len
)
1661 register char *start
;
1674 /* Specify how many text lines, from the top of the window,
1675 should be affected by insert-lines and delete-lines operations.
1676 This, and those operations, are used only within an update
1677 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1680 XTset_terminal_window (n
)
1683 if (updating_frame
== 0)
1686 if ((n
<= 0) || (n
> updating_frame
->height
))
1687 flexlines
= updating_frame
->height
;
1692 /* These variables need not be per frame
1693 because redisplay is done on a frame-by-frame basis
1694 and the line dance for one frame is finished before
1695 anything is done for anoter frame. */
1697 /* Array of line numbers from cached insert/delete operations.
1698 line_dance[i] is the old position of the line that we want
1699 to move to line i, or -1 if we want a blank line there. */
1700 static int *line_dance
;
1702 /* Allocated length of that array. */
1703 static int line_dance_len
;
1705 /* Flag indicating whether we've done any work. */
1706 static int line_dance_in_progress
;
1708 /* Perform an insert-lines or delete-lines operation,
1709 inserting N lines or deleting -N lines at vertical position VPOS. */
1710 XTins_del_lines (vpos
, n
)
1713 register int fence
, i
;
1715 if (vpos
>= flexlines
)
1718 if (!line_dance_in_progress
)
1720 int ht
= updating_frame
->height
;
1721 if (ht
> line_dance_len
)
1723 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1724 line_dance_len
= ht
;
1726 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1727 line_dance_in_progress
= 1;
1731 if (n
> flexlines
- vpos
)
1732 n
= flexlines
- vpos
;
1734 for (i
= flexlines
; --i
>= fence
;)
1735 line_dance
[i
] = line_dance
[i
-n
];
1736 for (i
= fence
; --i
>= vpos
;)
1742 if (n
> flexlines
- vpos
)
1743 n
= flexlines
- vpos
;
1744 fence
= flexlines
- n
;
1745 for (i
= vpos
; i
< fence
; ++i
)
1746 line_dance
[i
] = line_dance
[i
+ n
];
1747 for (i
= fence
; i
< flexlines
; ++i
)
1752 /* Here's where we actually move the pixels around.
1753 Must be called with input blocked. */
1757 register int i
, j
, distance
;
1758 register struct frame
*f
;
1762 /* Must check this flag first. If it's not set, then not only is the
1763 array uninitialized, but we might not even have a frame. */
1764 if (!line_dance_in_progress
)
1772 intborder
= CHAR_TO_PIXEL_COL (f
, FRAME_LEFT_SCROLL_BAR_WIDTH (f
));
1774 x_update_cursor (updating_frame
, 0);
1776 for (i
= 0; i
< ht
; ++i
)
1777 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1779 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1780 && line_dance
[j
]-j
== distance
); ++j
);
1781 /* Copy [i,j) upward from [i+distance,j+distance) */
1782 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1783 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1784 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1785 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1786 (j
-i
) * f
->output_data
.x
->line_height
,
1787 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1791 for (i
= ht
; --i
>=0; )
1792 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1794 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1795 && line_dance
[j
]-j
== distance
););
1796 /* Copy (j,i] downward from (j+distance, i+distance] */
1797 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1798 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1799 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1800 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1801 (i
-j
) * f
->output_data
.x
->line_height
,
1802 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1806 for (i
= 0; i
< ht
; ++i
)
1807 if (line_dance
[i
] == -1)
1809 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1811 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1812 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1813 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1814 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1817 line_dance_in_progress
= 0;
1820 /* Support routines for exposure events. */
1821 static void clear_cursor ();
1823 /* Output into a rectangle of an X-window (for frame F)
1824 the characters in f->phys_lines that overlap that rectangle.
1825 TOP and LEFT are the position of the upper left corner of the rectangle.
1826 ROWS and COLS are the size of the rectangle.
1827 Call this function with input blocked. */
1830 dumprectangle (f
, left
, top
, cols
, rows
)
1832 register int left
, top
, cols
, rows
;
1834 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1835 int cursor_cleared
= 0;
1839 if (FRAME_GARBAGED_P (f
))
1842 /* Express rectangle as four edges, instead of position-and-size. */
1843 bottom
= top
+ rows
;
1844 right
= left
+ cols
;
1846 /* Convert rectangle edges in pixels to edges in chars.
1847 Round down for left and top, up for right and bottom. */
1848 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1849 left
= PIXEL_TO_CHAR_COL (f
, left
);
1850 bottom
+= (f
->output_data
.x
->line_height
- 1);
1851 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1852 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1853 right
= PIXEL_TO_CHAR_COL (f
, right
);
1855 /* Clip the rectangle to what can be visible. */
1860 if (right
> FRAME_WINDOW_WIDTH (f
))
1861 right
= FRAME_WINDOW_WIDTH (f
);
1862 if (bottom
> f
->height
)
1865 /* Get size in chars of the rectangle. */
1866 cols
= right
- left
;
1867 rows
= bottom
- top
;
1869 /* If rectangle has zero area, return. */
1870 if (rows
<= 0) return;
1871 if (cols
<= 0) return;
1873 /* Turn off the cursor if it is in the rectangle.
1874 We will turn it back on afterward. */
1875 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1876 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1882 /* Display the text in the rectangle, one text line at a time. */
1884 for (y
= top
; y
< bottom
; y
++)
1886 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1888 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1891 while (*line
& GLYPH_MASK_PADDING
)
1893 /* We must display the whole glyph of a wide-column
1900 CHAR_TO_PIXEL_COL (f
, left
),
1901 CHAR_TO_PIXEL_ROW (f
, y
),
1902 line
, min (cols
, active_frame
->used
[y
] - left
),
1903 active_frame
->highlight
[y
], 0, NULL
);
1906 /* Turn the cursor on if we turned it off. */
1909 x_update_cursor (f
, 1);
1916 /* We used to only do this if Vx_no_window_manager was non-nil, but
1917 the ICCCM (section 4.1.6) says that the window's border pixmap
1918 and border pixel are window attributes which are "private to the
1919 client", so we can always change it to whatever we want. */
1921 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1922 f
->output_data
.x
->border_pixel
);
1924 x_update_cursor (f
, 1);
1928 frame_unhighlight (f
)
1931 /* We used to only do this if Vx_no_window_manager was non-nil, but
1932 the ICCCM (section 4.1.6) says that the window's border pixmap
1933 and border pixel are window attributes which are "private to the
1934 client", so we can always change it to whatever we want. */
1936 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1937 f
->output_data
.x
->border_tile
);
1939 x_update_cursor (f
, 1);
1942 static void XTframe_rehighlight ();
1943 static void x_frame_rehighlight ();
1945 /* The focus has changed. Update the frames as necessary to reflect
1946 the new situation. Note that we can't change the selected frame
1947 here, because the Lisp code we are interrupting might become confused.
1948 Each event gets marked with the frame in which it occurred, so the
1949 Lisp code can tell when the switch took place by examining the events. */
1952 x_new_focus_frame (dpyinfo
, frame
)
1953 struct x_display_info
*dpyinfo
;
1954 struct frame
*frame
;
1956 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1957 int events_enqueued
= 0;
1959 if (frame
!= dpyinfo
->x_focus_frame
)
1961 /* Set this before calling other routines, so that they see
1962 the correct value of x_focus_frame. */
1963 dpyinfo
->x_focus_frame
= frame
;
1965 if (old_focus
&& old_focus
->auto_lower
)
1966 x_lower_frame (old_focus
);
1969 selected_frame
= frame
;
1970 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1972 Fselect_window (selected_frame
->selected_window
);
1973 choose_minibuf_frame ();
1976 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1977 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1979 pending_autoraise_frame
= 0;
1982 x_frame_rehighlight (dpyinfo
);
1985 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1988 x_mouse_leave (dpyinfo
)
1989 struct x_display_info
*dpyinfo
;
1991 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1994 /* The focus has changed, or we have redirected a frame's focus to
1995 another frame (this happens when a frame uses a surrogate
1996 minibuffer frame). Shift the highlight as appropriate.
1998 The FRAME argument doesn't necessarily have anything to do with which
1999 frame is being highlighted or unhighlighted; we only use it to find
2000 the appropriate X display info. */
2002 XTframe_rehighlight (frame
)
2003 struct frame
*frame
;
2005 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
2009 x_frame_rehighlight (dpyinfo
)
2010 struct x_display_info
*dpyinfo
;
2012 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
2014 if (dpyinfo
->x_focus_frame
)
2016 dpyinfo
->x_highlight_frame
2017 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
2018 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
2019 : dpyinfo
->x_focus_frame
);
2020 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
2022 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
2023 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
2027 dpyinfo
->x_highlight_frame
= 0;
2029 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
2032 frame_unhighlight (old_highlight
);
2033 if (dpyinfo
->x_highlight_frame
)
2034 frame_highlight (dpyinfo
->x_highlight_frame
);
2038 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
2040 /* Initialize mode_switch_bit and modifier_meaning. */
2042 x_find_modifier_meanings (dpyinfo
)
2043 struct x_display_info
*dpyinfo
;
2045 int min_code
, max_code
;
2048 XModifierKeymap
*mods
;
2050 dpyinfo
->meta_mod_mask
= 0;
2051 dpyinfo
->shift_lock_mask
= 0;
2052 dpyinfo
->alt_mod_mask
= 0;
2053 dpyinfo
->super_mod_mask
= 0;
2054 dpyinfo
->hyper_mod_mask
= 0;
2057 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
2059 min_code
= dpyinfo
->display
->min_keycode
;
2060 max_code
= dpyinfo
->display
->max_keycode
;
2063 syms
= XGetKeyboardMapping (dpyinfo
->display
,
2064 min_code
, max_code
- min_code
+ 1,
2066 mods
= XGetModifierMapping (dpyinfo
->display
);
2068 /* Scan the modifier table to see which modifier bits the Meta and
2069 Alt keysyms are on. */
2071 int row
, col
; /* The row and column in the modifier table. */
2073 for (row
= 3; row
< 8; row
++)
2074 for (col
= 0; col
< mods
->max_keypermod
; col
++)
2077 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
2079 /* Zeroes are used for filler. Skip them. */
2083 /* Are any of this keycode's keysyms a meta key? */
2087 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
2089 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
2095 dpyinfo
->meta_mod_mask
|= (1 << row
);
2100 dpyinfo
->alt_mod_mask
|= (1 << row
);
2105 dpyinfo
->hyper_mod_mask
|= (1 << row
);
2110 dpyinfo
->super_mod_mask
|= (1 << row
);
2114 /* Ignore this if it's not on the lock modifier. */
2115 if ((1 << row
) == LockMask
)
2116 dpyinfo
->shift_lock_mask
= LockMask
;
2124 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
2125 if (! dpyinfo
->meta_mod_mask
)
2127 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
2128 dpyinfo
->alt_mod_mask
= 0;
2131 /* If some keys are both alt and meta,
2132 make them just meta, not alt. */
2133 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
2135 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
2138 XFree ((char *) syms
);
2139 XFreeModifiermap (mods
);
2142 /* Convert between the modifier bits X uses and the modifier bits
2145 x_x_to_emacs_modifiers (dpyinfo
, state
)
2146 struct x_display_info
*dpyinfo
;
2149 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
2150 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
2151 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
2152 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
2153 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
2154 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
2158 x_emacs_to_x_modifiers (dpyinfo
, state
)
2159 struct x_display_info
*dpyinfo
;
2162 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
2163 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
2164 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
2165 | ((state
& shift_modifier
) ? ShiftMask
: 0)
2166 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
2167 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
2170 /* Convert a keysym to its name. */
2173 x_get_keysym_name (keysym
)
2179 value
= XKeysymToString (keysym
);
2185 /* Mouse clicks and mouse movement. Rah. */
2187 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
2188 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
2189 that the glyph at X, Y occupies, if BOUNDS != 0.
2190 If NOCLIP is nonzero, do not force the value into range. */
2193 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
2195 register int pix_x
, pix_y
;
2196 register int *x
, *y
;
2200 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
2201 even for negative values. */
2203 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
2205 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
2207 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
2208 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
2212 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
2213 bounds
->height
= f
->output_data
.x
->line_height
;
2214 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
2215 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
2222 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
2223 pix_x
= FRAME_WINDOW_WIDTH (f
);
2227 else if (pix_y
> f
->height
)
2236 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
2239 register int *pix_x
, *pix_y
;
2241 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
2242 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
2245 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2247 If the event is a button press, then note that we have grabbed
2251 construct_mouse_click (result
, event
, f
)
2252 struct input_event
*result
;
2253 XButtonEvent
*event
;
2256 /* Make the event type no_event; we'll change that when we decide
2258 result
->kind
= mouse_click
;
2259 result
->code
= event
->button
- Button1
;
2260 result
->timestamp
= event
->time
;
2261 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2263 | (event
->type
== ButtonRelease
2271 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2272 XSETFASTINT (result
->x
, column
);
2273 XSETFASTINT (result
->y
, row
);
2275 XSETINT (result
->x
, event
->x
);
2276 XSETINT (result
->y
, event
->y
);
2277 XSETFRAME (result
->frame_or_window
, f
);
2281 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2284 construct_menu_click (result
, event
, f
)
2285 struct input_event
*result
;
2286 XButtonEvent
*event
;
2289 /* Make the event type no_event; we'll change that when we decide
2291 result
->kind
= mouse_click
;
2292 result
->code
= event
->button
- Button1
;
2293 result
->timestamp
= event
->time
;
2294 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2296 | (event
->type
== ButtonRelease
2300 XSETINT (result
->x
, event
->x
);
2301 XSETINT (result
->y
, -1);
2302 XSETFRAME (result
->frame_or_window
, f
);
2305 /* Function to report a mouse movement to the mainstream Emacs code.
2306 The input handler calls this.
2308 We have received a mouse movement event, which is given in *event.
2309 If the mouse is over a different glyph than it was last time, tell
2310 the mainstream emacs code by setting mouse_moved. If not, ask for
2311 another motion event, so we can check again the next time it moves. */
2314 note_mouse_movement (frame
, event
)
2316 XMotionEvent
*event
;
2318 last_mouse_movement_time
= event
->time
;
2320 if (event
->window
!= FRAME_X_WINDOW (frame
))
2322 frame
->mouse_moved
= 1;
2323 last_mouse_scroll_bar
= Qnil
;
2325 note_mouse_highlight (frame
, -1, -1);
2328 /* Has the mouse moved off the glyph it was on at the last sighting? */
2329 else if (event
->x
< last_mouse_glyph
.x
2330 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2331 || event
->y
< last_mouse_glyph
.y
2332 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2334 frame
->mouse_moved
= 1;
2335 last_mouse_scroll_bar
= Qnil
;
2337 note_mouse_highlight (frame
, event
->x
, event
->y
);
2341 /* This is used for debugging, to turn off note_mouse_highlight. */
2342 static int disable_mouse_highlight
;
2344 /* Take proper action when the mouse has moved to position X, Y on frame F
2345 as regards highlighting characters that have mouse-face properties.
2346 Also dehighlighting chars where the mouse was before.
2347 X and Y can be negative or out of range. */
2350 note_mouse_highlight (f
, x
, y
)
2354 int row
, column
, portion
;
2355 XRectangle new_glyph
;
2359 if (disable_mouse_highlight
)
2362 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2363 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2364 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2366 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
2371 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2375 /* Find out which glyph the mouse is on. */
2376 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2377 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
2379 /* Which window is that in? */
2380 window
= window_from_coordinates (f
, column
, row
, &portion
);
2381 w
= XWINDOW (window
);
2383 /* If we were displaying active text in another window, clear that. */
2384 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
2385 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2387 /* Are we in a window whose display is up to date?
2388 And verify the buffer's text has not changed. */
2389 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2390 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2391 && EQ (w
->window_end_valid
, w
->buffer
)
2392 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
2393 && (XFASTINT (w
->last_overlay_modified
)
2394 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
2396 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2399 /* Find which buffer position the mouse corresponds to. */
2400 for (i
= column
; i
>= 0; i
--)
2404 /* Is it outside the displayed active region (if any)? */
2406 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2407 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
2408 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2409 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2410 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2411 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2412 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2413 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2414 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2416 Lisp_Object mouse_face
, overlay
, position
;
2417 Lisp_Object
*overlay_vec
;
2418 int len
, noverlays
, ignor1
;
2419 struct buffer
*obuf
;
2422 /* If we get an out-of-range value, return now; avoid an error. */
2423 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2426 /* Make the window's buffer temporarily current for
2427 overlays_at and compute_char_face. */
2428 obuf
= current_buffer
;
2429 current_buffer
= XBUFFER (w
->buffer
);
2435 /* Yes. Clear the display of the old active region, if any. */
2436 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2438 /* Is this char mouse-active? */
2439 XSETINT (position
, pos
);
2442 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2444 /* Put all the overlays we want in a vector in overlay_vec.
2445 Store the length in len. */
2446 noverlays
= overlays_at (pos
, 1, &overlay_vec
, &len
,
2448 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2450 /* Find the highest priority overlay that has a mouse-face prop. */
2452 for (i
= 0; i
< noverlays
; i
++)
2454 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2455 if (!NILP (mouse_face
))
2457 overlay
= overlay_vec
[i
];
2462 /* If no overlay applies, get a text property. */
2464 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2466 /* Handle the overlay case. */
2467 if (! NILP (overlay
))
2469 /* Find the range of text around this char that
2470 should be active. */
2471 Lisp_Object before
, after
;
2474 before
= Foverlay_start (overlay
);
2475 after
= Foverlay_end (overlay
);
2476 /* Record this as the current active region. */
2477 fast_find_position (window
, XFASTINT (before
),
2478 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2479 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2480 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2481 = !fast_find_position (window
, XFASTINT (after
),
2482 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2483 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2484 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2485 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2486 = compute_char_face (f
, w
, pos
, 0, 0,
2487 &ignore
, pos
+ 1, 1);
2489 /* Display it as active. */
2490 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2492 /* Handle the text property case. */
2493 else if (! NILP (mouse_face
))
2495 /* Find the range of text around this char that
2496 should be active. */
2497 Lisp_Object before
, after
, beginning
, end
;
2500 beginning
= Fmarker_position (w
->start
);
2501 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2502 - XFASTINT (w
->window_end_pos
)));
2504 = Fprevious_single_property_change (make_number (pos
+ 1),
2506 w
->buffer
, beginning
);
2508 = Fnext_single_property_change (position
, Qmouse_face
,
2510 /* Record this as the current active region. */
2511 fast_find_position (window
, XFASTINT (before
),
2512 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2513 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2514 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2515 = !fast_find_position (window
, XFASTINT (after
),
2516 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2517 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2518 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2519 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2520 = compute_char_face (f
, w
, pos
, 0, 0,
2521 &ignore
, pos
+ 1, 1);
2523 /* Display it as active. */
2524 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2528 current_buffer
= obuf
;
2533 /* Find the row and column of position POS in window WINDOW.
2534 Store them in *COLUMNP and *ROWP.
2535 This assumes display in WINDOW is up to date.
2536 If POS is above start of WINDOW, return coords
2537 of start of first screen line.
2538 If POS is after end of WINDOW, return coords of end of last screen line.
2540 Value is 1 if POS is in range, 0 if it was off screen. */
2543 fast_find_position (window
, pos
, columnp
, rowp
)
2546 int *columnp
, *rowp
;
2548 struct window
*w
= XWINDOW (window
);
2549 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2552 int left
= WINDOW_LEFT_MARGIN (w
);
2553 int top
= XFASTINT (w
->top
);
2554 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2555 int width
= window_internal_width (w
);
2558 int maybe_next_line
= 0;
2560 /* Find the right row. */
2565 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2566 if (linestart
> pos
)
2568 /* If the position sought is the end of the buffer,
2569 don't include the blank lines at the bottom of the window. */
2570 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2572 maybe_next_line
= 1;
2579 /* Find the right column with in it. */
2580 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2582 for (i
= 0; i
< width
; i
++)
2584 if (charstarts
[left
+ i
] == pos
)
2587 *columnp
= i
+ left
;
2590 else if (charstarts
[left
+ i
] > pos
)
2592 else if (charstarts
[left
+ i
] > 0)
2596 /* If we're looking for the end of the buffer,
2597 and we didn't find it in the line we scanned,
2598 use the start of the following line. */
2599 if (maybe_next_line
)
2610 /* Display the active region described by mouse_face_*
2611 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2614 show_mouse_face (dpyinfo
, hl
)
2615 struct x_display_info
*dpyinfo
;
2618 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2619 int width
= window_internal_width (w
);
2620 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2623 int old_curs_x
= curs_x
;
2624 int old_curs_y
= curs_y
;
2626 /* Set these variables temporarily
2627 so that if we have to turn the cursor off and on again
2628 we will put it back at the same place. */
2629 curs_x
= f
->phys_cursor_x
;
2630 curs_y
= f
->phys_cursor_y
;
2631 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2632 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2634 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2635 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2636 : WINDOW_LEFT_MARGIN (w
));
2637 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2638 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2639 : WINDOW_LEFT_MARGIN (w
) + width
);
2640 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2642 /* If the cursor's in the text we are about to rewrite,
2643 turn the cursor off. */
2645 && curs_x
>= column
- 1
2646 && curs_x
<= endcolumn
)
2648 x_update_cursor (f
, 0);
2653 CHAR_TO_PIXEL_COL (f
, column
),
2654 CHAR_TO_PIXEL_ROW (f
, i
),
2655 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2657 /* Highlight with mouse face if hl > 0. */
2658 hl
> 0 ? 3 : 0, 0, NULL
);
2661 /* If we turned the cursor off, turn it back on. */
2663 x_display_cursor (f
, 1, curs_x
, curs_y
);
2665 curs_x
= old_curs_x
;
2666 curs_y
= old_curs_y
;
2668 /* Change the mouse cursor according to the value of HL. */
2670 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2671 f
->output_data
.x
->cross_cursor
);
2673 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2674 f
->output_data
.x
->text_cursor
);
2677 /* Clear out the mouse-highlighted active region.
2678 Redraw it unhighlighted first. */
2681 clear_mouse_face (dpyinfo
)
2682 struct x_display_info
*dpyinfo
;
2684 if (! NILP (dpyinfo
->mouse_face_window
))
2685 show_mouse_face (dpyinfo
, 0);
2687 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2688 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2689 dpyinfo
->mouse_face_window
= Qnil
;
2692 /* Just discard the mouse face information for frame F, if any.
2693 This is used when the size of F is changed. */
2695 cancel_mouse_face (f
)
2699 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2701 window
= dpyinfo
->mouse_face_window
;
2702 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
2704 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2705 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2706 dpyinfo
->mouse_face_window
= Qnil
;
2710 static struct scroll_bar
*x_window_to_scroll_bar ();
2711 static void x_scroll_bar_report_motion ();
2713 /* Return the current position of the mouse.
2714 *fp should be a frame which indicates which display to ask about.
2716 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2717 and *part to the frame, window, and scroll bar part that the mouse
2718 is over. Set *x and *y to the portion and whole of the mouse's
2719 position on the scroll bar.
2721 If the mouse movement started elsewhere, set *fp to the frame the
2722 mouse is on, *bar_window to nil, and *x and *y to the character cell
2725 Set *time to the server timestamp for the time at which the mouse
2726 was at this position.
2728 Don't store anything if we don't have a valid set of values to report.
2730 This clears the mouse_moved flag, so we can wait for the next mouse
2734 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2737 Lisp_Object
*bar_window
;
2738 enum scroll_bar_part
*part
;
2740 unsigned long *time
;
2746 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
2747 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2753 Window dummy_window
;
2756 Lisp_Object frame
, tail
;
2758 /* Clear the mouse-moved flag for every frame on this display. */
2759 FOR_EACH_FRAME (tail
, frame
)
2760 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2761 XFRAME (frame
)->mouse_moved
= 0;
2763 last_mouse_scroll_bar
= Qnil
;
2765 /* Figure out which root window we're on. */
2766 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2767 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2769 /* The root window which contains the pointer. */
2772 /* Trash which we can't trust if the pointer is on
2773 a different screen. */
2776 /* The position on that root window. */
2779 /* More trash we can't trust. */
2782 /* Modifier keys and pointer buttons, about which
2784 (unsigned int *) &dummy
);
2786 /* Now we have a position on the root; find the innermost window
2787 containing the pointer. */
2791 int parent_x
, parent_y
;
2796 /* XTranslateCoordinates can get errors if the window
2797 structure is changing at the same time this function
2798 is running. So at least we must not crash from them. */
2800 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
2802 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2803 && FRAME_LIVE_P (last_mouse_frame
))
2805 /* If mouse was grabbed on a frame, give coords for that frame
2806 even if the mouse is now outside it. */
2807 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2809 /* From-window, to-window. */
2810 root
, FRAME_X_WINDOW (last_mouse_frame
),
2812 /* From-position, to-position. */
2813 root_x
, root_y
, &win_x
, &win_y
,
2817 f1
= last_mouse_frame
;
2823 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2825 /* From-window, to-window. */
2828 /* From-position, to-position. */
2829 root_x
, root_y
, &win_x
, &win_y
,
2834 if (child
== None
|| child
== win
)
2842 /* Now we know that:
2843 win is the innermost window containing the pointer
2844 (XTC says it has no child containing the pointer),
2845 win_x and win_y are the pointer's position in it
2846 (XTC did this the last time through), and
2847 parent_x and parent_y are the pointer's position in win's parent.
2848 (They are what win_x and win_y were when win was child.
2849 If win is the root window, it has no parent, and
2850 parent_{x,y} are invalid, but that's okay, because we'll
2851 never use them in that case.) */
2853 /* Is win one of our frames? */
2854 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2857 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2860 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
2862 /* If not, is it one of our scroll bars? */
2865 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2869 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2875 if (f1
== 0 && insist
> 0)
2876 f1
= selected_frame
;
2880 int ignore1
, ignore2
;
2882 /* Ok, we found a frame. Store all the values. */
2884 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2886 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2892 XSETINT (*x
, win_x
);
2893 XSETINT (*y
, win_y
);
2894 *time
= last_mouse_movement_time
;
2902 /* Scroll bar support. */
2904 /* Given an X window ID, find the struct scroll_bar which manages it.
2905 This can be called in GC, so we have to make sure to strip off mark
2907 static struct scroll_bar
*
2908 x_window_to_scroll_bar (window_id
)
2911 Lisp_Object tail
, frame
;
2913 for (tail
= Vframe_list
;
2914 XGCTYPE (tail
) == Lisp_Cons
;
2915 tail
= XCONS (tail
)->cdr
)
2917 Lisp_Object frame
, bar
, condemned
;
2919 frame
= XCONS (tail
)->car
;
2920 /* All elements of Vframe_list should be frames. */
2921 if (! GC_FRAMEP (frame
))
2924 /* Scan this frame's scroll bar list for a scroll bar with the
2926 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2927 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2928 /* This trick allows us to search both the ordinary and
2929 condemned scroll bar lists with one loop. */
2930 ! GC_NILP (bar
) || (bar
= condemned
,
2933 bar
= XSCROLL_BAR (bar
)->next
)
2934 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2935 return XSCROLL_BAR (bar
);
2941 /* Open a new X window to serve as a scroll bar, and return the
2942 scroll bar vector for it. */
2943 static struct scroll_bar
*
2944 x_scroll_bar_create (window
, top
, left
, width
, height
)
2945 struct window
*window
;
2946 int top
, left
, width
, height
;
2948 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2949 struct scroll_bar
*bar
2950 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2955 XSetWindowAttributes a
;
2957 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2958 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2959 | ButtonMotionMask
| PointerMotionHintMask
2961 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2963 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2968 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2969 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2970 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2971 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2972 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2973 sb_widget
= XtCreateManagedWidget ("box",
2975 f
->output_data
.x
->edit_widget
, al
, ac
);
2976 SET_SCROLL_BAR_X_WINDOW
2977 (bar
, sb_widget
->core
.window
);
2979 SET_SCROLL_BAR_X_WINDOW
2981 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2983 /* Position and size of scroll bar. */
2984 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, top
,
2985 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2, height
,
2987 /* Border width, depth, class, and visual. */
2988 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2994 XSETWINDOW (bar
->window
, window
);
2995 XSETINT (bar
->top
, top
);
2996 XSETINT (bar
->left
, left
);
2997 XSETINT (bar
->width
, width
);
2998 XSETINT (bar
->height
, height
);
2999 XSETINT (bar
->start
, 0);
3000 XSETINT (bar
->end
, 0);
3001 bar
->dragging
= Qnil
;
3003 /* Add bar to its frame's list of scroll bars. */
3004 bar
->next
= FRAME_SCROLL_BARS (f
);
3006 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3007 if (! NILP (bar
->next
))
3008 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3010 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
3017 /* Draw BAR's handle in the proper position.
3018 If the handle is already drawn from START to END, don't bother
3019 redrawing it, unless REBUILD is non-zero; in that case, always
3020 redraw it. (REBUILD is handy for drawing the handle after expose
3023 Normally, we want to constrain the start and end of the handle to
3024 fit inside its rectangle, but if the user is dragging the scroll bar
3025 handle, we want to let them drag it down all the way, so that the
3026 bar's top is as far down as it goes; otherwise, there's no way to
3027 move to the very end of the buffer. */
3029 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
3030 struct scroll_bar
*bar
;
3034 int dragging
= ! NILP (bar
->dragging
);
3035 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3036 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3037 GC gc
= f
->output_data
.x
->normal_gc
;
3039 /* If the display is already accurate, do nothing. */
3041 && start
== XINT (bar
->start
)
3042 && end
== XINT (bar
->end
))
3048 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
3049 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3050 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3052 /* Make sure the values are reasonable, and try to preserve
3053 the distance between start and end. */
3055 int length
= end
- start
;
3059 else if (start
> top_range
)
3061 end
= start
+ length
;
3065 else if (end
> top_range
&& ! dragging
)
3069 /* Store the adjusted setting in the scroll bar. */
3070 XSETINT (bar
->start
, start
);
3071 XSETINT (bar
->end
, end
);
3073 /* Clip the end position, just for display. */
3074 if (end
> top_range
)
3077 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
3078 below top positions, to make sure the handle is always at least
3079 that many pixels tall. */
3080 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3082 /* Draw the empty space above the handle. Note that we can't clear
3083 zero-height areas; that means "clear to end of window." */
3085 XClearArea (FRAME_X_DISPLAY (f
), w
,
3087 /* x, y, width, height, and exposures. */
3088 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3089 VERTICAL_SCROLL_BAR_TOP_BORDER
,
3090 inside_width
, start
,
3093 /* Draw the handle itself. */
3094 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3096 /* x, y, width, height */
3097 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3098 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
3099 inside_width
, end
- start
);
3102 /* Draw the empty space below the handle. Note that we can't
3103 clear zero-height areas; that means "clear to end of window." */
3104 if (end
< inside_height
)
3105 XClearArea (FRAME_X_DISPLAY (f
), w
,
3107 /* x, y, width, height, and exposures. */
3108 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3109 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
3110 inside_width
, inside_height
- end
,
3118 /* Move a scroll bar around on the screen, to accommodate changing
3119 window configurations. */
3121 x_scroll_bar_move (bar
, top
, left
, width
, height
)
3122 struct scroll_bar
*bar
;
3123 int top
, left
, width
, height
;
3125 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3126 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3132 unsigned int mask
= 0;
3134 wc
.x
= left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3137 wc
.width
= width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
3140 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
3141 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
3142 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
3143 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
3146 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
3150 XSETINT (bar
->left
, left
);
3151 XSETINT (bar
->top
, top
);
3152 XSETINT (bar
->width
, width
);
3153 XSETINT (bar
->height
, height
);
3158 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
3161 x_scroll_bar_remove (bar
)
3162 struct scroll_bar
*bar
;
3164 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3168 /* Destroy the window. */
3169 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
3171 /* Disassociate this scroll bar from its window. */
3172 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3177 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3178 that we are displaying PORTION characters out of a total of WHOLE
3179 characters, starting at POSITION. If WINDOW has no scroll bar,
3182 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
3183 struct window
*window
;
3184 int portion
, whole
, position
;
3186 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3187 int top
= XINT (window
->top
);
3188 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
3189 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
3191 /* Where should this scroll bar be, pixelwise? */
3192 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
3193 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
3195 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3196 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3197 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3198 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
3200 struct scroll_bar
*bar
;
3202 /* Does the scroll bar exist yet? */
3203 if (NILP (window
->vertical_scroll_bar
))
3204 bar
= x_scroll_bar_create (window
,
3205 pixel_top
, pixel_left
,
3206 pixel_width
, pixel_height
);
3209 /* It may just need to be moved and resized. */
3210 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3211 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
3214 /* Set the scroll bar's current state, unless we're currently being
3216 if (NILP (bar
->dragging
))
3218 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, pixel_height
);
3221 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
3224 int start
= ((double) position
* top_range
) / whole
;
3225 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
3227 x_scroll_bar_set_handle (bar
, start
, end
, 0);
3231 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
3235 /* The following three hooks are used when we're doing a thorough
3236 redisplay of the frame. We don't explicitly know which scroll bars
3237 are going to be deleted, because keeping track of when windows go
3238 away is a real pain - "Can you say set-window-configuration, boys
3239 and girls?" Instead, we just assert at the beginning of redisplay
3240 that *all* scroll bars are to be removed, and then save a scroll bar
3241 from the fiery pit when we actually redisplay its window. */
3243 /* Arrange for all scroll bars on FRAME to be removed at the next call
3244 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3245 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
3247 XTcondemn_scroll_bars (frame
)
3250 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3251 while (! NILP (FRAME_SCROLL_BARS (frame
)))
3254 bar
= FRAME_SCROLL_BARS (frame
);
3255 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
3256 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
3257 XSCROLL_BAR (bar
)->prev
= Qnil
;
3258 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
3259 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
3260 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
3264 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
3265 Note that WINDOW isn't necessarily condemned at all. */
3267 XTredeem_scroll_bar (window
)
3268 struct window
*window
;
3270 struct scroll_bar
*bar
;
3272 /* We can't redeem this window's scroll bar if it doesn't have one. */
3273 if (NILP (window
->vertical_scroll_bar
))
3276 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3278 /* Unlink it from the condemned list. */
3280 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3282 if (NILP (bar
->prev
))
3284 /* If the prev pointer is nil, it must be the first in one of
3286 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3287 /* It's not condemned. Everything's fine. */
3289 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3290 window
->vertical_scroll_bar
))
3291 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3293 /* If its prev pointer is nil, it must be at the front of
3294 one or the other! */
3298 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3300 if (! NILP (bar
->next
))
3301 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3303 bar
->next
= FRAME_SCROLL_BARS (f
);
3305 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3306 if (! NILP (bar
->next
))
3307 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3311 /* Remove all scroll bars on FRAME that haven't been saved since the
3312 last call to `*condemn_scroll_bars_hook'. */
3314 XTjudge_scroll_bars (f
)
3317 Lisp_Object bar
, next
;
3319 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3321 /* Clear out the condemned list now so we won't try to process any
3322 more events on the hapless scroll bars. */
3323 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3325 for (; ! NILP (bar
); bar
= next
)
3327 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3329 x_scroll_bar_remove (b
);
3332 b
->next
= b
->prev
= Qnil
;
3335 /* Now there should be no references to the condemned scroll bars,
3336 and they should get garbage-collected. */
3340 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3342 This may be called from a signal handler, so we have to ignore GC
3345 x_scroll_bar_expose (bar
, event
)
3346 struct scroll_bar
*bar
;
3349 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3350 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3351 GC gc
= f
->output_data
.x
->normal_gc
;
3352 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3356 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3358 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3359 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3361 /* x, y, width, height */
3363 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
3364 XINT (bar
->height
) - 1);
3369 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3370 is set to something other than no_event, it is enqueued.
3372 This may be called from a signal handler, so we have to ignore GC
3375 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3376 struct scroll_bar
*bar
;
3378 struct input_event
*emacs_event
;
3380 if (! GC_WINDOWP (bar
->window
))
3383 emacs_event
->kind
= scroll_bar_click
;
3384 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3385 emacs_event
->modifiers
3386 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
3387 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
3388 event
->xbutton
.state
)
3389 | (event
->type
== ButtonRelease
3392 emacs_event
->frame_or_window
= bar
->window
;
3393 emacs_event
->timestamp
= event
->xbutton
.time
;
3395 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3397 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3399 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3400 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3403 if (y
> top_range
) y
= top_range
;
3405 if (y
< XINT (bar
->start
))
3406 emacs_event
->part
= scroll_bar_above_handle
;
3407 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3408 emacs_event
->part
= scroll_bar_handle
;
3410 emacs_event
->part
= scroll_bar_below_handle
;
3412 /* Just because the user has clicked on the handle doesn't mean
3413 they want to drag it. Lisp code needs to be able to decide
3414 whether or not we're dragging. */
3416 /* If the user has just clicked on the handle, record where they're
3418 if (event
->type
== ButtonPress
3419 && emacs_event
->part
== scroll_bar_handle
)
3420 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
3423 /* If the user has released the handle, set it to its final position. */
3424 if (event
->type
== ButtonRelease
3425 && ! NILP (bar
->dragging
))
3427 int new_start
= y
- XINT (bar
->dragging
);
3428 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3430 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3431 bar
->dragging
= Qnil
;
3434 /* Same deal here as the other #if 0. */
3436 /* Clicks on the handle are always reported as occurring at the top of
3438 if (emacs_event
->part
== scroll_bar_handle
)
3439 emacs_event
->x
= bar
->start
;
3441 XSETINT (emacs_event
->x
, y
);
3443 XSETINT (emacs_event
->x
, y
);
3446 XSETINT (emacs_event
->y
, top_range
);
3450 /* Handle some mouse motion while someone is dragging the scroll bar.
3452 This may be called from a signal handler, so we have to ignore GC
3455 x_scroll_bar_note_movement (bar
, event
)
3456 struct scroll_bar
*bar
;
3459 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
3461 last_mouse_movement_time
= event
->xmotion
.time
;
3464 XSETVECTOR (last_mouse_scroll_bar
, bar
);
3466 /* If we're dragging the bar, display it. */
3467 if (! GC_NILP (bar
->dragging
))
3469 /* Where should the handle be now? */
3470 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3472 if (new_start
!= XINT (bar
->start
))
3474 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3476 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3481 /* Return information to the user about the current position of the mouse
3482 on the scroll bar. */
3484 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3486 Lisp_Object
*bar_window
;
3487 enum scroll_bar_part
*part
;
3489 unsigned long *time
;
3491 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3492 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3493 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3495 Window dummy_window
;
3497 unsigned int dummy_mask
;
3501 /* Get the mouse's position relative to the scroll bar window, and
3503 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3505 /* Root, child, root x and root y. */
3506 &dummy_window
, &dummy_window
,
3507 &dummy_coord
, &dummy_coord
,
3509 /* Position relative to scroll bar. */
3512 /* Mouse buttons and modifier keys. */
3518 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3520 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3522 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3524 if (! NILP (bar
->dragging
))
3525 win_y
-= XINT (bar
->dragging
);
3529 if (win_y
> top_range
)
3533 *bar_window
= bar
->window
;
3535 if (! NILP (bar
->dragging
))
3536 *part
= scroll_bar_handle
;
3537 else if (win_y
< XINT (bar
->start
))
3538 *part
= scroll_bar_above_handle
;
3539 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3540 *part
= scroll_bar_handle
;
3542 *part
= scroll_bar_below_handle
;
3544 XSETINT (*x
, win_y
);
3545 XSETINT (*y
, top_range
);
3548 last_mouse_scroll_bar
= Qnil
;
3551 *time
= last_mouse_movement_time
;
3557 /* The screen has been cleared so we may have changed foreground or
3558 background colors, and the scroll bars may need to be redrawn.
3559 Clear out the scroll bars, and ask for expose events, so we can
3562 x_scroll_bar_clear (f
)
3567 /* We can have scroll bars even if this is 0,
3568 if we just turned off scroll bar mode.
3569 But in that case we should not clear them. */
3570 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3571 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3572 bar
= XSCROLL_BAR (bar
)->next
)
3573 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3577 /* This processes Expose events from the menubar specific X event
3578 loop in xmenu.c. This allows to redisplay the frame if necessary
3579 when handling menubar or popup items. */
3582 process_expose_from_menu (event
)
3586 struct x_display_info
*dpyinfo
;
3590 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3591 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3594 if (f
->async_visible
== 0)
3596 f
->async_visible
= 1;
3597 f
->async_iconified
= 0;
3598 f
->output_data
.x
->has_been_visible
= 1;
3599 SET_FRAME_GARBAGED (f
);
3603 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3604 event
.xexpose
.x
, event
.xexpose
.y
,
3605 event
.xexpose
.width
, event
.xexpose
.height
);
3610 struct scroll_bar
*bar
3611 = x_window_to_scroll_bar (event
.xexpose
.window
);
3614 x_scroll_bar_expose (bar
, &event
);
3620 /* Define a queue to save up SelectionRequest events for later handling. */
3622 struct selection_event_queue
3625 struct selection_event_queue
*next
;
3628 static struct selection_event_queue
*queue
;
3630 /* Nonzero means queue up certain events--don't process them yet. */
3631 static int x_queue_selection_requests
;
3633 /* Queue up an X event *EVENT, to be processed later. */
3636 x_queue_event (f
, event
)
3640 struct selection_event_queue
*queue_tmp
3641 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3643 if (queue_tmp
!= NULL
)
3645 queue_tmp
->event
= *event
;
3646 queue_tmp
->next
= queue
;
3651 /* Take all the queued events and put them back
3652 so that they get processed afresh. */
3655 x_unqueue_events (display
)
3658 while (queue
!= NULL
)
3660 struct selection_event_queue
*queue_tmp
= queue
;
3661 XPutBackEvent (display
, &queue_tmp
->event
);
3662 queue
= queue_tmp
->next
;
3663 free ((char *)queue_tmp
);
3667 /* Start queuing SelectionRequest events. */
3670 x_start_queuing_selection_requests (display
)
3673 x_queue_selection_requests
++;
3676 /* Stop queuing SelectionRequest events. */
3679 x_stop_queuing_selection_requests (display
)
3682 x_queue_selection_requests
--;
3683 x_unqueue_events (display
);
3686 /* The main X event-reading loop - XTread_socket. */
3688 /* Timestamp of enter window event. This is only used by XTread_socket,
3689 but we have to put it out here, since static variables within functions
3690 sometimes don't work. */
3691 static Time enter_timestamp
;
3693 /* This holds the state XLookupString needs to implement dead keys
3694 and other tricks known as "compose processing". _X Window System_
3695 says that a portable program can't use this, but Stephen Gildea assures
3696 me that letting the compiler initialize it to zeros will work okay.
3698 This must be defined outside of XTread_socket, for the same reasons
3699 given for enter_timestamp, above. */
3700 static XComposeStatus compose_status
;
3702 /* Record the last 100 characters stored
3703 to help debug the loss-of-chars-during-GC problem. */
3704 static int temp_index
;
3705 static short temp_buffer
[100];
3707 /* Set this to nonzero to fake an "X I/O error"
3708 on a particular display. */
3709 struct x_display_info
*XTread_socket_fake_io_error
;
3711 /* When we find no input here, we occasionally do a no-op command
3712 to verify that the X server is still running and we can still talk with it.
3713 We try all the open displays, one by one.
3714 This variable is used for cycling thru the displays. */
3715 static struct x_display_info
*next_noop_dpyinfo
;
3717 #define SET_SAVED_MENU_EVENT(size) { \
3718 if (f->output_data.x->saved_menu_event == 0) \
3719 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); \
3720 bcopy (&event, f->output_data.x->saved_menu_event, size); \
3721 if (numchars >= 1) \
3723 bufp->kind = menu_bar_activate_event; \
3724 XSETFRAME (bufp->frame_or_window, f); \
3730 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
3731 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
3733 /* Read events coming from the X server.
3734 This routine is called by the SIGIO handler.
3735 We return as soon as there are no more events to be read.
3737 Events representing keys are stored in buffer BUFP,
3738 which can hold up to NUMCHARS characters.
3739 We return the number of characters stored into the buffer,
3740 thus pretending to be `read'.
3742 EXPECTED is nonzero if the caller knows input is available. */
3745 XTread_socket (sd
, bufp
, numchars
, expected
)
3747 /* register */ struct input_event
*bufp
;
3748 /* register */ int numchars
;
3754 int items_pending
; /* How many items are in the X queue. */
3757 int event_found
= 0;
3760 struct x_display_info
*dpyinfo
;
3762 Status status_return
;
3765 if (interrupt_input_blocked
)
3767 interrupt_input_pending
= 1;
3771 interrupt_input_pending
= 0;
3774 /* So people can tell when we have read the available input. */
3775 input_signal_count
++;
3778 abort (); /* Don't think this happens. */
3780 /* Find the display we are supposed to read input for.
3781 It's the one communicating on descriptor SD. */
3782 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3784 #if 0 /* This ought to be unnecessary; let's verify it. */
3786 /* If available, Xlib uses FIOSNBIO to make the socket
3787 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3788 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3789 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3790 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3791 #endif /* ! defined (FIOSNBIO) */
3794 #if 0 /* This code can't be made to work, with multiple displays,
3795 and appears not to be used on any system any more.
3796 Also keyboard.c doesn't turn O_NDELAY on and off
3797 for X connections. */
3800 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3802 extern int read_alarm_should_throw
;
3803 read_alarm_should_throw
= 1;
3804 XPeekEvent (dpyinfo
->display
, &event
);
3805 read_alarm_should_throw
= 0;
3807 #endif /* HAVE_SELECT */
3811 /* For debugging, this gives a way to fake an I/O error. */
3812 if (dpyinfo
== XTread_socket_fake_io_error
)
3814 XTread_socket_fake_io_error
= 0;
3815 x_io_error_quitter (dpyinfo
->display
);
3818 while (XPending (dpyinfo
->display
) != 0)
3820 #ifdef USE_X_TOOLKIT
3821 /* needed to raise Motif submenus */
3822 XtAppNextEvent (Xt_app_con
, &event
);
3824 XNextEvent (dpyinfo
->display
, &event
);
3828 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
3829 &event
.xclient
.window
);
3830 /* The necessity of the following line took me
3831 a full work-day to decipher from the docs!! */
3832 if (f1
!= 0 && FRAME_XIC (f1
) && XFilterEvent (&event
, None
))
3842 if (event
.xclient
.message_type
3843 == dpyinfo
->Xatom_wm_protocols
3844 && event
.xclient
.format
== 32)
3846 if (event
.xclient
.data
.l
[0]
3847 == dpyinfo
->Xatom_wm_take_focus
)
3849 /* Use x_any_window_to_frame because this
3850 could be the shell widget window
3851 if the frame has no title bar. */
3852 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3854 /* Not quite sure this is needed -pd */
3855 if (f
&& FRAME_XIC (f
))
3856 XSetICFocus (FRAME_XIC (f
));
3858 /* Since we set WM_TAKE_FOCUS, we must call
3859 XSetInputFocus explicitly. But not if f is null,
3860 since that might be an event for a deleted frame. */
3863 Display
*d
= event
.xclient
.display
;
3864 /* Catch and ignore errors, in case window has been
3865 iconified by a window manager such as GWM. */
3866 int count
= x_catch_errors (d
);
3867 XSetInputFocus (d
, event
.xclient
.window
,
3868 RevertToPointerRoot
,
3869 event
.xclient
.data
.l
[1]);
3870 /* This is needed to detect the error
3871 if there is an error. */
3873 x_uncatch_errors (d
, count
);
3875 /* Not certain about handling scroll bars here */
3877 else if (event
.xclient
.data
.l
[0]
3878 == dpyinfo
->Xatom_wm_save_yourself
)
3880 /* Save state modify the WM_COMMAND property to
3881 something which can reinstate us. This notifies
3882 the session manager, who's looking for such a
3883 PropertyNotify. Can restart processing when
3884 a keyboard or mouse event arrives. */
3887 f
= x_top_window_to_frame (dpyinfo
,
3888 event
.xclient
.window
);
3890 /* This is just so we only give real data once
3891 for a single Emacs process. */
3892 if (f
== selected_frame
)
3893 XSetCommand (FRAME_X_DISPLAY (f
),
3894 event
.xclient
.window
,
3895 initial_argv
, initial_argc
);
3897 XSetCommand (FRAME_X_DISPLAY (f
),
3898 event
.xclient
.window
,
3902 else if (event
.xclient
.data
.l
[0]
3903 == dpyinfo
->Xatom_wm_delete_window
)
3906 = x_any_window_to_frame (dpyinfo
,
3907 event
.xclient
.window
);
3914 bufp
->kind
= delete_window_event
;
3915 XSETFRAME (bufp
->frame_or_window
, f
);
3923 else if (event
.xclient
.message_type
3924 == dpyinfo
->Xatom_wm_configure_denied
)
3927 else if (event
.xclient
.message_type
3928 == dpyinfo
->Xatom_wm_window_moved
)
3932 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3934 new_x
= event
.xclient
.data
.s
[0];
3935 new_y
= event
.xclient
.data
.s
[1];
3939 f
->output_data
.x
->left_pos
= new_x
;
3940 f
->output_data
.x
->top_pos
= new_y
;
3944 else if (event
.xclient
.message_type
3945 == dpyinfo
->Xatom_editres
)
3948 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3949 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3952 #endif /* HACK_EDITRES */
3956 case SelectionNotify
:
3957 #ifdef USE_X_TOOLKIT
3958 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3960 #endif /* not USE_X_TOOLKIT */
3961 x_handle_selection_notify (&event
);
3964 case SelectionClear
: /* Someone has grabbed ownership. */
3965 #ifdef USE_X_TOOLKIT
3966 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3968 #endif /* USE_X_TOOLKIT */
3970 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3975 bufp
->kind
= selection_clear_event
;
3976 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3977 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3978 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3979 bufp
->frame_or_window
= Qnil
;
3987 case SelectionRequest
: /* Someone wants our selection. */
3988 #ifdef USE_X_TOOLKIT
3989 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3991 #endif /* USE_X_TOOLKIT */
3992 if (x_queue_selection_requests
)
3993 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3997 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
4002 bufp
->kind
= selection_request_event
;
4003 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
4004 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
4005 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
4006 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
4007 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
4008 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
4009 bufp
->frame_or_window
= Qnil
;
4017 case PropertyNotify
:
4018 #ifdef USE_X_TOOLKIT
4019 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
4021 #endif /* not USE_X_TOOLKIT */
4022 x_handle_property_notify (&event
);
4025 case ReparentNotify
:
4026 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
4030 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
4031 x_real_positions (f
, &x
, &y
);
4032 f
->output_data
.x
->left_pos
= x
;
4033 f
->output_data
.x
->top_pos
= y
;
4038 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
4041 if (f
->async_visible
== 0)
4043 f
->async_visible
= 1;
4044 f
->async_iconified
= 0;
4045 f
->output_data
.x
->has_been_visible
= 1;
4046 SET_FRAME_GARBAGED (f
);
4049 dumprectangle (x_window_to_frame (dpyinfo
,
4050 event
.xexpose
.window
),
4051 event
.xexpose
.x
, event
.xexpose
.y
,
4052 event
.xexpose
.width
, event
.xexpose
.height
);
4056 struct scroll_bar
*bar
4057 = x_window_to_scroll_bar (event
.xexpose
.window
);
4060 x_scroll_bar_expose (bar
, &event
);
4061 #ifdef USE_X_TOOLKIT
4064 #endif /* USE_X_TOOLKIT */
4068 case GraphicsExpose
: /* This occurs when an XCopyArea's
4069 source area was obscured or not
4071 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
4075 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
4076 event
.xgraphicsexpose
.width
,
4077 event
.xgraphicsexpose
.height
);
4079 #ifdef USE_X_TOOLKIT
4082 #endif /* USE_X_TOOLKIT */
4085 case NoExpose
: /* This occurs when an XCopyArea's
4086 source area was completely
4091 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
4092 if (f
) /* F may no longer exist if
4093 the frame was deleted. */
4095 /* While a frame is unmapped, display generation is
4096 disabled; you don't want to spend time updating a
4097 display that won't ever be seen. */
4098 f
->async_visible
= 0;
4099 /* We can't distinguish, from the event, whether the window
4100 has become iconified or invisible. So assume, if it
4101 was previously visible, than now it is iconified.
4102 But x_make_frame_invisible clears both
4103 the visible flag and the iconified flag;
4104 and that way, we know the window is not iconified now. */
4105 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
4107 f
->async_iconified
= 1;
4109 bufp
->kind
= iconify_event
;
4110 XSETFRAME (bufp
->frame_or_window
, f
);
4119 /* We use x_top_window_to_frame because map events can come
4120 for subwindows and they don't mean that the frame is visible. */
4121 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
4124 f
->async_visible
= 1;
4125 f
->async_iconified
= 0;
4126 f
->output_data
.x
->has_been_visible
= 1;
4128 /* wait_reading_process_input will notice this and update
4129 the frame's display structures. */
4130 SET_FRAME_GARBAGED (f
);
4134 bufp
->kind
= deiconify_event
;
4135 XSETFRAME (bufp
->frame_or_window
, f
);
4140 else if (! NILP (Vframe_list
)
4141 && ! NILP (XCONS (Vframe_list
)->cdr
))
4142 /* Force a redisplay sooner or later
4143 to update the frame titles
4144 in case this is the second frame. */
4145 record_asynch_buffer_change ();
4149 /* Turn off processing if we become fully obscured. */
4150 case VisibilityNotify
:
4154 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
4158 KeySym keysym
, orig_keysym
;
4159 /* al%imercury@uunet.uu.net says that making this 81 instead of
4160 80 fixed a bug whereby meta chars made his Emacs hang. */
4161 unsigned char copy_buffer
[81];
4164 #if 0 /* This was how we made f10 work in Motif.
4165 The drawback is, you can't type at Emacs when the
4166 the mouse is in the menu bar. So it is better to
4167 turn off f10 in Motif and let Emacs handle it. */
4169 if (lw_window_is_in_menubar (event
.xkey
.window
,
4170 f
->output_data
.x
->menubar_widget
4173 SET_SAVED_KEY_EVENT
;
4176 #endif /* USE_MOTIF */
4180 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
4181 extra_keyboard_modifiers
);
4182 modifiers
= event
.xkey
.state
;
4184 /* This will have to go some day... */
4186 /* make_lispy_event turns chars into control chars.
4187 Don't do it here because XLookupString is too eager. */
4188 event
.xkey
.state
&= ~ControlMask
;
4189 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
4190 | dpyinfo
->super_mod_mask
4191 | dpyinfo
->hyper_mod_mask
4192 | dpyinfo
->alt_mod_mask
);
4194 /* In case Meta is ComposeCharacter,
4195 clear its status. According to Markus Ehrnsperger
4196 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
4197 this enables ComposeCharacter to work whether or
4198 not it is combined with Meta. */
4199 if (modifiers
& dpyinfo
->meta_mod_mask
)
4200 bzero (&compose_status
, sizeof (compose_status
));
4205 /* The necessity of the following line took me
4206 a full work-day to decipher from the docs!! */
4207 if (XFilterEvent (&event
, None
))
4209 nbytes
= XmbLookupString (FRAME_XIC (f
),
4210 &event
.xkey
, copy_buffer
,
4215 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4216 80, &keysym
, &compose_status
);
4218 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4219 80, &keysym
, &compose_status
);
4222 orig_keysym
= keysym
;
4226 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
4227 || keysym
== XK_Delete
4228 #ifdef XK_ISO_Left_Tab
4229 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
4231 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
4232 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
4234 /* This recognizes the "extended function keys".
4235 It seems there's no cleaner way.
4236 Test IsModifierKey to avoid handling mode_switch
4238 || ((unsigned) (keysym
) >= XK_Select
4239 && (unsigned)(keysym
) < XK_KP_Space
)
4241 #ifdef XK_dead_circumflex
4242 || orig_keysym
== XK_dead_circumflex
4244 #ifdef XK_dead_grave
4245 || orig_keysym
== XK_dead_grave
4247 #ifdef XK_dead_tilde
4248 || orig_keysym
== XK_dead_tilde
4250 #ifdef XK_dead_diaeresis
4251 || orig_keysym
== XK_dead_diaeresis
4253 #ifdef XK_dead_macron
4254 || orig_keysym
== XK_dead_macron
4256 #ifdef XK_dead_degree
4257 || orig_keysym
== XK_dead_degree
4259 #ifdef XK_dead_acute
4260 || orig_keysym
== XK_dead_acute
4262 #ifdef XK_dead_cedilla
4263 || orig_keysym
== XK_dead_cedilla
4265 #ifdef XK_dead_breve
4266 || orig_keysym
== XK_dead_breve
4268 #ifdef XK_dead_ogonek
4269 || orig_keysym
== XK_dead_ogonek
4271 #ifdef XK_dead_caron
4272 || orig_keysym
== XK_dead_caron
4274 #ifdef XK_dead_doubleacute
4275 || orig_keysym
== XK_dead_doubleacute
4277 #ifdef XK_dead_abovedot
4278 || orig_keysym
== XK_dead_abovedot
4280 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
4281 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
4282 /* Any "vendor-specific" key is ok. */
4283 || (orig_keysym
& (1 << 28)))
4284 && ! (IsModifierKey (orig_keysym
)
4286 #ifdef XK_Mode_switch
4287 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
4290 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
4292 #endif /* not HAVE_X11R5 */
4295 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4297 temp_buffer
[temp_index
++] = keysym
;
4298 bufp
->kind
= non_ascii_keystroke
;
4299 bufp
->code
= keysym
;
4300 XSETFRAME (bufp
->frame_or_window
, f
);
4302 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4304 bufp
->timestamp
= event
.xkey
.time
;
4309 else if (numchars
> nbytes
)
4313 for (i
= 0; i
< nbytes
; i
++)
4315 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4317 temp_buffer
[temp_index
++] = copy_buffer
[i
];
4318 bufp
->kind
= ascii_keystroke
;
4319 bufp
->code
= copy_buffer
[i
];
4320 XSETFRAME (bufp
->frame_or_window
, f
);
4322 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4324 bufp
->timestamp
= event
.xkey
.time
;
4339 /* Here's a possible interpretation of the whole
4340 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
4341 FocusIn event, you have to get a FocusOut event before you
4342 relinquish the focus. If you haven't received a FocusIn event,
4343 then a mere LeaveNotify is enough to free you. */
4346 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4348 if (event
.xcrossing
.focus
) /* Entered Window */
4350 /* Avoid nasty pop/raise loops. */
4351 if (f
&& (!(f
->auto_raise
)
4353 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
4355 x_new_focus_frame (dpyinfo
, f
);
4356 enter_timestamp
= event
.xcrossing
.time
;
4359 else if (f
== dpyinfo
->x_focus_frame
)
4360 x_new_focus_frame (dpyinfo
, 0);
4361 /* EnterNotify counts as mouse movement,
4362 so update things that depend on mouse position. */
4364 note_mouse_movement (f
, &event
.xmotion
);
4368 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4369 if (event
.xfocus
.detail
!= NotifyPointer
)
4370 dpyinfo
->x_focus_event_frame
= f
;
4372 x_new_focus_frame (dpyinfo
, f
);
4375 if (f
&& FRAME_XIC (f
))
4376 XSetICFocus (FRAME_XIC (f
));
4382 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4385 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4386 /* If we move outside the frame,
4387 then we're certainly no longer on any text in the frame. */
4388 clear_mouse_face (dpyinfo
);
4390 if (event
.xcrossing
.focus
)
4391 x_mouse_leave (dpyinfo
);
4394 if (f
== dpyinfo
->x_focus_event_frame
)
4395 dpyinfo
->x_focus_event_frame
= 0;
4396 if (f
== dpyinfo
->x_focus_frame
)
4397 x_new_focus_frame (dpyinfo
, 0);
4403 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4404 if (event
.xfocus
.detail
!= NotifyPointer
4405 && f
== dpyinfo
->x_focus_event_frame
)
4406 dpyinfo
->x_focus_event_frame
= 0;
4407 if (f
&& f
== dpyinfo
->x_focus_frame
)
4408 x_new_focus_frame (dpyinfo
, 0);
4411 if (f
&& FRAME_XIC (f
))
4412 XUnsetICFocus (FRAME_XIC (f
));
4419 if (dpyinfo
->grabbed
&& last_mouse_frame
4420 && FRAME_LIVE_P (last_mouse_frame
))
4421 f
= last_mouse_frame
;
4423 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
4425 note_mouse_movement (f
, &event
.xmotion
);
4428 struct scroll_bar
*bar
4429 = x_window_to_scroll_bar (event
.xmotion
.window
);
4432 x_scroll_bar_note_movement (bar
, &event
);
4434 /* If we move outside the frame,
4435 then we're certainly no longer on any text in the frame. */
4436 clear_mouse_face (dpyinfo
);
4441 case ConfigureNotify
:
4442 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
4445 #ifndef USE_X_TOOLKIT
4446 /* In the toolkit version, change_frame_size
4447 is called by the code that handles resizing
4448 of the EmacsFrame widget. */
4450 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4451 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4453 /* Even if the number of character rows and columns has
4454 not changed, the font size may have changed, so we need
4455 to check the pixel dimensions as well. */
4456 if (columns
!= f
->width
4457 || rows
!= f
->height
4458 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
4459 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
4461 change_frame_size (f
, rows
, columns
, 0, 1);
4462 SET_FRAME_GARBAGED (f
);
4463 cancel_mouse_face (f
);
4467 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
4468 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
4470 /* What we have now is the position of Emacs's own window.
4471 Convert that to the position of the window manager window. */
4472 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
4473 &f
->output_data
.x
->top_pos
);
4475 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4477 /* Since the WM decorations come below top_pos now,
4478 we must put them below top_pos in the future. */
4479 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4480 x_wm_set_size_hint (f
, (long) 0, 0);
4483 /* Some window managers pass (0,0) as the location of
4484 the window, and the Motif event handler stores it
4485 in the emacs widget, which messes up Motif menus. */
4486 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
4488 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
4489 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
4498 /* If we decide we want to generate an event to be seen
4499 by the rest of Emacs, we put it here. */
4500 struct input_event emacs_event
;
4501 emacs_event
.kind
= no_event
;
4503 bzero (&compose_status
, sizeof (compose_status
));
4505 if (dpyinfo
->grabbed
&& last_mouse_frame
4506 && FRAME_LIVE_P (last_mouse_frame
))
4507 f
= last_mouse_frame
;
4509 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4513 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4514 construct_mouse_click (&emacs_event
, &event
, f
);
4518 struct scroll_bar
*bar
4519 = x_window_to_scroll_bar (event
.xbutton
.window
);
4522 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4525 if (event
.type
== ButtonPress
)
4527 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4528 last_mouse_frame
= f
;
4532 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4535 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4537 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4543 #ifdef USE_X_TOOLKIT
4544 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4545 /* For a down-event in the menu bar,
4546 don't pass it to Xt right now.
4547 Instead, save it away
4548 and we will pass it to Xt from kbd_buffer_get_event.
4549 That way, we can run some Lisp code first. */
4550 if (f
&& event
.type
== ButtonPress
4551 /* Verify the event is really within the menu bar
4552 and not just sent to it due to grabbing. */
4553 && event
.xbutton
.x
>= 0
4554 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4555 && event
.xbutton
.y
>= 0
4556 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4557 && event
.xbutton
.same_screen
)
4559 SET_SAVED_BUTTON_EVENT
;
4560 XSETFRAME (last_mouse_press_frame
, f
);
4562 else if (event
.type
== ButtonPress
)
4564 last_mouse_press_frame
= Qnil
;
4567 #ifdef USE_MOTIF /* This should do not harm for Lucid,
4568 but I am trying to be cautious. */
4569 else if (event
.type
== ButtonRelease
)
4571 if (!NILP (last_mouse_press_frame
))
4573 f
= XFRAME (last_mouse_press_frame
);
4574 if (f
->output_data
.x
)
4576 SET_SAVED_BUTTON_EVENT
;
4582 #endif /* USE_MOTIF */
4585 #endif /* USE_X_TOOLKIT */
4589 case CirculateNotify
:
4591 case CirculateRequest
:
4595 /* Someone has changed the keyboard mapping - update the
4597 switch (event
.xmapping
.request
)
4599 case MappingModifier
:
4600 x_find_modifier_meanings (dpyinfo
);
4601 /* This is meant to fall through. */
4602 case MappingKeyboard
:
4603 XRefreshKeyboardMapping (&event
.xmapping
);
4609 #ifdef USE_X_TOOLKIT
4611 XtDispatchEvent (&event
);
4613 #endif /* USE_X_TOOLKIT */
4619 /* On some systems, an X bug causes Emacs to get no more events
4620 when the window is destroyed. Detect that. (1994.) */
4623 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4624 One XNOOP in 100 loops will make Emacs terminate.
4625 B. Bretthauer, 1994 */
4627 if (x_noop_count
>= 100)
4631 if (next_noop_dpyinfo
== 0)
4632 next_noop_dpyinfo
= x_display_list
;
4634 XNoOp (next_noop_dpyinfo
->display
);
4636 /* Each time we get here, cycle through the displays now open. */
4637 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4641 /* If the focus was just given to an autoraising frame,
4643 /* ??? This ought to be able to handle more than one such frame. */
4644 if (pending_autoraise_frame
)
4646 x_raise_frame (pending_autoraise_frame
);
4647 pending_autoraise_frame
= 0;
4654 /* Drawing the cursor. */
4657 /* Draw a hollow box cursor on frame F at X, Y.
4658 Don't change the inside of the box. */
4661 x_draw_box (f
, x
, y
)
4665 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4666 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4667 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4668 int height
= f
->output_data
.x
->line_height
;
4669 int c
= FAST_GLYPH_CHAR (f
->phys_cursor_glyph
);
4670 int charset
= CHAR_CHARSET (c
);
4673 unsigned long mask
= GCForeground
;
4675 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
4677 /* cursor_gc's foreground color is typically the same as the normal
4678 background color, which can cause the cursor box to be invisible. */
4679 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
4680 XChangeGC (FRAME_X_DISPLAY (f
),
4681 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
4684 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
4685 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), mask
, &xgcv
);
4687 /* If cursor is on a multi-column character, multiply WIDTH by columns. */
4688 width
*= (charset
== CHARSET_COMPOSITION
4689 ? cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->width
4690 : CHARSET_WIDTH (charset
));
4691 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4692 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
4693 left
, top
, width
- 1, height
- 1);
4696 /* Clear the cursor of frame F to background color,
4697 and mark the cursor as not shown.
4698 This is used when the text where the cursor is
4699 is about to be rewritten. */
4707 if (! FRAME_VISIBLE_P (f
)
4708 || ! f
->phys_cursor_on
)
4711 x_update_cursor (f
, 0);
4712 f
->phys_cursor_on
= 0;
4715 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4716 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4720 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4727 CHAR_TO_PIXEL_COL (f
, column
),
4728 CHAR_TO_PIXEL_ROW (f
, row
),
4729 &glyph
, 1, highlight
, 0, NULL
);
4733 x_display_bar_cursor (f
, on
, x
, y
)
4738 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4740 /* This is pointless on invisible frames, and dangerous on garbaged
4741 frames; in the latter case, the frame may be in the midst of
4742 changing its size, and x and y may be off the frame. */
4743 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4746 if (! on
&& ! f
->phys_cursor_on
)
4749 /* If there is anything wrong with the current cursor state, remove it. */
4750 if (f
->phys_cursor_on
4752 || f
->phys_cursor_x
!= x
4753 || f
->phys_cursor_y
!= y
4754 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4756 /* Erase the cursor by redrawing the character underneath it. */
4757 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4758 f
->phys_cursor_glyph
,
4759 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4760 f
->phys_cursor_on
= 0;
4763 /* If we now need a cursor in the new place or in the new form, do it so. */
4765 && (! f
->phys_cursor_on
4766 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4768 f
->phys_cursor_glyph
4769 = ((current_glyphs
->enable
[y
]
4770 && x
< current_glyphs
->used
[y
])
4771 ? current_glyphs
->glyphs
[y
][x
]
4773 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4774 f
->output_data
.x
->cursor_gc
,
4775 CHAR_TO_PIXEL_COL (f
, x
),
4776 CHAR_TO_PIXEL_ROW (f
, y
),
4777 max (f
->output_data
.x
->cursor_width
, 1),
4778 f
->output_data
.x
->line_height
);
4780 f
->phys_cursor_x
= x
;
4781 f
->phys_cursor_y
= y
;
4782 f
->phys_cursor_on
= 1;
4784 f
->output_data
.x
->current_cursor
= bar_cursor
;
4787 if (updating_frame
!= f
)
4788 XFlush (FRAME_X_DISPLAY (f
));
4792 /* Turn the displayed cursor of frame F on or off according to ON.
4793 If ON is nonzero, where to put the cursor is specified by X and Y. */
4796 x_display_box_cursor (f
, on
, x
, y
)
4801 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4803 /* This is pointless on invisible frames, and dangerous on garbaged
4804 frames; in the latter case, the frame may be in the midst of
4805 changing its size, and x and y may be off the frame. */
4806 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4809 /* If cursor is off and we want it off, return quickly. */
4810 if (!on
&& ! f
->phys_cursor_on
)
4813 /* If cursor is currently being shown and we don't want it to be
4814 or it is in the wrong place,
4815 or we want a hollow box and it's not so, (pout!)
4817 if (f
->phys_cursor_on
4819 || f
->phys_cursor_x
!= x
4820 || f
->phys_cursor_y
!= y
4821 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4822 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4824 int mouse_face_here
= 0;
4825 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4827 /* If the cursor is in the mouse face area, redisplay that when
4828 we clear the cursor. */
4829 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4831 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4832 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4833 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4835 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4836 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4837 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4838 /* Don't redraw the cursor's spot in mouse face
4839 if it is at the end of a line (on a newline).
4840 The cursor appears there, but mouse highlighting does not. */
4841 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4842 mouse_face_here
= 1;
4844 /* If the font is not as tall as a whole line,
4845 we must explicitly clear the line's whole height. */
4846 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4847 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4848 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4849 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4850 FONT_WIDTH (f
->output_data
.x
->font
),
4851 f
->output_data
.x
->line_height
, False
);
4852 /* Erase the cursor by redrawing the character underneath it. */
4853 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4854 f
->phys_cursor_glyph
,
4857 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4858 f
->phys_cursor_on
= 0;
4861 /* If we want to show a cursor,
4862 or we want a box cursor and it's not so,
4863 write it in the right place. */
4865 && (! f
->phys_cursor_on
4866 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4867 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4869 f
->phys_cursor_glyph
4870 = ((current_glyphs
->enable
[y
]
4871 && x
< current_glyphs
->used
[y
])
4872 ? current_glyphs
->glyphs
[y
][x
]
4874 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4876 x_draw_box (f
, x
, y
);
4877 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4881 x_draw_single_glyph (f
, y
, x
,
4882 f
->phys_cursor_glyph
, 2);
4883 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4886 f
->phys_cursor_x
= x
;
4887 f
->phys_cursor_y
= y
;
4888 f
->phys_cursor_on
= 1;
4891 if (updating_frame
!= f
)
4892 XFlush (FRAME_X_DISPLAY (f
));
4895 /* Display the cursor on frame F, or clear it, according to ON.
4896 Also set the frame's cursor position to X and Y. */
4898 x_display_cursor (f
, on
, x
, y
)
4905 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4906 x_display_box_cursor (f
, on
, x
, y
);
4907 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4908 x_display_bar_cursor (f
, on
, x
, y
);
4910 /* Those are the only two we have implemented! */
4916 /* Display the cursor on frame F, or clear it, according to ON.
4917 Don't change the cursor's position. */
4919 x_update_cursor (f
, on
)
4925 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4926 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4927 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4928 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4930 /* Those are the only two we have implemented! */
4938 /* Refresh bitmap kitchen sink icon for frame F
4939 when we get an expose event for it. */
4944 /* Normally, the window manager handles this function. */
4947 /* Make the x-window of frame F use the gnu icon bitmap. */
4950 x_bitmap_icon (f
, file
)
4954 int mask
, bitmap_id
;
4957 if (FRAME_X_WINDOW (f
) == 0)
4960 /* Free up our existing icon bitmap if any. */
4961 if (f
->output_data
.x
->icon_bitmap
> 0)
4962 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4963 f
->output_data
.x
->icon_bitmap
= 0;
4966 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4969 /* Create the GNU bitmap if necessary. */
4970 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4971 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4972 = x_create_bitmap_from_data (f
, gnu_bits
,
4973 gnu_width
, gnu_height
);
4975 /* The first time we create the GNU bitmap,
4976 this increments the refcount one extra time.
4977 As a result, the GNU bitmap is never freed.
4978 That way, we don't have to worry about allocating it again. */
4979 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4981 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4984 x_wm_set_icon_pixmap (f
, bitmap_id
);
4985 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4991 /* Make the x-window of frame F use a rectangle with text.
4992 Use ICON_NAME as the text. */
4995 x_text_icon (f
, icon_name
)
4999 if (FRAME_X_WINDOW (f
) == 0)
5005 text
.value
= (unsigned char *) icon_name
;
5006 text
.encoding
= XA_STRING
;
5008 text
.nitems
= strlen (icon_name
);
5009 #ifdef USE_X_TOOLKIT
5010 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5012 #else /* not USE_X_TOOLKIT */
5013 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
5014 #endif /* not USE_X_TOOLKIT */
5016 #else /* not HAVE_X11R4 */
5017 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
5018 #endif /* not HAVE_X11R4 */
5020 if (f
->output_data
.x
->icon_bitmap
> 0)
5021 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
5022 f
->output_data
.x
->icon_bitmap
= 0;
5023 x_wm_set_icon_pixmap (f
, 0);
5028 #define X_ERROR_MESSAGE_SIZE 200
5030 /* If non-nil, this should be a string.
5031 It means catch X errors and store the error message in this string. */
5033 static Lisp_Object x_error_message_string
;
5035 /* An X error handler which stores the error message in
5036 x_error_message_string. This is called from x_error_handler if
5037 x_catch_errors is in effect. */
5040 x_error_catcher (display
, error
)
5044 XGetErrorText (display
, error
->error_code
,
5045 XSTRING (x_error_message_string
)->data
,
5046 X_ERROR_MESSAGE_SIZE
);
5049 /* Begin trapping X errors for display DPY. Actually we trap X errors
5050 for all displays, but DPY should be the display you are actually
5053 After calling this function, X protocol errors no longer cause
5054 Emacs to exit; instead, they are recorded in the string
5055 stored in x_error_message_string.
5057 Calling x_check_errors signals an Emacs error if an X error has
5058 occurred since the last call to x_catch_errors or x_check_errors.
5060 Calling x_uncatch_errors resumes the normal error handling. */
5062 void x_check_errors ();
5063 static Lisp_Object
x_catch_errors_unwind ();
5066 x_catch_errors (dpy
)
5069 int count
= specpdl_ptr
- specpdl
;
5071 /* Make sure any errors from previous requests have been dealt with. */
5074 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
5076 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
5077 XSTRING (x_error_message_string
)->data
[0] = 0;
5082 /* Unbind the binding that we made to check for X errors. */
5085 x_catch_errors_unwind (old_val
)
5086 Lisp_Object old_val
;
5088 x_error_message_string
= old_val
;
5092 /* If any X protocol errors have arrived since the last call to
5093 x_catch_errors or x_check_errors, signal an Emacs error using
5094 sprintf (a buffer, FORMAT, the x error message text) as the text. */
5097 x_check_errors (dpy
, format
)
5101 /* Make sure to catch any errors incurred so far. */
5104 if (XSTRING (x_error_message_string
)->data
[0])
5105 error (format
, XSTRING (x_error_message_string
)->data
);
5108 /* Nonzero if we had any X protocol errors
5109 since we did x_catch_errors on DPY. */
5112 x_had_errors_p (dpy
)
5115 /* Make sure to catch any errors incurred so far. */
5118 return XSTRING (x_error_message_string
)->data
[0] != 0;
5121 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
5124 x_clear_errors (dpy
)
5127 XSTRING (x_error_message_string
)->data
[0] = 0;
5130 /* Stop catching X protocol errors and let them make Emacs die.
5131 DPY should be the display that was passed to x_catch_errors.
5132 COUNT should be the value that was returned by
5133 the corresponding call to x_catch_errors. */
5136 x_uncatch_errors (dpy
, count
)
5140 unbind_to (count
, Qnil
);
5144 static unsigned int x_wire_count
;
5147 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5152 /* Handle SIGPIPE, which can happen when the connection to a server
5153 simply goes away. SIGPIPE is handled by x_connection_signal.
5154 Don't need to do anything, because the write which caused the
5155 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
5156 which will do the appropriate cleanup for us. */
5159 x_connection_signal (signalnum
) /* If we don't have an argument, */
5160 int signalnum
; /* some compilers complain in signal calls. */
5163 /* USG systems forget handlers when they are used;
5164 must reestablish each time */
5165 signal (signalnum
, x_connection_signal
);
5169 /* Handling X errors. */
5171 /* Handle the loss of connection to display DISPLAY. */
5174 x_connection_closed (display
, error_message
)
5176 char *error_message
;
5178 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
5179 Lisp_Object frame
, tail
;
5181 /* Indicate that this display is dead. */
5183 #ifdef USE_X_TOOLKIT
5184 XtCloseDisplay (display
);
5187 dpyinfo
->display
= 0;
5189 /* First delete frames whose minibuffers are on frames
5190 that are on the dead display. */
5191 FOR_EACH_FRAME (tail
, frame
)
5193 Lisp_Object minibuf_frame
;
5195 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
5196 if (FRAME_X_P (XFRAME (frame
))
5197 && FRAME_X_P (XFRAME (minibuf_frame
))
5198 && ! EQ (frame
, minibuf_frame
)
5199 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
5200 Fdelete_frame (frame
, Qt
);
5203 /* Now delete all remaining frames on the dead display.
5204 We are now sure none of these is used as the minibuffer
5205 for another frame that we need to delete. */
5206 FOR_EACH_FRAME (tail
, frame
)
5207 if (FRAME_X_P (XFRAME (frame
))
5208 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
5210 /* Set this to t so that Fdelete_frame won't get confused
5211 trying to find a replacement. */
5212 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
5213 Fdelete_frame (frame
, Qt
);
5217 x_delete_display (dpyinfo
);
5219 if (x_display_list
== 0)
5221 fprintf (stderr
, "%s\n", error_message
);
5222 shut_down_emacs (0, 0, Qnil
);
5226 /* Ordinary stack unwind doesn't deal with these. */
5228 sigunblock (sigmask (SIGIO
));
5230 sigunblock (sigmask (SIGALRM
));
5231 TOTALLY_UNBLOCK_INPUT
;
5233 clear_waiting_for_input ();
5234 error ("%s", error_message
);
5237 /* This is the usual handler for X protocol errors.
5238 It kills all frames on the display that we got the error for.
5239 If that was the only one, it prints an error message and kills Emacs. */
5242 x_error_quitter (display
, error
)
5246 char buf
[256], buf1
[356];
5248 /* Note that there is no real way portable across R3/R4 to get the
5249 original error handler. */
5251 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
5252 sprintf (buf1
, "X protocol error: %s on protocol request %d",
5253 buf
, error
->request_code
);
5254 x_connection_closed (display
, buf1
);
5257 /* This is the first-level handler for X protocol errors.
5258 It calls x_error_quitter or x_error_catcher. */
5261 x_error_handler (display
, error
)
5265 char buf
[256], buf1
[356];
5267 if (! NILP (x_error_message_string
))
5268 x_error_catcher (display
, error
);
5270 x_error_quitter (display
, error
);
5273 /* This is the handler for X IO errors, always.
5274 It kills all frames on the display that we lost touch with.
5275 If that was the only one, it prints an error message and kills Emacs. */
5278 x_io_error_quitter (display
)
5283 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
5284 x_connection_closed (display
, buf
);
5287 /* Changing the font of the frame. */
5289 /* Give frame F the font named FONTNAME as its default font, and
5290 return the full name of that font. FONTNAME may be a wildcard
5291 pattern; in that case, we choose some font that fits the pattern.
5292 The return value shows which font we chose. */
5295 x_new_font (f
, fontname
)
5297 register char *fontname
;
5299 struct font_info
*fontp
5300 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
5305 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
5306 f
->output_data
.x
->font_baseline
5307 = (f
->output_data
.x
->font
->ascent
+ fontp
->baseline_offset
);
5308 f
->output_data
.x
->fontset
= -1;
5310 /* Compute the scroll bar width in character columns. */
5311 if (f
->scroll_bar_pixel_width
> 0)
5313 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
5314 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
5318 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
5319 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
5322 /* Now make the frame display the given font. */
5323 if (FRAME_X_WINDOW (f
) != 0)
5325 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
5326 f
->output_data
.x
->font
->fid
);
5327 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
5328 f
->output_data
.x
->font
->fid
);
5329 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
5330 f
->output_data
.x
->font
->fid
);
5332 frame_update_line_height (f
);
5333 x_set_window_size (f
, 0, f
->width
, f
->height
);
5336 /* If we are setting a new frame's font for the first time,
5337 there are no faces yet, so this font's height is the line height. */
5338 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
5340 return build_string (fontp
->full_name
);
5343 /* Give frame F the fontset named FONTSETNAME as its default font, and
5344 return the full name of that fontset. FONTSETNAME may be a wildcard
5345 pattern; in that case, we choose some fontset that fits the pattern.
5346 The return value shows which fontset we chose. */
5349 x_new_fontset (f
, fontsetname
)
5353 int fontset
= fs_query_fontset (f
, fontsetname
);
5354 struct fontset_info
*fontsetp
;
5360 if (f
->output_data
.x
->fontset
== fontset
)
5361 /* This fontset is already set in frame F. There's nothing more
5363 return build_string (fontsetname
);
5365 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
5367 if (!fontsetp
->fontname
[CHARSET_ASCII
])
5368 /* This fontset doesn't contain ASCII font. */
5371 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
5373 if (!STRINGP (result
))
5374 /* Can't load ASCII font. */
5377 /* Since x_new_font doesn't update any fontset information, do it now. */
5378 f
->output_data
.x
->fontset
= fontset
;
5379 FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
5380 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
5382 return build_string (fontsetname
);
5385 /* Calculate the absolute position in frame F
5386 from its current recorded position values and gravity. */
5388 x_calc_absolute_position (f
)
5392 int win_x
= 0, win_y
= 0;
5393 int flags
= f
->output_data
.x
->size_hint_flags
;
5396 /* We have nothing to do if the current position
5397 is already for the top-left corner. */
5398 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5401 #ifdef USE_X_TOOLKIT
5402 this_window
= XtWindow (f
->output_data
.x
->widget
);
5404 this_window
= FRAME_X_WINDOW (f
);
5407 /* Find the position of the outside upper-left corner of
5408 the inner window, with respect to the outer window.
5409 But do this only if we will need the results. */
5410 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
5415 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
5418 x_clear_errors (FRAME_X_DISPLAY (f
));
5419 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
5421 /* From-window, to-window. */
5423 f
->output_data
.x
->parent_desc
,
5425 /* From-position, to-position. */
5426 0, 0, &win_x
, &win_y
,
5430 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
5432 Window newroot
, newparent
= 0xdeadbeef;
5433 Window
*newchildren
;
5436 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
5437 &newparent
, &newchildren
, &nchildren
))
5440 XFree (newchildren
);
5442 f
->output_data
.x
->parent_desc
= newparent
;
5448 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
5452 /* Treat negative positions as relative to the leftmost bottommost
5453 position that fits on the screen. */
5454 if (flags
& XNegative
)
5455 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
5456 - 2 * f
->output_data
.x
->border_width
- win_x
5458 + f
->output_data
.x
->left_pos
);
5460 if (flags
& YNegative
)
5461 /* We used to subtract f->output_data.x->menubar_height here
5462 in the toolkit case, but PIXEL_HEIGHT already includes that. */
5463 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
5464 - 2 * f
->output_data
.x
->border_width
- win_y
5466 + f
->output_data
.x
->top_pos
);
5468 /* The left_pos and top_pos
5469 are now relative to the top and left screen edges,
5470 so the flags should correspond. */
5471 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5474 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5475 to really change the position, and 0 when calling from
5476 x_make_frame_visible (in that case, XOFF and YOFF are the current
5477 position values). It is -1 when calling from x_set_frame_parameters,
5478 which means, do adjust for borders but don't change the gravity. */
5480 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5482 register int xoff
, yoff
;
5485 int modified_top
, modified_left
;
5487 if (change_gravity
> 0)
5489 f
->output_data
.x
->top_pos
= yoff
;
5490 f
->output_data
.x
->left_pos
= xoff
;
5491 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5493 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5495 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5496 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5498 x_calc_absolute_position (f
);
5501 x_wm_set_size_hint (f
, (long) 0, 0);
5503 modified_left
= f
->output_data
.x
->left_pos
;
5504 modified_top
= f
->output_data
.x
->top_pos
;
5505 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
5506 this seems to be unnecessary and incorrect. rms, 4/17/97. */
5507 /* It is a mystery why we need to add the border_width here
5508 when the frame is already visible, but experiment says we do. */
5509 if (change_gravity
!= 0)
5511 modified_left
+= f
->output_data
.x
->border_width
;
5512 modified_top
+= f
->output_data
.x
->border_width
;
5516 #ifdef USE_X_TOOLKIT
5517 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5518 modified_left
, modified_top
);
5519 #else /* not USE_X_TOOLKIT */
5520 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5521 modified_left
, modified_top
);
5522 #endif /* not USE_X_TOOLKIT */
5526 /* Call this to change the size of frame F's x-window.
5527 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5528 for this size change and subsequent size changes.
5529 Otherwise we leave the window gravity unchanged. */
5531 x_set_window_size (f
, change_gravity
, cols
, rows
)
5536 int pixelwidth
, pixelheight
;
5538 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5542 #ifdef USE_X_TOOLKIT
5544 /* The x and y position of the widget is clobbered by the
5545 call to XtSetValues within EmacsFrameSetCharSize.
5546 This is a real kludge, but I don't understand Xt so I can't
5547 figure out a correct fix. Can anyone else tell me? -- rms. */
5548 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5549 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5550 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5551 f
->output_data
.x
->widget
->core
.x
= xpos
;
5552 f
->output_data
.x
->widget
->core
.y
= ypos
;
5555 #else /* not USE_X_TOOLKIT */
5557 check_frame_size (f
, &rows
, &cols
);
5558 f
->output_data
.x
->vertical_scroll_bar_extra
5559 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5561 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5562 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5563 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5564 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5565 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5567 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5568 x_wm_set_size_hint (f
, (long) 0, 0);
5570 XSync (FRAME_X_DISPLAY (f
), False
);
5571 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5572 pixelwidth
, pixelheight
);
5574 /* Now, strictly speaking, we can't be sure that this is accurate,
5575 but the window manager will get around to dealing with the size
5576 change request eventually, and we'll hear how it went when the
5577 ConfigureNotify event gets here.
5579 We could just not bother storing any of this information here,
5580 and let the ConfigureNotify event set everything up, but that
5581 might be kind of confusing to the lisp code, since size changes
5582 wouldn't be reported in the frame parameters until some random
5583 point in the future when the ConfigureNotify event arrives. */
5584 change_frame_size (f
, rows
, cols
, 0, 0);
5585 PIXEL_WIDTH (f
) = pixelwidth
;
5586 PIXEL_HEIGHT (f
) = pixelheight
;
5588 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5589 receive in the ConfigureNotify event; if we get what we asked
5590 for, then the event won't cause the screen to become garbaged, so
5591 we have to make sure to do it here. */
5592 SET_FRAME_GARBAGED (f
);
5594 XFlush (FRAME_X_DISPLAY (f
));
5596 #endif /* not USE_X_TOOLKIT */
5598 /* If cursor was outside the new size, mark it as off. */
5599 if (f
->phys_cursor_y
>= rows
5600 || f
->phys_cursor_x
>= cols
)
5602 f
->phys_cursor_x
= 0;
5603 f
->phys_cursor_y
= 0;
5604 f
->phys_cursor_on
= 0;
5607 /* Clear out any recollection of where the mouse highlighting was,
5608 since it might be in a place that's outside the new frame size.
5609 Actually checking whether it is outside is a pain in the neck,
5610 so don't try--just let the highlighting be done afresh with new size. */
5611 cancel_mouse_face (f
);
5616 /* Mouse warping. */
5619 x_set_mouse_position (f
, x
, y
)
5625 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5626 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5628 if (pix_x
< 0) pix_x
= 0;
5629 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5631 if (pix_y
< 0) pix_y
= 0;
5632 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5636 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5637 0, 0, 0, 0, pix_x
, pix_y
);
5641 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5644 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5650 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5651 0, 0, 0, 0, pix_x
, pix_y
);
5655 /* focus shifting, raising and lowering. */
5657 x_focus_on_frame (f
)
5660 #if 0 /* This proves to be unpleasant. */
5664 /* I don't think that the ICCCM allows programs to do things like this
5665 without the interaction of the window manager. Whatever you end up
5666 doing with this code, do it to x_unfocus_frame too. */
5667 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5668 RevertToPointerRoot
, CurrentTime
);
5676 /* Look at the remarks in x_focus_on_frame. */
5677 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5678 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5679 RevertToPointerRoot
, CurrentTime
);
5683 /* Raise frame F. */
5688 if (f
->async_visible
)
5691 #ifdef USE_X_TOOLKIT
5692 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5693 #else /* not USE_X_TOOLKIT */
5694 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5695 #endif /* not USE_X_TOOLKIT */
5696 XFlush (FRAME_X_DISPLAY (f
));
5701 /* Lower frame F. */
5706 if (f
->async_visible
)
5709 #ifdef USE_X_TOOLKIT
5710 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5711 #else /* not USE_X_TOOLKIT */
5712 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5713 #endif /* not USE_X_TOOLKIT */
5714 XFlush (FRAME_X_DISPLAY (f
));
5720 XTframe_raise_lower (f
, raise_flag
)
5730 /* Change of visibility. */
5732 /* This tries to wait until the frame is really visible.
5733 However, if the window manager asks the user where to position
5734 the frame, this will return before the user finishes doing that.
5735 The frame will not actually be visible at that time,
5736 but it will become visible later when the window manager
5737 finishes with it. */
5739 x_make_frame_visible (f
)
5744 int starting_flags
= f
->output_data
.x
->size_hint_flags
;
5745 int original_top
, original_left
;
5749 type
= x_icon_type (f
);
5751 x_bitmap_icon (f
, type
);
5753 if (! FRAME_VISIBLE_P (f
))
5755 /* We test FRAME_GARBAGED_P here to make sure we don't
5756 call x_set_offset a second time
5757 if we get to x_make_frame_visible a second time
5758 before the window gets really visible. */
5759 if (! FRAME_ICONIFIED_P (f
)
5760 && ! f
->output_data
.x
->asked_for_visible
)
5761 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5763 f
->output_data
.x
->asked_for_visible
= 1;
5765 if (! EQ (Vx_no_window_manager
, Qt
))
5766 x_wm_set_window_state (f
, NormalState
);
5767 #ifdef USE_X_TOOLKIT
5768 /* This was XtPopup, but that did nothing for an iconified frame. */
5769 XtMapWidget (f
->output_data
.x
->widget
);
5770 #else /* not USE_X_TOOLKIT */
5771 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5772 #endif /* not USE_X_TOOLKIT */
5773 #if 0 /* This seems to bring back scroll bars in the wrong places
5774 if the window configuration has changed. They seem
5775 to come back ok without this. */
5776 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5777 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5781 XFlush (FRAME_X_DISPLAY (f
));
5783 /* Synchronize to ensure Emacs knows the frame is visible
5784 before we do anything else. We do this loop with input not blocked
5785 so that incoming events are handled. */
5788 int count
= input_signal_count
;
5789 /* This must be before UNBLOCK_INPUT
5790 since events that arrive in response to the actions above
5791 will set it when they are handled. */
5792 int previously_visible
= f
->output_data
.x
->has_been_visible
;
5794 original_left
= f
->output_data
.x
->left_pos
;
5795 original_top
= f
->output_data
.x
->top_pos
;
5797 /* This must come after we set COUNT. */
5800 /* Arriving X events are processed here. */
5802 /* Now move the window back to where it was "supposed to be".
5803 But don't do it if the gravity is negative.
5804 When the gravity is negative, this uses a position
5805 that is 3 pixels too low. Perhaps that's really the border width.
5807 Don't do this if the window has never been visible before,
5808 because the window manager may choose the position
5809 and we don't want to override it. */
5811 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
5812 && f
->output_data
.x
->win_gravity
== NorthWestGravity
5813 && previously_visible
)
5817 #ifdef USE_X_TOOLKIT
5818 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5819 original_left
, original_top
);
5820 #else /* not USE_X_TOOLKIT */
5821 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5822 original_left
, original_top
);
5823 #endif /* not USE_X_TOOLKIT */
5827 XSETFRAME (frame
, f
);
5832 /* Once we have handled input events,
5833 we should have received the MapNotify if one is coming.
5834 So if we have not got it yet, stop looping.
5835 Some window managers make their own decisions
5836 about visibility. */
5837 if (input_signal_count
!= count
)
5839 /* Machines that do polling rather than SIGIO have been observed
5840 to go into a busy-wait here. So we'll fake an alarm signal
5841 to let the handler know that there's something to be read.
5842 We used to raise a real alarm, but it seems that the handler
5843 isn't always enabled here. This is probably a bug. */
5844 if (input_polling_used ())
5846 /* It could be confusing if a real alarm arrives while processing
5847 the fake one. Turn it off and let the handler reset it. */
5849 input_poll_signal ();
5851 /* Once we have handled input events,
5852 we should have received the MapNotify if one is coming.
5853 So if we have not got it yet, stop looping.
5854 Some window managers make their own decisions
5855 about visibility. */
5856 if (input_signal_count
!= count
)
5859 FRAME_SAMPLE_VISIBILITY (f
);
5863 /* Change from mapped state to withdrawn state. */
5865 /* Make the frame visible (mapped and not iconified). */
5867 x_make_frame_invisible (f
)
5873 #ifdef USE_X_TOOLKIT
5874 /* Use the frame's outermost window, not the one we normally draw on. */
5875 window
= XtWindow (f
->output_data
.x
->widget
);
5876 #else /* not USE_X_TOOLKIT */
5877 window
= FRAME_X_WINDOW (f
);
5878 #endif /* not USE_X_TOOLKIT */
5880 /* Don't keep the highlight on an invisible frame. */
5881 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5882 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5884 #if 0/* This might add unreliability; I don't trust it -- rms. */
5885 if (! f
->async_visible
&& ! f
->async_iconified
)
5891 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5892 that the current position of the window is user-specified, rather than
5893 program-specified, so that when the window is mapped again, it will be
5894 placed at the same location, without forcing the user to position it
5895 by hand again (they have already done that once for this window.) */
5896 x_wm_set_size_hint (f
, (long) 0, 1);
5900 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5901 DefaultScreen (FRAME_X_DISPLAY (f
))))
5903 UNBLOCK_INPUT_RESIGNAL
;
5904 error ("Can't notify window manager of window withdrawal");
5906 #else /* ! defined (HAVE_X11R4) */
5908 /* Tell the window manager what we're going to do. */
5909 if (! EQ (Vx_no_window_manager
, Qt
))
5913 unmap
.xunmap
.type
= UnmapNotify
;
5914 unmap
.xunmap
.window
= window
;
5915 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5916 unmap
.xunmap
.from_configure
= False
;
5917 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5918 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5920 SubstructureRedirectMask
|SubstructureNotifyMask
,
5923 UNBLOCK_INPUT_RESIGNAL
;
5924 error ("Can't notify window manager of withdrawal");
5928 /* Unmap the window ourselves. Cheeky! */
5929 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5930 #endif /* ! defined (HAVE_X11R4) */
5932 /* We can't distinguish this from iconification
5933 just by the event that we get from the server.
5934 So we can't win using the usual strategy of letting
5935 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5936 and synchronize with the server to make sure we agree. */
5938 FRAME_ICONIFIED_P (f
) = 0;
5939 f
->async_visible
= 0;
5940 f
->async_iconified
= 0;
5947 /* Change window state from mapped to iconified. */
5956 /* Don't keep the highlight on an invisible frame. */
5957 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5958 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5960 if (f
->async_iconified
)
5965 FRAME_SAMPLE_VISIBILITY (f
);
5967 type
= x_icon_type (f
);
5969 x_bitmap_icon (f
, type
);
5971 #ifdef USE_X_TOOLKIT
5973 if (! FRAME_VISIBLE_P (f
))
5975 if (! EQ (Vx_no_window_manager
, Qt
))
5976 x_wm_set_window_state (f
, IconicState
);
5977 /* This was XtPopup, but that did nothing for an iconified frame. */
5978 XtMapWidget (f
->output_data
.x
->widget
);
5979 /* The server won't give us any event to indicate
5980 that an invisible frame was changed to an icon,
5981 so we have to record it here. */
5984 f
->async_iconified
= 1;
5985 f
->async_visible
= 0;
5990 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5991 XtWindow (f
->output_data
.x
->widget
),
5992 DefaultScreen (FRAME_X_DISPLAY (f
)));
5996 error ("Can't notify window manager of iconification");
5998 f
->async_iconified
= 1;
5999 f
->async_visible
= 0;
6003 XFlush (FRAME_X_DISPLAY (f
));
6005 #else /* not USE_X_TOOLKIT */
6007 /* Make sure the X server knows where the window should be positioned,
6008 in case the user deiconifies with the window manager. */
6009 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
6010 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
6012 /* Since we don't know which revision of X we're running, we'll use both
6013 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
6015 /* X11R4: send a ClientMessage to the window manager using the
6016 WM_CHANGE_STATE type. */
6020 message
.xclient
.window
= FRAME_X_WINDOW (f
);
6021 message
.xclient
.type
= ClientMessage
;
6022 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
6023 message
.xclient
.format
= 32;
6024 message
.xclient
.data
.l
[0] = IconicState
;
6026 if (! XSendEvent (FRAME_X_DISPLAY (f
),
6027 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
6029 SubstructureRedirectMask
| SubstructureNotifyMask
,
6032 UNBLOCK_INPUT_RESIGNAL
;
6033 error ("Can't notify window manager of iconification");
6037 /* X11R3: set the initial_state field of the window manager hints to
6039 x_wm_set_window_state (f
, IconicState
);
6041 if (!FRAME_VISIBLE_P (f
))
6043 /* If the frame was withdrawn, before, we must map it. */
6044 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
6047 f
->async_iconified
= 1;
6048 f
->async_visible
= 0;
6050 XFlush (FRAME_X_DISPLAY (f
));
6052 #endif /* not USE_X_TOOLKIT */
6055 /* Destroy the X window of frame F. */
6057 x_destroy_window (f
)
6060 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6064 /* If a display connection is dead, don't try sending more
6065 commands to the X server. */
6066 if (dpyinfo
->display
!= 0)
6068 if (f
->output_data
.x
->icon_desc
!= 0)
6069 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
6073 XDestroyIC (FRAME_XIC (f
));
6074 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
6075 /* This line causes crashes on Solaris with Openwin,
6076 due to an apparent bug in XCloseIM.
6077 X11R6 seems not to have the bug. */
6078 XCloseIM (FRAME_XIM (f
));
6082 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
6083 #ifdef USE_X_TOOLKIT
6084 XtDestroyWidget (f
->output_data
.x
->widget
);
6085 free_frame_menubar (f
);
6086 #endif /* USE_X_TOOLKIT */
6088 free_frame_faces (f
);
6089 XFlush (FRAME_X_DISPLAY (f
));
6092 if (f
->output_data
.x
->saved_menu_event
)
6093 free (f
->output_data
.x
->saved_menu_event
);
6095 xfree (f
->output_data
.x
);
6096 f
->output_data
.x
= 0;
6097 if (f
== dpyinfo
->x_focus_frame
)
6098 dpyinfo
->x_focus_frame
= 0;
6099 if (f
== dpyinfo
->x_focus_event_frame
)
6100 dpyinfo
->x_focus_event_frame
= 0;
6101 if (f
== dpyinfo
->x_highlight_frame
)
6102 dpyinfo
->x_highlight_frame
= 0;
6104 dpyinfo
->reference_count
--;
6106 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6108 dpyinfo
->mouse_face_beg_row
6109 = dpyinfo
->mouse_face_beg_col
= -1;
6110 dpyinfo
->mouse_face_end_row
6111 = dpyinfo
->mouse_face_end_col
= -1;
6112 dpyinfo
->mouse_face_window
= Qnil
;
6118 /* Setting window manager hints. */
6120 /* Set the normal size hints for the window manager, for frame F.
6121 FLAGS is the flags word to use--or 0 meaning preserve the flags
6122 that the window now has.
6123 If USER_POSITION is nonzero, we set the USPosition
6124 flag (this is useful when FLAGS is 0). */
6126 x_wm_set_size_hint (f
, flags
, user_position
)
6131 XSizeHints size_hints
;
6133 #ifdef USE_X_TOOLKIT
6136 Dimension widget_width
, widget_height
;
6137 Window window
= XtWindow (f
->output_data
.x
->widget
);
6138 #else /* not USE_X_TOOLKIT */
6139 Window window
= FRAME_X_WINDOW (f
);
6140 #endif /* not USE_X_TOOLKIT */
6142 /* Setting PMaxSize caused various problems. */
6143 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
6145 flexlines
= f
->height
;
6147 size_hints
.x
= f
->output_data
.x
->left_pos
;
6148 size_hints
.y
= f
->output_data
.x
->top_pos
;
6150 #ifdef USE_X_TOOLKIT
6151 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
6152 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
6153 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
6154 size_hints
.height
= widget_height
;
6155 size_hints
.width
= widget_width
;
6156 #else /* not USE_X_TOOLKIT */
6157 size_hints
.height
= PIXEL_HEIGHT (f
);
6158 size_hints
.width
= PIXEL_WIDTH (f
);
6159 #endif /* not USE_X_TOOLKIT */
6161 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
6162 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
6163 size_hints
.max_width
6164 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
6165 size_hints
.max_height
6166 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
6168 /* Calculate the base and minimum sizes.
6170 (When we use the X toolkit, we don't do it here.
6171 Instead we copy the values that the widgets are using, below.) */
6172 #ifndef USE_X_TOOLKIT
6174 int base_width
, base_height
;
6175 int min_rows
= 0, min_cols
= 0;
6177 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
6178 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
6180 check_frame_size (f
, &min_rows
, &min_cols
);
6182 /* The window manager uses the base width hints to calculate the
6183 current number of rows and columns in the frame while
6184 resizing; min_width and min_height aren't useful for this
6185 purpose, since they might not give the dimensions for a
6186 zero-row, zero-column frame.
6188 We use the base_width and base_height members if we have
6189 them; otherwise, we set the min_width and min_height members
6190 to the size for a zero x zero frame. */
6193 size_hints
.flags
|= PBaseSize
;
6194 size_hints
.base_width
= base_width
;
6195 size_hints
.base_height
= base_height
;
6196 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
6197 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
6199 size_hints
.min_width
= base_width
;
6200 size_hints
.min_height
= base_height
;
6204 /* If we don't need the old flags, we don't need the old hint at all. */
6207 size_hints
.flags
|= flags
;
6210 #endif /* not USE_X_TOOLKIT */
6213 XSizeHints hints
; /* Sometimes I hate X Windows... */
6214 long supplied_return
;
6218 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
6221 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
6224 #ifdef USE_X_TOOLKIT
6225 size_hints
.base_height
= hints
.base_height
;
6226 size_hints
.base_width
= hints
.base_width
;
6227 size_hints
.min_height
= hints
.min_height
;
6228 size_hints
.min_width
= hints
.min_width
;
6232 size_hints
.flags
|= flags
;
6237 if (hints
.flags
& PSize
)
6238 size_hints
.flags
|= PSize
;
6239 if (hints
.flags
& PPosition
)
6240 size_hints
.flags
|= PPosition
;
6241 if (hints
.flags
& USPosition
)
6242 size_hints
.flags
|= USPosition
;
6243 if (hints
.flags
& USSize
)
6244 size_hints
.flags
|= USSize
;
6251 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
6252 size_hints
.flags
|= PWinGravity
;
6256 size_hints
.flags
&= ~ PPosition
;
6257 size_hints
.flags
|= USPosition
;
6259 #endif /* PWinGravity */
6262 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6264 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6268 /* Used for IconicState or NormalState */
6269 x_wm_set_window_state (f
, state
)
6273 #ifdef USE_X_TOOLKIT
6276 XtSetArg (al
[0], XtNinitialState
, state
);
6277 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6278 #else /* not USE_X_TOOLKIT */
6279 Window window
= FRAME_X_WINDOW (f
);
6281 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6282 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6284 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6285 #endif /* not USE_X_TOOLKIT */
6288 x_wm_set_icon_pixmap (f
, pixmap_id
)
6294 #ifdef USE_X_TOOLKIT
6295 Window window
= XtWindow (f
->output_data
.x
->widget
);
6297 Window window
= FRAME_X_WINDOW (f
);
6302 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6303 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6307 /* It seems there is no way to turn off use of an icon pixmap.
6308 The following line does it, only if no icon has yet been created,
6309 for some window managers. But with mwm it crashes.
6310 Some people say it should clear the IconPixmapHint bit in this case,
6311 but that doesn't work, and the X consortium said it isn't the
6312 right thing at all. Since there is no way to win,
6313 best to explicitly give up. */
6315 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6321 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6325 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6326 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6329 #else /* not USE_X_TOOLKIT */
6331 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6332 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6334 #endif /* not USE_X_TOOLKIT */
6337 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6341 #ifdef USE_X_TOOLKIT
6342 Window window
= XtWindow (f
->output_data
.x
->widget
);
6344 Window window
= FRAME_X_WINDOW (f
);
6347 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6348 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6349 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6351 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6355 /* Interface to fontset handler. */
6357 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6359 x_get_font_info (f
, font_idx
)
6363 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
6367 /* Return a list of names of available fonts matching PATTERN on frame
6368 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6369 to be listed. Frame F NULL means we have not yet created any
6370 frame on X, and consult the first display in x_display_list.
6371 MAXNAMES sets a limit on how many fonts to match. */
6374 x_list_fonts (f
, pattern
, size
, maxnames
)
6376 Lisp_Object pattern
;
6380 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
, tem
, second_best
;
6381 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
6383 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6384 if (NILP (patterns
))
6385 patterns
= Fcons (pattern
, Qnil
);
6387 /* We try at least 10 fonts because X server will return auto-scaled
6388 fonts at the head. */
6389 if (maxnames
< 10) maxnames
= 10;
6391 for (; CONSP (patterns
); patterns
= XCONS (patterns
)->cdr
)
6396 pattern
= XCONS (patterns
)->car
;
6397 /* See if we cached the result for this particular query.
6398 The cache is an alist of the form:
6399 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
6401 if (f
&& (tem
= XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
,
6402 key
= Fcons (pattern
, make_number (maxnames
)),
6403 !NILP (list
= Fassoc (key
, tem
))))
6405 list
= Fcdr_safe (list
);
6406 /* We have a cashed list. Don't have to get the list again. */
6410 /* At first, put PATTERN in the cache. */
6412 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, maxnames
, &num_fonts
);
6419 /* Make a list of all the fonts we got back.
6420 Store that in the font cache for the display. */
6421 for (i
= 0; i
< num_fonts
; i
++)
6424 int average_width
= -1, dashes
= 0, width
= 0;
6426 /* Count the number of dashes in NAMES[I]. If there are
6427 14 dashes, and the field value following 12th dash
6428 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
6429 is usually too ugly to be used for editing. Let's
6435 if (dashes
== 7) /* PIXEL_SIZE field */
6437 else if (dashes
== 12) /* AVERAGE_WIDTH field */
6438 average_width
= atoi (p
);
6440 if (dashes
< 14 || average_width
!= 0)
6442 tem
= build_string (names
[i
]);
6443 if (NILP (Fassoc (tem
, list
)))
6445 if (STRINGP (Vx_pixel_size_width_font_regexp
)
6446 && ((fast_c_string_match_ignore_case
6447 (Vx_pixel_size_width_font_regexp
, names
[i
]))
6449 /* We can set the value of PIXEL_SIZE to the
6450 width of this font. */
6451 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
6453 /* For the moment, width is not known. */
6454 list
= Fcons (Fcons (tem
, Qnil
), list
);
6458 XFreeFontNames (names
);
6461 /* Now store the result in the cache. */
6463 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
6464 = Fcons (Fcons (key
, list
),
6465 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6468 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6470 newlist
= second_best
= Qnil
;
6471 /* Make a list of the fonts that have the right width. */
6472 for (; CONSP (list
); list
= XCONS (list
)->cdr
)
6476 tem
= XCONS (list
)->car
;
6478 if (!CONSP (tem
) || NILP (XCONS (tem
)->car
))
6482 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6486 if (!INTEGERP (XCONS (tem
)->cdr
))
6488 /* Since we have not yet known the size of this font, we
6489 must try slow function call XLoadQueryFont. */
6490 XFontStruct
*thisinfo
;
6493 thisinfo
= XLoadQueryFont (dpy
,
6494 XSTRING (XCONS (tem
)->car
)->data
);
6500 = (thisinfo
->min_bounds
.width
== 0
6502 : make_number (thisinfo
->max_bounds
.width
));
6503 XFreeFont (dpy
, thisinfo
);
6506 /* For unknown reason, the previous call of XListFont had
6507 retruned a font which can't be opened. Record the size
6508 as 0 not to try to open it again. */
6509 XCONS (tem
)->cdr
= make_number (0);
6512 found_size
= XINT (XCONS (tem
)->cdr
);
6513 if (found_size
== size
)
6514 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6515 else if (found_size
> 0)
6517 if (NILP (second_best
))
6519 else if (found_size
< size
)
6521 if (XINT (XCONS (second_best
)->cdr
) > size
6522 || XINT (XCONS (second_best
)->cdr
) < found_size
)
6527 if (XINT (XCONS (second_best
)->cdr
) > size
6528 && XINT (XCONS (second_best
)->cdr
) > found_size
)
6533 if (!NILP (newlist
))
6535 else if (!NILP (second_best
))
6537 newlist
= Fcons (XCONS (second_best
)->car
, Qnil
);
6545 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6546 pointer to the structure font_info while allocating it dynamically.
6547 If SIZE is 0, load any size of font.
6548 If loading is failed, return NULL. */
6551 x_load_font (f
, fontname
, size
)
6553 register char *fontname
;
6556 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6557 Lisp_Object font_names
;
6559 /* Get a list of all the fonts that match this name. Once we
6560 have a list of matching fonts, we compare them against the fonts
6561 we already have by comparing names. */
6562 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 256);
6564 if (!NILP (font_names
))
6569 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6570 for (tail
= font_names
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
6571 if (!strcmp (dpyinfo
->font_table
[i
].name
,
6572 XSTRING (XCONS (tail
)->car
)->data
)
6573 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6574 XSTRING (XCONS (tail
)->car
)->data
))
6575 return (dpyinfo
->font_table
+ i
);
6578 /* Load the font and add it to the table. */
6582 struct font_info
*fontp
;
6583 unsigned long value
;
6585 /* If we have found fonts by x_list_font, load one of them. If
6586 not, we still try to load a font by the name given as FONTNAME
6587 because XListFonts (called in x_list_font) of some X server has
6588 a bug of not finding a font even if the font surely exists and
6589 is loadable by XLoadQueryFont. */
6590 if (!NILP (font_names
))
6591 fontname
= (char *) XSTRING (XCONS (font_names
)->car
)->data
;
6594 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
6599 /* Do we need to create the table? */
6600 if (dpyinfo
->font_table_size
== 0)
6602 dpyinfo
->font_table_size
= 16;
6604 = (struct font_info
*) xmalloc (dpyinfo
->font_table_size
6605 * sizeof (struct font_info
));
6607 /* Do we need to grow the table? */
6608 else if (dpyinfo
->n_fonts
6609 >= dpyinfo
->font_table_size
)
6611 dpyinfo
->font_table_size
*= 2;
6613 = (struct font_info
*) xrealloc (dpyinfo
->font_table
,
6614 (dpyinfo
->font_table_size
6615 * sizeof (struct font_info
)));
6618 fontp
= dpyinfo
->font_table
+ dpyinfo
->n_fonts
;
6620 /* Now fill in the slots of *FONTP. */
6623 fontp
->font_idx
= dpyinfo
->n_fonts
;
6624 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
6625 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
6627 /* Try to get the full name of FONT. Put it in FULL_NAME. */
6629 if (XGetFontProperty (font
, XA_FONT
, &value
))
6631 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
6635 /* Count the number of dashes in the "full name".
6636 If it is too few, this isn't really the font's full name,
6638 In X11R4, the fonts did not come with their canonical names
6649 full_name
= (char *) xmalloc (p
- name
+ 1);
6650 bcopy (name
, full_name
, p
- name
+ 1);
6657 fontp
->full_name
= full_name
;
6659 fontp
->full_name
= fontp
->name
;
6661 fontp
->size
= font
->max_bounds
.width
;
6662 fontp
->height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6664 if (NILP (font_names
))
6666 /* We come here because of a bug of XListFonts mentioned at
6667 the head of this block. Let's store this information in
6668 the cache for x_list_fonts. */
6669 Lisp_Object lispy_name
= build_string (fontname
);
6670 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
6672 XCONS (dpyinfo
->name_list_element
)->cdr
6673 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
6674 Fcons (Fcons (lispy_full_name
,
6675 make_number (fontp
->size
)),
6677 XCONS (dpyinfo
->name_list_element
)->cdr
);
6679 XCONS (dpyinfo
->name_list_element
)->cdr
6680 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
6681 Fcons (Fcons (lispy_full_name
,
6682 make_number (fontp
->size
)),
6684 XCONS (dpyinfo
->name_list_element
)->cdr
);
6687 /* The slot `encoding' specifies how to map a character
6688 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6689 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
6690 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
6691 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
6692 2:0xA020..0xFF7F). For the moment, we don't know which charset
6693 uses this font. So, we set informatoin in fontp->encoding[1]
6694 which is never used by any charset. If mapping can't be
6695 decided, set FONT_ENCODING_NOT_DECIDED. */
6697 = (font
->max_byte1
== 0
6699 ? (font
->min_char_or_byte2
< 0x80
6700 ? (font
->max_char_or_byte2
< 0x80
6701 ? 0 /* 0x20..0x7F */
6702 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6703 : 1) /* 0xA0..0xFF */
6705 : (font
->min_byte1
< 0x80
6706 ? (font
->max_byte1
< 0x80
6707 ? (font
->min_char_or_byte2
< 0x80
6708 ? (font
->max_char_or_byte2
< 0x80
6709 ? 0 /* 0x2020..0x7F7F */
6710 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6711 : 3) /* 0x20A0..0x7FFF */
6712 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6713 : (font
->min_char_or_byte2
< 0x80
6714 ? (font
->max_char_or_byte2
< 0x80
6715 ? 2 /* 0xA020..0xFF7F */
6716 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6717 : 1))); /* 0xA0A0..0xFFFF */
6719 fontp
->baseline_offset
6720 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6721 ? (long) value
: 0);
6722 fontp
->relative_compose
6723 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6724 ? (long) value
: 0);
6725 fontp
->default_ascent
6726 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6727 ? (long) value
: 0);
6736 /* Return a pointer to struct font_info of a font named FONTNAME for frame F.
6737 If no such font is loaded, return NULL. */
6739 x_query_font (f
, fontname
)
6741 register char *fontname
;
6743 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6746 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6747 if (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
6748 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
))
6749 return (dpyinfo
->font_table
+ i
);
6754 /* Initialization. */
6756 #ifdef USE_X_TOOLKIT
6757 static XrmOptionDescRec emacs_options
[] = {
6758 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6759 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6761 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6762 XrmoptionSepArg
, NULL
},
6763 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6765 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6766 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6767 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6768 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6769 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6770 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6771 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6773 #endif /* USE_X_TOOLKIT */
6775 static int x_initialized
;
6778 /* Test whether two display-name strings agree up to the dot that separates
6779 the screen number from the server number. */
6781 same_x_server (name1
, name2
)
6782 char *name1
, *name2
;
6785 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
6789 if (seen_colon
&& *name1
== '.')
6793 && (*name1
== '.' || *name1
== '\0')
6794 && (*name2
== '.' || *name2
== '\0'));
6798 struct x_display_info
*
6799 x_term_init (display_name
, xrm_option
, resource_name
)
6800 Lisp_Object display_name
;
6802 char *resource_name
;
6808 struct x_display_info
*dpyinfo
;
6820 setlocale (LC_ALL
, "");
6821 /* In case we just overrode what init_lread did, redo it. */
6822 setlocale (LC_NUMERIC
, "C");
6823 setlocale (LC_TIME
, "C");
6826 #ifdef USE_X_TOOLKIT
6827 /* weiner@footloose.sps.mot.com reports that this causes
6829 X protocol error: BadAtom (invalid Atom parameter)
6830 on protocol request 18skiloaf.
6831 So let's not use it until R6. */
6833 XtSetLanguageProc (NULL
, NULL
, NULL
);
6844 argv
[argc
++] = "-xrm";
6845 argv
[argc
++] = xrm_option
;
6847 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
6848 resource_name
, EMACS_CLASS
,
6849 emacs_options
, XtNumber (emacs_options
),
6853 /* I think this is to compensate for XtSetLanguageProc. */
6854 setlocale (LC_NUMERIC
, "C");
6855 setlocale (LC_TIME
, "C");
6859 #else /* not USE_X_TOOLKIT */
6861 XSetLocaleModifiers ("");
6863 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
6864 #endif /* not USE_X_TOOLKIT */
6866 /* Detect failure. */
6873 /* We have definitely succeeded. Record the new connection. */
6875 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
6879 struct x_display_info
*share
;
6882 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
6883 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
6884 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
6885 XSTRING (display_name
)->data
))
6888 dpyinfo
->kboard
= share
->kboard
;
6891 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
6892 init_kboard (dpyinfo
->kboard
);
6893 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
6895 char *vendor
= ServerVendor (dpy
);
6896 dpyinfo
->kboard
->Vsystem_key_alist
6897 = call1 (Qvendor_specific_keysyms
,
6898 build_string (vendor
? vendor
: ""));
6901 dpyinfo
->kboard
->next_kboard
= all_kboards
;
6902 all_kboards
= dpyinfo
->kboard
;
6903 /* Don't let the initial kboard remain current longer than necessary.
6904 That would cause problems if a file loaded on startup tries to
6905 prompt in the minibuffer. */
6906 if (current_kboard
== initial_kboard
)
6907 current_kboard
= dpyinfo
->kboard
;
6909 dpyinfo
->kboard
->reference_count
++;
6913 /* Put this display on the chain. */
6914 dpyinfo
->next
= x_display_list
;
6915 x_display_list
= dpyinfo
;
6917 /* Put it on x_display_name_list as well, to keep them parallel. */
6918 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
6919 x_display_name_list
);
6920 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
6922 dpyinfo
->display
= dpy
;
6925 XSetAfterFunction (x_current_display
, x_trace_wire
);
6929 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
6930 + XSTRING (Vsystem_name
)->size
6932 sprintf (dpyinfo
->x_id_name
, "%s@%s",
6933 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
6935 /* Figure out which modifier bits mean what. */
6936 x_find_modifier_meanings (dpyinfo
);
6938 /* Get the scroll bar cursor. */
6939 dpyinfo
->vertical_scroll_bar_cursor
6940 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
6942 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
6943 resource_name
, EMACS_CLASS
);
6944 #ifdef HAVE_XRMSETDATABASE
6945 XrmSetDatabase (dpyinfo
->display
, xrdb
);
6947 dpyinfo
->display
->db
= xrdb
;
6949 /* Put the rdb where we can find it in a way that works on
6951 dpyinfo
->xrdb
= xrdb
;
6953 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
6954 DefaultScreen (dpyinfo
->display
));
6955 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
6956 &dpyinfo
->n_planes
);
6957 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
6958 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
6959 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
6960 dpyinfo
->grabbed
= 0;
6961 dpyinfo
->reference_count
= 0;
6962 dpyinfo
->icon_bitmap_id
= -1;
6963 dpyinfo
->n_fonts
= 0;
6964 dpyinfo
->font_table_size
= 0;
6965 dpyinfo
->bitmaps
= 0;
6966 dpyinfo
->bitmaps_size
= 0;
6967 dpyinfo
->bitmaps_last
= 0;
6968 dpyinfo
->scratch_cursor_gc
= 0;
6969 dpyinfo
->mouse_face_mouse_frame
= 0;
6970 dpyinfo
->mouse_face_deferred_gc
= 0;
6971 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6972 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6973 dpyinfo
->mouse_face_face_id
= 0;
6974 dpyinfo
->mouse_face_window
= Qnil
;
6975 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
6976 dpyinfo
->mouse_face_defer
= 0;
6977 dpyinfo
->x_focus_frame
= 0;
6978 dpyinfo
->x_focus_event_frame
= 0;
6979 dpyinfo
->x_highlight_frame
= 0;
6981 dpyinfo
->Xatom_wm_protocols
6982 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
6983 dpyinfo
->Xatom_wm_take_focus
6984 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
6985 dpyinfo
->Xatom_wm_save_yourself
6986 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
6987 dpyinfo
->Xatom_wm_delete_window
6988 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
6989 dpyinfo
->Xatom_wm_change_state
6990 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
6991 dpyinfo
->Xatom_wm_configure_denied
6992 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
6993 dpyinfo
->Xatom_wm_window_moved
6994 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
6995 dpyinfo
->Xatom_editres
6996 = XInternAtom (dpyinfo
->display
, "Editres", False
);
6997 dpyinfo
->Xatom_CLIPBOARD
6998 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
6999 dpyinfo
->Xatom_TIMESTAMP
7000 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
7002 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
7003 dpyinfo
->Xatom_COMPOUND_TEXT
7004 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
7005 dpyinfo
->Xatom_DELETE
7006 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
7007 dpyinfo
->Xatom_MULTIPLE
7008 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
7010 = XInternAtom (dpyinfo
->display
, "INCR", False
);
7011 dpyinfo
->Xatom_EMACS_TMP
7012 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
7013 dpyinfo
->Xatom_TARGETS
7014 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
7016 = XInternAtom (dpyinfo
->display
, "NULL", False
);
7017 dpyinfo
->Xatom_ATOM_PAIR
7018 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
7019 /* For properties of font. */
7020 dpyinfo
->Xatom_PIXEL_SIZE
7021 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
7022 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
7023 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
7024 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
7025 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
7026 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
7027 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
7029 dpyinfo
->cut_buffers_initialized
= 0;
7031 connection
= ConnectionNumber (dpyinfo
->display
);
7032 dpyinfo
->connection
= connection
;
7037 null_bits
[0] = 0x00;
7040 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
7041 null_bits
, 1, 1, (long) 0, (long) 0,
7046 /* This is only needed for distinguishing keyboard and process input. */
7047 if (connection
!= 0)
7048 add_keyboard_wait_descriptor (connection
);
7051 #ifndef F_SETOWN_BUG
7053 #ifdef F_SETOWN_SOCK_NEG
7054 /* stdin is a socket here */
7055 fcntl (connection
, F_SETOWN
, -getpid ());
7056 #else /* ! defined (F_SETOWN_SOCK_NEG) */
7057 fcntl (connection
, F_SETOWN
, getpid ());
7058 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
7059 #endif /* ! defined (F_SETOWN) */
7060 #endif /* F_SETOWN_BUG */
7063 if (interrupt_input
)
7064 init_sigio (connection
);
7065 #endif /* ! defined (SIGIO) */
7068 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
7069 /* Make sure that we have a valid font for dialog boxes
7070 so that Xt does not crash. */
7072 Display
*dpy
= dpyinfo
->display
;
7077 d
.addr
= (XPointer
)&dpy
;
7078 d
.size
= sizeof (Display
*);
7079 fr
.addr
= XtDefaultFont
;
7080 fr
.size
= sizeof (XtDefaultFont
);
7081 to
.size
= sizeof (Font
*);
7082 to
.addr
= (XPointer
)&font
;
7083 count
= x_catch_errors (dpy
);
7084 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
7086 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
7087 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
7088 x_uncatch_errors (dpy
, count
);
7099 /* Get rid of display DPYINFO, assuming all frames are already gone,
7100 and without sending any more commands to the X server. */
7103 x_delete_display (dpyinfo
)
7104 struct x_display_info
*dpyinfo
;
7106 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
7108 /* Discard this display from x_display_name_list and x_display_list.
7109 We can't use Fdelq because that can quit. */
7110 if (! NILP (x_display_name_list
)
7111 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
7112 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
7117 tail
= x_display_name_list
;
7118 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
7120 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
7121 dpyinfo
->name_list_element
))
7123 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
7126 tail
= XCONS (tail
)->cdr
;
7130 if (x_display_list
== dpyinfo
)
7131 x_display_list
= dpyinfo
->next
;
7134 struct x_display_info
*tail
;
7136 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
7137 if (tail
->next
== dpyinfo
)
7138 tail
->next
= tail
->next
->next
;
7141 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
7142 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
7143 XrmDestroyDatabase (dpyinfo
->xrdb
);
7147 if (--dpyinfo
->kboard
->reference_count
== 0)
7148 delete_kboard (dpyinfo
->kboard
);
7150 xfree (dpyinfo
->font_table
);
7151 xfree (dpyinfo
->x_id_name
);
7155 /* Set up use of X before we make the first connection. */
7159 clear_frame_hook
= XTclear_frame
;
7160 clear_end_of_line_hook
= XTclear_end_of_line
;
7161 ins_del_lines_hook
= XTins_del_lines
;
7162 change_line_highlight_hook
= XTchange_line_highlight
;
7163 insert_glyphs_hook
= XTinsert_glyphs
;
7164 write_glyphs_hook
= XTwrite_glyphs
;
7165 delete_glyphs_hook
= XTdelete_glyphs
;
7166 ring_bell_hook
= XTring_bell
;
7167 reset_terminal_modes_hook
= XTreset_terminal_modes
;
7168 set_terminal_modes_hook
= XTset_terminal_modes
;
7169 update_begin_hook
= XTupdate_begin
;
7170 update_end_hook
= XTupdate_end
;
7171 set_terminal_window_hook
= XTset_terminal_window
;
7172 read_socket_hook
= XTread_socket
;
7173 frame_up_to_date_hook
= XTframe_up_to_date
;
7174 cursor_to_hook
= XTcursor_to
;
7175 reassert_line_highlight_hook
= XTreassert_line_highlight
;
7176 mouse_position_hook
= XTmouse_position
;
7177 frame_rehighlight_hook
= XTframe_rehighlight
;
7178 frame_raise_lower_hook
= XTframe_raise_lower
;
7179 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
7180 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
7181 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
7182 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
7184 scroll_region_ok
= 1; /* we'll scroll partial frames */
7185 char_ins_del_ok
= 0; /* just as fast to write the line */
7186 line_ins_del_ok
= 1; /* we'll just blt 'em */
7187 fast_clear_end_of_line
= 1; /* X does this well */
7188 memory_below_frame
= 0; /* we don't remember what scrolls
7194 /* Try to use interrupt input; if we can't, then start polling. */
7195 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
7197 #ifdef USE_X_TOOLKIT
7198 XtToolkitInitialize ();
7199 Xt_app_con
= XtCreateApplicationContext ();
7200 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
7203 /* Note that there is no real way portable across R3/R4 to get the
7204 original error handler. */
7205 XSetErrorHandler (x_error_handler
);
7206 XSetIOErrorHandler (x_io_error_quitter
);
7208 /* Disable Window Change signals; they are handled by X events. */
7210 signal (SIGWINCH
, SIG_DFL
);
7211 #endif /* ! defined (SIGWINCH) */
7213 signal (SIGPIPE
, x_connection_signal
);
7219 staticpro (&x_error_message_string
);
7220 x_error_message_string
= Qnil
;
7222 staticpro (&x_display_name_list
);
7223 x_display_name_list
= Qnil
;
7225 staticpro (&last_mouse_scroll_bar
);
7226 last_mouse_scroll_bar
= Qnil
;
7228 staticpro (&Qvendor_specific_keysyms
);
7229 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
7231 staticpro (&last_mouse_press_frame
);
7232 last_mouse_press_frame
= Qnil
;
7235 #endif /* not HAVE_X_WINDOWS */