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>
56 #else /* ! defined (BSD) */
60 #endif /* ! defined (BSD) */
65 #ifndef INCLUDED_FCNTL
72 #include <sys/param.h>
74 #include "dispextern.h"
75 #include "termhooks.h"
89 extern XtAppContext Xt_app_con
;
90 extern Widget Xt_app_shell
;
91 extern void free_frame_menubar ();
92 extern void _XEditResCheckMessages ();
93 #endif /* USE_X_TOOLKIT */
96 #define x_any_window_to_frame x_window_to_frame
97 #define x_top_window_to_frame x_window_to_frame
101 #ifndef XtNinitialState
102 #define XtNinitialState "initialState"
107 #define XMapWindow XMapRaised /* Raise them when mapping. */
108 #else /* ! defined (HAVE_X11) */
109 #include <X/Xkeyboard.h>
110 /*#include <X/Xproto.h> */
111 #endif /* ! defined (HAVE_X11) */
114 /* We could get this from param.h, but better not to depend on finding that.
115 And better not to risk that it might define other symbols used in this
118 #define MAXDESC FD_SETSIZE
122 #define SELECT_TYPE fd_set
123 #else /* no FD_SET */
125 #define SELECT_TYPE int
127 /* Define the macros to access a single-int bitmap of descriptors. */
128 #define FD_SET(n, p) (*(p) |= (1 << (n)))
129 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
130 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
131 #define FD_ZERO(p) (*(p) = 0)
132 #endif /* no FD_SET */
134 /* For sending Meta-characters. Do we need this? */
137 #define min(a,b) ((a)<(b) ? (a) : (b))
138 #define max(a,b) ((a)>(b) ? (a) : (b))
140 /* Nonzero means we must reprint all windows
141 because 1) we received an ExposeWindow event
142 or 2) we received too many ExposeRegion events to record.
144 This is never needed under X11. */
145 static int expose_all_windows
;
147 /* Nonzero means we must reprint all icon windows. */
149 static int expose_all_icons
;
152 /* ExposeRegion events, when received, are copied into this queue
153 for later processing. */
155 static struct event_queue x_expose_queue
;
157 /* ButtonPress and ButtonReleased events, when received,
158 are copied into this queue for later processing. */
160 struct event_queue x_mouse_queue
;
161 #endif /* HAVE_X11 */
163 #if defined (SIGIO) && defined (FIONREAD)
164 int BLOCK_INPUT_mask
;
165 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
167 /* The id of a bitmap used for icon windows.
168 One such map is shared by all Emacs icon windows.
169 This is zero if we have not yet had a need to create the bitmap. */
171 static Bitmap icon_bitmap
;
173 /* Font used for text icons. */
175 static FONT_TYPE
*icon_font_info
;
177 /* Stuff for dealing with the main icon title. */
179 extern Lisp_Object Vcommand_line_args
;
180 char *hostname
, *x_id_name
;
182 /* Initial values of argv and argc. */
183 extern char **initial_argv
;
184 extern int initial_argc
;
186 /* This is the X connection that we are using. */
188 Display
*x_current_display
;
190 /* The cursor to use for vertical scroll bars on x_current_display. */
191 static Cursor x_vertical_scroll_bar_cursor
;
193 /* Frame being updated by update_frame. This is declared in term.c.
194 This is set by update_begin and looked at by all the
195 XT functions. It is zero while not inside an update.
196 In that case, the XT functions assume that `selected_frame'
197 is the frame to apply to. */
198 extern struct frame
*updating_frame
;
200 /* The frame (if any) which has the X window that has keyboard focus.
201 Zero if none. This is examined by Ffocus_frame in frame.c. Note
202 that a mere EnterNotify event can set this; if you need to know the
203 last frame specified in a FocusIn or FocusOut event, use
204 x_focus_event_frame. */
205 struct frame
*x_focus_frame
;
207 /* This is a frame waiting to be autoraised, within XTread_socket. */
208 struct frame
*pending_autoraise_frame
;
210 /* The last frame mentioned in a FocusIn or FocusOut event. This is
211 separate from x_focus_frame, because whether or not LeaveNotify
212 events cause us to lose focus depends on whether or not we have
213 received a FocusIn event for it. */
214 struct frame
*x_focus_event_frame
;
216 /* The frame which currently has the visual highlight, and should get
217 keyboard input (other sorts of input have the frame encoded in the
218 event). It points to the X focus frame's selected window's
219 frame. It differs from x_focus_frame when we're using a global
221 static struct frame
*x_highlight_frame
;
223 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
224 mouse is moved to inside of frame when frame is de-iconified. */
226 static int warp_mouse_on_deiconify
;
228 /* During an update, maximum vpos for ins/del line operations to affect. */
230 static int flexlines
;
232 /* During an update, nonzero if chars output now should be highlighted. */
234 static int highlight
;
236 /* Nominal cursor position -- where to draw output.
237 During an update, these are different from the cursor-box position. */
244 In order to avoid asking for motion events and then throwing most
245 of them away or busy-polling the server for mouse positions, we ask
246 the server for pointer motion hints. This means that we get only
247 one event per group of mouse movements. "Groups" are delimited by
248 other kinds of events (focus changes and button clicks, for
249 example), or by XQueryPointer calls; when one of these happens, we
250 get another MotionNotify event the next time the mouse moves. This
251 is at least as efficient as getting motion events when mouse
252 tracking is on, and I suspect only negligibly worse when tracking
255 The silly O'Reilly & Associates Nutshell guides barely document
256 pointer motion hints at all (I think you have to infer how they
257 work from an example), and the description of XQueryPointer doesn't
258 mention that calling it causes you to get another motion hint from
259 the server, which is very important. */
261 /* Where the mouse was last time we reported a mouse event. */
262 static FRAME_PTR last_mouse_frame
;
263 static XRectangle last_mouse_glyph
;
265 /* The scroll bar in which the last X motion event occurred.
267 If the last X motion event occurred in a scroll bar, we set this
268 so XTmouse_position can know whether to report a scroll bar motion or
271 If the last X motion event didn't occur in a scroll bar, we set this
272 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
273 static Lisp_Object last_mouse_scroll_bar
;
275 /* Record which buttons are currently pressed. */
276 unsigned int x_mouse_grabbed
;
278 /* This is a hack. We would really prefer that XTmouse_position would
279 return the time associated with the position it returns, but there
280 doesn't seem to be any way to wrest the timestamp from the server
281 along with the position query. So, we just keep track of the time
282 of the last movement we received, and return that in hopes that
283 it's somewhat accurate. */
284 static Time last_mouse_movement_time
;
286 /* These variables describe the range of text currently shown
287 in its mouse-face, together with the window they apply to.
288 As long as the mouse stays within this range, we need not
289 redraw anything on its account. */
290 static int mouse_face_beg_row
, mouse_face_beg_col
;
291 static int mouse_face_end_row
, mouse_face_end_col
;
292 static int mouse_face_past_end
;
293 static Lisp_Object mouse_face_window
;
294 static int mouse_face_face_id
;
296 /* 1 if a mouse motion event came and we didn't handle it right away because
297 gc was in progress. */
298 static int mouse_face_deferred_gc
;
300 /* FRAME and X, Y position of mouse when last checked for
301 highlighting. X and Y can be negative or out of range for the frame. */
302 static FRAME_PTR mouse_face_mouse_frame
;
303 static int mouse_face_mouse_x
, mouse_face_mouse_y
;
305 /* Nonzero means defer mouse-motion highlighting. */
306 static int mouse_face_defer
;
309 /* `t' if a mouse button is depressed. */
311 extern Lisp_Object Vmouse_depressed
;
313 /* Tells if a window manager is present or not. */
315 extern Lisp_Object Vx_no_window_manager
;
317 /* Timestamp that we requested selection data was made. */
318 extern Time requestor_time
;
320 /* ID of the window requesting selection data. */
321 extern Window requestor_window
;
323 /* Nonzero enables some debugging for the X interface code. */
326 extern Lisp_Object Qface
, Qmouse_face
;
328 #else /* ! defined (HAVE_X11) */
330 /* Bit patterns for the mouse cursor. */
332 short MouseCursor
[] = {
333 0x0000, 0x0008, 0x0018, 0x0038,
334 0x0078, 0x00f8, 0x01f8, 0x03f8,
335 0x07f8, 0x00f8, 0x00d8, 0x0188,
336 0x0180, 0x0300, 0x0300, 0x0000};
338 short MouseMask
[] = {
339 0x000c, 0x001c, 0x003c, 0x007c,
340 0x00fc, 0x01fc, 0x03fc, 0x07fc,
341 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
342 0x03cc, 0x0780, 0x0780, 0x0300};
344 static short grey_bits
[] = {
345 0x0005, 0x000a, 0x0005, 0x000a};
347 static Pixmap GreyPixmap
= 0;
348 #endif /* ! defined (HAVE_X11) */
350 /* From time to time we get info on an Emacs window, here. */
352 static WINDOWINFO_TYPE windowinfo
;
356 /* A mask of extra modifier bits to put into every keyboard char. */
357 extern int extra_keyboard_modifiers
;
359 extern Display
*XOpenDisplay ();
360 extern Window
XCreateWindow ();
362 extern Cursor
XCreateCursor ();
363 extern FONT_TYPE
*XOpenFont ();
365 static void flashback ();
366 static void redraw_previous_char ();
367 static void redraw_following_char ();
368 static unsigned int x_x_to_emacs_modifiers ();
370 static int fast_find_position ();
371 static void note_mouse_highlight ();
372 static void clear_mouse_face ();
373 static void show_mouse_face ();
376 static void dumpqueue ();
377 #endif /* HAVE_X11 */
380 static int XTcursor_to ();
381 static int XTclear_end_of_line ();
384 /* Starting and ending updates.
386 These hooks are called by update_frame at the beginning and end
387 of a frame update. We record in `updating_frame' the identity
388 of the frame being updated, so that the XT... functions do not
389 need to take a frame as argument. Most of the XT... functions
390 should never be called except during an update, the only exceptions
391 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
393 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
404 flexlines
= f
->height
;
409 if (f
== mouse_face_mouse_frame
)
411 /* Don't do highlighting for mouse motion during the update. */
412 mouse_face_defer
= 1;
413 if (!NILP (mouse_face_window
))
415 int firstline
, lastline
, i
;
416 struct window
*w
= XWINDOW (mouse_face_window
);
418 /* Find the first, and the last+1, lines affected by redisplay. */
419 for (firstline
= 0; firstline
< f
->height
; firstline
++)
420 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
423 lastline
= f
->height
;
424 for (i
= f
->height
- 1; i
>= 0; i
--)
426 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
432 /* Can we tell that this update does not affect the window
433 where the mouse highlight is? If so, no need to turn off. */
434 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
435 || lastline
< XFASTINT (w
->top
)))
436 /* Otherwise turn off the mouse highlight now. */
442 #endif /* HAVE_X11 */
447 static void x_do_pending_expose ();
459 x_do_pending_expose ();
460 #endif /* HAVE_X11 */
462 x_display_cursor (f
, 1);
464 if (f
== mouse_face_mouse_frame
)
465 mouse_face_defer
= 0;
467 /* This fails in the case of having updated only the echo area
468 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
469 has no relation to the current contents, and its charstarts
470 have no relation to the contents of the window-buffer.
471 I don't know a clean way to check
472 for that case. window_end_valid isn't set up yet. */
473 if (f
== mouse_face_mouse_frame
)
474 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
481 /* This is called after a redisplay on frame F. */
484 XTframe_up_to_date (f
)
487 if (mouse_face_deferred_gc
|| f
== mouse_face_mouse_frame
)
489 note_mouse_highlight (mouse_face_mouse_frame
,
490 mouse_face_mouse_x
, mouse_face_mouse_y
);
491 mouse_face_deferred_gc
= 0;
495 /* External interface to control of standout mode.
496 Call this when about to modify line at position VPOS
497 and not change whether it is highlighted. */
499 XTreassert_line_highlight (new, vpos
)
505 /* Call this when about to modify line at position VPOS
506 and change whether it is highlighted. */
509 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
510 int new_highlight
, vpos
, first_unused_hpos
;
512 highlight
= new_highlight
;
513 XTcursor_to (vpos
, 0);
514 XTclear_end_of_line (updating_frame
->width
);
517 /* This is used when starting Emacs and when restarting after suspend.
518 When starting Emacs, no X window is mapped. And nothing must be done
519 to Emacs's own window if it is suspended (though that rarely happens). */
522 XTset_terminal_modes ()
526 /* This is called when exiting or suspending Emacs.
527 Exiting will make the X-windows go away, and suspending
528 requires no action. */
531 XTreset_terminal_modes ()
533 /* XTclear_frame (); */
536 /* Set the nominal cursor position of the frame.
537 This is where display update commands will take effect.
538 This does not affect the place where the cursor-box is displayed. */
541 XTcursor_to (row
, col
)
542 register int row
, col
;
550 if (updating_frame
== 0)
553 x_display_cursor (selected_frame
, 1);
559 /* Display a sequence of N glyphs found at GP.
560 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
561 HL is 1 if this text is highlighted, 2 if the cursor is on it,
562 3 if should appear in its mouse-face.
563 JUST_FOREGROUND if 1 means draw only the foreground;
564 don't alter the background.
566 FONT is the default font to use (for glyphs whose font-code is 0).
568 Since the display generation code is responsible for calling
569 compute_char_face and compute_glyph_face on everything it puts in
570 the display structure, we can assume that the face code on each
571 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
572 to which we can actually apply intern_face.
573 Call this function with input blocked. */
576 /* This is the multi-face code. */
579 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
582 register GLYPH
*gp
; /* Points to first GLYPH. */
583 register int n
; /* Number of glyphs to display. */
587 /* Holds characters to be displayed. */
588 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
589 register char *cp
; /* Steps through buf[]. */
590 register int tlen
= GLYPH_TABLE_LENGTH
;
591 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
592 Window window
= FRAME_X_WINDOW (f
);
593 int orig_left
= left
;
597 /* Get the face-code of the next GLYPH. */
601 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
602 cf
= FAST_GLYPH_FACE (g
);
604 /* Find the run of consecutive glyphs with the same face-code.
605 Extract their character codes into BUF. */
610 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
611 if (FAST_GLYPH_FACE (g
) != cf
)
614 *cp
++ = FAST_GLYPH_CHAR (g
);
619 /* LEN gets the length of the run. */
622 /* Now output this run of chars, with the font and pixel values
623 determined by the face code CF. */
625 struct face
*face
= FRAME_DEFAULT_FACE (f
);
626 FONT_TYPE
*font
= FACE_FONT (face
);
627 GC gc
= FACE_GC (face
);
628 int gc_temporary
= 0;
630 /* HL = 3 means use a mouse face previously chosen. */
632 cf
= mouse_face_face_id
;
634 /* First look at the face of the text itself. */
637 /* It's possible for the display table to specify
638 a face code that is out of range. Use 0 in that case. */
639 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
640 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
644 face
= FRAME_MODE_LINE_FACE (f
);
646 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
647 font
= FACE_FONT (face
);
651 /* Then comes the distinction between modeline and normal text. */
656 face
= FRAME_MODE_LINE_FACE (f
);
657 font
= FACE_FONT (face
);
661 #define FACE_DEFAULT (~0)
663 /* Now override that if the cursor's on this character. */
667 || (int) face
->font
== FACE_DEFAULT
)
669 gc
= f
->display
.x
->cursor_gc
;
671 /* Cursor on non-default face: must merge. */
677 xgcv
.background
= f
->display
.x
->cursor_pixel
;
678 if (face
== FRAME_DEFAULT_FACE (f
))
679 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
681 xgcv
.foreground
= face
->background
;
682 /* If the glyph would be invisible,
683 try a different foreground. */
684 if (xgcv
.foreground
== xgcv
.background
)
685 xgcv
.foreground
= face
->foreground
;
686 if (xgcv
.foreground
== xgcv
.background
)
687 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
688 if (xgcv
.foreground
== xgcv
.background
)
689 xgcv
.foreground
= face
->foreground
;
690 /* Make sure the cursor is distinct from text in this face. */
691 if (xgcv
.background
== face
->background
692 && xgcv
.foreground
== face
->foreground
)
694 xgcv
.background
= face
->foreground
;
695 xgcv
.foreground
= face
->background
;
697 xgcv
.font
= face
->font
->fid
;
698 xgcv
.graphics_exposures
= 0;
699 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
700 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
703 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
704 XSetStipple (x_current_display
, gc
, face
->stipple
);
710 if ((int) font
== FACE_DEFAULT
)
711 font
= f
->display
.x
->font
;
714 XDrawString (x_current_display
, window
, gc
,
715 left
, top
+ FONT_BASE (font
), buf
, len
);
718 XDrawImageString (x_current_display
, window
, gc
,
719 left
, top
+ FONT_BASE (font
), buf
, len
);
720 /* Clear the rest of the line's height. */
721 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
722 XClearArea (x_current_display
, window
, left
,
723 top
+ FONT_HEIGHT (font
),
724 FONT_WIDTH (font
) * len
,
725 /* This is how many pixels of height
727 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
731 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
732 which often is not up to date yet. */
733 if (!just_foreground
)
735 if (left
== orig_left
)
736 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
737 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
739 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
740 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
745 XFreeGC (x_current_display
, gc
);
747 /* We should probably check for XA_UNDERLINE_POSITION and
748 XA_UNDERLINE_THICKNESS properties on the font, but let's
749 just get the thing working, and come back to that. */
751 int underline_position
= 1;
753 if (font
->descent
<= underline_position
)
754 underline_position
= font
->descent
- 1;
757 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
761 + underline_position
),
762 len
* FONT_WIDTH (font
), 1);
765 left
+= len
* FONT_WIDTH (font
);
772 /* This is the old single-face code. */
775 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
778 register GLYPH
*gp
; /* Points to first GLYPH. */
779 register int n
; /* Number of glyphs to display. */
784 Window window
= FRAME_X_WINDOW (f
);
785 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
786 : (hl
? f
->display
.x
->reverse_gc
787 : f
->display
.x
->normal_gc
));
789 if (sizeof (GLYPH
) == sizeof (XChar2b
))
790 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
791 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
792 else if (sizeof (GLYPH
) == sizeof (unsigned char))
793 XDrawImageString (x_current_display
, window
, drawing_gc
,
794 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
796 /* What size of glyph ARE you using? And does X have a function to
802 /* Output some text at the nominal frame cursor position.
803 Advance the cursor over the text.
804 Output LEN glyphs at START.
806 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
807 controls the pixel values used for foreground and background. */
810 XTwrite_glyphs (start
, len
)
811 register GLYPH
*start
;
814 register int temp_length
;
824 /* If not within an update,
825 output at the frame's visible cursor. */
826 curs_x
= f
->cursor_x
;
827 curs_y
= f
->cursor_y
;
831 CHAR_TO_PIXEL_COL (f
, curs_x
),
832 CHAR_TO_PIXEL_ROW (f
, curs_y
),
833 start
, len
, highlight
, 0);
835 /* If we drew on top of the cursor, note that it is turned off. */
836 if (curs_y
== f
->phys_cursor_y
837 && curs_x
<= f
->phys_cursor_x
838 && curs_x
+ len
> f
->phys_cursor_x
)
839 f
->phys_cursor_x
= -1;
841 if (updating_frame
== 0)
844 x_display_cursor (f
, 1);
853 /* Clear to the end of the line.
854 Erase the current text line from the nominal cursor position (inclusive)
855 to column FIRST_UNUSED (exclusive). The idea is that everything
856 from FIRST_UNUSED onward is already erased. */
859 XTclear_end_of_line (first_unused
)
860 register int first_unused
;
862 struct frame
*f
= updating_frame
;
868 if (curs_y
< 0 || curs_y
>= f
->height
)
870 if (first_unused
<= 0)
873 if (first_unused
>= f
->width
)
874 first_unused
= f
->width
;
878 /* Notice if the cursor will be cleared by this operation. */
879 if (curs_y
== f
->phys_cursor_y
880 && curs_x
<= f
->phys_cursor_x
881 && f
->phys_cursor_x
< first_unused
)
882 f
->phys_cursor_x
= -1;
885 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
886 CHAR_TO_PIXEL_COL (f
, curs_x
),
887 CHAR_TO_PIXEL_ROW (f
, curs_y
),
888 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
889 f
->display
.x
->line_height
, False
);
891 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
893 #else /* ! defined (HAVE_X11) */
894 XPixSet (FRAME_X_WINDOW (f
),
895 CHAR_TO_PIXEL_COL (f
, curs_x
),
896 CHAR_TO_PIXEL_ROW (f
, curs_y
),
897 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
898 f
->display
.x
->line_height
,
899 f
->display
.x
->background_pixel
);
900 #endif /* ! defined (HAVE_X11) */
909 struct frame
*f
= updating_frame
;
914 f
->phys_cursor_x
= -1; /* Cursor not visible. */
915 curs_x
= 0; /* Nominal cursor position is top left. */
920 XClear (FRAME_X_WINDOW (f
));
922 /* We have to clear the scroll bars, too. If we have changed
923 colors or something like that, then they should be notified. */
924 x_scroll_bar_clear (f
);
928 #endif /* HAVE_X11 */
935 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
936 always contain the right glyphs to use.
938 It also needs to be changed to look at the details of the font and
939 see whether there is really overlap, and do nothing when there is
940 not. This can use font_char_overlap_left and font_char_overlap_right,
941 but just how to use them is not clear. */
943 /* Erase the character (if any) at the position just before X, Y in frame F,
944 then redraw it and the character before it.
945 This is necessary when we erase starting at X,
946 in case the character after X overlaps into the one before X.
947 Call this function with input blocked. */
950 redraw_previous_char (f
, x
, y
, highlight_flag
)
955 /* Erase the character before the new ones, in case
956 what was here before overlaps it.
957 Reoutput that character, and the previous character
958 (in case the previous character overlaps it). */
964 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
965 CHAR_TO_PIXEL_COL (f
, x
- 1),
966 CHAR_TO_PIXEL_ROW (f
, y
),
967 FONT_WIDTH (f
->display
.x
->font
),
968 f
->display
.x
->line_height
, False
);
970 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
971 CHAR_TO_PIXEL_ROW (f
, y
),
972 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
973 x
- start_x
, highlight_flag
, 1);
977 /* Erase the character (if any) at the position X, Y in frame F,
978 then redraw it and the character after it.
979 This is necessary when we erase endng at X,
980 in case the character after X overlaps into the one before X.
981 Call this function with input blocked. */
984 redraw_following_char (f
, x
, y
, highlight_flag
)
989 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
990 /* Erase the character after the new ones, in case
991 what was here before overlaps it.
992 Reoutput that character, and the following character
993 (in case the following character overlaps it). */
995 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1000 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1001 CHAR_TO_PIXEL_COL (f
, x
),
1002 CHAR_TO_PIXEL_ROW (f
, y
),
1003 FONT_WIDTH (f
->display
.x
->font
),
1004 f
->display
.x
->line_height
, False
);
1006 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1007 CHAR_TO_PIXEL_ROW (f
, y
),
1008 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1009 end_x
- x
, highlight_flag
, 1);
1014 #if 0 /* Not in use yet */
1016 /* Return 1 if character C in font F extends past its left edge. */
1019 font_char_overlap_left (font
, c
)
1025 /* Find the bounding-box info for C. */
1026 if (font
->per_char
== 0)
1027 s
= &font
->max_bounds
;
1030 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1033 /* Decode char into row number (byte 1) and code within row (byte 2). */
1036 if (!(within
>= font
->min_char_or_byte2
1037 && within
<= font
->max_char_or_byte2
1038 && row
>= font
->min_byte1
1039 && row
<= font
->max_byte1
))
1041 /* If char is out of range, try the font's default char instead. */
1042 c
= font
->default_char
;
1043 row
= c
>> (INTBITS
- 8);
1046 if (!(within
>= font
->min_char_or_byte2
1047 && within
<= font
->max_char_or_byte2
1048 && row
>= font
->min_byte1
1049 && row
<= font
->max_byte1
))
1050 /* Still out of range means this char does not overlap. */
1053 /* We found the info for this char. */
1054 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1058 return (s
&& s
->lbearing
< 0);
1061 /* Return 1 if character C in font F extends past its right edge. */
1064 font_char_overlap_right (font
, c
)
1070 /* Find the bounding-box info for C. */
1071 if (font
->per_char
== 0)
1072 s
= &font
->max_bounds
;
1075 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1078 /* Decode char into row number (byte 1) and code within row (byte 2). */
1081 if (!(within
>= font
->min_char_or_byte2
1082 && within
<= font
->max_char_or_byte2
1083 && row
>= font
->min_byte1
1084 && row
<= font
->max_byte1
))
1086 /* If char is out of range, try the font's default char instead. */
1087 c
= font
->default_char
;
1088 row
= c
>> (INTBITS
- 8);
1091 if (!(within
>= font
->min_char_or_byte2
1092 && within
<= font
->max_char_or_byte2
1093 && row
>= font
->min_byte1
1094 && row
<= font
->max_byte1
))
1095 /* Still out of range means this char does not overlap. */
1098 /* We found the info for this char. */
1099 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1103 return (s
&& s
->rbearing
>= s
->width
);
1107 /* Invert the middle quarter of the frame for .15 sec. */
1109 /* We use the select system call to do the waiting, so we have to make sure
1110 it's available. If it isn't, we just won't do visual bells. */
1111 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1113 /* Subtract the `struct timeval' values X and Y,
1114 storing the result in RESULT.
1115 Return 1 if the difference is negative, otherwise 0. */
1118 timeval_subtract (result
, x
, y
)
1119 struct timeval
*result
, x
, y
;
1121 /* Perform the carry for the later subtraction by updating y.
1122 This is safer because on some systems
1123 the tv_sec member is unsigned. */
1124 if (x
.tv_usec
< y
.tv_usec
)
1126 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1127 y
.tv_usec
-= 1000000 * nsec
;
1130 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1132 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1133 y
.tv_usec
+= 1000000 * nsec
;
1137 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1138 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1139 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1141 /* Return indication of whether the result should be considered negative. */
1142 return x
.tv_sec
< y
.tv_sec
;
1153 /* Create a GC that will use the GXxor function to flip foreground pixels
1154 into background pixels. */
1158 values
.function
= GXxor
;
1159 values
.foreground
= (f
->display
.x
->foreground_pixel
1160 ^ f
->display
.x
->background_pixel
);
1162 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
1163 GCFunction
| GCForeground
, &values
);
1167 int width
= PIXEL_WIDTH (f
);
1168 int height
= PIXEL_HEIGHT (f
);
1170 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1171 width
/4, height
/4, width
/2, height
/2);
1172 XFlush (x_current_display
);
1175 struct timeval wakeup
, now
;
1177 EMACS_GET_TIME (wakeup
);
1179 /* Compute time to wait until, propagating carry from usecs. */
1180 wakeup
.tv_usec
+= 150000;
1181 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1182 wakeup
.tv_usec
%= 1000000;
1184 /* Keep waiting until past the time wakeup. */
1187 struct timeval timeout
;
1189 EMACS_GET_TIME (timeout
);
1191 /* In effect, timeout = wakeup - timeout.
1192 Break if result would be negative. */
1193 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1196 /* Try to wait that long--but we might wake up sooner. */
1197 select (0, 0, 0, 0, &timeout
);
1201 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1202 width
/4, height
/4, width
/2, height
/2);
1203 XFreeGC (x_current_display
, gc
);
1204 XFlush (x_current_display
);
1214 /* Make audible bell. */
1217 #define XRINGBELL XBell (x_current_display, 0)
1218 #else /* ! defined (HAVE_X11) */
1219 #define XRINGBELL XFeep (0);
1220 #endif /* ! defined (HAVE_X11) */
1224 if (x_current_display
== 0)
1227 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1229 XTflash (selected_frame
);
1240 /* Insert and delete character.
1241 These are not supposed to be used because we are supposed to turn
1242 off the feature of using them. */
1245 XTinsert_glyphs (start
, len
)
1246 register char *start
;
1259 /* Specify how many text lines, from the top of the window,
1260 should be affected by insert-lines and delete-lines operations.
1261 This, and those operations, are used only within an update
1262 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1265 XTset_terminal_window (n
)
1268 if (updating_frame
== 0)
1271 if ((n
<= 0) || (n
> updating_frame
->height
))
1272 flexlines
= updating_frame
->height
;
1277 /* Perform an insert-lines operation.
1278 Insert N lines at a vertical position curs_y. */
1284 register int topregion
, bottomregion
;
1285 register int length
, newtop
, mask
;
1286 register struct frame
*f
= updating_frame
;
1287 int intborder
= f
->display
.x
->internal_border_width
;
1289 if (curs_y
>= flexlines
)
1293 bottomregion
= flexlines
- (n
+ 1);
1294 newtop
= topregion
+ n
;
1295 length
= (bottomregion
- topregion
) + 1;
1299 #endif /* HAVE_X11 */
1301 if ((length
> 0) && (newtop
<= flexlines
))
1304 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1305 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1306 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1307 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1308 length
* f
->display
.x
->line_height
, intborder
,
1309 CHAR_TO_PIXEL_ROW (f
, newtop
));
1310 #else /* ! defined (HAVE_X11) */
1311 XMoveArea (FRAME_X_WINDOW (f
),
1312 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1313 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1314 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1315 length
* f
->display
.x
->line_height
);
1316 /* Now we must process any ExposeRegion events that occur
1317 if the area being copied from is obscured.
1318 We can't let it wait because further i/d operations
1319 may want to copy this area to another area. */
1321 #endif /* ! defined (HAVE_X11) */
1324 newtop
= min (newtop
, (flexlines
- 1));
1325 length
= newtop
- topregion
;
1329 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1330 CHAR_TO_PIXEL_ROW (f
, topregion
),
1331 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1332 n
* f
->display
.x
->line_height
, False
);
1333 #else /* ! defined (HAVE_X11) */
1334 XPixSet (FRAME_X_WINDOW (f
),
1336 CHAR_TO_PIXEL_ROW (f
, topregion
),
1337 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1338 n
* f
->display
.x
->line_height
,
1339 f
->display
.x
->background_pixel
);
1340 #endif /* ! defined (HAVE_X11) */
1344 /* Perform a delete-lines operation, deleting N lines
1345 at a vertical position curs_y. */
1352 register struct frame
*f
= updating_frame
;
1353 int intborder
= f
->display
.x
->internal_border_width
;
1355 if (curs_y
>= flexlines
)
1360 #endif /* HAVE_X11 */
1362 if ((curs_y
+ n
) >= flexlines
)
1364 if (flexlines
>= (curs_y
+ 1))
1367 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1368 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1369 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1370 (flexlines
- curs_y
) * f
->display
.x
->line_height
, False
);
1371 #else /* ! defined (HAVE_X11) */
1372 XPixSet (FRAME_X_WINDOW (f
),
1373 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1374 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1375 (flexlines
- curs_y
) * f
->display
.x
->line_height
,
1376 f
->display
.x
->background_pixel
);
1377 #endif /* ! defined (HAVE_X11) */
1383 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1384 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1386 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1387 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1388 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
,
1389 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1390 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1392 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1393 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1394 n
* f
->display
.x
->line_height
, False
);
1395 #else /* ! defined (HAVE_X11) */
1396 XMoveArea (FRAME_X_WINDOW (f
),
1398 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1399 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1400 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1401 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
);
1402 /* Now we must process any ExposeRegion events that occur
1403 if the area being copied from is obscured.
1404 We can't let it wait because further i/d operations
1405 may want to copy this area to another area. */
1407 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1408 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1409 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1410 n
* f
->display
.x
->line_height
, f
->display
.x
->background_pixel
);
1411 #endif /* ! defined (HAVE_X11) */
1415 /* Perform an insert-lines or delete-lines operation,
1416 inserting N lines or deleting -N lines at vertical position VPOS. */
1418 XTins_del_lines (vpos
, n
)
1421 if (updating_frame
== 0)
1424 /* Hide the cursor. */
1425 x_display_cursor (updating_frame
, 0);
1427 XTcursor_to (vpos
, 0);
1438 /* Support routines for exposure events. */
1439 static void clear_cursor ();
1441 /* Output into a rectangle of an X-window (for frame F)
1442 the characters in f->phys_lines that overlap that rectangle.
1443 TOP and LEFT are the position of the upper left corner of the rectangle.
1444 ROWS and COLS are the size of the rectangle.
1445 Call this function with input blocked. */
1448 dumprectangle (f
, left
, top
, cols
, rows
)
1450 register int left
, top
, cols
, rows
;
1452 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1453 int cursor_cleared
= 0;
1457 if (FRAME_GARBAGED_P (f
))
1460 /* Express rectangle as four edges, instead of position-and-size. */
1461 bottom
= top
+ rows
;
1462 right
= left
+ cols
;
1464 #ifndef HAVE_X11 /* Window manger does this for X11. */
1466 int intborder
= f
->display
.x
->internal_border_width
;
1468 /* If the rectangle includes any of the internal border area,
1469 redisplay the border emphasis. */
1470 if (top
< intborder
|| left
< intborder
1471 || bottom
> intborder
+ f
->height
* f
->display
.x
->line_height
1472 || right
> intborder
+ f
->width
* f
->display
.x
->line_height
)
1475 #endif /* not HAVE_X11 Window manger does this for X11. */
1477 /* Convert rectangle edges in pixels to edges in chars.
1478 Round down for left and top, up for right and bottom. */
1479 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1480 left
= PIXEL_TO_CHAR_COL (f
, left
);
1481 bottom
+= (f
->display
.x
->line_height
- 1);
1482 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1483 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1484 right
= PIXEL_TO_CHAR_COL (f
, right
);
1486 /* Clip the rectangle to what can be visible. */
1491 if (right
> f
->width
)
1493 if (bottom
> f
->height
)
1496 /* Get size in chars of the rectangle. */
1497 cols
= right
- left
;
1498 rows
= bottom
- top
;
1500 /* If rectangle has zero area, return. */
1501 if (rows
<= 0) return;
1502 if (cols
<= 0) return;
1504 /* Turn off the cursor if it is in the rectangle.
1505 We will turn it back on afterward. */
1506 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1507 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1513 /* Display the text in the rectangle, one text line at a time. */
1515 for (y
= top
; y
< bottom
; y
++)
1517 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1519 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1523 CHAR_TO_PIXEL_COL (f
, left
),
1524 CHAR_TO_PIXEL_ROW (f
, y
),
1525 line
, min (cols
, active_frame
->used
[y
] - left
),
1526 active_frame
->highlight
[y
], 0);
1529 /* Turn the cursor on if we turned it off. */
1532 x_display_cursor (f
, 1);
1536 /* Process all queued ExposeRegion events. */
1542 XExposeRegionEvent r
;
1544 while (dequeue_event (&r
, &x_expose_queue
))
1546 struct frame
*f
= x_window_to_frame (r
.window
);
1547 if (f
->display
.x
->icon_desc
== r
.window
)
1550 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1554 #endif /* HAVE_X11 */
1556 /* Process all expose events that are pending, for X10.
1557 Redraws the cursor if necessary on any frame that
1558 is not in the process of being updated with update_frame. */
1562 x_do_pending_expose ()
1566 Lisp_Object tail
, frame
;
1568 if (expose_all_windows
)
1570 expose_all_windows
= 0;
1571 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1573 register int temp_width
, temp_height
;
1576 frame
= XCONS (tail
)->car
;
1577 if (XGCTYPE (frame
) != Lisp_Frame
)
1580 if (! FRAME_X_P (f
))
1582 if (!f
->async_visible
)
1584 if (!f
->display
.x
->needs_exposure
)
1587 intborder
= f
->display
.x
->internal_border_width
;
1590 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1591 temp_width
= ((windowinfo
.width
- 2 * intborder
1592 - f
->display
.x
->v_scroll_bar_width
)
1593 / FONT_WIDTH (f
->display
.x
->font
));
1594 temp_height
= ((windowinfo
.height
- 2 * intborder
1595 - f
->display
.x
->h_scroll_bar_height
)
1596 / f
->display
.x
->line_height
);
1597 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1599 change_frame_size (f
, max (1, temp_height
),
1600 max (1, temp_width
), 0, 1);
1601 x_resize_scroll_bars (f
);
1603 f
->display
.x
->left_pos
= windowinfo
.x
;
1604 f
->display
.x
->top_pos
= windowinfo
.y
;
1605 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1609 f
->display
.x
->needs_exposure
= 0;
1610 if (updating_frame
!= f
)
1611 x_display_cursor (f
, 1);
1616 /* Handle any individual-rectangle expose events queued
1617 for various windows. */
1620 #else /* ! defined (HAVE_X11) */
1622 #endif /* ! defined (HAVE_X11) */
1628 frame_highlight (frame
)
1629 struct frame
*frame
;
1631 /* We used to only do this if Vx_no_window_manager was non-nil, but
1632 the ICCCM (section 4.1.6) says that the window's border pixmap
1633 and border pixel are window attributes which are "private to the
1634 client", so we can always change it to whatever we want. */
1636 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1637 frame
->display
.x
->border_pixel
);
1639 x_display_cursor (frame
, 1);
1643 frame_unhighlight (frame
)
1644 struct frame
*frame
;
1646 /* We used to only do this if Vx_no_window_manager was non-nil, but
1647 the ICCCM (section 4.1.6) says that the window's border pixmap
1648 and border pixel are window attributes which are "private to the
1649 client", so we can always change it to whatever we want. */
1651 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1652 frame
->display
.x
->border_tile
);
1654 x_display_cursor (frame
, 1);
1656 #else /* ! defined (HAVE_X11) */
1657 /* Dump the border-emphasis of frame F.
1658 If F is selected, this is a lining of the same color as the border,
1659 just within the border, occupying a portion of the internal border.
1660 If F is not selected, it is background in the same place.
1661 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1663 ALWAYS = 1 is used when a frame becomes selected or deselected.
1664 In that case, we also turn the cursor off and on again
1665 so it will appear in the proper shape (solid if selected; else hollow.) */
1668 dumpborder (f
, always
)
1672 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1673 int width
= PIXEL_WIDTH (f
);
1674 int height
= PIXEL_HEIGHT (f
);
1677 if (f
!= selected_frame
)
1682 pixel
= f
->display
.x
->background_pixel
;
1686 pixel
= f
->display
.x
->border_pixel
;
1689 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1690 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1691 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1693 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1697 x_display_cursor (f
, 1);
1699 #endif /* ! defined (HAVE_X11) */
1701 static void XTframe_rehighlight ();
1703 /* The focus has changed. Update the frames as necessary to reflect
1704 the new situation. Note that we can't change the selected frame
1705 here, because the lisp code we are interrupting might become confused.
1706 Each event gets marked with the frame in which it occurred, so the
1707 lisp code can tell when the switch took place by examining the events. */
1710 x_new_focus_frame (frame
)
1711 struct frame
*frame
;
1713 struct frame
*old_focus
= x_focus_frame
;
1714 int events_enqueued
= 0;
1716 if (frame
!= x_focus_frame
)
1718 /* Set this before calling other routines, so that they see
1719 the correct value of x_focus_frame. */
1720 x_focus_frame
= frame
;
1722 if (old_focus
&& old_focus
->auto_lower
)
1723 x_lower_frame (old_focus
);
1726 selected_frame
= frame
;
1727 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1728 Lisp_Frame
, selected_frame
);
1729 Fselect_window (selected_frame
->selected_window
);
1730 choose_minibuf_frame ();
1733 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1734 pending_autoraise_frame
= x_focus_frame
;
1736 pending_autoraise_frame
= 0;
1739 XTframe_rehighlight ();
1743 /* The focus has changed, or we have redirected a frame's focus to
1744 another frame (this happens when a frame uses a surrogate
1745 minibuffer frame). Shift the highlight as appropriate. */
1747 XTframe_rehighlight ()
1749 struct frame
*old_highlight
= x_highlight_frame
;
1754 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1755 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1757 if (! FRAME_LIVE_P (x_highlight_frame
))
1759 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1760 x_highlight_frame
= x_focus_frame
;
1764 x_highlight_frame
= 0;
1766 if (x_highlight_frame
!= old_highlight
)
1769 frame_unhighlight (old_highlight
);
1770 if (x_highlight_frame
)
1771 frame_highlight (x_highlight_frame
);
1775 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1777 /* Which modifier keys are on which modifier bits?
1779 With each keystroke, X returns eight bits indicating which modifier
1780 keys were held down when the key was pressed. The interpretation
1781 of the top five modifier bits depends on what keys are attached
1782 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1785 x_meta_mod_mask is a mask containing the bits used for the meta key.
1786 It may have more than one bit set, if more than one modifier bit
1787 has meta keys on it. Basically, if EVENT is a KeyPress event,
1788 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1790 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1791 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1792 only be affected by the lock modifier bit if XK_Shift_Lock is in
1793 use; XK_Caps_Lock should only affect alphabetic keys. With this
1794 arrangement, the lock modifier should shift the character if
1795 (EVENT.state & x_shift_lock_mask) != 0. */
1796 static int x_meta_mod_mask
, x_shift_lock_mask
;
1798 /* These are like x_meta_mod_mask, but for different modifiers. */
1799 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1801 /* Initialize mode_switch_bit and modifier_meaning. */
1803 x_find_modifier_meanings ()
1805 int min_code
, max_code
;
1808 XModifierKeymap
*mods
;
1810 x_meta_mod_mask
= 0;
1811 x_shift_lock_mask
= 0;
1813 x_super_mod_mask
= 0;
1814 x_hyper_mod_mask
= 0;
1817 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1819 min_code
= x_current_display
->min_keycode
;
1820 max_code
= x_current_display
->max_keycode
;
1823 syms
= XGetKeyboardMapping (x_current_display
,
1824 min_code
, max_code
- min_code
+ 1,
1826 mods
= XGetModifierMapping (x_current_display
);
1828 /* Scan the modifier table to see which modifier bits the Meta and
1829 Alt keysyms are on. */
1831 int row
, col
; /* The row and column in the modifier table. */
1833 for (row
= 3; row
< 8; row
++)
1834 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1837 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1839 /* Zeroes are used for filler. Skip them. */
1843 /* Are any of this keycode's keysyms a meta key? */
1847 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1849 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1855 x_meta_mod_mask
|= (1 << row
);
1860 x_alt_mod_mask
|= (1 << row
);
1865 x_hyper_mod_mask
|= (1 << row
);
1870 x_super_mod_mask
|= (1 << row
);
1874 /* Ignore this if it's not on the lock modifier. */
1875 if ((1 << row
) == LockMask
)
1876 x_shift_lock_mask
= LockMask
;
1884 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1885 if (! x_meta_mod_mask
)
1887 x_meta_mod_mask
= x_alt_mod_mask
;
1891 /* If some keys are both alt and meta,
1892 make them just meta, not alt. */
1893 if (x_alt_mod_mask
& x_meta_mod_mask
)
1895 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1898 XFree ((char *) syms
);
1899 XFreeModifiermap (mods
);
1902 /* Convert between the modifier bits X uses and the modifier bits
1905 x_x_to_emacs_modifiers (state
)
1908 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1909 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1910 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1911 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1912 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1913 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1917 x_emacs_to_x_modifiers (state
)
1920 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1921 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1922 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1923 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1924 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1925 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1928 /* Mouse clicks and mouse movement. Rah. */
1931 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1932 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1933 that the glyph at X, Y occupies, if BOUNDS != 0.
1934 If NOCLIP is nonzero, do not force the value into range. */
1937 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1939 register int pix_x
, pix_y
;
1940 register int *x
, *y
;
1944 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1945 even for negative values. */
1947 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1949 pix_y
-= (f
)->display
.x
->line_height
- 1;
1951 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1952 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1956 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1957 bounds
->height
= f
->display
.x
->line_height
;
1958 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1959 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1966 else if (pix_x
> f
->width
)
1971 else if (pix_y
> f
->height
)
1980 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1983 register int *pix_x
, *pix_y
;
1985 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1986 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1989 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1991 If the event is a button press, then note that we have grabbed
1995 construct_mouse_click (result
, event
, f
)
1996 struct input_event
*result
;
1997 XButtonEvent
*event
;
2000 /* Make the event type no_event; we'll change that when we decide
2002 result
->kind
= mouse_click
;
2003 result
->code
= event
->button
- Button1
;
2004 result
->timestamp
= event
->time
;
2005 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2006 | (event
->type
== ButtonRelease
2010 /* Notice if the mouse is still grabbed. */
2011 if (event
->type
== ButtonPress
)
2013 if (! x_mouse_grabbed
)
2014 Vmouse_depressed
= Qt
;
2015 x_mouse_grabbed
|= (1 << event
->button
);
2016 last_mouse_frame
= f
;
2018 else if (event
->type
== ButtonRelease
)
2020 x_mouse_grabbed
&= ~(1 << event
->button
);
2021 if (!x_mouse_grabbed
)
2022 Vmouse_depressed
= Qnil
;
2029 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2030 XFASTINT (result
->x
) = column
;
2031 XFASTINT (result
->y
) = row
;
2033 XSET (result
->x
, Lisp_Int
, event
->x
);
2034 XSET (result
->y
, Lisp_Int
, event
->y
);
2035 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2039 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2042 construct_menu_click (result
, event
, f
)
2043 struct input_event
*result
;
2044 XButtonEvent
*event
;
2047 /* Make the event type no_event; we'll change that when we decide
2049 result
->kind
= mouse_click
;
2050 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
2051 result
->timestamp
= event
->time
;
2052 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2053 | (event
->type
== ButtonRelease
2057 XSET (result
->x
, Lisp_Int
, event
->x
);
2058 XSET (result
->y
, Lisp_Int
, -1);
2059 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2062 /* Function to report a mouse movement to the mainstream Emacs code.
2063 The input handler calls this.
2065 We have received a mouse movement event, which is given in *event.
2066 If the mouse is over a different glyph than it was last time, tell
2067 the mainstream emacs code by setting mouse_moved. If not, ask for
2068 another motion event, so we can check again the next time it moves. */
2071 note_mouse_movement (frame
, event
)
2073 XMotionEvent
*event
;
2076 last_mouse_movement_time
= event
->time
;
2078 if (event
->window
!= FRAME_X_WINDOW (frame
))
2081 last_mouse_scroll_bar
= Qnil
;
2083 note_mouse_highlight (frame
, -1, -1);
2085 /* Ask for another mouse motion event. */
2089 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2090 (Window
*) &dummy
, (Window
*) &dummy
,
2091 &dummy
, &dummy
, &dummy
, &dummy
,
2092 (unsigned int *) &dummy
);
2096 /* Has the mouse moved off the glyph it was on at the last sighting? */
2097 else if (event
->x
< last_mouse_glyph
.x
2098 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2099 || event
->y
< last_mouse_glyph
.y
2100 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2103 last_mouse_scroll_bar
= Qnil
;
2105 note_mouse_highlight (frame
, event
->x
, event
->y
);
2107 /* Ask for another mouse motion event. */
2111 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2112 (Window
*) &dummy
, (Window
*) &dummy
,
2113 &dummy
, &dummy
, &dummy
, &dummy
,
2114 (unsigned int *) &dummy
);
2119 /* It's on the same glyph. Call XQueryPointer so we'll get an
2120 event the next time the mouse moves and we can see if it's
2121 *still* on the same glyph. */
2124 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2125 (Window
*) &dummy
, (Window
*) &dummy
,
2126 &dummy
, &dummy
, &dummy
, &dummy
,
2127 (unsigned int *) &dummy
);
2131 /* This is used for debugging, to turn off note_mouse_highlight. */
2132 static int disable_mouse_highlight
;
2134 /* Take proper action when the mouse has moved to position X, Y on frame F
2135 as regards highlighting characters that have mouse-face properties.
2136 Also dehighlighting chars where the mouse was before.
2137 X and Y can be negative or out of range. */
2140 note_mouse_highlight (f
, x
, y
)
2143 int row
, column
, portion
;
2144 XRectangle new_glyph
;
2148 if (disable_mouse_highlight
)
2151 mouse_face_mouse_x
= x
;
2152 mouse_face_mouse_y
= y
;
2153 mouse_face_mouse_frame
= f
;
2155 if (mouse_face_defer
)
2160 mouse_face_deferred_gc
= 1;
2164 /* Find out which glyph the mouse is on. */
2165 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2166 &new_glyph
, x_mouse_grabbed
);
2168 /* Which window is that in? */
2169 window
= window_from_coordinates (f
, column
, row
, &portion
);
2170 w
= XWINDOW (window
);
2172 /* If we were displaying active text in another window, clear that. */
2173 if (! EQ (window
, mouse_face_window
))
2174 clear_mouse_face ();
2176 /* Are we in a window whose display is up to date?
2177 And verify the buffer's text has not changed. */
2178 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2179 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2180 && EQ (w
->window_end_valid
, w
->buffer
)
2181 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
2183 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2186 /* Find which buffer position the mouse corresponds to. */
2187 for (i
= column
; i
>= 0; i
--)
2191 /* Is it outside the displayed active region (if any)? */
2193 clear_mouse_face ();
2194 else if (! (EQ (window
, mouse_face_window
)
2195 && row
>= mouse_face_beg_row
2196 && row
<= mouse_face_end_row
2197 && (row
> mouse_face_beg_row
|| column
>= mouse_face_beg_col
)
2198 && (row
< mouse_face_end_row
|| column
< mouse_face_end_col
2199 || mouse_face_past_end
)))
2201 Lisp_Object mouse_face
, overlay
, position
;
2202 Lisp_Object
*overlay_vec
;
2203 int len
, noverlays
, ignor1
;
2204 struct buffer
*obuf
;
2207 /* If we get an out-of-range value, return now; avoid an error. */
2208 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2211 /* Make the window's buffer temporarily current for
2212 overlays_at and compute_char_face. */
2213 obuf
= current_buffer
;
2214 current_buffer
= XBUFFER (w
->buffer
);
2220 /* Yes. Clear the display of the old active region, if any. */
2221 clear_mouse_face ();
2223 /* Is this char mouse-active? */
2224 XSET (position
, Lisp_Int
, pos
);
2227 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2229 /* Put all the overlays we want in a vector in overlay_vec.
2230 Store the length in len. */
2231 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
, &ignor1
);
2232 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2234 /* Find the highest priority overlay that has a mouse-face prop. */
2236 for (i
= 0; i
< noverlays
; i
++)
2238 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2239 if (!NILP (mouse_face
))
2241 overlay
= overlay_vec
[i
];
2246 /* If no overlay applies, get a text property. */
2248 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2250 /* Handle the overlay case. */
2251 if (! NILP (overlay
))
2253 /* Find the range of text around this char that
2254 should be active. */
2255 Lisp_Object before
, after
;
2258 before
= Foverlay_start (overlay
);
2259 after
= Foverlay_end (overlay
);
2260 /* Record this as the current active region. */
2261 fast_find_position (window
, before
, &mouse_face_beg_col
,
2262 &mouse_face_beg_row
);
2264 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2265 &mouse_face_end_row
);
2266 mouse_face_window
= window
;
2267 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
2268 &ignore
, pos
+ 1, 1);
2270 /* Display it as active. */
2271 show_mouse_face (1);
2273 /* Handle the text property case. */
2274 else if (! NILP (mouse_face
))
2276 /* Find the range of text around this char that
2277 should be active. */
2278 Lisp_Object before
, after
, beginning
, end
;
2281 beginning
= Fmarker_position (w
->start
);
2282 XSET (end
, Lisp_Int
,
2283 (BUF_Z (XBUFFER (w
->buffer
))
2284 - XFASTINT (w
->window_end_pos
)));
2286 = Fprevious_single_property_change (make_number (pos
+ 1),
2288 w
->buffer
, beginning
);
2290 = Fnext_single_property_change (position
, Qmouse_face
,
2292 /* Record this as the current active region. */
2293 fast_find_position (window
, before
, &mouse_face_beg_col
,
2294 &mouse_face_beg_row
);
2296 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2297 &mouse_face_end_row
);
2298 mouse_face_window
= window
;
2300 = compute_char_face (f
, w
, pos
, 0, 0,
2301 &ignore
, pos
+ 1, 1);
2303 /* Display it as active. */
2304 show_mouse_face (1);
2308 current_buffer
= obuf
;
2313 /* Find the row and column of position POS in window WINDOW.
2314 Store them in *COLUMNP and *ROWP.
2315 This assumes display in WINDOW is up to date.
2316 If POS is above start of WINDOW, return coords
2317 of start of first screen line.
2318 If POS is after end of WINDOW, return coords of end of last screen line.
2320 Value is 1 if POS is in range, 0 if it was off screen. */
2323 fast_find_position (window
, pos
, columnp
, rowp
)
2326 int *columnp
, *rowp
;
2328 struct window
*w
= XWINDOW (window
);
2329 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2334 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2335 int width
= window_internal_width (w
);
2339 /* Find the right row. */
2344 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2345 if (linestart
> pos
)
2351 /* Find the right column with in it. */
2352 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2354 for (i
= 0; i
< width
; i
++)
2356 if (charstarts
[left
+ i
] == pos
)
2359 *columnp
= i
+ left
;
2362 else if (charstarts
[left
+ i
] > pos
)
2364 else if (charstarts
[left
+ i
] > 0)
2373 /* Display the active region described by mouse_face_*
2374 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2377 show_mouse_face (hl
)
2380 struct window
*w
= XWINDOW (mouse_face_window
);
2381 int width
= window_internal_width (w
);
2382 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2384 int curs_x
= f
->phys_cursor_x
;
2385 int curs_y
= f
->phys_cursor_y
;
2388 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2390 int column
= (i
== mouse_face_beg_row
? mouse_face_beg_col
: w
->left
);
2391 int endcolumn
= (i
== mouse_face_end_row
? mouse_face_end_col
: w
->left
+ width
);
2392 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
] - w
->left
);
2394 /* If the cursor's in the text we are about to rewrite,
2395 turn the cursor off. */
2397 && curs_x
>= mouse_face_beg_col
- 1 && curs_x
<= mouse_face_end_col
)
2399 x_display_cursor (f
, 0);
2404 CHAR_TO_PIXEL_COL (f
, column
),
2405 CHAR_TO_PIXEL_ROW (f
, i
),
2406 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2408 /* Highlight with mouse face if hl > 0. */
2412 /* If we turned the cursor off, turn it back on. */
2414 x_display_cursor (f
, 1);
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
&& FRAME_LIVE_P (last_mouse_frame
))
2518 /* If mouse was grabbed on a frame, give coords for that frame
2519 even if the mouse is now outside it. */
2520 XTranslateCoordinates (x_current_display
,
2522 /* From-window, to-window. */
2523 root
, FRAME_X_WINDOW (last_mouse_frame
),
2525 /* From-position, to-position. */
2526 root_x
, root_y
, &win_x
, &win_y
,
2530 f1
= last_mouse_frame
;
2536 XTranslateCoordinates (x_current_display
,
2538 /* From-window, to-window. */
2541 /* From-position, to-position. */
2542 root_x
, root_y
, &win_x
, &win_y
,
2555 /* Now we know that:
2556 win is the innermost window containing the pointer
2557 (XTC says it has no child containing the pointer),
2558 win_x and win_y are the pointer's position in it
2559 (XTC did this the last time through), and
2560 parent_x and parent_y are the pointer's position in win's parent.
2561 (They are what win_x and win_y were when win was child.
2562 If win is the root window, it has no parent, and
2563 parent_{x,y} are invalid, but that's okay, because we'll
2564 never use them in that case.) */
2566 /* Is win one of our frames? */
2567 f1
= x_any_window_to_frame (win
);
2570 /* If not, is it one of our scroll bars? */
2573 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2577 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2585 int ignore1
, ignore2
;
2587 /* Ok, we found a frame. Store all the values. */
2589 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2590 &last_mouse_glyph
, x_mouse_grabbed
);
2595 XSET (*x
, Lisp_Int
, win_x
);
2596 XSET (*y
, Lisp_Int
, win_y
);
2597 *time
= last_mouse_movement_time
;
2605 #else /* ! defined (HAVE_X11) */
2606 #define XEvent XKeyPressedEvent
2607 #endif /* ! defined (HAVE_X11) */
2609 /* Scroll bar support. */
2611 /* Given an X window ID, find the struct scroll_bar which manages it.
2612 This can be called in GC, so we have to make sure to strip off mark
2614 static struct scroll_bar
*
2615 x_window_to_scroll_bar (window_id
)
2618 Lisp_Object tail
, frame
;
2620 for (tail
= Vframe_list
;
2621 XGCTYPE (tail
) == Lisp_Cons
;
2622 tail
= XCONS (tail
)->cdr
)
2624 Lisp_Object frame
, bar
, condemned
;
2626 frame
= XCONS (tail
)->car
;
2627 /* All elements of Vframe_list should be frames. */
2628 if (XGCTYPE (frame
) != Lisp_Frame
)
2631 /* Scan this frame's scroll bar list for a scroll bar with the
2633 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2634 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2635 /* This trick allows us to search both the ordinary and
2636 condemned scroll bar lists with one loop. */
2637 ! GC_NILP (bar
) || (bar
= condemned
,
2640 bar
= XSCROLL_BAR (bar
)->next
)
2641 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2642 return XSCROLL_BAR (bar
);
2648 /* Open a new X window to serve as a scroll bar, and return the
2649 scroll bar vector for it. */
2650 static struct scroll_bar
*
2651 x_scroll_bar_create (window
, top
, left
, width
, height
)
2652 struct window
*window
;
2653 int top
, left
, width
, height
;
2655 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2656 struct scroll_bar
*bar
=
2657 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2662 XSetWindowAttributes a
;
2664 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2665 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2666 | ButtonMotionMask
| PointerMotionHintMask
2668 a
.cursor
= x_vertical_scroll_bar_cursor
;
2670 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2675 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2676 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2677 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2678 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2679 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2680 sb_widget
= XtCreateManagedWidget ("box",
2682 frame
->display
.x
->edit_widget
, al
, ac
);
2683 SET_SCROLL_BAR_X_WINDOW
2684 (bar
, sb_widget
->core
.window
);
2686 SET_SCROLL_BAR_X_WINDOW
2688 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2690 /* Position and size of scroll bar. */
2691 left
, top
, width
, height
,
2693 /* Border width, depth, class, and visual. */
2694 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2700 XSET (bar
->window
, Lisp_Window
, window
);
2701 XSET (bar
->top
, Lisp_Int
, top
);
2702 XSET (bar
->left
, Lisp_Int
, left
);
2703 XSET (bar
->width
, Lisp_Int
, width
);
2704 XSET (bar
->height
, Lisp_Int
, height
);
2705 XSET (bar
->start
, Lisp_Int
, 0);
2706 XSET (bar
->end
, Lisp_Int
, 0);
2707 bar
->dragging
= Qnil
;
2709 /* Add bar to its frame's list of scroll bars. */
2710 bar
->next
= FRAME_SCROLL_BARS (frame
);
2712 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2713 if (! NILP (bar
->next
))
2714 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2716 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2723 /* Draw BAR's handle in the proper position.
2724 If the handle is already drawn from START to END, don't bother
2725 redrawing it, unless REBUILD is non-zero; in that case, always
2726 redraw it. (REBUILD is handy for drawing the handle after expose
2729 Normally, we want to constrain the start and end of the handle to
2730 fit inside its rectangle, but if the user is dragging the scroll bar
2731 handle, we want to let them drag it down all the way, so that the
2732 bar's top is as far down as it goes; otherwise, there's no way to
2733 move to the very end of the buffer. */
2735 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2736 struct scroll_bar
*bar
;
2740 int dragging
= ! NILP (bar
->dragging
);
2741 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2742 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2744 /* If the display is already accurate, do nothing. */
2746 && start
== XINT (bar
->start
)
2747 && end
== XINT (bar
->end
))
2753 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2754 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2755 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2757 /* Make sure the values are reasonable, and try to preserve
2758 the distance between start and end. */
2760 int length
= end
- start
;
2764 else if (start
> top_range
)
2766 end
= start
+ length
;
2770 else if (end
> top_range
&& ! dragging
)
2774 /* Store the adjusted setting in the scroll bar. */
2775 XSET (bar
->start
, Lisp_Int
, start
);
2776 XSET (bar
->end
, Lisp_Int
, end
);
2778 /* Clip the end position, just for display. */
2779 if (end
> top_range
)
2782 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2783 below top positions, to make sure the handle is always at least
2784 that many pixels tall. */
2785 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2787 /* Draw the empty space above the handle. Note that we can't clear
2788 zero-height areas; that means "clear to end of window." */
2790 XClearArea (x_current_display
, w
,
2792 /* x, y, width, height, and exposures. */
2793 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2794 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2795 inside_width
, start
,
2798 /* Draw the handle itself. */
2799 XFillRectangle (x_current_display
, w
, gc
,
2801 /* x, y, width, height */
2802 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2803 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2804 inside_width
, end
- start
);
2807 /* Draw the empty space below the handle. Note that we can't
2808 clear zero-height areas; that means "clear to end of window." */
2809 if (end
< inside_height
)
2810 XClearArea (x_current_display
, w
,
2812 /* x, y, width, height, and exposures. */
2813 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2814 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2815 inside_width
, inside_height
- end
,
2823 /* Move a scroll bar around on the screen, to accommodate changing
2824 window configurations. */
2826 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2827 struct scroll_bar
*bar
;
2828 int top
, left
, width
, height
;
2834 unsigned int mask
= 0;
2841 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2842 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2843 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2844 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2847 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2851 XSET (bar
->left
, Lisp_Int
, left
);
2852 XSET (bar
->top
, Lisp_Int
, top
);
2853 XSET (bar
->width
, Lisp_Int
, width
);
2854 XSET (bar
->height
, Lisp_Int
, height
);
2859 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2862 x_scroll_bar_remove (bar
)
2863 struct scroll_bar
*bar
;
2865 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2869 /* Destroy the window. */
2870 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2872 /* Disassociate this scroll bar from its window. */
2873 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2878 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2879 that we are displaying PORTION characters out of a total of WHOLE
2880 characters, starting at POSITION. If WINDOW has no scroll bar,
2883 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2884 struct window
*window
;
2885 int portion
, whole
, position
;
2887 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2888 int top
= XINT (window
->top
);
2889 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2890 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2892 /* Where should this scroll bar be, pixelwise? */
2893 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2894 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2895 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2896 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2898 struct scroll_bar
*bar
;
2900 /* Does the scroll bar exist yet? */
2901 if (NILP (window
->vertical_scroll_bar
))
2902 bar
= x_scroll_bar_create (window
,
2903 pixel_top
, pixel_left
,
2904 pixel_width
, pixel_height
);
2907 /* It may just need to be moved and resized. */
2908 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2909 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2912 /* Set the scroll bar's current state, unless we're currently being
2914 if (NILP (bar
->dragging
))
2917 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2920 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2923 int start
= ((double) position
* top_range
) / whole
;
2924 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2926 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2930 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2934 /* The following three hooks are used when we're doing a thorough
2935 redisplay of the frame. We don't explicitly know which scroll bars
2936 are going to be deleted, because keeping track of when windows go
2937 away is a real pain - "Can you say set-window-configuration, boys
2938 and girls?" Instead, we just assert at the beginning of redisplay
2939 that *all* scroll bars are to be removed, and then save a scroll bar
2940 from the fiery pit when we actually redisplay its window. */
2942 /* Arrange for all scroll bars on FRAME to be removed at the next call
2943 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2944 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2946 XTcondemn_scroll_bars (frame
)
2949 /* The condemned list should be empty at this point; if it's not,
2950 then the rest of Emacs isn't using the condemn/redeem/judge
2951 protocol correctly. */
2952 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2955 /* Move them all to the "condemned" list. */
2956 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2957 FRAME_SCROLL_BARS (frame
) = Qnil
;
2960 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2961 Note that WINDOW isn't necessarily condemned at all. */
2963 XTredeem_scroll_bar (window
)
2964 struct window
*window
;
2966 struct scroll_bar
*bar
;
2968 /* We can't redeem this window's scroll bar if it doesn't have one. */
2969 if (NILP (window
->vertical_scroll_bar
))
2972 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2974 /* Unlink it from the condemned list. */
2976 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2978 if (NILP (bar
->prev
))
2980 /* If the prev pointer is nil, it must be the first in one of
2982 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2983 /* It's not condemned. Everything's fine. */
2985 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2986 window
->vertical_scroll_bar
))
2987 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2989 /* If its prev pointer is nil, it must be at the front of
2990 one or the other! */
2994 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2996 if (! NILP (bar
->next
))
2997 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2999 bar
->next
= FRAME_SCROLL_BARS (f
);
3001 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
3002 if (! NILP (bar
->next
))
3003 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
3007 /* Remove all scroll bars on FRAME that haven't been saved since the
3008 last call to `*condemn_scroll_bars_hook'. */
3010 XTjudge_scroll_bars (f
)
3013 Lisp_Object bar
, next
;
3015 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3017 /* Clear out the condemned list now so we won't try to process any
3018 more events on the hapless scroll bars. */
3019 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3021 for (; ! NILP (bar
); bar
= next
)
3023 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3025 x_scroll_bar_remove (b
);
3028 b
->next
= b
->prev
= Qnil
;
3031 /* Now there should be no references to the condemned scroll bars,
3032 and they should get garbage-collected. */
3036 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3038 This may be called from a signal handler, so we have to ignore GC
3041 x_scroll_bar_expose (bar
, event
)
3042 struct scroll_bar
*bar
;
3045 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3046 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
3050 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3052 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3053 XDrawRectangle (x_current_display
, w
, gc
,
3055 /* x, y, width, height */
3056 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
3061 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3062 is set to something other than no_event, it is enqueued.
3064 This may be called from a signal handler, so we have to ignore GC
3067 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3068 struct scroll_bar
*bar
;
3070 struct input_event
*emacs_event
;
3072 if (XGCTYPE (bar
->window
) != Lisp_Window
)
3075 emacs_event
->kind
= scroll_bar_click
;
3076 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3077 emacs_event
->modifiers
=
3078 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
3079 | (event
->type
== ButtonRelease
3082 emacs_event
->frame_or_window
= bar
->window
;
3083 emacs_event
->timestamp
= event
->xbutton
.time
;
3085 int internal_height
=
3086 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3088 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3089 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3092 if (y
> top_range
) y
= top_range
;
3094 if (y
< XINT (bar
->start
))
3095 emacs_event
->part
= scroll_bar_above_handle
;
3096 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3097 emacs_event
->part
= scroll_bar_handle
;
3099 emacs_event
->part
= scroll_bar_below_handle
;
3101 /* Just because the user has clicked on the handle doesn't mean
3102 they want to drag it. Lisp code needs to be able to decide
3103 whether or not we're dragging. */
3105 /* If the user has just clicked on the handle, record where they're
3107 if (event
->type
== ButtonPress
3108 && emacs_event
->part
== scroll_bar_handle
)
3109 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
3112 /* If the user has released the handle, set it to its final position. */
3113 if (event
->type
== ButtonRelease
3114 && ! NILP (bar
->dragging
))
3116 int new_start
= y
- XINT (bar
->dragging
);
3117 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3119 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3120 bar
->dragging
= Qnil
;
3123 /* Same deal here as the other #if 0. */
3125 /* Clicks on the handle are always reported as occurring at the top of
3127 if (emacs_event
->part
== scroll_bar_handle
)
3128 emacs_event
->x
= bar
->start
;
3130 XSET (emacs_event
->x
, Lisp_Int
, y
);
3132 XSET (emacs_event
->x
, Lisp_Int
, y
);
3135 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
3139 /* Handle some mouse motion while someone is dragging the scroll bar.
3141 This may be called from a signal handler, so we have to ignore GC
3144 x_scroll_bar_note_movement (bar
, event
)
3145 struct scroll_bar
*bar
;
3148 last_mouse_movement_time
= event
->xmotion
.time
;
3151 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
3153 /* If we're dragging the bar, display it. */
3154 if (! GC_NILP (bar
->dragging
))
3156 /* Where should the handle be now? */
3157 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3159 if (new_start
!= XINT (bar
->start
))
3161 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3163 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3167 /* Call XQueryPointer so we'll get an event the next time the mouse
3168 moves and we can see *still* on the same position. */
3172 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3173 (Window
*) &dummy
, (Window
*) &dummy
,
3174 &dummy
, &dummy
, &dummy
, &dummy
,
3175 (unsigned int *) &dummy
);
3179 /* Return information to the user about the current position of the mouse
3180 on the scroll bar. */
3182 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
3184 Lisp_Object
*bar_window
;
3185 enum scroll_bar_part
*part
;
3187 unsigned long *time
;
3189 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3191 Window dummy_window
;
3193 unsigned int dummy_mask
;
3197 /* Get the mouse's position relative to the scroll bar window, and
3199 if (! XQueryPointer (x_current_display
,
3200 SCROLL_BAR_X_WINDOW (bar
),
3202 /* Root, child, root x and root y. */
3203 &dummy_window
, &dummy_window
,
3204 &dummy_coord
, &dummy_coord
,
3206 /* Position relative to scroll bar. */
3209 /* Mouse buttons and modifier keys. */
3215 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3217 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3219 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3221 if (! NILP (bar
->dragging
))
3222 win_y
-= XINT (bar
->dragging
);
3226 if (win_y
> top_range
)
3229 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3230 *bar_window
= bar
->window
;
3232 if (! NILP (bar
->dragging
))
3233 *part
= scroll_bar_handle
;
3234 else if (win_y
< XINT (bar
->start
))
3235 *part
= scroll_bar_above_handle
;
3236 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3237 *part
= scroll_bar_handle
;
3239 *part
= scroll_bar_below_handle
;
3241 XSET (*x
, Lisp_Int
, win_y
);
3242 XSET (*y
, Lisp_Int
, top_range
);
3245 last_mouse_scroll_bar
= Qnil
;
3248 *time
= last_mouse_movement_time
;
3254 /* The screen has been cleared so we may have changed foreground or
3255 background colors, and the scroll bars may need to be redrawn.
3256 Clear out the scroll bars, and ask for expose events, so we can
3259 x_scroll_bar_clear (f
)
3264 for (bar
= FRAME_SCROLL_BARS (f
);
3265 XTYPE (bar
) == Lisp_Vector
;
3266 bar
= XSCROLL_BAR (bar
)->next
)
3267 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3271 /* This processes Expose events from the menubar specific X event
3272 loop in menubar.c. This allows to redisplay the frame if necessary
3273 when handling menubar or popup items. */
3276 process_expose_from_menu (event
)
3283 f
= x_window_to_frame (event
.xexpose
.window
);
3286 if (f
->async_visible
== 0)
3288 f
->async_visible
= 1;
3289 f
->async_iconified
= 0;
3290 SET_FRAME_GARBAGED (f
);
3294 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3295 event
.xexpose
.x
, event
.xexpose
.y
,
3296 event
.xexpose
.width
, event
.xexpose
.height
);
3301 struct scroll_bar
*bar
3302 = x_window_to_scroll_bar (event
.xexpose
.window
);
3305 x_scroll_bar_expose (bar
, &event
);
3312 /* The main X event-reading loop - XTread_socket. */
3314 /* Timestamp of enter window event. This is only used by XTread_socket,
3315 but we have to put it out here, since static variables within functions
3316 sometimes don't work. */
3317 static Time enter_timestamp
;
3319 /* This holds the state XLookupString needs to implement dead keys
3320 and other tricks known as "compose processing". _X Window System_
3321 says that a portable program can't use this, but Stephen Gildea assures
3322 me that letting the compiler initialize it to zeros will work okay.
3324 This must be defined outside of XTread_socket, for the same reasons
3325 given for enter_timestamp, above. */
3326 static XComposeStatus compose_status
;
3328 /* Communication with window managers. */
3329 Atom Xatom_wm_protocols
;
3331 /* Kinds of protocol things we may receive. */
3332 Atom Xatom_wm_take_focus
;
3333 Atom Xatom_wm_save_yourself
;
3334 Atom Xatom_wm_delete_window
;
3336 /* Other WM communication */
3337 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3338 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3340 /* Window manager communication. */
3341 Atom Xatom_wm_change_state
;
3343 /* EditRes protocol */
3344 Atom Xatom_editres_name
;
3346 /* Record the last 100 characters stored
3347 to help debug the loss-of-chars-during-GC problem. */
3349 short temp_buffer
[100];
3351 /* Read events coming from the X server.
3352 This routine is called by the SIGIO handler.
3353 We return as soon as there are no more events to be read.
3355 Events representing keys are stored in buffer BUFP,
3356 which can hold up to NUMCHARS characters.
3357 We return the number of characters stored into the buffer,
3358 thus pretending to be `read'.
3360 WAITP is nonzero if we should block until input arrives.
3361 EXPECTED is nonzero if the caller knows input is available. */
3364 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3366 register struct input_event
*bufp
;
3367 register int numchars
;
3374 int items_pending
; /* How many items are in the X queue. */
3377 int event_found
= 0;
3381 if (interrupt_input_blocked
)
3383 interrupt_input_pending
= 1;
3387 interrupt_input_pending
= 0;
3391 abort (); /* Don't think this happens. */
3394 /* If available, Xlib uses FIOSNBIO to make the socket
3395 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3396 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3397 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3398 fcntl (fileno (stdin
), F_SETFL
, 0);
3399 #endif /* ! defined (FIOSNBIO) */
3403 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3405 extern int read_alarm_should_throw
;
3406 read_alarm_should_throw
= 1;
3407 XPeekEvent (XDISPLAY
&event
);
3408 read_alarm_should_throw
= 0;
3410 #endif /* HAVE_SELECT */
3413 while (XStuffPending () != 0)
3415 XNextEvent (XDISPLAY
&event
);
3423 if (event
.xclient
.message_type
== Xatom_wm_protocols
3424 && event
.xclient
.format
== 32)
3426 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3428 f
= x_window_to_frame (event
.xclient
.window
);
3429 /* Since we set WM_TAKE_FOCUS, we must call
3430 XSetInputFocus explicitly. But not if f is null,
3431 since that might be an event for a deleted frame. */
3433 XSetInputFocus (event
.xclient
.display
,
3434 event
.xclient
.window
,
3435 RevertToPointerRoot
,
3436 event
.xclient
.data
.l
[1]);
3437 /* Not certain about handling scroll bars here */
3439 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3441 /* Save state modify the WM_COMMAND property to
3442 something which can reinstate us. This notifies
3443 the session manager, who's looking for such a
3444 PropertyNotify. Can restart processing when
3445 a keyboard or mouse event arrives. */
3448 /* This is just so we only give real data once
3449 for a single Emacs process. */
3450 if (x_top_window_to_frame (event
.xclient
.window
)
3452 XSetCommand (x_current_display
,
3453 event
.xclient
.window
,
3454 initial_argv
, initial_argc
);
3456 XSetCommand (x_current_display
,
3457 event
.xclient
.window
,
3461 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3463 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3470 bufp
->kind
= delete_window_event
;
3471 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3479 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3482 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3485 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3487 new_x
= event
.xclient
.data
.s
[0];
3488 new_y
= event
.xclient
.data
.s
[1];
3492 f
->display
.x
->left_pos
= new_x
;
3493 f
->display
.x
->top_pos
= new_y
;
3496 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3497 else if (event
.xclient
.message_type
== Xatom_editres_name
)
3499 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3500 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3502 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3506 case SelectionNotify
:
3507 #ifdef USE_X_TOOLKIT
3508 if (! x_window_to_frame (event
.xselection
.requestor
))
3510 #endif /* not USE_X_TOOLKIT */
3511 x_handle_selection_notify (&event
);
3514 case SelectionClear
: /* Someone has grabbed ownership. */
3515 #ifdef USE_X_TOOLKIT
3516 if (! x_window_to_frame (event
.xselectionclear
.window
))
3518 #endif /* USE_X_TOOLKIT */
3520 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3525 bufp
->kind
= selection_clear_event
;
3526 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3527 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3528 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3536 case SelectionRequest
: /* Someone wants our selection. */
3537 #ifdef USE_X_TOOLKIT
3538 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3540 #endif /* USE_X_TOOLKIT */
3542 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3547 bufp
->kind
= selection_request_event
;
3548 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3549 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3550 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3551 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3552 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3553 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3561 case PropertyNotify
:
3562 #ifdef USE_X_TOOLKIT
3563 if (!x_any_window_to_frame (event
.xproperty
.window
))
3565 #endif /* not USE_X_TOOLKIT */
3566 x_handle_property_notify (&event
);
3569 case ReparentNotify
:
3570 f
= x_top_window_to_frame (event
.xreparent
.window
);
3574 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3575 x_real_positions (f
, &x
, &y
);
3576 f
->display
.x
->left_pos
= x
;
3577 f
->display
.x
->top_pos
= y
;
3582 f
= x_window_to_frame (event
.xexpose
.window
);
3585 if (f
->async_visible
== 0)
3587 f
->async_visible
= 1;
3588 f
->async_iconified
= 0;
3589 SET_FRAME_GARBAGED (f
);
3592 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3593 event
.xexpose
.x
, event
.xexpose
.y
,
3594 event
.xexpose
.width
, event
.xexpose
.height
);
3598 struct scroll_bar
*bar
3599 = x_window_to_scroll_bar (event
.xexpose
.window
);
3602 x_scroll_bar_expose (bar
, &event
);
3603 #ifdef USE_X_TOOLKIT
3606 #endif /* USE_X_TOOLKIT */
3610 case GraphicsExpose
: /* This occurs when an XCopyArea's
3611 source area was obscured or not
3613 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3617 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3618 event
.xgraphicsexpose
.width
,
3619 event
.xgraphicsexpose
.height
);
3621 #ifdef USE_X_TOOLKIT
3624 #endif /* USE_X_TOOLKIT */
3627 case NoExpose
: /* This occurs when an XCopyArea's
3628 source area was completely
3631 #else /* ! defined (HAVE_X11) */
3633 if (event
.subwindow
!= 0)
3634 break; /* duplicate event */
3635 f
= x_window_to_frame (event
.window
);
3636 if (event
.window
== f
->display
.x
->icon_desc
)
3639 f
->async_iconified
= 1;
3641 if (event
.window
== FRAME_X_WINDOW (f
))
3643 /* Say must check all windows' needs_exposure flags. */
3644 expose_all_windows
= 1;
3645 f
->display
.x
->needs_exposure
= 1;
3646 f
->async_visible
= 1;
3651 if (event
.subwindow
!= 0)
3652 break; /* duplicate event */
3653 f
= x_window_to_frame (event
.window
);
3654 if (event
.window
== f
->display
.x
->icon_desc
)
3659 /* If window already needs full redraw, ignore this rectangle. */
3660 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3662 /* Put the event on the queue of rectangles to redraw. */
3663 if (enqueue_event (&event
, &x_expose_queue
))
3664 /* If it is full, we can't record the rectangle,
3665 so redraw this entire window. */
3667 /* Say must check all windows' needs_exposure flags. */
3668 expose_all_windows
= 1;
3669 f
->display
.x
->needs_exposure
= 1;
3674 /* This should happen only when we are expecting it,
3675 in x_read_exposes. */
3677 #endif /* ! defined (HAVE_X11) */
3681 f
= x_any_window_to_frame (event
.xunmap
.window
);
3682 if (f
) /* F may no longer exist if
3683 the frame was deleted. */
3685 /* While a frame is unmapped, display generation is
3686 disabled; you don't want to spend time updating a
3687 display that won't ever be seen. */
3688 f
->async_visible
= 0;
3689 /* We can't distinguish, from the event, whether the window
3690 has become iconified or invisible. So assume, if it
3691 was previously visible, than now it is iconified.
3692 We depend on x_make_frame_invisible to mark it iconified. */
3693 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3694 f
->async_iconified
= 1;
3696 #ifdef USE_X_TOOLKIT
3698 #endif /* USE_X_TOOLKIT */
3702 /* We use x_top_window_to_frame because map events can come
3703 for subwindows and they don't mean that the frame is visible. */
3704 f
= x_top_window_to_frame (event
.xmap
.window
);
3707 f
->async_visible
= 1;
3708 f
->async_iconified
= 0;
3710 /* wait_reading_process_input will notice this and update
3711 the frame's display structures. */
3712 SET_FRAME_GARBAGED (f
);
3714 #ifdef USE_X_TOOLKIT
3716 #endif /* USE_X_TOOLKIT */
3719 /* Turn off processing if we become fully obscured. */
3720 case VisibilityNotify
:
3723 #else /* ! defined (HAVE_X11) */
3725 f
= x_window_to_frame (event
.window
);
3726 if (event
.window
== f
->display
.x
->icon_desc
)
3727 f
->async_iconified
= 0;
3728 if (event
.window
== FRAME_X_WINDOW (f
))
3729 f
->async_visible
= 0;
3731 #endif /* ! defined (HAVE_X11) */
3735 f
= x_any_window_to_frame (event
.xkey
.window
);
3739 KeySym keysym
, orig_keysym
;
3740 /* al%imercury@uunet.uu.net says that making this 81 instead of
3741 80 fixed a bug whereby meta chars made his Emacs hang. */
3742 unsigned char copy_buffer
[81];
3746 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3747 modifiers
= event
.xkey
.state
;
3749 /* This will have to go some day... */
3751 /* make_lispy_event turns chars into control chars.
3752 Don't do it here because XLookupString is too eager. */
3753 event
.xkey
.state
&= ~ControlMask
;
3755 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3758 orig_keysym
= keysym
;
3762 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3763 || keysym
== XK_Delete
3764 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3765 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3767 /* This recognizes the "extended function keys".
3768 It seems there's no cleaner way.
3769 Test IsModifierKey to avoid handling mode_switch
3771 || ((unsigned) (keysym
) >= XK_Select
3772 && (unsigned)(keysym
) < XK_KP_Space
)
3774 #ifdef XK_dead_circumflex
3775 || orig_keysym
== XK_dead_circumflex
3777 #ifdef XK_dead_grave
3778 || orig_keysym
== XK_dead_grave
3780 #ifdef XK_dead_tilde
3781 || orig_keysym
== XK_dead_tilde
3783 #ifdef XK_dead_diaeresis
3784 || orig_keysym
== XK_dead_diaeresis
3786 #ifdef XK_dead_macron
3787 || orig_keysym
== XK_dead_macron
3789 #ifdef XK_dead_degree
3790 || orig_keysym
== XK_dead_degree
3792 #ifdef XK_dead_acute
3793 || orig_keysym
== XK_dead_acute
3795 #ifdef XK_dead_cedilla
3796 || orig_keysym
== XK_dead_cedilla
3798 #ifdef XK_dead_breve
3799 || orig_keysym
== XK_dead_breve
3801 #ifdef XK_dead_ogonek
3802 || orig_keysym
== XK_dead_ogonek
3804 #ifdef XK_dead_caron
3805 || orig_keysym
== XK_dead_caron
3807 #ifdef XK_dead_doubleacute
3808 || orig_keysym
== XK_dead_doubleacute
3810 #ifdef XK_dead_abovedot
3811 || orig_keysym
== XK_dead_abovedot
3813 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3814 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3815 /* Any "vendor-specific" key is ok. */
3816 || (orig_keysym
& (1 << 28)))
3817 && ! (IsModifierKey (orig_keysym
)
3819 #ifdef XK_Mode_switch
3820 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3823 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3825 #endif /* not HAVE_X11R5 */
3828 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3830 temp_buffer
[temp_index
++] = keysym
;
3831 bufp
->kind
= non_ascii_keystroke
;
3832 bufp
->code
= keysym
;
3833 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3834 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3835 bufp
->timestamp
= event
.xkey
.time
;
3840 else if (numchars
> nbytes
)
3844 for (i
= 0; i
< nbytes
; i
++)
3846 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3848 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3849 bufp
->kind
= ascii_keystroke
;
3850 bufp
->code
= copy_buffer
[i
];
3851 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3852 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3853 bufp
->timestamp
= event
.xkey
.time
;
3867 #else /* ! defined (HAVE_X11) */
3870 register char *where_mapping
;
3872 f
= x_window_to_frame (event
.window
);
3873 /* Ignore keys typed on icon windows. */
3874 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3876 where_mapping
= XLookupMapping (&event
, &nbytes
);
3877 /* Nasty fix for arrow keys */
3878 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3880 switch (event
.detail
& 0xff)
3882 case KC_CURSOR_LEFT
:
3883 where_mapping
= "\002";
3885 case KC_CURSOR_RIGHT
:
3886 where_mapping
= "\006";
3889 where_mapping
= "\020";
3891 case KC_CURSOR_DOWN
:
3892 where_mapping
= "\016";
3897 if (numchars
- nbytes
> 0)
3901 for (i
= 0; i
< nbytes
; i
++)
3903 bufp
->kind
= ascii_keystroke
;
3904 bufp
->code
= where_mapping
[i
];
3905 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3906 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3914 #endif /* ! defined (HAVE_X11) */
3918 /* Here's a possible interpretation of the whole
3919 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3920 FocusIn event, you have to get a FocusOut event before you
3921 relinquish the focus. If you haven't received a FocusIn event,
3922 then a mere LeaveNotify is enough to free you. */
3925 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3927 if (event
.xcrossing
.focus
) /* Entered Window */
3929 /* Avoid nasty pop/raise loops. */
3930 if (f
&& (!(f
->auto_raise
)
3932 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3934 x_new_focus_frame (f
);
3935 enter_timestamp
= event
.xcrossing
.time
;
3938 else if (f
== x_focus_frame
)
3939 x_new_focus_frame (0);
3940 /* EnterNotify counts as mouse movement,
3941 so update things that depend on mouse position. */
3943 note_mouse_movement (f
, &event
.xmotion
);
3944 #ifdef USE_X_TOOLKIT
3946 #endif /* USE_X_TOOLKIT */
3950 f
= x_any_window_to_frame (event
.xfocus
.window
);
3951 if (event
.xfocus
.detail
!= NotifyPointer
)
3952 x_focus_event_frame
= f
;
3954 x_new_focus_frame (f
);
3955 #ifdef USE_X_TOOLKIT
3957 #endif /* USE_X_TOOLKIT */
3962 f
= x_top_window_to_frame (event
.xcrossing
.window
);
3965 if (f
== mouse_face_mouse_frame
)
3966 /* If we move outside the frame,
3967 then we're certainly no longer on any text in the frame. */
3968 clear_mouse_face ();
3970 if (event
.xcrossing
.focus
)
3972 if (! x_focus_event_frame
)
3973 x_new_focus_frame (0);
3975 x_new_focus_frame (f
);
3979 if (f
== x_focus_event_frame
)
3980 x_focus_event_frame
= 0;
3981 if (f
== x_focus_frame
)
3982 x_new_focus_frame (0);
3985 #ifdef USE_X_TOOLKIT
3987 #endif /* USE_X_TOOLKIT */
3991 f
= x_any_window_to_frame (event
.xfocus
.window
);
3992 if (event
.xfocus
.detail
!= NotifyPointer
3993 && f
== x_focus_event_frame
)
3994 x_focus_event_frame
= 0;
3995 if (f
&& f
== x_focus_frame
)
3996 x_new_focus_frame (0);
3997 #ifdef USE_X_TOOLKIT
3999 #endif /* USE_X_TOOLKIT */
4002 #else /* ! defined (HAVE_X11) */
4005 if ((event
.detail
& 0xFF) == 1)
4006 break; /* Coming from our own subwindow */
4007 if (event
.subwindow
!= 0)
4008 break; /* Entering our own subwindow. */
4011 f
= x_window_to_frame (event
.window
);
4014 x_new_focus_frame (f
);
4019 if ((event
.detail
& 0xFF) == 1)
4020 break; /* Entering our own subwindow */
4021 if (event
.subwindow
!= 0)
4022 break; /* Leaving our own subwindow. */
4025 if (x_focus_frame
== 0
4026 && x_input_frame
!= 0
4027 && x_input_frame
== x_window_to_frame (event
.window
)
4028 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
4033 frame_unhighlight (f
);
4036 #endif /* ! defined (HAVE_X11) */
4041 if (x_mouse_grabbed
&& FRAME_LIVE_P (last_mouse_frame
))
4042 f
= last_mouse_frame
;
4044 f
= x_window_to_frame (event
.xmotion
.window
);
4046 note_mouse_movement (f
, &event
.xmotion
);
4049 struct scroll_bar
*bar
4050 = x_window_to_scroll_bar (event
.xmotion
.window
);
4053 x_scroll_bar_note_movement (bar
, &event
);
4055 /* If we move outside the frame,
4056 then we're certainly no longer on any text in the frame. */
4057 clear_mouse_face ();
4060 #if 0 /* This should be unnecessary, since the toolkit has no use
4061 for motion events that happen outside of the menu event loop,
4062 and it seems to cause the bug that mouse events stop coming
4064 #ifdef USE_X_TOOLKIT
4066 #endif /* USE_X_TOOLKIT */
4070 case ConfigureNotify
:
4071 f
= x_any_window_to_frame (event
.xconfigure
.window
);
4072 #ifdef USE_X_TOOLKIT
4075 && ! event
.xconfigure
.send_event
4077 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
4082 /* Find the position of the outside upper-left corner of
4083 the window, in the root coordinate system. Don't
4084 refer to the parent window here; we may be processing
4085 this event after the window manager has changed our
4086 parent, but before we have reached the ReparentNotify. */
4087 XTranslateCoordinates (x_current_display
,
4089 /* From-window, to-window. */
4090 XtWindow (f
->display
.x
->widget
),
4093 /* From-position, to-position. */
4094 -event
.xconfigure
.border_width
,
4095 -event
.xconfigure
.border_width
,
4100 event
.xconfigure
.x
= win_x
;
4101 event
.xconfigure
.y
= win_y
;
4103 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4104 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4105 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4106 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4108 /* What we have now is the position of Emacs's own window.
4109 Convert that to the position of the window manager window. */
4112 x_real_positions (f
, &x
, &y
);
4113 f
->display
.x
->left_pos
= x
;
4114 f
->display
.x
->top_pos
= y
;
4118 #else /* not USE_X_TOOLKIT */
4121 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4122 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4124 /* Even if the number of character rows and columns has
4125 not changed, the font size may have changed, so we need
4126 to check the pixel dimensions as well. */
4127 if (columns
!= f
->width
4128 || rows
!= f
->height
4129 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
4130 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
4132 change_frame_size (f
, rows
, columns
, 0, 1);
4133 SET_FRAME_GARBAGED (f
);
4136 if (! event
.xconfigure
.send_event
)
4141 /* Find the position of the outside upper-left corner of
4142 the window, in the root coordinate system. Don't
4143 refer to the parent window here; we may be processing
4144 this event after the window manager has changed our
4145 parent, but before we have reached the ReparentNotify. */
4146 XTranslateCoordinates (x_current_display
,
4148 /* From-window, to-window. */
4149 f
->display
.x
->window_desc
,
4152 /* From-position, to-position. */
4153 -event
.xconfigure
.border_width
,
4154 -event
.xconfigure
.border_width
,
4159 event
.xconfigure
.x
= win_x
;
4160 event
.xconfigure
.y
= win_y
;
4163 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4164 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4165 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4166 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4168 /* What we have now is the position of Emacs's own window.
4169 Convert that to the position of the window manager window. */
4172 x_real_positions (f
, &x
, &y
);
4173 f
->display
.x
->left_pos
= x
;
4174 f
->display
.x
->top_pos
= y
;
4175 if (y
!= event
.xconfigure
.y
)
4177 /* Since the WM decorations come below top_pos now,
4178 we must put them below top_pos in the future. */
4179 f
->display
.x
->win_gravity
= NorthWestGravity
;
4180 x_wm_set_size_hint (f
, 0, 0);
4184 #endif /* not USE_X_TOOLKIT */
4190 /* If we decide we want to generate an event to be seen
4191 by the rest of Emacs, we put it here. */
4192 struct input_event emacs_event
;
4193 emacs_event
.kind
= no_event
;
4195 bzero (&compose_status
, sizeof (compose_status
));
4197 f
= x_window_to_frame (event
.xbutton
.window
);
4200 if (!x_focus_frame
|| (f
== x_focus_frame
))
4201 construct_mouse_click (&emacs_event
, &event
, f
);
4205 struct scroll_bar
*bar
=
4206 x_window_to_scroll_bar (event
.xbutton
.window
);
4209 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4210 #ifdef USE_X_TOOLKIT
4213 f
= x_any_window_to_frame (event
.xbutton
.window
);
4214 if (f
&& event
.type
== ButtonPress
)
4215 construct_menu_click (&emacs_event
,
4218 #endif /* USE_X_TOOLKIT */
4221 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4223 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4229 #ifdef USE_X_TOOLKIT
4231 #endif /* USE_X_TOOLKIT */
4235 #else /* ! defined (HAVE_X11) */
4237 case ButtonReleased
:
4238 f
= x_window_to_frame (event
.window
);
4241 if (event
.window
== f
->display
.x
->icon_desc
)
4243 x_make_frame_visible (f
);
4245 if (warp_mouse_on_deiconify
)
4246 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
4249 if (event
.window
== FRAME_X_WINDOW (f
))
4255 enqueue_event (&event
, &x_mouse_queue
);
4258 bufp
->kind
= ascii_keystroke
;
4259 bufp
->code
= 'X' & 037; /* C-x */
4260 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4261 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4264 bufp
->kind
= ascii_keystroke
;
4265 bufp
->code
= 0; /* C-@ */
4266 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4267 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4274 #endif /* ! defined (HAVE_X11) */
4278 case CirculateNotify
:
4280 case CirculateRequest
:
4283 #endif /* ! defined (HAVE_X11) */
4286 /* Someone has changed the keyboard mapping - update the
4288 switch (event
.xmapping
.request
)
4290 case MappingModifier
:
4291 x_find_modifier_meanings ();
4292 /* This is meant to fall through. */
4293 case MappingKeyboard
:
4294 XRefreshKeyboardMapping (&event
.xmapping
);
4296 #ifdef USE_X_TOOLKIT
4298 #endif /* USE_X_TOOLKIT */
4302 #ifdef USE_X_TOOLKIT
4305 XtDispatchEvent (&event
);
4307 #endif /* USE_X_TOOLKIT */
4314 /* On some systems, an X bug causes Emacs to get no more events
4315 when the window is destroyed. Detect that. (1994.) */
4316 XNoOp (x_current_display
);
4317 #endif /* X_IO_BUG */
4319 #if 0 /* This fails for serial-line connections to the X server,
4320 because the characters arrive one by one, and a partial
4321 command makes select return but gives nothing to read.
4322 We'll have to hope that the bug that this tried to fix
4323 in 1988 has been fixed in Xlib or the X server. */
4325 if (expected
&& ! event_found
)
4327 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4328 there is an EOF condition; in other words, that X has died.
4329 Act as if there had been a hangup. */
4330 int fd
= ConnectionNumber (x_current_display
);
4331 SELECT_TYPE mask
, junk1
, junk2
;
4336 EMACS_SET_SECS_USECS (timeout
, 0, 0);
4339 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
4340 && !XStuffPending ())
4341 kill (getpid (), SIGHUP
);
4343 #endif /* HAVE_SELECT */
4347 if (updating_frame
== 0)
4348 x_do_pending_expose ();
4351 /* If the focus was just given to an autoraising frame,
4354 if (pending_autoraise_frame
)
4356 x_raise_frame (pending_autoraise_frame
);
4357 pending_autoraise_frame
= 0;
4366 /* Read and process only Expose events
4367 until we get an ExposeCopy event; then return.
4368 This is used in insert/delete line.
4369 We assume input is already blocked. */
4375 XKeyPressedEvent event
;
4379 /* while there are more events*/
4380 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
4384 if (event
.subwindow
!= 0)
4385 break; /* duplicate event */
4386 f
= x_window_to_frame (event
.window
);
4387 if (event
.window
== f
->display
.x
->icon_desc
)
4392 if (event
.window
== FRAME_X_WINDOW (f
))
4394 expose_all_windows
= 1;
4395 f
->display
.x
->needs_exposure
= 1;
4401 if (event
.subwindow
!= 0)
4402 break; /* duplicate event */
4403 f
= x_window_to_frame (event
.window
);
4404 if (event
.window
== f
->display
.x
->icon_desc
)
4409 /* If window already needs full redraw, ignore this rectangle. */
4410 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
4412 /* Put the event on the queue of rectangles to redraw. */
4413 if (enqueue_event (&event
, &x_expose_queue
))
4414 /* If it is full, we can't record the rectangle,
4415 so redraw this entire window. */
4417 /* Say must check all windows' needs_exposure flags. */
4418 expose_all_windows
= 1;
4419 f
->display
.x
->needs_exposure
= 1;
4428 #endif /* HAVE_X11 */
4431 /* Drawing the cursor. */
4434 /* Draw a hollow box cursor. Don't change the inside of the box. */
4440 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
4441 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
4442 int width
= FONT_WIDTH (f
->display
.x
->font
);
4443 int height
= f
->display
.x
->line_height
;
4446 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4447 f
->display
.x
->cursor_gc
,
4448 left
, top
, width
- 1, height
- 1);
4449 #else /* ! defined (HAVE_X11) */
4450 XPixSet (FRAME_X_WINDOW (f
),
4451 left
, top
, width
, 1,
4452 f
->display
.x
->cursor_pixel
);
4454 XPixSet (FRAME_X_WINDOW (f
),
4455 left
, top
, 1, height
,
4456 f
->display
.x
->cursor_pixel
);
4458 XPixSet (FRAME_X_WINDOW (f
),
4459 left
+width
-1, top
, 1, height
,
4460 f
->display
.x
->cursor_pixel
);
4462 XPixSet (FRAME_X_WINDOW (f
),
4463 left
, top
+height
-1, width
, 1,
4464 f
->display
.x
->cursor_pixel
);
4465 #endif /* ! defined (HAVE_X11) */
4468 /* Clear the cursor of frame F to background color,
4469 and mark the cursor as not shown.
4470 This is used when the text where the cursor is
4471 is about to be rewritten. */
4479 if (! FRAME_VISIBLE_P (f
)
4480 || f
->phys_cursor_x
< 0)
4484 x_display_cursor (f
, 0);
4485 #else /* ! defined (HAVE_X11) */
4486 XPixSet (FRAME_X_WINDOW (f
),
4487 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4488 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4489 FONT_WIDTH (f
->display
.x
->font
), f
->display
.x
->line_height
,
4490 f
->display
.x
->background_pixel
);
4491 #endif /* ! defined (HAVE_X11) */
4492 f
->phys_cursor_x
= -1;
4495 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4496 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4500 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4507 CHAR_TO_PIXEL_COL (f
, column
),
4508 CHAR_TO_PIXEL_ROW (f
, row
),
4509 &glyph
, 1, highlight
, 0);
4513 x_display_bar_cursor (f
, on
)
4517 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4519 /* This is pointless on invisible frames, and dangerous on garbaged
4520 frames; in the latter case, the frame may be in the midst of
4521 changing its size, and curs_x and curs_y may be off the frame. */
4522 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4525 if (! on
&& f
->phys_cursor_x
< 0)
4528 /* If we're not updating, then we want to use the current frame's
4529 cursor position, not our local idea of where the cursor ought to be. */
4530 if (f
!= updating_frame
)
4532 curs_x
= FRAME_CURSOR_X (f
);
4533 curs_y
= FRAME_CURSOR_Y (f
);
4536 /* If there is anything wrong with the current cursor state, remove it. */
4537 if (f
->phys_cursor_x
>= 0
4539 || f
->phys_cursor_x
!= curs_x
4540 || f
->phys_cursor_y
!= curs_y
4541 || f
->display
.x
->current_cursor
!= bar_cursor
))
4543 /* Erase the cursor by redrawing the character underneath it. */
4544 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4545 f
->phys_cursor_glyph
,
4546 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4547 f
->phys_cursor_x
= -1;
4550 /* If we now need a cursor in the new place or in the new form, do it so. */
4552 && (f
->phys_cursor_x
< 0
4553 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4555 f
->phys_cursor_glyph
4556 = ((current_glyphs
->enable
[curs_y
]
4557 && curs_x
< current_glyphs
->used
[curs_y
])
4558 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4560 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4561 f
->display
.x
->cursor_gc
,
4562 CHAR_TO_PIXEL_COL (f
, curs_x
),
4563 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4564 1, f
->display
.x
->line_height
);
4566 f
->phys_cursor_x
= curs_x
;
4567 f
->phys_cursor_y
= curs_y
;
4569 f
->display
.x
->current_cursor
= bar_cursor
;
4572 if (updating_frame
!= f
)
4577 /* Turn the displayed cursor of frame F on or off according to ON.
4578 If ON is nonzero, where to put the cursor is specified
4579 by F->cursor_x and F->cursor_y. */
4582 x_display_box_cursor (f
, on
)
4586 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4588 /* This is pointless on invisible frames, and dangerous on garbaged
4589 frames; in the latter case, the frame may be in the midst of
4590 changing its size, and curs_x and curs_y may be off the frame. */
4591 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4594 /* If cursor is off and we want it off, return quickly. */
4595 if (!on
&& f
->phys_cursor_x
< 0)
4598 /* If we're not updating, then we want to use the current frame's
4599 cursor position, not our local idea of where the cursor ought to be. */
4600 if (f
!= updating_frame
)
4602 curs_x
= FRAME_CURSOR_X (f
);
4603 curs_y
= FRAME_CURSOR_Y (f
);
4606 /* If cursor is currently being shown and we don't want it to be
4607 or it is in the wrong place,
4608 or we want a hollow box and it's not so, (pout!)
4610 if (f
->phys_cursor_x
>= 0
4612 || f
->phys_cursor_x
!= curs_x
4613 || f
->phys_cursor_y
!= curs_y
4614 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4615 && (f
!= x_highlight_frame
))))
4617 int mouse_face_here
= 0;
4619 /* If the cursor is in the mouse face area, redisplay that when
4620 we clear the cursor. */
4621 if (f
== mouse_face_mouse_frame
4623 (f
->phys_cursor_y
> mouse_face_beg_row
4624 || (f
->phys_cursor_y
== mouse_face_beg_row
4625 && f
->phys_cursor_x
>= mouse_face_beg_col
))
4627 (f
->phys_cursor_y
< mouse_face_end_row
4628 || (f
->phys_cursor_y
== mouse_face_end_row
4629 && f
->phys_cursor_x
< mouse_face_end_col
)))
4630 mouse_face_here
= 1;
4632 /* If the font is not as tall as a whole line,
4633 we must explicitly clear the line's whole height. */
4634 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4635 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
4636 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4637 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4638 FONT_WIDTH (f
->display
.x
->font
),
4639 f
->display
.x
->line_height
, False
);
4640 /* Erase the cursor by redrawing the character underneath it. */
4641 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4642 f
->phys_cursor_glyph
,
4645 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4646 f
->phys_cursor_x
= -1;
4649 /* If we want to show a cursor,
4650 or we want a box cursor and it's not so,
4651 write it in the right place. */
4653 && (f
->phys_cursor_x
< 0
4654 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4655 && f
== x_highlight_frame
)))
4657 f
->phys_cursor_glyph
4658 = ((current_glyphs
->enable
[curs_y
]
4659 && curs_x
< current_glyphs
->used
[curs_y
])
4660 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4662 if (f
!= x_highlight_frame
)
4665 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4669 x_draw_single_glyph (f
, curs_y
, curs_x
,
4670 f
->phys_cursor_glyph
, 2);
4671 f
->display
.x
->current_cursor
= filled_box_cursor
;
4674 f
->phys_cursor_x
= curs_x
;
4675 f
->phys_cursor_y
= curs_y
;
4678 if (updating_frame
!= f
)
4682 x_display_cursor (f
, on
)
4688 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4689 x_display_box_cursor (f
, on
);
4690 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4691 x_display_bar_cursor (f
, on
);
4693 /* Those are the only two we have implemented! */
4701 /* Refresh bitmap kitchen sink icon for frame F
4702 when we get an expose event for it. */
4708 /* Normally, the window manager handles this function. */
4709 #else /* ! defined (HAVE_X11) */
4712 if (f
->display
.x
->icon_bitmap_flag
)
4713 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
4714 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
4715 icon_bitmap
, GXcopy
, AllPlanes
);
4718 extern struct frame
*selected_frame
;
4719 struct Lisp_String
*str
;
4720 unsigned char *string
;
4723 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
4725 if (f
->display
.x
->icon_label
!= string
)
4727 f
->display
.x
->icon_label
= string
;
4728 XChangeWindow (f
->display
.x
->icon_desc
,
4729 XQueryWidth (string
, icon_font_info
->id
) + 10,
4730 icon_font_info
->height
+ 10);
4733 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4734 str
->size
, icon_font_info
->id
,
4735 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4738 #endif /* ! defined (HAVE_X11) */
4741 /* Make the x-window of frame F use the gnu icon bitmap. */
4750 if (FRAME_X_WINDOW (f
) == 0)
4756 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4757 gnu_bits
, gnu_width
, gnu_height
);
4758 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4759 f
->display
.x
->icon_bitmap_flag
= 1;
4760 #else /* ! defined (HAVE_X11) */
4761 if (f
->display
.x
->icon_desc
)
4763 XClearIconWindow (FRAME_X_WINDOW (f
));
4764 XDestroyWindow (f
->display
.x
->icon_desc
);
4767 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4768 0, 0, sink_width
, sink_height
,
4769 2, WhitePixmap
, (Pixmap
) NULL
);
4771 if (icon_window
== 0)
4774 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4775 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4777 f
->display
.x
->icon_desc
= icon_window
;
4778 f
->display
.x
->icon_bitmap_flag
= 1;
4780 if (icon_bitmap
== 0)
4782 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4783 #endif /* ! defined (HAVE_X11) */
4789 /* Make the x-window of frame F use a rectangle with text. */
4792 x_text_icon (f
, icon_name
)
4800 char *X_DefaultValue
;
4804 #define WhitePixel 1
4805 #endif /* WhitePixel */
4808 #define BlackPixel 0
4809 #endif /* BlackPixel */
4810 #endif /* HAVE_X11 */
4812 if (FRAME_X_WINDOW (f
) == 0)
4817 f
->display
.x
->icon_label
= icon_name
;
4819 if (! f
->display
.x
->icon_label
)
4820 f
->display
.x
->icon_label
= " *emacs* ";
4823 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4824 (char *) f
->display
.x
->icon_label
);
4827 f
->display
.x
->icon_bitmap_flag
= 0;
4828 x_wm_set_icon_pixmap (f
, 0);
4829 #else /* ! defined (HAVE_X11) */
4830 if (icon_font_info
== 0)
4832 = XGetFont (XGetDefault (XDISPLAY
4833 (char *) XSTRING (Vinvocation_name
)->data
,
4836 if (f
->display
.x
->icon_desc
)
4838 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4839 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4843 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4845 if (! f
->display
.x
->icon_label
)
4846 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4848 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4849 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4850 f
->display
.x
->left_pos
,
4851 f
->display
.x
->top_pos
,
4852 width
+ 10, icon_font_info
->height
+ 10,
4853 2, BlackPixmap
, WhitePixmap
);
4855 if (icon_window
== 0)
4858 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4859 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4861 f
->display
.x
->icon_desc
= icon_window
;
4862 f
->display
.x
->icon_bitmap_flag
= 0;
4863 f
->display
.x
->icon_label
= 0;
4864 #endif /* ! defined (HAVE_X11) */
4869 /* Handling X errors. */
4871 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4872 X server's connection, or an error reported via the X protocol. */
4875 x_connection_closed ()
4880 shut_down_emacs (0, 1, Qnil
);
4885 /* An X error handler which prints an error message and then kills
4886 Emacs. This is what's normally installed as Xlib's handler for
4889 x_error_quitter (display
, error
)
4895 /* Note that there is no real way portable across R3/R4 to get the
4896 original error handler. */
4898 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4899 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4900 buf
, error
->request_code
);
4903 /* While we're testing Emacs 19, we'll just dump core whenever we
4904 get an X error, so we can figure out why it happened. */
4908 x_connection_closed ();
4911 /* A handler for X IO errors which prints an error message and then
4912 kills Emacs. This is what is always installed as Xlib's handler
4915 x_io_error_quitter (display
)
4918 fprintf (stderr
, "Connection to X server %s lost.\n",
4919 XDisplayName (DisplayString (display
)));
4922 /* While we're testing Emacs 19, we'll just dump core whenever we
4923 get an X error, so we can figure out why it happened. */
4927 x_connection_closed ();
4930 /* A buffer for storing X error messages. */
4931 static char *x_caught_error_message
;
4932 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4934 /* An X error handler which stores the error message in
4935 x_caught_error_message. This is what's installed when
4936 x_catch_errors is in effect. */
4938 x_error_catcher (display
, error
)
4942 XGetErrorText (display
, error
->error_code
,
4943 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4947 /* Begin trapping X errors.
4949 After calling this function, X protocol errors no longer cause
4950 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4952 Calling x_check_errors signals an Emacs error if an X error has
4953 occurred since the last call to x_catch_errors or x_check_errors.
4955 Calling x_uncatch_errors resumes the normal error handling. */
4957 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4962 /* Make sure any errors from previous requests have been dealt with. */
4963 XSync (x_current_display
, False
);
4965 /* Set up the error buffer. */
4966 x_caught_error_message
4967 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4968 x_caught_error_message
[0] = '\0';
4970 /* Install our little error handler. */
4971 XHandleError (x_error_catcher
);
4974 /* If any X protocol errors have arrived since the last call to
4975 x_catch_errors or x_check_errors, signal an Emacs error using
4976 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4979 x_check_errors (format
)
4982 /* Make sure to catch any errors incurred so far. */
4983 XSync (x_current_display
, False
);
4985 if (x_caught_error_message
[0])
4987 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4989 sprintf (buf
, format
, x_caught_error_message
);
4990 x_uncatch_errors ();
4995 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
5000 /* Make sure to catch any errors incurred so far. */
5001 XSync (x_current_display
, False
);
5003 return x_caught_error_message
[0] != 0;
5006 /* Stop catching X protocol errors and let them make Emacs die. */
5011 xfree (x_caught_error_message
);
5012 x_caught_error_message
= 0;
5013 XHandleError (x_error_quitter
);
5017 static unsigned int x_wire_count
;
5020 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5025 /* Changing the font of the frame. */
5027 /* Set the font of the x-window specified by frame F
5028 to the font named NEWNAME. This is safe to use
5029 even before F has an actual x-window. */
5039 /* A table of all the fonts we have already loaded. */
5040 static struct font_info
*x_font_table
;
5042 /* The current capacity of x_font_table. */
5043 static int x_font_table_size
;
5045 /* The number of fonts actually stored in x_font_table.
5046 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
5047 0 <= n_fonts <= x_font_table_size. */
5051 x_new_font (f
, fontname
)
5053 register char *fontname
;
5056 int n_matching_fonts
;
5057 XFontStruct
*font_info
;
5060 /* Get a list of all the fonts that match this name. Once we
5061 have a list of matching fonts, we compare them against the fonts
5062 we already have by comparing font ids. */
5063 font_names
= (char **) XListFonts (x_current_display
, fontname
,
5064 1024, &n_matching_fonts
);
5065 /* Apparently it doesn't set n_matching_fonts to zero when it can't
5066 find any matches; font_names == 0 is the only clue. */
5068 n_matching_fonts
= 0;
5070 /* Don't just give up if n_matching_fonts is 0.
5071 Apparently there's a bug on Suns: XListFontsWithInfo can
5072 fail to find a font, but XLoadQueryFont may still find it. */
5074 /* See if we've already loaded a matching font. */
5075 already_loaded
= -1;
5076 if (n_matching_fonts
!= 0)
5080 for (i
= 0; i
< n_fonts
; i
++)
5081 for (j
= 0; j
< n_matching_fonts
; j
++)
5082 if (!strcmp (x_font_table
[i
].name
, font_names
[j
]))
5085 fontname
= font_names
[j
];
5091 /* If we have, just return it from the table. */
5092 if (already_loaded
>= 0)
5093 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
5095 /* Otherwise, load the font and add it to the table. */
5101 /* Try to find a character-cell font in the list. */
5103 /* A laudable goal, but this isn't how to do it. */
5104 for (i
= 0; i
< n_matching_fonts
; i
++)
5105 if (! font_info
[i
].per_char
)
5111 /* See comment above. */
5112 if (n_matching_fonts
!= 0)
5113 fontname
= font_names
[i
];
5115 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
5118 /* Free the information from XListFonts. */
5119 if (n_matching_fonts
)
5120 XFreeFontNames (font_names
);
5124 /* Do we need to create the table? */
5125 if (x_font_table_size
== 0)
5127 x_font_table_size
= 16;
5129 = (struct font_info
*) xmalloc (x_font_table_size
5130 * sizeof (x_font_table
[0]));
5132 /* Do we need to grow the table? */
5133 else if (n_fonts
>= x_font_table_size
)
5135 x_font_table_size
*= 2;
5137 = (struct font_info
*) xrealloc (x_font_table
,
5139 * sizeof (x_font_table
[0])));
5142 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
5143 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
5144 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
5147 /* Now make the frame display the given font. */
5148 if (FRAME_X_WINDOW (f
) != 0)
5150 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
5151 f
->display
.x
->font
->fid
);
5152 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
5153 f
->display
.x
->font
->fid
);
5154 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
5155 f
->display
.x
->font
->fid
);
5157 frame_update_line_height (f
);
5158 x_set_window_size (f
, 0, f
->width
, f
->height
);
5161 /* If we are setting a new frame's font for the first time,
5162 there are no faces yet, so this font's height is the line height. */
5163 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
5166 Lisp_Object lispy_name
;
5168 lispy_name
= build_string (fontname
);
5170 /* Free the information from XListFonts. The data
5171 we actually retain comes from XLoadQueryFont. */
5172 XFreeFontNames (font_names
);
5177 #else /* ! defined (HAVE_X11) */
5178 x_new_font (f
, newname
)
5180 register char *newname
;
5185 temp
= XGetFont (newname
);
5186 if (temp
== (FONT_TYPE
*) 0)
5189 if (f
->display
.x
->font
)
5190 XLoseFont (f
->display
.x
->font
);
5192 f
->display
.x
->font
= temp
;
5194 if (FRAME_X_WINDOW (f
) != 0)
5195 x_set_window_size (f
, 0, f
->width
, f
->height
);
5199 #endif /* ! defined (HAVE_X11) */
5201 x_calc_absolute_position (f
)
5206 int win_x
= 0, win_y
= 0;
5207 int flags
= f
->display
.x
->size_hint_flags
;
5209 /* Find the position of the outside upper-left corner of
5210 the inner window, with respect to the outer window. */
5211 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
5214 XTranslateCoordinates (x_current_display
,
5216 /* From-window, to-window. */
5217 f
->display
.x
->window_desc
,
5218 f
->display
.x
->parent_desc
,
5220 /* From-position, to-position. */
5221 0, 0, &win_x
, &win_y
,
5228 /* Treat negative positions as relative to the leftmost bottommost
5229 position that fits on the screen. */
5230 if (flags
& XNegative
)
5231 f
->display
.x
->left_pos
= (x_screen_width
5232 - 2 * f
->display
.x
->border_width
- win_x
5234 + f
->display
.x
->left_pos
);
5236 if (flags
& YNegative
)
5237 f
->display
.x
->top_pos
= (x_screen_height
5238 - 2 * f
->display
.x
->border_width
- win_y
5240 + f
->display
.x
->top_pos
);
5241 /* The left_pos and top_pos
5242 are now relative to the top and left screen edges,
5243 so the flags should correspond. */
5244 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5245 #else /* ! defined (HAVE_X11) */
5246 WINDOWINFO_TYPE parentinfo
;
5248 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
5250 if (f
->display
.x
->left_pos
< 0)
5251 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
5252 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
5254 if (f
->display
.x
->top_pos
< 0)
5255 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
5256 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
5257 #endif /* ! defined (HAVE_X11) */
5260 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5261 to really change the position, and 0 when calling from
5262 x_make_frame_visible (in that case, XOFF and YOFF are the current
5263 position values). */
5265 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5267 register int xoff
, yoff
;
5272 f
->display
.x
->top_pos
= yoff
;
5273 f
->display
.x
->left_pos
= xoff
;
5274 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5276 f
->display
.x
->size_hint_flags
|= XNegative
;
5278 f
->display
.x
->size_hint_flags
|= YNegative
;
5279 f
->display
.x
->win_gravity
= NorthWestGravity
;
5281 x_calc_absolute_position (f
);
5284 x_wm_set_size_hint (f
, 0, 0);
5286 #ifdef USE_X_TOOLKIT
5287 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
5288 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5289 #else /* not USE_X_TOOLKIT */
5290 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
5291 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5292 #endif /* not USE_X_TOOLKIT */
5296 /* Call this to change the size of frame F's x-window.
5297 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5298 for this size change and subsequent size changes.
5299 Otherwise we leave the window gravity unchanged. */
5301 x_set_window_size (f
, change_gravity
, cols
, rows
)
5306 int pixelwidth
, pixelheight
;
5309 #ifdef USE_X_TOOLKIT
5312 /* The x and y position of the widget is clobbered by the
5313 call to XtSetValues within EmacsFrameSetCharSize.
5314 This is a real kludge, but I don't understand Xt so I can't
5315 figure out a correct fix. Can anyone else tell me? -- rms. */
5316 int xpos
= f
->display
.x
->widget
->core
.x
;
5317 int ypos
= f
->display
.x
->widget
->core
.y
;
5318 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
5319 f
->display
.x
->widget
->core
.x
= xpos
;
5320 f
->display
.x
->widget
->core
.y
= ypos
;
5324 #else /* not USE_X_TOOLKIT */
5328 check_frame_size (f
, &rows
, &cols
);
5329 f
->display
.x
->vertical_scroll_bar_extra
5330 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5331 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
5333 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5334 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5337 f
->display
.x
->win_gravity
= NorthWestGravity
;
5338 x_wm_set_size_hint (f
, 0, 0);
5339 #endif /* ! defined (HAVE_X11) */
5340 XSync (x_current_display
, False
);
5341 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
5343 /* Now, strictly speaking, we can't be sure that this is accurate,
5344 but the window manager will get around to dealing with the size
5345 change request eventually, and we'll hear how it went when the
5346 ConfigureNotify event gets here.
5348 We could just not bother storing any of this information here,
5349 and let the ConfigureNotify event set everything up, but that
5350 might be kind of confusing to the lisp code, since size changes
5351 wouldn't be reported in the frame parameters until some random
5352 point in the future when the ConfigureNotify event arrives. */
5353 change_frame_size (f
, rows
, cols
, 0, 0);
5354 PIXEL_WIDTH (f
) = pixelwidth
;
5355 PIXEL_HEIGHT (f
) = pixelheight
;
5357 /* If cursor was outside the new size, mark it as off. */
5358 if (f
->phys_cursor_y
>= rows
5359 || f
->phys_cursor_x
>= cols
)
5361 f
->phys_cursor_x
= -1;
5362 f
->phys_cursor_y
= -1;
5365 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5366 receive in the ConfigureNotify event; if we get what we asked
5367 for, then the event won't cause the screen to become garbaged, so
5368 we have to make sure to do it here. */
5369 SET_FRAME_GARBAGED (f
);
5373 #endif /* not USE_X_TOOLKIT */
5377 x_set_resize_hint (f
)
5380 XSetResizeHint (FRAME_X_WINDOW (f
),
5381 2 * f
->display
.x
->internal_border_width
,
5382 2 * f
->display
.x
->internal_border_width
,
5383 FONT_WIDTH (f
->display
.x
->font
),
5384 f
->display
.x
->line_height
);
5386 #endif /* HAVE_X11 */
5388 /* Mouse warping, focus shifting, raising and lowering. */
5391 x_set_mouse_position (f
, x
, y
)
5397 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
5398 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
5400 if (pix_x
< 0) pix_x
= 0;
5401 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5403 if (pix_y
< 0) pix_y
= 0;
5404 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5408 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5412 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5415 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5421 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5426 x_focus_on_frame (f
)
5429 #if 0 /* This proves to be unpleasant. */
5433 /* I don't think that the ICCCM allows programs to do things like this
5434 without the interaction of the window manager. Whatever you end up
5435 doing with this code, do it to x_unfocus_frame too. */
5436 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
5437 RevertToPointerRoot
, CurrentTime
);
5445 /* Look at the remarks in x_focus_on_frame. */
5446 if (x_focus_frame
== f
)
5447 XSetInputFocus (x_current_display
, PointerRoot
,
5448 RevertToPointerRoot
, CurrentTime
);
5452 #endif /* ! defined (HAVE_X11) */
5454 /* Raise frame F. */
5459 if (f
->async_visible
)
5462 #ifdef USE_X_TOOLKIT
5463 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5464 #else /* not USE_X_TOOLKIT */
5465 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5466 #endif /* not USE_X_TOOLKIT */
5472 /* Lower frame F. */
5477 if (f
->async_visible
)
5480 #ifdef USE_X_TOOLKIT
5481 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5482 #else /* not USE_X_TOOLKIT */
5483 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5484 #endif /* not USE_X_TOOLKIT */
5491 XTframe_raise_lower (f
, raise
)
5502 /* Change from withdrawn state to mapped state,
5505 x_make_frame_visible (f
)
5512 if (! FRAME_VISIBLE_P (f
))
5515 #ifndef USE_X_TOOLKIT
5516 if (! FRAME_ICONIFIED_P (f
))
5517 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5520 if (! EQ (Vx_no_window_manager
, Qt
))
5521 x_wm_set_window_state (f
, NormalState
);
5522 #ifdef USE_X_TOOLKIT
5523 /* This was XtPopup, but that did nothing for an iconified frame. */
5524 XtMapWidget (f
->display
.x
->widget
);
5525 #else /* not USE_X_TOOLKIT */
5526 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5527 #endif /* not USE_X_TOOLKIT */
5528 #if 0 /* This seems to bring back scroll bars in the wrong places
5529 if the window configuration has changed. They seem
5530 to come back ok without this. */
5531 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5532 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5534 #else /* ! defined (HAVE_X11) */
5535 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5536 if (f
->display
.x
->icon_desc
!= 0)
5537 XUnmapWindow (f
->display
.x
->icon_desc
);
5539 /* Handled by the MapNotify event for X11 */
5540 f
->async_visible
= 1;
5541 f
->async_iconified
= 0;
5543 /* NOTE: this may cause problems for the first frame. */
5545 #endif /* ! defined (HAVE_X11) */
5553 /* Change from mapped state to withdrawn state. */
5555 x_make_frame_invisible (f
)
5561 #ifdef USE_X_TOOLKIT
5562 /* Use the frame's outermost window, not the one we normally draw on. */
5563 window
= XtWindow (f
->display
.x
->widget
);
5564 #else /* not USE_X_TOOLKIT */
5565 window
= FRAME_X_WINDOW (f
);
5566 #endif /* not USE_X_TOOLKIT */
5568 /* Don't keep the highlight on an invisible frame. */
5569 if (x_highlight_frame
== f
)
5570 x_highlight_frame
= 0;
5572 #if 0/* This might add unreliability; I don't trust it -- rms. */
5573 if (! f
->async_visible
&& ! f
->async_iconified
)
5579 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5580 that the current position of the window is user-specified, rather than
5581 program-specified, so that when the window is mapped again, it will be
5582 placed at the same location, without forcing the user to position it
5583 by hand again (they have already done that once for this window.) */
5584 x_wm_set_size_hint (f
, 0, 1);
5588 if (! XWithdrawWindow (x_current_display
, window
,
5589 DefaultScreen (x_current_display
)))
5591 UNBLOCK_INPUT_RESIGNAL
;
5592 error ("Can't notify window manager of window withdrawal");
5594 #else /* ! defined (HAVE_X11R4) */
5597 /* Tell the window manager what we're going to do. */
5598 if (! EQ (Vx_no_window_manager
, Qt
))
5602 unmap
.xunmap
.type
= UnmapNotify
;
5603 unmap
.xunmap
.window
= window
;
5604 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5605 unmap
.xunmap
.from_configure
= False
;
5606 if (! XSendEvent (x_current_display
,
5607 DefaultRootWindow (x_current_display
),
5609 SubstructureRedirectMask
|SubstructureNotifyMask
,
5612 UNBLOCK_INPUT_RESIGNAL
;
5613 error ("Can't notify window manager of withdrawal");
5617 /* Unmap the window ourselves. Cheeky! */
5618 XUnmapWindow (x_current_display
, window
);
5619 #else /* ! defined (HAVE_X11) */
5621 XUnmapWindow (FRAME_X_WINDOW (f
));
5622 if (f
->display
.x
->icon_desc
!= 0)
5623 XUnmapWindow (f
->display
.x
->icon_desc
);
5625 #endif /* ! defined (HAVE_X11) */
5626 #endif /* ! defined (HAVE_X11R4) */
5628 /* We can't distinguish this from iconification
5629 just by the event that we get from the server.
5630 So we can't win using the usual strategy of letting
5631 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5632 and synchronize with the server to make sure we agree. */
5634 FRAME_ICONIFIED_P (f
) = 0;
5635 f
->async_visible
= 0;
5636 f
->async_iconified
= 0;
5643 /* Change window state from mapped to iconified. */
5651 /* Don't keep the highlight on an invisible frame. */
5652 if (x_highlight_frame
== f
)
5653 x_highlight_frame
= 0;
5655 if (f
->async_iconified
)
5658 #ifdef USE_X_TOOLKIT
5661 if (! FRAME_VISIBLE_P (f
))
5663 if (! EQ (Vx_no_window_manager
, Qt
))
5664 x_wm_set_window_state (f
, IconicState
);
5665 /* This was XtPopup, but that did nothing for an iconified frame. */
5666 XtMapWidget (f
->display
.x
->widget
);
5671 result
= XIconifyWindow (x_current_display
,
5672 XtWindow (f
->display
.x
->widget
),
5673 DefaultScreen (x_current_display
));
5677 error ("Can't notify window manager of iconification");
5679 f
->async_iconified
= 1;
5684 #else /* not USE_X_TOOLKIT */
5689 /* Make sure the X server knows where the window should be positioned,
5690 in case the user deiconifies with the window manager. */
5691 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5692 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5694 /* Since we don't know which revision of X we're running, we'll use both
5695 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5697 /* X11R4: send a ClientMessage to the window manager using the
5698 WM_CHANGE_STATE type. */
5702 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5703 message
.xclient
.type
= ClientMessage
;
5704 message
.xclient
.message_type
= Xatom_wm_change_state
;
5705 message
.xclient
.format
= 32;
5706 message
.xclient
.data
.l
[0] = IconicState
;
5708 if (! XSendEvent (x_current_display
,
5709 DefaultRootWindow (x_current_display
),
5711 SubstructureRedirectMask
| SubstructureNotifyMask
,
5714 UNBLOCK_INPUT_RESIGNAL
;
5715 error ("Can't notify window manager of iconification");
5719 /* X11R3: set the initial_state field of the window manager hints to
5721 x_wm_set_window_state (f
, IconicState
);
5723 if (!FRAME_VISIBLE_P (f
))
5725 /* If the frame was withdrawn, before, we must map it. */
5726 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5727 #if 0 /* We don't have subwindows in the icon. */
5728 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5729 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5733 f
->async_iconified
= 1;
5734 #else /* ! defined (HAVE_X11) */
5735 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5737 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
5738 if (f
->display
.x
->icon_desc
!= 0)
5740 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
5743 #endif /* ! defined (HAVE_X11) */
5747 #endif /* not USE_X_TOOLKIT */
5750 /* Destroy the X window of frame F. */
5752 x_destroy_window (f
)
5757 if (f
->display
.x
->icon_desc
!= 0)
5758 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5759 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5760 #ifdef USE_X_TOOLKIT
5761 XtDestroyWidget (f
->display
.x
->widget
);
5762 free_frame_menubar (f
);
5763 #endif /* USE_X_TOOLKIT */
5765 free_frame_faces (f
);
5768 xfree (f
->display
.x
);
5770 if (f
== x_focus_frame
)
5772 if (f
== x_highlight_frame
)
5773 x_highlight_frame
= 0;
5775 if (f
== mouse_face_mouse_frame
)
5777 mouse_face_beg_row
= mouse_face_beg_col
= -1;
5778 mouse_face_end_row
= mouse_face_end_col
= -1;
5779 mouse_face_window
= Qnil
;
5785 /* Manage event queues for X10. */
5789 /* Manage event queues.
5791 This code is only used by the X10 support.
5793 We cannot leave events in the X queue and get them when we are ready
5794 because X does not provide a subroutine to get only a certain kind
5795 of event but not block if there are no queued events of that kind.
5797 Therefore, we must examine events as they come in and copy events
5798 of certain kinds into our private queues.
5800 All ExposeRegion events are put in x_expose_queue.
5801 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5804 /* Write the event *P_XREP into the event queue *QUEUE.
5805 If the queue is full, do nothing, but return nonzero. */
5808 enqueue_event (p_xrep
, queue
)
5809 register XEvent
*p_xrep
;
5810 register struct event_queue
*queue
;
5812 int newindex
= queue
->windex
+ 1;
5813 if (newindex
== EVENT_BUFFER_SIZE
)
5815 if (newindex
== queue
->rindex
)
5817 queue
->xrep
[queue
->windex
] = *p_xrep
;
5818 queue
->windex
= newindex
;
5822 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5823 If *QUEUE is empty, do nothing and return 0. */
5826 dequeue_event (p_xrep
, queue
)
5827 register XEvent
*p_xrep
;
5828 register struct event_queue
*queue
;
5830 if (queue
->windex
== queue
->rindex
)
5832 *p_xrep
= queue
->xrep
[queue
->rindex
++];
5833 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
5838 /* Return the number of events buffered in *QUEUE. */
5841 queue_event_count (queue
)
5842 register struct event_queue
*queue
;
5844 int tem
= queue
->windex
- queue
->rindex
;
5847 return EVENT_BUFFER_SIZE
+ tem
;
5850 /* Return nonzero if mouse input is pending. */
5853 mouse_event_pending_p ()
5855 return queue_event_count (&x_mouse_queue
);
5857 #endif /* HAVE_X11 */
5859 /* Setting window manager hints. */
5863 /* Set the normal size hints for the window manager, for frame F.
5864 FLAGS is the flags word to use--or 0 meaning preserve the flags
5865 that the window now has.
5866 If USER_POSITION is nonzero, we set the USPosition
5867 flag (this is useful when FLAGS is 0). */
5869 x_wm_set_size_hint (f
, flags
, user_position
)
5874 XSizeHints size_hints
;
5876 #ifdef USE_X_TOOLKIT
5879 Dimension widget_width
, widget_height
;
5880 Window window
= XtWindow (f
->display
.x
->widget
);
5881 #else /* not USE_X_TOOLKIT */
5882 Window window
= FRAME_X_WINDOW (f
);
5883 #endif /* not USE_X_TOOLKIT */
5885 /* Setting PMaxSize caused various problems. */
5886 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5888 flexlines
= f
->height
;
5890 size_hints
.x
= f
->display
.x
->left_pos
;
5891 size_hints
.y
= f
->display
.x
->top_pos
;
5893 #ifdef USE_X_TOOLKIT
5894 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5895 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5896 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5897 size_hints
.height
= widget_height
;
5898 size_hints
.width
= widget_width
;
5899 #else /* not USE_X_TOOLKIT */
5900 size_hints
.height
= PIXEL_HEIGHT (f
);
5901 size_hints
.width
= PIXEL_WIDTH (f
);
5902 #endif /* not USE_X_TOOLKIT */
5904 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5905 size_hints
.height_inc
= f
->display
.x
->line_height
;
5906 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5907 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5910 int base_width
, base_height
;
5911 int min_rows
= 0, min_cols
= 0;
5913 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5914 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5916 check_frame_size (f
, &min_rows
, &min_cols
);
5918 /* The window manager uses the base width hints to calculate the
5919 current number of rows and columns in the frame while
5920 resizing; min_width and min_height aren't useful for this
5921 purpose, since they might not give the dimensions for a
5922 zero-row, zero-column frame.
5924 We use the base_width and base_height members if we have
5925 them; otherwise, we set the min_width and min_height members
5926 to the size for a zero x zero frame. */
5929 size_hints
.flags
|= PBaseSize
;
5930 size_hints
.base_width
= base_width
;
5931 size_hints
.base_height
= base_height
;
5932 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5933 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5935 size_hints
.min_width
= base_width
;
5936 size_hints
.min_height
= base_height
;
5941 size_hints
.flags
|= flags
;
5944 XSizeHints hints
; /* Sometimes I hate X Windows... */
5945 long supplied_return
;
5949 value
= XGetWMNormalHints (x_current_display
, window
, &hints
,
5952 value
= XGetNormalHints (x_current_display
, window
, &hints
);
5957 if (hints
.flags
& PSize
)
5958 size_hints
.flags
|= PSize
;
5959 if (hints
.flags
& PPosition
)
5960 size_hints
.flags
|= PPosition
;
5961 if (hints
.flags
& USPosition
)
5962 size_hints
.flags
|= USPosition
;
5963 if (hints
.flags
& USSize
)
5964 size_hints
.flags
|= USSize
;
5968 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5969 size_hints
.flags
|= PWinGravity
;
5973 size_hints
.flags
&= ~ PPosition
;
5974 size_hints
.flags
|= USPosition
;
5976 #endif /* PWinGravity */
5979 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
5981 XSetNormalHints (x_current_display
, window
, &size_hints
);
5985 /* Used for IconicState or NormalState */
5986 x_wm_set_window_state (f
, state
)
5990 #ifdef USE_X_TOOLKIT
5993 XtSetArg (al
[0], XtNinitialState
, state
);
5994 XtSetValues (f
->display
.x
->widget
, al
, 1);
5995 #else /* not USE_X_TOOLKIT */
5996 Window window
= FRAME_X_WINDOW (f
);
5998 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5999 f
->display
.x
->wm_hints
.initial_state
= state
;
6001 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6002 #endif /* not USE_X_TOOLKIT */
6005 x_wm_set_icon_pixmap (f
, icon_pixmap
)
6009 #ifdef USE_X_TOOLKIT
6010 Window window
= XtWindow (f
->display
.x
->widget
);
6012 Window window
= FRAME_X_WINDOW (f
);
6017 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6018 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
6021 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
6023 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6026 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6030 #ifdef USE_X_TOOLKIT
6031 Window window
= XtWindow (f
->display
.x
->widget
);
6033 Window window
= FRAME_X_WINDOW (f
);
6036 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
6037 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
6038 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
6040 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6044 /* Initialization. */
6046 #ifdef USE_X_TOOLKIT
6047 static XrmOptionDescRec emacs_options
[] = {
6048 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6049 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6051 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6052 XrmoptionSepArg
, NULL
},
6053 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6055 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6056 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6057 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6058 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6059 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6060 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6061 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6063 #endif /* USE_X_TOOLKIT */
6066 x_term_init (display_name
, xrm_option
, resource_name
)
6069 char *resource_name
;
6075 #ifndef F_SETOWN_BUG
6077 extern int old_fcntl_owner
;
6078 #endif /* ! defined (F_SETOWN) */
6079 #endif /* F_SETOWN_BUG */
6081 x_focus_frame
= x_highlight_frame
= 0;
6083 #ifdef USE_X_TOOLKIT
6084 argv
= (char **) XtMalloc (7 * sizeof (char *));
6086 argv
[1] = "-display";
6087 argv
[2] = display_name
;
6089 /* Usually `emacs', but not always. */
6090 argv
[4] = resource_name
;
6094 argv
[argc
++] = "-xrm";
6095 argv
[argc
++] = xrm_option
;
6097 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
6098 emacs_options
, XtNumber (emacs_options
),
6101 XtFree ((char *)argv
);
6102 x_current_display
= XtDisplay (Xt_app_shell
);
6104 #else /* not USE_X_TOOLKIT */
6105 x_current_display
= XOpenDisplay (display_name
);
6106 #endif /* not USE_X_TOOLKIT */
6107 if (x_current_display
== 0)
6108 fatal ("X server %s not responding.\n\
6109 Check the DISPLAY environment variable or use \"-d\"\n",
6115 XSetAfterFunction (x_current_display
, x_trace_wire
);
6117 hostname
= get_system_name ();
6118 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
6121 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
6124 /* Figure out which modifier bits mean what. */
6125 x_find_modifier_meanings ();
6127 /* Get the scroll bar cursor. */
6128 x_vertical_scroll_bar_cursor
6129 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
6132 /* Watch for PropertyNotify events on the root window; we use them
6133 to figure out when to invalidate our cache of the cut buffers. */
6134 x_watch_cut_buffer_cache ();
6137 if (ConnectionNumber (x_current_display
) != 0)
6138 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
6139 change_input_fd (ConnectionNumber (x_current_display
));
6141 #endif /* ! defined (HAVE_X11) */
6143 #ifndef F_SETOWN_BUG
6145 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
6146 #ifdef F_SETOWN_SOCK_NEG
6147 /* stdin is a socket here */
6148 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
6149 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6150 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
6151 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6152 #endif /* ! defined (F_SETOWN) */
6153 #endif /* F_SETOWN_BUG */
6157 #endif /* ! defined (SIGIO) */
6159 expose_all_windows
= 0;
6161 clear_frame_hook
= XTclear_frame
;
6162 clear_end_of_line_hook
= XTclear_end_of_line
;
6163 ins_del_lines_hook
= XTins_del_lines
;
6164 change_line_highlight_hook
= XTchange_line_highlight
;
6165 insert_glyphs_hook
= XTinsert_glyphs
;
6166 write_glyphs_hook
= XTwrite_glyphs
;
6167 delete_glyphs_hook
= XTdelete_glyphs
;
6168 ring_bell_hook
= XTring_bell
;
6169 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6170 set_terminal_modes_hook
= XTset_terminal_modes
;
6171 update_begin_hook
= XTupdate_begin
;
6172 update_end_hook
= XTupdate_end
;
6173 set_terminal_window_hook
= XTset_terminal_window
;
6174 read_socket_hook
= XTread_socket
;
6175 frame_up_to_date_hook
= XTframe_up_to_date
;
6176 cursor_to_hook
= XTcursor_to
;
6177 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6178 mouse_position_hook
= XTmouse_position
;
6179 frame_rehighlight_hook
= XTframe_rehighlight
;
6180 frame_raise_lower_hook
= XTframe_raise_lower
;
6181 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6182 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6183 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6184 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6186 scroll_region_ok
= 1; /* we'll scroll partial frames */
6187 char_ins_del_ok
= 0; /* just as fast to write the line */
6188 line_ins_del_ok
= 1; /* we'll just blt 'em */
6189 fast_clear_end_of_line
= 1; /* X does this well */
6190 memory_below_frame
= 0; /* we don't remember what scrolls
6194 /* Try to use interrupt input; if we can't, then start polling. */
6195 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6197 /* Note that there is no real way portable across R3/R4 to get the
6198 original error handler. */
6199 XHandleError (x_error_quitter
);
6200 XHandleIOError (x_io_error_quitter
);
6202 /* Disable Window Change signals; they are handled by X events. */
6204 signal (SIGWINCH
, SIG_DFL
);
6205 #endif /* ! defined (SIGWINCH) */
6207 signal (SIGPIPE
, x_connection_closed
);
6213 staticpro (&last_mouse_scroll_bar
);
6214 last_mouse_scroll_bar
= Qnil
;
6215 staticpro (&mouse_face_window
);
6216 mouse_face_window
= Qnil
;
6218 #endif /* ! defined (HAVE_X11) */
6219 #endif /* ! defined (HAVE_X_WINDOWS) */