1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 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 #include <sys/param.h>
69 #include "dispextern.h"
70 #include "termhooks.h"
85 extern XtAppContext Xt_app_con
;
86 extern Widget Xt_app_shell
;
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"
103 #define XMapWindow XMapRaised /* Raise them when mapping. */
104 #else /* ! defined (HAVE_X11) */
105 #include <X/Xkeyboard.h>
106 /*#include <X/Xproto.h> */
107 #endif /* ! defined (HAVE_X11) */
110 /* We could get this from param.h, but better not to depend on finding that.
111 And better not to risk that it might define other symbols used in this
114 #define MAXDESC FD_SETSIZE
118 #define SELECT_TYPE fd_set
119 #else /* no FD_SET */
121 #define SELECT_TYPE int
123 /* Define the macros to access a single-int bitmap of descriptors. */
124 #define FD_SET(n, p) (*(p) |= (1 << (n)))
125 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
126 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
127 #define FD_ZERO(p) (*(p) = 0)
128 #endif /* no FD_SET */
130 /* For sending Meta-characters. Do we need this? */
133 #define min(a,b) ((a)<(b) ? (a) : (b))
134 #define max(a,b) ((a)>(b) ? (a) : (b))
136 /* Nonzero means we must reprint all windows
137 because 1) we received an ExposeWindow event
138 or 2) we received too many ExposeRegion events to record.
140 This is never needed under X11. */
141 static int expose_all_windows
;
143 /* Nonzero means we must reprint all icon windows. */
145 static int expose_all_icons
;
148 /* ExposeRegion events, when received, are copied into this queue
149 for later processing. */
151 static struct event_queue x_expose_queue
;
153 /* ButtonPress and ButtonReleased events, when received,
154 are copied into this queue for later processing. */
156 struct event_queue x_mouse_queue
;
157 #endif /* HAVE_X11 */
159 #if defined (SIGIO) && defined (FIONREAD)
160 int BLOCK_INPUT_mask
;
161 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
163 /* The id of a bitmap used for icon windows.
164 One such map is shared by all Emacs icon windows.
165 This is zero if we have not yet had a need to create the bitmap. */
167 static Bitmap icon_bitmap
;
169 /* Font used for text icons. */
171 static FONT_TYPE
*icon_font_info
;
173 /* Stuff for dealing with the main icon title. */
175 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
178 /* Initial values of argv and argc. */
179 extern char **initial_argv
;
180 extern int initial_argc
;
182 /* This is the X connection that we are using. */
184 Display
*x_current_display
;
186 /* The cursor to use for vertical scroll bars on x_current_display. */
187 static Cursor x_vertical_scroll_bar_cursor
;
189 /* Frame being updated by update_frame. This is declared in term.c.
190 This is set by update_begin and looked at by all the
191 XT functions. It is zero while not inside an update.
192 In that case, the XT functions assume that `selected_frame'
193 is the frame to apply to. */
194 extern struct frame
*updating_frame
;
196 /* The frame (if any) which has the X window that has keyboard focus.
197 Zero if none. This is examined by Ffocus_frame in frame.c. Note
198 that a mere EnterNotify event can set this; if you need to know the
199 last frame specified in a FocusIn or FocusOut event, use
200 x_focus_event_frame. */
201 struct frame
*x_focus_frame
;
203 /* This is a frame waiting to be autoraised, within XTread_socket. */
204 struct frame
*pending_autoraise_frame
;
206 /* The last frame mentioned in a FocusIn or FocusOut event. This is
207 separate from x_focus_frame, because whether or not LeaveNotify
208 events cause us to lose focus depends on whether or not we have
209 received a FocusIn event for it. */
210 struct frame
*x_focus_event_frame
;
212 /* The frame which currently has the visual highlight, and should get
213 keyboard input (other sorts of input have the frame encoded in the
214 event). It points to the X focus frame's selected window's
215 frame. It differs from x_focus_frame when we're using a global
217 static struct frame
*x_highlight_frame
;
219 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
220 mouse is moved to inside of frame when frame is de-iconified. */
222 static int warp_mouse_on_deiconify
;
224 /* During an update, maximum vpos for ins/del line operations to affect. */
226 static int flexlines
;
228 /* During an update, nonzero if chars output now should be highlighted. */
230 static int highlight
;
232 /* Nominal cursor position -- where to draw output.
233 During an update, these are different from the cursor-box position. */
238 /* Reusable Graphics Context for drawing a cursor in a non-default face. */
239 static GC scratch_cursor_gc
;
243 In order to avoid asking for motion events and then throwing most
244 of them away or busy-polling the server for mouse positions, we ask
245 the server for pointer motion hints. This means that we get only
246 one event per group of mouse movements. "Groups" are delimited by
247 other kinds of events (focus changes and button clicks, for
248 example), or by XQueryPointer calls; when one of these happens, we
249 get another MotionNotify event the next time the mouse moves. This
250 is at least as efficient as getting motion events when mouse
251 tracking is on, and I suspect only negligibly worse when tracking
254 The silly O'Reilly & Associates Nutshell guides barely document
255 pointer motion hints at all (I think you have to infer how they
256 work from an example), and the description of XQueryPointer doesn't
257 mention that calling it causes you to get another motion hint from
258 the server, which is very important. */
260 /* Where the mouse was last time we reported a mouse event. */
261 static FRAME_PTR last_mouse_frame
;
262 static XRectangle last_mouse_glyph
;
264 /* The scroll bar in which the last X motion event occurred.
266 If the last X motion event occurred in a scroll bar, we set this
267 so XTmouse_position can know whether to report a scroll bar motion or
270 If the last X motion event didn't occur in a scroll bar, we set this
271 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
272 static Lisp_Object last_mouse_scroll_bar
;
274 /* Record which buttons are currently pressed. */
275 unsigned int x_mouse_grabbed
;
277 /* This is a hack. We would really prefer that XTmouse_position would
278 return the time associated with the position it returns, but there
279 doesn't seem to be any way to wrest the timestamp from the server
280 along with the position query. So, we just keep track of the time
281 of the last movement we received, and return that in hopes that
282 it's somewhat accurate. */
283 static Time last_mouse_movement_time
;
285 /* These variables describe the range of text currently shown
286 in its mouse-face, together with the window they apply to.
287 As long as the mouse stays within this range, we need not
288 redraw anything on its account. */
289 static int mouse_face_beg_row
, mouse_face_beg_col
;
290 static int mouse_face_end_row
, mouse_face_end_col
;
291 static int mouse_face_past_end
;
292 static Lisp_Object mouse_face_window
;
293 static int mouse_face_face_id
;
295 /* 1 if a mouse motion event came and we didn't handle it right away because
296 gc was in progress. */
297 static int mouse_face_deferred_gc
;
299 /* FRAME and X, Y position of mouse when last checked for
300 highlighting. X and Y can be negative or out of range for the frame. */
301 static FRAME_PTR mouse_face_mouse_frame
;
302 static int mouse_face_mouse_x
, mouse_face_mouse_y
;
304 /* Nonzero means defer mouse-motion highlighting. */
305 static int mouse_face_defer
;
308 /* `t' if a mouse button is depressed. */
310 extern Lisp_Object Vmouse_depressed
;
312 /* Tells if a window manager is present or not. */
314 extern Lisp_Object Vx_no_window_manager
;
316 /* Timestamp that we requested selection data was made. */
317 extern Time requestor_time
;
319 /* ID of the window requesting selection data. */
320 extern Window requestor_window
;
322 /* Nonzero enables some debugging for the X interface code. */
325 extern Lisp_Object Qface
, Qmouse_face
;
327 #else /* ! defined (HAVE_X11) */
329 /* Bit patterns for the mouse cursor. */
331 short MouseCursor
[] = {
332 0x0000, 0x0008, 0x0018, 0x0038,
333 0x0078, 0x00f8, 0x01f8, 0x03f8,
334 0x07f8, 0x00f8, 0x00d8, 0x0188,
335 0x0180, 0x0300, 0x0300, 0x0000};
337 short MouseMask
[] = {
338 0x000c, 0x001c, 0x003c, 0x007c,
339 0x00fc, 0x01fc, 0x03fc, 0x07fc,
340 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
341 0x03cc, 0x0780, 0x0780, 0x0300};
343 static short grey_bits
[] = {
344 0x0005, 0x000a, 0x0005, 0x000a};
346 static Pixmap GreyPixmap
= 0;
347 #endif /* ! defined (HAVE_X11) */
349 static int x_noop_count
;
352 /* From time to time we get info on an Emacs window, here. */
354 static WINDOWINFO_TYPE windowinfo
;
358 /* A mask of extra modifier bits to put into every keyboard char. */
359 extern int extra_keyboard_modifiers
;
361 extern Display
*XOpenDisplay ();
362 extern Window
XCreateWindow ();
364 extern Cursor
XCreateCursor ();
365 extern FONT_TYPE
*XOpenFont ();
367 static void flashback ();
368 static void redraw_previous_char ();
369 static void redraw_following_char ();
370 static unsigned int x_x_to_emacs_modifiers ();
372 static int fast_find_position ();
373 static void note_mouse_highlight ();
374 static void clear_mouse_face ();
375 static void show_mouse_face ();
378 static void dumpqueue ();
379 #endif /* HAVE_X11 */
382 static int XTcursor_to ();
383 static int XTclear_end_of_line ();
386 /* Starting and ending updates.
388 These hooks are called by update_frame at the beginning and end
389 of a frame update. We record in `updating_frame' the identity
390 of the frame being updated, so that the XT... functions do not
391 need to take a frame as argument. Most of the XT... functions
392 should never be called except during an update, the only exceptions
393 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
395 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
406 flexlines
= f
->height
;
411 if (f
== mouse_face_mouse_frame
)
413 /* Don't do highlighting for mouse motion during the update. */
414 mouse_face_defer
= 1;
415 if (!NILP (mouse_face_window
))
417 int firstline
, lastline
, i
;
418 struct window
*w
= XWINDOW (mouse_face_window
);
420 /* Find the first, and the last+1, lines affected by redisplay. */
421 for (firstline
= 0; firstline
< f
->height
; firstline
++)
422 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
425 lastline
= f
->height
;
426 for (i
= f
->height
- 1; i
>= 0; i
--)
428 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
434 /* Can we tell that this update does not affect the window
435 where the mouse highlight is? If so, no need to turn off. */
436 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
437 || lastline
< XFASTINT (w
->top
)))
438 /* Otherwise turn off the mouse highlight now. */
444 #endif /* HAVE_X11 */
449 static void x_do_pending_expose ();
461 x_do_pending_expose ();
462 #endif /* HAVE_X11 */
464 x_display_cursor (f
, 1);
466 if (f
== mouse_face_mouse_frame
)
467 mouse_face_defer
= 0;
469 /* This fails in the case of having updated only the echo area
470 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
471 has no relation to the current contents, and its charstarts
472 have no relation to the contents of the window-buffer.
473 I don't know a clean way to check
474 for that case. window_end_valid isn't set up yet. */
475 if (f
== mouse_face_mouse_frame
)
476 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
483 /* This is called after a redisplay on frame F. */
486 XTframe_up_to_date (f
)
489 if (mouse_face_deferred_gc
|| f
== mouse_face_mouse_frame
)
491 note_mouse_highlight (mouse_face_mouse_frame
,
492 mouse_face_mouse_x
, mouse_face_mouse_y
);
493 mouse_face_deferred_gc
= 0;
497 /* External interface to control of standout mode.
498 Call this when about to modify line at position VPOS
499 and not change whether it is highlighted. */
501 XTreassert_line_highlight (new, vpos
)
507 /* Call this when about to modify line at position VPOS
508 and change whether it is highlighted. */
511 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
512 int new_highlight
, vpos
, first_unused_hpos
;
514 highlight
= new_highlight
;
515 XTcursor_to (vpos
, 0);
516 XTclear_end_of_line (updating_frame
->width
);
519 /* This is used when starting Emacs and when restarting after suspend.
520 When starting Emacs, no X window is mapped. And nothing must be done
521 to Emacs's own window if it is suspended (though that rarely happens). */
524 XTset_terminal_modes ()
528 /* This is called when exiting or suspending Emacs.
529 Exiting will make the X-windows go away, and suspending
530 requires no action. */
533 XTreset_terminal_modes ()
535 /* XTclear_frame (); */
538 /* Set the nominal cursor position of the frame.
539 This is where display update commands will take effect.
540 This does not affect the place where the cursor-box is displayed. */
543 XTcursor_to (row
, col
)
544 register int row
, col
;
552 if (updating_frame
== 0)
555 x_display_cursor (selected_frame
, 1);
561 /* Display a sequence of N glyphs found at GP.
562 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
563 HL is 1 if this text is highlighted, 2 if the cursor is on it,
564 3 if should appear in its mouse-face.
565 JUST_FOREGROUND if 1 means draw only the foreground;
566 don't alter the background.
568 FONT is the default font to use (for glyphs whose font-code is 0).
570 Since the display generation code is responsible for calling
571 compute_char_face and compute_glyph_face on everything it puts in
572 the display structure, we can assume that the face code on each
573 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
574 to which we can actually apply intern_face.
575 Call this function with input blocked. */
578 /* This is the multi-face code. */
581 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
584 register GLYPH
*gp
; /* Points to first GLYPH. */
585 register int n
; /* Number of glyphs to display. */
589 /* Holds characters to be displayed. */
590 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
591 register char *cp
; /* Steps through buf[]. */
592 register int tlen
= GLYPH_TABLE_LENGTH
;
593 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
594 Window window
= FRAME_X_WINDOW (f
);
595 int orig_left
= left
;
599 /* Get the face-code of the next GLYPH. */
603 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
604 cf
= FAST_GLYPH_FACE (g
);
606 /* Find the run of consecutive glyphs with the same face-code.
607 Extract their character codes into BUF. */
612 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
613 if (FAST_GLYPH_FACE (g
) != cf
)
616 *cp
++ = FAST_GLYPH_CHAR (g
);
621 /* LEN gets the length of the run. */
624 /* Now output this run of chars, with the font and pixel values
625 determined by the face code CF. */
627 struct face
*face
= FRAME_DEFAULT_FACE (f
);
628 FONT_TYPE
*font
= FACE_FONT (face
);
629 GC gc
= FACE_GC (face
);
631 /* HL = 3 means use a mouse face previously chosen. */
633 cf
= mouse_face_face_id
;
635 /* First look at the face of the text itself. */
638 /* It's possible for the display table to specify
639 a face code that is out of range. Use 0 in that case. */
640 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
641 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
645 face
= FRAME_MODE_LINE_FACE (f
);
647 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
648 font
= FACE_FONT (face
);
652 /* Then comes the distinction between modeline and normal text. */
657 face
= FRAME_MODE_LINE_FACE (f
);
658 font
= FACE_FONT (face
);
662 #define FACE_DEFAULT (~0)
664 /* Now override that if the cursor's on this character. */
668 || (int) face
->font
== FACE_DEFAULT
669 || face
->font
== f
->display
.x
->font
)
670 && face
->background
== f
->display
.x
->background_pixel
671 && face
->foreground
== f
->display
.x
->foreground_pixel
)
673 gc
= f
->display
.x
->cursor_gc
;
675 /* Cursor on non-default face: must merge. */
681 xgcv
.background
= f
->display
.x
->cursor_pixel
;
682 xgcv
.foreground
= face
->background
;
683 /* If the glyph would be invisible,
684 try a different foreground. */
685 if (xgcv
.foreground
== xgcv
.background
)
686 xgcv
.foreground
= face
->foreground
;
687 if (xgcv
.foreground
== xgcv
.background
)
688 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
689 if (xgcv
.foreground
== xgcv
.background
)
690 xgcv
.foreground
= face
->foreground
;
691 /* Make sure the cursor is distinct from text in this face. */
692 if (xgcv
.background
== face
->background
693 && xgcv
.foreground
== face
->foreground
)
695 xgcv
.background
= face
->foreground
;
696 xgcv
.foreground
= face
->background
;
698 xgcv
.font
= face
->font
->fid
;
699 xgcv
.graphics_exposures
= 0;
700 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
701 if (scratch_cursor_gc
)
702 XChangeGC (x_current_display
, scratch_cursor_gc
, mask
, &xgcv
);
705 XCreateGC (x_current_display
, window
, mask
, &xgcv
);
706 gc
= scratch_cursor_gc
;
708 /* If this code is restored, it must also reset to the default stipple
710 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
711 XSetStipple (x_current_display
, gc
, face
->stipple
);
716 if ((int) font
== FACE_DEFAULT
)
717 font
= f
->display
.x
->font
;
720 XDrawString (x_current_display
, window
, gc
,
721 left
, top
+ FONT_BASE (font
), buf
, len
);
724 XDrawImageString (x_current_display
, window
, gc
,
725 left
, top
+ FONT_BASE (font
), buf
, len
);
726 /* Clear the rest of the line's height. */
727 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
728 XClearArea (x_current_display
, window
, left
,
729 top
+ FONT_HEIGHT (font
),
730 FONT_WIDTH (font
) * len
,
731 /* This is how many pixels of height
733 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
737 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
738 which often is not up to date yet. */
739 if (!just_foreground
)
741 if (left
== orig_left
)
742 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
743 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
745 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
746 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
750 /* We should probably check for XA_UNDERLINE_POSITION and
751 XA_UNDERLINE_THICKNESS properties on the font, but let's
752 just get the thing working, and come back to that. */
754 int underline_position
= 1;
756 if (font
->descent
<= underline_position
)
757 underline_position
= font
->descent
- 1;
760 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
764 + underline_position
),
765 len
* FONT_WIDTH (font
), 1);
768 left
+= len
* FONT_WIDTH (font
);
775 /* This is the old single-face code. */
778 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
781 register GLYPH
*gp
; /* Points to first GLYPH. */
782 register int n
; /* Number of glyphs to display. */
787 Window window
= FRAME_X_WINDOW (f
);
788 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
789 : (hl
? f
->display
.x
->reverse_gc
790 : f
->display
.x
->normal_gc
));
792 if (sizeof (GLYPH
) == sizeof (XChar2b
))
793 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
794 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
795 else if (sizeof (GLYPH
) == sizeof (unsigned char))
796 XDrawImageString (x_current_display
, window
, drawing_gc
,
797 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
799 /* What size of glyph ARE you using? And does X have a function to
805 /* Output some text at the nominal frame cursor position.
806 Advance the cursor over the text.
807 Output LEN glyphs at START.
809 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
810 controls the pixel values used for foreground and background. */
813 XTwrite_glyphs (start
, len
)
814 register GLYPH
*start
;
817 register int temp_length
;
827 /* If not within an update,
828 output at the frame's visible cursor. */
829 curs_x
= f
->cursor_x
;
830 curs_y
= f
->cursor_y
;
834 CHAR_TO_PIXEL_COL (f
, curs_x
),
835 CHAR_TO_PIXEL_ROW (f
, curs_y
),
836 start
, len
, highlight
, 0);
838 /* If we drew on top of the cursor, note that it is turned off. */
839 if (curs_y
== f
->phys_cursor_y
840 && curs_x
<= f
->phys_cursor_x
841 && curs_x
+ len
> f
->phys_cursor_x
)
842 f
->phys_cursor_x
= -1;
844 if (updating_frame
== 0)
847 x_display_cursor (f
, 1);
856 /* Clear to the end of the line.
857 Erase the current text line from the nominal cursor position (inclusive)
858 to column FIRST_UNUSED (exclusive). The idea is that everything
859 from FIRST_UNUSED onward is already erased. */
862 XTclear_end_of_line (first_unused
)
863 register int first_unused
;
865 struct frame
*f
= updating_frame
;
871 if (curs_y
< 0 || curs_y
>= f
->height
)
873 if (first_unused
<= 0)
876 if (first_unused
>= f
->width
)
877 first_unused
= f
->width
;
881 /* Notice if the cursor will be cleared by this operation. */
882 if (curs_y
== f
->phys_cursor_y
883 && curs_x
<= f
->phys_cursor_x
884 && f
->phys_cursor_x
< first_unused
)
885 f
->phys_cursor_x
= -1;
888 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
889 CHAR_TO_PIXEL_COL (f
, curs_x
),
890 CHAR_TO_PIXEL_ROW (f
, curs_y
),
891 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
892 f
->display
.x
->line_height
, False
);
894 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
896 #else /* ! defined (HAVE_X11) */
897 XPixSet (FRAME_X_WINDOW (f
),
898 CHAR_TO_PIXEL_COL (f
, curs_x
),
899 CHAR_TO_PIXEL_ROW (f
, curs_y
),
900 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
901 f
->display
.x
->line_height
,
902 f
->display
.x
->background_pixel
);
903 #endif /* ! defined (HAVE_X11) */
912 struct frame
*f
= updating_frame
;
917 f
->phys_cursor_x
= -1; /* Cursor not visible. */
918 curs_x
= 0; /* Nominal cursor position is top left. */
923 XClear (FRAME_X_WINDOW (f
));
925 /* We have to clear the scroll bars, too. If we have changed
926 colors or something like that, then they should be notified. */
927 x_scroll_bar_clear (f
);
931 #endif /* HAVE_X11 */
938 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
939 always contain the right glyphs to use.
941 It also needs to be changed to look at the details of the font and
942 see whether there is really overlap, and do nothing when there is
943 not. This can use font_char_overlap_left and font_char_overlap_right,
944 but just how to use them is not clear. */
946 /* Erase the character (if any) at the position just before X, Y in frame F,
947 then redraw it and the character before it.
948 This is necessary when we erase starting at X,
949 in case the character after X overlaps into the one before X.
950 Call this function with input blocked. */
953 redraw_previous_char (f
, x
, y
, highlight_flag
)
958 /* Erase the character before the new ones, in case
959 what was here before overlaps it.
960 Reoutput that character, and the previous character
961 (in case the previous character overlaps it). */
967 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
968 CHAR_TO_PIXEL_COL (f
, x
- 1),
969 CHAR_TO_PIXEL_ROW (f
, y
),
970 FONT_WIDTH (f
->display
.x
->font
),
971 f
->display
.x
->line_height
, False
);
973 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
974 CHAR_TO_PIXEL_ROW (f
, y
),
975 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
976 x
- start_x
, highlight_flag
, 1);
980 /* Erase the character (if any) at the position X, Y in frame F,
981 then redraw it and the character after it.
982 This is necessary when we erase endng at X,
983 in case the character after X overlaps into the one before X.
984 Call this function with input blocked. */
987 redraw_following_char (f
, x
, y
, highlight_flag
)
992 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
993 /* Erase the character after the new ones, in case
994 what was here before overlaps it.
995 Reoutput that character, and the following character
996 (in case the following character overlaps it). */
998 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1003 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1004 CHAR_TO_PIXEL_COL (f
, x
),
1005 CHAR_TO_PIXEL_ROW (f
, y
),
1006 FONT_WIDTH (f
->display
.x
->font
),
1007 f
->display
.x
->line_height
, False
);
1009 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1010 CHAR_TO_PIXEL_ROW (f
, y
),
1011 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1012 end_x
- x
, highlight_flag
, 1);
1017 #if 0 /* Not in use yet */
1019 /* Return 1 if character C in font F extends past its left edge. */
1022 font_char_overlap_left (font
, c
)
1028 /* Find the bounding-box info for C. */
1029 if (font
->per_char
== 0)
1030 s
= &font
->max_bounds
;
1033 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1036 /* Decode char into row number (byte 1) and code within row (byte 2). */
1039 if (!(within
>= font
->min_char_or_byte2
1040 && within
<= font
->max_char_or_byte2
1041 && row
>= font
->min_byte1
1042 && row
<= font
->max_byte1
))
1044 /* If char is out of range, try the font's default char instead. */
1045 c
= font
->default_char
;
1046 row
= c
>> (INTBITS
- 8);
1049 if (!(within
>= font
->min_char_or_byte2
1050 && within
<= font
->max_char_or_byte2
1051 && row
>= font
->min_byte1
1052 && row
<= font
->max_byte1
))
1053 /* Still out of range means this char does not overlap. */
1056 /* We found the info for this char. */
1057 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1061 return (s
&& s
->lbearing
< 0);
1064 /* Return 1 if character C in font F extends past its right edge. */
1067 font_char_overlap_right (font
, c
)
1073 /* Find the bounding-box info for C. */
1074 if (font
->per_char
== 0)
1075 s
= &font
->max_bounds
;
1078 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1081 /* Decode char into row number (byte 1) and code within row (byte 2). */
1084 if (!(within
>= font
->min_char_or_byte2
1085 && within
<= font
->max_char_or_byte2
1086 && row
>= font
->min_byte1
1087 && row
<= font
->max_byte1
))
1089 /* If char is out of range, try the font's default char instead. */
1090 c
= font
->default_char
;
1091 row
= c
>> (INTBITS
- 8);
1094 if (!(within
>= font
->min_char_or_byte2
1095 && within
<= font
->max_char_or_byte2
1096 && row
>= font
->min_byte1
1097 && row
<= font
->max_byte1
))
1098 /* Still out of range means this char does not overlap. */
1101 /* We found the info for this char. */
1102 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1106 return (s
&& s
->rbearing
>= s
->width
);
1110 /* Invert the middle quarter of the frame for .15 sec. */
1112 /* We use the select system call to do the waiting, so we have to make sure
1113 it's available. If it isn't, we just won't do visual bells. */
1114 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1116 /* Subtract the `struct timeval' values X and Y,
1117 storing the result in RESULT.
1118 Return 1 if the difference is negative, otherwise 0. */
1121 timeval_subtract (result
, x
, y
)
1122 struct timeval
*result
, x
, y
;
1124 /* Perform the carry for the later subtraction by updating y.
1125 This is safer because on some systems
1126 the tv_sec member is unsigned. */
1127 if (x
.tv_usec
< y
.tv_usec
)
1129 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1130 y
.tv_usec
-= 1000000 * nsec
;
1133 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1135 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1136 y
.tv_usec
+= 1000000 * nsec
;
1140 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1141 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1142 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1144 /* Return indication of whether the result should be considered negative. */
1145 return x
.tv_sec
< y
.tv_sec
;
1156 /* Create a GC that will use the GXxor function to flip foreground pixels
1157 into background pixels. */
1161 values
.function
= GXxor
;
1162 values
.foreground
= (f
->display
.x
->foreground_pixel
1163 ^ f
->display
.x
->background_pixel
);
1165 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
1166 GCFunction
| GCForeground
, &values
);
1170 int width
= PIXEL_WIDTH (f
);
1171 int height
= PIXEL_HEIGHT (f
);
1173 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1174 width
/4, height
/4, width
/2, height
/2);
1175 XFlush (x_current_display
);
1178 struct timeval wakeup
, now
;
1180 EMACS_GET_TIME (wakeup
);
1182 /* Compute time to wait until, propagating carry from usecs. */
1183 wakeup
.tv_usec
+= 150000;
1184 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1185 wakeup
.tv_usec
%= 1000000;
1187 /* Keep waiting until past the time wakeup. */
1190 struct timeval timeout
;
1192 EMACS_GET_TIME (timeout
);
1194 /* In effect, timeout = wakeup - timeout.
1195 Break if result would be negative. */
1196 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1199 /* Try to wait that long--but we might wake up sooner. */
1200 select (0, 0, 0, 0, &timeout
);
1204 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1205 width
/4, height
/4, width
/2, height
/2);
1206 XFreeGC (x_current_display
, gc
);
1207 XFlush (x_current_display
);
1217 /* Make audible bell. */
1220 #define XRINGBELL XBell (x_current_display, 0)
1221 #else /* ! defined (HAVE_X11) */
1222 #define XRINGBELL XFeep (0);
1223 #endif /* ! defined (HAVE_X11) */
1227 if (x_current_display
== 0)
1230 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1232 XTflash (selected_frame
);
1243 /* Insert and delete character.
1244 These are not supposed to be used because we are supposed to turn
1245 off the feature of using them. */
1248 XTinsert_glyphs (start
, len
)
1249 register char *start
;
1262 /* Specify how many text lines, from the top of the window,
1263 should be affected by insert-lines and delete-lines operations.
1264 This, and those operations, are used only within an update
1265 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1268 XTset_terminal_window (n
)
1271 if (updating_frame
== 0)
1274 if ((n
<= 0) || (n
> updating_frame
->height
))
1275 flexlines
= updating_frame
->height
;
1280 /* Perform an insert-lines operation.
1281 Insert N lines at a vertical position curs_y. */
1287 register int topregion
, bottomregion
;
1288 register int length
, newtop
, mask
;
1289 register struct frame
*f
= updating_frame
;
1290 int intborder
= f
->display
.x
->internal_border_width
;
1292 if (curs_y
>= flexlines
)
1296 bottomregion
= flexlines
- (n
+ 1);
1297 newtop
= topregion
+ n
;
1298 length
= (bottomregion
- topregion
) + 1;
1302 #endif /* HAVE_X11 */
1304 if ((length
> 0) && (newtop
<= flexlines
))
1307 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1308 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1309 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1310 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1311 length
* f
->display
.x
->line_height
, intborder
,
1312 CHAR_TO_PIXEL_ROW (f
, newtop
));
1313 #else /* ! defined (HAVE_X11) */
1314 XMoveArea (FRAME_X_WINDOW (f
),
1315 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1316 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1317 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1318 length
* f
->display
.x
->line_height
);
1319 /* Now we must process any ExposeRegion events that occur
1320 if the area being copied from is obscured.
1321 We can't let it wait because further i/d operations
1322 may want to copy this area to another area. */
1324 #endif /* ! defined (HAVE_X11) */
1327 newtop
= min (newtop
, (flexlines
- 1));
1328 length
= newtop
- topregion
;
1332 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1333 CHAR_TO_PIXEL_ROW (f
, topregion
),
1334 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1335 n
* f
->display
.x
->line_height
, False
);
1336 #else /* ! defined (HAVE_X11) */
1337 XPixSet (FRAME_X_WINDOW (f
),
1339 CHAR_TO_PIXEL_ROW (f
, topregion
),
1340 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1341 n
* f
->display
.x
->line_height
,
1342 f
->display
.x
->background_pixel
);
1343 #endif /* ! defined (HAVE_X11) */
1347 /* Perform a delete-lines operation, deleting N lines
1348 at a vertical position curs_y. */
1355 register struct frame
*f
= updating_frame
;
1356 int intborder
= f
->display
.x
->internal_border_width
;
1358 if (curs_y
>= flexlines
)
1363 #endif /* HAVE_X11 */
1365 if ((curs_y
+ n
) >= flexlines
)
1367 if (flexlines
>= (curs_y
+ 1))
1370 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1371 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1372 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1373 (flexlines
- curs_y
) * f
->display
.x
->line_height
, False
);
1374 #else /* ! defined (HAVE_X11) */
1375 XPixSet (FRAME_X_WINDOW (f
),
1376 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1377 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1378 (flexlines
- curs_y
) * f
->display
.x
->line_height
,
1379 f
->display
.x
->background_pixel
);
1380 #endif /* ! defined (HAVE_X11) */
1386 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1387 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1389 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1390 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1391 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
,
1392 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1393 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1395 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1396 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1397 n
* f
->display
.x
->line_height
, False
);
1398 #else /* ! defined (HAVE_X11) */
1399 XMoveArea (FRAME_X_WINDOW (f
),
1401 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1402 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1403 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1404 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
);
1405 /* Now we must process any ExposeRegion events that occur
1406 if the area being copied from is obscured.
1407 We can't let it wait because further i/d operations
1408 may want to copy this area to another area. */
1410 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1411 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1412 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1413 n
* f
->display
.x
->line_height
, f
->display
.x
->background_pixel
);
1414 #endif /* ! defined (HAVE_X11) */
1418 /* Perform an insert-lines or delete-lines operation,
1419 inserting N lines or deleting -N lines at vertical position VPOS. */
1421 XTins_del_lines (vpos
, n
)
1424 if (updating_frame
== 0)
1427 /* Hide the cursor. */
1428 x_display_cursor (updating_frame
, 0);
1430 XTcursor_to (vpos
, 0);
1441 /* Support routines for exposure events. */
1442 static void clear_cursor ();
1444 /* Output into a rectangle of an X-window (for frame F)
1445 the characters in f->phys_lines that overlap that rectangle.
1446 TOP and LEFT are the position of the upper left corner of the rectangle.
1447 ROWS and COLS are the size of the rectangle.
1448 Call this function with input blocked. */
1451 dumprectangle (f
, left
, top
, cols
, rows
)
1453 register int left
, top
, cols
, rows
;
1455 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1456 int cursor_cleared
= 0;
1460 if (FRAME_GARBAGED_P (f
))
1463 /* Express rectangle as four edges, instead of position-and-size. */
1464 bottom
= top
+ rows
;
1465 right
= left
+ cols
;
1467 #ifndef HAVE_X11 /* Window manger does this for X11. */
1469 int intborder
= f
->display
.x
->internal_border_width
;
1471 /* If the rectangle includes any of the internal border area,
1472 redisplay the border emphasis. */
1473 if (top
< intborder
|| left
< intborder
1474 || bottom
> intborder
+ f
->height
* f
->display
.x
->line_height
1475 || right
> intborder
+ f
->width
* f
->display
.x
->line_height
)
1478 #endif /* not HAVE_X11 Window manger does this for X11. */
1480 /* Convert rectangle edges in pixels to edges in chars.
1481 Round down for left and top, up for right and bottom. */
1482 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1483 left
= PIXEL_TO_CHAR_COL (f
, left
);
1484 bottom
+= (f
->display
.x
->line_height
- 1);
1485 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1486 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1487 right
= PIXEL_TO_CHAR_COL (f
, right
);
1489 /* Clip the rectangle to what can be visible. */
1494 if (right
> f
->width
)
1496 if (bottom
> f
->height
)
1499 /* Get size in chars of the rectangle. */
1500 cols
= right
- left
;
1501 rows
= bottom
- top
;
1503 /* If rectangle has zero area, return. */
1504 if (rows
<= 0) return;
1505 if (cols
<= 0) return;
1507 /* Turn off the cursor if it is in the rectangle.
1508 We will turn it back on afterward. */
1509 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1510 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1516 /* Display the text in the rectangle, one text line at a time. */
1518 for (y
= top
; y
< bottom
; y
++)
1520 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1522 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1526 CHAR_TO_PIXEL_COL (f
, left
),
1527 CHAR_TO_PIXEL_ROW (f
, y
),
1528 line
, min (cols
, active_frame
->used
[y
] - left
),
1529 active_frame
->highlight
[y
], 0);
1532 /* Turn the cursor on if we turned it off. */
1535 x_display_cursor (f
, 1);
1539 /* Process all queued ExposeRegion events. */
1545 XExposeRegionEvent r
;
1547 while (dequeue_event (&r
, &x_expose_queue
))
1549 struct frame
*f
= x_window_to_frame (r
.window
);
1550 if (f
->display
.x
->icon_desc
== r
.window
)
1553 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1557 #endif /* HAVE_X11 */
1559 /* Process all expose events that are pending, for X10.
1560 Redraws the cursor if necessary on any frame that
1561 is not in the process of being updated with update_frame. */
1565 x_do_pending_expose ()
1569 Lisp_Object tail
, frame
;
1571 if (expose_all_windows
)
1573 expose_all_windows
= 0;
1574 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1576 register int temp_width
, temp_height
;
1579 frame
= XCONS (tail
)->car
;
1580 if (XGCTYPE (frame
) != Lisp_Frame
)
1583 if (! FRAME_X_P (f
))
1585 if (!f
->async_visible
)
1587 if (!f
->display
.x
->needs_exposure
)
1590 intborder
= f
->display
.x
->internal_border_width
;
1593 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1594 temp_width
= ((windowinfo
.width
- 2 * intborder
1595 - f
->display
.x
->v_scroll_bar_width
)
1596 / FONT_WIDTH (f
->display
.x
->font
));
1597 temp_height
= ((windowinfo
.height
- 2 * intborder
1598 - f
->display
.x
->h_scroll_bar_height
)
1599 / f
->display
.x
->line_height
);
1600 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1602 change_frame_size (f
, max (1, temp_height
),
1603 max (1, temp_width
), 0, 1);
1604 x_resize_scroll_bars (f
);
1606 f
->display
.x
->left_pos
= windowinfo
.x
;
1607 f
->display
.x
->top_pos
= windowinfo
.y
;
1608 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1612 f
->display
.x
->needs_exposure
= 0;
1613 if (updating_frame
!= f
)
1614 x_display_cursor (f
, 1);
1619 /* Handle any individual-rectangle expose events queued
1620 for various windows. */
1623 #else /* ! defined (HAVE_X11) */
1625 #endif /* ! defined (HAVE_X11) */
1631 frame_highlight (frame
)
1632 struct frame
*frame
;
1634 /* We used to only do this if Vx_no_window_manager was non-nil, but
1635 the ICCCM (section 4.1.6) says that the window's border pixmap
1636 and border pixel are window attributes which are "private to the
1637 client", so we can always change it to whatever we want. */
1639 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1640 frame
->display
.x
->border_pixel
);
1642 x_display_cursor (frame
, 1);
1646 frame_unhighlight (frame
)
1647 struct frame
*frame
;
1649 /* We used to only do this if Vx_no_window_manager was non-nil, but
1650 the ICCCM (section 4.1.6) says that the window's border pixmap
1651 and border pixel are window attributes which are "private to the
1652 client", so we can always change it to whatever we want. */
1654 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1655 frame
->display
.x
->border_tile
);
1657 x_display_cursor (frame
, 1);
1659 #else /* ! defined (HAVE_X11) */
1660 /* Dump the border-emphasis of frame F.
1661 If F is selected, this is a lining of the same color as the border,
1662 just within the border, occupying a portion of the internal border.
1663 If F is not selected, it is background in the same place.
1664 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1666 ALWAYS = 1 is used when a frame becomes selected or deselected.
1667 In that case, we also turn the cursor off and on again
1668 so it will appear in the proper shape (solid if selected; else hollow.) */
1671 dumpborder (f
, always
)
1675 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1676 int width
= PIXEL_WIDTH (f
);
1677 int height
= PIXEL_HEIGHT (f
);
1680 if (f
!= selected_frame
)
1685 pixel
= f
->display
.x
->background_pixel
;
1689 pixel
= f
->display
.x
->border_pixel
;
1692 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1693 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1694 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1696 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1700 x_display_cursor (f
, 1);
1702 #endif /* ! defined (HAVE_X11) */
1704 static void XTframe_rehighlight ();
1706 /* The focus has changed. Update the frames as necessary to reflect
1707 the new situation. Note that we can't change the selected frame
1708 here, because the lisp code we are interrupting might become confused.
1709 Each event gets marked with the frame in which it occurred, so the
1710 lisp code can tell when the switch took place by examining the events. */
1713 x_new_focus_frame (frame
)
1714 struct frame
*frame
;
1716 struct frame
*old_focus
= x_focus_frame
;
1717 int events_enqueued
= 0;
1719 if (frame
!= x_focus_frame
)
1721 /* Set this before calling other routines, so that they see
1722 the correct value of x_focus_frame. */
1723 x_focus_frame
= frame
;
1725 if (old_focus
&& old_focus
->auto_lower
)
1726 x_lower_frame (old_focus
);
1729 selected_frame
= frame
;
1730 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1731 Lisp_Frame
, selected_frame
);
1732 Fselect_window (selected_frame
->selected_window
);
1733 choose_minibuf_frame ();
1736 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1737 pending_autoraise_frame
= x_focus_frame
;
1739 pending_autoraise_frame
= 0;
1742 XTframe_rehighlight ();
1746 /* The focus has changed, or we have redirected a frame's focus to
1747 another frame (this happens when a frame uses a surrogate
1748 minibuffer frame). Shift the highlight as appropriate. */
1750 XTframe_rehighlight ()
1752 struct frame
*old_highlight
= x_highlight_frame
;
1757 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1758 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1760 if (! FRAME_LIVE_P (x_highlight_frame
))
1762 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1763 x_highlight_frame
= x_focus_frame
;
1767 x_highlight_frame
= 0;
1769 if (x_highlight_frame
!= old_highlight
)
1772 frame_unhighlight (old_highlight
);
1773 if (x_highlight_frame
)
1774 frame_highlight (x_highlight_frame
);
1778 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1780 /* Which modifier keys are on which modifier bits?
1782 With each keystroke, X returns eight bits indicating which modifier
1783 keys were held down when the key was pressed. The interpretation
1784 of the top five modifier bits depends on what keys are attached
1785 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1788 x_meta_mod_mask is a mask containing the bits used for the meta key.
1789 It may have more than one bit set, if more than one modifier bit
1790 has meta keys on it. Basically, if EVENT is a KeyPress event,
1791 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1793 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1794 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1795 only be affected by the lock modifier bit if XK_Shift_Lock is in
1796 use; XK_Caps_Lock should only affect alphabetic keys. With this
1797 arrangement, the lock modifier should shift the character if
1798 (EVENT.state & x_shift_lock_mask) != 0. */
1799 static int x_meta_mod_mask
, x_shift_lock_mask
;
1801 /* These are like x_meta_mod_mask, but for different modifiers. */
1802 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1804 /* Initialize mode_switch_bit and modifier_meaning. */
1806 x_find_modifier_meanings ()
1808 int min_code
, max_code
;
1811 XModifierKeymap
*mods
;
1813 x_meta_mod_mask
= 0;
1814 x_shift_lock_mask
= 0;
1816 x_super_mod_mask
= 0;
1817 x_hyper_mod_mask
= 0;
1820 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1822 min_code
= x_current_display
->min_keycode
;
1823 max_code
= x_current_display
->max_keycode
;
1826 syms
= XGetKeyboardMapping (x_current_display
,
1827 min_code
, max_code
- min_code
+ 1,
1829 mods
= XGetModifierMapping (x_current_display
);
1831 /* Scan the modifier table to see which modifier bits the Meta and
1832 Alt keysyms are on. */
1834 int row
, col
; /* The row and column in the modifier table. */
1836 for (row
= 3; row
< 8; row
++)
1837 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1840 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1842 /* Zeroes are used for filler. Skip them. */
1846 /* Are any of this keycode's keysyms a meta key? */
1850 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1852 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1858 x_meta_mod_mask
|= (1 << row
);
1863 x_alt_mod_mask
|= (1 << row
);
1868 x_hyper_mod_mask
|= (1 << row
);
1873 x_super_mod_mask
|= (1 << row
);
1877 /* Ignore this if it's not on the lock modifier. */
1878 if ((1 << row
) == LockMask
)
1879 x_shift_lock_mask
= LockMask
;
1887 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1888 if (! x_meta_mod_mask
)
1890 x_meta_mod_mask
= x_alt_mod_mask
;
1894 /* If some keys are both alt and meta,
1895 make them just meta, not alt. */
1896 if (x_alt_mod_mask
& x_meta_mod_mask
)
1898 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1901 XFree ((char *) syms
);
1902 XFreeModifiermap (mods
);
1905 /* Convert between the modifier bits X uses and the modifier bits
1908 x_x_to_emacs_modifiers (state
)
1911 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1912 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1913 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1914 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1915 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1916 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1920 x_emacs_to_x_modifiers (state
)
1923 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1924 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1925 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1926 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1927 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1928 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1931 /* Mouse clicks and mouse movement. Rah. */
1934 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1935 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1936 that the glyph at X, Y occupies, if BOUNDS != 0.
1937 If NOCLIP is nonzero, do not force the value into range. */
1940 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1942 register int pix_x
, pix_y
;
1943 register int *x
, *y
;
1947 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1948 even for negative values. */
1950 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1952 pix_y
-= (f
)->display
.x
->line_height
- 1;
1954 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1955 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1959 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1960 bounds
->height
= f
->display
.x
->line_height
;
1961 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1962 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1969 else if (pix_x
> f
->width
)
1974 else if (pix_y
> f
->height
)
1983 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1986 register int *pix_x
, *pix_y
;
1988 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1989 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1992 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1994 If the event is a button press, then note that we have grabbed
1998 construct_mouse_click (result
, event
, f
)
1999 struct input_event
*result
;
2000 XButtonEvent
*event
;
2003 /* Make the event type no_event; we'll change that when we decide
2005 result
->kind
= mouse_click
;
2006 result
->code
= event
->button
- Button1
;
2007 result
->timestamp
= event
->time
;
2008 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2009 | (event
->type
== ButtonRelease
2017 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2018 XFASTINT (result
->x
) = column
;
2019 XFASTINT (result
->y
) = row
;
2021 XSET (result
->x
, Lisp_Int
, event
->x
);
2022 XSET (result
->y
, Lisp_Int
, event
->y
);
2023 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2027 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2030 construct_menu_click (result
, event
, f
)
2031 struct input_event
*result
;
2032 XButtonEvent
*event
;
2035 /* Make the event type no_event; we'll change that when we decide
2037 result
->kind
= mouse_click
;
2038 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
2039 result
->timestamp
= event
->time
;
2040 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2041 | (event
->type
== ButtonRelease
2045 XSET (result
->x
, Lisp_Int
, event
->x
);
2046 XSET (result
->y
, Lisp_Int
, -1);
2047 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2050 /* Function to report a mouse movement to the mainstream Emacs code.
2051 The input handler calls this.
2053 We have received a mouse movement event, which is given in *event.
2054 If the mouse is over a different glyph than it was last time, tell
2055 the mainstream emacs code by setting mouse_moved. If not, ask for
2056 another motion event, so we can check again the next time it moves. */
2059 note_mouse_movement (frame
, event
)
2061 XMotionEvent
*event
;
2064 last_mouse_movement_time
= event
->time
;
2066 if (event
->window
!= FRAME_X_WINDOW (frame
))
2069 last_mouse_scroll_bar
= Qnil
;
2071 note_mouse_highlight (frame
, -1, -1);
2073 /* Ask for another mouse motion event. */
2076 Window dummy_window
;
2078 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2079 &dummy_window
, &dummy_window
,
2080 &dummy
, &dummy
, &dummy
, &dummy
,
2081 (unsigned int *) &dummy
);
2085 /* Has the mouse moved off the glyph it was on at the last sighting? */
2086 else if (event
->x
< last_mouse_glyph
.x
2087 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2088 || event
->y
< last_mouse_glyph
.y
2089 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2092 last_mouse_scroll_bar
= Qnil
;
2094 note_mouse_highlight (frame
, event
->x
, event
->y
);
2096 /* Ask for another mouse motion event. */
2099 Window dummy_window
;
2101 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2102 &dummy_window
, &dummy_window
,
2103 &dummy
, &dummy
, &dummy
, &dummy
,
2104 (unsigned int *) &dummy
);
2109 /* It's on the same glyph. Call XQueryPointer so we'll get an
2110 event the next time the mouse moves and we can see if it's
2111 *still* on the same glyph. */
2113 Window dummy_window
;
2115 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2116 &dummy_window
, &dummy_window
,
2117 &dummy
, &dummy
, &dummy
, &dummy
,
2118 (unsigned int *) &dummy
);
2122 /* This is used for debugging, to turn off note_mouse_highlight. */
2123 static int disable_mouse_highlight
;
2125 /* Take proper action when the mouse has moved to position X, Y on frame F
2126 as regards highlighting characters that have mouse-face properties.
2127 Also dehighlighting chars where the mouse was before.
2128 X and Y can be negative or out of range. */
2131 note_mouse_highlight (f
, x
, y
)
2134 int row
, column
, portion
;
2135 XRectangle new_glyph
;
2139 if (disable_mouse_highlight
)
2142 mouse_face_mouse_x
= x
;
2143 mouse_face_mouse_y
= y
;
2144 mouse_face_mouse_frame
= f
;
2146 if (mouse_face_defer
)
2151 mouse_face_deferred_gc
= 1;
2155 /* Find out which glyph the mouse is on. */
2156 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2157 &new_glyph
, x_mouse_grabbed
);
2159 /* Which window is that in? */
2160 window
= window_from_coordinates (f
, column
, row
, &portion
);
2161 w
= XWINDOW (window
);
2163 /* If we were displaying active text in another window, clear that. */
2164 if (! EQ (window
, mouse_face_window
))
2165 clear_mouse_face ();
2167 /* Are we in a window whose display is up to date?
2168 And verify the buffer's text has not changed. */
2169 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2170 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2171 && EQ (w
->window_end_valid
, w
->buffer
)
2172 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
2174 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2177 /* Find which buffer position the mouse corresponds to. */
2178 for (i
= column
; i
>= 0; i
--)
2182 /* Is it outside the displayed active region (if any)? */
2184 clear_mouse_face ();
2185 else if (! (EQ (window
, mouse_face_window
)
2186 && row
>= mouse_face_beg_row
2187 && row
<= mouse_face_end_row
2188 && (row
> mouse_face_beg_row
|| column
>= mouse_face_beg_col
)
2189 && (row
< mouse_face_end_row
|| column
< mouse_face_end_col
2190 || mouse_face_past_end
)))
2192 Lisp_Object mouse_face
, overlay
, position
;
2193 Lisp_Object
*overlay_vec
;
2194 int len
, noverlays
, ignor1
;
2195 struct buffer
*obuf
;
2198 /* If we get an out-of-range value, return now; avoid an error. */
2199 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2202 /* Make the window's buffer temporarily current for
2203 overlays_at and compute_char_face. */
2204 obuf
= current_buffer
;
2205 current_buffer
= XBUFFER (w
->buffer
);
2211 /* Yes. Clear the display of the old active region, if any. */
2212 clear_mouse_face ();
2214 /* Is this char mouse-active? */
2215 XSET (position
, Lisp_Int
, pos
);
2218 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2220 /* Put all the overlays we want in a vector in overlay_vec.
2221 Store the length in len. */
2222 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
, &ignor1
);
2223 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2225 /* Find the highest priority overlay that has a mouse-face prop. */
2227 for (i
= 0; i
< noverlays
; i
++)
2229 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2230 if (!NILP (mouse_face
))
2232 overlay
= overlay_vec
[i
];
2237 /* If no overlay applies, get a text property. */
2239 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2241 /* Handle the overlay case. */
2242 if (! NILP (overlay
))
2244 /* Find the range of text around this char that
2245 should be active. */
2246 Lisp_Object before
, after
;
2249 before
= Foverlay_start (overlay
);
2250 after
= Foverlay_end (overlay
);
2251 /* Record this as the current active region. */
2252 fast_find_position (window
, before
, &mouse_face_beg_col
,
2253 &mouse_face_beg_row
);
2255 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2256 &mouse_face_end_row
);
2257 mouse_face_window
= window
;
2258 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
2259 &ignore
, pos
+ 1, 1);
2261 /* Display it as active. */
2262 show_mouse_face (1);
2264 /* Handle the text property case. */
2265 else if (! NILP (mouse_face
))
2267 /* Find the range of text around this char that
2268 should be active. */
2269 Lisp_Object before
, after
, beginning
, end
;
2272 beginning
= Fmarker_position (w
->start
);
2273 XSET (end
, Lisp_Int
,
2274 (BUF_Z (XBUFFER (w
->buffer
))
2275 - XFASTINT (w
->window_end_pos
)));
2277 = Fprevious_single_property_change (make_number (pos
+ 1),
2279 w
->buffer
, beginning
);
2281 = Fnext_single_property_change (position
, Qmouse_face
,
2283 /* Record this as the current active region. */
2284 fast_find_position (window
, before
, &mouse_face_beg_col
,
2285 &mouse_face_beg_row
);
2287 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2288 &mouse_face_end_row
);
2289 mouse_face_window
= window
;
2291 = compute_char_face (f
, w
, pos
, 0, 0,
2292 &ignore
, pos
+ 1, 1);
2294 /* Display it as active. */
2295 show_mouse_face (1);
2299 current_buffer
= obuf
;
2304 /* Find the row and column of position POS in window WINDOW.
2305 Store them in *COLUMNP and *ROWP.
2306 This assumes display in WINDOW is up to date.
2307 If POS is above start of WINDOW, return coords
2308 of start of first screen line.
2309 If POS is after end of WINDOW, return coords of end of last screen line.
2311 Value is 1 if POS is in range, 0 if it was off screen. */
2314 fast_find_position (window
, pos
, columnp
, rowp
)
2317 int *columnp
, *rowp
;
2319 struct window
*w
= XWINDOW (window
);
2320 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2325 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2326 int width
= window_internal_width (w
);
2330 /* Find the right row. */
2335 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2336 if (linestart
> pos
)
2342 /* Find the right column with in it. */
2343 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2345 for (i
= 0; i
< width
; i
++)
2347 if (charstarts
[left
+ i
] == pos
)
2350 *columnp
= i
+ left
;
2353 else if (charstarts
[left
+ i
] > pos
)
2355 else if (charstarts
[left
+ i
] > 0)
2364 /* Display the active region described by mouse_face_*
2365 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2368 show_mouse_face (hl
)
2371 struct window
*w
= XWINDOW (mouse_face_window
);
2372 int width
= window_internal_width (w
);
2373 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2376 int old_curs_x
= curs_x
;
2377 int old_curs_y
= curs_y
;
2379 /* Set these variables temporarily
2380 so that if we have to turn the cursor off and on again
2381 we will put it back at the same place. */
2382 curs_x
= f
->phys_cursor_x
;
2383 curs_y
= f
->phys_cursor_y
;
2385 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2387 int column
= (i
== mouse_face_beg_row
? mouse_face_beg_col
: w
->left
);
2388 int endcolumn
= (i
== mouse_face_end_row
? mouse_face_end_col
: w
->left
+ width
);
2389 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2391 /* If the cursor's in the text we are about to rewrite,
2392 turn the cursor off. */
2394 && curs_x
>= mouse_face_beg_col
- 1 && curs_x
<= mouse_face_end_col
)
2396 x_display_cursor (f
, 0);
2401 CHAR_TO_PIXEL_COL (f
, column
),
2402 CHAR_TO_PIXEL_ROW (f
, i
),
2403 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2405 /* Highlight with mouse face if hl > 0. */
2409 /* If we turned the cursor off, turn it back on. */
2411 x_display_cursor (f
, 1);
2413 curs_x
= old_curs_x
;
2414 curs_y
= old_curs_y
;
2416 /* Change the mouse cursor according to the value of HL. */
2418 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->cross_cursor
);
2420 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->text_cursor
);
2423 /* Clear out the mouse-highlighted active region.
2424 Redraw it unhighlighted first. */
2429 if (! NILP (mouse_face_window
))
2430 show_mouse_face (0);
2432 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2433 mouse_face_end_row
= mouse_face_end_col
= -1;
2434 mouse_face_window
= Qnil
;
2437 static struct scroll_bar
*x_window_to_scroll_bar ();
2438 static void x_scroll_bar_report_motion ();
2440 /* Return the current position of the mouse.
2442 If the mouse movement started in a scroll bar, set *f, *bar_window,
2443 and *part to the frame, window, and scroll bar part that the mouse
2444 is over. Set *x and *y to the portion and whole of the mouse's
2445 position on the scroll bar.
2447 If the mouse movement started elsewhere, set *f to the frame the
2448 mouse is on, *bar_window to nil, and *x and *y to the character cell
2451 Set *time to the server timestamp for the time at which the mouse
2452 was at this position.
2454 Don't store anything if we don't have a valid set of values to report.
2456 This clears the mouse_moved flag, so we can wait for the next mouse
2457 movement. This also calls XQueryPointer, which will cause the
2458 server to give us another MotionNotify when the mouse moves
2462 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
2464 Lisp_Object
*bar_window
;
2465 enum scroll_bar_part
*part
;
2467 unsigned long *time
;
2473 if (! NILP (last_mouse_scroll_bar
))
2474 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
2480 Window dummy_window
;
2484 last_mouse_scroll_bar
= Qnil
;
2486 /* Figure out which root window we're on. */
2487 XQueryPointer (x_current_display
,
2488 DefaultRootWindow (x_current_display
),
2490 /* The root window which contains the pointer. */
2493 /* Trash which we can't trust if the pointer is on
2494 a different screen. */
2497 /* The position on that root window. */
2500 /* More trash we can't trust. */
2503 /* Modifier keys and pointer buttons, about which
2505 (unsigned int *) &dummy
);
2507 /* Now we have a position on the root; find the innermost window
2508 containing the pointer. */
2512 int parent_x
, parent_y
;
2516 if (x_mouse_grabbed
&& last_mouse_frame
2517 && FRAME_LIVE_P (last_mouse_frame
))
2519 /* If mouse was grabbed on a frame, give coords for that frame
2520 even if the mouse is now outside it. */
2521 XTranslateCoordinates (x_current_display
,
2523 /* From-window, to-window. */
2524 root
, FRAME_X_WINDOW (last_mouse_frame
),
2526 /* From-position, to-position. */
2527 root_x
, root_y
, &win_x
, &win_y
,
2531 f1
= last_mouse_frame
;
2537 XTranslateCoordinates (x_current_display
,
2539 /* From-window, to-window. */
2542 /* From-position, to-position. */
2543 root_x
, root_y
, &win_x
, &win_y
,
2556 /* Now we know that:
2557 win is the innermost window containing the pointer
2558 (XTC says it has no child containing the pointer),
2559 win_x and win_y are the pointer's position in it
2560 (XTC did this the last time through), and
2561 parent_x and parent_y are the pointer's position in win's parent.
2562 (They are what win_x and win_y were when win was child.
2563 If win is the root window, it has no parent, and
2564 parent_{x,y} are invalid, but that's okay, because we'll
2565 never use them in that case.) */
2567 /* Is win one of our frames? */
2568 f1
= x_any_window_to_frame (win
);
2571 /* If not, is it one of our scroll bars? */
2574 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2578 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2586 int ignore1
, ignore2
;
2588 /* Ok, we found a frame. Store all the values. */
2590 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2591 &last_mouse_glyph
, x_mouse_grabbed
);
2596 XSET (*x
, Lisp_Int
, win_x
);
2597 XSET (*y
, Lisp_Int
, win_y
);
2598 *time
= last_mouse_movement_time
;
2606 #else /* ! defined (HAVE_X11) */
2607 #define XEvent XKeyPressedEvent
2608 #endif /* ! defined (HAVE_X11) */
2610 /* Scroll bar support. */
2612 /* Given an X window ID, find the struct scroll_bar which manages it.
2613 This can be called in GC, so we have to make sure to strip off mark
2615 static struct scroll_bar
*
2616 x_window_to_scroll_bar (window_id
)
2619 Lisp_Object tail
, frame
;
2621 for (tail
= Vframe_list
;
2622 XGCTYPE (tail
) == Lisp_Cons
;
2623 tail
= XCONS (tail
)->cdr
)
2625 Lisp_Object frame
, bar
, condemned
;
2627 frame
= XCONS (tail
)->car
;
2628 /* All elements of Vframe_list should be frames. */
2629 if (XGCTYPE (frame
) != Lisp_Frame
)
2632 /* Scan this frame's scroll bar list for a scroll bar with the
2634 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2635 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2636 /* This trick allows us to search both the ordinary and
2637 condemned scroll bar lists with one loop. */
2638 ! GC_NILP (bar
) || (bar
= condemned
,
2641 bar
= XSCROLL_BAR (bar
)->next
)
2642 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2643 return XSCROLL_BAR (bar
);
2649 /* Open a new X window to serve as a scroll bar, and return the
2650 scroll bar vector for it. */
2651 static struct scroll_bar
*
2652 x_scroll_bar_create (window
, top
, left
, width
, height
)
2653 struct window
*window
;
2654 int top
, left
, width
, height
;
2656 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2657 struct scroll_bar
*bar
=
2658 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2663 XSetWindowAttributes a
;
2665 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2666 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2667 | ButtonMotionMask
| PointerMotionHintMask
2669 a
.cursor
= x_vertical_scroll_bar_cursor
;
2671 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2676 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2677 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2678 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2679 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2680 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2681 sb_widget
= XtCreateManagedWidget ("box",
2683 frame
->display
.x
->edit_widget
, al
, ac
);
2684 SET_SCROLL_BAR_X_WINDOW
2685 (bar
, sb_widget
->core
.window
);
2687 SET_SCROLL_BAR_X_WINDOW
2689 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2691 /* Position and size of scroll bar. */
2692 left
, top
, width
, height
,
2694 /* Border width, depth, class, and visual. */
2695 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2701 XSET (bar
->window
, Lisp_Window
, window
);
2702 XSET (bar
->top
, Lisp_Int
, top
);
2703 XSET (bar
->left
, Lisp_Int
, left
);
2704 XSET (bar
->width
, Lisp_Int
, width
);
2705 XSET (bar
->height
, Lisp_Int
, height
);
2706 XSET (bar
->start
, Lisp_Int
, 0);
2707 XSET (bar
->end
, Lisp_Int
, 0);
2708 bar
->dragging
= Qnil
;
2710 /* Add bar to its frame's list of scroll bars. */
2711 bar
->next
= FRAME_SCROLL_BARS (frame
);
2713 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2714 if (! NILP (bar
->next
))
2715 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2717 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2724 /* Draw BAR's handle in the proper position.
2725 If the handle is already drawn from START to END, don't bother
2726 redrawing it, unless REBUILD is non-zero; in that case, always
2727 redraw it. (REBUILD is handy for drawing the handle after expose
2730 Normally, we want to constrain the start and end of the handle to
2731 fit inside its rectangle, but if the user is dragging the scroll bar
2732 handle, we want to let them drag it down all the way, so that the
2733 bar's top is as far down as it goes; otherwise, there's no way to
2734 move to the very end of the buffer. */
2736 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2737 struct scroll_bar
*bar
;
2741 int dragging
= ! NILP (bar
->dragging
);
2742 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2743 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2745 /* If the display is already accurate, do nothing. */
2747 && start
== XINT (bar
->start
)
2748 && end
== XINT (bar
->end
))
2754 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2755 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2756 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2758 /* Make sure the values are reasonable, and try to preserve
2759 the distance between start and end. */
2761 int length
= end
- start
;
2765 else if (start
> top_range
)
2767 end
= start
+ length
;
2771 else if (end
> top_range
&& ! dragging
)
2775 /* Store the adjusted setting in the scroll bar. */
2776 XSET (bar
->start
, Lisp_Int
, start
);
2777 XSET (bar
->end
, Lisp_Int
, end
);
2779 /* Clip the end position, just for display. */
2780 if (end
> top_range
)
2783 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2784 below top positions, to make sure the handle is always at least
2785 that many pixels tall. */
2786 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2788 /* Draw the empty space above the handle. Note that we can't clear
2789 zero-height areas; that means "clear to end of window." */
2791 XClearArea (x_current_display
, w
,
2793 /* x, y, width, height, and exposures. */
2794 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2795 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2796 inside_width
, start
,
2799 /* Draw the handle itself. */
2800 XFillRectangle (x_current_display
, w
, gc
,
2802 /* x, y, width, height */
2803 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2804 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2805 inside_width
, end
- start
);
2808 /* Draw the empty space below the handle. Note that we can't
2809 clear zero-height areas; that means "clear to end of window." */
2810 if (end
< inside_height
)
2811 XClearArea (x_current_display
, w
,
2813 /* x, y, width, height, and exposures. */
2814 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2815 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2816 inside_width
, inside_height
- end
,
2824 /* Move a scroll bar around on the screen, to accommodate changing
2825 window configurations. */
2827 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2828 struct scroll_bar
*bar
;
2829 int top
, left
, width
, height
;
2835 unsigned int mask
= 0;
2842 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2843 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2844 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2845 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2848 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2852 XSET (bar
->left
, Lisp_Int
, left
);
2853 XSET (bar
->top
, Lisp_Int
, top
);
2854 XSET (bar
->width
, Lisp_Int
, width
);
2855 XSET (bar
->height
, Lisp_Int
, height
);
2860 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2863 x_scroll_bar_remove (bar
)
2864 struct scroll_bar
*bar
;
2866 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2870 /* Destroy the window. */
2871 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2873 /* Disassociate this scroll bar from its window. */
2874 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2879 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2880 that we are displaying PORTION characters out of a total of WHOLE
2881 characters, starting at POSITION. If WINDOW has no scroll bar,
2884 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2885 struct window
*window
;
2886 int portion
, whole
, position
;
2888 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2889 int top
= XINT (window
->top
);
2890 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2891 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2893 /* Where should this scroll bar be, pixelwise? */
2894 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2895 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2896 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2897 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2899 struct scroll_bar
*bar
;
2901 /* Does the scroll bar exist yet? */
2902 if (NILP (window
->vertical_scroll_bar
))
2903 bar
= x_scroll_bar_create (window
,
2904 pixel_top
, pixel_left
,
2905 pixel_width
, pixel_height
);
2908 /* It may just need to be moved and resized. */
2909 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2910 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2913 /* Set the scroll bar's current state, unless we're currently being
2915 if (NILP (bar
->dragging
))
2918 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2921 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2924 int start
= ((double) position
* top_range
) / whole
;
2925 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2927 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2931 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2935 /* The following three hooks are used when we're doing a thorough
2936 redisplay of the frame. We don't explicitly know which scroll bars
2937 are going to be deleted, because keeping track of when windows go
2938 away is a real pain - "Can you say set-window-configuration, boys
2939 and girls?" Instead, we just assert at the beginning of redisplay
2940 that *all* scroll bars are to be removed, and then save a scroll bar
2941 from the fiery pit when we actually redisplay its window. */
2943 /* Arrange for all scroll bars on FRAME to be removed at the next call
2944 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2945 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2947 XTcondemn_scroll_bars (frame
)
2950 /* The condemned list should be empty at this point; if it's not,
2951 then the rest of Emacs isn't using the condemn/redeem/judge
2952 protocol correctly. */
2953 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2956 /* Move them all to the "condemned" list. */
2957 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2958 FRAME_SCROLL_BARS (frame
) = Qnil
;
2961 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2962 Note that WINDOW isn't necessarily condemned at all. */
2964 XTredeem_scroll_bar (window
)
2965 struct window
*window
;
2967 struct scroll_bar
*bar
;
2969 /* We can't redeem this window's scroll bar if it doesn't have one. */
2970 if (NILP (window
->vertical_scroll_bar
))
2973 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2975 /* Unlink it from the condemned list. */
2977 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2979 if (NILP (bar
->prev
))
2981 /* If the prev pointer is nil, it must be the first in one of
2983 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2984 /* It's not condemned. Everything's fine. */
2986 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2987 window
->vertical_scroll_bar
))
2988 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2990 /* If its prev pointer is nil, it must be at the front of
2991 one or the other! */
2995 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2997 if (! NILP (bar
->next
))
2998 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3000 bar
->next
= FRAME_SCROLL_BARS (f
);
3002 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
3003 if (! NILP (bar
->next
))
3004 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
3008 /* Remove all scroll bars on FRAME that haven't been saved since the
3009 last call to `*condemn_scroll_bars_hook'. */
3011 XTjudge_scroll_bars (f
)
3014 Lisp_Object bar
, next
;
3016 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3018 /* Clear out the condemned list now so we won't try to process any
3019 more events on the hapless scroll bars. */
3020 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3022 for (; ! NILP (bar
); bar
= next
)
3024 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3026 x_scroll_bar_remove (b
);
3029 b
->next
= b
->prev
= Qnil
;
3032 /* Now there should be no references to the condemned scroll bars,
3033 and they should get garbage-collected. */
3037 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3039 This may be called from a signal handler, so we have to ignore GC
3042 x_scroll_bar_expose (bar
, event
)
3043 struct scroll_bar
*bar
;
3046 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3047 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
3051 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3053 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3054 XDrawRectangle (x_current_display
, w
, gc
,
3056 /* x, y, width, height */
3057 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
3062 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3063 is set to something other than no_event, it is enqueued.
3065 This may be called from a signal handler, so we have to ignore GC
3068 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3069 struct scroll_bar
*bar
;
3071 struct input_event
*emacs_event
;
3073 if (XGCTYPE (bar
->window
) != Lisp_Window
)
3076 emacs_event
->kind
= scroll_bar_click
;
3077 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3078 emacs_event
->modifiers
=
3079 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
3080 | (event
->type
== ButtonRelease
3083 emacs_event
->frame_or_window
= bar
->window
;
3084 emacs_event
->timestamp
= event
->xbutton
.time
;
3086 int internal_height
=
3087 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3089 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3090 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3093 if (y
> top_range
) y
= top_range
;
3095 if (y
< XINT (bar
->start
))
3096 emacs_event
->part
= scroll_bar_above_handle
;
3097 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3098 emacs_event
->part
= scroll_bar_handle
;
3100 emacs_event
->part
= scroll_bar_below_handle
;
3102 /* Just because the user has clicked on the handle doesn't mean
3103 they want to drag it. Lisp code needs to be able to decide
3104 whether or not we're dragging. */
3106 /* If the user has just clicked on the handle, record where they're
3108 if (event
->type
== ButtonPress
3109 && emacs_event
->part
== scroll_bar_handle
)
3110 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
3113 /* If the user has released the handle, set it to its final position. */
3114 if (event
->type
== ButtonRelease
3115 && ! NILP (bar
->dragging
))
3117 int new_start
= y
- XINT (bar
->dragging
);
3118 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3120 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3121 bar
->dragging
= Qnil
;
3124 /* Same deal here as the other #if 0. */
3126 /* Clicks on the handle are always reported as occurring at the top of
3128 if (emacs_event
->part
== scroll_bar_handle
)
3129 emacs_event
->x
= bar
->start
;
3131 XSET (emacs_event
->x
, Lisp_Int
, y
);
3133 XSET (emacs_event
->x
, Lisp_Int
, y
);
3136 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
3140 /* Handle some mouse motion while someone is dragging the scroll bar.
3142 This may be called from a signal handler, so we have to ignore GC
3145 x_scroll_bar_note_movement (bar
, event
)
3146 struct scroll_bar
*bar
;
3149 last_mouse_movement_time
= event
->xmotion
.time
;
3152 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
3154 /* If we're dragging the bar, display it. */
3155 if (! GC_NILP (bar
->dragging
))
3157 /* Where should the handle be now? */
3158 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3160 if (new_start
!= XINT (bar
->start
))
3162 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3164 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3168 /* Call XQueryPointer so we'll get an event the next time the mouse
3169 moves and we can see *still* on the same position. */
3172 Window dummy_window
;
3174 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3175 &dummy_window
, &dummy_window
,
3176 &dummy
, &dummy
, &dummy
, &dummy
,
3177 (unsigned int *) &dummy
);
3181 /* Return information to the user about the current position of the mouse
3182 on the scroll bar. */
3184 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
3186 Lisp_Object
*bar_window
;
3187 enum scroll_bar_part
*part
;
3189 unsigned long *time
;
3191 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3193 Window dummy_window
;
3195 unsigned int dummy_mask
;
3199 /* Get the mouse's position relative to the scroll bar window, and
3201 if (! XQueryPointer (x_current_display
,
3202 SCROLL_BAR_X_WINDOW (bar
),
3204 /* Root, child, root x and root y. */
3205 &dummy_window
, &dummy_window
,
3206 &dummy_coord
, &dummy_coord
,
3208 /* Position relative to scroll bar. */
3211 /* Mouse buttons and modifier keys. */
3217 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3219 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3221 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3223 if (! NILP (bar
->dragging
))
3224 win_y
-= XINT (bar
->dragging
);
3228 if (win_y
> top_range
)
3231 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3232 *bar_window
= bar
->window
;
3234 if (! NILP (bar
->dragging
))
3235 *part
= scroll_bar_handle
;
3236 else if (win_y
< XINT (bar
->start
))
3237 *part
= scroll_bar_above_handle
;
3238 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3239 *part
= scroll_bar_handle
;
3241 *part
= scroll_bar_below_handle
;
3243 XSET (*x
, Lisp_Int
, win_y
);
3244 XSET (*y
, Lisp_Int
, top_range
);
3247 last_mouse_scroll_bar
= Qnil
;
3250 *time
= last_mouse_movement_time
;
3256 /* The screen has been cleared so we may have changed foreground or
3257 background colors, and the scroll bars may need to be redrawn.
3258 Clear out the scroll bars, and ask for expose events, so we can
3261 x_scroll_bar_clear (f
)
3266 for (bar
= FRAME_SCROLL_BARS (f
);
3267 XTYPE (bar
) == Lisp_Vector
;
3268 bar
= XSCROLL_BAR (bar
)->next
)
3269 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3273 /* This processes Expose events from the menubar specific X event
3274 loop in menubar.c. This allows to redisplay the frame if necessary
3275 when handling menubar or popup items. */
3278 process_expose_from_menu (event
)
3285 f
= x_window_to_frame (event
.xexpose
.window
);
3288 if (f
->async_visible
== 0)
3290 f
->async_visible
= 1;
3291 f
->async_iconified
= 0;
3292 SET_FRAME_GARBAGED (f
);
3296 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3297 event
.xexpose
.x
, event
.xexpose
.y
,
3298 event
.xexpose
.width
, event
.xexpose
.height
);
3303 struct scroll_bar
*bar
3304 = x_window_to_scroll_bar (event
.xexpose
.window
);
3307 x_scroll_bar_expose (bar
, &event
);
3313 /* Define a queue to save up SelectionRequest events for later handling. */
3315 struct selection_event_queue
3318 struct selection_event_queue
*next
;
3321 static struct selection_event_queue
*queue
;
3323 /* Nonzero means queue up certain events--don't process them yet. */
3324 static int x_queue_selection_requests
;
3326 /* Queue up an X event *EVENT, to be processed later. */
3329 x_queue_event (event
)
3332 struct selection_event_queue
*queue_tmp
3333 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3335 if (queue_tmp
!= NULL
)
3337 queue_tmp
->event
= *event
;
3338 queue_tmp
->next
= queue
;
3343 /* Take all the queued events and put them back
3344 so that they get processed afresh. */
3349 while (queue
!= NULL
)
3351 struct selection_event_queue
*queue_tmp
= queue
;
3352 XPutBackEvent (XDISPLAY
&queue_tmp
->event
);
3353 queue
= queue_tmp
->next
;
3354 free ((char *)queue_tmp
);
3358 /* Start queuing SelectionRequest events. */
3361 x_start_queuing_selection_requests ()
3363 x_queue_selection_requests
++;
3366 /* Stop queuing SelectionRequest events. */
3369 x_stop_queuing_selection_requests ()
3371 x_queue_selection_requests
--;
3372 x_unqueue_events ();
3375 /* The main X event-reading loop - XTread_socket. */
3377 /* Timestamp of enter window event. This is only used by XTread_socket,
3378 but we have to put it out here, since static variables within functions
3379 sometimes don't work. */
3380 static Time enter_timestamp
;
3382 /* This holds the state XLookupString needs to implement dead keys
3383 and other tricks known as "compose processing". _X Window System_
3384 says that a portable program can't use this, but Stephen Gildea assures
3385 me that letting the compiler initialize it to zeros will work okay.
3387 This must be defined outside of XTread_socket, for the same reasons
3388 given for enter_timestamp, above. */
3389 static XComposeStatus compose_status
;
3391 /* Communication with window managers. */
3392 Atom Xatom_wm_protocols
;
3394 /* Kinds of protocol things we may receive. */
3395 Atom Xatom_wm_take_focus
;
3396 Atom Xatom_wm_save_yourself
;
3397 Atom Xatom_wm_delete_window
;
3399 /* Other WM communication */
3400 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3401 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3403 /* Window manager communication. */
3404 Atom Xatom_wm_change_state
;
3406 /* EditRes protocol */
3407 Atom Xatom_editres_name
;
3409 /* Record the last 100 characters stored
3410 to help debug the loss-of-chars-during-GC problem. */
3412 short temp_buffer
[100];
3414 /* Read events coming from the X server.
3415 This routine is called by the SIGIO handler.
3416 We return as soon as there are no more events to be read.
3418 Events representing keys are stored in buffer BUFP,
3419 which can hold up to NUMCHARS characters.
3420 We return the number of characters stored into the buffer,
3421 thus pretending to be `read'.
3423 WAITP is nonzero if we should block until input arrives.
3424 EXPECTED is nonzero if the caller knows input is available. */
3427 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3429 register struct input_event
*bufp
;
3430 register int numchars
;
3437 int items_pending
; /* How many items are in the X queue. */
3440 int event_found
= 0;
3444 if (interrupt_input_blocked
)
3446 interrupt_input_pending
= 1;
3450 interrupt_input_pending
= 0;
3454 abort (); /* Don't think this happens. */
3457 /* If available, Xlib uses FIOSNBIO to make the socket
3458 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3459 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3460 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3461 fcntl (fileno (stdin
), F_SETFL
, 0);
3462 #endif /* ! defined (FIOSNBIO) */
3466 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3468 extern int read_alarm_should_throw
;
3469 read_alarm_should_throw
= 1;
3470 XPeekEvent (XDISPLAY
&event
);
3471 read_alarm_should_throw
= 0;
3473 #endif /* HAVE_SELECT */
3476 while (XStuffPending () != 0)
3478 XNextEvent (XDISPLAY
&event
);
3486 if (event
.xclient
.message_type
== Xatom_wm_protocols
3487 && event
.xclient
.format
== 32)
3489 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3491 f
= x_window_to_frame (event
.xclient
.window
);
3492 /* Since we set WM_TAKE_FOCUS, we must call
3493 XSetInputFocus explicitly. But not if f is null,
3494 since that might be an event for a deleted frame. */
3496 XSetInputFocus (event
.xclient
.display
,
3497 event
.xclient
.window
,
3498 RevertToPointerRoot
,
3499 event
.xclient
.data
.l
[1]);
3500 /* Not certain about handling scroll bars here */
3502 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3504 /* Save state modify the WM_COMMAND property to
3505 something which can reinstate us. This notifies
3506 the session manager, who's looking for such a
3507 PropertyNotify. Can restart processing when
3508 a keyboard or mouse event arrives. */
3511 /* This is just so we only give real data once
3512 for a single Emacs process. */
3513 if (x_top_window_to_frame (event
.xclient
.window
)
3515 XSetCommand (x_current_display
,
3516 event
.xclient
.window
,
3517 initial_argv
, initial_argc
);
3519 XSetCommand (x_current_display
,
3520 event
.xclient
.window
,
3524 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3526 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3533 bufp
->kind
= delete_window_event
;
3534 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3542 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3545 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3548 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3550 new_x
= event
.xclient
.data
.s
[0];
3551 new_y
= event
.xclient
.data
.s
[1];
3555 f
->display
.x
->left_pos
= new_x
;
3556 f
->display
.x
->top_pos
= new_y
;
3559 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3560 else if (event
.xclient
.message_type
== Xatom_editres_name
)
3562 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3563 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3565 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3569 case SelectionNotify
:
3570 #ifdef USE_X_TOOLKIT
3571 if (! x_window_to_frame (event
.xselection
.requestor
))
3573 #endif /* not USE_X_TOOLKIT */
3574 x_handle_selection_notify (&event
);
3577 case SelectionClear
: /* Someone has grabbed ownership. */
3578 #ifdef USE_X_TOOLKIT
3579 if (! x_window_to_frame (event
.xselectionclear
.window
))
3581 #endif /* USE_X_TOOLKIT */
3583 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3588 bufp
->kind
= selection_clear_event
;
3589 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3590 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3591 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3599 case SelectionRequest
: /* Someone wants our selection. */
3600 #ifdef USE_X_TOOLKIT
3601 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3603 #endif /* USE_X_TOOLKIT */
3604 if (x_queue_selection_requests
)
3605 x_queue_event (&event
);
3608 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3613 bufp
->kind
= selection_request_event
;
3614 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3615 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3616 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3617 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3618 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3619 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3627 case PropertyNotify
:
3628 #ifdef USE_X_TOOLKIT
3629 if (!x_any_window_to_frame (event
.xproperty
.window
))
3631 #endif /* not USE_X_TOOLKIT */
3632 x_handle_property_notify (&event
);
3635 case ReparentNotify
:
3636 f
= x_top_window_to_frame (event
.xreparent
.window
);
3640 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3641 x_real_positions (f
, &x
, &y
);
3642 f
->display
.x
->left_pos
= x
;
3643 f
->display
.x
->top_pos
= y
;
3648 f
= x_window_to_frame (event
.xexpose
.window
);
3651 if (f
->async_visible
== 0)
3653 f
->async_visible
= 1;
3654 f
->async_iconified
= 0;
3655 SET_FRAME_GARBAGED (f
);
3658 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3659 event
.xexpose
.x
, event
.xexpose
.y
,
3660 event
.xexpose
.width
, event
.xexpose
.height
);
3664 struct scroll_bar
*bar
3665 = x_window_to_scroll_bar (event
.xexpose
.window
);
3668 x_scroll_bar_expose (bar
, &event
);
3669 #ifdef USE_X_TOOLKIT
3672 #endif /* USE_X_TOOLKIT */
3676 case GraphicsExpose
: /* This occurs when an XCopyArea's
3677 source area was obscured or not
3679 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3683 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3684 event
.xgraphicsexpose
.width
,
3685 event
.xgraphicsexpose
.height
);
3687 #ifdef USE_X_TOOLKIT
3690 #endif /* USE_X_TOOLKIT */
3693 case NoExpose
: /* This occurs when an XCopyArea's
3694 source area was completely
3697 #else /* ! defined (HAVE_X11) */
3699 if (event
.subwindow
!= 0)
3700 break; /* duplicate event */
3701 f
= x_window_to_frame (event
.window
);
3702 if (event
.window
== f
->display
.x
->icon_desc
)
3705 f
->async_iconified
= 1;
3707 if (event
.window
== FRAME_X_WINDOW (f
))
3709 /* Say must check all windows' needs_exposure flags. */
3710 expose_all_windows
= 1;
3711 f
->display
.x
->needs_exposure
= 1;
3712 f
->async_visible
= 1;
3717 if (event
.subwindow
!= 0)
3718 break; /* duplicate event */
3719 f
= x_window_to_frame (event
.window
);
3720 if (event
.window
== f
->display
.x
->icon_desc
)
3725 /* If window already needs full redraw, ignore this rectangle. */
3726 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3728 /* Put the event on the queue of rectangles to redraw. */
3729 if (enqueue_event (&event
, &x_expose_queue
))
3730 /* If it is full, we can't record the rectangle,
3731 so redraw this entire window. */
3733 /* Say must check all windows' needs_exposure flags. */
3734 expose_all_windows
= 1;
3735 f
->display
.x
->needs_exposure
= 1;
3740 /* This should happen only when we are expecting it,
3741 in x_read_exposes. */
3743 #endif /* ! defined (HAVE_X11) */
3747 f
= x_any_window_to_frame (event
.xunmap
.window
);
3748 if (f
) /* F may no longer exist if
3749 the frame was deleted. */
3751 /* While a frame is unmapped, display generation is
3752 disabled; you don't want to spend time updating a
3753 display that won't ever be seen. */
3754 f
->async_visible
= 0;
3755 /* We can't distinguish, from the event, whether the window
3756 has become iconified or invisible. So assume, if it
3757 was previously visible, than now it is iconified.
3758 We depend on x_make_frame_invisible to mark it iconified. */
3759 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3760 f
->async_iconified
= 1;
3762 #ifdef USE_X_TOOLKIT
3764 #endif /* USE_X_TOOLKIT */
3768 /* We use x_top_window_to_frame because map events can come
3769 for subwindows and they don't mean that the frame is visible. */
3770 f
= x_top_window_to_frame (event
.xmap
.window
);
3773 f
->async_visible
= 1;
3774 f
->async_iconified
= 0;
3776 /* wait_reading_process_input will notice this and update
3777 the frame's display structures. */
3778 SET_FRAME_GARBAGED (f
);
3780 #ifdef USE_X_TOOLKIT
3782 #endif /* USE_X_TOOLKIT */
3785 /* Turn off processing if we become fully obscured. */
3786 case VisibilityNotify
:
3789 #else /* ! defined (HAVE_X11) */
3791 f
= x_window_to_frame (event
.window
);
3792 if (event
.window
== f
->display
.x
->icon_desc
)
3793 f
->async_iconified
= 0;
3794 if (event
.window
== FRAME_X_WINDOW (f
))
3795 f
->async_visible
= 0;
3797 #endif /* ! defined (HAVE_X11) */
3801 f
= x_any_window_to_frame (event
.xkey
.window
);
3805 KeySym keysym
, orig_keysym
;
3806 /* al%imercury@uunet.uu.net says that making this 81 instead of
3807 80 fixed a bug whereby meta chars made his Emacs hang. */
3808 unsigned char copy_buffer
[81];
3812 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3813 modifiers
= event
.xkey
.state
;
3815 /* This will have to go some day... */
3817 /* make_lispy_event turns chars into control chars.
3818 Don't do it here because XLookupString is too eager. */
3819 event
.xkey
.state
&= ~ControlMask
;
3821 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3824 orig_keysym
= keysym
;
3828 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3829 || keysym
== XK_Delete
3830 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3831 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3833 /* This recognizes the "extended function keys".
3834 It seems there's no cleaner way.
3835 Test IsModifierKey to avoid handling mode_switch
3837 || ((unsigned) (keysym
) >= XK_Select
3838 && (unsigned)(keysym
) < XK_KP_Space
)
3840 #ifdef XK_dead_circumflex
3841 || orig_keysym
== XK_dead_circumflex
3843 #ifdef XK_dead_grave
3844 || orig_keysym
== XK_dead_grave
3846 #ifdef XK_dead_tilde
3847 || orig_keysym
== XK_dead_tilde
3849 #ifdef XK_dead_diaeresis
3850 || orig_keysym
== XK_dead_diaeresis
3852 #ifdef XK_dead_macron
3853 || orig_keysym
== XK_dead_macron
3855 #ifdef XK_dead_degree
3856 || orig_keysym
== XK_dead_degree
3858 #ifdef XK_dead_acute
3859 || orig_keysym
== XK_dead_acute
3861 #ifdef XK_dead_cedilla
3862 || orig_keysym
== XK_dead_cedilla
3864 #ifdef XK_dead_breve
3865 || orig_keysym
== XK_dead_breve
3867 #ifdef XK_dead_ogonek
3868 || orig_keysym
== XK_dead_ogonek
3870 #ifdef XK_dead_caron
3871 || orig_keysym
== XK_dead_caron
3873 #ifdef XK_dead_doubleacute
3874 || orig_keysym
== XK_dead_doubleacute
3876 #ifdef XK_dead_abovedot
3877 || orig_keysym
== XK_dead_abovedot
3879 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3880 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3881 /* Any "vendor-specific" key is ok. */
3882 || (orig_keysym
& (1 << 28)))
3883 && ! (IsModifierKey (orig_keysym
)
3885 #ifdef XK_Mode_switch
3886 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3889 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3891 #endif /* not HAVE_X11R5 */
3894 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3896 temp_buffer
[temp_index
++] = keysym
;
3897 bufp
->kind
= non_ascii_keystroke
;
3898 bufp
->code
= keysym
;
3899 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3900 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3901 bufp
->timestamp
= event
.xkey
.time
;
3906 else if (numchars
> nbytes
)
3910 for (i
= 0; i
< nbytes
; i
++)
3912 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3914 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3915 bufp
->kind
= ascii_keystroke
;
3916 bufp
->code
= copy_buffer
[i
];
3917 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3918 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3919 bufp
->timestamp
= event
.xkey
.time
;
3933 #else /* ! defined (HAVE_X11) */
3936 register char *where_mapping
;
3938 f
= x_window_to_frame (event
.window
);
3939 /* Ignore keys typed on icon windows. */
3940 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3942 where_mapping
= XLookupMapping (&event
, &nbytes
);
3943 /* Nasty fix for arrow keys */
3944 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3946 switch (event
.detail
& 0xff)
3948 case KC_CURSOR_LEFT
:
3949 where_mapping
= "\002";
3951 case KC_CURSOR_RIGHT
:
3952 where_mapping
= "\006";
3955 where_mapping
= "\020";
3957 case KC_CURSOR_DOWN
:
3958 where_mapping
= "\016";
3963 if (numchars
- nbytes
> 0)
3967 for (i
= 0; i
< nbytes
; i
++)
3969 bufp
->kind
= ascii_keystroke
;
3970 bufp
->code
= where_mapping
[i
];
3971 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3972 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3980 #endif /* ! defined (HAVE_X11) */
3984 /* Here's a possible interpretation of the whole
3985 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3986 FocusIn event, you have to get a FocusOut event before you
3987 relinquish the focus. If you haven't received a FocusIn event,
3988 then a mere LeaveNotify is enough to free you. */
3991 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3993 if (event
.xcrossing
.focus
) /* Entered Window */
3995 /* Avoid nasty pop/raise loops. */
3996 if (f
&& (!(f
->auto_raise
)
3998 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
4000 x_new_focus_frame (f
);
4001 enter_timestamp
= event
.xcrossing
.time
;
4004 else if (f
== x_focus_frame
)
4005 x_new_focus_frame (0);
4006 /* EnterNotify counts as mouse movement,
4007 so update things that depend on mouse position. */
4009 note_mouse_movement (f
, &event
.xmotion
);
4010 #ifdef USE_X_TOOLKIT
4012 #endif /* USE_X_TOOLKIT */
4016 f
= x_any_window_to_frame (event
.xfocus
.window
);
4017 if (event
.xfocus
.detail
!= NotifyPointer
)
4018 x_focus_event_frame
= f
;
4020 x_new_focus_frame (f
);
4021 #ifdef USE_X_TOOLKIT
4023 #endif /* USE_X_TOOLKIT */
4028 f
= x_top_window_to_frame (event
.xcrossing
.window
);
4031 if (f
== mouse_face_mouse_frame
)
4032 /* If we move outside the frame,
4033 then we're certainly no longer on any text in the frame. */
4034 clear_mouse_face ();
4036 if (event
.xcrossing
.focus
)
4038 if (! x_focus_event_frame
)
4039 x_new_focus_frame (0);
4041 x_new_focus_frame (f
);
4045 if (f
== x_focus_event_frame
)
4046 x_focus_event_frame
= 0;
4047 if (f
== x_focus_frame
)
4048 x_new_focus_frame (0);
4051 #ifdef USE_X_TOOLKIT
4053 #endif /* USE_X_TOOLKIT */
4057 f
= x_any_window_to_frame (event
.xfocus
.window
);
4058 if (event
.xfocus
.detail
!= NotifyPointer
4059 && f
== x_focus_event_frame
)
4060 x_focus_event_frame
= 0;
4061 if (f
&& f
== x_focus_frame
)
4062 x_new_focus_frame (0);
4063 #ifdef USE_X_TOOLKIT
4065 #endif /* USE_X_TOOLKIT */
4068 #else /* ! defined (HAVE_X11) */
4071 if ((event
.detail
& 0xFF) == 1)
4072 break; /* Coming from our own subwindow */
4073 if (event
.subwindow
!= 0)
4074 break; /* Entering our own subwindow. */
4077 f
= x_window_to_frame (event
.window
);
4080 x_new_focus_frame (f
);
4085 if ((event
.detail
& 0xFF) == 1)
4086 break; /* Entering our own subwindow */
4087 if (event
.subwindow
!= 0)
4088 break; /* Leaving our own subwindow. */
4091 if (x_focus_frame
== 0
4092 && x_input_frame
!= 0
4093 && x_input_frame
== x_window_to_frame (event
.window
)
4094 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
4099 frame_unhighlight (f
);
4102 #endif /* ! defined (HAVE_X11) */
4107 if (x_mouse_grabbed
&& last_mouse_frame
4108 && FRAME_LIVE_P (last_mouse_frame
))
4109 f
= last_mouse_frame
;
4111 f
= x_window_to_frame (event
.xmotion
.window
);
4113 note_mouse_movement (f
, &event
.xmotion
);
4116 struct scroll_bar
*bar
4117 = x_window_to_scroll_bar (event
.xmotion
.window
);
4120 x_scroll_bar_note_movement (bar
, &event
);
4122 /* If we move outside the frame,
4123 then we're certainly no longer on any text in the frame. */
4124 clear_mouse_face ();
4127 #if 0 /* This should be unnecessary, since the toolkit has no use
4128 for motion events that happen outside of the menu event loop,
4129 and it seems to cause the bug that mouse events stop coming
4131 #ifdef USE_X_TOOLKIT
4133 #endif /* USE_X_TOOLKIT */
4137 case ConfigureNotify
:
4138 f
= x_any_window_to_frame (event
.xconfigure
.window
);
4139 #ifdef USE_X_TOOLKIT
4142 && ! event
.xconfigure
.send_event
4144 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
4149 /* Find the position of the outside upper-left corner of
4150 the window, in the root coordinate system. Don't
4151 refer to the parent window here; we may be processing
4152 this event after the window manager has changed our
4153 parent, but before we have reached the ReparentNotify. */
4154 XTranslateCoordinates (x_current_display
,
4156 /* From-window, to-window. */
4157 XtWindow (f
->display
.x
->widget
),
4160 /* From-position, to-position. */
4161 -event
.xconfigure
.border_width
,
4162 -event
.xconfigure
.border_width
,
4167 event
.xconfigure
.x
= win_x
;
4168 event
.xconfigure
.y
= win_y
;
4170 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4171 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4172 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4173 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4175 /* What we have now is the position of Emacs's own window.
4176 Convert that to the position of the window manager window. */
4179 x_real_positions (f
, &x
, &y
);
4180 f
->display
.x
->left_pos
= x
;
4181 f
->display
.x
->top_pos
= y
;
4185 #else /* not USE_X_TOOLKIT */
4188 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4189 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4191 /* Even if the number of character rows and columns has
4192 not changed, the font size may have changed, so we need
4193 to check the pixel dimensions as well. */
4194 if (columns
!= f
->width
4195 || rows
!= f
->height
4196 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
4197 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
4199 change_frame_size (f
, rows
, columns
, 0, 1);
4200 SET_FRAME_GARBAGED (f
);
4203 if (! event
.xconfigure
.send_event
)
4208 /* Find the position of the outside upper-left corner of
4209 the window, in the root coordinate system. Don't
4210 refer to the parent window here; we may be processing
4211 this event after the window manager has changed our
4212 parent, but before we have reached the ReparentNotify. */
4213 XTranslateCoordinates (x_current_display
,
4215 /* From-window, to-window. */
4216 f
->display
.x
->window_desc
,
4219 /* From-position, to-position. */
4220 -event
.xconfigure
.border_width
,
4221 -event
.xconfigure
.border_width
,
4226 event
.xconfigure
.x
= win_x
;
4227 event
.xconfigure
.y
= win_y
;
4230 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4231 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4232 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4233 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4235 /* What we have now is the position of Emacs's own window.
4236 Convert that to the position of the window manager window. */
4239 x_real_positions (f
, &x
, &y
);
4240 f
->display
.x
->left_pos
= x
;
4241 f
->display
.x
->top_pos
= y
;
4242 if (y
!= event
.xconfigure
.y
)
4244 /* Since the WM decorations come below top_pos now,
4245 we must put them below top_pos in the future. */
4246 f
->display
.x
->win_gravity
= NorthWestGravity
;
4247 x_wm_set_size_hint (f
, 0, 0);
4251 #endif /* not USE_X_TOOLKIT */
4257 /* If we decide we want to generate an event to be seen
4258 by the rest of Emacs, we put it here. */
4259 struct input_event emacs_event
;
4260 emacs_event
.kind
= no_event
;
4262 bzero (&compose_status
, sizeof (compose_status
));
4264 f
= x_window_to_frame (event
.xbutton
.window
);
4267 if (!x_focus_frame
|| (f
== x_focus_frame
))
4268 construct_mouse_click (&emacs_event
, &event
, f
);
4272 struct scroll_bar
*bar
4273 = x_window_to_scroll_bar (event
.xbutton
.window
);
4276 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4277 #ifdef USE_X_TOOLKIT
4280 f
= x_any_window_to_frame (event
.xbutton
.window
);
4281 if (f
&& event
.type
== ButtonPress
)
4282 construct_menu_click (&emacs_event
,
4285 #endif /* USE_X_TOOLKIT */
4288 if (event
.type
== ButtonPress
)
4290 x_mouse_grabbed
|= (1 << event
.xbutton
.button
);
4291 Vmouse_depressed
= Qt
;
4292 last_mouse_frame
= f
;
4296 x_mouse_grabbed
&= ~(1 << event
.xbutton
.button
);
4297 if (!x_mouse_grabbed
)
4298 Vmouse_depressed
= Qnil
;
4301 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4303 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4309 #ifdef USE_X_TOOLKIT
4311 #endif /* USE_X_TOOLKIT */
4315 #else /* ! defined (HAVE_X11) */
4317 case ButtonReleased
:
4318 f
= x_window_to_frame (event
.window
);
4321 if (event
.window
== f
->display
.x
->icon_desc
)
4323 x_make_frame_visible (f
);
4325 if (warp_mouse_on_deiconify
)
4326 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
4329 if (event
.window
== FRAME_X_WINDOW (f
))
4335 enqueue_event (&event
, &x_mouse_queue
);
4338 bufp
->kind
= ascii_keystroke
;
4339 bufp
->code
= 'X' & 037; /* C-x */
4340 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4341 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4344 bufp
->kind
= ascii_keystroke
;
4345 bufp
->code
= 0; /* C-@ */
4346 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4347 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4354 #endif /* ! defined (HAVE_X11) */
4358 case CirculateNotify
:
4360 case CirculateRequest
:
4363 #endif /* ! defined (HAVE_X11) */
4366 /* Someone has changed the keyboard mapping - update the
4368 switch (event
.xmapping
.request
)
4370 case MappingModifier
:
4371 x_find_modifier_meanings ();
4372 /* This is meant to fall through. */
4373 case MappingKeyboard
:
4374 XRefreshKeyboardMapping (&event
.xmapping
);
4376 #ifdef USE_X_TOOLKIT
4378 #endif /* USE_X_TOOLKIT */
4382 #ifdef USE_X_TOOLKIT
4385 XtDispatchEvent (&event
);
4387 #endif /* USE_X_TOOLKIT */
4392 /* On some systems, an X bug causes Emacs to get no more events
4393 when the window is destroyed. Detect that. (1994.) */
4396 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4397 One XNOOP in 100 loops will make Emacs terminate.
4398 B. Bretthauer, 1994 */
4400 if (x_noop_count
>= 100)
4403 XNoOp (x_current_display
);
4407 #if 0 /* This fails for serial-line connections to the X server,
4408 because the characters arrive one by one, and a partial
4409 command makes select return but gives nothing to read.
4410 We'll have to hope that the bug that this tried to fix
4411 in 1988 has been fixed in Xlib or the X server. */
4413 if (expected
&& ! event_found
)
4415 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4416 there is an EOF condition; in other words, that X has died.
4417 Act as if there had been a hangup. */
4418 int fd
= ConnectionNumber (x_current_display
);
4419 SELECT_TYPE mask
, junk1
, junk2
;
4424 EMACS_SET_SECS_USECS (timeout
, 0, 0);
4427 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
4428 && !XStuffPending ())
4429 kill (getpid (), SIGHUP
);
4431 #endif /* HAVE_SELECT */
4435 if (updating_frame
== 0)
4436 x_do_pending_expose ();
4439 /* If the focus was just given to an autoraising frame,
4442 if (pending_autoraise_frame
)
4444 x_raise_frame (pending_autoraise_frame
);
4445 pending_autoraise_frame
= 0;
4454 /* Read and process only Expose events
4455 until we get an ExposeCopy event; then return.
4456 This is used in insert/delete line.
4457 We assume input is already blocked. */
4463 XKeyPressedEvent event
;
4467 /* while there are more events*/
4468 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
4472 if (event
.subwindow
!= 0)
4473 break; /* duplicate event */
4474 f
= x_window_to_frame (event
.window
);
4475 if (event
.window
== f
->display
.x
->icon_desc
)
4480 if (event
.window
== FRAME_X_WINDOW (f
))
4482 expose_all_windows
= 1;
4483 f
->display
.x
->needs_exposure
= 1;
4489 if (event
.subwindow
!= 0)
4490 break; /* duplicate event */
4491 f
= x_window_to_frame (event
.window
);
4492 if (event
.window
== f
->display
.x
->icon_desc
)
4497 /* If window already needs full redraw, ignore this rectangle. */
4498 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
4500 /* Put the event on the queue of rectangles to redraw. */
4501 if (enqueue_event (&event
, &x_expose_queue
))
4502 /* If it is full, we can't record the rectangle,
4503 so redraw this entire window. */
4505 /* Say must check all windows' needs_exposure flags. */
4506 expose_all_windows
= 1;
4507 f
->display
.x
->needs_exposure
= 1;
4516 #endif /* HAVE_X11 */
4519 /* Drawing the cursor. */
4522 /* Draw a hollow box cursor. Don't change the inside of the box. */
4528 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
4529 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
4530 int width
= FONT_WIDTH (f
->display
.x
->font
);
4531 int height
= f
->display
.x
->line_height
;
4534 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4535 f
->display
.x
->cursor_gc
,
4536 left
, top
, width
- 1, height
- 1);
4537 #else /* ! defined (HAVE_X11) */
4538 XPixSet (FRAME_X_WINDOW (f
),
4539 left
, top
, width
, 1,
4540 f
->display
.x
->cursor_pixel
);
4542 XPixSet (FRAME_X_WINDOW (f
),
4543 left
, top
, 1, height
,
4544 f
->display
.x
->cursor_pixel
);
4546 XPixSet (FRAME_X_WINDOW (f
),
4547 left
+width
-1, top
, 1, height
,
4548 f
->display
.x
->cursor_pixel
);
4550 XPixSet (FRAME_X_WINDOW (f
),
4551 left
, top
+height
-1, width
, 1,
4552 f
->display
.x
->cursor_pixel
);
4553 #endif /* ! defined (HAVE_X11) */
4556 /* Clear the cursor of frame F to background color,
4557 and mark the cursor as not shown.
4558 This is used when the text where the cursor is
4559 is about to be rewritten. */
4567 if (! FRAME_VISIBLE_P (f
)
4568 || f
->phys_cursor_x
< 0)
4572 x_display_cursor (f
, 0);
4573 #else /* ! defined (HAVE_X11) */
4574 XPixSet (FRAME_X_WINDOW (f
),
4575 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4576 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4577 FONT_WIDTH (f
->display
.x
->font
), f
->display
.x
->line_height
,
4578 f
->display
.x
->background_pixel
);
4579 #endif /* ! defined (HAVE_X11) */
4580 f
->phys_cursor_x
= -1;
4583 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4584 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4588 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4595 CHAR_TO_PIXEL_COL (f
, column
),
4596 CHAR_TO_PIXEL_ROW (f
, row
),
4597 &glyph
, 1, highlight
, 0);
4601 x_display_bar_cursor (f
, on
)
4605 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4607 /* This is pointless on invisible frames, and dangerous on garbaged
4608 frames; in the latter case, the frame may be in the midst of
4609 changing its size, and curs_x and curs_y may be off the frame. */
4610 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4613 if (! on
&& f
->phys_cursor_x
< 0)
4616 /* If we're not updating, then we want to use the current frame's
4617 cursor position, not our local idea of where the cursor ought to be. */
4618 if (f
!= updating_frame
)
4620 curs_x
= FRAME_CURSOR_X (f
);
4621 curs_y
= FRAME_CURSOR_Y (f
);
4624 /* If there is anything wrong with the current cursor state, remove it. */
4625 if (f
->phys_cursor_x
>= 0
4627 || f
->phys_cursor_x
!= curs_x
4628 || f
->phys_cursor_y
!= curs_y
4629 || f
->display
.x
->current_cursor
!= bar_cursor
))
4631 /* Erase the cursor by redrawing the character underneath it. */
4632 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4633 f
->phys_cursor_glyph
,
4634 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4635 f
->phys_cursor_x
= -1;
4638 /* If we now need a cursor in the new place or in the new form, do it so. */
4640 && (f
->phys_cursor_x
< 0
4641 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4643 f
->phys_cursor_glyph
4644 = ((current_glyphs
->enable
[curs_y
]
4645 && curs_x
< current_glyphs
->used
[curs_y
])
4646 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4648 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4649 f
->display
.x
->cursor_gc
,
4650 CHAR_TO_PIXEL_COL (f
, curs_x
),
4651 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4652 1, f
->display
.x
->line_height
);
4654 f
->phys_cursor_x
= curs_x
;
4655 f
->phys_cursor_y
= curs_y
;
4657 f
->display
.x
->current_cursor
= bar_cursor
;
4660 if (updating_frame
!= f
)
4665 /* Turn the displayed cursor of frame F on or off according to ON.
4666 If ON is nonzero, where to put the cursor is specified
4667 by F->cursor_x and F->cursor_y. */
4670 x_display_box_cursor (f
, on
)
4674 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4676 /* This is pointless on invisible frames, and dangerous on garbaged
4677 frames; in the latter case, the frame may be in the midst of
4678 changing its size, and curs_x and curs_y may be off the frame. */
4679 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4682 /* If cursor is off and we want it off, return quickly. */
4683 if (!on
&& f
->phys_cursor_x
< 0)
4686 /* If we're not updating, then we want to use the current frame's
4687 cursor position, not our local idea of where the cursor ought to be. */
4688 if (f
!= updating_frame
)
4690 curs_x
= FRAME_CURSOR_X (f
);
4691 curs_y
= FRAME_CURSOR_Y (f
);
4694 /* If cursor is currently being shown and we don't want it to be
4695 or it is in the wrong place,
4696 or we want a hollow box and it's not so, (pout!)
4698 if (f
->phys_cursor_x
>= 0
4700 || f
->phys_cursor_x
!= curs_x
4701 || f
->phys_cursor_y
!= curs_y
4702 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4703 && (f
!= x_highlight_frame
))))
4705 int mouse_face_here
= 0;
4707 /* If the cursor is in the mouse face area, redisplay that when
4708 we clear the cursor. */
4709 if (f
== mouse_face_mouse_frame
4711 (f
->phys_cursor_y
> mouse_face_beg_row
4712 || (f
->phys_cursor_y
== mouse_face_beg_row
4713 && f
->phys_cursor_x
>= mouse_face_beg_col
))
4715 (f
->phys_cursor_y
< mouse_face_end_row
4716 || (f
->phys_cursor_y
== mouse_face_end_row
4717 && f
->phys_cursor_x
< mouse_face_end_col
)))
4718 mouse_face_here
= 1;
4720 /* If the font is not as tall as a whole line,
4721 we must explicitly clear the line's whole height. */
4722 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4723 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
4724 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4725 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4726 FONT_WIDTH (f
->display
.x
->font
),
4727 f
->display
.x
->line_height
, False
);
4728 /* Erase the cursor by redrawing the character underneath it. */
4729 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4730 f
->phys_cursor_glyph
,
4733 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4734 f
->phys_cursor_x
= -1;
4737 /* If we want to show a cursor,
4738 or we want a box cursor and it's not so,
4739 write it in the right place. */
4741 && (f
->phys_cursor_x
< 0
4742 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4743 && f
== x_highlight_frame
)))
4745 f
->phys_cursor_glyph
4746 = ((current_glyphs
->enable
[curs_y
]
4747 && curs_x
< current_glyphs
->used
[curs_y
])
4748 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4750 if (f
!= x_highlight_frame
)
4753 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4757 x_draw_single_glyph (f
, curs_y
, curs_x
,
4758 f
->phys_cursor_glyph
, 2);
4759 f
->display
.x
->current_cursor
= filled_box_cursor
;
4762 f
->phys_cursor_x
= curs_x
;
4763 f
->phys_cursor_y
= curs_y
;
4766 if (updating_frame
!= f
)
4770 x_display_cursor (f
, on
)
4776 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4777 x_display_box_cursor (f
, on
);
4778 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4779 x_display_bar_cursor (f
, on
);
4781 /* Those are the only two we have implemented! */
4789 /* Refresh bitmap kitchen sink icon for frame F
4790 when we get an expose event for it. */
4796 /* Normally, the window manager handles this function. */
4797 #else /* ! defined (HAVE_X11) */
4800 if (f
->display
.x
->icon_bitmap_flag
)
4801 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
4802 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
4803 icon_bitmap
, GXcopy
, AllPlanes
);
4806 extern struct frame
*selected_frame
;
4807 struct Lisp_String
*str
;
4808 unsigned char *string
;
4811 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
4813 if (f
->display
.x
->icon_label
!= string
)
4815 f
->display
.x
->icon_label
= string
;
4816 XChangeWindow (f
->display
.x
->icon_desc
,
4817 XQueryWidth (string
, icon_font_info
->id
) + 10,
4818 icon_font_info
->height
+ 10);
4821 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4822 str
->size
, icon_font_info
->id
,
4823 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4826 #endif /* ! defined (HAVE_X11) */
4829 /* Make the x-window of frame F use the gnu icon bitmap. */
4838 if (FRAME_X_WINDOW (f
) == 0)
4844 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4845 gnu_bits
, gnu_width
, gnu_height
);
4846 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4847 f
->display
.x
->icon_bitmap_flag
= 1;
4848 #else /* ! defined (HAVE_X11) */
4849 if (f
->display
.x
->icon_desc
)
4851 XClearIconWindow (FRAME_X_WINDOW (f
));
4852 XDestroyWindow (f
->display
.x
->icon_desc
);
4855 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4856 0, 0, sink_width
, sink_height
,
4857 2, WhitePixmap
, (Pixmap
) NULL
);
4859 if (icon_window
== 0)
4862 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4863 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4865 f
->display
.x
->icon_desc
= icon_window
;
4866 f
->display
.x
->icon_bitmap_flag
= 1;
4868 if (icon_bitmap
== 0)
4870 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4871 #endif /* ! defined (HAVE_X11) */
4877 /* Make the x-window of frame F use a rectangle with text. */
4880 x_text_icon (f
, icon_name
)
4888 char *X_DefaultValue
;
4892 #define WhitePixel 1
4893 #endif /* WhitePixel */
4896 #define BlackPixel 0
4897 #endif /* BlackPixel */
4898 #endif /* HAVE_X11 */
4900 if (FRAME_X_WINDOW (f
) == 0)
4905 f
->display
.x
->icon_label
= icon_name
;
4907 if (! f
->display
.x
->icon_label
)
4908 f
->display
.x
->icon_label
= " *emacs* ";
4911 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4912 (char *) f
->display
.x
->icon_label
);
4915 f
->display
.x
->icon_bitmap_flag
= 0;
4916 x_wm_set_icon_pixmap (f
, 0);
4917 #else /* ! defined (HAVE_X11) */
4918 if (icon_font_info
== 0)
4920 = XGetFont (XGetDefault (XDISPLAY
4921 (char *) XSTRING (Vinvocation_name
)->data
,
4924 if (f
->display
.x
->icon_desc
)
4926 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4927 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4931 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4933 if (! f
->display
.x
->icon_label
)
4934 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4936 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4937 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4938 f
->display
.x
->left_pos
,
4939 f
->display
.x
->top_pos
,
4940 width
+ 10, icon_font_info
->height
+ 10,
4941 2, BlackPixmap
, WhitePixmap
);
4943 if (icon_window
== 0)
4946 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4947 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4949 f
->display
.x
->icon_desc
= icon_window
;
4950 f
->display
.x
->icon_bitmap_flag
= 0;
4951 f
->display
.x
->icon_label
= 0;
4952 #endif /* ! defined (HAVE_X11) */
4957 /* Handling X errors. */
4959 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4960 X server's connection, or an error reported via the X protocol. */
4963 x_connection_closed ()
4968 shut_down_emacs (0, 1, Qnil
);
4973 /* An X error handler which prints an error message and then kills
4974 Emacs. This is what's normally installed as Xlib's handler for
4977 x_error_quitter (display
, error
)
4983 /* Note that there is no real way portable across R3/R4 to get the
4984 original error handler. */
4986 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4987 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4988 buf
, error
->request_code
);
4991 /* While we're testing Emacs 19, we'll just dump core whenever we
4992 get an X error, so we can figure out why it happened. */
4996 x_connection_closed ();
4999 /* A handler for X IO errors which prints an error message and then
5000 kills Emacs. This is what is always installed as Xlib's handler
5003 x_io_error_quitter (display
)
5006 fprintf (stderr
, "Connection to X server %s lost.\n",
5007 XDisplayName (DisplayString (display
)));
5010 /* While we're testing Emacs 19, we'll just dump core whenever we
5011 get an X error, so we can figure out why it happened. */
5015 x_connection_closed ();
5018 /* A buffer for storing X error messages. */
5019 static char *x_caught_error_message
;
5020 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
5022 /* An X error handler which stores the error message in
5023 x_caught_error_message. This is what's installed when
5024 x_catch_errors is in effect. */
5026 x_error_catcher (display
, error
)
5030 XGetErrorText (display
, error
->error_code
,
5031 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
5035 /* Begin trapping X errors.
5037 After calling this function, X protocol errors no longer cause
5038 Emacs to exit; instead, they are recorded in x_cfc_error_message.
5040 Calling x_check_errors signals an Emacs error if an X error has
5041 occurred since the last call to x_catch_errors or x_check_errors.
5043 Calling x_uncatch_errors resumes the normal error handling. */
5045 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
5050 /* Make sure any errors from previous requests have been dealt with. */
5051 XSync (x_current_display
, False
);
5053 /* Set up the error buffer. */
5054 x_caught_error_message
5055 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
5056 x_caught_error_message
[0] = '\0';
5058 /* Install our little error handler. */
5059 XHandleError (x_error_catcher
);
5062 /* If any X protocol errors have arrived since the last call to
5063 x_catch_errors or x_check_errors, signal an Emacs error using
5064 sprintf (a buffer, FORMAT, the x error message text) as the text. */
5067 x_check_errors (format
)
5070 /* Make sure to catch any errors incurred so far. */
5071 XSync (x_current_display
, False
);
5073 if (x_caught_error_message
[0])
5075 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
5077 sprintf (buf
, format
, x_caught_error_message
);
5078 x_uncatch_errors ();
5083 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
5088 /* Make sure to catch any errors incurred so far. */
5089 XSync (x_current_display
, False
);
5091 return x_caught_error_message
[0] != 0;
5094 /* Stop catching X protocol errors and let them make Emacs die. */
5099 xfree (x_caught_error_message
);
5100 x_caught_error_message
= 0;
5101 XHandleError (x_error_quitter
);
5105 static unsigned int x_wire_count
;
5108 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5113 /* Changing the font of the frame. */
5115 /* Set the font of the x-window specified by frame F
5116 to the font named NEWNAME. This is safe to use
5117 even before F has an actual x-window. */
5128 /* A table of all the fonts we have already loaded. */
5129 static struct font_info
*x_font_table
;
5131 /* The current capacity of x_font_table. */
5132 static int x_font_table_size
;
5134 /* The number of fonts actually stored in x_font_table.
5135 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
5136 0 <= n_fonts <= x_font_table_size. */
5139 /* Give frame F the font named FONTNAME as its default font, and
5140 return the full name of that font. FONTNAME may be a wildcard
5141 pattern; in that case, we choose some font that fits the pattern.
5142 The return value shows which font we chose. */
5145 x_new_font (f
, fontname
)
5147 register char *fontname
;
5150 int n_matching_fonts
;
5151 XFontStruct
*font_info
;
5154 /* Get a list of all the fonts that match this name. Once we
5155 have a list of matching fonts, we compare them against the fonts
5156 we already have by comparing font ids. */
5157 font_names
= (char **) XListFonts (x_current_display
, fontname
,
5158 1024, &n_matching_fonts
);
5159 /* Apparently it doesn't set n_matching_fonts to zero when it can't
5160 find any matches; font_names == 0 is the only clue. */
5162 n_matching_fonts
= 0;
5164 /* Don't just give up if n_matching_fonts is 0.
5165 Apparently there's a bug on Suns: XListFontsWithInfo can
5166 fail to find a font, but XLoadQueryFont may still find it. */
5168 /* See if we've already loaded a matching font. */
5169 already_loaded
= -1;
5170 if (n_matching_fonts
!= 0)
5174 for (i
= 0; i
< n_fonts
; i
++)
5175 for (j
= 0; j
< n_matching_fonts
; j
++)
5176 if (!strcmp (x_font_table
[i
].name
, font_names
[j
])
5177 || !strcmp (x_font_table
[i
].full_name
, font_names
[j
]))
5180 fontname
= x_font_table
[i
].full_name
;
5186 /* If we have, just return it from the table. */
5187 if (already_loaded
>= 0)
5188 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
5190 /* Otherwise, load the font and add it to the table. */
5197 /* Try to find a character-cell font in the list. */
5199 /* A laudable goal, but this isn't how to do it. */
5200 for (i
= 0; i
< n_matching_fonts
; i
++)
5201 if (! font_info
[i
].per_char
)
5207 /* See comment above. */
5208 if (n_matching_fonts
!= 0)
5209 fontname
= font_names
[i
];
5211 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
5214 /* Free the information from XListFonts. */
5215 if (n_matching_fonts
)
5216 XFreeFontNames (font_names
);
5220 /* Do we need to create the table? */
5221 if (x_font_table_size
== 0)
5223 x_font_table_size
= 16;
5225 = (struct font_info
*) xmalloc (x_font_table_size
5226 * sizeof (x_font_table
[0]));
5228 /* Do we need to grow the table? */
5229 else if (n_fonts
>= x_font_table_size
)
5231 x_font_table_size
*= 2;
5233 = (struct font_info
*) xrealloc (x_font_table
,
5235 * sizeof (x_font_table
[0])));
5238 /* Try to get the full name of FONT. Put it in full_name. */
5240 for (i
= 0; i
< font
->n_properties
; i
++)
5243 = XGetAtomName (x_current_display
, font
->properties
[i
].name
);
5244 if (!strcmp (atom
, "FONT"))
5245 full_name
= XGetAtomName (x_current_display
,
5246 (Atom
) (font
->properties
[i
].card32
));
5250 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
5251 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
5253 x_font_table
[n_fonts
].full_name
= full_name
;
5255 x_font_table
[n_fonts
].full_name
= x_font_table
[n_fonts
].name
;
5256 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
5259 fontname
= full_name
;
5262 /* Now make the frame display the given font. */
5263 if (FRAME_X_WINDOW (f
) != 0)
5265 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
5266 f
->display
.x
->font
->fid
);
5267 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
5268 f
->display
.x
->font
->fid
);
5269 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
5270 f
->display
.x
->font
->fid
);
5272 frame_update_line_height (f
);
5273 x_set_window_size (f
, 0, f
->width
, f
->height
);
5276 /* If we are setting a new frame's font for the first time,
5277 there are no faces yet, so this font's height is the line height. */
5278 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
5281 Lisp_Object lispy_name
;
5283 lispy_name
= build_string (fontname
);
5285 /* Free the information from XListFonts. The data
5286 we actually retain comes from XLoadQueryFont. */
5287 XFreeFontNames (font_names
);
5292 #else /* ! defined (HAVE_X11) */
5293 x_new_font (f
, newname
)
5295 register char *newname
;
5300 temp
= XGetFont (newname
);
5301 if (temp
== (FONT_TYPE
*) 0)
5304 if (f
->display
.x
->font
)
5305 XLoseFont (f
->display
.x
->font
);
5307 f
->display
.x
->font
= temp
;
5309 if (FRAME_X_WINDOW (f
) != 0)
5310 x_set_window_size (f
, 0, f
->width
, f
->height
);
5314 #endif /* ! defined (HAVE_X11) */
5316 x_calc_absolute_position (f
)
5321 int win_x
= 0, win_y
= 0;
5322 int flags
= f
->display
.x
->size_hint_flags
;
5324 /* Find the position of the outside upper-left corner of
5325 the inner window, with respect to the outer window. */
5326 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
5329 XTranslateCoordinates (x_current_display
,
5331 /* From-window, to-window. */
5332 f
->display
.x
->window_desc
,
5333 f
->display
.x
->parent_desc
,
5335 /* From-position, to-position. */
5336 0, 0, &win_x
, &win_y
,
5343 /* Treat negative positions as relative to the leftmost bottommost
5344 position that fits on the screen. */
5345 if (flags
& XNegative
)
5346 f
->display
.x
->left_pos
= (x_screen_width
5347 - 2 * f
->display
.x
->border_width
- win_x
5349 + f
->display
.x
->left_pos
);
5351 if (flags
& YNegative
)
5352 f
->display
.x
->top_pos
= (x_screen_height
5353 - 2 * f
->display
.x
->border_width
- win_y
5355 + f
->display
.x
->top_pos
);
5356 /* The left_pos and top_pos
5357 are now relative to the top and left screen edges,
5358 so the flags should correspond. */
5359 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5360 #else /* ! defined (HAVE_X11) */
5361 WINDOWINFO_TYPE parentinfo
;
5363 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
5365 if (f
->display
.x
->left_pos
< 0)
5366 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
5367 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
5369 if (f
->display
.x
->top_pos
< 0)
5370 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
5371 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
5372 #endif /* ! defined (HAVE_X11) */
5375 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5376 to really change the position, and 0 when calling from
5377 x_make_frame_visible (in that case, XOFF and YOFF are the current
5378 position values). */
5380 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5382 register int xoff
, yoff
;
5387 f
->display
.x
->top_pos
= yoff
;
5388 f
->display
.x
->left_pos
= xoff
;
5389 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5391 f
->display
.x
->size_hint_flags
|= XNegative
;
5393 f
->display
.x
->size_hint_flags
|= YNegative
;
5394 f
->display
.x
->win_gravity
= NorthWestGravity
;
5396 x_calc_absolute_position (f
);
5399 x_wm_set_size_hint (f
, 0, 0);
5401 #ifdef USE_X_TOOLKIT
5402 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
5403 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5404 #else /* not USE_X_TOOLKIT */
5405 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
5406 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5407 #endif /* not USE_X_TOOLKIT */
5411 /* Call this to change the size of frame F's x-window.
5412 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5413 for this size change and subsequent size changes.
5414 Otherwise we leave the window gravity unchanged. */
5416 x_set_window_size (f
, change_gravity
, cols
, rows
)
5421 int pixelwidth
, pixelheight
;
5424 #ifdef USE_X_TOOLKIT
5427 /* The x and y position of the widget is clobbered by the
5428 call to XtSetValues within EmacsFrameSetCharSize.
5429 This is a real kludge, but I don't understand Xt so I can't
5430 figure out a correct fix. Can anyone else tell me? -- rms. */
5431 int xpos
= f
->display
.x
->widget
->core
.x
;
5432 int ypos
= f
->display
.x
->widget
->core
.y
;
5433 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
5434 f
->display
.x
->widget
->core
.x
= xpos
;
5435 f
->display
.x
->widget
->core
.y
= ypos
;
5439 #else /* not USE_X_TOOLKIT */
5443 check_frame_size (f
, &rows
, &cols
);
5444 f
->display
.x
->vertical_scroll_bar_extra
5445 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5446 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
5448 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5449 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5452 f
->display
.x
->win_gravity
= NorthWestGravity
;
5453 x_wm_set_size_hint (f
, 0, 0);
5454 #endif /* ! defined (HAVE_X11) */
5455 XSync (x_current_display
, False
);
5456 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
5458 /* Now, strictly speaking, we can't be sure that this is accurate,
5459 but the window manager will get around to dealing with the size
5460 change request eventually, and we'll hear how it went when the
5461 ConfigureNotify event gets here.
5463 We could just not bother storing any of this information here,
5464 and let the ConfigureNotify event set everything up, but that
5465 might be kind of confusing to the lisp code, since size changes
5466 wouldn't be reported in the frame parameters until some random
5467 point in the future when the ConfigureNotify event arrives. */
5468 change_frame_size (f
, rows
, cols
, 0, 0);
5469 PIXEL_WIDTH (f
) = pixelwidth
;
5470 PIXEL_HEIGHT (f
) = pixelheight
;
5472 /* If cursor was outside the new size, mark it as off. */
5473 if (f
->phys_cursor_y
>= rows
5474 || f
->phys_cursor_x
>= cols
)
5476 f
->phys_cursor_x
= -1;
5477 f
->phys_cursor_y
= -1;
5480 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5481 receive in the ConfigureNotify event; if we get what we asked
5482 for, then the event won't cause the screen to become garbaged, so
5483 we have to make sure to do it here. */
5484 SET_FRAME_GARBAGED (f
);
5488 #endif /* not USE_X_TOOLKIT */
5492 x_set_resize_hint (f
)
5495 XSetResizeHint (FRAME_X_WINDOW (f
),
5496 2 * f
->display
.x
->internal_border_width
,
5497 2 * f
->display
.x
->internal_border_width
,
5498 FONT_WIDTH (f
->display
.x
->font
),
5499 f
->display
.x
->line_height
);
5501 #endif /* HAVE_X11 */
5503 /* Mouse warping, focus shifting, raising and lowering. */
5506 x_set_mouse_position (f
, x
, y
)
5512 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
5513 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
5515 if (pix_x
< 0) pix_x
= 0;
5516 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5518 if (pix_y
< 0) pix_y
= 0;
5519 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5523 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5527 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5530 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5536 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5541 x_focus_on_frame (f
)
5544 #if 0 /* This proves to be unpleasant. */
5548 /* I don't think that the ICCCM allows programs to do things like this
5549 without the interaction of the window manager. Whatever you end up
5550 doing with this code, do it to x_unfocus_frame too. */
5551 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
5552 RevertToPointerRoot
, CurrentTime
);
5560 /* Look at the remarks in x_focus_on_frame. */
5561 if (x_focus_frame
== f
)
5562 XSetInputFocus (x_current_display
, PointerRoot
,
5563 RevertToPointerRoot
, CurrentTime
);
5567 #endif /* ! defined (HAVE_X11) */
5569 /* Raise frame F. */
5574 if (f
->async_visible
)
5577 #ifdef USE_X_TOOLKIT
5578 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5579 #else /* not USE_X_TOOLKIT */
5580 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5581 #endif /* not USE_X_TOOLKIT */
5587 /* Lower frame F. */
5592 if (f
->async_visible
)
5595 #ifdef USE_X_TOOLKIT
5596 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5597 #else /* not USE_X_TOOLKIT */
5598 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5599 #endif /* not USE_X_TOOLKIT */
5606 XTframe_raise_lower (f
, raise
)
5617 /* Change from withdrawn state to mapped state,
5620 x_make_frame_visible (f
)
5627 if (! FRAME_VISIBLE_P (f
))
5630 #ifndef USE_X_TOOLKIT
5631 if (! FRAME_ICONIFIED_P (f
))
5632 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5635 if (! EQ (Vx_no_window_manager
, Qt
))
5636 x_wm_set_window_state (f
, NormalState
);
5637 #ifdef USE_X_TOOLKIT
5638 /* This was XtPopup, but that did nothing for an iconified frame. */
5639 XtMapWidget (f
->display
.x
->widget
);
5640 #else /* not USE_X_TOOLKIT */
5641 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5642 #endif /* not USE_X_TOOLKIT */
5643 #if 0 /* This seems to bring back scroll bars in the wrong places
5644 if the window configuration has changed. They seem
5645 to come back ok without this. */
5646 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5647 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5649 #else /* ! defined (HAVE_X11) */
5650 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5651 if (f
->display
.x
->icon_desc
!= 0)
5652 XUnmapWindow (f
->display
.x
->icon_desc
);
5654 /* Handled by the MapNotify event for X11 */
5655 f
->async_visible
= 1;
5656 f
->async_iconified
= 0;
5658 /* NOTE: this may cause problems for the first frame. */
5660 #endif /* ! defined (HAVE_X11) */
5667 /* Synchronize to ensure Emacs knows the frame is visible
5668 before we do anything else. We do this loop with input not blocked
5669 so that incoming events are handled. */
5672 XSET (frame
, Lisp_Frame
, f
);
5673 while (! f
->async_visible
)
5676 /* Machines that do polling rather than SIGIO have been observed
5677 to go into a busy-wait here. So we'll fake an alarm signal
5678 to let the handler know that there's something to be read.
5679 We used to raise a real alarm, but it seems that the handler
5680 isn't always enabled here. This is probably a bug. */
5681 if (input_polling_used ())
5683 /* It could be confusing if a real alarm arrives while processing
5684 the fake one. Turn it off and let the handler reset it. */
5686 input_poll_signal ();
5689 FRAME_SAMPLE_VISIBILITY (f
);
5693 /* Change from mapped state to withdrawn state. */
5695 x_make_frame_invisible (f
)
5701 #ifdef USE_X_TOOLKIT
5702 /* Use the frame's outermost window, not the one we normally draw on. */
5703 window
= XtWindow (f
->display
.x
->widget
);
5704 #else /* not USE_X_TOOLKIT */
5705 window
= FRAME_X_WINDOW (f
);
5706 #endif /* not USE_X_TOOLKIT */
5708 /* Don't keep the highlight on an invisible frame. */
5709 if (x_highlight_frame
== f
)
5710 x_highlight_frame
= 0;
5712 #if 0/* This might add unreliability; I don't trust it -- rms. */
5713 if (! f
->async_visible
&& ! f
->async_iconified
)
5719 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5720 that the current position of the window is user-specified, rather than
5721 program-specified, so that when the window is mapped again, it will be
5722 placed at the same location, without forcing the user to position it
5723 by hand again (they have already done that once for this window.) */
5724 x_wm_set_size_hint (f
, 0, 1);
5728 if (! XWithdrawWindow (x_current_display
, window
,
5729 DefaultScreen (x_current_display
)))
5731 UNBLOCK_INPUT_RESIGNAL
;
5732 error ("Can't notify window manager of window withdrawal");
5734 #else /* ! defined (HAVE_X11R4) */
5737 /* Tell the window manager what we're going to do. */
5738 if (! EQ (Vx_no_window_manager
, Qt
))
5742 unmap
.xunmap
.type
= UnmapNotify
;
5743 unmap
.xunmap
.window
= window
;
5744 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5745 unmap
.xunmap
.from_configure
= False
;
5746 if (! XSendEvent (x_current_display
,
5747 DefaultRootWindow (x_current_display
),
5749 SubstructureRedirectMask
|SubstructureNotifyMask
,
5752 UNBLOCK_INPUT_RESIGNAL
;
5753 error ("Can't notify window manager of withdrawal");
5757 /* Unmap the window ourselves. Cheeky! */
5758 XUnmapWindow (x_current_display
, window
);
5759 #else /* ! defined (HAVE_X11) */
5761 XUnmapWindow (FRAME_X_WINDOW (f
));
5762 if (f
->display
.x
->icon_desc
!= 0)
5763 XUnmapWindow (f
->display
.x
->icon_desc
);
5765 #endif /* ! defined (HAVE_X11) */
5766 #endif /* ! defined (HAVE_X11R4) */
5768 /* We can't distinguish this from iconification
5769 just by the event that we get from the server.
5770 So we can't win using the usual strategy of letting
5771 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5772 and synchronize with the server to make sure we agree. */
5774 FRAME_ICONIFIED_P (f
) = 0;
5775 f
->async_visible
= 0;
5776 f
->async_iconified
= 0;
5783 /* Change window state from mapped to iconified. */
5791 /* Don't keep the highlight on an invisible frame. */
5792 if (x_highlight_frame
== f
)
5793 x_highlight_frame
= 0;
5795 if (f
->async_iconified
)
5798 #ifdef USE_X_TOOLKIT
5801 if (! FRAME_VISIBLE_P (f
))
5803 if (! EQ (Vx_no_window_manager
, Qt
))
5804 x_wm_set_window_state (f
, IconicState
);
5805 /* This was XtPopup, but that did nothing for an iconified frame. */
5806 XtMapWidget (f
->display
.x
->widget
);
5811 result
= XIconifyWindow (x_current_display
,
5812 XtWindow (f
->display
.x
->widget
),
5813 DefaultScreen (x_current_display
));
5817 error ("Can't notify window manager of iconification");
5819 f
->async_iconified
= 1;
5824 #else /* not USE_X_TOOLKIT */
5829 /* Make sure the X server knows where the window should be positioned,
5830 in case the user deiconifies with the window manager. */
5831 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5832 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5834 /* Since we don't know which revision of X we're running, we'll use both
5835 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5837 /* X11R4: send a ClientMessage to the window manager using the
5838 WM_CHANGE_STATE type. */
5842 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5843 message
.xclient
.type
= ClientMessage
;
5844 message
.xclient
.message_type
= Xatom_wm_change_state
;
5845 message
.xclient
.format
= 32;
5846 message
.xclient
.data
.l
[0] = IconicState
;
5848 if (! XSendEvent (x_current_display
,
5849 DefaultRootWindow (x_current_display
),
5851 SubstructureRedirectMask
| SubstructureNotifyMask
,
5854 UNBLOCK_INPUT_RESIGNAL
;
5855 error ("Can't notify window manager of iconification");
5859 /* X11R3: set the initial_state field of the window manager hints to
5861 x_wm_set_window_state (f
, IconicState
);
5863 if (!FRAME_VISIBLE_P (f
))
5865 /* If the frame was withdrawn, before, we must map it. */
5866 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5867 #if 0 /* We don't have subwindows in the icon. */
5868 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5869 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5873 f
->async_iconified
= 1;
5874 #else /* ! defined (HAVE_X11) */
5875 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5877 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
5878 if (f
->display
.x
->icon_desc
!= 0)
5880 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
5883 #endif /* ! defined (HAVE_X11) */
5887 #endif /* not USE_X_TOOLKIT */
5890 /* Destroy the X window of frame F. */
5892 x_destroy_window (f
)
5897 if (f
->display
.x
->icon_desc
!= 0)
5898 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5899 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5900 #ifdef USE_X_TOOLKIT
5901 XtDestroyWidget (f
->display
.x
->widget
);
5902 free_frame_menubar (f
);
5903 #endif /* USE_X_TOOLKIT */
5905 free_frame_faces (f
);
5908 xfree (f
->display
.x
);
5910 if (f
== x_focus_frame
)
5912 if (f
== x_highlight_frame
)
5913 x_highlight_frame
= 0;
5915 if (f
== mouse_face_mouse_frame
)
5917 mouse_face_beg_row
= mouse_face_beg_col
= -1;
5918 mouse_face_end_row
= mouse_face_end_col
= -1;
5919 mouse_face_window
= Qnil
;
5925 /* Manage event queues for X10. */
5929 /* Manage event queues.
5931 This code is only used by the X10 support.
5933 We cannot leave events in the X queue and get them when we are ready
5934 because X does not provide a subroutine to get only a certain kind
5935 of event but not block if there are no queued events of that kind.
5937 Therefore, we must examine events as they come in and copy events
5938 of certain kinds into our private queues.
5940 All ExposeRegion events are put in x_expose_queue.
5941 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5944 /* Write the event *P_XREP into the event queue *QUEUE.
5945 If the queue is full, do nothing, but return nonzero. */
5948 enqueue_event (p_xrep
, queue
)
5949 register XEvent
*p_xrep
;
5950 register struct event_queue
*queue
;
5952 int newindex
= queue
->windex
+ 1;
5953 if (newindex
== EVENT_BUFFER_SIZE
)
5955 if (newindex
== queue
->rindex
)
5957 queue
->xrep
[queue
->windex
] = *p_xrep
;
5958 queue
->windex
= newindex
;
5962 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5963 If *QUEUE is empty, do nothing and return 0. */
5966 dequeue_event (p_xrep
, queue
)
5967 register XEvent
*p_xrep
;
5968 register struct event_queue
*queue
;
5970 if (queue
->windex
== queue
->rindex
)
5972 *p_xrep
= queue
->xrep
[queue
->rindex
++];
5973 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
5978 /* Return the number of events buffered in *QUEUE. */
5981 queue_event_count (queue
)
5982 register struct event_queue
*queue
;
5984 int tem
= queue
->windex
- queue
->rindex
;
5987 return EVENT_BUFFER_SIZE
+ tem
;
5990 /* Return nonzero if mouse input is pending. */
5993 mouse_event_pending_p ()
5995 return queue_event_count (&x_mouse_queue
);
5997 #endif /* HAVE_X11 */
5999 /* Setting window manager hints. */
6003 /* Set the normal size hints for the window manager, for frame F.
6004 FLAGS is the flags word to use--or 0 meaning preserve the flags
6005 that the window now has.
6006 If USER_POSITION is nonzero, we set the USPosition
6007 flag (this is useful when FLAGS is 0). */
6009 x_wm_set_size_hint (f
, flags
, user_position
)
6014 XSizeHints size_hints
;
6016 #ifdef USE_X_TOOLKIT
6019 Dimension widget_width
, widget_height
;
6020 Window window
= XtWindow (f
->display
.x
->widget
);
6021 #else /* not USE_X_TOOLKIT */
6022 Window window
= FRAME_X_WINDOW (f
);
6023 #endif /* not USE_X_TOOLKIT */
6025 /* Setting PMaxSize caused various problems. */
6026 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
6028 flexlines
= f
->height
;
6030 size_hints
.x
= f
->display
.x
->left_pos
;
6031 size_hints
.y
= f
->display
.x
->top_pos
;
6033 #ifdef USE_X_TOOLKIT
6034 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
6035 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
6036 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
6037 size_hints
.height
= widget_height
;
6038 size_hints
.width
= widget_width
;
6039 #else /* not USE_X_TOOLKIT */
6040 size_hints
.height
= PIXEL_HEIGHT (f
);
6041 size_hints
.width
= PIXEL_WIDTH (f
);
6042 #endif /* not USE_X_TOOLKIT */
6044 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
6045 size_hints
.height_inc
= f
->display
.x
->line_height
;
6046 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
6047 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
6050 int base_width
, base_height
;
6051 int min_rows
= 0, min_cols
= 0;
6053 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
6054 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
6056 check_frame_size (f
, &min_rows
, &min_cols
);
6058 /* The window manager uses the base width hints to calculate the
6059 current number of rows and columns in the frame while
6060 resizing; min_width and min_height aren't useful for this
6061 purpose, since they might not give the dimensions for a
6062 zero-row, zero-column frame.
6064 We use the base_width and base_height members if we have
6065 them; otherwise, we set the min_width and min_height members
6066 to the size for a zero x zero frame. */
6069 size_hints
.flags
|= PBaseSize
;
6070 size_hints
.base_width
= base_width
;
6071 size_hints
.base_height
= base_height
;
6072 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
6073 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
6075 size_hints
.min_width
= base_width
;
6076 size_hints
.min_height
= base_height
;
6081 size_hints
.flags
|= flags
;
6084 XSizeHints hints
; /* Sometimes I hate X Windows... */
6085 long supplied_return
;
6089 value
= XGetWMNormalHints (x_current_display
, window
, &hints
,
6092 value
= XGetNormalHints (x_current_display
, window
, &hints
);
6097 if (hints
.flags
& PSize
)
6098 size_hints
.flags
|= PSize
;
6099 if (hints
.flags
& PPosition
)
6100 size_hints
.flags
|= PPosition
;
6101 if (hints
.flags
& USPosition
)
6102 size_hints
.flags
|= USPosition
;
6103 if (hints
.flags
& USSize
)
6104 size_hints
.flags
|= USSize
;
6108 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
6109 size_hints
.flags
|= PWinGravity
;
6113 size_hints
.flags
&= ~ PPosition
;
6114 size_hints
.flags
|= USPosition
;
6116 #endif /* PWinGravity */
6119 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
6121 XSetNormalHints (x_current_display
, window
, &size_hints
);
6125 /* Used for IconicState or NormalState */
6126 x_wm_set_window_state (f
, state
)
6130 #ifdef USE_X_TOOLKIT
6133 XtSetArg (al
[0], XtNinitialState
, state
);
6134 XtSetValues (f
->display
.x
->widget
, al
, 1);
6135 #else /* not USE_X_TOOLKIT */
6136 Window window
= FRAME_X_WINDOW (f
);
6138 f
->display
.x
->wm_hints
.flags
|= StateHint
;
6139 f
->display
.x
->wm_hints
.initial_state
= state
;
6141 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6142 #endif /* not USE_X_TOOLKIT */
6145 x_wm_set_icon_pixmap (f
, icon_pixmap
)
6149 #ifdef USE_X_TOOLKIT
6150 Window window
= XtWindow (f
->display
.x
->widget
);
6152 Window window
= FRAME_X_WINDOW (f
);
6157 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6158 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
6161 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
6163 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6166 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6170 #ifdef USE_X_TOOLKIT
6171 Window window
= XtWindow (f
->display
.x
->widget
);
6173 Window window
= FRAME_X_WINDOW (f
);
6176 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
6177 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
6178 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
6180 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6184 /* Initialization. */
6186 #ifdef USE_X_TOOLKIT
6187 static XrmOptionDescRec emacs_options
[] = {
6188 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6189 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6191 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6192 XrmoptionSepArg
, NULL
},
6193 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6195 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6196 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6197 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6198 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6199 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6200 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6201 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6203 #endif /* USE_X_TOOLKIT */
6206 x_term_init (display_name
, xrm_option
, resource_name
)
6209 char *resource_name
;
6215 #ifndef F_SETOWN_BUG
6217 extern int old_fcntl_owner
;
6218 #endif /* ! defined (F_SETOWN) */
6219 #endif /* F_SETOWN_BUG */
6223 x_focus_frame
= x_highlight_frame
= 0;
6225 #ifdef USE_X_TOOLKIT
6226 argv
= (char **) XtMalloc (7 * sizeof (char *));
6228 argv
[1] = "-display";
6229 argv
[2] = display_name
;
6231 /* Usually `emacs', but not always. */
6232 argv
[4] = resource_name
;
6236 argv
[argc
++] = "-xrm";
6237 argv
[argc
++] = xrm_option
;
6239 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
6240 emacs_options
, XtNumber (emacs_options
),
6243 XtFree ((char *)argv
);
6244 x_current_display
= XtDisplay (Xt_app_shell
);
6246 #else /* not USE_X_TOOLKIT */
6247 x_current_display
= XOpenDisplay (display_name
);
6248 #endif /* not USE_X_TOOLKIT */
6249 if (x_current_display
== 0)
6250 fatal ("X server %s not responding.\n\
6251 Check the DISPLAY environment variable or use \"-d\"\n",
6257 XSetAfterFunction (x_current_display
, x_trace_wire
);
6259 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
6260 + XSTRING (Vsystem_name
)->size
6262 sprintf (x_id_name
, "%s@%s",
6263 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
6266 /* Figure out which modifier bits mean what. */
6267 x_find_modifier_meanings ();
6269 /* Get the scroll bar cursor. */
6270 x_vertical_scroll_bar_cursor
6271 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
6274 /* Watch for PropertyNotify events on the root window; we use them
6275 to figure out when to invalidate our cache of the cut buffers. */
6276 x_watch_cut_buffer_cache ();
6279 if (ConnectionNumber (x_current_display
) != 0)
6280 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
6281 change_input_fd (ConnectionNumber (x_current_display
));
6283 #endif /* ! defined (HAVE_X11) */
6285 #ifndef F_SETOWN_BUG
6287 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
6288 #ifdef F_SETOWN_SOCK_NEG
6289 /* stdin is a socket here */
6290 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
6291 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6292 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
6293 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6294 #endif /* ! defined (F_SETOWN) */
6295 #endif /* F_SETOWN_BUG */
6299 #endif /* ! defined (SIGIO) */
6301 expose_all_windows
= 0;
6303 clear_frame_hook
= XTclear_frame
;
6304 clear_end_of_line_hook
= XTclear_end_of_line
;
6305 ins_del_lines_hook
= XTins_del_lines
;
6306 change_line_highlight_hook
= XTchange_line_highlight
;
6307 insert_glyphs_hook
= XTinsert_glyphs
;
6308 write_glyphs_hook
= XTwrite_glyphs
;
6309 delete_glyphs_hook
= XTdelete_glyphs
;
6310 ring_bell_hook
= XTring_bell
;
6311 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6312 set_terminal_modes_hook
= XTset_terminal_modes
;
6313 update_begin_hook
= XTupdate_begin
;
6314 update_end_hook
= XTupdate_end
;
6315 set_terminal_window_hook
= XTset_terminal_window
;
6316 read_socket_hook
= XTread_socket
;
6317 frame_up_to_date_hook
= XTframe_up_to_date
;
6318 cursor_to_hook
= XTcursor_to
;
6319 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6320 mouse_position_hook
= XTmouse_position
;
6321 frame_rehighlight_hook
= XTframe_rehighlight
;
6322 frame_raise_lower_hook
= XTframe_raise_lower
;
6323 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6324 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6325 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6326 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6328 scroll_region_ok
= 1; /* we'll scroll partial frames */
6329 char_ins_del_ok
= 0; /* just as fast to write the line */
6330 line_ins_del_ok
= 1; /* we'll just blt 'em */
6331 fast_clear_end_of_line
= 1; /* X does this well */
6332 memory_below_frame
= 0; /* we don't remember what scrolls
6336 /* Try to use interrupt input; if we can't, then start polling. */
6337 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6339 /* Note that there is no real way portable across R3/R4 to get the
6340 original error handler. */
6341 XHandleError (x_error_quitter
);
6342 XHandleIOError (x_io_error_quitter
);
6344 /* Disable Window Change signals; they are handled by X events. */
6346 signal (SIGWINCH
, SIG_DFL
);
6347 #endif /* ! defined (SIGWINCH) */
6349 signal (SIGPIPE
, x_connection_closed
);
6355 staticpro (&last_mouse_scroll_bar
);
6356 last_mouse_scroll_bar
= Qnil
;
6357 staticpro (&mouse_face_window
);
6358 mouse_face_window
= Qnil
;
6360 #endif /* ! defined (HAVE_X11) */
6361 #endif /* ! defined (HAVE_X_WINDOWS) */