1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
60 #ifndef INCLUDED_FCNTL
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
71 #include "dispextern.h"
72 #include "termhooks.h"
84 #include "intervals.h"
87 extern void free_frame_menubar ();
88 extern void _XEditResCheckMessages ();
89 #endif /* USE_X_TOOLKIT */
92 #define x_any_window_to_frame x_window_to_frame
93 #define x_top_window_to_frame x_window_to_frame
97 #ifndef XtNinitialState
98 #define XtNinitialState "initialState"
102 #define min(a,b) ((a)<(b) ? (a) : (b))
103 #define max(a,b) ((a)>(b) ? (a) : (b))
105 /* This is a chain of structures for all the X displays currently in use. */
106 struct x_display_info
*x_display_list
;
108 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
109 one for each element of x_display_list and in the same order.
110 NAME is the name of the frame.
111 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
112 Lisp_Object x_display_name_list
;
114 /* Frame being updated by update_frame. This is declared in term.c.
115 This is set by update_begin and looked at by all the
116 XT functions. It is zero while not inside an update.
117 In that case, the XT functions assume that `selected_frame'
118 is the frame to apply to. */
119 extern struct frame
*updating_frame
;
121 /* This is a frame waiting to be autoraised, within XTread_socket. */
122 struct frame
*pending_autoraise_frame
;
125 /* The application context for Xt use. */
126 XtAppContext Xt_app_con
;
129 /* During an update, maximum vpos for ins/del line operations to affect. */
131 static int flexlines
;
133 /* During an update, nonzero if chars output now should be highlighted. */
135 static int highlight
;
137 /* Nominal cursor position -- where to draw output.
138 During an update, these are different from the cursor-box position. */
145 In order to avoid asking for motion events and then throwing most
146 of them away or busy-polling the server for mouse positions, we ask
147 the server for pointer motion hints. This means that we get only
148 one event per group of mouse movements. "Groups" are delimited by
149 other kinds of events (focus changes and button clicks, for
150 example), or by XQueryPointer calls; when one of these happens, we
151 get another MotionNotify event the next time the mouse moves. This
152 is at least as efficient as getting motion events when mouse
153 tracking is on, and I suspect only negligibly worse when tracking
156 The silly O'Reilly & Associates Nutshell guides barely document
157 pointer motion hints at all (I think you have to infer how they
158 work from an example), and the description of XQueryPointer doesn't
159 mention that calling it causes you to get another motion hint from
160 the server, which is very important. */
162 /* Where the mouse was last time we reported a mouse event. */
163 static FRAME_PTR last_mouse_frame
;
164 static XRectangle last_mouse_glyph
;
166 /* The scroll bar in which the last X motion event occurred.
168 If the last X motion event occurred in a scroll bar, we set this
169 so XTmouse_position can know whether to report a scroll bar motion or
172 If the last X motion event didn't occur in a scroll bar, we set this
173 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
174 static Lisp_Object last_mouse_scroll_bar
;
176 /* This is a hack. We would really prefer that XTmouse_position would
177 return the time associated with the position it returns, but there
178 doesn't seem to be any way to wrest the timestamp from the server
179 along with the position query. So, we just keep track of the time
180 of the last movement we received, and return that in hopes that
181 it's somewhat accurate. */
182 static Time last_mouse_movement_time
;
184 /* Incremented by XTread_socket whenever it really tries to read events. */
186 static int volatile input_signal_count
;
188 static int input_signal_count
;
191 /* Used locally within XTread_socket. */
192 static int x_noop_count
;
194 /* Initial values of argv and argc. */
195 extern char **initial_argv
;
196 extern int initial_argc
;
198 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
200 /* Tells if a window manager is present or not. */
202 extern Lisp_Object Vx_no_window_manager
;
204 /* Nonzero enables some debugging for the X interface code. */
207 extern Lisp_Object Qface
, Qmouse_face
;
211 /* A mask of extra modifier bits to put into every keyboard char. */
212 extern int extra_keyboard_modifiers
;
214 extern XrmDatabase
x_load_resources ();
216 void x_delete_display ();
218 static void flashback ();
219 static void redraw_previous_char ();
220 static void redraw_following_char ();
221 static unsigned int x_x_to_emacs_modifiers ();
223 static int fast_find_position ();
224 static void note_mouse_highlight ();
225 static void clear_mouse_face ();
226 static void show_mouse_face ();
227 static void do_line_dance ();
229 static int XTcursor_to ();
230 static int XTclear_end_of_line ();
231 static int x_io_error_quitter ();
232 void x_catch_errors ();
233 void x_uncatch_errors ();
235 /* Return the struct x_display_info corresponding to DPY. */
237 struct x_display_info
*
238 x_display_info_for_display (dpy
)
241 struct x_display_info
*dpyinfo
;
243 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
244 if (dpyinfo
->display
== dpy
)
250 /* Starting and ending updates.
252 These hooks are called by update_frame at the beginning and end
253 of a frame update. We record in `updating_frame' the identity
254 of the frame being updated, so that the XT... functions do not
255 need to take a frame as argument. Most of the XT... functions
256 should never be called except during an update, the only exceptions
257 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
268 flexlines
= f
->height
;
273 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
275 /* Don't do highlighting for mouse motion during the update. */
276 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
278 /* If the frame needs to be redrawn,
279 simply forget about any prior mouse highlighting. */
280 if (FRAME_GARBAGED_P (f
))
281 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
283 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
285 int firstline
, lastline
, i
;
286 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
288 /* Find the first, and the last+1, lines affected by redisplay. */
289 for (firstline
= 0; firstline
< f
->height
; firstline
++)
290 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
293 lastline
= f
->height
;
294 for (i
= f
->height
- 1; i
>= 0; i
--)
296 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
302 /* Can we tell that this update does not affect the window
303 where the mouse highlight is? If so, no need to turn off.
304 Likewise, don't do anything if the frame is garbaged;
305 in that case, the FRAME_CURRENT_GLYPHS that we would use
306 are all wrong, and we will redisplay that line anyway. */
307 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
308 || lastline
< XFASTINT (w
->top
)))
309 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
325 x_display_cursor (f
, 1);
327 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
328 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
330 /* This fails in the case of having updated only the echo area
331 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
332 has no relation to the current contents, and its charstarts
333 have no relation to the contents of the window-buffer.
334 I don't know a clean way to check
335 for that case. window_end_valid isn't set up yet. */
336 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
337 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
338 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
341 XFlush (FRAME_X_DISPLAY (f
));
345 /* This is called after a redisplay on frame F. */
348 XTframe_up_to_date (f
)
351 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
352 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
354 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
355 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
356 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
357 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
361 /* External interface to control of standout mode.
362 Call this when about to modify line at position VPOS
363 and not change whether it is highlighted. */
365 XTreassert_line_highlight (new, vpos
)
371 /* Call this when about to modify line at position VPOS
372 and change whether it is highlighted. */
375 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
376 int new_highlight
, vpos
, first_unused_hpos
;
378 highlight
= new_highlight
;
379 XTcursor_to (vpos
, 0);
380 XTclear_end_of_line (updating_frame
->width
);
383 /* This is used when starting Emacs and when restarting after suspend.
384 When starting Emacs, no X window is mapped. And nothing must be done
385 to Emacs's own window if it is suspended (though that rarely happens). */
388 XTset_terminal_modes ()
392 /* This is called when exiting or suspending Emacs.
393 Exiting will make the X-windows go away, and suspending
394 requires no action. */
397 XTreset_terminal_modes ()
399 /* XTclear_frame (); */
402 /* Set the nominal cursor position of the frame.
403 This is where display update commands will take effect.
404 This does not affect the place where the cursor-box is displayed. */
407 XTcursor_to (row
, col
)
408 register int row
, col
;
416 if (updating_frame
== 0)
419 x_display_cursor (selected_frame
, 1);
420 XFlush (FRAME_X_DISPLAY (selected_frame
));
425 /* Display a sequence of N glyphs found at GP.
426 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
427 HL is 1 if this text is highlighted, 2 if the cursor is on it,
428 3 if should appear in its mouse-face.
429 JUST_FOREGROUND if 1 means draw only the foreground;
430 don't alter the background.
432 FONT is the default font to use (for glyphs whose font-code is 0).
434 Since the display generation code is responsible for calling
435 compute_char_face and compute_glyph_face on everything it puts in
436 the display structure, we can assume that the face code on each
437 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
438 to which we can actually apply intern_face.
439 Call this function with input blocked. */
442 /* This is the multi-face code. */
445 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
448 register GLYPH
*gp
; /* Points to first GLYPH. */
449 register int n
; /* Number of glyphs to display. */
453 /* Holds characters to be displayed. */
454 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
455 register char *cp
; /* Steps through buf[]. */
456 register int tlen
= GLYPH_TABLE_LENGTH
;
457 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
458 Window window
= FRAME_X_WINDOW (f
);
459 int orig_left
= left
;
463 /* Get the face-code of the next GLYPH. */
467 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
468 cf
= FAST_GLYPH_FACE (g
);
470 /* Find the run of consecutive glyphs with the same face-code.
471 Extract their character codes into BUF. */
476 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
477 if (FAST_GLYPH_FACE (g
) != cf
)
480 *cp
++ = FAST_GLYPH_CHAR (g
);
485 /* LEN gets the length of the run. */
488 /* Now output this run of chars, with the font and pixel values
489 determined by the face code CF. */
491 struct face
*face
= FRAME_DEFAULT_FACE (f
);
492 XFontStruct
*font
= FACE_FONT (face
);
493 GC gc
= FACE_GC (face
);
496 /* HL = 3 means use a mouse face previously chosen. */
498 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
500 /* First look at the face of the text itself. */
503 /* It's possible for the display table to specify
504 a face code that is out of range. Use 0 in that case. */
505 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
506 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
510 face
= FRAME_MODE_LINE_FACE (f
);
512 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
513 font
= FACE_FONT (face
);
515 if (FACE_STIPPLE (face
))
519 /* Then comes the distinction between modeline and normal text. */
524 face
= FRAME_MODE_LINE_FACE (f
);
525 font
= FACE_FONT (face
);
527 if (FACE_STIPPLE (face
))
531 #define FACE_DEFAULT (~0)
533 /* Now override that if the cursor's on this character. */
536 /* The cursor overrides stippling. */
540 || face
->font
== (XFontStruct
*) FACE_DEFAULT
541 || face
->font
== f
->display
.x
->font
)
542 && face
->background
== f
->display
.x
->background_pixel
543 && face
->foreground
== f
->display
.x
->foreground_pixel
)
545 gc
= f
->display
.x
->cursor_gc
;
547 /* Cursor on non-default face: must merge. */
553 xgcv
.background
= f
->display
.x
->cursor_pixel
;
554 xgcv
.foreground
= face
->background
;
555 /* If the glyph would be invisible,
556 try a different foreground. */
557 if (xgcv
.foreground
== xgcv
.background
)
558 xgcv
.foreground
= face
->foreground
;
559 if (xgcv
.foreground
== xgcv
.background
)
560 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
561 if (xgcv
.foreground
== xgcv
.background
)
562 xgcv
.foreground
= face
->foreground
;
563 /* Make sure the cursor is distinct from text in this face. */
564 if (xgcv
.background
== face
->background
565 && xgcv
.foreground
== face
->foreground
)
567 xgcv
.background
= face
->foreground
;
568 xgcv
.foreground
= face
->background
;
570 xgcv
.font
= face
->font
->fid
;
571 xgcv
.graphics_exposures
= 0;
572 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
573 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
574 XChangeGC (FRAME_X_DISPLAY (f
),
575 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
578 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
579 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
580 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
582 /* If this code is restored, it must also reset to the default stipple
584 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
585 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
590 if (font
== (XFontStruct
*) FACE_DEFAULT
)
591 font
= f
->display
.x
->font
;
594 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
595 left
, top
+ FONT_BASE (font
), buf
, len
);
600 /* Turn stipple on. */
601 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
603 /* Draw stipple on background. */
604 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
606 FONT_WIDTH (font
) * len
,
609 /* Turn stipple off. */
610 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
612 /* Draw the text, solidly, onto the stipple pattern. */
613 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
614 left
, top
+ FONT_BASE (font
), buf
, len
);
617 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
618 left
, top
+ FONT_BASE (font
), buf
, len
);
620 /* Clear the rest of the line's height. */
621 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
622 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
623 top
+ FONT_HEIGHT (font
),
624 FONT_WIDTH (font
) * len
,
625 /* This is how many pixels of height
627 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
631 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
632 which often is not up to date yet. */
633 if (!just_foreground
)
635 if (left
== orig_left
)
636 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
637 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
639 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
640 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
644 /* We should probably check for XA_UNDERLINE_POSITION and
645 XA_UNDERLINE_THICKNESS properties on the font, but let's
646 just get the thing working, and come back to that. */
648 int underline_position
= 1;
650 if (font
->descent
<= underline_position
)
651 underline_position
= font
->descent
- 1;
654 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
658 + underline_position
),
659 len
* FONT_WIDTH (font
), 1);
662 left
+= len
* FONT_WIDTH (font
);
669 /* This is the old single-face code. */
672 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
675 register GLYPH
*gp
; /* Points to first GLYPH. */
676 register int n
; /* Number of glyphs to display. */
681 Window window
= FRAME_X_WINDOW (f
);
682 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
683 : (hl
? f
->display
.x
->reverse_gc
684 : f
->display
.x
->normal_gc
));
686 if (sizeof (GLYPH
) == sizeof (XChar2b
))
687 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
688 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
689 else if (sizeof (GLYPH
) == sizeof (unsigned char))
690 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
691 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
693 /* What size of glyph ARE you using? And does X have a function to
699 /* Output some text at the nominal frame cursor position.
700 Advance the cursor over the text.
701 Output LEN glyphs at START.
703 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
704 controls the pixel values used for foreground and background. */
707 XTwrite_glyphs (start
, len
)
708 register GLYPH
*start
;
711 register int temp_length
;
722 /* If not within an update,
723 output at the frame's visible cursor. */
724 curs_x
= f
->cursor_x
;
725 curs_y
= f
->cursor_y
;
729 CHAR_TO_PIXEL_COL (f
, curs_x
),
730 CHAR_TO_PIXEL_ROW (f
, curs_y
),
731 start
, len
, highlight
, 0);
733 /* If we drew on top of the cursor, note that it is turned off. */
734 if (curs_y
== f
->phys_cursor_y
735 && curs_x
<= f
->phys_cursor_x
736 && curs_x
+ len
> f
->phys_cursor_x
)
737 f
->phys_cursor_x
= -1;
739 if (updating_frame
== 0)
742 x_display_cursor (f
, 1);
751 /* Clear to the end of the line.
752 Erase the current text line from the nominal cursor position (inclusive)
753 to column FIRST_UNUSED (exclusive). The idea is that everything
754 from FIRST_UNUSED onward is already erased. */
757 XTclear_end_of_line (first_unused
)
758 register int first_unused
;
760 struct frame
*f
= updating_frame
;
766 if (curs_y
< 0 || curs_y
>= f
->height
)
768 if (first_unused
<= 0)
771 if (first_unused
>= f
->width
)
772 first_unused
= f
->width
;
778 /* Notice if the cursor will be cleared by this operation. */
779 if (curs_y
== f
->phys_cursor_y
780 && curs_x
<= f
->phys_cursor_x
781 && f
->phys_cursor_x
< first_unused
)
782 f
->phys_cursor_x
= -1;
784 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
785 CHAR_TO_PIXEL_COL (f
, curs_x
),
786 CHAR_TO_PIXEL_ROW (f
, curs_y
),
787 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
788 f
->display
.x
->line_height
, False
);
790 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
800 struct frame
*f
= updating_frame
;
805 f
->phys_cursor_x
= -1; /* Cursor not visible. */
806 curs_x
= 0; /* Nominal cursor position is top left. */
811 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
813 /* We have to clear the scroll bars, too. If we have changed
814 colors or something like that, then they should be notified. */
815 x_scroll_bar_clear (f
);
817 XFlush (FRAME_X_DISPLAY (f
));
822 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
823 always contain the right glyphs to use.
825 It also needs to be changed to look at the details of the font and
826 see whether there is really overlap, and do nothing when there is
827 not. This can use font_char_overlap_left and font_char_overlap_right,
828 but just how to use them is not clear. */
830 /* Erase the character (if any) at the position just before X, Y in frame F,
831 then redraw it and the character before it.
832 This is necessary when we erase starting at X,
833 in case the character after X overlaps into the one before X.
834 Call this function with input blocked. */
837 redraw_previous_char (f
, x
, y
, highlight_flag
)
842 /* Erase the character before the new ones, in case
843 what was here before overlaps it.
844 Reoutput that character, and the previous character
845 (in case the previous character overlaps it). */
851 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
852 CHAR_TO_PIXEL_COL (f
, x
- 1),
853 CHAR_TO_PIXEL_ROW (f
, y
),
854 FONT_WIDTH (f
->display
.x
->font
),
855 f
->display
.x
->line_height
, False
);
857 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
858 CHAR_TO_PIXEL_ROW (f
, y
),
859 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
860 x
- start_x
, highlight_flag
, 1);
864 /* Erase the character (if any) at the position X, Y in frame F,
865 then redraw it and the character after it.
866 This is necessary when we erase endng at X,
867 in case the character after X overlaps into the one before X.
868 Call this function with input blocked. */
871 redraw_following_char (f
, x
, y
, highlight_flag
)
876 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
877 /* Erase the character after the new ones, in case
878 what was here before overlaps it.
879 Reoutput that character, and the following character
880 (in case the following character overlaps it). */
882 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
887 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
888 CHAR_TO_PIXEL_COL (f
, x
),
889 CHAR_TO_PIXEL_ROW (f
, y
),
890 FONT_WIDTH (f
->display
.x
->font
),
891 f
->display
.x
->line_height
, False
);
893 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
894 CHAR_TO_PIXEL_ROW (f
, y
),
895 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
896 end_x
- x
, highlight_flag
, 1);
901 #if 0 /* Not in use yet */
903 /* Return 1 if character C in font F extends past its left edge. */
906 font_char_overlap_left (font
, c
)
912 /* Find the bounding-box info for C. */
913 if (font
->per_char
== 0)
914 s
= &font
->max_bounds
;
917 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
920 /* Decode char into row number (byte 1) and code within row (byte 2). */
923 if (!(within
>= font
->min_char_or_byte2
924 && within
<= font
->max_char_or_byte2
925 && row
>= font
->min_byte1
926 && row
<= font
->max_byte1
))
928 /* If char is out of range, try the font's default char instead. */
929 c
= font
->default_char
;
930 row
= c
>> (INTBITS
- 8);
933 if (!(within
>= font
->min_char_or_byte2
934 && within
<= font
->max_char_or_byte2
935 && row
>= font
->min_byte1
936 && row
<= font
->max_byte1
))
937 /* Still out of range means this char does not overlap. */
940 /* We found the info for this char. */
941 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
945 return (s
&& s
->lbearing
< 0);
948 /* Return 1 if character C in font F extends past its right edge. */
951 font_char_overlap_right (font
, c
)
957 /* Find the bounding-box info for C. */
958 if (font
->per_char
== 0)
959 s
= &font
->max_bounds
;
962 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
965 /* Decode char into row number (byte 1) and code within row (byte 2). */
968 if (!(within
>= font
->min_char_or_byte2
969 && within
<= font
->max_char_or_byte2
970 && row
>= font
->min_byte1
971 && row
<= font
->max_byte1
))
973 /* If char is out of range, try the font's default char instead. */
974 c
= font
->default_char
;
975 row
= c
>> (INTBITS
- 8);
978 if (!(within
>= font
->min_char_or_byte2
979 && within
<= font
->max_char_or_byte2
980 && row
>= font
->min_byte1
981 && row
<= font
->max_byte1
))
982 /* Still out of range means this char does not overlap. */
985 /* We found the info for this char. */
986 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
990 return (s
&& s
->rbearing
>= s
->width
);
994 /* Invert the middle quarter of the frame for .15 sec. */
996 /* We use the select system call to do the waiting, so we have to make sure
997 it's available. If it isn't, we just won't do visual bells. */
998 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1000 /* Subtract the `struct timeval' values X and Y,
1001 storing the result in RESULT.
1002 Return 1 if the difference is negative, otherwise 0. */
1005 timeval_subtract (result
, x
, y
)
1006 struct timeval
*result
, x
, y
;
1008 /* Perform the carry for the later subtraction by updating y.
1009 This is safer because on some systems
1010 the tv_sec member is unsigned. */
1011 if (x
.tv_usec
< y
.tv_usec
)
1013 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1014 y
.tv_usec
-= 1000000 * nsec
;
1017 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1019 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1020 y
.tv_usec
+= 1000000 * nsec
;
1024 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1025 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1026 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1028 /* Return indication of whether the result should be considered negative. */
1029 return x
.tv_sec
< y
.tv_sec
;
1040 /* Create a GC that will use the GXxor function to flip foreground pixels
1041 into background pixels. */
1045 values
.function
= GXxor
;
1046 values
.foreground
= (f
->display
.x
->foreground_pixel
1047 ^ f
->display
.x
->background_pixel
);
1049 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1050 GCFunction
| GCForeground
, &values
);
1054 int width
= PIXEL_WIDTH (f
);
1055 int height
= PIXEL_HEIGHT (f
);
1057 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1058 width
/4, height
/4, width
/2, height
/2);
1059 XFlush (FRAME_X_DISPLAY (f
));
1062 struct timeval wakeup
, now
;
1064 EMACS_GET_TIME (wakeup
);
1066 /* Compute time to wait until, propagating carry from usecs. */
1067 wakeup
.tv_usec
+= 150000;
1068 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1069 wakeup
.tv_usec
%= 1000000;
1071 /* Keep waiting until past the time wakeup. */
1074 struct timeval timeout
;
1076 EMACS_GET_TIME (timeout
);
1078 /* In effect, timeout = wakeup - timeout.
1079 Break if result would be negative. */
1080 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1083 /* Try to wait that long--but we might wake up sooner. */
1084 select (0, 0, 0, 0, &timeout
);
1088 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1089 width
/4, height
/4, width
/2, height
/2);
1090 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1091 XFlush (FRAME_X_DISPLAY (f
));
1101 /* Make audible bell. */
1103 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1107 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1110 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1112 XTflash (selected_frame
);
1118 XFlush (FRAME_X_DISPLAY (selected_frame
));
1123 /* Insert and delete character.
1124 These are not supposed to be used because we are supposed to turn
1125 off the feature of using them. */
1128 XTinsert_glyphs (start
, len
)
1129 register char *start
;
1142 /* Specify how many text lines, from the top of the window,
1143 should be affected by insert-lines and delete-lines operations.
1144 This, and those operations, are used only within an update
1145 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1148 XTset_terminal_window (n
)
1151 if (updating_frame
== 0)
1154 if ((n
<= 0) || (n
> updating_frame
->height
))
1155 flexlines
= updating_frame
->height
;
1160 /* These variables need not be per frame
1161 because redisplay is done on a frame-by-frame basis
1162 and the line dance for one frame is finished before
1163 anything is done for anoter frame. */
1165 /* Array of line numbers from cached insert/delete operations.
1166 line_dance[i] is the old position of the line that we want
1167 to move to line i, or -1 if we want a blank line there. */
1168 static int *line_dance
;
1170 /* Allocated length of that array. */
1171 static int line_dance_len
;
1173 /* Flag indicating whether we've done any work. */
1174 static int line_dance_in_progress
;
1176 /* Perform an insert-lines or delete-lines operation,
1177 inserting N lines or deleting -N lines at vertical position VPOS. */
1178 XTins_del_lines (vpos
, n
)
1181 register int fence
, i
;
1183 if (vpos
>= flexlines
)
1186 if (!line_dance_in_progress
)
1188 int ht
= updating_frame
->height
;
1189 if (ht
> line_dance_len
)
1191 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1192 line_dance_len
= ht
;
1194 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1195 line_dance_in_progress
= 1;
1199 if (n
> flexlines
- vpos
)
1200 n
= flexlines
- vpos
;
1202 for (i
= flexlines
; --i
>= fence
;)
1203 line_dance
[i
] = line_dance
[i
-n
];
1204 for (i
= fence
; --i
>= vpos
;)
1210 if (n
> flexlines
- vpos
)
1211 n
= flexlines
- vpos
;
1212 fence
= flexlines
- n
;
1213 for (i
= vpos
; i
< fence
; ++i
)
1214 line_dance
[i
] = line_dance
[i
+ n
];
1215 for (i
= fence
; i
< flexlines
; ++i
)
1220 /* Here's where we actually move the pixels around.
1221 Must be called with input blocked. */
1225 register int i
, j
, distance
;
1226 register struct frame
*f
;
1230 /* Must check this flag first. If it's not set, then not only is the
1231 array uninitialized, but we might not even have a frame. */
1232 if (!line_dance_in_progress
)
1240 intborder
= f
->display
.x
->internal_border_width
;
1242 x_display_cursor (updating_frame
, 0);
1244 for (i
= 0; i
< ht
; ++i
)
1245 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1247 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1248 && line_dance
[j
]-j
== distance
); ++j
);
1249 /* Copy [i,j) upward from [i+distance,j+distance) */
1250 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1251 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1252 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1253 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1254 (j
-i
) * f
->display
.x
->line_height
,
1255 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1259 for (i
= ht
; --i
>=0; )
1260 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1262 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1263 && line_dance
[j
]-j
== distance
););
1264 /* Copy (j,i] downward from (j+distance, i+distance] */
1265 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1266 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1267 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1268 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1269 (i
-j
) * f
->display
.x
->line_height
,
1270 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1274 for (i
= 0; i
< ht
; ++i
)
1275 if (line_dance
[i
] == -1)
1277 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1279 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1280 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1281 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1282 (j
-i
) * f
->display
.x
->line_height
, False
);
1285 line_dance_in_progress
= 0;
1288 /* Support routines for exposure events. */
1289 static void clear_cursor ();
1291 /* Output into a rectangle of an X-window (for frame F)
1292 the characters in f->phys_lines that overlap that rectangle.
1293 TOP and LEFT are the position of the upper left corner of the rectangle.
1294 ROWS and COLS are the size of the rectangle.
1295 Call this function with input blocked. */
1298 dumprectangle (f
, left
, top
, cols
, rows
)
1300 register int left
, top
, cols
, rows
;
1302 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1303 int cursor_cleared
= 0;
1307 if (FRAME_GARBAGED_P (f
))
1310 /* Express rectangle as four edges, instead of position-and-size. */
1311 bottom
= top
+ rows
;
1312 right
= left
+ cols
;
1314 /* Convert rectangle edges in pixels to edges in chars.
1315 Round down for left and top, up for right and bottom. */
1316 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1317 left
= PIXEL_TO_CHAR_COL (f
, left
);
1318 bottom
+= (f
->display
.x
->line_height
- 1);
1319 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1320 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1321 right
= PIXEL_TO_CHAR_COL (f
, right
);
1323 /* Clip the rectangle to what can be visible. */
1328 if (right
> f
->width
)
1330 if (bottom
> f
->height
)
1333 /* Get size in chars of the rectangle. */
1334 cols
= right
- left
;
1335 rows
= bottom
- top
;
1337 /* If rectangle has zero area, return. */
1338 if (rows
<= 0) return;
1339 if (cols
<= 0) return;
1341 /* Turn off the cursor if it is in the rectangle.
1342 We will turn it back on afterward. */
1343 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1344 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1350 /* Display the text in the rectangle, one text line at a time. */
1352 for (y
= top
; y
< bottom
; y
++)
1354 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1356 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1360 CHAR_TO_PIXEL_COL (f
, left
),
1361 CHAR_TO_PIXEL_ROW (f
, y
),
1362 line
, min (cols
, active_frame
->used
[y
] - left
),
1363 active_frame
->highlight
[y
], 0);
1366 /* Turn the cursor on if we turned it off. */
1369 x_display_cursor (f
, 1);
1376 /* We used to only do this if Vx_no_window_manager was non-nil, but
1377 the ICCCM (section 4.1.6) says that the window's border pixmap
1378 and border pixel are window attributes which are "private to the
1379 client", so we can always change it to whatever we want. */
1381 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1382 f
->display
.x
->border_pixel
);
1384 x_display_cursor (f
, 1);
1388 frame_unhighlight (f
)
1391 /* We used to only do this if Vx_no_window_manager was non-nil, but
1392 the ICCCM (section 4.1.6) says that the window's border pixmap
1393 and border pixel are window attributes which are "private to the
1394 client", so we can always change it to whatever we want. */
1396 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1397 f
->display
.x
->border_tile
);
1399 x_display_cursor (f
, 1);
1402 static void XTframe_rehighlight ();
1403 static void x_frame_rehighlight ();
1405 /* The focus has changed. Update the frames as necessary to reflect
1406 the new situation. Note that we can't change the selected frame
1407 here, because the Lisp code we are interrupting might become confused.
1408 Each event gets marked with the frame in which it occurred, so the
1409 Lisp code can tell when the switch took place by examining the events. */
1412 x_new_focus_frame (dpyinfo
, frame
)
1413 struct x_display_info
*dpyinfo
;
1414 struct frame
*frame
;
1416 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1417 int events_enqueued
= 0;
1419 if (frame
!= dpyinfo
->x_focus_frame
)
1421 /* Set this before calling other routines, so that they see
1422 the correct value of x_focus_frame. */
1423 dpyinfo
->x_focus_frame
= frame
;
1425 if (old_focus
&& old_focus
->auto_lower
)
1426 x_lower_frame (old_focus
);
1429 selected_frame
= frame
;
1430 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1432 Fselect_window (selected_frame
->selected_window
);
1433 choose_minibuf_frame ();
1436 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1437 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1439 pending_autoraise_frame
= 0;
1442 x_frame_rehighlight (dpyinfo
);
1445 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1448 x_mouse_leave (dpyinfo
)
1449 struct x_display_info
*dpyinfo
;
1451 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1454 /* The focus has changed, or we have redirected a frame's focus to
1455 another frame (this happens when a frame uses a surrogate
1456 minibuffer frame). Shift the highlight as appropriate.
1458 The FRAME argument doesn't necessarily have anything to do with which
1459 frame is being highlighted or unhighlighted; we only use it to find
1460 the appropriate X display info. */
1462 XTframe_rehighlight (frame
)
1463 struct frame
*frame
;
1465 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
1469 x_frame_rehighlight (dpyinfo
)
1470 struct x_display_info
*dpyinfo
;
1472 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1474 if (dpyinfo
->x_focus_frame
)
1476 dpyinfo
->x_highlight_frame
1477 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
1478 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
1479 : dpyinfo
->x_focus_frame
);
1480 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
1482 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
1483 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1487 dpyinfo
->x_highlight_frame
= 0;
1489 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
1492 frame_unhighlight (old_highlight
);
1493 if (dpyinfo
->x_highlight_frame
)
1494 frame_highlight (dpyinfo
->x_highlight_frame
);
1498 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1500 /* Initialize mode_switch_bit and modifier_meaning. */
1502 x_find_modifier_meanings (dpyinfo
)
1503 struct x_display_info
*dpyinfo
;
1505 int min_code
, max_code
;
1508 XModifierKeymap
*mods
;
1510 dpyinfo
->meta_mod_mask
= 0;
1511 dpyinfo
->shift_lock_mask
= 0;
1512 dpyinfo
->alt_mod_mask
= 0;
1513 dpyinfo
->super_mod_mask
= 0;
1514 dpyinfo
->hyper_mod_mask
= 0;
1517 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1519 min_code
= display
->min_keycode
;
1520 max_code
= display
->max_keycode
;
1523 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1524 min_code
, max_code
- min_code
+ 1,
1526 mods
= XGetModifierMapping (dpyinfo
->display
);
1528 /* Scan the modifier table to see which modifier bits the Meta and
1529 Alt keysyms are on. */
1531 int row
, col
; /* The row and column in the modifier table. */
1533 for (row
= 3; row
< 8; row
++)
1534 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1537 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1539 /* Zeroes are used for filler. Skip them. */
1543 /* Are any of this keycode's keysyms a meta key? */
1547 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1549 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1555 dpyinfo
->meta_mod_mask
|= (1 << row
);
1560 dpyinfo
->alt_mod_mask
|= (1 << row
);
1565 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1570 dpyinfo
->super_mod_mask
|= (1 << row
);
1574 /* Ignore this if it's not on the lock modifier. */
1575 if ((1 << row
) == LockMask
)
1576 dpyinfo
->shift_lock_mask
= LockMask
;
1584 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1585 if (! dpyinfo
->meta_mod_mask
)
1587 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1588 dpyinfo
->alt_mod_mask
= 0;
1591 /* If some keys are both alt and meta,
1592 make them just meta, not alt. */
1593 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1595 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1598 XFree ((char *) syms
);
1599 XFreeModifiermap (mods
);
1602 /* Convert between the modifier bits X uses and the modifier bits
1605 x_x_to_emacs_modifiers (dpyinfo
, state
)
1606 struct x_display_info
*dpyinfo
;
1609 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1610 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1611 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1612 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1613 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1614 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1618 x_emacs_to_x_modifiers (dpyinfo
, state
)
1619 struct x_display_info
*dpyinfo
;
1622 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1623 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1624 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1625 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1626 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1627 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1630 /* Mouse clicks and mouse movement. Rah. */
1632 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1633 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1634 that the glyph at X, Y occupies, if BOUNDS != 0.
1635 If NOCLIP is nonzero, do not force the value into range. */
1638 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1640 register int pix_x
, pix_y
;
1641 register int *x
, *y
;
1645 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1646 even for negative values. */
1648 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1650 pix_y
-= (f
)->display
.x
->line_height
- 1;
1652 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1653 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1657 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1658 bounds
->height
= f
->display
.x
->line_height
;
1659 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1660 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1667 else if (pix_x
> f
->width
)
1672 else if (pix_y
> f
->height
)
1681 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1684 register int *pix_x
, *pix_y
;
1686 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1687 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1690 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1692 If the event is a button press, then note that we have grabbed
1696 construct_mouse_click (result
, event
, f
)
1697 struct input_event
*result
;
1698 XButtonEvent
*event
;
1701 /* Make the event type no_event; we'll change that when we decide
1703 result
->kind
= mouse_click
;
1704 result
->code
= event
->button
- Button1
;
1705 result
->timestamp
= event
->time
;
1706 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1708 | (event
->type
== ButtonRelease
1716 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1717 XSETFASTINT (result
->x
, column
);
1718 XSETFASTINT (result
->y
, row
);
1720 XSETINT (result
->x
, event
->x
);
1721 XSETINT (result
->y
, event
->y
);
1722 XSETFRAME (result
->frame_or_window
, f
);
1726 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1729 construct_menu_click (result
, event
, f
)
1730 struct input_event
*result
;
1731 XButtonEvent
*event
;
1734 /* Make the event type no_event; we'll change that when we decide
1736 result
->kind
= mouse_click
;
1737 XSETINT (result
->code
, event
->button
- Button1
);
1738 result
->timestamp
= event
->time
;
1739 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1741 | (event
->type
== ButtonRelease
1745 XSETINT (result
->x
, event
->x
);
1746 XSETINT (result
->y
, -1);
1747 XSETFRAME (result
->frame_or_window
, f
);
1750 /* Function to report a mouse movement to the mainstream Emacs code.
1751 The input handler calls this.
1753 We have received a mouse movement event, which is given in *event.
1754 If the mouse is over a different glyph than it was last time, tell
1755 the mainstream emacs code by setting mouse_moved. If not, ask for
1756 another motion event, so we can check again the next time it moves. */
1759 note_mouse_movement (frame
, event
)
1761 XMotionEvent
*event
;
1764 last_mouse_movement_time
= event
->time
;
1766 if (event
->window
!= FRAME_X_WINDOW (frame
))
1769 last_mouse_scroll_bar
= Qnil
;
1771 note_mouse_highlight (frame
, -1, -1);
1773 /* Ask for another mouse motion event. */
1776 Window dummy_window
;
1778 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1779 &dummy_window
, &dummy_window
,
1780 &dummy
, &dummy
, &dummy
, &dummy
,
1781 (unsigned int *) &dummy
);
1785 /* Has the mouse moved off the glyph it was on at the last sighting? */
1786 else if (event
->x
< last_mouse_glyph
.x
1787 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1788 || event
->y
< last_mouse_glyph
.y
1789 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1792 last_mouse_scroll_bar
= Qnil
;
1794 note_mouse_highlight (frame
, event
->x
, event
->y
);
1796 /* Ask for another mouse motion event. */
1799 Window dummy_window
;
1801 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1802 &dummy_window
, &dummy_window
,
1803 &dummy
, &dummy
, &dummy
, &dummy
,
1804 (unsigned int *) &dummy
);
1809 /* It's on the same glyph. Call XQueryPointer so we'll get an
1810 event the next time the mouse moves and we can see if it's
1811 *still* on the same glyph. */
1813 Window dummy_window
;
1815 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1816 &dummy_window
, &dummy_window
,
1817 &dummy
, &dummy
, &dummy
, &dummy
,
1818 (unsigned int *) &dummy
);
1822 /* This is used for debugging, to turn off note_mouse_highlight. */
1823 static int disable_mouse_highlight
;
1825 /* Take proper action when the mouse has moved to position X, Y on frame F
1826 as regards highlighting characters that have mouse-face properties.
1827 Also dehighlighting chars where the mouse was before.
1828 X and Y can be negative or out of range. */
1831 note_mouse_highlight (f
, x
, y
)
1834 int row
, column
, portion
;
1835 XRectangle new_glyph
;
1839 if (disable_mouse_highlight
)
1842 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1843 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1844 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1846 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1851 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1855 /* Find out which glyph the mouse is on. */
1856 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1857 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1859 /* Which window is that in? */
1860 window
= window_from_coordinates (f
, column
, row
, &portion
);
1861 w
= XWINDOW (window
);
1863 /* If we were displaying active text in another window, clear that. */
1864 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1865 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1867 /* Are we in a window whose display is up to date?
1868 And verify the buffer's text has not changed. */
1869 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1870 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1871 && EQ (w
->window_end_valid
, w
->buffer
)
1872 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1874 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1877 /* Find which buffer position the mouse corresponds to. */
1878 for (i
= column
; i
>= 0; i
--)
1882 /* Is it outside the displayed active region (if any)? */
1884 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1885 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1886 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1887 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1888 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1889 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1890 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1891 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1892 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1894 Lisp_Object mouse_face
, overlay
, position
;
1895 Lisp_Object
*overlay_vec
;
1896 int len
, noverlays
, ignor1
;
1897 struct buffer
*obuf
;
1900 /* If we get an out-of-range value, return now; avoid an error. */
1901 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1904 /* Make the window's buffer temporarily current for
1905 overlays_at and compute_char_face. */
1906 obuf
= current_buffer
;
1907 current_buffer
= XBUFFER (w
->buffer
);
1913 /* Yes. Clear the display of the old active region, if any. */
1914 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1916 /* Is this char mouse-active? */
1917 XSETINT (position
, pos
);
1920 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1922 /* Put all the overlays we want in a vector in overlay_vec.
1923 Store the length in len. */
1924 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1926 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1928 /* Find the highest priority overlay that has a mouse-face prop. */
1930 for (i
= 0; i
< noverlays
; i
++)
1932 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1933 if (!NILP (mouse_face
))
1935 overlay
= overlay_vec
[i
];
1940 /* If no overlay applies, get a text property. */
1942 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1944 /* Handle the overlay case. */
1945 if (! NILP (overlay
))
1947 /* Find the range of text around this char that
1948 should be active. */
1949 Lisp_Object before
, after
;
1952 before
= Foverlay_start (overlay
);
1953 after
= Foverlay_end (overlay
);
1954 /* Record this as the current active region. */
1955 fast_find_position (window
, before
,
1956 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1957 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1958 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
1959 = !fast_find_position (window
, after
,
1960 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
1961 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
1962 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1963 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
1964 = compute_char_face (f
, w
, pos
, 0, 0,
1965 &ignore
, pos
+ 1, 1);
1967 /* Display it as active. */
1968 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
1970 /* Handle the text property case. */
1971 else if (! NILP (mouse_face
))
1973 /* Find the range of text around this char that
1974 should be active. */
1975 Lisp_Object before
, after
, beginning
, end
;
1978 beginning
= Fmarker_position (w
->start
);
1979 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1980 - XFASTINT (w
->window_end_pos
)));
1982 = Fprevious_single_property_change (make_number (pos
+ 1),
1984 w
->buffer
, beginning
);
1986 = Fnext_single_property_change (position
, Qmouse_face
,
1988 /* Record this as the current active region. */
1989 fast_find_position (window
, before
,
1990 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1991 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1992 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
1993 = !fast_find_position (window
, after
,
1994 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
1995 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
1996 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1997 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
1998 = compute_char_face (f
, w
, pos
, 0, 0,
1999 &ignore
, pos
+ 1, 1);
2001 /* Display it as active. */
2002 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2006 current_buffer
= obuf
;
2011 /* Find the row and column of position POS in window WINDOW.
2012 Store them in *COLUMNP and *ROWP.
2013 This assumes display in WINDOW is up to date.
2014 If POS is above start of WINDOW, return coords
2015 of start of first screen line.
2016 If POS is after end of WINDOW, return coords of end of last screen line.
2018 Value is 1 if POS is in range, 0 if it was off screen. */
2021 fast_find_position (window
, pos
, columnp
, rowp
)
2024 int *columnp
, *rowp
;
2026 struct window
*w
= XWINDOW (window
);
2027 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2032 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2033 int width
= window_internal_width (w
);
2036 int maybe_next_line
= 0;
2038 /* Find the right row. */
2043 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2044 if (linestart
> pos
)
2046 /* If the position sought is the end of the buffer,
2047 don't include the blank lines at the bottom of the window. */
2048 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2050 maybe_next_line
= 1;
2057 /* Find the right column with in it. */
2058 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2060 for (i
= 0; i
< width
; i
++)
2062 if (charstarts
[left
+ i
] == pos
)
2065 *columnp
= i
+ left
;
2068 else if (charstarts
[left
+ i
] > pos
)
2070 else if (charstarts
[left
+ i
] > 0)
2074 /* If we're looking for the end of the buffer,
2075 and we didn't find it in the line we scanned,
2076 use the start of the following line. */
2077 if (maybe_next_line
)
2088 /* Display the active region described by mouse_face_*
2089 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2092 show_mouse_face (dpyinfo
, hl
)
2093 struct x_display_info
*dpyinfo
;
2096 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2097 int width
= window_internal_width (w
);
2098 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2101 int old_curs_x
= curs_x
;
2102 int old_curs_y
= curs_y
;
2104 /* Set these variables temporarily
2105 so that if we have to turn the cursor off and on again
2106 we will put it back at the same place. */
2107 curs_x
= f
->phys_cursor_x
;
2108 curs_y
= f
->phys_cursor_y
;
2110 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2111 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2113 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2114 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2116 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2117 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2119 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2121 /* If the cursor's in the text we are about to rewrite,
2122 turn the cursor off. */
2124 && curs_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
2125 && curs_x
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
)
2127 x_display_cursor (f
, 0);
2132 CHAR_TO_PIXEL_COL (f
, column
),
2133 CHAR_TO_PIXEL_ROW (f
, i
),
2134 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2136 /* Highlight with mouse face if hl > 0. */
2140 /* If we turned the cursor off, turn it back on. */
2142 x_display_cursor (f
, 1);
2144 curs_x
= old_curs_x
;
2145 curs_y
= old_curs_y
;
2147 /* Change the mouse cursor according to the value of HL. */
2149 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2150 f
->display
.x
->cross_cursor
);
2152 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2153 f
->display
.x
->text_cursor
);
2156 /* Clear out the mouse-highlighted active region.
2157 Redraw it unhighlighted first. */
2160 clear_mouse_face (dpyinfo
)
2161 struct x_display_info
*dpyinfo
;
2163 if (! NILP (dpyinfo
->mouse_face_window
))
2164 show_mouse_face (dpyinfo
, 0);
2166 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2167 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2168 dpyinfo
->mouse_face_window
= Qnil
;
2171 static struct scroll_bar
*x_window_to_scroll_bar ();
2172 static void x_scroll_bar_report_motion ();
2174 /* Return the current position of the mouse.
2175 *fp should be a frame which indicates which display to ask about.
2177 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2178 and *part to the frame, window, and scroll bar part that the mouse
2179 is over. Set *x and *y to the portion and whole of the mouse's
2180 position on the scroll bar.
2182 If the mouse movement started elsewhere, set *fp to the frame the
2183 mouse is on, *bar_window to nil, and *x and *y to the character cell
2186 Set *time to the server timestamp for the time at which the mouse
2187 was at this position.
2189 Don't store anything if we don't have a valid set of values to report.
2191 This clears the mouse_moved flag, so we can wait for the next mouse
2192 movement. This also calls XQueryPointer, which will cause the
2193 server to give us another MotionNotify when the mouse moves
2197 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2200 Lisp_Object
*bar_window
;
2201 enum scroll_bar_part
*part
;
2203 unsigned long *time
;
2209 if (! NILP (last_mouse_scroll_bar
))
2210 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2216 Window dummy_window
;
2220 last_mouse_scroll_bar
= Qnil
;
2222 /* Figure out which root window we're on. */
2223 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2224 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2226 /* The root window which contains the pointer. */
2229 /* Trash which we can't trust if the pointer is on
2230 a different screen. */
2233 /* The position on that root window. */
2236 /* More trash we can't trust. */
2239 /* Modifier keys and pointer buttons, about which
2241 (unsigned int *) &dummy
);
2243 /* Now we have a position on the root; find the innermost window
2244 containing the pointer. */
2248 int parent_x
, parent_y
;
2252 /* XTranslateCoordinates can get errors if the window
2253 structure is changing at the same time this function
2254 is running. So at least we must not crash from them. */
2256 x_catch_errors (FRAME_X_DISPLAY (*fp
));
2258 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2259 && FRAME_LIVE_P (last_mouse_frame
))
2261 /* If mouse was grabbed on a frame, give coords for that frame
2262 even if the mouse is now outside it. */
2263 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2265 /* From-window, to-window. */
2266 root
, FRAME_X_WINDOW (last_mouse_frame
),
2268 /* From-position, to-position. */
2269 root_x
, root_y
, &win_x
, &win_y
,
2273 f1
= last_mouse_frame
;
2279 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2281 /* From-window, to-window. */
2284 /* From-position, to-position. */
2285 root_x
, root_y
, &win_x
, &win_y
,
2298 /* Now we know that:
2299 win is the innermost window containing the pointer
2300 (XTC says it has no child containing the pointer),
2301 win_x and win_y are the pointer's position in it
2302 (XTC did this the last time through), and
2303 parent_x and parent_y are the pointer's position in win's parent.
2304 (They are what win_x and win_y were when win was child.
2305 If win is the root window, it has no parent, and
2306 parent_{x,y} are invalid, but that's okay, because we'll
2307 never use them in that case.) */
2309 /* Is win one of our frames? */
2310 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2313 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2316 x_uncatch_errors (FRAME_X_DISPLAY (*fp
));
2318 /* If not, is it one of our scroll bars? */
2321 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2325 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2331 if (f1
== 0 && insist
)
2332 f1
= selected_frame
;
2336 int ignore1
, ignore2
;
2338 /* Ok, we found a frame. Store all the values. */
2340 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2342 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2348 XSETINT (*x
, win_x
);
2349 XSETINT (*y
, win_y
);
2350 *time
= last_mouse_movement_time
;
2358 /* Scroll bar support. */
2360 /* Given an X window ID, find the struct scroll_bar which manages it.
2361 This can be called in GC, so we have to make sure to strip off mark
2363 static struct scroll_bar
*
2364 x_window_to_scroll_bar (window_id
)
2367 Lisp_Object tail
, frame
;
2369 for (tail
= Vframe_list
;
2370 XGCTYPE (tail
) == Lisp_Cons
;
2371 tail
= XCONS (tail
)->cdr
)
2373 Lisp_Object frame
, bar
, condemned
;
2375 frame
= XCONS (tail
)->car
;
2376 /* All elements of Vframe_list should be frames. */
2377 if (! GC_FRAMEP (frame
))
2380 /* Scan this frame's scroll bar list for a scroll bar with the
2382 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2383 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2384 /* This trick allows us to search both the ordinary and
2385 condemned scroll bar lists with one loop. */
2386 ! GC_NILP (bar
) || (bar
= condemned
,
2389 bar
= XSCROLL_BAR (bar
)->next
)
2390 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2391 return XSCROLL_BAR (bar
);
2397 /* Open a new X window to serve as a scroll bar, and return the
2398 scroll bar vector for it. */
2399 static struct scroll_bar
*
2400 x_scroll_bar_create (window
, top
, left
, width
, height
)
2401 struct window
*window
;
2402 int top
, left
, width
, height
;
2404 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2405 struct scroll_bar
*bar
2406 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2411 XSetWindowAttributes a
;
2413 a
.background_pixel
= f
->display
.x
->background_pixel
;
2414 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2415 | ButtonMotionMask
| PointerMotionHintMask
2417 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2419 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2424 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2425 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2426 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2427 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2428 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2429 sb_widget
= XtCreateManagedWidget ("box",
2431 f
->display
.x
->edit_widget
, al
, ac
);
2432 SET_SCROLL_BAR_X_WINDOW
2433 (bar
, sb_widget
->core
.window
);
2435 SET_SCROLL_BAR_X_WINDOW
2437 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2439 /* Position and size of scroll bar. */
2440 left
, top
, width
, height
,
2442 /* Border width, depth, class, and visual. */
2443 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2449 XSETWINDOW (bar
->window
, window
);
2450 XSETINT (bar
->top
, top
);
2451 XSETINT (bar
->left
, left
);
2452 XSETINT (bar
->width
, width
);
2453 XSETINT (bar
->height
, height
);
2454 XSETINT (bar
->start
, 0);
2455 XSETINT (bar
->end
, 0);
2456 bar
->dragging
= Qnil
;
2458 /* Add bar to its frame's list of scroll bars. */
2459 bar
->next
= FRAME_SCROLL_BARS (f
);
2461 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2462 if (! NILP (bar
->next
))
2463 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2465 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2472 /* Draw BAR's handle in the proper position.
2473 If the handle is already drawn from START to END, don't bother
2474 redrawing it, unless REBUILD is non-zero; in that case, always
2475 redraw it. (REBUILD is handy for drawing the handle after expose
2478 Normally, we want to constrain the start and end of the handle to
2479 fit inside its rectangle, but if the user is dragging the scroll bar
2480 handle, we want to let them drag it down all the way, so that the
2481 bar's top is as far down as it goes; otherwise, there's no way to
2482 move to the very end of the buffer. */
2484 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2485 struct scroll_bar
*bar
;
2489 int dragging
= ! NILP (bar
->dragging
);
2490 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2491 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2492 GC gc
= f
->display
.x
->normal_gc
;
2494 /* If the display is already accurate, do nothing. */
2496 && start
== XINT (bar
->start
)
2497 && end
== XINT (bar
->end
))
2503 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2504 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2505 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2507 /* Make sure the values are reasonable, and try to preserve
2508 the distance between start and end. */
2510 int length
= end
- start
;
2514 else if (start
> top_range
)
2516 end
= start
+ length
;
2520 else if (end
> top_range
&& ! dragging
)
2524 /* Store the adjusted setting in the scroll bar. */
2525 XSETINT (bar
->start
, start
);
2526 XSETINT (bar
->end
, end
);
2528 /* Clip the end position, just for display. */
2529 if (end
> top_range
)
2532 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2533 below top positions, to make sure the handle is always at least
2534 that many pixels tall. */
2535 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2537 /* Draw the empty space above the handle. Note that we can't clear
2538 zero-height areas; that means "clear to end of window." */
2540 XClearArea (FRAME_X_DISPLAY (f
), w
,
2542 /* x, y, width, height, and exposures. */
2543 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2544 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2545 inside_width
, start
,
2548 /* Draw the handle itself. */
2549 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2551 /* x, y, width, height */
2552 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2553 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2554 inside_width
, end
- start
);
2557 /* Draw the empty space below the handle. Note that we can't
2558 clear zero-height areas; that means "clear to end of window." */
2559 if (end
< inside_height
)
2560 XClearArea (FRAME_X_DISPLAY (f
), w
,
2562 /* x, y, width, height, and exposures. */
2563 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2564 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2565 inside_width
, inside_height
- end
,
2573 /* Move a scroll bar around on the screen, to accommodate changing
2574 window configurations. */
2576 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2577 struct scroll_bar
*bar
;
2578 int top
, left
, width
, height
;
2580 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2581 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2587 unsigned int mask
= 0;
2594 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2595 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2596 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2597 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2600 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2604 XSETINT (bar
->left
, left
);
2605 XSETINT (bar
->top
, top
);
2606 XSETINT (bar
->width
, width
);
2607 XSETINT (bar
->height
, height
);
2612 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2615 x_scroll_bar_remove (bar
)
2616 struct scroll_bar
*bar
;
2618 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2622 /* Destroy the window. */
2623 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2625 /* Disassociate this scroll bar from its window. */
2626 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2631 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2632 that we are displaying PORTION characters out of a total of WHOLE
2633 characters, starting at POSITION. If WINDOW has no scroll bar,
2636 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2637 struct window
*window
;
2638 int portion
, whole
, position
;
2640 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2641 int top
= XINT (window
->top
);
2642 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2643 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2645 /* Where should this scroll bar be, pixelwise? */
2646 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2647 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2649 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2650 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2651 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
2652 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2654 struct scroll_bar
*bar
;
2656 /* Does the scroll bar exist yet? */
2657 if (NILP (window
->vertical_scroll_bar
))
2658 bar
= x_scroll_bar_create (window
,
2659 pixel_top
, pixel_left
,
2660 pixel_width
, pixel_height
);
2663 /* It may just need to be moved and resized. */
2664 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2665 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2668 /* Set the scroll bar's current state, unless we're currently being
2670 if (NILP (bar
->dragging
))
2672 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2675 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2678 int start
= ((double) position
* top_range
) / whole
;
2679 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2681 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2685 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2689 /* The following three hooks are used when we're doing a thorough
2690 redisplay of the frame. We don't explicitly know which scroll bars
2691 are going to be deleted, because keeping track of when windows go
2692 away is a real pain - "Can you say set-window-configuration, boys
2693 and girls?" Instead, we just assert at the beginning of redisplay
2694 that *all* scroll bars are to be removed, and then save a scroll bar
2695 from the fiery pit when we actually redisplay its window. */
2697 /* Arrange for all scroll bars on FRAME to be removed at the next call
2698 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2699 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2701 XTcondemn_scroll_bars (frame
)
2704 /* The condemned list should be empty at this point; if it's not,
2705 then the rest of Emacs isn't using the condemn/redeem/judge
2706 protocol correctly. */
2707 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2710 /* Move them all to the "condemned" list. */
2711 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2712 FRAME_SCROLL_BARS (frame
) = Qnil
;
2715 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2716 Note that WINDOW isn't necessarily condemned at all. */
2718 XTredeem_scroll_bar (window
)
2719 struct window
*window
;
2721 struct scroll_bar
*bar
;
2723 /* We can't redeem this window's scroll bar if it doesn't have one. */
2724 if (NILP (window
->vertical_scroll_bar
))
2727 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2729 /* Unlink it from the condemned list. */
2731 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2733 if (NILP (bar
->prev
))
2735 /* If the prev pointer is nil, it must be the first in one of
2737 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2738 /* It's not condemned. Everything's fine. */
2740 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2741 window
->vertical_scroll_bar
))
2742 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2744 /* If its prev pointer is nil, it must be at the front of
2745 one or the other! */
2749 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2751 if (! NILP (bar
->next
))
2752 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2754 bar
->next
= FRAME_SCROLL_BARS (f
);
2756 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2757 if (! NILP (bar
->next
))
2758 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2762 /* Remove all scroll bars on FRAME that haven't been saved since the
2763 last call to `*condemn_scroll_bars_hook'. */
2765 XTjudge_scroll_bars (f
)
2768 Lisp_Object bar
, next
;
2770 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2772 /* Clear out the condemned list now so we won't try to process any
2773 more events on the hapless scroll bars. */
2774 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2776 for (; ! NILP (bar
); bar
= next
)
2778 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2780 x_scroll_bar_remove (b
);
2783 b
->next
= b
->prev
= Qnil
;
2786 /* Now there should be no references to the condemned scroll bars,
2787 and they should get garbage-collected. */
2791 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2793 This may be called from a signal handler, so we have to ignore GC
2796 x_scroll_bar_expose (bar
, event
)
2797 struct scroll_bar
*bar
;
2800 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2801 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2802 GC gc
= f
->display
.x
->normal_gc
;
2806 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2808 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2809 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2811 /* x, y, width, height */
2812 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2817 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2818 is set to something other than no_event, it is enqueued.
2820 This may be called from a signal handler, so we have to ignore GC
2823 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2824 struct scroll_bar
*bar
;
2826 struct input_event
*emacs_event
;
2828 if (! GC_WINDOWP (bar
->window
))
2831 emacs_event
->kind
= scroll_bar_click
;
2832 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2833 emacs_event
->modifiers
2834 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2835 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2836 event
->xbutton
.state
)
2837 | (event
->type
== ButtonRelease
2840 emacs_event
->frame_or_window
= bar
->window
;
2841 emacs_event
->timestamp
= event
->xbutton
.time
;
2844 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2846 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2847 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2850 if (y
> top_range
) y
= top_range
;
2852 if (y
< XINT (bar
->start
))
2853 emacs_event
->part
= scroll_bar_above_handle
;
2854 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2855 emacs_event
->part
= scroll_bar_handle
;
2857 emacs_event
->part
= scroll_bar_below_handle
;
2859 /* Just because the user has clicked on the handle doesn't mean
2860 they want to drag it. Lisp code needs to be able to decide
2861 whether or not we're dragging. */
2863 /* If the user has just clicked on the handle, record where they're
2865 if (event
->type
== ButtonPress
2866 && emacs_event
->part
== scroll_bar_handle
)
2867 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2870 /* If the user has released the handle, set it to its final position. */
2871 if (event
->type
== ButtonRelease
2872 && ! NILP (bar
->dragging
))
2874 int new_start
= y
- XINT (bar
->dragging
);
2875 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2877 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2878 bar
->dragging
= Qnil
;
2881 /* Same deal here as the other #if 0. */
2883 /* Clicks on the handle are always reported as occurring at the top of
2885 if (emacs_event
->part
== scroll_bar_handle
)
2886 emacs_event
->x
= bar
->start
;
2888 XSETINT (emacs_event
->x
, y
);
2890 XSETINT (emacs_event
->x
, y
);
2893 XSETINT (emacs_event
->y
, top_range
);
2897 /* Handle some mouse motion while someone is dragging the scroll bar.
2899 This may be called from a signal handler, so we have to ignore GC
2902 x_scroll_bar_note_movement (bar
, event
)
2903 struct scroll_bar
*bar
;
2906 last_mouse_movement_time
= event
->xmotion
.time
;
2909 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2911 /* If we're dragging the bar, display it. */
2912 if (! GC_NILP (bar
->dragging
))
2914 /* Where should the handle be now? */
2915 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2917 if (new_start
!= XINT (bar
->start
))
2919 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2921 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2925 /* Call XQueryPointer so we'll get an event the next time the mouse
2926 moves and we can see *still* on the same position. */
2929 Window dummy_window
;
2931 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2932 &dummy_window
, &dummy_window
,
2933 &dummy
, &dummy
, &dummy
, &dummy
,
2934 (unsigned int *) &dummy
);
2938 /* Return information to the user about the current position of the mouse
2939 on the scroll bar. */
2941 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2943 Lisp_Object
*bar_window
;
2944 enum scroll_bar_part
*part
;
2946 unsigned long *time
;
2948 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2949 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2950 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2952 Window dummy_window
;
2954 unsigned int dummy_mask
;
2958 /* Get the mouse's position relative to the scroll bar window, and
2960 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
2962 /* Root, child, root x and root y. */
2963 &dummy_window
, &dummy_window
,
2964 &dummy_coord
, &dummy_coord
,
2966 /* Position relative to scroll bar. */
2969 /* Mouse buttons and modifier keys. */
2975 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2977 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2979 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2981 if (! NILP (bar
->dragging
))
2982 win_y
-= XINT (bar
->dragging
);
2986 if (win_y
> top_range
)
2990 *bar_window
= bar
->window
;
2992 if (! NILP (bar
->dragging
))
2993 *part
= scroll_bar_handle
;
2994 else if (win_y
< XINT (bar
->start
))
2995 *part
= scroll_bar_above_handle
;
2996 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2997 *part
= scroll_bar_handle
;
2999 *part
= scroll_bar_below_handle
;
3001 XSETINT (*x
, win_y
);
3002 XSETINT (*y
, top_range
);
3005 last_mouse_scroll_bar
= Qnil
;
3008 *time
= last_mouse_movement_time
;
3014 /* The screen has been cleared so we may have changed foreground or
3015 background colors, and the scroll bars may need to be redrawn.
3016 Clear out the scroll bars, and ask for expose events, so we can
3019 x_scroll_bar_clear (f
)
3024 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3025 bar
= XSCROLL_BAR (bar
)->next
)
3026 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3030 /* This processes Expose events from the menubar specific X event
3031 loop in xmenu.c. This allows to redisplay the frame if necessary
3032 when handling menubar or popup items. */
3035 process_expose_from_menu (event
)
3039 struct x_display_info
*dpyinfo
;
3043 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3044 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3047 if (f
->async_visible
== 0)
3049 f
->async_visible
= 1;
3050 f
->async_iconified
= 0;
3051 SET_FRAME_GARBAGED (f
);
3055 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3056 event
.xexpose
.x
, event
.xexpose
.y
,
3057 event
.xexpose
.width
, event
.xexpose
.height
);
3062 struct scroll_bar
*bar
3063 = x_window_to_scroll_bar (event
.xexpose
.window
);
3066 x_scroll_bar_expose (bar
, &event
);
3072 /* Define a queue to save up SelectionRequest events for later handling. */
3074 struct selection_event_queue
3077 struct selection_event_queue
*next
;
3080 static struct selection_event_queue
*queue
;
3082 /* Nonzero means queue up certain events--don't process them yet. */
3083 static int x_queue_selection_requests
;
3085 /* Queue up an X event *EVENT, to be processed later. */
3088 x_queue_event (f
, event
)
3092 struct selection_event_queue
*queue_tmp
3093 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3095 if (queue_tmp
!= NULL
)
3097 queue_tmp
->event
= *event
;
3098 queue_tmp
->next
= queue
;
3103 /* Take all the queued events and put them back
3104 so that they get processed afresh. */
3107 x_unqueue_events (display
)
3110 while (queue
!= NULL
)
3112 struct selection_event_queue
*queue_tmp
= queue
;
3113 XPutBackEvent (display
, &queue_tmp
->event
);
3114 queue
= queue_tmp
->next
;
3115 free ((char *)queue_tmp
);
3119 /* Start queuing SelectionRequest events. */
3122 x_start_queuing_selection_requests (display
)
3125 x_queue_selection_requests
++;
3128 /* Stop queuing SelectionRequest events. */
3131 x_stop_queuing_selection_requests (display
)
3134 x_queue_selection_requests
--;
3135 x_unqueue_events (display
);
3138 /* The main X event-reading loop - XTread_socket. */
3140 /* Timestamp of enter window event. This is only used by XTread_socket,
3141 but we have to put it out here, since static variables within functions
3142 sometimes don't work. */
3143 static Time enter_timestamp
;
3145 /* This holds the state XLookupString needs to implement dead keys
3146 and other tricks known as "compose processing". _X Window System_
3147 says that a portable program can't use this, but Stephen Gildea assures
3148 me that letting the compiler initialize it to zeros will work okay.
3150 This must be defined outside of XTread_socket, for the same reasons
3151 given for enter_timestamp, above. */
3152 static XComposeStatus compose_status
;
3154 /* Record the last 100 characters stored
3155 to help debug the loss-of-chars-during-GC problem. */
3157 short temp_buffer
[100];
3159 /* Set this to nonzero to fake an "X I/O error"
3160 on a particular display. */
3161 struct x_display_info
*XTread_socket_fake_io_error
;
3163 /* Read events coming from the X server.
3164 This routine is called by the SIGIO handler.
3165 We return as soon as there are no more events to be read.
3167 Events representing keys are stored in buffer BUFP,
3168 which can hold up to NUMCHARS characters.
3169 We return the number of characters stored into the buffer,
3170 thus pretending to be `read'.
3172 WAITP is nonzero if we should block until input arrives.
3173 EXPECTED is nonzero if the caller knows input is available. */
3176 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3178 register struct input_event
*bufp
;
3179 register int numchars
;
3186 int items_pending
; /* How many items are in the X queue. */
3189 int event_found
= 0;
3192 struct x_display_info
*dpyinfo
;
3194 if (interrupt_input_blocked
)
3196 interrupt_input_pending
= 1;
3200 interrupt_input_pending
= 0;
3203 /* So people can tell when we have read the available input. */
3204 input_signal_count
++;
3207 abort (); /* Don't think this happens. */
3209 /* Find the display we are supposed to read input for.
3210 It's the one communicating on descriptor SD. */
3211 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3213 #if 0 /* This ought to be unnecessary; let's verify it. */
3215 /* If available, Xlib uses FIOSNBIO to make the socket
3216 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3217 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3218 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3219 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3220 #endif /* ! defined (FIOSNBIO) */
3223 #if 0 /* This code can't be made to work, with multiple displays,
3224 and appears not to be used on any system any more.
3225 Also keyboard.c doesn't turn O_NDELAY on and off
3226 for X connections. */
3229 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3231 extern int read_alarm_should_throw
;
3232 read_alarm_should_throw
= 1;
3233 XPeekEvent (dpyinfo
->display
, &event
);
3234 read_alarm_should_throw
= 0;
3236 #endif /* HAVE_SELECT */
3240 /* For debugging, this gives a way to fake an I/O error. */
3241 if (dpyinfo
== XTread_socket_fake_io_error
)
3243 XTread_socket_fake_io_error
= 0;
3244 x_io_error_quitter (dpyinfo
->display
);
3247 while (XPending (dpyinfo
->display
) != 0)
3249 XNextEvent (dpyinfo
->display
, &event
);
3256 if (event
.xclient
.message_type
3257 == dpyinfo
->Xatom_wm_protocols
3258 && event
.xclient
.format
== 32)
3260 if (event
.xclient
.data
.l
[0]
3261 == dpyinfo
->Xatom_wm_take_focus
)
3263 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3264 /* Since we set WM_TAKE_FOCUS, we must call
3265 XSetInputFocus explicitly. But not if f is null,
3266 since that might be an event for a deleted frame. */
3268 XSetInputFocus (event
.xclient
.display
,
3269 event
.xclient
.window
,
3270 RevertToPointerRoot
,
3271 event
.xclient
.data
.l
[1]);
3272 /* Not certain about handling scroll bars here */
3274 else if (event
.xclient
.data
.l
[0]
3275 == dpyinfo
->Xatom_wm_save_yourself
)
3277 /* Save state modify the WM_COMMAND property to
3278 something which can reinstate us. This notifies
3279 the session manager, who's looking for such a
3280 PropertyNotify. Can restart processing when
3281 a keyboard or mouse event arrives. */
3284 f
= x_top_window_to_frame (dpyinfo
,
3285 event
.xclient
.window
);
3287 /* This is just so we only give real data once
3288 for a single Emacs process. */
3289 if (f
== selected_frame
)
3290 XSetCommand (FRAME_X_DISPLAY (f
),
3291 event
.xclient
.window
,
3292 initial_argv
, initial_argc
);
3294 XSetCommand (FRAME_X_DISPLAY (f
),
3295 event
.xclient
.window
,
3299 else if (event
.xclient
.data
.l
[0]
3300 == dpyinfo
->Xatom_wm_delete_window
)
3303 = x_any_window_to_frame (dpyinfo
,
3304 event
.xclient
.window
);
3311 bufp
->kind
= delete_window_event
;
3312 XSETFRAME (bufp
->frame_or_window
, f
);
3320 else if (event
.xclient
.message_type
3321 == dpyinfo
->Xatom_wm_configure_denied
)
3324 else if (event
.xclient
.message_type
3325 == dpyinfo
->Xatom_wm_window_moved
)
3329 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3331 new_x
= event
.xclient
.data
.s
[0];
3332 new_y
= event
.xclient
.data
.s
[1];
3336 f
->display
.x
->left_pos
= new_x
;
3337 f
->display
.x
->top_pos
= new_y
;
3340 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3341 else if (event
.xclient
.message_type
3342 == dpyinfo
->Xatom_editres
)
3345 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3346 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
,
3349 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3353 case SelectionNotify
:
3354 #ifdef USE_X_TOOLKIT
3355 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3357 #endif /* not USE_X_TOOLKIT */
3358 x_handle_selection_notify (&event
);
3361 case SelectionClear
: /* Someone has grabbed ownership. */
3362 #ifdef USE_X_TOOLKIT
3363 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3365 #endif /* USE_X_TOOLKIT */
3367 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3372 bufp
->kind
= selection_clear_event
;
3373 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3374 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3375 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3383 case SelectionRequest
: /* Someone wants our selection. */
3384 #ifdef USE_X_TOOLKIT
3385 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3387 #endif /* USE_X_TOOLKIT */
3388 if (x_queue_selection_requests
)
3389 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3393 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3398 bufp
->kind
= selection_request_event
;
3399 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3400 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3401 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3402 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3403 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3404 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3412 case PropertyNotify
:
3413 #ifdef USE_X_TOOLKIT
3414 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3416 #endif /* not USE_X_TOOLKIT */
3417 x_handle_property_notify (&event
);
3420 case ReparentNotify
:
3421 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3425 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3426 x_real_positions (f
, &x
, &y
);
3427 f
->display
.x
->left_pos
= x
;
3428 f
->display
.x
->top_pos
= y
;
3433 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3436 if (f
->async_visible
== 0)
3438 f
->async_visible
= 1;
3439 f
->async_iconified
= 0;
3440 SET_FRAME_GARBAGED (f
);
3443 dumprectangle (x_window_to_frame (dpyinfo
,
3444 event
.xexpose
.window
),
3445 event
.xexpose
.x
, event
.xexpose
.y
,
3446 event
.xexpose
.width
, event
.xexpose
.height
);
3450 struct scroll_bar
*bar
3451 = x_window_to_scroll_bar (event
.xexpose
.window
);
3454 x_scroll_bar_expose (bar
, &event
);
3455 #ifdef USE_X_TOOLKIT
3458 #endif /* USE_X_TOOLKIT */
3462 case GraphicsExpose
: /* This occurs when an XCopyArea's
3463 source area was obscured or not
3465 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3469 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3470 event
.xgraphicsexpose
.width
,
3471 event
.xgraphicsexpose
.height
);
3473 #ifdef USE_X_TOOLKIT
3476 #endif /* USE_X_TOOLKIT */
3479 case NoExpose
: /* This occurs when an XCopyArea's
3480 source area was completely
3485 f
= x_any_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3486 if (f
) /* F may no longer exist if
3487 the frame was deleted. */
3489 /* While a frame is unmapped, display generation is
3490 disabled; you don't want to spend time updating a
3491 display that won't ever be seen. */
3492 f
->async_visible
= 0;
3493 /* We can't distinguish, from the event, whether the window
3494 has become iconified or invisible. So assume, if it
3495 was previously visible, than now it is iconified.
3496 We depend on x_make_frame_invisible to mark it iconified. */
3497 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3498 f
->async_iconified
= 1;
3500 bufp
->kind
= iconify_event
;
3501 XSETFRAME (bufp
->frame_or_window
, f
);
3506 #ifdef USE_X_TOOLKIT
3508 #endif /* USE_X_TOOLKIT */
3512 /* We use x_top_window_to_frame because map events can come
3513 for subwindows and they don't mean that the frame is visible. */
3514 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
3517 f
->async_visible
= 1;
3518 f
->async_iconified
= 0;
3520 /* wait_reading_process_input will notice this and update
3521 the frame's display structures. */
3522 SET_FRAME_GARBAGED (f
);
3526 bufp
->kind
= deiconify_event
;
3527 XSETFRAME (bufp
->frame_or_window
, f
);
3533 #ifdef USE_X_TOOLKIT
3535 #endif /* USE_X_TOOLKIT */
3538 /* Turn off processing if we become fully obscured. */
3539 case VisibilityNotify
:
3543 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
3547 KeySym keysym
, orig_keysym
;
3548 /* al%imercury@uunet.uu.net says that making this 81 instead of
3549 80 fixed a bug whereby meta chars made his Emacs hang. */
3550 unsigned char copy_buffer
[81];
3554 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3555 extra_keyboard_modifiers
);
3556 modifiers
= event
.xkey
.state
;
3558 /* This will have to go some day... */
3560 /* make_lispy_event turns chars into control chars.
3561 Don't do it here because XLookupString is too eager. */
3562 event
.xkey
.state
&= ~ControlMask
;
3563 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3564 80, &keysym
, &compose_status
);
3566 orig_keysym
= keysym
;
3570 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3571 || keysym
== XK_Delete
3572 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3573 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3575 /* This recognizes the "extended function keys".
3576 It seems there's no cleaner way.
3577 Test IsModifierKey to avoid handling mode_switch
3579 || ((unsigned) (keysym
) >= XK_Select
3580 && (unsigned)(keysym
) < XK_KP_Space
)
3582 #ifdef XK_dead_circumflex
3583 || orig_keysym
== XK_dead_circumflex
3585 #ifdef XK_dead_grave
3586 || orig_keysym
== XK_dead_grave
3588 #ifdef XK_dead_tilde
3589 || orig_keysym
== XK_dead_tilde
3591 #ifdef XK_dead_diaeresis
3592 || orig_keysym
== XK_dead_diaeresis
3594 #ifdef XK_dead_macron
3595 || orig_keysym
== XK_dead_macron
3597 #ifdef XK_dead_degree
3598 || orig_keysym
== XK_dead_degree
3600 #ifdef XK_dead_acute
3601 || orig_keysym
== XK_dead_acute
3603 #ifdef XK_dead_cedilla
3604 || orig_keysym
== XK_dead_cedilla
3606 #ifdef XK_dead_breve
3607 || orig_keysym
== XK_dead_breve
3609 #ifdef XK_dead_ogonek
3610 || orig_keysym
== XK_dead_ogonek
3612 #ifdef XK_dead_caron
3613 || orig_keysym
== XK_dead_caron
3615 #ifdef XK_dead_doubleacute
3616 || orig_keysym
== XK_dead_doubleacute
3618 #ifdef XK_dead_abovedot
3619 || orig_keysym
== XK_dead_abovedot
3621 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3622 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3623 /* Any "vendor-specific" key is ok. */
3624 || (orig_keysym
& (1 << 28)))
3625 && ! (IsModifierKey (orig_keysym
)
3627 #ifdef XK_Mode_switch
3628 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3631 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3633 #endif /* not HAVE_X11R5 */
3636 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3638 temp_buffer
[temp_index
++] = keysym
;
3639 bufp
->kind
= non_ascii_keystroke
;
3640 bufp
->code
= keysym
;
3641 XSETFRAME (bufp
->frame_or_window
, f
);
3643 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3645 bufp
->timestamp
= event
.xkey
.time
;
3650 else if (numchars
> nbytes
)
3654 for (i
= 0; i
< nbytes
; i
++)
3656 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3658 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3659 bufp
->kind
= ascii_keystroke
;
3660 bufp
->code
= copy_buffer
[i
];
3661 XSETFRAME (bufp
->frame_or_window
, f
);
3663 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3665 bufp
->timestamp
= event
.xkey
.time
;
3680 /* Here's a possible interpretation of the whole
3681 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3682 FocusIn event, you have to get a FocusOut event before you
3683 relinquish the focus. If you haven't received a FocusIn event,
3684 then a mere LeaveNotify is enough to free you. */
3687 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3689 if (event
.xcrossing
.focus
) /* Entered Window */
3691 /* Avoid nasty pop/raise loops. */
3692 if (f
&& (!(f
->auto_raise
)
3694 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3696 x_new_focus_frame (dpyinfo
, f
);
3697 enter_timestamp
= event
.xcrossing
.time
;
3700 else if (f
== dpyinfo
->x_focus_frame
)
3701 x_new_focus_frame (dpyinfo
, 0);
3702 /* EnterNotify counts as mouse movement,
3703 so update things that depend on mouse position. */
3705 note_mouse_movement (f
, &event
.xmotion
);
3706 #ifdef USE_X_TOOLKIT
3708 #endif /* USE_X_TOOLKIT */
3712 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3713 if (event
.xfocus
.detail
!= NotifyPointer
)
3714 dpyinfo
->x_focus_event_frame
= f
;
3716 x_new_focus_frame (dpyinfo
, f
);
3717 #ifdef USE_X_TOOLKIT
3719 #endif /* USE_X_TOOLKIT */
3724 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3727 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3728 /* If we move outside the frame,
3729 then we're certainly no longer on any text in the frame. */
3730 clear_mouse_face (dpyinfo
);
3732 if (event
.xcrossing
.focus
)
3733 x_mouse_leave (dpyinfo
);
3736 if (f
== dpyinfo
->x_focus_event_frame
)
3737 dpyinfo
->x_focus_event_frame
= 0;
3738 if (f
== dpyinfo
->x_focus_frame
)
3739 x_new_focus_frame (dpyinfo
, 0);
3742 #ifdef USE_X_TOOLKIT
3744 #endif /* USE_X_TOOLKIT */
3748 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3749 if (event
.xfocus
.detail
!= NotifyPointer
3750 && f
== dpyinfo
->x_focus_event_frame
)
3751 dpyinfo
->x_focus_event_frame
= 0;
3752 if (f
&& f
== dpyinfo
->x_focus_frame
)
3753 x_new_focus_frame (dpyinfo
, 0);
3754 #ifdef USE_X_TOOLKIT
3756 #endif /* USE_X_TOOLKIT */
3761 if (dpyinfo
->grabbed
&& last_mouse_frame
3762 && FRAME_LIVE_P (last_mouse_frame
))
3763 f
= last_mouse_frame
;
3765 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3767 note_mouse_movement (f
, &event
.xmotion
);
3770 struct scroll_bar
*bar
3771 = x_window_to_scroll_bar (event
.xmotion
.window
);
3774 x_scroll_bar_note_movement (bar
, &event
);
3776 /* If we move outside the frame,
3777 then we're certainly no longer on any text in the frame. */
3778 clear_mouse_face (dpyinfo
);
3781 #if 0 /* This should be unnecessary, since the toolkit has no use
3782 for motion events that happen outside of the menu event loop,
3783 and it seems to cause the bug that mouse events stop coming
3785 #ifdef USE_X_TOOLKIT
3787 #endif /* USE_X_TOOLKIT */
3791 case ConfigureNotify
:
3792 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
3794 #ifdef USE_X_TOOLKIT
3795 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
))
3799 #ifndef USE_X_TOOLKIT
3800 /* In the toolkit version, change_frame_size
3801 is called by the code that handles resizing
3802 of the EmacsFrame widget. */
3804 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3805 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3807 /* Even if the number of character rows and columns has
3808 not changed, the font size may have changed, so we need
3809 to check the pixel dimensions as well. */
3810 if (columns
!= f
->width
3811 || rows
!= f
->height
3812 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3813 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3815 change_frame_size (f
, rows
, columns
, 0, 1);
3816 SET_FRAME_GARBAGED (f
);
3820 /* Formerly, in the USE_X_TOOLKIT version,
3821 we did not test send_event here. */
3823 #ifndef USE_X_TOOLKIT
3824 && ! event
.xconfigure
.send_event
3831 /* Find the position of the outside upper-left corner of
3832 the window, in the root coordinate system. Don't
3833 refer to the parent window here; we may be processing
3834 this event after the window manager has changed our
3835 parent, but before we have reached the ReparentNotify. */
3836 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3838 /* From-window, to-window. */
3839 event
.xconfigure
.window
,
3840 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3842 /* From-position, to-position. */
3843 -event
.xconfigure
.border_width
,
3844 -event
.xconfigure
.border_width
,
3849 event
.xconfigure
.x
= win_x
;
3850 event
.xconfigure
.y
= win_y
;
3853 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3854 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3855 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3856 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3858 /* What we have now is the position of Emacs's own window.
3859 Convert that to the position of the window manager window. */
3862 x_real_positions (f
, &x
, &y
);
3863 f
->display
.x
->left_pos
= x
;
3864 f
->display
.x
->top_pos
= y
;
3865 /* Formerly we did not do this in the USE_X_TOOLKIT
3866 version. Let's try making them the same. */
3867 /* #ifndef USE_X_TOOLKIT */
3868 if (y
!= event
.xconfigure
.y
)
3870 /* Since the WM decorations come below top_pos now,
3871 we must put them below top_pos in the future. */
3872 f
->display
.x
->win_gravity
= NorthWestGravity
;
3873 x_wm_set_size_hint (f
, 0, 0);
3878 #ifdef USE_X_TOOLKIT
3887 /* If we decide we want to generate an event to be seen
3888 by the rest of Emacs, we put it here. */
3889 struct input_event emacs_event
;
3890 emacs_event
.kind
= no_event
;
3892 bzero (&compose_status
, sizeof (compose_status
));
3894 if (dpyinfo
->grabbed
&& last_mouse_frame
3895 && FRAME_LIVE_P (last_mouse_frame
))
3896 f
= last_mouse_frame
;
3898 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3902 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
3903 construct_mouse_click (&emacs_event
, &event
, f
);
3907 struct scroll_bar
*bar
3908 = x_window_to_scroll_bar (event
.xbutton
.window
);
3911 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3912 #ifdef USE_X_TOOLKIT
3915 /* Assume we have a menubar button press. A bad
3916 assumption should behave benignly. */
3917 popup_get_selection (&event
, dpyinfo
);
3920 #endif /* USE_X_TOOLKIT */
3923 if (event
.type
== ButtonPress
)
3925 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
3926 last_mouse_frame
= f
;
3930 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
3933 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3935 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3941 #ifdef USE_X_TOOLKIT
3943 #endif /* USE_X_TOOLKIT */
3947 case CirculateNotify
:
3949 case CirculateRequest
:
3953 /* Someone has changed the keyboard mapping - update the
3955 switch (event
.xmapping
.request
)
3957 case MappingModifier
:
3958 x_find_modifier_meanings (dpyinfo
);
3959 /* This is meant to fall through. */
3960 case MappingKeyboard
:
3961 XRefreshKeyboardMapping (&event
.xmapping
);
3963 #ifdef USE_X_TOOLKIT
3965 #endif /* USE_X_TOOLKIT */
3969 #ifdef USE_X_TOOLKIT
3972 XtDispatchEvent (&event
);
3974 #endif /* USE_X_TOOLKIT */
3980 /* On some systems, an X bug causes Emacs to get no more events
3981 when the window is destroyed. Detect that. (1994.) */
3984 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
3985 One XNOOP in 100 loops will make Emacs terminate.
3986 B. Bretthauer, 1994 */
3988 if (x_noop_count
>= 100)
3991 /* Use the first display in the list. Why not? */
3992 XNoOp (x_display_list
->display
);
3996 /* If the focus was just given to an autoraising frame,
3998 /* ??? This ought to be able to handle more than one such frame. */
3999 if (pending_autoraise_frame
)
4001 x_raise_frame (pending_autoraise_frame
);
4002 pending_autoraise_frame
= 0;
4009 /* Drawing the cursor. */
4012 /* Draw a hollow box cursor. Don't change the inside of the box. */
4018 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
4019 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
4020 int width
= FONT_WIDTH (f
->display
.x
->font
);
4021 int height
= f
->display
.x
->line_height
;
4023 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4024 f
->display
.x
->cursor_gc
,
4025 left
, top
, width
- 1, height
- 1);
4028 /* Clear the cursor of frame F to background color,
4029 and mark the cursor as not shown.
4030 This is used when the text where the cursor is
4031 is about to be rewritten. */
4039 if (! FRAME_VISIBLE_P (f
)
4040 || f
->phys_cursor_x
< 0)
4043 x_display_cursor (f
, 0);
4044 f
->phys_cursor_x
= -1;
4047 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4048 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4052 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4059 CHAR_TO_PIXEL_COL (f
, column
),
4060 CHAR_TO_PIXEL_ROW (f
, row
),
4061 &glyph
, 1, highlight
, 0);
4065 x_display_bar_cursor (f
, on
)
4069 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4071 /* This is pointless on invisible frames, and dangerous on garbaged
4072 frames; in the latter case, the frame may be in the midst of
4073 changing its size, and curs_x and curs_y may be off the frame. */
4074 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4077 if (! on
&& f
->phys_cursor_x
< 0)
4080 /* If we're not updating, then we want to use the current frame's
4081 cursor position, not our local idea of where the cursor ought to be. */
4082 if (f
!= updating_frame
)
4084 curs_x
= FRAME_CURSOR_X (f
);
4085 curs_y
= FRAME_CURSOR_Y (f
);
4088 /* If there is anything wrong with the current cursor state, remove it. */
4089 if (f
->phys_cursor_x
>= 0
4091 || f
->phys_cursor_x
!= curs_x
4092 || f
->phys_cursor_y
!= curs_y
4093 || f
->display
.x
->current_cursor
!= bar_cursor
))
4095 /* Erase the cursor by redrawing the character underneath it. */
4096 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4097 f
->phys_cursor_glyph
,
4098 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4099 f
->phys_cursor_x
= -1;
4102 /* If we now need a cursor in the new place or in the new form, do it so. */
4104 && (f
->phys_cursor_x
< 0
4105 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4107 f
->phys_cursor_glyph
4108 = ((current_glyphs
->enable
[curs_y
]
4109 && curs_x
< current_glyphs
->used
[curs_y
])
4110 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4112 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4113 f
->display
.x
->cursor_gc
,
4114 CHAR_TO_PIXEL_COL (f
, curs_x
),
4115 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4116 max (f
->display
.x
->cursor_width
, 1),
4117 f
->display
.x
->line_height
);
4119 f
->phys_cursor_x
= curs_x
;
4120 f
->phys_cursor_y
= curs_y
;
4122 f
->display
.x
->current_cursor
= bar_cursor
;
4125 if (updating_frame
!= f
)
4126 XFlush (FRAME_X_DISPLAY (f
));
4130 /* Turn the displayed cursor of frame F on or off according to ON.
4131 If ON is nonzero, where to put the cursor is specified
4132 by F->cursor_x and F->cursor_y. */
4135 x_display_box_cursor (f
, on
)
4139 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4141 /* This is pointless on invisible frames, and dangerous on garbaged
4142 frames; in the latter case, the frame may be in the midst of
4143 changing its size, and curs_x and curs_y may be off the frame. */
4144 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4147 /* If cursor is off and we want it off, return quickly. */
4148 if (!on
&& f
->phys_cursor_x
< 0)
4151 /* If we're not updating, then we want to use the current frame's
4152 cursor position, not our local idea of where the cursor ought to be. */
4153 if (f
!= updating_frame
)
4155 curs_x
= FRAME_CURSOR_X (f
);
4156 curs_y
= FRAME_CURSOR_Y (f
);
4159 /* If cursor is currently being shown and we don't want it to be
4160 or it is in the wrong place,
4161 or we want a hollow box and it's not so, (pout!)
4163 if (f
->phys_cursor_x
>= 0
4165 || f
->phys_cursor_x
!= curs_x
4166 || f
->phys_cursor_y
!= curs_y
4167 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4168 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4170 int mouse_face_here
= 0;
4171 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4173 /* If the cursor is in the mouse face area, redisplay that when
4174 we clear the cursor. */
4175 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4177 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4178 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4179 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4181 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4182 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4183 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4184 /* Don't redraw the cursor's spot in mouse face
4185 if it is at the end of a line (on a newline).
4186 The cursor appears there, but mouse highlighting does not. */
4187 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4188 mouse_face_here
= 1;
4190 /* If the font is not as tall as a whole line,
4191 we must explicitly clear the line's whole height. */
4192 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4193 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4194 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4195 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4196 FONT_WIDTH (f
->display
.x
->font
),
4197 f
->display
.x
->line_height
, False
);
4198 /* Erase the cursor by redrawing the character underneath it. */
4199 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4200 f
->phys_cursor_glyph
,
4203 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4204 f
->phys_cursor_x
= -1;
4207 /* If we want to show a cursor,
4208 or we want a box cursor and it's not so,
4209 write it in the right place. */
4211 && (f
->phys_cursor_x
< 0
4212 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4213 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4215 f
->phys_cursor_glyph
4216 = ((current_glyphs
->enable
[curs_y
]
4217 && curs_x
< current_glyphs
->used
[curs_y
])
4218 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4220 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4223 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4227 x_draw_single_glyph (f
, curs_y
, curs_x
,
4228 f
->phys_cursor_glyph
, 2);
4229 f
->display
.x
->current_cursor
= filled_box_cursor
;
4232 f
->phys_cursor_x
= curs_x
;
4233 f
->phys_cursor_y
= curs_y
;
4236 if (updating_frame
!= f
)
4237 XFlush (FRAME_X_DISPLAY (f
));
4240 x_display_cursor (f
, on
)
4246 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4247 x_display_box_cursor (f
, on
);
4248 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4249 x_display_bar_cursor (f
, on
);
4251 /* Those are the only two we have implemented! */
4259 /* Refresh bitmap kitchen sink icon for frame F
4260 when we get an expose event for it. */
4265 /* Normally, the window manager handles this function. */
4268 /* Make the x-window of frame F use the gnu icon bitmap. */
4271 x_bitmap_icon (f
, file
)
4275 int mask
, bitmap_id
;
4278 if (FRAME_X_WINDOW (f
) == 0)
4281 /* Free up our existing icon bitmap if any. */
4282 if (f
->display
.x
->icon_bitmap
> 0)
4283 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4284 f
->display
.x
->icon_bitmap
= 0;
4287 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4290 /* Create the GNU bitmap if necessary. */
4291 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4292 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4293 = x_create_bitmap_from_data (f
, gnu_bits
,
4294 gnu_width
, gnu_height
);
4296 /* The first time we create the GNU bitmap,
4297 this increments the refcount one extra time.
4298 As a result, the GNU bitmap is never freed.
4299 That way, we don't have to worry about allocating it again. */
4300 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4302 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4305 x_wm_set_icon_pixmap (f
, bitmap_id
);
4306 f
->display
.x
->icon_bitmap
= bitmap_id
;
4312 /* Make the x-window of frame F use a rectangle with text. */
4315 x_text_icon (f
, icon_name
)
4319 if (FRAME_X_WINDOW (f
) == 0)
4323 f
->display
.x
->icon_label
= icon_name
;
4325 if (! f
->display
.x
->icon_label
)
4326 f
->display
.x
->icon_label
= " *emacs* ";
4329 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4330 (char *) f
->display
.x
->icon_label
);
4333 if (f
->display
.x
->icon_bitmap
> 0)
4334 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4335 f
->display
.x
->icon_bitmap
= 0;
4336 x_wm_set_icon_pixmap (f
, 0);
4341 /* Handling X errors. */
4343 /* Handle the loss of connection to display DISPLAY. */
4346 x_connection_closed (display
, error_message
)
4348 char *error_message
;
4350 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4351 Lisp_Object frame
, tail
;
4356 /* First delete frames whose minibuffers are on frames
4357 that are on the dead display. */
4358 FOR_EACH_FRAME (tail
, frame
)
4360 Lisp_Object minibuf_frame
;
4362 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4363 if (FRAME_X_P (XFRAME (frame
))
4364 && FRAME_X_P (XFRAME (minibuf_frame
))
4365 && ! EQ (frame
, minibuf_frame
)
4366 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4367 Fdelete_frame (frame
, Qt
);
4370 /* Now delete all remaining frames on the dead display.
4371 We are now sure none of these is used as the minibuffer
4372 for another frame that we need to delete. */
4373 FOR_EACH_FRAME (tail
, frame
)
4374 if (FRAME_X_P (XFRAME (frame
))
4375 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4376 Fdelete_frame (frame
, Qt
);
4378 x_delete_display (dpyinfo
);
4380 if (x_display_list
== 0)
4382 fprintf (stderr
, "%s", error_message
);
4383 shut_down_emacs (0, 0, Qnil
);
4387 /* Ordinary stack unwind doesn't deal with these. */
4389 sigunblock (sigmask (SIGIO
));
4391 sigunblock (sigmask (SIGALRM
));
4392 TOTALLY_UNBLOCK_INPUT
;
4394 error ("%s", error_message
);
4398 x_connection_signal (signalnum
) /* If we don't have an argument, */
4399 int signalnum
; /* some compilers complain in signal calls. */
4401 /* We really ought to close the connection to the display
4402 that actually failed.
4403 But do we actually get this signal ever with X11? */
4404 fprintf (stderr
, "X connection closed");
4405 shut_down_emacs (0, 0, Qnil
);
4409 /* This is the usual handler for X protocol errors.
4410 It kills all frames on the display that we got the error for.
4411 If that was the only one, it prints an error message and kills Emacs. */
4414 x_error_quitter (display
, error
)
4418 char buf
[256], buf1
[356];
4420 /* Note that there is no real way portable across R3/R4 to get the
4421 original error handler. */
4423 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4424 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4425 buf
, error
->request_code
);
4426 x_connection_closed (display
, buf1
);
4429 /* This is the handler for X IO errors, always.
4430 It kills all frames on the display that we lost touch with.
4431 If that was the only one, it prints an error message and kills Emacs. */
4434 x_io_error_quitter (display
)
4439 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4440 x_connection_closed (display
, buf
);
4443 /* A buffer for storing X error messages. */
4444 static char *x_caught_error_message
;
4445 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4447 /* An X error handler which stores the error message in
4448 x_caught_error_message. This is what's installed when
4449 x_catch_errors is in effect. */
4452 x_error_catcher (display
, error
)
4456 XGetErrorText (display
, error
->error_code
,
4457 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4461 /* Begin trapping X errors for display DPY. Actually we trap X errors
4462 for all displays, but DPY should be the display you are actually
4465 After calling this function, X protocol errors no longer cause
4466 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4468 Calling x_check_errors signals an Emacs error if an X error has
4469 occurred since the last call to x_catch_errors or x_check_errors.
4471 Calling x_uncatch_errors resumes the normal error handling. */
4473 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4476 x_catch_errors (dpy
)
4479 /* Make sure any errors from previous requests have been dealt with. */
4482 /* Set up the error buffer. */
4483 x_caught_error_message
4484 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4485 x_caught_error_message
[0] = '\0';
4487 /* Install our little error handler. */
4488 XSetErrorHandler (x_error_catcher
);
4491 /* If any X protocol errors have arrived since the last call to
4492 x_catch_errors or x_check_errors, signal an Emacs error using
4493 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4496 x_check_errors (dpy
, format
)
4500 /* Make sure to catch any errors incurred so far. */
4503 if (x_caught_error_message
[0])
4505 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4507 sprintf (buf
, format
, x_caught_error_message
);
4508 x_uncatch_errors (dpy
);
4513 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4516 x_had_errors_p (dpy
)
4519 /* Make sure to catch any errors incurred so far. */
4522 return x_caught_error_message
[0] != 0;
4525 /* Stop catching X protocol errors and let them make Emacs die. */
4528 x_uncatch_errors (dpy
)
4531 xfree (x_caught_error_message
);
4532 x_caught_error_message
= 0;
4533 XSetErrorHandler (x_error_quitter
);
4537 static unsigned int x_wire_count
;
4540 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4545 /* Changing the font of the frame. */
4547 /* Give frame F the font named FONTNAME as its default font, and
4548 return the full name of that font. FONTNAME may be a wildcard
4549 pattern; in that case, we choose some font that fits the pattern.
4550 The return value shows which font we chose. */
4553 x_new_font (f
, fontname
)
4555 register char *fontname
;
4558 int n_matching_fonts
;
4559 XFontStruct
*font_info
;
4562 /* Get a list of all the fonts that match this name. Once we
4563 have a list of matching fonts, we compare them against the fonts
4564 we already have by comparing font ids. */
4565 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4566 1024, &n_matching_fonts
);
4567 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4568 find any matches; font_names == 0 is the only clue. */
4570 n_matching_fonts
= 0;
4572 /* Don't just give up if n_matching_fonts is 0.
4573 Apparently there's a bug on Suns: XListFontsWithInfo can
4574 fail to find a font, but XLoadQueryFont may still find it. */
4576 /* See if we've already loaded a matching font. */
4577 already_loaded
= -1;
4578 if (n_matching_fonts
!= 0)
4582 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4583 for (j
= 0; j
< n_matching_fonts
; j
++)
4584 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4585 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4588 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4594 /* If we have, just return it from the table. */
4595 if (already_loaded
>= 0)
4596 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4597 /* Otherwise, load the font and add it to the table. */
4605 /* Try to find a character-cell font in the list. */
4607 /* A laudable goal, but this isn't how to do it. */
4608 for (i
= 0; i
< n_matching_fonts
; i
++)
4609 if (! font_info
[i
].per_char
)
4615 /* See comment above. */
4616 if (n_matching_fonts
!= 0)
4617 fontname
= font_names
[i
];
4619 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4622 /* Free the information from XListFonts. */
4623 if (n_matching_fonts
)
4624 XFreeFontNames (font_names
);
4628 /* Do we need to create the table? */
4629 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4631 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4632 FRAME_X_DISPLAY_INFO (f
)->font_table
4633 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4634 * sizeof (struct font_info
));
4636 /* Do we need to grow the table? */
4637 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4638 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4640 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4641 FRAME_X_DISPLAY_INFO (f
)->font_table
4642 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4643 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4644 * sizeof (struct font_info
)));
4647 /* Try to get the full name of FONT. Put it in full_name. */
4649 for (i
= 0; i
< font
->n_properties
; i
++)
4652 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4653 if (!strcmp (atom
, "FONT"))
4655 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4656 (Atom
) (font
->properties
[i
].card32
));
4660 /* Count the number of dashes in the "full name".
4661 If it is too few, this isn't really the font's full name,
4663 In X11R4, the fonts did not come with their canonical names
4681 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4682 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4683 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4685 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4687 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4688 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4689 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4692 fontname
= full_name
;
4695 /* Compute the scroll bar width in character columns. */
4696 if (f
->scroll_bar_pixel_width
> 0)
4698 int wid
= FONT_WIDTH (f
->display
.x
->font
);
4699 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4702 f
->scroll_bar_cols
= 2;
4704 /* Now make the frame display the given font. */
4705 if (FRAME_X_WINDOW (f
) != 0)
4707 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->normal_gc
,
4708 f
->display
.x
->font
->fid
);
4709 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->reverse_gc
,
4710 f
->display
.x
->font
->fid
);
4711 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->cursor_gc
,
4712 f
->display
.x
->font
->fid
);
4714 frame_update_line_height (f
);
4715 x_set_window_size (f
, 0, f
->width
, f
->height
);
4718 /* If we are setting a new frame's font for the first time,
4719 there are no faces yet, so this font's height is the line height. */
4720 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
4723 Lisp_Object lispy_name
;
4725 lispy_name
= build_string (fontname
);
4727 /* Free the information from XListFonts. The data
4728 we actually retain comes from XLoadQueryFont. */
4729 XFreeFontNames (font_names
);
4735 x_calc_absolute_position (f
)
4739 int win_x
= 0, win_y
= 0;
4740 int flags
= f
->display
.x
->size_hint_flags
;
4742 /* Find the position of the outside upper-left corner of
4743 the inner window, with respect to the outer window. */
4744 if (f
->display
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4747 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4749 /* From-window, to-window. */
4750 f
->display
.x
->window_desc
,
4751 f
->display
.x
->parent_desc
,
4753 /* From-position, to-position. */
4754 0, 0, &win_x
, &win_y
,
4761 /* Treat negative positions as relative to the leftmost bottommost
4762 position that fits on the screen. */
4763 if (flags
& XNegative
)
4764 f
->display
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4765 - 2 * f
->display
.x
->border_width
- win_x
4767 + f
->display
.x
->left_pos
);
4769 if (flags
& YNegative
)
4770 f
->display
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
4771 - 2 * f
->display
.x
->border_width
- win_y
4773 + f
->display
.x
->top_pos
);
4774 /* The left_pos and top_pos
4775 are now relative to the top and left screen edges,
4776 so the flags should correspond. */
4777 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4780 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4781 to really change the position, and 0 when calling from
4782 x_make_frame_visible (in that case, XOFF and YOFF are the current
4783 position values). */
4785 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4787 register int xoff
, yoff
;
4792 f
->display
.x
->top_pos
= yoff
;
4793 f
->display
.x
->left_pos
= xoff
;
4794 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4796 f
->display
.x
->size_hint_flags
|= XNegative
;
4798 f
->display
.x
->size_hint_flags
|= YNegative
;
4799 f
->display
.x
->win_gravity
= NorthWestGravity
;
4801 x_calc_absolute_position (f
);
4804 x_wm_set_size_hint (f
, 0, 0);
4806 #ifdef USE_X_TOOLKIT
4807 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
),
4808 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4809 #else /* not USE_X_TOOLKIT */
4810 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4811 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4812 #endif /* not USE_X_TOOLKIT */
4816 /* Call this to change the size of frame F's x-window.
4817 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4818 for this size change and subsequent size changes.
4819 Otherwise we leave the window gravity unchanged. */
4821 x_set_window_size (f
, change_gravity
, cols
, rows
)
4826 int pixelwidth
, pixelheight
;
4829 #ifdef USE_X_TOOLKIT
4832 /* The x and y position of the widget is clobbered by the
4833 call to XtSetValues within EmacsFrameSetCharSize.
4834 This is a real kludge, but I don't understand Xt so I can't
4835 figure out a correct fix. Can anyone else tell me? -- rms. */
4836 int xpos
= f
->display
.x
->widget
->core
.x
;
4837 int ypos
= f
->display
.x
->widget
->core
.y
;
4838 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4839 f
->display
.x
->widget
->core
.x
= xpos
;
4840 f
->display
.x
->widget
->core
.y
= ypos
;
4844 #else /* not USE_X_TOOLKIT */
4848 check_frame_size (f
, &rows
, &cols
);
4849 f
->display
.x
->vertical_scroll_bar_extra
4850 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4852 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4853 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4854 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
4855 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4856 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4858 f
->display
.x
->win_gravity
= NorthWestGravity
;
4859 x_wm_set_size_hint (f
, 0, 0);
4861 XSync (FRAME_X_DISPLAY (f
), False
);
4862 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4863 pixelwidth
, pixelheight
);
4865 /* Now, strictly speaking, we can't be sure that this is accurate,
4866 but the window manager will get around to dealing with the size
4867 change request eventually, and we'll hear how it went when the
4868 ConfigureNotify event gets here.
4870 We could just not bother storing any of this information here,
4871 and let the ConfigureNotify event set everything up, but that
4872 might be kind of confusing to the lisp code, since size changes
4873 wouldn't be reported in the frame parameters until some random
4874 point in the future when the ConfigureNotify event arrives. */
4875 change_frame_size (f
, rows
, cols
, 0, 0);
4876 PIXEL_WIDTH (f
) = pixelwidth
;
4877 PIXEL_HEIGHT (f
) = pixelheight
;
4879 /* If cursor was outside the new size, mark it as off. */
4880 if (f
->phys_cursor_y
>= rows
4881 || f
->phys_cursor_x
>= cols
)
4883 f
->phys_cursor_x
= -1;
4884 f
->phys_cursor_y
= -1;
4887 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4888 receive in the ConfigureNotify event; if we get what we asked
4889 for, then the event won't cause the screen to become garbaged, so
4890 we have to make sure to do it here. */
4891 SET_FRAME_GARBAGED (f
);
4893 XFlush (FRAME_X_DISPLAY (f
));
4895 #endif /* not USE_X_TOOLKIT */
4898 /* Mouse warping, focus shifting, raising and lowering. */
4901 x_set_mouse_position (f
, x
, y
)
4907 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4908 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
4910 if (pix_x
< 0) pix_x
= 0;
4911 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4913 if (pix_y
< 0) pix_y
= 0;
4914 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4918 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4919 0, 0, 0, 0, pix_x
, pix_y
);
4923 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
4926 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4932 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4933 0, 0, 0, 0, pix_x
, pix_y
);
4937 x_focus_on_frame (f
)
4940 #if 0 /* This proves to be unpleasant. */
4944 /* I don't think that the ICCCM allows programs to do things like this
4945 without the interaction of the window manager. Whatever you end up
4946 doing with this code, do it to x_unfocus_frame too. */
4947 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4948 RevertToPointerRoot
, CurrentTime
);
4956 /* Look at the remarks in x_focus_on_frame. */
4957 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
4958 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
4959 RevertToPointerRoot
, CurrentTime
);
4963 /* Raise frame F. */
4968 if (f
->async_visible
)
4971 #ifdef USE_X_TOOLKIT
4972 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4973 #else /* not USE_X_TOOLKIT */
4974 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4975 #endif /* not USE_X_TOOLKIT */
4976 XFlush (FRAME_X_DISPLAY (f
));
4981 /* Lower frame F. */
4986 if (f
->async_visible
)
4989 #ifdef USE_X_TOOLKIT
4990 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4991 #else /* not USE_X_TOOLKIT */
4992 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4993 #endif /* not USE_X_TOOLKIT */
4994 XFlush (FRAME_X_DISPLAY (f
));
5000 XTframe_raise_lower (f
, raise
)
5010 /* Change from withdrawn state to mapped state,
5013 x_make_frame_visible (f
)
5021 type
= x_icon_type (f
);
5023 x_bitmap_icon (f
, type
);
5025 if (! FRAME_VISIBLE_P (f
))
5027 #ifndef USE_X_TOOLKIT
5028 if (! FRAME_ICONIFIED_P (f
))
5029 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5032 if (! EQ (Vx_no_window_manager
, Qt
))
5033 x_wm_set_window_state (f
, NormalState
);
5034 #ifdef USE_X_TOOLKIT
5035 /* This was XtPopup, but that did nothing for an iconified frame. */
5036 XtMapWidget (f
->display
.x
->widget
);
5037 #else /* not USE_X_TOOLKIT */
5038 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5039 #endif /* not USE_X_TOOLKIT */
5040 #if 0 /* This seems to bring back scroll bars in the wrong places
5041 if the window configuration has changed. They seem
5042 to come back ok without this. */
5043 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5044 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5048 XFlush (FRAME_X_DISPLAY (f
));
5050 /* Synchronize to ensure Emacs knows the frame is visible
5051 before we do anything else. We do this loop with input not blocked
5052 so that incoming events are handled. */
5055 int count
= input_signal_count
;
5057 /* This must come after we set COUNT. */
5060 XSETFRAME (frame
, f
);
5065 /* Once we have handled input events,
5066 we should have received the MapNotify if one is coming.
5067 So if we have not got it yet, stop looping.
5068 Some window managers make their own decisions
5069 about visibility. */
5070 if (input_signal_count
!= count
)
5072 /* Machines that do polling rather than SIGIO have been observed
5073 to go into a busy-wait here. So we'll fake an alarm signal
5074 to let the handler know that there's something to be read.
5075 We used to raise a real alarm, but it seems that the handler
5076 isn't always enabled here. This is probably a bug. */
5077 if (input_polling_used ())
5079 /* It could be confusing if a real alarm arrives while processing
5080 the fake one. Turn it off and let the handler reset it. */
5082 input_poll_signal ();
5084 /* Once we have handled input events,
5085 we should have received the MapNotify if one is coming.
5086 So if we have not got it yet, stop looping.
5087 Some window managers make their own decisions
5088 about visibility. */
5089 if (input_signal_count
!= count
)
5092 FRAME_SAMPLE_VISIBILITY (f
);
5096 /* Change from mapped state to withdrawn state. */
5098 x_make_frame_invisible (f
)
5104 #ifdef USE_X_TOOLKIT
5105 /* Use the frame's outermost window, not the one we normally draw on. */
5106 window
= XtWindow (f
->display
.x
->widget
);
5107 #else /* not USE_X_TOOLKIT */
5108 window
= FRAME_X_WINDOW (f
);
5109 #endif /* not USE_X_TOOLKIT */
5111 /* Don't keep the highlight on an invisible frame. */
5112 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5113 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5115 #if 0/* This might add unreliability; I don't trust it -- rms. */
5116 if (! f
->async_visible
&& ! f
->async_iconified
)
5122 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5123 that the current position of the window is user-specified, rather than
5124 program-specified, so that when the window is mapped again, it will be
5125 placed at the same location, without forcing the user to position it
5126 by hand again (they have already done that once for this window.) */
5127 x_wm_set_size_hint (f
, 0, 1);
5131 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5132 DefaultScreen (FRAME_X_DISPLAY (f
))))
5134 UNBLOCK_INPUT_RESIGNAL
;
5135 error ("Can't notify window manager of window withdrawal");
5137 #else /* ! defined (HAVE_X11R4) */
5139 /* Tell the window manager what we're going to do. */
5140 if (! EQ (Vx_no_window_manager
, Qt
))
5144 unmap
.xunmap
.type
= UnmapNotify
;
5145 unmap
.xunmap
.window
= window
;
5146 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5147 unmap
.xunmap
.from_configure
= False
;
5148 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5149 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5151 SubstructureRedirectMask
|SubstructureNotifyMask
,
5154 UNBLOCK_INPUT_RESIGNAL
;
5155 error ("Can't notify window manager of withdrawal");
5159 /* Unmap the window ourselves. Cheeky! */
5160 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5161 #endif /* ! defined (HAVE_X11R4) */
5163 /* We can't distinguish this from iconification
5164 just by the event that we get from the server.
5165 So we can't win using the usual strategy of letting
5166 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5167 and synchronize with the server to make sure we agree. */
5169 FRAME_ICONIFIED_P (f
) = 0;
5170 f
->async_visible
= 0;
5171 f
->async_iconified
= 0;
5178 /* Change window state from mapped to iconified. */
5187 /* Don't keep the highlight on an invisible frame. */
5188 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5189 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5191 if (f
->async_iconified
)
5196 type
= x_icon_type (f
);
5198 x_bitmap_icon (f
, type
);
5200 #ifdef USE_X_TOOLKIT
5202 if (! FRAME_VISIBLE_P (f
))
5204 if (! EQ (Vx_no_window_manager
, Qt
))
5205 x_wm_set_window_state (f
, IconicState
);
5206 /* This was XtPopup, but that did nothing for an iconified frame. */
5207 XtMapWidget (f
->display
.x
->widget
);
5212 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5213 XtWindow (f
->display
.x
->widget
),
5214 DefaultScreen (FRAME_X_DISPLAY (f
)));
5218 error ("Can't notify window manager of iconification");
5220 f
->async_iconified
= 1;
5223 XFlush (FRAME_X_DISPLAY (f
));
5225 #else /* not USE_X_TOOLKIT */
5227 /* Make sure the X server knows where the window should be positioned,
5228 in case the user deiconifies with the window manager. */
5229 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5230 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5232 /* Since we don't know which revision of X we're running, we'll use both
5233 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5235 /* X11R4: send a ClientMessage to the window manager using the
5236 WM_CHANGE_STATE type. */
5240 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5241 message
.xclient
.type
= ClientMessage
;
5242 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5243 message
.xclient
.format
= 32;
5244 message
.xclient
.data
.l
[0] = IconicState
;
5246 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5247 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5249 SubstructureRedirectMask
| SubstructureNotifyMask
,
5252 UNBLOCK_INPUT_RESIGNAL
;
5253 error ("Can't notify window manager of iconification");
5257 /* X11R3: set the initial_state field of the window manager hints to
5259 x_wm_set_window_state (f
, IconicState
);
5261 if (!FRAME_VISIBLE_P (f
))
5263 /* If the frame was withdrawn, before, we must map it. */
5264 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5267 f
->async_iconified
= 1;
5269 XFlush (FRAME_X_DISPLAY (f
));
5271 #endif /* not USE_X_TOOLKIT */
5274 /* Destroy the X window of frame F. */
5276 x_destroy_window (f
)
5279 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5283 if (f
->display
.x
->icon_desc
!= 0)
5284 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->icon_desc
);
5285 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->window_desc
);
5286 #ifdef USE_X_TOOLKIT
5287 XtDestroyWidget (f
->display
.x
->widget
);
5288 free_frame_menubar (f
);
5289 #endif /* USE_X_TOOLKIT */
5291 free_frame_faces (f
);
5292 XFlush (FRAME_X_DISPLAY (f
));
5294 xfree (f
->display
.x
);
5296 if (f
== dpyinfo
->x_focus_frame
)
5297 dpyinfo
->x_focus_frame
= 0;
5298 if (f
== dpyinfo
->x_focus_event_frame
)
5299 dpyinfo
->x_focus_event_frame
= 0;
5300 if (f
== dpyinfo
->x_highlight_frame
)
5301 dpyinfo
->x_highlight_frame
= 0;
5303 dpyinfo
->reference_count
--;
5305 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5307 dpyinfo
->mouse_face_beg_row
5308 = dpyinfo
->mouse_face_beg_col
= -1;
5309 dpyinfo
->mouse_face_end_row
5310 = dpyinfo
->mouse_face_end_col
= -1;
5311 dpyinfo
->mouse_face_window
= Qnil
;
5317 /* Setting window manager hints. */
5319 /* Set the normal size hints for the window manager, for frame F.
5320 FLAGS is the flags word to use--or 0 meaning preserve the flags
5321 that the window now has.
5322 If USER_POSITION is nonzero, we set the USPosition
5323 flag (this is useful when FLAGS is 0). */
5325 x_wm_set_size_hint (f
, flags
, user_position
)
5330 XSizeHints size_hints
;
5332 #ifdef USE_X_TOOLKIT
5335 Dimension widget_width
, widget_height
;
5336 Window window
= XtWindow (f
->display
.x
->widget
);
5337 #else /* not USE_X_TOOLKIT */
5338 Window window
= FRAME_X_WINDOW (f
);
5339 #endif /* not USE_X_TOOLKIT */
5341 /* Setting PMaxSize caused various problems. */
5342 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5344 flexlines
= f
->height
;
5346 size_hints
.x
= f
->display
.x
->left_pos
;
5347 size_hints
.y
= f
->display
.x
->top_pos
;
5349 #ifdef USE_X_TOOLKIT
5350 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5351 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5352 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5353 size_hints
.height
= widget_height
;
5354 size_hints
.width
= widget_width
;
5355 #else /* not USE_X_TOOLKIT */
5356 size_hints
.height
= PIXEL_HEIGHT (f
);
5357 size_hints
.width
= PIXEL_WIDTH (f
);
5358 #endif /* not USE_X_TOOLKIT */
5360 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5361 size_hints
.height_inc
= f
->display
.x
->line_height
;
5362 size_hints
.max_width
5363 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5364 size_hints
.max_height
5365 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5368 int base_width
, base_height
;
5369 int min_rows
= 0, min_cols
= 0;
5371 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5372 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5374 check_frame_size (f
, &min_rows
, &min_cols
);
5376 /* The window manager uses the base width hints to calculate the
5377 current number of rows and columns in the frame while
5378 resizing; min_width and min_height aren't useful for this
5379 purpose, since they might not give the dimensions for a
5380 zero-row, zero-column frame.
5382 We use the base_width and base_height members if we have
5383 them; otherwise, we set the min_width and min_height members
5384 to the size for a zero x zero frame. */
5387 size_hints
.flags
|= PBaseSize
;
5388 size_hints
.base_width
= base_width
;
5389 size_hints
.base_height
= base_height
;
5390 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5391 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5393 size_hints
.min_width
= base_width
;
5394 size_hints
.min_height
= base_height
;
5399 size_hints
.flags
|= flags
;
5402 XSizeHints hints
; /* Sometimes I hate X Windows... */
5403 long supplied_return
;
5407 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5410 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5415 if (hints
.flags
& PSize
)
5416 size_hints
.flags
|= PSize
;
5417 if (hints
.flags
& PPosition
)
5418 size_hints
.flags
|= PPosition
;
5419 if (hints
.flags
& USPosition
)
5420 size_hints
.flags
|= USPosition
;
5421 if (hints
.flags
& USSize
)
5422 size_hints
.flags
|= USSize
;
5426 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5427 size_hints
.flags
|= PWinGravity
;
5431 size_hints
.flags
&= ~ PPosition
;
5432 size_hints
.flags
|= USPosition
;
5434 #endif /* PWinGravity */
5437 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5439 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5443 /* Used for IconicState or NormalState */
5444 x_wm_set_window_state (f
, state
)
5448 #ifdef USE_X_TOOLKIT
5451 XtSetArg (al
[0], XtNinitialState
, state
);
5452 XtSetValues (f
->display
.x
->widget
, al
, 1);
5453 #else /* not USE_X_TOOLKIT */
5454 Window window
= FRAME_X_WINDOW (f
);
5456 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5457 f
->display
.x
->wm_hints
.initial_state
= state
;
5459 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5460 #endif /* not USE_X_TOOLKIT */
5463 x_wm_set_icon_pixmap (f
, pixmap_id
)
5467 #ifdef USE_X_TOOLKIT
5468 Window window
= XtWindow (f
->display
.x
->widget
);
5470 Window window
= FRAME_X_WINDOW (f
);
5475 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5476 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5477 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5481 f
->display
.x
->wm_hints
.icon_pixmap
= None
;
5482 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5485 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5488 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5492 #ifdef USE_X_TOOLKIT
5493 Window window
= XtWindow (f
->display
.x
->widget
);
5495 Window window
= FRAME_X_WINDOW (f
);
5498 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5499 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5500 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5502 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5506 /* Initialization. */
5508 #ifdef USE_X_TOOLKIT
5509 static XrmOptionDescRec emacs_options
[] = {
5510 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5511 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5513 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5514 XrmoptionSepArg
, NULL
},
5515 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5517 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5518 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5519 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5520 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5521 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5522 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5523 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5525 #endif /* USE_X_TOOLKIT */
5527 static int x_initialized
;
5530 /* Test whether two display-name strings agree up to the dot that separates
5531 the screen number from the server number. */
5533 same_x_server (name1
, name2
)
5534 char *name1
, *name2
;
5537 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5541 if (seen_colon
&& *name1
== '.')
5545 && (*name1
== '.' || *name1
== '\0')
5546 && (*name2
== '.' || *name2
== '\0'));
5550 struct x_display_info
*
5551 x_term_init (display_name
, xrm_option
, resource_name
)
5552 Lisp_Object display_name
;
5554 char *resource_name
;
5560 struct x_display_info
*dpyinfo
;
5569 #ifdef USE_X_TOOLKIT
5570 /* weiner@footloose.sps.mot.com reports that this causes
5572 X protocol error: BadAtom (invalid Atom parameter)
5573 on protocol request 18skiloaf.
5574 So let's not use it until R6. */
5576 XtSetLanguageProc (NULL
, NULL
, NULL
);
5587 argv
[argc
++] = "-xrm";
5588 argv
[argc
++] = xrm_option
;
5590 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5591 resource_name
, EMACS_CLASS
,
5592 emacs_options
, XtNumber (emacs_options
),
5596 #else /* not USE_X_TOOLKIT */
5598 XSetLocaleModifiers ("");
5600 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5601 #endif /* not USE_X_TOOLKIT */
5603 /* Detect failure. */
5607 /* We have definitely succeeded. Record the new connection. */
5609 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5613 struct x_display_info
*share
;
5616 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5617 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5618 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5619 XSTRING (display_name
)->data
))
5622 dpyinfo
->kboard
= share
->kboard
;
5625 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5626 init_kboard (dpyinfo
->kboard
);
5627 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5628 all_kboards
= dpyinfo
->kboard
;
5629 /* Don't let the initial kboard remain current longer than necessary.
5630 That would cause problems if a file loaded on startup tries to
5631 prompt in the minibuffer. */
5632 if (current_kboard
== initial_kboard
)
5633 current_kboard
= dpyinfo
->kboard
;
5635 dpyinfo
->kboard
->reference_count
++;
5639 /* Put this display on the chain. */
5640 dpyinfo
->next
= x_display_list
;
5641 x_display_list
= dpyinfo
;
5643 /* Put it on x_display_name_list as well, to keep them parallel. */
5644 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5645 x_display_name_list
);
5646 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5648 dpyinfo
->display
= dpy
;
5651 XSetAfterFunction (x_current_display
, x_trace_wire
);
5655 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5656 + XSTRING (Vsystem_name
)->size
5658 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5659 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5661 /* Figure out which modifier bits mean what. */
5662 x_find_modifier_meanings (dpyinfo
);
5664 /* Get the scroll bar cursor. */
5665 dpyinfo
->vertical_scroll_bar_cursor
5666 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5668 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5669 resource_name
, EMACS_CLASS
);
5670 #ifdef HAVE_XRMSETDATABASE
5671 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5673 dpyinfo
->display
->db
= xrdb
;
5675 /* Put the rdb where we can find it in a way that works on
5677 dpyinfo
->xrdb
= xrdb
;
5679 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5680 DefaultScreen (dpyinfo
->display
));
5681 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5682 &dpyinfo
->n_planes
);
5683 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
5684 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
5685 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
5686 dpyinfo
->grabbed
= 0;
5687 dpyinfo
->reference_count
= 0;
5688 dpyinfo
->icon_bitmap_id
= -1;
5689 dpyinfo
->n_fonts
= 0;
5690 dpyinfo
->font_table_size
= 0;
5691 dpyinfo
->bitmaps
= 0;
5692 dpyinfo
->bitmaps_size
= 0;
5693 dpyinfo
->bitmaps_last
= 0;
5694 dpyinfo
->scratch_cursor_gc
= 0;
5695 dpyinfo
->mouse_face_mouse_frame
= 0;
5696 dpyinfo
->mouse_face_deferred_gc
= 0;
5697 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5698 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5699 dpyinfo
->mouse_face_face_id
= 0;
5700 dpyinfo
->mouse_face_window
= Qnil
;
5701 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
5702 dpyinfo
->mouse_face_defer
= 0;
5703 dpyinfo
->x_focus_frame
= 0;
5704 dpyinfo
->x_focus_event_frame
= 0;
5705 dpyinfo
->x_highlight_frame
= 0;
5707 dpyinfo
->Xatom_wm_protocols
5708 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
5709 dpyinfo
->Xatom_wm_take_focus
5710 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
5711 dpyinfo
->Xatom_wm_save_yourself
5712 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
5713 dpyinfo
->Xatom_wm_delete_window
5714 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
5715 dpyinfo
->Xatom_wm_change_state
5716 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
5717 dpyinfo
->Xatom_wm_configure_denied
5718 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
5719 dpyinfo
->Xatom_wm_window_moved
5720 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
5721 dpyinfo
->Xatom_editres
5722 = XInternAtom (dpyinfo
->display
, "Editres", False
);
5723 dpyinfo
->Xatom_CLIPBOARD
5724 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
5725 dpyinfo
->Xatom_TIMESTAMP
5726 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
5728 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
5729 dpyinfo
->Xatom_DELETE
5730 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
5731 dpyinfo
->Xatom_MULTIPLE
5732 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
5734 = XInternAtom (dpyinfo
->display
, "INCR", False
);
5735 dpyinfo
->Xatom_EMACS_TMP
5736 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
5737 dpyinfo
->Xatom_TARGETS
5738 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
5740 = XInternAtom (dpyinfo
->display
, "NULL", False
);
5741 dpyinfo
->Xatom_ATOM_PAIR
5742 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
5744 dpyinfo
->cut_buffers_initialized
= 0;
5746 connection
= ConnectionNumber (dpyinfo
->display
);
5747 dpyinfo
->connection
= connection
;
5750 /* This is only needed for distinguishing keyboard and process input. */
5751 if (connection
!= 0)
5752 add_keyboard_wait_descriptor (connection
);
5755 #ifndef F_SETOWN_BUG
5757 #ifdef F_SETOWN_SOCK_NEG
5758 /* stdin is a socket here */
5759 fcntl (connection
, F_SETOWN
, -getpid ());
5760 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5761 fcntl (connection
, F_SETOWN
, getpid ());
5762 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5763 #endif /* ! defined (F_SETOWN) */
5764 #endif /* F_SETOWN_BUG */
5767 init_sigio (connection
);
5768 #endif /* ! defined (SIGIO) */
5773 /* Get rid of display DPYINFO, assuming all frames are already gone,
5774 and without sending any more commands to the X server. */
5777 x_delete_display (dpyinfo
)
5778 struct x_display_info
*dpyinfo
;
5780 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
5782 /* Discard this display from x_display_name_list and x_display_list.
5783 We can't use Fdelq because that can quit. */
5784 if (! NILP (x_display_name_list
)
5785 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
5786 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
5791 tail
= x_display_name_list
;
5792 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
5794 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
5795 dpyinfo
->name_list_element
))
5797 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
5800 tail
= XCONS (tail
)->cdr
;
5804 if (x_display_list
== dpyinfo
)
5805 x_display_list
= dpyinfo
->next
;
5808 struct x_display_info
*tail
;
5810 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
5811 if (tail
->next
== dpyinfo
)
5812 tail
->next
= tail
->next
->next
;
5815 #ifndef USE_X_TOOLKIT
5816 /* I'm told Xt does this itself. */
5817 XrmDestroyDatabase (dpyinfo
->xrdb
);
5820 if (--dpyinfo
->kboard
->reference_count
== 0)
5821 delete_kboard (dpyinfo
->kboard
);
5823 xfree (dpyinfo
->font_table
);
5824 xfree (dpyinfo
->x_id_name
);
5828 /* Set up use of X before we make the first connection. */
5832 clear_frame_hook
= XTclear_frame
;
5833 clear_end_of_line_hook
= XTclear_end_of_line
;
5834 ins_del_lines_hook
= XTins_del_lines
;
5835 change_line_highlight_hook
= XTchange_line_highlight
;
5836 insert_glyphs_hook
= XTinsert_glyphs
;
5837 write_glyphs_hook
= XTwrite_glyphs
;
5838 delete_glyphs_hook
= XTdelete_glyphs
;
5839 ring_bell_hook
= XTring_bell
;
5840 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5841 set_terminal_modes_hook
= XTset_terminal_modes
;
5842 update_begin_hook
= XTupdate_begin
;
5843 update_end_hook
= XTupdate_end
;
5844 set_terminal_window_hook
= XTset_terminal_window
;
5845 read_socket_hook
= XTread_socket
;
5846 frame_up_to_date_hook
= XTframe_up_to_date
;
5847 cursor_to_hook
= XTcursor_to
;
5848 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5849 mouse_position_hook
= XTmouse_position
;
5850 frame_rehighlight_hook
= XTframe_rehighlight
;
5851 frame_raise_lower_hook
= XTframe_raise_lower
;
5852 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5853 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5854 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5855 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5857 scroll_region_ok
= 1; /* we'll scroll partial frames */
5858 char_ins_del_ok
= 0; /* just as fast to write the line */
5859 line_ins_del_ok
= 1; /* we'll just blt 'em */
5860 fast_clear_end_of_line
= 1; /* X does this well */
5861 memory_below_frame
= 0; /* we don't remember what scrolls
5867 /* Try to use interrupt input; if we can't, then start polling. */
5868 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5870 #ifdef USE_X_TOOLKIT
5871 XtToolkitInitialize ();
5872 Xt_app_con
= XtCreateApplicationContext ();
5875 /* Note that there is no real way portable across R3/R4 to get the
5876 original error handler. */
5877 XSetErrorHandler (x_error_quitter
);
5878 XSetIOErrorHandler (x_io_error_quitter
);
5880 /* Disable Window Change signals; they are handled by X events. */
5882 signal (SIGWINCH
, SIG_DFL
);
5883 #endif /* ! defined (SIGWINCH) */
5885 signal (SIGPIPE
, x_connection_signal
);
5891 staticpro (&x_display_name_list
);
5892 x_display_name_list
= Qnil
;
5894 staticpro (&last_mouse_scroll_bar
);
5895 last_mouse_scroll_bar
= Qnil
;
5897 #endif /* ! defined (HAVE_X_WINDOWS) */