1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993 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. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 #define NEW_SELECTIONS
30 /* On 4.3 these lose if they come after xterm.h. */
31 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
32 /* Putting these at the beginning seems to be standard for other .c files. */
41 #include "blockinput.h"
43 /* This may include sys/types.h, and that somehow loses
44 if this is not done before the other system files. */
46 #include <X11/cursorfont.h>
49 /* Load sys/types.h if not already loaded.
50 In some systems loading it twice is suicidal. */
52 #include <sys/types.h>
57 #include <sys/ioctl.h>
59 #else /* ! defined (BSD) */
63 #endif /* ! defined (BSD) */
73 #include <sys/param.h>
75 #include "dispextern.h"
76 #include "termhooks.h"
90 #define XMapWindow XMapRaised /* Raise them when mapping. */
91 #else /* ! defined (HAVE_X11) */
92 #include <X/Xkeyboard.h>
93 /*#include <X/Xproto.h> */
94 #endif /* ! defined (HAVE_X11) */
97 /* We could get this from param.h, but better not to depend on finding that.
98 And better not to risk that it might define other symbols used in this
101 #define MAXDESC FD_SETSIZE
105 #define SELECT_TYPE fd_set
106 #else /* no FD_SET */
108 #define SELECT_TYPE int
110 /* Define the macros to access a single-int bitmap of descriptors. */
111 #define FD_SET(n, p) (*(p) |= (1 << (n)))
112 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
113 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
114 #define FD_ZERO(p) (*(p) = 0)
115 #endif /* no FD_SET */
117 /* For sending Meta-characters. Do we need this? */
120 #define min(a,b) ((a)<(b) ? (a) : (b))
121 #define max(a,b) ((a)>(b) ? (a) : (b))
123 /* Nonzero means we must reprint all windows
124 because 1) we received an ExposeWindow event
125 or 2) we received too many ExposeRegion events to record.
127 This is never needed under X11. */
128 static int expose_all_windows
;
130 /* Nonzero means we must reprint all icon windows. */
132 static int expose_all_icons
;
135 /* ExposeRegion events, when received, are copied into this queue
136 for later processing. */
138 static struct event_queue x_expose_queue
;
140 /* ButtonPressed and ButtonReleased events, when received,
141 are copied into this queue for later processing. */
143 struct event_queue x_mouse_queue
;
144 #endif /* HAVE_X11 */
146 #if defined (SIGIO) && defined (FIONREAD)
147 int BLOCK_INPUT_mask
;
148 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
150 /* The id of a bitmap used for icon windows.
151 One such map is shared by all Emacs icon windows.
152 This is zero if we have not yet had a need to create the bitmap. */
154 static Bitmap icon_bitmap
;
156 /* Font used for text icons. */
158 static FONT_TYPE
*icon_font_info
;
160 /* Stuff for dealing with the main icon title. */
162 extern Lisp_Object Vcommand_line_args
;
163 char *hostname
, *x_id_name
;
165 /* This is the X connection that we are using. */
167 Display
*x_current_display
;
169 /* The cursor to use for vertical scroll bars on x_current_display. */
170 static Cursor x_vertical_scroll_bar_cursor
;
172 /* Frame being updated by update_frame. This is declared in term.c.
173 This is set by update_begin and looked at by all the
174 XT functions. It is zero while not inside an update.
175 In that case, the XT functions assume that `selected_frame'
176 is the frame to apply to. */
177 extern struct frame
*updating_frame
;
179 /* The frame (if any) which has the X window that has keyboard focus.
180 Zero if none. This is examined by Ffocus_frame in frame.c. Note
181 that a mere EnterNotify event can set this; if you need to know the
182 last frame specified in a FocusIn or FocusOut event, use
183 x_focus_event_frame. */
184 struct frame
*x_focus_frame
;
186 /* The last frame mentioned in a FocusIn or FocusOut event. This is
187 separate from x_focus_frame, because whether or not LeaveNotify
188 events cause us to lose focus depends on whether or not we have
189 received a FocusIn event for it. */
190 struct frame
*x_focus_event_frame
;
192 /* The frame which currently has the visual highlight, and should get
193 keyboard input (other sorts of input have the frame encoded in the
194 event). It points to the X focus frame's selected window's
195 frame. It differs from x_focus_frame when we're using a global
197 static struct frame
*x_highlight_frame
;
199 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
200 mouse is moved to inside of frame when frame is de-iconified. */
202 static int warp_mouse_on_deiconify
;
204 /* During an update, maximum vpos for ins/del line operations to affect. */
206 static int flexlines
;
208 /* During an update, nonzero if chars output now should be highlighted. */
210 static int highlight
;
212 /* Nominal cursor position -- where to draw output.
213 During an update, these are different from the cursor-box position. */
219 /* `t' if a mouse button is depressed. */
221 extern Lisp_Object Vmouse_depressed
;
223 /* Tells if a window manager is present or not. */
225 extern Lisp_Object Vx_no_window_manager
;
227 /* Timestamp that we requested selection data was made. */
228 extern Time requestor_time
;
230 /* ID of the window requesting selection data. */
231 extern Window requestor_window
;
233 /* Nonzero enables some debugging for the X interface code. */
236 #else /* ! defined (HAVE_X11) */
238 /* Bit patterns for the mouse cursor. */
240 short MouseCursor
[] = {
241 0x0000, 0x0008, 0x0018, 0x0038,
242 0x0078, 0x00f8, 0x01f8, 0x03f8,
243 0x07f8, 0x00f8, 0x00d8, 0x0188,
244 0x0180, 0x0300, 0x0300, 0x0000};
246 short MouseMask
[] = {
247 0x000c, 0x001c, 0x003c, 0x007c,
248 0x00fc, 0x01fc, 0x03fc, 0x07fc,
249 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
250 0x03cc, 0x0780, 0x0780, 0x0300};
252 static short grey_bits
[] = {
253 0x0005, 0x000a, 0x0005, 0x000a};
255 static Pixmap GreyPixmap
= 0;
256 #endif /* ! defined (HAVE_X11) */
258 /* From time to time we get info on an Emacs window, here. */
260 static WINDOWINFO_TYPE windowinfo
;
264 /* A mask of extra modifier bits to put into every keyboard char. */
265 extern int extra_keyboard_modifiers
;
267 extern Display
*XOpenDisplay ();
268 extern Window
XCreateWindow ();
270 extern Cursor
XCreateCursor ();
271 extern FONT_TYPE
*XOpenFont ();
273 static void flashback ();
276 static void dumpqueue ();
277 #endif /* HAVE_X11 */
280 static int XTcursor_to ();
281 static int XTclear_end_of_line ();
284 /* Starting and ending updates.
286 These hooks are called by update_frame at the beginning and end
287 of a frame update. We record in `updating_frame' the identity
288 of the frame being updated, so that the XT... functions do not
289 need to take a frame as argument. Most of the XT... functions
290 should never be called except during an update, the only exceptions
291 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
293 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
304 flexlines
= f
->height
;
310 #endif /* HAVE_X11 */
315 static void x_do_pending_expose ();
324 if (updating_frame
== 0
325 || updating_frame
!= f
)
331 x_do_pending_expose ();
332 #endif /* HAVE_X11 */
334 x_display_cursor (f
, 1);
340 /* External interface to control of standout mode.
341 Call this when about to modify line at position VPOS
342 and not change whether it is highlighted. */
344 XTreassert_line_highlight (new, vpos
)
350 /* Call this when about to modify line at position VPOS
351 and change whether it is highlighted. */
354 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
355 int new_highlight
, vpos
, first_unused_hpos
;
357 highlight
= new_highlight
;
358 XTcursor_to (vpos
, 0);
359 XTclear_end_of_line (updating_frame
->width
);
362 /* This is used when starting Emacs and when restarting after suspend.
363 When starting Emacs, no X window is mapped. And nothing must be done
364 to Emacs's own window if it is suspended (though that rarely happens). */
367 XTset_terminal_modes ()
371 /* This is called when exiting or suspending Emacs.
372 Exiting will make the X-windows go away, and suspending
373 requires no action. */
376 XTreset_terminal_modes ()
378 /* XTclear_frame (); */
381 /* Set the nominal cursor position of the frame.
382 This is where display update commands will take effect.
383 This does not affect the place where the cursor-box is displayed. */
386 XTcursor_to (row
, col
)
387 register int row
, col
;
395 if (updating_frame
== 0)
398 x_display_cursor (selected_frame
, 1);
404 /* Display a sequence of N glyphs found at GP.
405 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
406 HL is 1 if this text is highlighted, 2 if the cursor is on it.
408 FONT is the default font to use (for glyphs whose font-code is 0).
410 Since the display generation code is responsible for calling
411 compute_char_face and compute_glyph_face on everything it puts in
412 the display structure, we can assume that the face code on each
413 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
414 to which we can actually apply intern_face. */
417 /* This is the multi-face code. */
420 dumpglyphs (f
, left
, top
, gp
, n
, hl
)
423 register GLYPH
*gp
; /* Points to first GLYPH. */
424 register int n
; /* Number of glyphs to display. */
427 /* Holds characters to be displayed. */
428 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
429 register char *cp
; /* Steps through buf[]. */
430 register int tlen
= GLYPH_TABLE_LENGTH
;
431 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
432 Window window
= FRAME_X_WINDOW (f
);
436 /* Get the face-code of the next GLYPH. */
440 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
443 /* Find the run of consecutive glyphs with the same face-code.
444 Extract their character codes into BUF. */
449 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
450 if (GLYPH_FACE (g
) != cf
)
453 *cp
++ = GLYPH_CHAR (g
);
458 /* LEN gets the length of the run. */
461 /* Now output this run of chars, with the font and pixel values
462 determined by the face code CF. */
464 struct face
*face
= FRAME_DEFAULT_FACE (f
);
465 FONT_TYPE
*font
= FACE_FONT (face
);
466 GC gc
= FACE_GC (face
);
468 int gc_temporary
= 0;
470 /* First look at the face of the text itself. */
473 /* The face codes on the glyphs must be valid indices into the
474 frame's face table. */
475 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
476 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
480 face
= FRAME_MODE_LINE_FACE (f
);
482 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
483 font
= FACE_FONT (face
);
488 /* Then comes the distinction between modeline and normal text. */
493 face
= FRAME_MODE_LINE_FACE (f
);
494 font
= FACE_FONT (face
);
499 #define FACE_DEFAULT (~0)
501 /* Now override that if the cursor's on this character. */
506 || (int) face
->font
== FACE_DEFAULT
)
508 gc
= f
->display
.x
->cursor_gc
;
510 /* Cursor on non-default face: must merge. */
516 xgcv
.background
= f
->display
.x
->cursor_pixel
;
517 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
518 xgcv
.font
= face
->font
->fid
;
519 xgcv
.graphics_exposures
= 0;
520 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
521 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
524 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
525 XSetStipple (x_current_display
, gc
, face
->stipple
);
531 if ((int) font
== FACE_DEFAULT
)
532 font
= f
->display
.x
->font
;
534 XDrawImageString (x_current_display
, window
, gc
,
535 left
, top
+ FONT_BASE (font
), buf
, len
);
538 XFreeGC (x_current_display
, gc
);
540 /* We should probably check for XA_UNDERLINE_POSITION and
541 XA_UNDERLINE_THICKNESS properties on the font, but let's
542 just get the thing working, and come back to that. */
544 int underline_position
= 1;
546 if (font
->descent
<= underline_position
)
547 underline_position
= font
->descent
- 1;
550 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
554 + underline_position
),
555 len
* FONT_WIDTH (font
), 1);
558 left
+= len
* FONT_WIDTH (font
);
565 /* This is the old single-face code. */
568 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
571 register GLYPH
*gp
; /* Points to first GLYPH. */
572 register int n
; /* Number of glyphs to display. */
577 Window window
= FRAME_X_WINDOW (f
);
578 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
579 : (hl
? f
->display
.x
->reverse_gc
580 : f
->display
.x
->normal_gc
));
582 if (sizeof (GLYPH
) == sizeof (XChar2b
))
583 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
584 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
585 else if (sizeof (GLYPH
) == sizeof (unsigned char))
586 XDrawImageString (x_current_display
, window
, drawing_gc
,
587 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
589 /* What size of glyph ARE you using? And does X have a function to
595 /* Output some text at the nominal frame cursor position.
596 Advance the cursor over the text.
597 Output LEN glyphs at START.
599 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
600 controls the pixel values used for foreground and background. */
603 XTwrite_glyphs (start
, len
)
604 register GLYPH
*start
;
607 register int temp_length
;
617 /* If not within an update,
618 output at the frame's visible cursor. */
619 curs_x
= f
->cursor_x
;
620 curs_y
= f
->cursor_y
;
624 CHAR_TO_PIXEL_COL (f
, curs_x
),
625 CHAR_TO_PIXEL_ROW (f
, curs_y
),
626 start
, len
, highlight
);
628 /* If we drew on top of the cursor, note that it is turned off. */
629 if (curs_y
== f
->phys_cursor_y
630 && curs_x
<= f
->phys_cursor_x
631 && curs_x
+ len
> f
->phys_cursor_x
)
632 f
->phys_cursor_x
= -1;
634 if (updating_frame
== 0)
637 x_display_cursor (f
, 1);
646 /* Clear to the end of the line.
647 Erase the current text line from the nominal cursor position (inclusive)
648 to column FIRST_UNUSED (exclusive). The idea is that everything
649 from FIRST_UNUSED onward is already erased. */
652 XTclear_end_of_line (first_unused
)
653 register int first_unused
;
655 struct frame
*f
= updating_frame
;
661 if (curs_y
< 0 || curs_y
>= f
->height
)
663 if (first_unused
<= 0)
666 if (first_unused
>= f
->width
)
667 first_unused
= f
->width
;
671 /* Notice if the cursor will be cleared by this operation. */
672 if (curs_y
== f
->phys_cursor_y
673 && curs_x
<= f
->phys_cursor_x
674 && f
->phys_cursor_x
< first_unused
)
675 f
->phys_cursor_x
= -1;
678 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
679 CHAR_TO_PIXEL_COL (f
, curs_x
),
680 CHAR_TO_PIXEL_ROW (f
, curs_y
),
681 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
682 FONT_HEIGHT (f
->display
.x
->font
), False
);
684 #else /* ! defined (HAVE_X11) */
685 XPixSet (FRAME_X_WINDOW (f
),
686 CHAR_TO_PIXEL_COL (f
, curs_x
),
687 CHAR_TO_PIXEL_ROW (f
, curs_y
),
688 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
689 FONT_HEIGHT (f
->display
.x
->font
),
690 f
->display
.x
->background_pixel
);
691 #endif /* ! defined (HAVE_X11) */
700 struct frame
*f
= updating_frame
;
705 f
->phys_cursor_x
= -1; /* Cursor not visible. */
706 curs_x
= 0; /* Nominal cursor position is top left. */
711 XClear (FRAME_X_WINDOW (f
));
713 /* We have to clear the scroll bars, too. If we have changed
714 colors or something like that, then they should be notified. */
715 x_scroll_bar_clear (f
);
719 #endif /* HAVE_X11 */
725 /* Invert the middle quarter of the frame for .15 sec. */
727 /* We use the select system call to do the waiting, so we have to make sure
728 it's available. If it isn't, we just won't do visual bells. */
729 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
731 /* Subtract the `struct timeval' values X and Y,
732 storing the result in RESULT.
733 Return 1 if the difference is negative, otherwise 0. */
736 timeval_subtract (result
, x
, y
)
737 struct timeval
*result
, x
, y
;
739 /* Perform the carry for the later subtraction by updating y.
740 This is safer because on some systems
741 the tv_sec member is unsigned. */
742 if (x
.tv_usec
< y
.tv_usec
)
744 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
745 y
.tv_usec
-= 1000000 * nsec
;
748 if (x
.tv_usec
- y
.tv_usec
> 1000000)
750 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
751 y
.tv_usec
+= 1000000 * nsec
;
755 /* Compute the time remaining to wait. tv_usec is certainly positive. */
756 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
757 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
759 /* Return indication of whether the result should be considered negative. */
760 return x
.tv_sec
< y
.tv_sec
;
771 /* Create a GC that will use the GXxor function to flip foreground pixels
772 into background pixels. */
776 values
.function
= GXxor
;
777 values
.foreground
= (f
->display
.x
->foreground_pixel
778 ^ f
->display
.x
->background_pixel
);
780 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
781 GCFunction
| GCForeground
, &values
);
785 int width
= PIXEL_WIDTH (f
);
786 int height
= PIXEL_HEIGHT (f
);
788 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
789 width
/4, height
/4, width
/2, height
/2);
790 XFlush (x_current_display
);
793 struct timeval wakeup
, now
;
795 gettimeofday (&wakeup
, (struct timezone
*) 0);
797 /* Compute time to wait until, propagating carry from usecs. */
798 wakeup
.tv_usec
+= 150000;
799 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
800 wakeup
.tv_usec
%= 1000000;
802 /* Keep waiting until past the time wakeup. */
805 struct timeval timeout
;
807 gettimeofday (&timeout
, (struct timezone
*)0);
809 /* In effect, timeout = wakeup - timeout.
810 Break if result would be negative. */
811 if (timeval_subtract (&timeout
, wakeup
, timeout
))
814 /* Try to wait that long--but we might wake up sooner. */
815 select (0, 0, 0, 0, &timeout
);
819 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
820 width
/4, height
/4, width
/2, height
/2);
821 XFreeGC (x_current_display
, gc
);
822 XFlush (x_current_display
);
832 /* Make audible bell. */
835 #define XRINGBELL XBell(x_current_display, 0)
836 #else /* ! defined (HAVE_X11) */
837 #define XRINGBELL XFeep(0);
838 #endif /* ! defined (HAVE_X11) */
842 if (x_current_display
== 0)
845 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
847 XTflash (selected_frame
);
858 /* Insert and delete character.
859 These are not supposed to be used because we are supposed to turn
860 off the feature of using them. */
863 XTinsert_glyphs (start
, len
)
864 register char *start
;
877 /* Specify how many text lines, from the top of the window,
878 should be affected by insert-lines and delete-lines operations.
879 This, and those operations, are used only within an update
880 that is bounded by calls to XTupdate_begin and XTupdate_end. */
883 XTset_terminal_window (n
)
886 if (updating_frame
== 0)
889 if ((n
<= 0) || (n
> updating_frame
->height
))
890 flexlines
= updating_frame
->height
;
895 /* Perform an insert-lines operation.
896 Insert N lines at a vertical position curs_y. */
902 register int topregion
, bottomregion
;
903 register int length
, newtop
, mask
;
904 register struct frame
*f
= updating_frame
;
905 int intborder
= f
->display
.x
->internal_border_width
;
907 if (curs_y
>= flexlines
)
911 bottomregion
= flexlines
- (n
+ 1);
912 newtop
= topregion
+ n
;
913 length
= (bottomregion
- topregion
) + 1;
917 #endif /* HAVE_X11 */
919 if ((length
> 0) && (newtop
<= flexlines
))
922 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
923 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
924 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
925 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
926 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
927 CHAR_TO_PIXEL_ROW (f
, newtop
));
928 #else /* ! defined (HAVE_X11) */
929 XMoveArea (FRAME_X_WINDOW (f
),
930 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
931 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
932 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
933 length
* FONT_HEIGHT (f
->display
.x
->font
));
934 /* Now we must process any ExposeRegion events that occur
935 if the area being copied from is obscured.
936 We can't let it wait because further i/d operations
937 may want to copy this area to another area. */
939 #endif /* ! defined (HAVE_X11) */
942 newtop
= min (newtop
, (flexlines
- 1));
943 length
= newtop
- topregion
;
947 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
948 CHAR_TO_PIXEL_ROW (f
, topregion
),
949 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
950 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
951 #else /* ! defined (HAVE_X11) */
952 XPixSet (FRAME_X_WINDOW (f
),
954 CHAR_TO_PIXEL_ROW (f
, topregion
),
955 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
956 n
* FONT_HEIGHT (f
->display
.x
->font
),
957 f
->display
.x
->background_pixel
);
958 #endif /* ! defined (HAVE_X11) */
962 /* Perform a delete-lines operation, deleting N lines
963 at a vertical position curs_y. */
970 register struct frame
*f
= updating_frame
;
971 int intborder
= f
->display
.x
->internal_border_width
;
973 if (curs_y
>= flexlines
)
978 #endif /* HAVE_X11 */
980 if ((curs_y
+ n
) >= flexlines
)
982 if (flexlines
>= (curs_y
+ 1))
985 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
986 CHAR_TO_PIXEL_ROW (f
, curs_y
),
987 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
988 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
989 #else /* ! defined (HAVE_X11) */
990 XPixSet (FRAME_X_WINDOW (f
),
991 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
992 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
993 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
994 f
->display
.x
->background_pixel
);
995 #endif /* ! defined (HAVE_X11) */
1001 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1002 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1004 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1005 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1006 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
1007 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1008 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1010 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1011 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1012 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
1013 #else /* ! defined (HAVE_X11) */
1014 XMoveArea (FRAME_X_WINDOW (f
),
1016 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1017 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1018 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1019 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
1020 /* Now we must process any ExposeRegion events that occur
1021 if the area being copied from is obscured.
1022 We can't let it wait because further i/d operations
1023 may want to copy this area to another area. */
1025 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1026 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1027 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1028 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
1029 #endif /* ! defined (HAVE_X11) */
1033 /* Perform an insert-lines or delete-lines operation,
1034 inserting N lines or deleting -N lines at vertical position VPOS. */
1036 XTins_del_lines (vpos
, n
)
1039 if (updating_frame
== 0)
1042 /* Hide the cursor. */
1043 x_display_cursor (updating_frame
, 0);
1045 XTcursor_to (vpos
, 0);
1056 /* Support routines for exposure events. */
1057 static void clear_cursor ();
1059 /* Output into a rectangle of an X-window (for frame F)
1060 the characters in f->phys_lines that overlap that rectangle.
1061 TOP and LEFT are the position of the upper left corner of the rectangle.
1062 ROWS and COLS are the size of the rectangle. */
1065 dumprectangle (f
, left
, top
, cols
, rows
)
1067 register int left
, top
, cols
, rows
;
1069 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1070 int cursor_cleared
= 0;
1074 if (FRAME_GARBAGED_P (f
))
1077 /* Express rectangle as four edges, instead of position-and-size. */
1078 bottom
= top
+ rows
;
1079 right
= left
+ cols
;
1081 #ifndef HAVE_X11 /* Window manger does this for X11. */
1083 int intborder
= f
->display
.x
->internal_border_width
;
1085 /* If the rectangle includes any of the internal border area,
1086 redisplay the border emphasis. */
1087 if (top
< intborder
|| left
< intborder
1088 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1089 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1092 #endif /* HAVE_X11 Window manger does this for X11. */
1094 /* Convert rectangle edges in pixels to edges in chars.
1095 Round down for left and top, up for right and bottom. */
1096 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1097 left
= PIXEL_TO_CHAR_COL (f
, left
);
1098 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1099 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1100 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1101 right
= PIXEL_TO_CHAR_COL (f
, right
);
1103 /* Clip the rectangle to what can be visible. */
1108 if (right
> f
->width
)
1110 if (bottom
> f
->height
)
1113 /* Get size in chars of the rectangle. */
1114 cols
= right
- left
;
1115 rows
= bottom
- top
;
1117 /* If rectangle has zero area, return. */
1118 if (rows
<= 0) return;
1119 if (cols
<= 0) return;
1121 /* Turn off the cursor if it is in the rectangle.
1122 We will turn it back on afterward. */
1123 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1124 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1130 /* Display the text in the rectangle, one text line at a time. */
1132 for (y
= top
; y
< bottom
; y
++)
1134 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1136 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1140 CHAR_TO_PIXEL_COL (f
, left
),
1141 CHAR_TO_PIXEL_ROW (f
, y
),
1142 line
, min (cols
, active_frame
->used
[y
] - left
),
1143 active_frame
->highlight
[y
]);
1146 /* Turn the cursor on if we turned it off. */
1149 x_display_cursor (f
, 1);
1153 /* Process all queued ExposeRegion events. */
1159 XExposeRegionEvent r
;
1161 while (dequeue_event (&r
, &x_expose_queue
))
1163 struct frame
*f
= x_window_to_frame (r
.window
);
1164 if (f
->display
.x
->icon_desc
== r
.window
)
1167 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1171 #endif /* HAVE_X11 */
1173 /* Process all expose events that are pending, for X10.
1174 Redraws the cursor if necessary on any frame that
1175 is not in the process of being updated with update_frame. */
1179 x_do_pending_expose ()
1183 Lisp_Object tail
, frame
;
1185 if (expose_all_windows
)
1187 expose_all_windows
= 0;
1188 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1190 register int temp_width
, temp_height
;
1193 frame
= XCONS (tail
)->car
;
1194 if (XGCTYPE (frame
) != Lisp_Frame
)
1197 if (! FRAME_X_P (f
))
1199 if (!f
->async_visible
)
1201 if (!f
->display
.x
->needs_exposure
)
1204 intborder
= f
->display
.x
->internal_border_width
;
1207 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1208 temp_width
= ((windowinfo
.width
- 2 * intborder
1209 - f
->display
.x
->v_scroll_bar_width
)
1210 / FONT_WIDTH (f
->display
.x
->font
));
1211 temp_height
= ((windowinfo
.height
- 2 * intborder
1212 - f
->display
.x
->h_scroll_bar_height
)
1213 / FONT_HEIGHT (f
->display
.x
->font
));
1214 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1216 change_frame_size (f
, max (1, temp_height
),
1217 max (1, temp_width
), 0, 1);
1218 x_resize_scroll_bars (f
);
1220 f
->display
.x
->left_pos
= windowinfo
.x
;
1221 f
->display
.x
->top_pos
= windowinfo
.y
;
1222 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1226 f
->display
.x
->needs_exposure
= 0;
1227 if (updating_frame
!= f
)
1228 x_display_cursor (f
, 1);
1233 /* Handle any individual-rectangle expose events queued
1234 for various windows. */
1237 #else /* ! defined (HAVE_X11) */
1239 #endif /* ! defined (HAVE_X11) */
1245 frame_highlight (frame
)
1246 struct frame
*frame
;
1248 /* We used to only do this if Vx_no_window_manager was non-nil, but
1249 the ICCCM (section 4.1.6) says that the window's border pixmap
1250 and border pixel are window attributes which are "private to the
1251 client", so we can always change it to whatever we want. */
1253 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1254 frame
->display
.x
->border_pixel
);
1256 x_display_cursor (frame
, 1);
1260 frame_unhighlight (frame
)
1261 struct frame
*frame
;
1263 /* We used to only do this if Vx_no_window_manager was non-nil, but
1264 the ICCCM (section 4.1.6) says that the window's border pixmap
1265 and border pixel are window attributes which are "private to the
1266 client", so we can always change it to whatever we want. */
1268 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1269 frame
->display
.x
->border_tile
);
1271 x_display_cursor (frame
, 1);
1273 #else /* ! defined (HAVE_X11) */
1274 /* Dump the border-emphasis of frame F.
1275 If F is selected, this is a lining of the same color as the border,
1276 just within the border, occupying a portion of the internal border.
1277 If F is not selected, it is background in the same place.
1278 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1280 ALWAYS = 1 is used when a frame becomes selected or deselected.
1281 In that case, we also turn the cursor off and on again
1282 so it will appear in the proper shape (solid if selected; else hollow.) */
1285 dumpborder (f
, always
)
1289 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1290 int width
= PIXEL_WIDTH (f
);
1291 int height
= PIXEL_HEIGHT (f
);
1294 if (f
!= selected_frame
)
1299 pixel
= f
->display
.x
->background_pixel
;
1303 pixel
= f
->display
.x
->border_pixel
;
1306 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1307 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1308 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1310 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1314 x_display_cursor (f
, 1);
1316 #endif /* ! defined (HAVE_X11) */
1318 static void XTframe_rehighlight ();
1320 /* The focus has changed. Update the frames as necessary to reflect
1321 the new situation. Note that we can't change the selected frame
1322 here, because the lisp code we are interrupting might become confused.
1323 Each event gets marked with the frame in which it occurred, so the
1324 lisp code can tell when the switch took place by examining the events. */
1327 x_new_focus_frame (frame
)
1328 struct frame
*frame
;
1330 struct frame
*old_focus
= x_focus_frame
;
1331 int events_enqueued
= 0;
1333 if (frame
!= x_focus_frame
)
1335 /* Set this before calling other routines, so that they see
1336 the correct value of x_focus_frame. */
1337 x_focus_frame
= frame
;
1339 if (old_focus
&& old_focus
->auto_lower
)
1340 x_lower_frame (old_focus
);
1343 selected_frame
= frame
;
1344 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1345 Lisp_Frame
, selected_frame
);
1346 Fselect_window (selected_frame
->selected_window
);
1347 choose_minibuf_frame ();
1350 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1351 x_raise_frame (x_focus_frame
);
1354 XTframe_rehighlight ();
1358 /* The focus has changed, or we have redirected a frame's focus to
1359 another frame (this happens when a frame uses a surrogate
1360 minibuffer frame). Shift the highlight as appropriate. */
1362 XTframe_rehighlight ()
1364 struct frame
*old_highlight
= x_highlight_frame
;
1369 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1370 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1372 if (! FRAME_LIVE_P (x_highlight_frame
))
1374 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1375 x_highlight_frame
= x_focus_frame
;
1379 x_highlight_frame
= 0;
1381 if (x_highlight_frame
!= old_highlight
)
1384 frame_unhighlight (old_highlight
);
1385 if (x_highlight_frame
)
1386 frame_highlight (x_highlight_frame
);
1390 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1392 /* Which modifier keys are on which modifier bits?
1394 With each keystroke, X returns eight bits indicating which modifier
1395 keys were held down when the key was pressed. The interpretation
1396 of the top five modifier bits depends on what keys are attached
1397 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1400 x_meta_mod_mask is a mask containing the bits used for the meta key.
1401 It may have more than one bit set, if more than one modifier bit
1402 has meta keys on it. Basically, if EVENT is a KeyPress event,
1403 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1405 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1406 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1407 only be affected by the lock modifier bit if XK_Shift_Lock is in
1408 use; XK_Caps_Lock should only affect alphabetic keys. With this
1409 arrangement, the lock modifier should shift the character if
1410 (EVENT.state & x_shift_lock_mask) != 0. */
1411 static int x_meta_mod_mask
, x_shift_lock_mask
;
1413 /* These are like x_meta_mod_mask, but for different modifiers. */
1414 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1416 /* Initialize mode_switch_bit and modifier_meaning. */
1418 x_find_modifier_meanings ()
1420 int min_code
, max_code
;
1423 XModifierKeymap
*mods
;
1425 x_meta_mod_mask
= 0;
1426 x_shift_lock_mask
= 0;
1428 x_super_mod_mask
= 0;
1429 x_hyper_mod_mask
= 0;
1432 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1434 min_code
= x_current_display
->min_keycode
;
1435 max_code
= x_current_display
->max_keycode
;
1438 syms
= XGetKeyboardMapping (x_current_display
,
1439 min_code
, max_code
- min_code
+ 1,
1441 mods
= XGetModifierMapping (x_current_display
);
1443 /* Scan the modifier table to see which modifier bits the Meta and
1444 Alt keysyms are on. */
1446 int row
, col
; /* The row and column in the modifier table. */
1448 for (row
= 3; row
< 8; row
++)
1449 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1452 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1454 /* Are any of this keycode's keysyms a meta key? */
1458 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1460 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1466 x_meta_mod_mask
|= (1 << row
);
1471 x_alt_mod_mask
|= (1 << row
);
1476 x_hyper_mod_mask
|= (1 << row
);
1481 x_super_mod_mask
|= (1 << row
);
1485 /* Ignore this if it's not on the lock modifier. */
1486 if ((1 << row
) == LockMask
)
1487 x_shift_lock_mask
= LockMask
;
1495 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1496 if (! x_meta_mod_mask
)
1498 x_meta_mod_mask
= x_alt_mod_mask
;
1502 /* If some keys are both alt and meta,
1503 make them just meta, not alt. */
1504 if (x_alt_mod_mask
& x_meta_mod_mask
)
1506 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1509 XFree ((char *) syms
);
1510 XFreeModifiermap (mods
);
1514 /* Convert between the modifier bits X uses and the modifier bits
1517 x_x_to_emacs_modifiers (state
)
1520 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1521 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1522 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1523 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1524 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1525 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1529 x_emacs_to_x_modifiers (state
)
1532 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1533 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1534 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1535 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1536 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1537 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1540 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1541 return as a function key. If you add a keysym to this, you should
1542 make sure that the tables make_lispy_event uses contain a suitable
1545 x_is_vendor_fkey (sym
)
1550 || (sym
== DXK_Remove
)
1556 /* Mouse clicks and mouse movement. Rah. */
1559 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1560 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1561 that the glyph at X, Y occupies, if BOUNDS != 0. */
1563 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1565 register unsigned int pix_x
, pix_y
;
1566 register int *x
, *y
;
1569 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1570 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1574 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1575 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1576 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1577 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1580 if (pix_x
< 0) pix_x
= 0;
1581 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1583 if (pix_y
< 0) pix_y
= 0;
1584 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1590 /* Any buttons grabbed. */
1591 unsigned int x_mouse_grabbed
;
1593 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1595 If the event is a button press, then note that we have grabbed
1599 construct_mouse_click (result
, event
, f
)
1600 struct input_event
*result
;
1601 XButtonEvent
*event
;
1604 /* Make the event type no_event; we'll change that when we decide
1606 result
->kind
= mouse_click
;
1607 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1608 result
->timestamp
= event
->time
;
1609 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1610 | (event
->type
== ButtonRelease
1614 /* Notice if the mouse is still grabbed. */
1615 if (event
->type
== ButtonPress
)
1617 if (! x_mouse_grabbed
)
1618 Vmouse_depressed
= Qt
;
1619 x_mouse_grabbed
|= (1 << event
->button
);
1621 else if (event
->type
== ButtonRelease
)
1623 x_mouse_grabbed
&= ~(1 << event
->button
);
1624 if (!x_mouse_grabbed
)
1625 Vmouse_depressed
= Qnil
;
1631 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1632 XFASTINT (result
->x
) = column
;
1633 XFASTINT (result
->y
) = row
;
1634 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1639 /* Mouse movement. Rah.
1641 In order to avoid asking for motion events and then throwing most
1642 of them away or busy-polling the server for mouse positions, we ask
1643 the server for pointer motion hints. This means that we get only
1644 one event per group of mouse movements. "Groups" are delimited by
1645 other kinds of events (focus changes and button clicks, for
1646 example), or by XQueryPointer calls; when one of these happens, we
1647 get another MotionNotify event the next time the mouse moves. This
1648 is at least as efficient as getting motion events when mouse
1649 tracking is on, and I suspect only negligibly worse when tracking
1652 The silly O'Reilly & Associates Nutshell guides barely document
1653 pointer motion hints at all (I think you have to infer how they
1654 work from an example), and the description of XQueryPointer doesn't
1655 mention that calling it causes you to get another motion hint from
1656 the server, which is very important. */
1658 /* Where the mouse was last time we reported a mouse event. */
1659 static FRAME_PTR last_mouse_frame
;
1660 static XRectangle last_mouse_glyph
;
1662 /* The scroll bar in which the last X motion event occurred.
1664 If the last X motion event occurred in a scroll bar, we set this
1665 so XTmouse_position can know whether to report a scroll bar motion or
1668 If the last X motion event didn't occur in a scroll bar, we set this
1669 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1670 static Lisp_Object last_mouse_scroll_bar
;
1672 /* This is a hack. We would really prefer that XTmouse_position would
1673 return the time associated with the position it returns, but there
1674 doesn't seem to be any way to wrest the timestamp from the server
1675 along with the position query. So, we just keep track of the time
1676 of the last movement we received, and return that in hopes that
1677 it's somewhat accurate. */
1678 static Time last_mouse_movement_time
;
1680 /* Function to report a mouse movement to the mainstream Emacs code.
1681 The input handler calls this.
1683 We have received a mouse movement event, which is given in *event.
1684 If the mouse is over a different glyph than it was last time, tell
1685 the mainstream emacs code by setting mouse_moved. If not, ask for
1686 another motion event, so we can check again the next time it moves. */
1688 note_mouse_movement (frame
, event
)
1690 XMotionEvent
*event
;
1693 last_mouse_movement_time
= event
->time
;
1695 /* Has the mouse moved off the glyph it was on at the last sighting? */
1696 if (event
->x
< last_mouse_glyph
.x
1697 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1698 || event
->y
< last_mouse_glyph
.y
1699 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1702 last_mouse_scroll_bar
= Qnil
;
1706 /* It's on the same glyph. Call XQueryPointer so we'll get an
1707 event the next time the mouse moves and we can see if it's
1708 *still* on the same glyph. */
1711 XQueryPointer (event
->display
, event
->window
,
1712 (Window
*) &dummy
, (Window
*) &dummy
,
1713 &dummy
, &dummy
, &dummy
, &dummy
,
1714 (unsigned int *) &dummy
);
1718 static struct scroll_bar
*x_window_to_scroll_bar ();
1719 static void x_scroll_bar_report_motion ();
1721 /* Return the current position of the mouse.
1723 If the mouse movement started in a scroll bar, set *f, *bar_window,
1724 and *part to the frame, window, and scroll bar part that the mouse
1725 is over. Set *x and *y to the portion and whole of the mouse's
1726 position on the scroll bar.
1728 If the mouse movement started elsewhere, set *f to the frame the
1729 mouse is on, *bar_window to nil, and *x and *y to the character cell
1732 Set *time to the server timestamp for the time at which the mouse
1733 was at this position.
1735 Don't store anything if we don't have a valid set of values to report.
1737 This clears the mouse_moved flag, so we can wait for the next mouse
1738 movement. This also calls XQueryPointer, which will cause the
1739 server to give us another MotionNotify when the mouse moves
1743 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1745 Lisp_Object
*bar_window
;
1746 enum scroll_bar_part
*part
;
1748 unsigned long *time
;
1754 if (! NILP (last_mouse_scroll_bar
))
1755 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1761 Window dummy_window
;
1765 last_mouse_scroll_bar
= Qnil
;
1767 /* Figure out which root window we're on. */
1768 XQueryPointer (x_current_display
,
1769 DefaultRootWindow (x_current_display
),
1771 /* The root window which contains the pointer. */
1774 /* Trash which we can't trust if the pointer is on
1775 a different screen. */
1778 /* The position on that root window. */
1781 /* More trash we can't trust. */
1784 /* Modifier keys and pointer buttons, about which
1786 (unsigned int *) &dummy
);
1788 /* Now we have a position on the root; find the innermost window
1789 containing the pointer. */
1793 int parent_x
, parent_y
;
1798 XTranslateCoordinates (x_current_display
,
1800 /* From-window, to-window. */
1803 /* From-position, to-position. */
1804 root_x
, root_y
, &win_x
, &win_y
,
1817 /* Now we know that:
1818 win is the innermost window containing the pointer
1819 (XTC says it has no child containing the pointer),
1820 win_x and win_y are the pointer's position in it
1821 (XTC did this the last time through), and
1822 parent_x and parent_y are the pointer's position in win's parent.
1823 (They are what win_x and win_y were when win was child.
1824 If win is the root window, it has no parent, and
1825 parent_{x,y} are invalid, but that's okay, because we'll
1826 never use them in that case.) */
1828 /* Is win one of our frames? */
1829 f1
= x_window_to_frame (win
);
1831 /* If not, is it one of our scroll bars? */
1834 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1838 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1846 /* Ok, we found a frame. Convert from pixels to characters
1847 and store all the values. */
1849 pixel_to_glyph_coords (f1
, win_x
, win_y
, &win_x
, &win_y
,
1855 XSET (*x
, Lisp_Int
, win_x
);
1856 XSET (*y
, Lisp_Int
, win_y
);
1857 *time
= last_mouse_movement_time
;
1865 #else /* ! defined (HAVE_X11) */
1866 #define XEvent XKeyPressedEvent
1867 #endif /* ! defined (HAVE_X11) */
1869 /* Scroll bar support. */
1871 /* Given an X window ID, find the struct scroll_bar which manages it.
1872 This can be called in GC, so we have to make sure to strip off mark
1874 static struct scroll_bar
*
1875 x_window_to_scroll_bar (window_id
)
1878 Lisp_Object tail
, frame
;
1880 for (tail
= Vframe_list
;
1881 XGCTYPE (tail
) == Lisp_Cons
;
1882 tail
= XCONS (tail
)->cdr
)
1884 Lisp_Object frame
= XCONS (tail
)->car
;
1885 Lisp_Object bar
, condemned
;
1887 /* All elements of Vframe_list should be frames. */
1888 if (XGCTYPE (frame
) != Lisp_Frame
)
1891 /* Scan this frame's scroll bar list for a scroll bar with the
1893 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1894 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1895 /* This trick allows us to search both the ordinary and
1896 condemned scroll bar lists with one loop. */
1897 ! GC_NILP (bar
) || (bar
= condemned
,
1900 bar
= XSCROLL_BAR(bar
)->next
)
1901 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1902 return XSCROLL_BAR (bar
);
1908 /* Open a new X window to serve as a scroll bar, and return the
1909 scroll bar vector for it. */
1910 static struct scroll_bar
*
1911 x_scroll_bar_create (window
, top
, left
, width
, height
)
1912 struct window
*window
;
1913 int top
, left
, width
, height
;
1915 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1916 struct scroll_bar
*bar
=
1917 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1922 XSetWindowAttributes a
;
1925 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1926 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1927 | ButtonMotionMask
| PointerMotionHintMask
1929 a
.cursor
= x_vertical_scroll_bar_cursor
;
1931 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1933 SET_SCROLL_BAR_X_WINDOW
1935 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1937 /* Position and size of scroll bar. */
1938 left
, top
, width
, height
,
1940 /* Border width, depth, class, and visual. */
1941 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1947 XSET (bar
->window
, Lisp_Window
, window
);
1948 XSET (bar
->top
, Lisp_Int
, top
);
1949 XSET (bar
->left
, Lisp_Int
, left
);
1950 XSET (bar
->width
, Lisp_Int
, width
);
1951 XSET (bar
->height
, Lisp_Int
, height
);
1952 XSET (bar
->start
, Lisp_Int
, 0);
1953 XSET (bar
->end
, Lisp_Int
, 0);
1954 bar
->dragging
= Qnil
;
1956 /* Add bar to its frame's list of scroll bars. */
1957 bar
->next
= FRAME_SCROLL_BARS (frame
);
1959 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
1960 if (! NILP (bar
->next
))
1961 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1963 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
1970 /* Draw BAR's handle in the proper position.
1971 If the handle is already drawn from START to END, don't bother
1972 redrawing it, unless REBUILD is non-zero; in that case, always
1973 redraw it. (REBUILD is handy for drawing the handle after expose
1976 Normally, we want to constrain the start and end of the handle to
1977 fit inside its rectangle, but if the user is dragging the scroll bar
1978 handle, we want to let them drag it down all the way, so that the
1979 bar's top is as far down as it goes; otherwise, there's no way to
1980 move to the very end of the buffer. */
1982 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1983 struct scroll_bar
*bar
;
1987 int dragging
= ! NILP (bar
->dragging
);
1988 Window w
= SCROLL_BAR_X_WINDOW (bar
);
1989 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1991 /* If the display is already accurate, do nothing. */
1993 && start
== XINT (bar
->start
)
1994 && end
== XINT (bar
->end
))
2000 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2001 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2002 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2004 /* Make sure the values are reasonable, and try to preserve
2005 the distance between start and end. */
2007 int length
= end
- start
;
2011 else if (start
> top_range
)
2013 end
= start
+ length
;
2017 else if (end
> top_range
&& ! dragging
)
2021 /* Store the adjusted setting in the scroll bar. */
2022 XSET (bar
->start
, Lisp_Int
, start
);
2023 XSET (bar
->end
, Lisp_Int
, end
);
2025 /* Clip the end position, just for display. */
2026 if (end
> top_range
)
2029 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2030 below top positions, to make sure the handle is always at least
2031 that many pixels tall. */
2032 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2034 /* Draw the empty space above the handle. Note that we can't clear
2035 zero-height areas; that means "clear to end of window." */
2037 XClearArea (x_current_display
, w
,
2039 /* x, y, width, height, and exposures. */
2040 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2041 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2042 inside_width
, start
,
2045 /* Draw the handle itself. */
2046 XFillRectangle (x_current_display
, w
, gc
,
2048 /* x, y, width, height */
2049 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2050 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2051 inside_width
, end
- start
);
2054 /* Draw the empty space below the handle. Note that we can't
2055 clear zero-height areas; that means "clear to end of window." */
2056 if (end
< inside_height
)
2057 XClearArea (x_current_display
, w
,
2059 /* x, y, width, height, and exposures. */
2060 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2061 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2062 inside_width
, inside_height
- end
,
2070 /* Move a scroll bar around on the screen, to accommodate changing
2071 window configurations. */
2073 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2074 struct scroll_bar
*bar
;
2075 int top
, left
, width
, height
;
2081 unsigned int mask
= 0;
2088 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2089 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2090 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2091 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2094 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2098 XSET (bar
->left
, Lisp_Int
, left
);
2099 XSET (bar
->top
, Lisp_Int
, top
);
2100 XSET (bar
->width
, Lisp_Int
, width
);
2101 XSET (bar
->height
, Lisp_Int
, height
);
2106 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2109 x_scroll_bar_remove (bar
)
2110 struct scroll_bar
*bar
;
2112 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2116 /* Destroy the window. */
2117 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2119 /* Disassociate this scroll bar from its window. */
2120 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2125 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2126 that we are displaying PORTION characters out of a total of WHOLE
2127 characters, starting at POSITION. If WINDOW has no scroll bar,
2130 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2131 struct window
*window
;
2132 int portion
, whole
, position
;
2134 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2135 int top
= XINT (window
->top
);
2136 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2137 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2139 /* Where should this scroll bar be, pixelwise? */
2140 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2141 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2142 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2143 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2145 struct scroll_bar
*bar
;
2147 /* Does the scroll bar exist yet? */
2148 if (NILP (window
->vertical_scroll_bar
))
2149 bar
= x_scroll_bar_create (window
,
2150 pixel_top
, pixel_left
,
2151 pixel_width
, pixel_height
);
2154 /* It may just need to be moved and resized. */
2155 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2156 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2159 /* Set the scroll bar's current state, unless we're currently being
2161 if (NILP (bar
->dragging
))
2164 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2167 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2170 int start
= ((double) position
* top_range
) / whole
;
2171 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2173 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2177 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2181 /* The following three hooks are used when we're doing a thorough
2182 redisplay of the frame. We don't explicitly know which scroll bars
2183 are going to be deleted, because keeping track of when windows go
2184 away is a real pain - "Can you say set-window-configuration, boys
2185 and girls?" Instead, we just assert at the beginning of redisplay
2186 that *all* scroll bars are to be removed, and then save a scroll bar
2187 from the fiery pit when we actually redisplay its window. */
2189 /* Arrange for all scroll bars on FRAME to be removed at the next call
2190 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2191 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2193 XTcondemn_scroll_bars (frame
)
2196 /* The condemned list should be empty at this point; if it's not,
2197 then the rest of Emacs isn't using the condemn/redeem/judge
2198 protocol correctly. */
2199 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2202 /* Move them all to the "condemned" list. */
2203 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2204 FRAME_SCROLL_BARS (frame
) = Qnil
;
2207 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2208 Note that WINDOW isn't necessarily condemned at all. */
2210 XTredeem_scroll_bar (window
)
2211 struct window
*window
;
2213 struct scroll_bar
*bar
;
2215 /* We can't redeem this window's scroll bar if it doesn't have one. */
2216 if (NILP (window
->vertical_scroll_bar
))
2219 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2221 /* Unlink it from the condemned list. */
2223 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2225 if (NILP (bar
->prev
))
2227 /* If the prev pointer is nil, it must be the first in one of
2229 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2230 /* It's not condemned. Everything's fine. */
2232 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2233 window
->vertical_scroll_bar
))
2234 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2236 /* If its prev pointer is nil, it must be at the front of
2237 one or the other! */
2241 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2243 if (! NILP (bar
->next
))
2244 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2246 bar
->next
= FRAME_SCROLL_BARS (f
);
2248 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2249 if (! NILP (bar
->next
))
2250 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2254 /* Remove all scroll bars on FRAME that haven't been saved since the
2255 last call to `*condemn_scroll_bars_hook'. */
2257 XTjudge_scroll_bars (f
)
2260 Lisp_Object bar
, next
;
2262 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2264 /* Clear out the condemned list now so we won't try to process any
2265 more events on the hapless scroll bars. */
2266 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2268 for (; ! NILP (bar
); bar
= next
)
2270 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2272 x_scroll_bar_remove (b
);
2275 b
->next
= b
->prev
= Qnil
;
2278 /* Now there should be no references to the condemned scroll bars,
2279 and they should get garbage-collected. */
2283 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2285 This may be called from a signal handler, so we have to ignore GC
2288 x_scroll_bar_expose (bar
, event
)
2289 struct scroll_bar
*bar
;
2292 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2293 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2297 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2299 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2300 XDrawRectangle (x_current_display
, w
, gc
,
2302 /* x, y, width, height */
2303 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2305 /* Draw another line to make the extra-thick border on the right. */
2306 XFillRectangle (x_current_display
, w
, gc
,
2308 /* x, y, width, height */
2309 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2314 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2315 is set to something other than no_event, it is enqueued.
2317 This may be called from a signal handler, so we have to ignore GC
2320 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2321 struct scroll_bar
*bar
;
2323 struct input_event
*emacs_event
;
2325 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2328 emacs_event
->kind
= scroll_bar_click
;
2329 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2330 emacs_event
->modifiers
=
2331 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2332 | (event
->type
== ButtonRelease
2335 emacs_event
->frame_or_window
= bar
->window
;
2336 emacs_event
->timestamp
= event
->xbutton
.time
;
2338 int internal_height
=
2339 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2341 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2342 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2345 if (y
> top_range
) y
= top_range
;
2347 if (y
< XINT (bar
->start
))
2348 emacs_event
->part
= scroll_bar_above_handle
;
2349 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2350 emacs_event
->part
= scroll_bar_handle
;
2352 emacs_event
->part
= scroll_bar_below_handle
;
2354 /* Just because the user has clicked on the handle doesn't mean
2355 they want to drag it. Lisp code needs to be able to decide
2356 whether or not we're dragging. */
2358 /* If the user has just clicked on the handle, record where they're
2360 if (event
->type
== ButtonPress
2361 && emacs_event
->part
== scroll_bar_handle
)
2362 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2365 /* If the user has released the handle, set it to its final position. */
2366 if (event
->type
== ButtonRelease
2367 && ! NILP (bar
->dragging
))
2369 int new_start
= y
- XINT (bar
->dragging
);
2370 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2372 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2373 bar
->dragging
= Qnil
;
2376 /* Same deal here as the other #if 0. */
2378 /* Clicks on the handle are always reported as occurring at the top of
2380 if (emacs_event
->part
== scroll_bar_handle
)
2381 emacs_event
->x
= bar
->start
;
2383 XSET (emacs_event
->x
, Lisp_Int
, y
);
2385 XSET (emacs_event
->x
, Lisp_Int
, y
);
2388 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2392 /* Handle some mouse motion while someone is dragging the scroll bar.
2394 This may be called from a signal handler, so we have to ignore GC
2397 x_scroll_bar_note_movement (bar
, event
)
2398 struct scroll_bar
*bar
;
2401 last_mouse_movement_time
= event
->xmotion
.time
;
2404 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2406 /* If we're dragging the bar, display it. */
2407 if (! GC_NILP (bar
->dragging
))
2409 /* Where should the handle be now? */
2410 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2412 if (new_start
!= XINT (bar
->start
))
2414 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2416 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2420 /* Call XQueryPointer so we'll get an event the next time the mouse
2421 moves and we can see *still* on the same position. */
2425 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2426 (Window
*) &dummy
, (Window
*) &dummy
,
2427 &dummy
, &dummy
, &dummy
, &dummy
,
2428 (unsigned int *) &dummy
);
2432 /* Return information to the user about the current position of the mouse
2433 on the scroll bar. */
2435 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2437 Lisp_Object
*bar_window
;
2438 enum scroll_bar_part
*part
;
2440 unsigned long *time
;
2442 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2444 Window dummy_window
;
2446 unsigned int dummy_mask
;
2450 /* Get the mouse's position relative to the scroll bar window, and
2452 if (! XQueryPointer (x_current_display
,
2453 SCROLL_BAR_X_WINDOW (bar
),
2455 /* Root, child, root x and root y. */
2456 &dummy_window
, &dummy_window
,
2457 &dummy_coord
, &dummy_coord
,
2459 /* Position relative to scroll bar. */
2462 /* Mouse buttons and modifier keys. */
2468 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2470 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2472 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2474 if (! NILP (bar
->dragging
))
2475 win_y
-= XINT (bar
->dragging
);
2479 if (win_y
> top_range
)
2482 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2483 *bar_window
= bar
->window
;
2485 if (! NILP (bar
->dragging
))
2486 *part
= scroll_bar_handle
;
2487 else if (win_y
< XINT (bar
->start
))
2488 *part
= scroll_bar_above_handle
;
2489 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2490 *part
= scroll_bar_handle
;
2492 *part
= scroll_bar_below_handle
;
2494 XSET (*x
, Lisp_Int
, win_y
);
2495 XSET (*y
, Lisp_Int
, top_range
);
2498 last_mouse_scroll_bar
= Qnil
;
2501 *time
= last_mouse_movement_time
;
2507 /* The screen has been cleared so we may have changed foreground or
2508 background colors, and the scroll bars may need to be redrawn.
2509 Clear out the scroll bars, and ask for expose events, so we can
2512 x_scroll_bar_clear (f
)
2517 for (bar
= FRAME_SCROLL_BARS (f
);
2518 XTYPE (bar
) == Lisp_Vector
;
2519 bar
= XSCROLL_BAR (bar
)->next
)
2520 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2526 /* The main X event-reading loop - XTread_socket. */
2528 /* Timestamp of enter window event. This is only used by XTread_socket,
2529 but we have to put it out here, since static variables within functions
2530 sometimes don't work. */
2531 static Time enter_timestamp
;
2533 /* This holds the state XLookupString needs to implement dead keys
2534 and other tricks known as "compose processing". _X Window System_
2535 says that a portable program can't use this, but Stephen Gildea assures
2536 me that letting the compiler initialize it to zeros will work okay.
2538 This must be defined outside of XTread_socket, for the same reasons
2539 given for enter_timestamp, above. */
2540 static XComposeStatus compose_status
;
2542 /* Communication with window managers. */
2543 Atom Xatom_wm_protocols
;
2545 /* Kinds of protocol things we may receive. */
2546 Atom Xatom_wm_take_focus
;
2547 Atom Xatom_wm_save_yourself
;
2548 Atom Xatom_wm_delete_window
;
2550 /* Other WM communication */
2551 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2552 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2554 /* Window manager communication. */
2555 Atom Xatom_wm_change_state
;
2557 /* Record the last 100 characters stored
2558 to help debug the loss-of-chars-during-GC problem. */
2560 short temp_buffer
[100];
2562 /* Read events coming from the X server.
2563 This routine is called by the SIGIO handler.
2564 We return as soon as there are no more events to be read.
2566 Events representing keys are stored in buffer BUFP,
2567 which can hold up to NUMCHARS characters.
2568 We return the number of characters stored into the buffer,
2569 thus pretending to be `read'.
2571 WAITP is nonzero if we should block until input arrives.
2572 EXPECTED is nonzero if the caller knows input is available. */
2575 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2577 register struct input_event
*bufp
;
2578 register int numchars
;
2585 int items_pending
; /* How many items are in the X queue. */
2588 int event_found
= 0;
2592 if (interrupt_input_blocked
)
2594 interrupt_input_pending
= 1;
2598 interrupt_input_pending
= 0;
2602 abort (); /* Don't think this happens. */
2605 /* If available, Xlib uses FIOSNBIO to make the socket
2606 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2607 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2608 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2609 fcntl (fileno (stdin
), F_SETFL
, 0);
2610 #endif /* ! defined (FIOSNBIO) */
2614 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2616 extern int read_alarm_should_throw
;
2617 read_alarm_should_throw
= 1;
2618 XPeekEvent (XDISPLAY
&event
);
2619 read_alarm_should_throw
= 0;
2621 #endif /* HAVE_SELECT */
2624 while (XStuffPending () != 0)
2626 XNextEvent (XDISPLAY
&event
);
2634 if (event
.xclient
.message_type
== Xatom_wm_protocols
2635 && event
.xclient
.format
== 32)
2637 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2639 f
= x_window_to_frame (event
.xclient
.window
);
2641 x_focus_on_frame (f
);
2642 /* Not certain about handling scroll bars here */
2644 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2646 /* Save state modify the WM_COMMAND property to
2647 something which can reinstate us. This notifies
2648 the session manager, who's looking for such a
2649 PropertyNotify. Can restart processing when
2650 a keyboard or mouse event arrives. */
2655 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2657 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2665 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2668 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2672 new_x
= event
.xclient
.data
.s
[0];
2673 new_y
= event
.xclient
.data
.s
[1];
2678 #ifdef NEW_SELECTIONS
2679 case SelectionNotify
:
2680 x_handle_selection_notify (&event
);
2684 case SelectionClear
: /* Someone has grabbed ownership. */
2685 #ifdef NEW_SELECTIONS
2687 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2692 bufp
->kind
= selection_clear_event
;
2693 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2694 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2695 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2702 x_disown_selection (event
.xselectionclear
.window
,
2703 event
.xselectionclear
.selection
,
2704 event
.xselectionclear
.time
);
2708 case SelectionRequest
: /* Someone wants our selection. */
2709 #ifdef NEW_SELECTIONS
2711 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2716 bufp
->kind
= selection_request_event
;
2717 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2718 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2719 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2720 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2721 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2722 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2729 x_answer_selection_request (event
);
2733 case PropertyNotify
:
2734 #ifdef NEW_SELECTIONS
2735 x_handle_property_notify (&event
);
2737 /* If we're being told about a root window property, then it's
2738 a cut buffer change. */
2739 if (event
.xproperty
.window
== ROOT_WINDOW
)
2740 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2742 /* Otherwise, we're probably handling an incremental
2743 selection transmission. */
2746 /* If we were to do this synchronously, there'd be no worry
2747 about re-selecting. */
2748 x_send_incremental (event
);
2753 case ReparentNotify
:
2754 f
= x_window_to_frame (event
.xreparent
.window
);
2756 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
2760 f
= x_window_to_frame (event
.xexpose
.window
);
2763 if (f
->async_visible
== 0)
2765 f
->async_visible
= 1;
2766 f
->async_iconified
= 0;
2767 SET_FRAME_GARBAGED (f
);
2771 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2772 event
.xexpose
.x
, event
.xexpose
.y
,
2773 event
.xexpose
.width
, event
.xexpose
.height
);
2778 struct scroll_bar
*bar
2779 = x_window_to_scroll_bar (event
.xexpose
.window
);
2782 x_scroll_bar_expose (bar
, &event
);
2786 case GraphicsExpose
: /* This occurs when an XCopyArea's
2787 source area was obscured or not
2789 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2793 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2794 event
.xgraphicsexpose
.width
,
2795 event
.xgraphicsexpose
.height
);
2799 case NoExpose
: /* This occurs when an XCopyArea's
2800 source area was completely
2803 #else /* ! defined (HAVE_X11) */
2805 if (event
.subwindow
!= 0)
2806 break; /* duplicate event */
2807 f
= x_window_to_frame (event
.window
);
2808 if (event
.window
== f
->display
.x
->icon_desc
)
2811 f
->async_iconified
= 1;
2813 if (event
.window
== FRAME_X_WINDOW (f
))
2815 /* Say must check all windows' needs_exposure flags. */
2816 expose_all_windows
= 1;
2817 f
->display
.x
->needs_exposure
= 1;
2818 f
->async_visible
= 1;
2823 if (event
.subwindow
!= 0)
2824 break; /* duplicate event */
2825 f
= x_window_to_frame (event
.window
);
2826 if (event
.window
== f
->display
.x
->icon_desc
)
2831 /* If window already needs full redraw, ignore this rectangle. */
2832 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2834 /* Put the event on the queue of rectangles to redraw. */
2835 if (enqueue_event (&event
, &x_expose_queue
))
2836 /* If it is full, we can't record the rectangle,
2837 so redraw this entire window. */
2839 /* Say must check all windows' needs_exposure flags. */
2840 expose_all_windows
= 1;
2841 f
->display
.x
->needs_exposure
= 1;
2846 /* This should happen only when we are expecting it,
2847 in x_read_exposes. */
2849 #endif /* ! defined (HAVE_X11) */
2853 f
= x_window_to_frame (event
.xunmap
.window
);
2854 if (f
) /* F may no longer exist if
2855 the frame was deleted. */
2857 /* While a frame is unmapped, display generation is
2858 disabled; you don't want to spend time updating a
2859 display that won't ever be seen. */
2860 f
->async_visible
= 0;
2861 /* The window manager never makes a window invisible
2862 ("withdrawn"); all it does is switch between visible
2863 and iconified. Frames get into the invisible state
2864 only through x_make_frame_invisible.
2865 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
2866 f->async_iconified = 1;
2871 f = x_window_to_frame (event.xmap.window);
2874 f->async_visible = 1;
2875 f->async_iconified = 0;
2877 /* wait_reading_process_input will notice this and update
2878 the frame's display structures. */
2879 SET_FRAME_GARBAGED (f
);
2883 /* Turn off processing if we become fully obscured. */
2884 case VisibilityNotify
:
2887 #else /* ! defined (HAVE_X11) */
2889 f
= x_window_to_frame (event
.window
);
2890 if (event
.window
== f
->display
.x
->icon_desc
)
2891 f
->async_iconified
= 0;
2892 if (event
.window
== FRAME_X_WINDOW (f
))
2893 f
->async_visible
= 0;
2895 #endif /* ! defined (HAVE_X11) */
2899 f
= x_window_to_frame (event
.xkey
.window
);
2903 KeySym keysym
, orig_keysym
;
2904 char copy_buffer
[80];
2908 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
2909 modifiers
= event
.xkey
.state
;
2911 /* This will have to go some day... */
2913 /* make_lispy_event turns chars into control chars.
2914 Don't do it here because XLookupString is too eager. */
2915 event
.xkey
.state
&= ~ControlMask
;
2917 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2920 /* Strip off the vendor-specific keysym bit, and take a shot
2921 at recognizing the codes. HP servers have extra keysyms
2922 that fit into the MiscFunctionKey category. */
2923 orig_keysym
= keysym
;
2928 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
2929 || keysym
== XK_Delete
2930 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2931 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
2933 /* This recognizes the "extended function keys".
2934 It seems there's no cleaner way.
2935 Test IsModifierKey to avoid handling mode_switch
2937 || ((unsigned) (keysym
) >= XK_Select
2938 && (unsigned)(keysym
) < XK_KP_Space
)
2940 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2941 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
2942 || x_is_vendor_fkey (orig_keysym
))
2943 && ! IsModifierKey (orig_keysym
)) /* wherever */
2945 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2947 temp_buffer
[temp_index
++] = keysym
;
2948 bufp
->kind
= non_ascii_keystroke
;
2949 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff00);
2950 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2951 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
2952 bufp
->timestamp
= event
.xkey
.time
;
2957 else if (numchars
> nbytes
)
2961 for (i
= 0; i
< nbytes
; i
++)
2963 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2965 temp_buffer
[temp_index
++] = copy_buffer
[i
];
2966 bufp
->kind
= ascii_keystroke
;
2967 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2968 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2969 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
2970 bufp
->timestamp
= event
.xkey
.time
;
2984 #else /* ! defined (HAVE_X11) */
2987 register char *where_mapping
;
2989 f
= x_window_to_frame (event
.window
);
2990 /* Ignore keys typed on icon windows. */
2991 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2993 where_mapping
= XLookupMapping (&event
, &nbytes
);
2994 /* Nasty fix for arrow keys */
2995 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2997 switch (event
.detail
& 0xff)
2999 case KC_CURSOR_LEFT
:
3000 where_mapping
= "\002";
3002 case KC_CURSOR_RIGHT
:
3003 where_mapping
= "\006";
3006 where_mapping
= "\020";
3008 case KC_CURSOR_DOWN
:
3009 where_mapping
= "\016";
3014 if (numchars
- nbytes
> 0)
3018 for (i
= 0; i
< nbytes
; i
++)
3020 bufp
->kind
= ascii_keystroke
;
3021 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
3022 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3023 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3031 #endif /* ! defined (HAVE_X11) */
3035 /* Here's a possible interpretation of the whole
3036 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3037 FocusIn event, you have to get a FocusOut event before you
3038 relinquish the focus. If you haven't received a FocusIn event,
3039 then a mere LeaveNotify is enough to free you. */
3042 f
= x_window_to_frame (event
.xcrossing
.window
);
3044 if (event
.xcrossing
.focus
) /* Entered Window */
3046 /* Avoid nasty pop/raise loops. */
3047 if (f
&& (!(f
->auto_raise
)
3049 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3051 x_new_focus_frame (f
);
3052 enter_timestamp
= event
.xcrossing
.time
;
3055 else if (f
== x_focus_frame
)
3056 x_new_focus_frame (0);
3061 f
= x_window_to_frame (event
.xfocus
.window
);
3062 if (event
.xfocus
.detail
!= NotifyPointer
)
3063 x_focus_event_frame
= f
;
3065 x_new_focus_frame (f
);
3070 f
= x_window_to_frame (event
.xcrossing
.window
);
3072 if (event
.xcrossing
.focus
)
3074 if (! x_focus_event_frame
)
3075 x_new_focus_frame (0);
3077 x_new_focus_frame (f
);
3081 if (f
== x_focus_event_frame
)
3082 x_focus_event_frame
= 0;
3083 if (f
== x_focus_frame
)
3084 x_new_focus_frame (0);
3089 f
= x_window_to_frame (event
.xfocus
.window
);
3090 if (event
.xfocus
.detail
!= NotifyPointer
3091 && f
== x_focus_event_frame
)
3092 x_focus_event_frame
= 0;
3093 if (f
&& f
== x_focus_frame
)
3094 x_new_focus_frame (0);
3097 #else /* ! defined (HAVE_X11) */
3100 if ((event
.detail
& 0xFF) == 1)
3101 break; /* Coming from our own subwindow */
3102 if (event
.subwindow
!= 0)
3103 break; /* Entering our own subwindow. */
3106 f
= x_window_to_frame (event
.window
);
3109 x_new_focus_frame (f
);
3114 if ((event
.detail
& 0xFF) == 1)
3115 break; /* Entering our own subwindow */
3116 if (event
.subwindow
!= 0)
3117 break; /* Leaving our own subwindow. */
3120 if (x_focus_frame
== 0
3121 && x_input_frame
!= 0
3122 && x_input_frame
== x_window_to_frame (event
.window
)
3123 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3128 frame_unhighlight (f
);
3131 #endif /* ! defined (HAVE_X11) */
3136 f
= x_window_to_frame (event
.xmotion
.window
);
3138 note_mouse_movement (f
, &event
.xmotion
);
3141 struct scroll_bar
*bar
=
3142 x_window_to_scroll_bar (event
.xmotion
.window
);
3145 x_scroll_bar_note_movement (bar
, &event
);
3150 case ConfigureNotify
:
3151 f
= x_window_to_frame (event
.xconfigure
.window
);
3154 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3155 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3157 /* Even if the number of character rows and columns has
3158 not changed, the font size may have changed, so we need
3159 to check the pixel dimensions as well. */
3160 if (columns
!= f
->width
3161 || rows
!= f
->height
3162 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3163 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3165 change_frame_size (f
, rows
, columns
, 0, 1);
3166 SET_FRAME_GARBAGED (f
);
3169 if (! event
.xconfigure
.send_event
)
3174 /* Find the position of the outside upper-left corner of
3175 the window, in the root coordinate system. Don't
3176 refer to the parent window here; we may be processing
3177 this event after the window manager has changed our
3178 parent, but before we have reached the ReparentNotify. */
3179 XTranslateCoordinates (x_current_display
,
3181 /* From-window, to-window. */
3182 f
->display
.x
->window_desc
,
3185 /* From-position, to-position. */
3186 -event
.xconfigure
.border_width
,
3187 -event
.xconfigure
.border_width
,
3192 event
.xconfigure
.x
= win_x
;
3193 event
.xconfigure
.y
= win_y
;
3196 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3197 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3198 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3199 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3206 /* If we decide we want to generate an event to be seen
3207 by the rest of Emacs, we put it here. */
3208 struct input_event emacs_event
;
3209 emacs_event
.kind
= no_event
;
3211 f
= x_window_to_frame (event
.xbutton
.window
);
3214 if (!x_focus_frame
|| (f
== x_focus_frame
))
3215 construct_mouse_click (&emacs_event
,
3220 struct scroll_bar
*bar
=
3221 x_window_to_scroll_bar (event
.xbutton
.window
);
3224 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3227 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3229 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3237 #else /* ! defined (HAVE_X11) */
3239 case ButtonReleased
:
3240 f
= x_window_to_frame (event
.window
);
3243 if (event
.window
== f
->display
.x
->icon_desc
)
3245 x_make_frame_visible (f
);
3247 if (warp_mouse_on_deiconify
)
3248 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3251 if (event
.window
== FRAME_X_WINDOW (f
))
3257 enqueue_event (&event
, &x_mouse_queue
);
3260 bufp
->kind
= ascii_keystroke
;
3261 bufp
->code
= (char) 'X' & 037; /* C-x */
3262 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3263 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3266 bufp
->kind
= ascii_keystroke
;
3267 bufp
->code
= (char) 0; /* C-@ */
3268 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3269 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3276 #endif /* ! defined (HAVE_X11) */
3280 case CirculateNotify
:
3282 case CirculateRequest
:
3285 #endif /* ! defined (HAVE_X11) */
3288 /* Someone has changed the keyboard mapping - update the
3290 switch (event
.xmapping
.request
)
3292 case MappingModifier
:
3293 x_find_modifier_meanings ();
3294 /* This is meant to fall through. */
3295 case MappingKeyboard
:
3296 XRefreshKeyboardMapping (&event
.xmapping
);
3306 if (expected
&& ! event_found
)
3308 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3309 there is an EOF condition; in other words, that X has died.
3310 Act as if there had been a hangup. */
3311 int fd
= ConnectionNumber (x_current_display
);
3316 EMACS_SET_SECS_USECS (timeout
, 0, 0);
3317 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0, &timeout
)
3318 && !XStuffPending ())
3319 kill (getpid (), SIGHUP
);
3321 #endif /* ! defined (HAVE_SELECT) */
3324 if (updating_frame
== 0)
3325 x_do_pending_expose ();
3333 /* Read and process only Expose events
3334 until we get an ExposeCopy event; then return.
3335 This is used in insert/delete line.
3336 We assume input is already blocked. */
3342 XKeyPressedEvent event
;
3346 /* while there are more events*/
3347 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3351 if (event
.subwindow
!= 0)
3352 break; /* duplicate event */
3353 f
= x_window_to_frame (event
.window
);
3354 if (event
.window
== f
->display
.x
->icon_desc
)
3359 if (event
.window
== FRAME_X_WINDOW (f
))
3361 expose_all_windows
= 1;
3362 f
->display
.x
->needs_exposure
= 1;
3368 if (event
.subwindow
!= 0)
3369 break; /* duplicate event */
3370 f
= x_window_to_frame (event
.window
);
3371 if (event
.window
== f
->display
.x
->icon_desc
)
3376 /* If window already needs full redraw, ignore this rectangle. */
3377 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3379 /* Put the event on the queue of rectangles to redraw. */
3380 if (enqueue_event (&event
, &x_expose_queue
))
3381 /* If it is full, we can't record the rectangle,
3382 so redraw this entire window. */
3384 /* Say must check all windows' needs_exposure flags. */
3385 expose_all_windows
= 1;
3386 f
->display
.x
->needs_exposure
= 1;
3395 #endif /* HAVE_X11 */
3398 /* Drawing the cursor. */
3401 /* Draw a hollow box cursor. Don't change the inside of the box. */
3407 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3408 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3409 int width
= FONT_WIDTH (f
->display
.x
->font
);
3410 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3413 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3414 f
->display
.x
->cursor_gc
,
3415 left
, top
, width
- 1, height
- 1);
3416 #else /* ! defined (HAVE_X11) */
3417 XPixSet (FRAME_X_WINDOW (f
),
3418 left
, top
, width
, 1,
3419 f
->display
.x
->cursor_pixel
);
3421 XPixSet (FRAME_X_WINDOW (f
),
3422 left
, top
, 1, height
,
3423 f
->display
.x
->cursor_pixel
);
3425 XPixSet (FRAME_X_WINDOW (f
),
3426 left
+width
-1, top
, 1, height
,
3427 f
->display
.x
->cursor_pixel
);
3429 XPixSet (FRAME_X_WINDOW (f
),
3430 left
, top
+height
-1, width
, 1,
3431 f
->display
.x
->cursor_pixel
);
3432 #endif /* ! defined (HAVE_X11) */
3435 /* Clear the cursor of frame F to background color,
3436 and mark the cursor as not shown.
3437 This is used when the text where the cursor is
3438 is about to be rewritten. */
3446 if (! FRAME_VISIBLE_P (f
)
3447 || f
->phys_cursor_x
< 0)
3451 x_display_cursor (f
, 0);
3452 #else /* ! defined (HAVE_X11) */
3453 XPixSet (FRAME_X_WINDOW (f
),
3454 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3455 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3456 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3457 f
->display
.x
->background_pixel
);
3458 #endif /* ! defined (HAVE_X11) */
3459 f
->phys_cursor_x
= -1;
3462 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3463 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3467 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3474 CHAR_TO_PIXEL_COL (f
, column
),
3475 CHAR_TO_PIXEL_ROW (f
, row
),
3476 &glyph
, 1, highlight
);
3480 x_display_bar_cursor (f
, on
)
3484 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3486 /* This is pointless on invisible frames, and dangerous on garbaged
3487 frames; in the latter case, the frame may be in the midst of
3488 changing its size, and curs_x and curs_y may be off the frame. */
3489 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3492 if (! on
&& f
->phys_cursor_x
< 0)
3495 /* If we're not updating, then we want to use the current frame's
3496 cursor position, not our local idea of where the cursor ought to be. */
3497 if (f
!= updating_frame
)
3499 curs_x
= FRAME_CURSOR_X (f
);
3500 curs_y
= FRAME_CURSOR_Y (f
);
3503 /* If there is anything wrong with the current cursor state, remove it. */
3504 if (f
->phys_cursor_x
>= 0
3506 || f
->phys_cursor_x
!= curs_x
3507 || f
->phys_cursor_y
!= curs_y
3508 || f
->display
.x
->current_cursor
!= bar_cursor
))
3510 /* Erase the cursor by redrawing the character underneath it. */
3511 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3512 f
->phys_cursor_glyph
,
3513 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3514 f
->phys_cursor_x
= -1;
3517 /* If we now need a cursor in the new place or in the new form, do it so. */
3519 && (f
->phys_cursor_x
< 0
3520 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3522 f
->phys_cursor_glyph
3523 = ((current_glyphs
->enable
[curs_y
]
3524 && curs_x
< current_glyphs
->used
[curs_y
])
3525 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3527 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3528 f
->display
.x
->cursor_gc
,
3529 CHAR_TO_PIXEL_COL (f
, curs_x
),
3530 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3531 1, FONT_HEIGHT (f
->display
.x
->font
));
3533 f
->phys_cursor_x
= curs_x
;
3534 f
->phys_cursor_y
= curs_y
;
3536 f
->display
.x
->current_cursor
= bar_cursor
;
3539 if (updating_frame
!= f
)
3544 /* Turn the displayed cursor of frame F on or off according to ON.
3545 If ON is nonzero, where to put the cursor is specified
3546 by F->cursor_x and F->cursor_y. */
3549 x_display_box_cursor (f
, on
)
3553 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3555 /* This is pointless on invisible frames, and dangerous on garbaged
3556 frames; in the latter case, the frame may be in the midst of
3557 changing its size, and curs_x and curs_y may be off the frame. */
3558 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3561 /* If cursor is off and we want it off, return quickly. */
3562 if (!on
&& f
->phys_cursor_x
< 0)
3565 /* If we're not updating, then we want to use the current frame's
3566 cursor position, not our local idea of where the cursor ought to be. */
3567 if (f
!= updating_frame
)
3569 curs_x
= FRAME_CURSOR_X (f
);
3570 curs_y
= FRAME_CURSOR_Y (f
);
3573 /* If cursor is currently being shown and we don't want it to be
3574 or it is in the wrong place,
3575 or we want a hollow box and it's not so, (pout!)
3577 if (f
->phys_cursor_x
>= 0
3579 || f
->phys_cursor_x
!= curs_x
3580 || f
->phys_cursor_y
!= curs_y
3581 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3582 && (f
!= x_highlight_frame
))))
3584 /* Erase the cursor by redrawing the character underneath it. */
3585 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3586 f
->phys_cursor_glyph
,
3587 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3588 f
->phys_cursor_x
= -1;
3591 /* If we want to show a cursor,
3592 or we want a box cursor and it's not so,
3593 write it in the right place. */
3595 && (f
->phys_cursor_x
< 0
3596 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3597 && f
== x_highlight_frame
)))
3599 f
->phys_cursor_glyph
3600 = ((current_glyphs
->enable
[curs_y
]
3601 && curs_x
< current_glyphs
->used
[curs_y
])
3602 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3604 if (f
!= x_highlight_frame
)
3607 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3611 x_draw_single_glyph (f
, curs_y
, curs_x
,
3612 f
->phys_cursor_glyph
, 2);
3613 f
->display
.x
->current_cursor
= filled_box_cursor
;
3616 f
->phys_cursor_x
= curs_x
;
3617 f
->phys_cursor_y
= curs_y
;
3620 if (updating_frame
!= f
)
3624 x_display_cursor (f
, on
)
3628 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3629 x_display_box_cursor (f
, on
);
3630 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3631 x_display_bar_cursor (f
, on
);
3633 /* Those are the only two we have implemented! */
3639 /* Refresh bitmap kitchen sink icon for frame F
3640 when we get an expose event for it. */
3646 /* Normally, the window manager handles this function. */
3647 #else /* ! defined (HAVE_X11) */
3650 if (f
->display
.x
->icon_bitmap_flag
)
3651 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3652 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3653 icon_bitmap
, GXcopy
, AllPlanes
);
3656 extern struct frame
*selected_frame
;
3657 struct Lisp_String
*str
;
3658 unsigned char *string
;
3661 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3663 if (f
->display
.x
->icon_label
!= string
)
3665 f
->display
.x
->icon_label
= string
;
3666 XChangeWindow (f
->display
.x
->icon_desc
,
3667 XQueryWidth (string
, icon_font_info
->id
) + 10,
3668 icon_font_info
->height
+ 10);
3671 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3672 str
->size
, icon_font_info
->id
,
3673 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3676 #endif /* ! defined (HAVE_X11) */
3679 /* Make the x-window of frame F use the gnu icon bitmap. */
3688 if (FRAME_X_WINDOW (f
) == 0)
3694 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3695 gnu_bits
, gnu_width
, gnu_height
);
3696 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3697 f
->display
.x
->icon_bitmap_flag
= 1;
3698 #else /* ! defined (HAVE_X11) */
3699 if (f
->display
.x
->icon_desc
)
3701 XClearIconWindow (FRAME_X_WINDOW (f
));
3702 XDestroyWindow (f
->display
.x
->icon_desc
);
3705 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3706 0, 0, sink_width
, sink_height
,
3707 2, WhitePixmap
, (Pixmap
) NULL
);
3709 if (icon_window
== 0)
3712 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3713 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3715 f
->display
.x
->icon_desc
= icon_window
;
3716 f
->display
.x
->icon_bitmap_flag
= 1;
3718 if (icon_bitmap
== 0)
3720 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3721 #endif /* ! defined (HAVE_X11) */
3727 /* Make the x-window of frame F use a rectangle with text. */
3730 x_text_icon (f
, icon_name
)
3738 char *X_DefaultValue
;
3742 #define WhitePixel 1
3743 #endif /* WhitePixel */
3746 #define BlackPixel 0
3747 #endif /* BlackPixel */
3748 #endif /* HAVE_X11 */
3750 if (FRAME_X_WINDOW (f
) == 0)
3755 f
->display
.x
->icon_label
= icon_name
;
3757 if (! f
->display
.x
->icon_label
)
3758 f
->display
.x
->icon_label
= " *emacs* ";
3761 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3762 (char *) f
->display
.x
->icon_label
);
3765 f
->display
.x
->icon_bitmap_flag
= 0;
3766 x_wm_set_icon_pixmap (f
, 0);
3767 #else /* ! defined (HAVE_X11) */
3768 if (icon_font_info
== 0)
3770 = XGetFont (XGetDefault (XDISPLAY
3771 (char *) XSTRING (Vinvocation_name
)->data
,
3774 if (f
->display
.x
->icon_desc
)
3776 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3777 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3781 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3783 if (! f
->display
.x
->icon_label
)
3784 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3786 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3787 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3788 f
->display
.x
->left_pos
,
3789 f
->display
.x
->top_pos
,
3790 width
+ 10, icon_font_info
->height
+ 10,
3791 2, BlackPixmap
, WhitePixmap
);
3793 if (icon_window
== 0)
3796 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3797 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3799 f
->display
.x
->icon_desc
= icon_window
;
3800 f
->display
.x
->icon_bitmap_flag
= 0;
3801 f
->display
.x
->icon_label
= 0;
3802 #endif /* ! defined (HAVE_X11) */
3807 /* Handling X errors. */
3809 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3810 X server's connection, or an error reported via the X protocol. */
3813 x_connection_closed ()
3818 shut_down_emacs (0, 1, Qnil
);
3823 /* An X error handler which prints an error message and then kills
3824 Emacs. This is what's normally installed as Xlib's handler for
3827 x_error_quitter (display
, error
)
3833 /* Note that there is no real way portable across R3/R4 to get the
3834 original error handler. */
3836 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3837 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3838 buf
, error
->request_code
);
3841 /* While we're testing Emacs 19, we'll just dump core whenever we
3842 get an X error, so we can figure out why it happened. */
3846 x_connection_closed ();
3849 /* A handler for X IO errors which prints an error message and then
3850 kills Emacs. This is what is always installed as Xlib's handler
3853 x_io_error_quitter (display
)
3856 fprintf (stderr
, "Connection to X server %s lost.\n",
3857 XDisplayName (DisplayString (display
)));
3860 /* While we're testing Emacs 19, we'll just dump core whenever we
3861 get an X error, so we can figure out why it happened. */
3865 x_connection_closed ();
3868 /* A buffer for storing X error messages. */
3869 static char *x_caught_error_message
;
3870 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
3872 /* An X error handler which stores the error message in
3873 x_caught_error_message. This is what's installed when
3874 x_catch_errors is in effect. */
3876 x_error_catcher (display
, error
)
3880 XGetErrorText (display
, error
->error_code
,
3881 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
3885 /* Begin trapping X errors.
3887 After calling this function, X protocol errors no longer cause
3888 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3890 Calling x_check_errors signals an Emacs error if an X error has
3891 occurred since the last call to x_catch_errors or x_check_errors.
3893 Calling x_uncatch_errors resumes the normal error handling. */
3895 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3900 /* Make sure any errors from previous requests have been dealt with. */
3901 XSync (x_current_display
, False
);
3903 /* Set up the error buffer. */
3904 x_caught_error_message
3905 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
3906 x_caught_error_message
[0] = '\0';
3908 /* Install our little error handler. */
3909 XHandleError (x_error_catcher
);
3912 /* If any X protocol errors have arrived since the last call to
3913 x_catch_errors or x_check_errors, signal an Emacs error using
3914 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3916 x_check_errors (format
)
3919 /* Make sure to catch any errors incurred so far. */
3920 XSync (x_current_display
, False
);
3922 if (x_caught_error_message
[0])
3924 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
3926 sprintf (buf
, format
, x_caught_error_message
);
3927 x_uncatch_errors ();
3935 xfree (x_caught_error_message
);
3936 x_caught_error_message
= 0;
3937 XHandleError (x_error_quitter
);
3941 static unsigned int x_wire_count
;
3944 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3949 /* Changing the font of the frame. */
3951 /* Set the font of the x-window specified by frame F
3952 to the font named NEWNAME. This is safe to use
3953 even before F has an actual x-window. */
3957 /* A table of all the fonts we have already loaded. */
3958 static XFontStruct
**x_font_table
;
3960 /* The current capacity of x_font_table. */
3961 static int x_font_table_size
;
3963 /* The number of fonts actually stored in x_font_table.
3964 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3965 0 <= n_fonts <= x_font_table_size. */
3969 x_new_font (f
, fontname
)
3971 register char *fontname
;
3974 int n_matching_fonts
;
3975 XFontStruct
*font_info
;
3978 /* Get a list of all the fonts that match this name. Once we
3979 have a list of matching fonts, we compare them against the fonts
3980 we already have by comparing font ids. */
3981 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3982 1024, &n_matching_fonts
,
3984 /* Apparently it doesn't set n_matching_fonts to zero when it can't
3985 find any matches; font_names == 0 is the only clue. */
3987 n_matching_fonts
= 0;
3989 /* Don't just give up if n_matching_fonts is 0.
3990 Apparently there's a bug on Suns: XListFontsWithInfo can
3991 fail to find a font, but XLoadQueryFont may still find it. */
3993 /* See if we've already loaded a matching font. */
3994 already_loaded
= -1;
3995 if (n_matching_fonts
!= 0)
3999 for (i
= 0; i
< n_fonts
; i
++)
4000 for (j
= 0; j
< n_matching_fonts
; j
++)
4001 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
4004 fontname
= font_names
[j
];
4010 /* If we have, just return it from the table. */
4011 if (already_loaded
> 0)
4012 f
->display
.x
->font
= x_font_table
[already_loaded
];
4014 /* Otherwise, load the font and add it to the table. */
4020 /* Try to find a character-cell font in the list. */
4022 /* A laudable goal, but this isn't how to do it. */
4023 for (i
= 0; i
< n_matching_fonts
; i
++)
4024 if (! font_info
[i
].per_char
)
4030 /* See comment above. */
4031 if (n_matching_fonts
!= 0)
4032 fontname
= font_names
[i
];
4034 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
4037 /* Free the information from XListFontsWithInfo. */
4038 if (n_matching_fonts
)
4039 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
4043 /* Do we need to create the table? */
4044 if (x_font_table_size
== 0)
4046 x_font_table_size
= 16;
4048 = (XFontStruct
**) xmalloc (x_font_table_size
4049 * sizeof (x_font_table
[0]));
4051 /* Do we need to grow the table? */
4052 else if (n_fonts
>= x_font_table_size
)
4054 x_font_table_size
*= 2;
4056 = (XFontStruct
**) xrealloc (x_font_table
,
4058 * sizeof (x_font_table
[0])));
4061 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
4064 /* Now make the frame display the given font. */
4065 if (FRAME_X_WINDOW (f
) != 0)
4067 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
4068 f
->display
.x
->font
->fid
);
4069 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
4070 f
->display
.x
->font
->fid
);
4071 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
4072 f
->display
.x
->font
->fid
);
4074 x_set_window_size (f
, f
->width
, f
->height
);
4078 Lisp_Object lispy_name
= build_string (fontname
);
4081 /* Free the information from XListFontsWithInfo. The data
4082 we actually retain comes from XLoadQueryFont. */
4083 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
4088 #else /* ! defined (HAVE_X11) */
4089 x_new_font (f
, newname
)
4091 register char *newname
;
4096 temp
= XGetFont (newname
);
4097 if (temp
== (FONT_TYPE
*) 0)
4100 if (f
->display
.x
->font
)
4101 XLoseFont (f
->display
.x
->font
);
4103 f
->display
.x
->font
= temp
;
4105 if (FRAME_X_WINDOW (f
) != 0)
4106 x_set_window_size (f
, f
->width
, f
->height
);
4110 #endif /* ! defined (HAVE_X11) */
4112 /* X Window sizes and positions. */
4114 x_calc_absolute_position (f
)
4118 if (f
->display
.x
->left_pos
< 0)
4119 f
->display
.x
->left_pos
= (x_screen_width
4120 - 2 * f
->display
.x
->border_width
4122 + f
->display
.x
->left_pos
);
4124 if (f
->display
.x
->top_pos
< 0)
4125 f
->display
.x
->top_pos
= (x_screen_height
4126 - 2 * f
->display
.x
->border_width
4128 + f
->display
.x
->top_pos
);
4129 #else /* ! defined (HAVE_X11) */
4130 WINDOWINFO_TYPE parentinfo
;
4132 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
4134 if (f
->display
.x
->left_pos
< 0)
4135 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
4136 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
4138 if (f
->display
.x
->top_pos
< 0)
4139 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
4140 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
4141 #endif /* ! defined (HAVE_X11) */
4144 x_set_offset (f
, xoff
, yoff
)
4146 register int xoff
, yoff
;
4148 f
->display
.x
->top_pos
= yoff
;
4149 f
->display
.x
->left_pos
= xoff
;
4150 x_calc_absolute_position (f
);
4153 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4154 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4156 x_wm_set_size_hint (f
, 0);
4157 #endif /* ! defined (HAVE_X11) */
4161 /* Call this to change the size of frame F's x-window. */
4163 x_set_window_size (f
, cols
, rows
)
4167 int pixelwidth
, pixelheight
;
4172 check_frame_size (f
, &rows
, &cols
);
4173 f
->display
.x
->vertical_scroll_bar_extra
=
4174 (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4175 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
4177 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4178 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4181 x_wm_set_size_hint (f
, 0);
4182 #endif /* ! defined (HAVE_X11) */
4183 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4185 /* Now, strictly speaking, we can't be sure that this is accurate,
4186 but the window manager will get around to dealing with the size
4187 change request eventually, and we'll hear how it went when the
4188 ConfigureNotify event gets here.
4190 We could just not bother storing any of this information here,
4191 and let the ConfigureNotify event set everything up, but that
4192 might be kind of confusing to the lisp code, since size changes
4193 wouldn't be reported in the frame parameters until some random
4194 point in the future when the ConfigureNotify event arrives. */
4195 change_frame_size (f
, rows
, cols
, 0, 0);
4196 PIXEL_WIDTH (f
) = pixelwidth
;
4197 PIXEL_HEIGHT (f
) = pixelheight
;
4199 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4200 receive in the ConfigureNotify event; if we get what we asked
4201 for, then the event won't cause the screen to become garbaged, so
4202 we have to make sure to do it here. */
4203 SET_FRAME_GARBAGED (f
);
4210 x_set_resize_hint (f
)
4213 XSetResizeHint (FRAME_X_WINDOW (f
),
4214 2 * f
->display
.x
->internal_border_width
,
4215 2 * f
->display
.x
->internal_border_width
,
4216 FONT_WIDTH (f
->display
.x
->font
),
4217 FONT_HEIGHT (f
->display
.x
->font
));
4219 #endif /* HAVE_X11 */
4221 /* Mouse warping, focus shifting, raising and lowering. */
4223 x_set_mouse_position (f
, x
, y
)
4231 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4232 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4234 if (pix_x
< 0) pix_x
= 0;
4235 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4237 if (pix_y
< 0) pix_y
= 0;
4238 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4242 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4247 x_focus_on_frame (f
)
4252 /* I don't think that the ICCCM allows programs to do things like this
4253 without the interaction of the window manager. Whatever you end up
4254 doing with this code, do it to x_unfocus_frame too. */
4255 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4256 RevertToPointerRoot
, CurrentTime
);
4264 /* Look at the remarks in x_focus_on_frame. */
4265 if (x_focus_frame
== f
)
4266 XSetInputFocus (x_current_display
, PointerRoot
,
4267 RevertToPointerRoot
, CurrentTime
);
4271 #endif /* ! defined (HAVE_X11) */
4273 /* Raise frame F. */
4278 if (f
->async_visible
)
4281 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4287 /* Lower frame F. */
4292 if (f
->async_visible
)
4295 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4302 XTframe_raise_lower (f
, raise
)
4313 /* Change from withdrawn state to mapped state. */
4315 x_make_frame_visible (f
)
4322 if (! FRAME_VISIBLE_P (f
))
4325 if (! EQ (Vx_no_window_manager
, Qt
))
4326 x_wm_set_window_state (f
, NormalState
);
4328 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4329 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4330 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4331 #else /* ! defined (HAVE_X11) */
4332 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4333 if (f
->display
.x
->icon_desc
!= 0)
4334 XUnmapWindow (f
->display
.x
->icon_desc
);
4336 /* Handled by the MapNotify event for X11 */
4337 f
->async_visible
= 1;
4338 f
->async_iconified
= 0;
4340 /* NOTE: this may cause problems for the first frame. */
4342 #endif /* ! defined (HAVE_X11) */
4350 /* Change from mapped state to withdrawn state. */
4352 x_make_frame_invisible (f
)
4357 /* Don't keep the highlight on an invisible frame. */
4358 if (x_highlight_frame
== f
)
4359 x_highlight_frame
= 0;
4361 if (! f
->async_visible
&& ! f
->async_iconified
)
4368 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4369 DefaultScreen (x_current_display
)))
4371 UNBLOCK_INPUT_RESIGNAL
;
4372 error ("can't notify window manager of window withdrawal");
4375 #else /* ! defined (HAVE_X11R4) */
4378 /* Tell the window manager what we're going to do. */
4379 if (! EQ (Vx_no_window_manager
, Qt
))
4383 unmap
.xunmap
.type
= UnmapNotify
;
4384 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4385 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4386 unmap
.xunmap
.from_configure
= False
;
4387 if (! XSendEvent (x_current_display
,
4388 DefaultRootWindow (x_current_display
),
4390 SubstructureRedirectMask
|SubstructureNotifyMask
,
4393 UNBLOCK_INPUT_RESIGNAL
;
4394 error ("can't notify window manager of withdrawal");
4398 /* Unmap the window ourselves. Cheeky! */
4399 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4401 #else /* ! defined (HAVE_X11) */
4403 XUnmapWindow (FRAME_X_WINDOW (f
));
4404 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4405 if (f
->display
.x
->icon_desc
!= 0)
4406 XUnmapWindow (f
->display
.x
->icon_desc
);
4408 #endif /* ! defined (HAVE_X11) */
4409 #endif /* ! defined (HAVE_X11R4) */
4415 /* Change window state from mapped to iconified. */
4422 /* Don't keep the highlight on an invisible frame. */
4423 if (x_highlight_frame
== f
)
4424 x_highlight_frame
= 0;
4426 if (f
->async_iconified
)
4432 /* Since we don't know which revision of X we're running, we'll use both
4433 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4435 /* X11R4: send a ClientMessage to the window manager using the
4436 WM_CHANGE_STATE type. */
4440 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4441 message
.xclient
.type
= ClientMessage
;
4442 message
.xclient
.message_type
= Xatom_wm_change_state
;
4443 message
.xclient
.format
= 32;
4444 message
.xclient
.data
.l
[0] = IconicState
;
4446 if (! XSendEvent (x_current_display
,
4447 DefaultRootWindow (x_current_display
),
4449 SubstructureRedirectMask
| SubstructureNotifyMask
,
4452 UNBLOCK_INPUT_RESIGNAL
;
4453 error ("Can't notify window manager of iconification.");
4457 /* X11R3: set the initial_state field of the window manager hints to
4459 x_wm_set_window_state (f
, IconicState
);
4461 f
->async_iconified
= 1;
4462 #else /* ! defined (HAVE_X11) */
4463 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4465 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4466 if (f
->display
.x
->icon_desc
!= 0)
4468 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4471 #endif /* ! defined (HAVE_X11) */
4477 /* Destroy the X window of frame F. */
4479 x_destroy_window (f
)
4484 if (f
->display
.x
->icon_desc
!= 0)
4485 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4486 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4487 free_frame_faces (f
);
4490 xfree (f
->display
.x
);
4492 if (f
== x_focus_frame
)
4494 if (f
== x_highlight_frame
)
4495 x_highlight_frame
= 0;
4500 /* Manage event queues for X10. */
4504 /* Manage event queues.
4506 This code is only used by the X10 support.
4508 We cannot leave events in the X queue and get them when we are ready
4509 because X does not provide a subroutine to get only a certain kind
4510 of event but not block if there are no queued events of that kind.
4512 Therefore, we must examine events as they come in and copy events
4513 of certain kinds into our private queues.
4515 All ExposeRegion events are put in x_expose_queue.
4516 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4519 /* Write the event *P_XREP into the event queue *QUEUE.
4520 If the queue is full, do nothing, but return nonzero. */
4523 enqueue_event (p_xrep
, queue
)
4524 register XEvent
*p_xrep
;
4525 register struct event_queue
*queue
;
4527 int newindex
= queue
->windex
+ 1;
4528 if (newindex
== EVENT_BUFFER_SIZE
)
4530 if (newindex
== queue
->rindex
)
4532 queue
->xrep
[queue
->windex
] = *p_xrep
;
4533 queue
->windex
= newindex
;
4537 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4538 If *QUEUE is empty, do nothing and return 0. */
4541 dequeue_event (p_xrep
, queue
)
4542 register XEvent
*p_xrep
;
4543 register struct event_queue
*queue
;
4545 if (queue
->windex
== queue
->rindex
)
4547 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4548 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4553 /* Return the number of events buffered in *QUEUE. */
4556 queue_event_count (queue
)
4557 register struct event_queue
*queue
;
4559 int tem
= queue
->windex
- queue
->rindex
;
4562 return EVENT_BUFFER_SIZE
+ tem
;
4565 /* Return nonzero if mouse input is pending. */
4568 mouse_event_pending_p ()
4570 return queue_event_count (&x_mouse_queue
);
4572 #endif /* HAVE_X11 */
4574 /* Setting window manager hints. */
4578 x_wm_set_size_hint (f
, prompting
)
4582 XSizeHints size_hints
;
4583 Window window
= FRAME_X_WINDOW (f
);
4585 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
4587 flexlines
= f
->height
;
4589 size_hints
.x
= f
->display
.x
->left_pos
;
4590 size_hints
.y
= f
->display
.x
->top_pos
;
4591 size_hints
.height
= PIXEL_HEIGHT (f
);
4592 size_hints
.width
= PIXEL_WIDTH (f
);
4593 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4594 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4596 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4597 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4600 int base_width
, base_height
;
4602 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4603 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4606 int min_rows
= 0, min_cols
= 0;
4607 check_frame_size (f
, &min_rows
, &min_cols
);
4609 /* The window manager uses the base width hints to calculate the
4610 current number of rows and columns in the frame while
4611 resizing; min_width and min_height aren't useful for this
4612 purpose, since they might not give the dimensions for a
4613 zero-row, zero-column frame.
4615 We use the base_width and base_height members if we have
4616 them; otherwise, we set the min_width and min_height members
4617 to the size for a zero x zero frame. */
4620 size_hints
.flags
|= PBaseSize
;
4621 size_hints
.base_width
= base_width
;
4622 size_hints
.base_height
= base_height
;
4623 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4624 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4626 size_hints
.min_width
= base_width
;
4627 size_hints
.min_height
= base_height
;
4634 size_hints
.flags
|= prompting
;
4637 XSizeHints hints
; /* Sometimes I hate X Windows... */
4639 if (XGetNormalHints (x_current_display
, window
, &hints
) == 0)
4641 if (hints
.flags
& PSize
)
4642 size_hints
.flags
|= PSize
;
4643 if (hints
.flags
& PPosition
)
4644 size_hints
.flags
|= PPosition
;
4645 if (hints
.flags
& USPosition
)
4646 size_hints
.flags
|= USPosition
;
4647 if (hints
.flags
& USSize
)
4648 size_hints
.flags
|= USSize
;
4652 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4654 XSetNormalHints (x_current_display
, window
, &size_hints
);
4658 /* Used for IconicState or NormalState */
4659 x_wm_set_window_state (f
, state
)
4663 Window window
= FRAME_X_WINDOW (f
);
4665 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4666 f
->display
.x
->wm_hints
.initial_state
= state
;
4668 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4671 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4675 Window window
= FRAME_X_WINDOW (f
);
4679 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4680 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4683 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4685 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4688 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4692 Window window
= FRAME_X_WINDOW (f
);
4694 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4695 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4696 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4698 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4702 /* Initialization. */
4705 x_term_init (display_name
)
4711 extern int old_fcntl_owner
;
4712 #endif /* ! defined (F_SETOWN) */
4714 x_focus_frame
= x_highlight_frame
= 0;
4716 x_current_display
= XOpenDisplay (display_name
);
4717 if (x_current_display
== 0)
4718 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4723 int hostname_size
= 256;
4725 hostname
= (char *) xmalloc (hostname_size
);
4728 XSetAfterFunction (x_current_display
, x_trace_wire
);
4731 /* Try to get the host name; if the buffer is too short, try
4732 again. Apparently, the only indication gethostname gives of
4733 whether the buffer was large enough is the presence or absence
4734 of a '\0' in the string. Eech. */
4737 gethostname (hostname
, hostname_size
- 1);
4738 hostname
[hostname_size
- 1] = '\0';
4740 /* Was the buffer large enough for gethostname to store the '\0'? */
4741 if (strlen (hostname
) < hostname_size
- 1)
4744 hostname_size
<<= 1;
4745 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4747 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4750 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
4753 /* Figure out which modifier bits mean what. */
4754 x_find_modifier_meanings ();
4756 /* Get the scroll bar cursor. */
4757 x_vertical_scroll_bar_cursor
4758 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4761 /* Watch for PropertyNotify events on the root window; we use them
4762 to figure out when to invalidate our cache of the cut buffers. */
4763 x_watch_cut_buffer_cache ();
4766 if (ConnectionNumber (x_current_display
) != 0)
4768 dup2 (ConnectionNumber (x_current_display
), 0);
4770 #ifndef SYSV_STREAMS
4771 /* Streams somehow keeps track of which descriptor number
4772 is being used to talk to X. So it is not safe to substitute
4773 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4774 close (ConnectionNumber (x_current_display
));
4775 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4776 * check the def of the macro;
4777 * it is a genuine lvalue */
4778 #endif /* SYSV_STREAMS */
4781 #endif /* ! defined (HAVE_X11) */
4784 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4785 #ifdef F_SETOWN_SOCK_NEG
4786 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4787 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4788 fcntl (0, F_SETOWN
, getpid ());
4789 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4790 #endif /* ! defined (F_SETOWN) */
4794 #endif /* ! defined (SIGIO) */
4796 /* Must use interrupt input because we cannot otherwise
4797 arrange for C-g to be noticed immediately.
4798 We cannot connect it to SIGINT. */
4799 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4801 expose_all_windows
= 0;
4803 clear_frame_hook
= XTclear_frame
;
4804 clear_end_of_line_hook
= XTclear_end_of_line
;
4805 ins_del_lines_hook
= XTins_del_lines
;
4806 change_line_highlight_hook
= XTchange_line_highlight
;
4807 insert_glyphs_hook
= XTinsert_glyphs
;
4808 write_glyphs_hook
= XTwrite_glyphs
;
4809 delete_glyphs_hook
= XTdelete_glyphs
;
4810 ring_bell_hook
= XTring_bell
;
4811 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4812 set_terminal_modes_hook
= XTset_terminal_modes
;
4813 update_begin_hook
= XTupdate_begin
;
4814 update_end_hook
= XTupdate_end
;
4815 set_terminal_window_hook
= XTset_terminal_window
;
4816 read_socket_hook
= XTread_socket
;
4817 cursor_to_hook
= XTcursor_to
;
4818 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4819 mouse_position_hook
= XTmouse_position
;
4820 frame_rehighlight_hook
= XTframe_rehighlight
;
4821 frame_raise_lower_hook
= XTframe_raise_lower
;
4822 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
4823 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
4824 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
4825 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
4827 scroll_region_ok
= 1; /* we'll scroll partial frames */
4828 char_ins_del_ok
= 0; /* just as fast to write the line */
4829 line_ins_del_ok
= 1; /* we'll just blt 'em */
4830 fast_clear_end_of_line
= 1; /* X does this well */
4831 memory_below_frame
= 0; /* we don't remember what scrolls
4835 /* Note that there is no real way portable across R3/R4 to get the
4836 original error handler. */
4837 XHandleError (x_error_quitter
);
4838 XHandleIOError (x_io_error_quitter
);
4840 /* Disable Window Change signals; they are handled by X events. */
4842 signal (SIGWINCH
, SIG_DFL
);
4843 #endif /* ! defined (SIGWINCH) */
4845 signal (SIGPIPE
, x_connection_closed
);
4851 staticpro (&last_mouse_scroll_bar
);
4853 #endif /* ! defined (HAVE_X11) */
4854 #endif /* ! defined (HAVE_X_WINDOWS) */