1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992, 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.
34 /* On 4.3 these lose if they come after xterm.h. */
38 /* This may include sys/types.h, and that somehow loses
39 if this is not done before the other system files. */
41 #include <X11/cursorfont.h>
44 /* Load sys/types.h if not already loaded.
45 In some systems loading it twice is suicidal. */
47 #include <sys/types.h>
52 #include <sys/ioctl.h>
54 #else /* ! defined (BSD) */
55 #include <sys/termio.h>
57 #endif /* ! defined (BSD) */
59 /* Allow m- file to inhibit use of FIONREAD. */
60 #ifdef BROKEN_FIONREAD
62 #endif /* ! defined (BROKEN_FIONREAD) */
64 /* We are unable to use interrupts if FIONREAD is not available,
65 so flush SIGIO so we won't try. */
69 #endif /* ! defined (SIGIO) */
79 #include <sys/param.h>
81 #include "dispextern.h"
82 #include "termhooks.h"
96 #define XMapWindow XMapRaised /* Raise them when mapping. */
97 #else /* ! defined (HAVE_X11) */
98 #include <X/Xkeyboard.h>
99 /*#include <X/Xproto.h> */
100 #endif /* ! defined (HAVE_X11) */
102 /* For sending Meta-characters. Do we need this? */
105 #define min(a,b) ((a)<(b) ? (a) : (b))
106 #define max(a,b) ((a)>(b) ? (a) : (b))
108 /* Nonzero means we must reprint all windows
109 because 1) we received an ExposeWindow event
110 or 2) we received too many ExposeRegion events to record.
112 This is never needed under X11. */
113 static int expose_all_windows
;
115 /* Nonzero means we must reprint all icon windows. */
117 static int expose_all_icons
;
120 /* ExposeRegion events, when received, are copied into this queue
121 for later processing. */
123 static struct event_queue x_expose_queue
;
125 /* ButtonPressed and ButtonReleased events, when received,
126 are copied into this queue for later processing. */
128 struct event_queue x_mouse_queue
;
129 #endif /* HAVE_X11 */
131 /* Nonzero after BLOCK_INPUT; prevents input events from being
132 processed until later. */
136 #if defined (SIGIO) && defined (FIONREAD)
137 int BLOCK_INPUT_mask
;
138 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
140 /* Nonzero if input events came in while x_input_blocked was nonzero.
141 UNBLOCK_INPUT checks for this. */
145 /* The id of a bitmap used for icon windows.
146 One such map is shared by all Emacs icon windows.
147 This is zero if we have not yet had a need to create the bitmap. */
149 static Bitmap icon_bitmap
;
151 /* Font used for text icons. */
153 static FONT_TYPE
*icon_font_info
;
155 /* Stuff for dealing with the main icon title. */
157 extern Lisp_Object Vcommand_line_args
;
158 char *hostname
, *x_id_name
;
159 Lisp_Object invocation_name
;
161 /* This is the X connection that we are using. */
163 Display
*x_current_display
;
165 /* The cursor to use for vertical scroll bars on x_current_display. */
166 static Cursor x_vertical_scroll_bar_cursor
;
168 /* Frame being updated by update_frame. */
169 /* This is set by XTupdate_begin and looked at by all the
170 XT functions. It is zero while not inside an update.
171 In that case, the XT functions assume that `selected_frame'
172 is the frame to apply to. */
174 static struct frame
*updating_frame
;
176 /* The frame (if any) which has the X window that has keyboard focus.
177 Zero if none. This is examined by Ffocus_frame in frame.c. Note
178 that a mere EnterNotify event can set this; if you need to know the
179 last frame specified in a FocusIn or FocusOut event, use
180 x_focus_event_frame. */
181 struct frame
*x_focus_frame
;
183 /* The last frame mentioned in a FocusIn or FocusOut event. This is
184 separate from x_focus_frame, because whether or not LeaveNotify
185 events cause us to lose focus depends on whether or not we have
186 received a FocusIn event for it. */
187 struct frame
*x_focus_event_frame
;
189 /* The frame which currently has the visual highlight, and should get
190 keyboard input (other sorts of input have the frame encoded in the
191 event). It points to the X focus frame's selected window's
192 frame. It differs from x_focus_frame when we're using a global
194 static struct frame
*x_highlight_frame
;
196 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
197 mouse is moved to inside of frame when frame is de-iconified. */
199 static int warp_mouse_on_deiconify
;
201 /* During an update, maximum vpos for ins/del line operations to affect. */
203 static int flexlines
;
205 /* During an update, nonzero if chars output now should be highlighted. */
207 static int highlight
;
209 /* Nominal cursor position -- where to draw output.
210 During an update, these are different from the cursor-box position. */
216 /* `t' if a mouse button is depressed. */
218 extern Lisp_Object Vmouse_depressed
;
220 /* Tells if a window manager is present or not. */
222 extern Lisp_Object Vx_no_window_manager
;
224 /* Timestamp that we requested selection data was made. */
225 extern Time requestor_time
;
227 /* ID of the window requesting selection data. */
228 extern Window requestor_window
;
230 /* Nonzero enables some debugging for the X interface code. */
233 #else /* ! defined (HAVE_X11) */
235 /* Bit patterns for the mouse cursor. */
237 short MouseCursor
[] = {
238 0x0000, 0x0008, 0x0018, 0x0038,
239 0x0078, 0x00f8, 0x01f8, 0x03f8,
240 0x07f8, 0x00f8, 0x00d8, 0x0188,
241 0x0180, 0x0300, 0x0300, 0x0000};
243 short MouseMask
[] = {
244 0x000c, 0x001c, 0x003c, 0x007c,
245 0x00fc, 0x01fc, 0x03fc, 0x07fc,
246 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
247 0x03cc, 0x0780, 0x0780, 0x0300};
249 static short grey_bits
[] = {
250 0x0005, 0x000a, 0x0005, 0x000a};
252 static Pixmap GreyPixmap
= 0;
253 #endif /* ! defined (HAVE_X11) */
255 /* From time to time we get info on an Emacs window, here. */
257 static WINDOWINFO_TYPE windowinfo
;
261 /* See keyboard.c. */
262 extern int extra_keyboard_modifiers
;
264 extern Display
*XOpenDisplay ();
265 extern Window
XCreateWindow ();
267 extern Cursor
XCreateCursor ();
268 extern FONT_TYPE
*XOpenFont ();
270 static void flashback ();
273 static void dumpqueue ();
274 #endif /* HAVE_X11 */
277 static int XTcursor_to ();
278 static int XTclear_end_of_line ();
281 /* Starting and ending updates.
283 These hooks are called by update_frame at the beginning and end
284 of a frame update. We record in `updating_frame' the identity
285 of the frame being updated, so that the XT... functions do not
286 need to take a frame as argument. Most of the XT... functions
287 should never be called except during an update, the only exceptions
288 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
290 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
302 flexlines
= f
->height
;
308 #endif /* HAVE_X11 */
313 static void x_do_pending_expose ();
322 if (updating_frame
== 0
323 || updating_frame
!= f
)
329 x_do_pending_expose ();
330 #endif /* HAVE_X11 */
332 x_display_cursor (f
, 1);
339 /* External interface to control of standout mode.
340 Call this when about to modify line at position VPOS
341 and not change whether it is highlighted. */
343 XTreassert_line_highlight (new, vpos
)
349 /* Call this when about to modify line at position VPOS
350 and change whether it is highlighted. */
353 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
354 int new_highlight
, vpos
, first_unused_hpos
;
356 highlight
= new_highlight
;
357 XTcursor_to (vpos
, 0);
358 XTclear_end_of_line (updating_frame
->width
);
361 /* This is used when starting Emacs and when restarting after suspend.
362 When starting Emacs, no X window is mapped. And nothing must be done
363 to Emacs's own window if it is suspended (though that rarely happens). */
366 XTset_terminal_modes ()
370 /* This is called when exiting or suspending Emacs.
371 Exiting will make the X-windows go away, and suspending
372 requires no action. */
375 XTreset_terminal_modes ()
377 /* XTclear_frame (); */
380 /* Set the nominal cursor position of the frame.
381 This is where display update commands will take effect.
382 This does not affect the place where the cursor-box is displayed. */
385 XTcursor_to (row
, col
)
386 register int row
, col
;
394 if (updating_frame
== 0)
397 x_display_cursor (selected_frame
, 1);
403 /* Display a sequence of N glyphs found at GP.
404 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
405 HL is 1 if this text is highlighted, 2 if the cursor is on it.
407 FONT is the default font to use (for glyphs whose font-code is 0). */
410 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
413 register GLYPH
*gp
; /* Points to first GLYPH. */
414 register int n
; /* Number of glyphs to display. */
419 Window window
= FRAME_X_WINDOW (f
);
420 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
421 : (hl
? f
->display
.x
->reverse_gc
422 : f
->display
.x
->normal_gc
));
424 if (sizeof (GLYPH
) == sizeof (XChar2b
))
425 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
426 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
427 else if (sizeof (GLYPH
) == sizeof (unsigned char))
428 XDrawImageString (x_current_display
, window
, drawing_gc
,
429 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
431 /* What size of glyph ARE you using? And does X have a function to
438 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
441 register GLYPH
*gp
; /* Points to first GLYPH. */
442 register int n
; /* Number of glyphs to display. */
446 char buf
[f
->width
]; /* Holds characters to be displayed. */
447 register char *cp
; /* Steps through buf[]. */
448 register int tlen
= GLYPH_TABLE_LENGTH
;
449 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
450 Window window
= FRAME_X_WINDOW (f
);
451 int cursor_pixel
= f
->display
.x
->cursor_pixel
;
452 int fg_pixel
= f
->display
.x
->foreground_pixel
;
453 int bg_pixel
= f
->display
.x
->background_pixel
;
454 int intborder
= f
->display
.x
->internal_border_width
;
458 /* Get the face-code of the next GLYPH. */
462 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
463 g
= GLYPH_ALIAS (tbase
, g
);
467 /* Find the run of consecutive glyphs with the same face-code.
468 Extract their character codes into BUF. */
473 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
474 g
= GLYPH_ALIAS (tbase
, g
);
483 /* LEN gets the length of the run. */
486 /* Now output this run of chars, with the font and pixel values
487 determined by the face code CF. */
491 GC GC_cursor
= f
->display
.x
->cursor_gc
;
492 GC GC_reverse
= f
->display
.x
->reverse_gc
;
493 GC GC_normal
= f
->display
.x
->normal_gc
;
495 XDrawImageString (x_current_display
, window
,
498 : (hl
? GC_reverse
: GC_normal
)),
499 left
, top
+ FONT_BASE (font
), buf
, len
);
500 #else /* ! defined (HAVE_X11) */
501 XText (window
, left
, top
,
506 ? (cursor_pixel
== fg_pixel
? bg_pixel
: fg_pixel
)
507 : hl
? bg_pixel
: fg_pixel
),
508 (hl
== 2 ? cursor_pixel
509 : hl
? fg_pixel
: bg_pixel
));
510 #endif /* ! defined (HAVE_X11) */
515 if (FACE_IS_FONT (cf
))
516 XDrawImageString (x_current_display
, FRAME_X_WINDOW (f
),
518 left
, top
+ FONT_BASE (FACE_FONT (cf
)),
520 else if (FACE_IS_IMAGE (cf
))
521 XCopyPlane (x_current_display
, FACE_IMAGE (cf
),
523 f
->display
.x
->normal_gc
,
525 FACE_IMAGE_WIDTH (cf
),
526 FACE_IMAGE_HEIGHT (cf
), left
, top
);
529 #else /* ! defined (HAVE_X11) */
530 register struct face
*fp
= x_face_table
[cf
];
532 XText (window
, left
, top
,
537 ? (cursor_pixel
== fp
->fg
? fp
->bg
: fp
->fg
)
538 : hl
? fp
->bg
: fp
->fg
),
539 (hl
== 2 ? cursor_pixel
540 : hl
? fp
->fg
: fp
->bg
));
541 #endif /* ! defined (HAVE_X11) */
543 left
+= len
* FONT_WIDTH (font
);
548 /* Output some text at the nominal frame cursor position.
549 Advance the cursor over the text.
550 Output LEN glyphs at START.
552 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
553 controls the pixel values used for foreground and background. */
556 XTwrite_glyphs (start
, len
)
557 register GLYPH
*start
;
560 register int temp_length
;
570 /* If not within an update,
571 output at the frame's visible cursor. */
572 curs_x
= f
->cursor_x
;
573 curs_y
= f
->cursor_y
;
577 CHAR_TO_PIXEL_COL (f
, curs_x
),
578 CHAR_TO_PIXEL_ROW (f
, curs_y
),
579 start
, len
, highlight
, f
->display
.x
->font
);
581 /* If we drew on top of the cursor, note that it is turned off. */
582 if (curs_y
== f
->phys_cursor_y
583 && curs_x
<= f
->phys_cursor_x
584 && curs_x
+ len
> f
->phys_cursor_x
)
585 f
->phys_cursor_x
= -1;
587 if (updating_frame
== 0)
590 x_display_cursor (f
, 1);
599 /* Clear to the end of the line.
600 Erase the current text line from the nominal cursor position (inclusive)
601 to column FIRST_UNUSED (exclusive). The idea is that everything
602 from FIRST_UNUSED onward is already erased. */
605 XTclear_end_of_line (first_unused
)
606 register int first_unused
;
608 struct frame
*f
= updating_frame
;
614 if (curs_y
< 0 || curs_y
>= f
->height
)
616 if (first_unused
<= 0)
619 if (first_unused
>= f
->width
)
620 first_unused
= f
->width
;
624 /* Notice if the cursor will be cleared by this operation. */
625 if (curs_y
== f
->phys_cursor_y
626 && curs_x
<= f
->phys_cursor_x
627 && f
->phys_cursor_x
< first_unused
)
628 f
->phys_cursor_x
= -1;
631 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
632 CHAR_TO_PIXEL_COL (f
, curs_x
),
633 CHAR_TO_PIXEL_ROW (f
, curs_y
),
634 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
635 FONT_HEIGHT (f
->display
.x
->font
), False
);
637 #else /* ! defined (HAVE_X11) */
638 XPixSet (FRAME_X_WINDOW (f
),
639 CHAR_TO_PIXEL_COL (f
, curs_x
),
640 CHAR_TO_PIXEL_ROW (f
, curs_y
),
641 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
642 FONT_HEIGHT (f
->display
.x
->font
),
643 f
->display
.x
->background_pixel
);
644 #endif /* ! defined (HAVE_X11) */
653 struct frame
*f
= updating_frame
;
658 f
->phys_cursor_x
= -1; /* Cursor not visible. */
659 curs_x
= 0; /* Nominal cursor position is top left. */
664 XClear (FRAME_X_WINDOW (f
));
666 /* We have to clear the scroll bars, too. If we have changed
667 colors or something like that, then they should be notified. */
668 x_scroll_bar_clear (f
);
672 #endif /* HAVE_X11 */
678 /* Invert the middle quarter of the frame for .15 sec. */
680 /* We use the select system call to do the waiting, so we have to make sure
681 it's avaliable. If it isn't, we just won't do visual bells. */
682 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
684 /* Subtract the `struct timeval' values X and Y,
685 storing the result in RESULT.
686 Return 1 if the difference is negative, otherwise 0. */
689 timeval_subtract (result
, x
, y
)
690 struct timeval
*result
, x
, y
;
692 /* Perform the carry for the later subtraction by updating y.
693 This is safer because on some systems
694 the tv_sec member is unsigned. */
695 if (x
.tv_usec
< y
.tv_usec
)
697 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
698 y
.tv_usec
-= 1000000 * nsec
;
701 if (x
.tv_usec
- y
.tv_usec
> 1000000)
703 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
704 y
.tv_usec
+= 1000000 * nsec
;
708 /* Compute the time remaining to wait. tv_usec is certainly positive. */
709 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
710 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
712 /* Return indication of whether the result should be considered negative. */
713 return x
.tv_sec
< y
.tv_sec
;
724 /* Create a GC that will use the GXxor function to flip foreground pixels
725 into background pixels. */
729 values
.function
= GXxor
;
730 values
.foreground
= (f
->display
.x
->foreground_pixel
731 ^ f
->display
.x
->background_pixel
);
733 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
734 GCFunction
| GCForeground
, &values
);
738 int width
= PIXEL_WIDTH (f
);
739 int height
= PIXEL_HEIGHT (f
);
741 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
742 width
/4, height
/4, width
/2, height
/2);
743 XFlush (x_current_display
);
746 struct timeval wakeup
, now
;
748 gettimeofday (&wakeup
, (struct timezone
*) 0);
750 /* Compute time to wait until, propagating carry from usecs. */
751 wakeup
.tv_usec
+= 150000;
752 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
753 wakeup
.tv_usec
%= 1000000;
755 /* Keep waiting until past the time wakeup. */
758 struct timeval timeout
;
760 gettimeofday (&timeout
, (struct timezone
*)0);
762 /* In effect, timeout = wakeup - timeout.
763 Break if result would be negative. */
764 if (timeval_subtract (&timeout
, wakeup
, timeout
))
767 /* Try to wait that long--but we might wake up sooner. */
768 select (0, 0, 0, 0, &timeout
);
772 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
773 width
/4, height
/4, width
/2, height
/2);
774 XFreeGC (x_current_display
, gc
);
775 XFlush (x_current_display
);
785 /* Make audible bell. */
788 #define XRINGBELL XBell(x_current_display, 0)
789 #else /* ! defined (HAVE_X11) */
790 #define XRINGBELL XFeep(0);
791 #endif /* ! defined (HAVE_X11) */
795 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
797 XTflash (selected_frame
);
808 /* Insert and delete character.
809 These are not supposed to be used because we are supposed to turn
810 off the feature of using them. */
813 XTinsert_glyphs (start
, len
)
814 register char *start
;
827 /* Specify how many text lines, from the top of the window,
828 should be affected by insert-lines and delete-lines operations.
829 This, and those operations, are used only within an update
830 that is bounded by calls to XTupdate_begin and XTupdate_end. */
833 XTset_terminal_window (n
)
836 if (updating_frame
== 0)
839 if ((n
<= 0) || (n
> updating_frame
->height
))
840 flexlines
= updating_frame
->height
;
845 /* Perform an insert-lines operation.
846 Insert N lines at a vertical position curs_y. */
852 register int topregion
, bottomregion
;
853 register int length
, newtop
, mask
;
854 register struct frame
*f
= updating_frame
;
855 int intborder
= f
->display
.x
->internal_border_width
;
857 if (curs_y
>= flexlines
)
861 bottomregion
= flexlines
- (n
+ 1);
862 newtop
= topregion
+ n
;
863 length
= (bottomregion
- topregion
) + 1;
867 #endif /* HAVE_X11 */
869 if ((length
> 0) && (newtop
<= flexlines
))
872 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
873 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
874 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
875 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
876 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
877 CHAR_TO_PIXEL_ROW (f
, newtop
));
878 #else /* ! defined (HAVE_X11) */
879 XMoveArea (FRAME_X_WINDOW (f
),
880 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
881 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
882 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
883 length
* FONT_HEIGHT (f
->display
.x
->font
));
884 /* Now we must process any ExposeRegion events that occur
885 if the area being copied from is obscured.
886 We can't let it wait because further i/d operations
887 may want to copy this area to another area. */
889 #endif /* ! defined (HAVE_X11) */
892 newtop
= min (newtop
, (flexlines
- 1));
893 length
= newtop
- topregion
;
897 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
898 CHAR_TO_PIXEL_ROW (f
, topregion
),
899 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
900 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
901 #else /* ! defined (HAVE_X11) */
902 XPixSet (FRAME_X_WINDOW (f
),
904 CHAR_TO_PIXEL_ROW (f
, topregion
),
905 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
906 n
* FONT_HEIGHT (f
->display
.x
->font
),
907 f
->display
.x
->background_pixel
);
908 #endif /* ! defined (HAVE_X11) */
912 /* Perform a delete-lines operation, deleting N lines
913 at a vertical position curs_y. */
920 register struct frame
*f
= updating_frame
;
921 int intborder
= f
->display
.x
->internal_border_width
;
923 if (curs_y
>= flexlines
)
928 #endif /* HAVE_X11 */
930 if ((curs_y
+ n
) >= flexlines
)
932 if (flexlines
>= (curs_y
+ 1))
935 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
936 CHAR_TO_PIXEL_ROW (f
, curs_y
),
937 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
938 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
939 #else /* ! defined (HAVE_X11) */
940 XPixSet (FRAME_X_WINDOW (f
),
941 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
942 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
943 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
944 f
->display
.x
->background_pixel
);
945 #endif /* ! defined (HAVE_X11) */
951 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
952 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
954 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
955 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
956 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
957 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
958 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
960 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
961 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
962 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
963 #else /* ! defined (HAVE_X11) */
964 XMoveArea (FRAME_X_WINDOW (f
),
966 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
967 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
968 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
969 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
970 /* Now we must process any ExposeRegion events that occur
971 if the area being copied from is obscured.
972 We can't let it wait because further i/d operations
973 may want to copy this area to another area. */
975 XPixSet (FRAME_X_WINDOW (f
), intborder
,
976 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
977 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
978 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
979 #endif /* ! defined (HAVE_X11) */
983 /* Perform an insert-lines or delete-lines operation,
984 inserting N lines or deleting -N lines at vertical position VPOS. */
986 XTins_del_lines (vpos
, n
)
989 if (updating_frame
== 0)
992 /* Hide the cursor. */
993 x_display_cursor (updating_frame
, 0);
995 XTcursor_to (vpos
, 0);
1006 /* Support routines for exposure events. */
1007 static void clear_cursor ();
1009 /* Output into a rectangle of an X-window (for frame F)
1010 the characters in f->phys_lines that overlap that rectangle.
1011 TOP and LEFT are the position of the upper left corner of the rectangle.
1012 ROWS and COLS are the size of the rectangle. */
1015 dumprectangle (f
, left
, top
, cols
, rows
)
1017 register int left
, top
, cols
, rows
;
1019 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1020 int cursor_cleared
= 0;
1024 if (FRAME_GARBAGED_P (f
))
1027 /* Express rectangle as four edges, instead of position-and-size. */
1028 bottom
= top
+ rows
;
1029 right
= left
+ cols
;
1031 #ifndef HAVE_X11 /* Window manger does this for X11. */
1033 int intborder
= f
->display
.x
->internal_border_width
;
1035 /* If the rectangle includes any of the internal border area,
1036 redisplay the border emphasis. */
1037 if (top
< intborder
|| left
< intborder
1038 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1039 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1042 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1044 /* Convert rectangle edges in pixels to edges in chars.
1045 Round down for left and top, up for right and bottom. */
1046 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1047 left
= PIXEL_TO_CHAR_COL (f
, left
);
1048 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1049 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1050 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1051 right
= PIXEL_TO_CHAR_COL (f
, right
);
1053 /* Clip the rectangle to what can be visible. */
1058 if (right
> f
->width
)
1060 if (bottom
> f
->height
)
1063 /* Get size in chars of the rectangle. */
1064 cols
= right
- left
;
1065 rows
= bottom
- top
;
1067 /* If rectangle has zero area, return. */
1068 if (rows
<= 0) return;
1069 if (cols
<= 0) return;
1071 /* Turn off the cursor if it is in the rectangle.
1072 We will turn it back on afterward. */
1073 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1074 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1080 /* Display the text in the rectangle, one text line at a time. */
1082 for (y
= top
; y
< bottom
; y
++)
1084 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1086 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1090 CHAR_TO_PIXEL_COL (f
, left
),
1091 CHAR_TO_PIXEL_ROW (f
, y
),
1092 line
, min (cols
, active_frame
->used
[y
] - left
),
1093 active_frame
->highlight
[y
], f
->display
.x
->font
);
1096 /* Turn the cursor on if we turned it off. */
1099 x_display_cursor (f
, 1);
1103 /* Process all queued ExposeRegion events. */
1109 XExposeRegionEvent r
;
1111 while (dequeue_event (&r
, &x_expose_queue
))
1113 struct frame
*f
= x_window_to_frame (r
.window
);
1114 if (f
->display
.x
->icon_desc
== r
.window
)
1117 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1121 #endif /* HAVE_X11 */
1123 /* Process all expose events that are pending, for X10.
1124 Redraws the cursor if necessary on any frame that
1125 is not in the process of being updated with update_frame. */
1129 x_do_pending_expose ()
1133 Lisp_Object tail
, frame
;
1135 if (expose_all_windows
)
1137 expose_all_windows
= 0;
1138 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1140 register int temp_width
, temp_height
;
1143 frame
= XCONS (tail
)->car
;
1144 if (XGCTYPE (frame
) != Lisp_Frame
)
1147 if (! FRAME_X_P (f
))
1149 if (!f
->async_visible
)
1151 if (!f
->display
.x
->needs_exposure
)
1154 intborder
= f
->display
.x
->internal_border_width
;
1157 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1158 temp_width
= ((windowinfo
.width
- 2 * intborder
1159 - f
->display
.x
->v_scroll_bar_width
)
1160 / FONT_WIDTH (f
->display
.x
->font
));
1161 temp_height
= ((windowinfo
.height
- 2 * intborder
1162 - f
->display
.x
->h_scroll_bar_height
)
1163 / FONT_HEIGHT (f
->display
.x
->font
));
1164 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1166 change_frame_size (f
, max (1, temp_height
),
1167 max (1, temp_width
), 0, 1);
1168 x_resize_scroll_bars (f
);
1170 f
->display
.x
->left_pos
= windowinfo
.x
;
1171 f
->display
.x
->top_pos
= windowinfo
.y
;
1172 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1176 f
->display
.x
->needs_exposure
= 0;
1177 if (updating_frame
!= f
)
1178 x_display_cursor (f
, 1);
1183 /* Handle any individual-rectangle expose events queued
1184 for various windows. */
1187 #else /* ! defined (HAVE_X11) */
1189 #endif /* ! defined (HAVE_X11) */
1195 frame_highlight (frame
)
1196 struct frame
*frame
;
1198 if (! EQ (Vx_no_window_manager
, Qnil
))
1199 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1200 frame
->display
.x
->border_pixel
);
1201 x_display_cursor (frame
, 1);
1205 frame_unhighlight (frame
)
1206 struct frame
*frame
;
1208 if (! EQ (Vx_no_window_manager
, Qnil
))
1209 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1210 frame
->display
.x
->border_tile
);
1211 x_display_cursor (frame
, 1);
1213 #else /* ! defined (HAVE_X11) */
1214 /* Dump the border-emphasis of frame F.
1215 If F is selected, this is a lining of the same color as the border,
1216 just within the border, occupying a portion of the internal border.
1217 If F is not selected, it is background in the same place.
1218 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1220 ALWAYS = 1 is used when a frame becomes selected or deselected.
1221 In that case, we also turn the cursor off and on again
1222 so it will appear in the proper shape (solid if selected; else hollow.) */
1225 dumpborder (f
, always
)
1229 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1230 int width
= PIXEL_WIDTH (f
);
1231 int height
= PIXEL_HEIGHT (f
);
1234 if (f
!= selected_frame
)
1239 pixel
= f
->display
.x
->background_pixel
;
1243 pixel
= f
->display
.x
->border_pixel
;
1246 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1247 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1248 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1250 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1254 x_display_cursor (f
, 1);
1256 #endif /* ! defined (HAVE_X11) */
1258 static void XTframe_rehighlight ();
1260 /* The focus has changed. Update the frames as necessary to reflect
1261 the new situation. Note that we can't change the selected frame
1262 here, because the lisp code we are interrupting might become confused.
1263 Each event gets marked with the frame in which it occured, so the
1264 lisp code can tell when the switch took place by examining the events. */
1267 x_new_focus_frame (frame
)
1268 struct frame
*frame
;
1270 struct frame
*old_focus
= x_focus_frame
;
1271 int events_enqueued
= 0;
1273 if (frame
!= x_focus_frame
)
1275 /* Set this before calling other routines, so that they see
1276 the correct value of x_focus_frame. */
1277 x_focus_frame
= frame
;
1279 if (old_focus
&& old_focus
->auto_lower
)
1280 x_lower_frame (old_focus
);
1283 selected_frame
= frame
;
1284 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1285 Lisp_Frame
, selected_frame
);
1286 Fselect_window (selected_frame
->selected_window
);
1287 choose_minibuf_frame ();
1290 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1291 x_raise_frame (x_focus_frame
);
1294 XTframe_rehighlight ();
1298 /* The focus has changed, or we have redirected a frame's focus to
1299 another frame (this happens when a frame uses a surrogate
1300 minibuffer frame). Shift the highlight as appropriate. */
1302 XTframe_rehighlight ()
1304 struct frame
*old_highlight
= x_highlight_frame
;
1309 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1310 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1312 if (! FRAME_LIVE_P (x_highlight_frame
))
1314 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1315 x_highlight_frame
= x_focus_frame
;
1319 x_highlight_frame
= 0;
1321 if (x_highlight_frame
!= old_highlight
)
1324 frame_unhighlight (old_highlight
);
1325 if (x_highlight_frame
)
1326 frame_highlight (x_highlight_frame
);
1330 /* Mouse clicks and mouse movement. Rah. */
1333 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1334 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1335 that the glyph at X, Y occupies, if BOUNDS != 0. */
1337 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1339 register unsigned int pix_x
, pix_y
;
1340 register int *x
, *y
;
1343 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1344 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1348 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1349 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1350 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1351 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1354 if (pix_x
< 0) pix_x
= 0;
1355 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1357 if (pix_y
< 0) pix_y
= 0;
1358 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1364 /* Any buttons grabbed. */
1365 unsigned int x_mouse_grabbed
;
1367 /* Which modifier keys are on which modifier bits?
1369 With each keystroke, X returns eight bits indicating which modifier
1370 keys were held down when the key was pressed. The interpretation
1371 of the top five modifier bits depends on what keys are attached
1372 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1375 x_meta_mod_mask is a mask containing the bits used for the meta key.
1376 It may have more than one bit set, if more than one modifier bit
1377 has meta keys on it. Basically, if EVENT is a KeyPress event,
1378 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1380 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1381 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1382 only be affected by the lock modifier bit if XK_Shift_Lock is in
1383 use; XK_Caps_Lock should only affect alphabetic keys. With this
1384 arrangement, the lock modifier should shift the character if
1385 (EVENT.state & x_shift_lock_mask) != 0. */
1386 static int x_meta_mod_mask
, x_shift_lock_mask
;
1388 /* Initialize mode_switch_bit and modifier_meaning. */
1390 x_find_modifier_meanings ()
1392 int min_code
, max_code
;
1395 XModifierKeymap
*mods
;
1396 int alt_mod_mask
= 0;
1398 x_meta_mod_mask
= 0;
1399 x_shift_lock_mask
= 0;
1401 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1402 syms
= XGetKeyboardMapping (x_current_display
,
1403 min_code
, max_code
- min_code
+ 1,
1405 mods
= XGetModifierMapping (x_current_display
);
1407 /* Scan the modifier table to see which modifier bits the Meta and
1408 Alt keysyms are on. */
1410 int row
, col
; /* The row and column in the modifier table. */
1412 for (row
= 3; row
< 8; row
++)
1413 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1416 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1418 /* Are any of this keycode's keysyms a meta key? */
1422 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1424 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1430 x_meta_mod_mask
|= (1 << row
);
1435 alt_mod_mask
|= (1 << row
);
1439 /* Ignore this if it's not on the lock modifier. */
1440 if ((1 << row
) == LockMask
)
1441 x_shift_lock_mask
= LockMask
;
1449 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1450 if (! x_meta_mod_mask
)
1451 x_meta_mod_mask
= alt_mod_mask
;
1453 XFree ((char *) syms
);
1454 XFreeModifiermap (mods
);
1458 /* Convert a set of X modifier bits to the proper form for a
1459 struct input_event modifiers value. */
1462 x_convert_modifiers (state
)
1465 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1466 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1467 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0));
1470 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1472 If the event is a button press, then note that we have grabbed
1476 construct_mouse_click (result
, event
, f
)
1477 struct input_event
*result
;
1478 XButtonEvent
*event
;
1481 /* Make the event type no_event; we'll change that when we decide
1483 result
->kind
= mouse_click
;
1484 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1485 result
->timestamp
= event
->time
;
1486 result
->modifiers
= (x_convert_modifiers (event
->state
)
1487 | (event
->type
== ButtonRelease
1491 /* Notice if the mouse is still grabbed. */
1492 if (event
->type
== ButtonPress
)
1494 if (! x_mouse_grabbed
)
1495 Vmouse_depressed
= Qt
;
1496 x_mouse_grabbed
|= (1 << event
->button
);
1498 else if (event
->type
== ButtonRelease
)
1500 x_mouse_grabbed
&= ~(1 << event
->button
);
1501 if (!x_mouse_grabbed
)
1502 Vmouse_depressed
= Qnil
;
1508 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1509 XFASTINT (result
->x
) = column
;
1510 XFASTINT (result
->y
) = row
;
1511 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1516 /* Mouse movement. Rah.
1518 In order to avoid asking for motion events and then throwing most
1519 of them away or busy-polling the server for mouse positions, we ask
1520 the server for pointer motion hints. This means that we get only
1521 one event per group of mouse movements. "Groups" are delimited by
1522 other kinds of events (focus changes and button clicks, for
1523 example), or by XQueryPointer calls; when one of these happens, we
1524 get another MotionNotify event the next time the mouse moves. This
1525 is at least as efficient as getting motion events when mouse
1526 tracking is on, and I suspect only negligibly worse when tracking
1529 The silly O'Reilly & Associates Nutshell guides barely document
1530 pointer motion hints at all (I think you have to infer how they
1531 work from an example), and the description of XQueryPointer doesn't
1532 mention that calling it causes you to get another motion hint from
1533 the server, which is very important. */
1535 /* Where the mouse was last time we reported a mouse event. */
1536 static FRAME_PTR last_mouse_frame
;
1537 static XRectangle last_mouse_glyph
;
1539 /* The scroll bar in which the last X motion event occurred.
1541 If the last X motion event occured in a scroll bar, we set this
1542 so XTmouse_position can know whether to report a scroll bar motion or
1545 If the last X motion event didn't occur in a scroll bar, we set this
1546 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1547 static Lisp_Object last_mouse_scroll_bar
;
1549 /* This is a hack. We would really prefer that XTmouse_position would
1550 return the time associated with the position it returns, but there
1551 doesn't seem to be any way to wrest the timestamp from the server
1552 along with the position query. So, we just keep track of the time
1553 of the last movement we received, and return that in hopes that
1554 it's somewhat accurate. */
1555 static Time last_mouse_movement_time
;
1557 /* Function to report a mouse movement to the mainstream Emacs code.
1558 The input handler calls this.
1560 We have received a mouse movement event, which is given in *event.
1561 If the mouse is over a different glyph than it was last time, tell
1562 the mainstream emacs code by setting mouse_moved. If not, ask for
1563 another motion event, so we can check again the next time it moves. */
1565 note_mouse_movement (frame
, event
)
1567 XMotionEvent
*event
;
1570 last_mouse_movement_time
= event
->time
;
1572 /* Has the mouse moved off the glyph it was on at the last sighting? */
1573 if (event
->x
< last_mouse_glyph
.x
1574 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1575 || event
->y
< last_mouse_glyph
.y
1576 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1579 last_mouse_scroll_bar
= Qnil
;
1583 /* It's on the same glyph. Call XQueryPointer so we'll get an
1584 event the next time the mouse moves and we can see if it's
1585 *still* on the same glyph. */
1588 XQueryPointer (event
->display
, event
->window
,
1589 (Window
*) &dummy
, (Window
*) &dummy
,
1590 &dummy
, &dummy
, &dummy
, &dummy
,
1591 (unsigned int *) &dummy
);
1595 static struct scroll_bar
*x_window_to_scroll_bar ();
1596 static void x_scroll_bar_report_motion ();
1598 /* Return the current position of the mouse.
1600 If the mouse movement started in a scroll bar, set *f, *bar_window,
1601 and *part to the frame, window, and scroll bar part that the mouse
1602 is over. Set *x and *y to the portion and whole of the mouse's
1603 position on the scroll bar.
1605 If the mouse movement started elsewhere, set *f to the frame the
1606 mouse is on, *bar_window to nil, and *x and *y to the character cell
1609 Set *time to the server timestamp for the time at which the mouse
1610 was at this position.
1612 This clears the mouse_moved flag, so we can wait for the next mouse
1613 movement. This also calls XQueryPointer, which will cause the
1614 server to give us another MotionNotify when the mouse moves
1618 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1620 Lisp_Object
*bar_window
;
1621 enum scroll_bar_part
*part
;
1623 unsigned long *time
;
1627 if (! NILP (last_mouse_scroll_bar
))
1628 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1634 Window dummy_window
;
1638 last_mouse_scroll_bar
= Qnil
;
1640 /* Figure out which root window we're on. */
1641 XQueryPointer (x_current_display
,
1642 DefaultRootWindow (x_current_display
),
1644 /* The root window which contains the pointer. */
1647 /* Trash which we can't trust if the pointer is on
1648 a different screen. */
1651 /* The position on that root window. */
1654 /* More trash we can't trust. */
1657 /* Modifier keys and pointer buttons, about which
1659 (unsigned int *) &dummy
);
1661 /* Now we have a position on the root; find the innermost window
1662 containing the pointer. */
1666 int parent_x
, parent_y
;
1671 XTranslateCoordinates (x_current_display
,
1673 /* From-window, to-window. */
1676 /* From-position, to-position. */
1677 root_x
, root_y
, &win_x
, &win_y
,
1690 /* Now we know that:
1691 win is the innermost window containing the pointer
1692 (XTC says it has no child containing the pointer),
1693 win_x and win_y are the pointer's position in it
1694 (XTC did this the last time through), and
1695 parent_x and parent_y are the pointer's position in win's parent.
1696 (They are what win_x and win_y were when win was child.
1697 If win is the root window, it has no parent, and
1698 parent_{x,y} are invalid, but that's okay, because we'll
1699 never use them in that case.) */
1701 /* Is win one of our frames? */
1702 *f
= x_window_to_frame (win
);
1704 /* If not, is it one of our scroll bars? */
1707 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1711 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1719 pixel_to_glyph_coords (*f
, win_x
, win_y
, &win_x
, &win_y
,
1724 XSET (*x
, Lisp_Int
, win_x
);
1725 XSET (*y
, Lisp_Int
, win_y
);
1726 *time
= last_mouse_movement_time
;
1734 #else /* ! defined (HAVE_X11) */
1735 #define XEvent XKeyPressedEvent
1736 #endif /* ! defined (HAVE_X11) */
1738 /* Scroll bar support. */
1740 /* Given an X window ID, find the struct scroll_bar which manages it.
1741 This can be called in GC, so we have to make sure to strip off mark
1743 static struct scroll_bar
*
1744 x_window_to_scroll_bar (window_id
)
1747 Lisp_Object tail
, frame
;
1749 for (tail
= Vframe_list
;
1750 XGCTYPE (tail
) == Lisp_Cons
;
1751 tail
= XCONS (tail
)->cdr
)
1753 Lisp_Object frame
= XCONS (tail
)->car
;
1754 Lisp_Object bar
, condemned
;
1756 /* All elements of Vframe_list should be frames. */
1757 if (XGCTYPE (frame
) != Lisp_Frame
)
1760 /* Scan this frame's scroll bar list for a scroll bar with the
1762 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1763 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1764 /* This trick allows us to search both the ordinary and
1765 condemned scroll bar lists with one loop. */
1766 ! GC_NILP (bar
) || (bar
= condemned
,
1769 bar
= XSCROLL_BAR(bar
)->next
)
1770 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1771 return XSCROLL_BAR (bar
);
1777 /* Open a new X window to serve as a scroll bar, and return the
1778 scroll bar vector for it. */
1779 static struct scroll_bar
*
1780 x_scroll_bar_create (window
, top
, left
, width
, height
)
1781 struct window
*window
;
1782 int top
, left
, width
, height
;
1784 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1785 struct scroll_bar
*bar
=
1786 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1791 XSetWindowAttributes a
;
1794 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1795 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1796 | ButtonMotionMask
| PointerMotionHintMask
1798 a
.cursor
= x_vertical_scroll_bar_cursor
;
1800 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1802 SET_SCROLL_BAR_X_WINDOW
1804 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1806 /* Position and size of scroll bar. */
1807 left
, top
, width
, height
,
1809 /* Border width, depth, class, and visual. */
1810 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1816 XSET (bar
->window
, Lisp_Window
, window
);
1817 XSET (bar
->top
, Lisp_Int
, top
);
1818 XSET (bar
->left
, Lisp_Int
, left
);
1819 XSET (bar
->width
, Lisp_Int
, width
);
1820 XSET (bar
->height
, Lisp_Int
, height
);
1821 XSET (bar
->start
, Lisp_Int
, 0);
1822 XSET (bar
->end
, Lisp_Int
, 0);
1823 bar
->dragging
= Qnil
;
1825 /* Add bar to its frame's list of scroll bars. */
1826 bar
->next
= FRAME_SCROLL_BARS (frame
);
1828 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
1829 if (! NILP (bar
->next
))
1830 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1832 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
1839 /* Draw BAR's handle in the proper position.
1840 If the handle is already drawn from START to END, don't bother
1841 redrawing it, unless REBUILD is non-zero; in that case, always
1842 redraw it. (REBUILD is handy for drawing the handle after expose
1845 Normally, we want to constrain the start and end of the handle to
1846 fit inside its rectangle, but if the user is dragging the scroll bar
1847 handle, we want to let them drag it down all the way, so that the
1848 bar's top is as far down as it goes; otherwise, there's no way to
1849 move to the very end of the buffer. */
1851 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1852 struct scroll_bar
*bar
;
1856 int dragging
= ! NILP (bar
->dragging
);
1857 Window w
= SCROLL_BAR_X_WINDOW (bar
);
1858 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1860 /* If the display is already accurate, do nothing. */
1862 && start
== XINT (bar
->start
)
1863 && end
== XINT (bar
->end
))
1869 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
1870 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
1871 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
1873 /* Make sure the values are reasonable, and try to preserve
1874 the distance between start and end. */
1876 int length
= end
- start
;
1880 else if (start
> top_range
)
1882 end
= start
+ length
;
1886 else if (end
> top_range
&& ! dragging
)
1890 /* Store the adjusted setting in the scroll bar. */
1891 XSET (bar
->start
, Lisp_Int
, start
);
1892 XSET (bar
->end
, Lisp_Int
, end
);
1894 /* Clip the end position, just for display. */
1895 if (end
> top_range
)
1898 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1899 below top positions, to make sure the handle is always at least
1900 that many pixels tall. */
1901 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
1903 /* Draw the empty space above the handle. Note that we can't clear
1904 zero-height areas; that means "clear to end of window." */
1906 XClearArea (x_current_display
, w
,
1908 /* x, y, width, height, and exposures. */
1909 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1910 VERTICAL_SCROLL_BAR_TOP_BORDER
,
1911 inside_width
, start
,
1914 /* Draw the handle itself. */
1915 XFillRectangle (x_current_display
, w
, gc
,
1917 /* x, y, width, height */
1918 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1919 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
1920 inside_width
, end
- start
);
1923 /* Draw the empty space below the handle. Note that we can't
1924 clear zero-height areas; that means "clear to end of window." */
1925 if (end
< inside_height
)
1926 XClearArea (x_current_display
, w
,
1928 /* x, y, width, height, and exposures. */
1929 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1930 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
1931 inside_width
, inside_height
- end
,
1939 /* Move a scroll bar around on the screen, to accomodate changing
1940 window configurations. */
1942 x_scroll_bar_move (bar
, top
, left
, width
, height
)
1943 struct scroll_bar
*bar
;
1944 int top
, left
, width
, height
;
1950 unsigned int mask
= 0;
1957 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
1958 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
1959 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
1960 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
1963 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
1967 XSET (bar
->left
, Lisp_Int
, left
);
1968 XSET (bar
->top
, Lisp_Int
, top
);
1969 XSET (bar
->width
, Lisp_Int
, width
);
1970 XSET (bar
->height
, Lisp_Int
, height
);
1975 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
1978 x_scroll_bar_remove (bar
)
1979 struct scroll_bar
*bar
;
1981 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1985 /* Destroy the window. */
1986 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
1988 /* Disassociate this scroll bar from its window. */
1989 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
1994 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1995 that we are displaying PORTION characters out of a total of WHOLE
1996 characters, starting at POSITION. If WINDOW has no scroll bar,
1999 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2000 struct window
*window
;
2001 int portion
, whole
, position
;
2003 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2004 int top
= XINT (window
->top
);
2005 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2006 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2008 /* Where should this scroll bar be, pixelwise? */
2009 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2010 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2011 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2012 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2014 struct scroll_bar
*bar
;
2016 /* Does the scroll bar exist yet? */
2017 if (NILP (window
->vertical_scroll_bar
))
2018 bar
= x_scroll_bar_create (window
,
2019 pixel_top
, pixel_left
,
2020 pixel_width
, pixel_height
);
2023 /* It may just need to be moved and resized. */
2024 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2025 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2028 /* Set the scroll bar's current state, unless we're currently being
2030 if (NILP (bar
->dragging
))
2033 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2036 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2039 int start
= (position
* top_range
) / whole
;
2040 int end
= ((position
+ portion
) * top_range
) / whole
;
2042 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2046 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2050 /* The following three hooks are used when we're doing a thorough
2051 redisplay of the frame. We don't explicitly know which scroll bars
2052 are going to be deleted, because keeping track of when windows go
2053 away is a real pain - "Can you say set-window-configuration, boys
2054 and girls?" Instead, we just assert at the beginning of redisplay
2055 that *all* scroll bars are to be removed, and then save a scroll bar
2056 from the fiery pit when we actually redisplay its window. */
2058 /* Arrange for all scroll bars on FRAME to be removed at the next call
2059 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2060 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2062 XTcondemn_scroll_bars (frame
)
2065 /* The condemned list should be empty at this point; if it's not,
2066 then the rest of Emacs isn't using the condemn/redeem/judge
2067 protocol correctly. */
2068 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2071 /* Move them all to the "condemned" list. */
2072 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2073 FRAME_SCROLL_BARS (frame
) = Qnil
;
2076 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2077 Note that WINDOW isn't necessarily condemned at all. */
2079 XTredeem_scroll_bar (window
)
2080 struct window
*window
;
2082 struct scroll_bar
*bar
;
2084 /* We can't redeem this window's scroll bar if it doesn't have one. */
2085 if (NILP (window
->vertical_scroll_bar
))
2088 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2090 /* Unlink it from the condemned list. */
2092 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2094 if (NILP (bar
->prev
))
2096 /* If the prev pointer is nil, it must be the first in one of
2098 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2099 /* It's not condemned. Everything's fine. */
2101 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2102 window
->vertical_scroll_bar
))
2103 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2105 /* If its prev pointer is nil, it must be at the front of
2106 one or the other! */
2110 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2112 if (! NILP (bar
->next
))
2113 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2115 bar
->next
= FRAME_SCROLL_BARS (f
);
2117 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2118 if (! NILP (bar
->next
))
2119 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2123 /* Remove all scroll bars on FRAME that haven't been saved since the
2124 last call to `*condemn_scroll_bars_hook'. */
2126 XTjudge_scroll_bars (f
)
2129 Lisp_Object bar
, next
;
2131 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2133 /* Clear out the condemned list now so we won't try to process any
2134 more events on the hapless scroll bars. */
2135 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2137 for (; ! NILP (bar
); bar
= next
)
2139 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2141 x_scroll_bar_remove (b
);
2144 b
->next
= b
->prev
= Qnil
;
2147 /* Now there should be no references to the condemned scroll bars,
2148 and they should get garbage-collected. */
2152 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2154 This may be called from a signal handler, so we have to ignore GC
2157 x_scroll_bar_expose (bar
, event
)
2158 struct scroll_bar
*bar
;
2161 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2162 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2166 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2168 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2169 XDrawRectangle (x_current_display
, w
, gc
,
2171 /* x, y, width, height */
2172 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2174 /* Draw another line to make the extra-thick border on the right. */
2175 XFillRectangle (x_current_display
, w
, gc
,
2177 /* x, y, width, height */
2178 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2183 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2184 is set to something other than no_event, it is enqueued.
2186 This may be called from a signal handler, so we have to ignore GC
2189 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2190 struct scroll_bar
*bar
;
2192 struct input_event
*emacs_event
;
2194 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2197 emacs_event
->kind
= scroll_bar_click
;
2198 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2199 emacs_event
->modifiers
=
2200 (x_convert_modifiers (event
->xbutton
.state
)
2201 | (event
->type
== ButtonRelease
2204 emacs_event
->frame_or_window
= bar
->window
;
2205 emacs_event
->timestamp
= event
->xbutton
.time
;
2207 int internal_height
=
2208 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2210 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2211 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2214 if (y
> top_range
) y
= top_range
;
2216 if (y
< XINT (bar
->start
))
2217 emacs_event
->part
= scroll_bar_above_handle
;
2218 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2219 emacs_event
->part
= scroll_bar_handle
;
2221 emacs_event
->part
= scroll_bar_below_handle
;
2223 /* If the user has just clicked on the handle, record where they're
2225 if (event
->type
== ButtonPress
2226 && emacs_event
->part
== scroll_bar_handle
)
2227 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2229 /* If the user has released the handle, set it to its final position. */
2230 if (event
->type
== ButtonRelease
2231 && ! NILP (bar
->dragging
))
2233 int new_start
= y
- XINT (bar
->dragging
);
2234 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2236 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2237 bar
->dragging
= Qnil
;
2240 /* Clicks on the handle are always reported as occuring at the top of
2242 if (emacs_event
->part
== scroll_bar_handle
)
2243 emacs_event
->x
= bar
->start
;
2245 XSET (emacs_event
->x
, Lisp_Int
, y
);
2247 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2251 /* Handle some mouse motion while someone is dragging the scroll bar.
2253 This may be called from a signal handler, so we have to ignore GC
2256 x_scroll_bar_note_movement (bar
, event
)
2257 struct scroll_bar
*bar
;
2260 last_mouse_movement_time
= event
->xmotion
.time
;
2263 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2265 /* If we're dragging the bar, display it. */
2266 if (! GC_NILP (bar
->dragging
))
2268 /* Where should the handle be now? */
2269 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2271 if (new_start
!= XINT (bar
->start
))
2273 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2275 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2279 /* Call XQueryPointer so we'll get an event the next time the mouse
2280 moves and we can see *still* on the same position. */
2284 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2285 (Window
*) &dummy
, (Window
*) &dummy
,
2286 &dummy
, &dummy
, &dummy
, &dummy
,
2287 (unsigned int *) &dummy
);
2291 /* Return information to the user about the current position of the mouse
2292 on the scroll bar. */
2294 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2296 Lisp_Object
*bar_window
;
2297 enum scroll_bar_part
*part
;
2299 unsigned long *time
;
2301 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2306 /* Get the mouse's position relative to the scroll bar window, and
2309 Window dummy_window
;
2311 unsigned int dummy_mask
;
2313 if (! XQueryPointer (x_current_display
,
2314 SCROLL_BAR_X_WINDOW (bar
),
2316 /* Root, child, root x and root y. */
2317 &dummy_window
, &dummy_window
,
2318 &dummy_coord
, &dummy_coord
,
2320 /* Position relative to scroll bar. */
2323 /* Mouse buttons and modifier keys. */
2332 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2333 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2335 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2337 if (! NILP (bar
->dragging
))
2338 win_y
-= XINT (bar
->dragging
);
2342 if (win_y
> top_range
)
2345 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2346 *bar_window
= bar
->window
;
2348 if (! NILP (bar
->dragging
))
2349 *part
= scroll_bar_handle
;
2350 else if (win_y
< XINT (bar
->start
))
2351 *part
= scroll_bar_above_handle
;
2352 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2353 *part
= scroll_bar_handle
;
2355 *part
= scroll_bar_below_handle
;
2357 XSET (*x
, Lisp_Int
, win_y
);
2358 XSET (*y
, Lisp_Int
, top_range
);
2359 *time
= last_mouse_movement_time
;
2363 last_mouse_scroll_bar
= Qnil
;
2370 /* The screen has been cleared so we may have changed foreground or
2371 background colors, and the scroll bars may need to be redrawn.
2372 Clear out the scroll bars, and ask for expose events, so we can
2375 x_scroll_bar_clear (f
)
2380 for (bar
= FRAME_SCROLL_BARS (f
);
2381 XTYPE (bar
) == Lisp_Vector
;
2382 bar
= XSCROLL_BAR (bar
)->next
)
2383 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2389 /* The main X event-reading loop - XTread_socket. */
2391 /* Timestamp of enter window event. This is only used by XTread_socket,
2392 but we have to put it out here, since static variables within functions
2393 sometimes don't work. */
2394 static Time enter_timestamp
;
2396 /* This holds the state XLookupString needs to implement dead keys
2397 and other tricks known as "compose processing". _X Window System_
2398 says that a portable program can't use this, but Stephen Gildea assures
2399 me that letting the compiler initialize it to zeros will work okay.
2401 This must be defined outside of XTread_socket, for the same reasons
2402 given for enter_timestamp, above. */
2403 static XComposeStatus compose_status
;
2405 /* Communication with window managers. */
2406 Atom Xatom_wm_protocols
;
2408 /* Kinds of protocol things we may receive. */
2409 Atom Xatom_wm_take_focus
;
2410 Atom Xatom_wm_save_yourself
;
2411 Atom Xatom_wm_delete_window
;
2413 /* Other WM communication */
2414 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2415 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2417 /* Read events coming from the X server.
2418 This routine is called by the SIGIO handler.
2419 We return as soon as there are no more events to be read.
2421 Events representing keys are stored in buffer BUFP,
2422 which can hold up to NUMCHARS characters.
2423 We return the number of characters stored into the buffer,
2424 thus pretending to be `read'.
2426 WAITP is nonzero if we should block until input arrives.
2427 EXPECTED is nonzero if the caller knows input is available. */
2430 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2432 register struct input_event
*bufp
;
2433 register int numchars
;
2440 int items_pending
; /* How many items are in the X queue. */
2447 if (x_input_blocked
)
2449 x_pending_input
= 1;
2453 x_pending_input
= 0;
2457 abort (); /* Don't think this happens. */
2460 /* If available, Xlib uses FIOSNBIO to make the socket
2461 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2462 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2463 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2464 fcntl (fileno (stdin
), F_SETFL
, 0);
2465 #endif /* ! defined (FIOSNBIO) */
2469 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2471 extern int read_alarm_should_throw
;
2472 read_alarm_should_throw
= 1;
2473 XPeekEvent (XDISPLAY
&event
);
2474 read_alarm_should_throw
= 0;
2476 #endif /* HAVE_SELECT */
2479 while (XStuffPending () != 0)
2481 XNextEvent (XDISPLAY
&event
);
2489 if (event
.xclient
.message_type
== Xatom_wm_protocols
2490 && event
.xclient
.format
== 32)
2492 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2494 f
= x_window_to_frame (event
.xclient
.window
);
2496 x_focus_on_frame (f
);
2497 /* Not certain about handling scroll bars here */
2499 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2501 /* Save state modify the WM_COMMAND property to
2502 something which can reinstate us. This notifies
2503 the session manager, who's looking for such a
2504 PropertyNotify. Can restart processing when
2505 a keyboard or mouse event arrives. */
2510 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2512 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2520 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2523 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2527 new_x
= event
.xclient
.data
.s
[0];
2528 new_y
= event
.xclient
.data
.s
[1];
2533 case SelectionClear
: /* Someone has grabbed ownership. */
2534 x_disown_selection (event
.xselectionclear
.window
,
2535 event
.xselectionclear
.selection
,
2536 event
.xselectionclear
.time
);
2539 case SelectionRequest
: /* Someone wants our selection. */
2540 x_answer_selection_request (event
);
2543 case PropertyNotify
:
2545 /* If we're being told about a root window property, then it's
2546 a cut buffer change. */
2547 if (event
.xproperty
.window
== ROOT_WINDOW
)
2548 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2550 /* Otherwise, we're probably handling an incremental
2551 selection transmission. */
2554 /* If we were to do this synchronously, there'd be no worry
2555 about re-selecting. */
2556 x_send_incremental (event
);
2561 f
= x_window_to_frame (event
.xexpose
.window
);
2564 if (f
->async_visible
== 0)
2566 f
->async_visible
= 1;
2567 f
->async_iconified
= 0;
2568 SET_FRAME_GARBAGED (f
);
2572 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2573 event
.xexpose
.x
, event
.xexpose
.y
,
2574 event
.xexpose
.width
, event
.xexpose
.height
);
2579 struct scroll_bar
*bar
2580 = x_window_to_scroll_bar (event
.xexpose
.window
);
2583 x_scroll_bar_expose (bar
, &event
);
2587 case GraphicsExpose
: /* This occurs when an XCopyArea's
2588 source area was obscured or not
2590 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2594 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2595 event
.xgraphicsexpose
.width
,
2596 event
.xgraphicsexpose
.height
);
2600 case NoExpose
: /* This occurs when an XCopyArea's
2601 source area was completely
2604 #else /* ! defined (HAVE_X11) */
2606 if (event
.subwindow
!= 0)
2607 break; /* duplicate event */
2608 f
= x_window_to_frame (event
.window
);
2609 if (event
.window
== f
->display
.x
->icon_desc
)
2612 f
->async_iconified
= 1;
2614 if (event
.window
== FRAME_X_WINDOW (f
))
2616 /* Say must check all windows' needs_exposure flags. */
2617 expose_all_windows
= 1;
2618 f
->display
.x
->needs_exposure
= 1;
2619 f
->async_visible
= 1;
2624 if (event
.subwindow
!= 0)
2625 break; /* duplicate event */
2626 f
= x_window_to_frame (event
.window
);
2627 if (event
.window
== f
->display
.x
->icon_desc
)
2632 /* If window already needs full redraw, ignore this rectangle. */
2633 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2635 /* Put the event on the queue of rectangles to redraw. */
2636 if (enqueue_event (&event
, &x_expose_queue
))
2637 /* If it is full, we can't record the rectangle,
2638 so redraw this entire window. */
2640 /* Say must check all windows' needs_exposure flags. */
2641 expose_all_windows
= 1;
2642 f
->display
.x
->needs_exposure
= 1;
2647 /* This should happen only when we are expecting it,
2648 in x_read_exposes. */
2650 #endif /* ! defined (HAVE_X11) */
2654 f
= x_window_to_frame (event
.xunmap
.window
);
2655 if (f
) /* F may no longer exist if
2656 the frame was deleted. */
2658 /* While a frame is unmapped, display generation is
2659 disabled; you don't want to spend time updating a
2660 display that won't ever be seen. */
2661 f
->async_visible
= 0;
2666 f
= x_window_to_frame (event
.xmap
.window
);
2669 f
->async_visible
= 1;
2670 f
->async_iconified
= 0;
2672 /* wait_reading_process_input will notice this and update
2673 the frame's display structures. */
2674 SET_FRAME_GARBAGED (f
);
2678 /* Turn off processing if we become fully obscured. */
2679 case VisibilityNotify
:
2682 #else /* ! defined (HAVE_X11) */
2684 f
= x_window_to_frame (event
.window
);
2685 if (event
.window
== f
->display
.x
->icon_desc
)
2686 f
->async_iconified
= 0;
2687 if (event
.window
== FRAME_X_WINDOW (f
))
2688 f
->async_visible
= 0;
2690 #endif /* ! defined (HAVE_X11) */
2694 f
= x_window_to_frame (event
.xkey
.window
);
2699 char copy_buffer
[80];
2702 event
.xkey
.state
|= extra_keyboard_modifiers
;
2703 modifiers
= event
.xkey
.state
;
2705 /* Some keyboards generate different characters
2706 depending on the state of the meta key, in an attempt
2707 to support non-English typists. It would be nice to
2708 keep this functionality somehow, but for now, we will
2709 just clear the meta-key flag to get the 'pure' character. */
2710 event
.xkey
.state
&= ~Mod1Mask
;
2712 /* This will have to go some day... */
2714 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2717 /* Strip off the vendor-specific keysym bit, and take a shot
2718 at recognizing the codes. HP servers have extra keysyms
2719 that fit into the MiscFunctionKey category. */
2724 if (IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2725 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < 0xff80 */
2726 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2727 || IsFunctionKey (keysym
)) /* 0xffbe <= x < 0xffe1 */
2729 bufp
->kind
= non_ascii_keystroke
;
2730 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff50);
2731 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2732 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2733 bufp
->timestamp
= event
.xkey
.time
;
2738 else if (numchars
> nbytes
)
2744 bufp
->kind
= ascii_keystroke
;
2745 XSET (bufp
->code
, Lisp_Int
, *copy_buffer
);
2746 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2747 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2748 bufp
->timestamp
= event
.xkey
.time
;
2752 for (i
= nbytes
- 1; i
> 1; i
--)
2754 bufp
->kind
= ascii_keystroke
;
2755 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2756 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2757 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2758 bufp
->timestamp
= event
.xkey
.time
;
2768 #else /* ! defined (HAVE_X11) */
2771 register char *where_mapping
;
2773 f
= x_window_to_frame (event
.window
);
2774 /* Ignore keys typed on icon windows. */
2775 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2777 where_mapping
= XLookupMapping (&event
, &nbytes
);
2778 /* Nasty fix for arrow keys */
2779 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2781 switch (event
.detail
& 0xff)
2783 case KC_CURSOR_LEFT
:
2784 where_mapping
= "\002";
2786 case KC_CURSOR_RIGHT
:
2787 where_mapping
= "\006";
2790 where_mapping
= "\020";
2792 case KC_CURSOR_DOWN
:
2793 where_mapping
= "\016";
2798 if (numchars
- nbytes
> 0)
2802 for (i
= 0; i
< nbytes
; i
++)
2804 bufp
->kind
= ascii_keystroke
;
2805 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2806 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2807 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2815 #endif /* ! defined (HAVE_X11) */
2819 /* Here's a possible interpretation of the whole
2820 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2821 FocusIn event, you have to get a FocusOut event before you
2822 relinquish the focus. If you haven't received a FocusIn event,
2823 then a mere LeaveNotify is enough to free you. */
2826 f
= x_window_to_frame (event
.xcrossing
.window
);
2828 if (event
.xcrossing
.focus
) /* Entered Window */
2830 /* Avoid nasty pop/raise loops. */
2831 if (f
&& (!(f
->auto_raise
)
2833 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
2835 x_new_focus_frame (f
);
2836 enter_timestamp
= event
.xcrossing
.time
;
2839 else if (f
== x_focus_frame
)
2840 x_new_focus_frame (0);
2845 f
= x_window_to_frame (event
.xfocus
.window
);
2846 if (event
.xfocus
.detail
!= NotifyPointer
)
2847 x_focus_event_frame
= f
;
2849 x_new_focus_frame (f
);
2854 f
= x_window_to_frame (event
.xcrossing
.window
);
2856 if (event
.xcrossing
.focus
)
2858 if (! x_focus_event_frame
)
2859 x_new_focus_frame (0);
2861 x_new_focus_frame (f
);
2865 if (f
== x_focus_event_frame
)
2866 x_focus_event_frame
= 0;
2867 if (f
== x_focus_frame
)
2868 x_new_focus_frame (0);
2873 f
= x_window_to_frame (event
.xfocus
.window
);
2874 if (event
.xfocus
.detail
!= NotifyPointer
2875 && f
== x_focus_event_frame
)
2876 x_focus_event_frame
= 0;
2877 if (f
&& f
== x_focus_frame
)
2878 x_new_focus_frame (0);
2881 #else /* ! defined (HAVE_X11) */
2884 if ((event
.detail
& 0xFF) == 1)
2885 break; /* Coming from our own subwindow */
2886 if (event
.subwindow
!= 0)
2887 break; /* Entering our own subwindow. */
2890 f
= x_window_to_frame (event
.window
);
2893 x_new_focus_frame (f
);
2898 if ((event
.detail
& 0xFF) == 1)
2899 break; /* Entering our own subwindow */
2900 if (event
.subwindow
!= 0)
2901 break; /* Leaving our own subwindow. */
2904 if (x_focus_frame
== 0
2905 && x_input_frame
!= 0
2906 && x_input_frame
== x_window_to_frame (event
.window
)
2907 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
2912 frame_unhighlight (f
);
2915 #endif /* ! defined (HAVE_X11) */
2920 f
= x_window_to_frame (event
.xmotion
.window
);
2922 note_mouse_movement (f
, &event
.xmotion
);
2925 struct scroll_bar
*bar
=
2926 x_window_to_scroll_bar (event
.xmotion
.window
);
2929 x_scroll_bar_note_movement (bar
, &event
);
2934 case ConfigureNotify
:
2935 f
= x_window_to_frame (event
.xconfigure
.window
);
2938 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
2939 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
2941 /* Even if the number of character rows and columns has
2942 not changed, the font size may have changed, so we need
2943 to check the pixel dimensions as well. */
2944 if (columns
!= f
->width
2945 || rows
!= f
->height
2946 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
2947 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
2949 change_frame_size (f
, rows
, columns
, 0, 1);
2950 SET_FRAME_GARBAGED (f
);
2953 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
2954 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
2955 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
2956 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
2963 /* If we decide we want to generate an event to be seen
2964 by the rest of Emacs, we put it here. */
2965 struct input_event emacs_event
;
2966 emacs_event
.kind
= no_event
;
2968 f
= x_window_to_frame (event
.xbutton
.window
);
2971 if (!x_focus_frame
|| (f
== x_focus_frame
))
2972 construct_mouse_click (&emacs_event
,
2977 struct scroll_bar
*bar
=
2978 x_window_to_scroll_bar (event
.xbutton
.window
);
2981 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
2984 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
2986 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
2994 #else /* ! defined (HAVE_X11) */
2996 case ButtonReleased
:
2997 f
= x_window_to_frame (event
.window
);
3000 if (event
.window
== f
->display
.x
->icon_desc
)
3002 x_make_frame_visible (f
);
3004 if (warp_mouse_on_deiconify
)
3005 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3008 if (event
.window
== FRAME_X_WINDOW (f
))
3014 enqueue_event (&event
, &x_mouse_queue
);
3017 bufp
->kind
= ascii_keystroke
;
3018 bufp
->code
= (char) 'X' & 037; /* C-x */
3019 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3020 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3023 bufp
->kind
= ascii_keystroke
;
3024 bufp
->code
= (char) 0; /* C-@ */
3025 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3026 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3033 #endif /* ! defined (HAVE_X11) */
3037 case CirculateNotify
:
3039 case CirculateRequest
:
3042 #endif /* ! defined (HAVE_X11) */
3045 /* Someone has changed the keyboard mapping - update the
3047 switch (event
.xmapping
.request
)
3049 case MappingModifier
:
3050 x_find_modifier_meanings ();
3051 /* This is meant to fall through. */
3052 case MappingKeyboard
:
3053 XRefreshKeyboardMapping (&event
.xmapping
);
3064 if (expected
&& ! event_found
)
3066 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3067 there is an EOF condition; in other words, that X has died.
3068 Act as if there had been a hangup. */
3070 int fd
= ConnectionNumber (x_current_display
);
3073 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3075 && !XStuffPending ())
3076 kill (getpid (), SIGHUP
);
3078 #endif /* ! defined (HAVE_SELECT) */
3082 if (updating_frame
== 0)
3083 x_do_pending_expose ();
3091 /* Read and process only Expose events
3092 until we get an ExposeCopy event; then return.
3093 This is used in insert/delete line.
3094 We assume input is already blocked. */
3100 XKeyPressedEvent event
;
3104 /* while there are more events*/
3105 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3109 if (event
.subwindow
!= 0)
3110 break; /* duplicate event */
3111 f
= x_window_to_frame (event
.window
);
3112 if (event
.window
== f
->display
.x
->icon_desc
)
3117 if (event
.window
== FRAME_X_WINDOW (f
))
3119 expose_all_windows
= 1;
3120 f
->display
.x
->needs_exposure
= 1;
3126 if (event
.subwindow
!= 0)
3127 break; /* duplicate event */
3128 f
= x_window_to_frame (event
.window
);
3129 if (event
.window
== f
->display
.x
->icon_desc
)
3134 /* If window already needs full redraw, ignore this rectangle. */
3135 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3137 /* Put the event on the queue of rectangles to redraw. */
3138 if (enqueue_event (&event
, &x_expose_queue
))
3139 /* If it is full, we can't record the rectangle,
3140 so redraw this entire window. */
3142 /* Say must check all windows' needs_exposure flags. */
3143 expose_all_windows
= 1;
3144 f
->display
.x
->needs_exposure
= 1;
3153 #endif /* HAVE_X11 */
3156 /* Drawing the cursor. */
3159 /* Draw a hollow box cursor. Don't change the inside of the box. */
3165 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3166 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3167 int width
= FONT_WIDTH (f
->display
.x
->font
);
3168 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3171 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3172 f
->display
.x
->cursor_gc
,
3173 left
, top
, width
- 1, height
- 1);
3174 #else /* ! defined (HAVE_X11) */
3175 XPixSet (FRAME_X_WINDOW (f
),
3176 left
, top
, width
, 1,
3177 f
->display
.x
->cursor_pixel
);
3179 XPixSet (FRAME_X_WINDOW (f
),
3180 left
, top
, 1, height
,
3181 f
->display
.x
->cursor_pixel
);
3183 XPixSet (FRAME_X_WINDOW (f
),
3184 left
+width
-1, top
, 1, height
,
3185 f
->display
.x
->cursor_pixel
);
3187 XPixSet (FRAME_X_WINDOW (f
),
3188 left
, top
+height
-1, width
, 1,
3189 f
->display
.x
->cursor_pixel
);
3190 #endif /* ! defined (HAVE_X11) */
3193 /* Clear the cursor of frame F to background color,
3194 and mark the cursor as not shown.
3195 This is used when the text where the cursor is
3196 is about to be rewritten. */
3204 if (! FRAME_VISIBLE_P (f
)
3205 || f
->phys_cursor_x
< 0)
3209 x_display_cursor (f
, 0);
3210 #else /* ! defined (HAVE_X11) */
3211 XPixSet (FRAME_X_WINDOW (f
),
3212 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3213 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3214 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3215 f
->display
.x
->background_pixel
);
3216 #endif /* ! defined (HAVE_X11) */
3217 f
->phys_cursor_x
= -1;
3220 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3221 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3225 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3232 CHAR_TO_PIXEL_COL (f
, column
),
3233 CHAR_TO_PIXEL_ROW (f
, row
),
3234 &glyph
, 1, highlight
, f
->display
.x
->font
);
3238 x_display_bar_cursor (f
, on
)
3242 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3244 if (! FRAME_VISIBLE_P (f
))
3247 if (! on
&& f
->phys_cursor_x
< 0)
3250 /* If we're not updating, then we want to use the current frame's
3251 cursor position, not our local idea of where the cursor ought to be. */
3252 if (f
!= updating_frame
)
3254 curs_x
= FRAME_CURSOR_X (f
);
3255 curs_y
= FRAME_CURSOR_Y (f
);
3258 /* If there is anything wrong with the current cursor state, remove it. */
3259 if (f
->phys_cursor_x
>= 0
3261 || f
->phys_cursor_x
!= curs_x
3262 || f
->phys_cursor_y
!= curs_y
3263 || f
->display
.x
->current_cursor
!= bar_cursor
))
3265 /* Erase the cursor by redrawing the character underneath it. */
3266 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3267 f
->phys_cursor_glyph
,
3268 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3269 f
->phys_cursor_x
= -1;
3272 /* If we now need a cursor in the new place or in the new form, do it so. */
3274 && (f
->phys_cursor_x
< 0
3275 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3277 f
->phys_cursor_glyph
3278 = ((current_glyphs
->enable
[curs_y
]
3279 && curs_x
< current_glyphs
->used
[curs_y
])
3280 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3282 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3283 f
->display
.x
->cursor_gc
,
3284 CHAR_TO_PIXEL_COL (f
, curs_x
),
3285 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3286 1, FONT_HEIGHT (f
->display
.x
->font
));
3288 f
->phys_cursor_x
= curs_x
;
3289 f
->phys_cursor_y
= curs_y
;
3291 f
->display
.x
->current_cursor
= bar_cursor
;
3294 if (updating_frame
!= f
)
3299 /* Turn the displayed cursor of frame F on or off according to ON.
3300 If ON is nonzero, where to put the cursor is specified
3301 by F->cursor_x and F->cursor_y. */
3304 x_display_box_cursor (f
, on
)
3308 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3310 if (! FRAME_VISIBLE_P (f
))
3313 /* If cursor is off and we want it off, return quickly. */
3314 if (!on
&& f
->phys_cursor_x
< 0)
3317 /* If we're not updating, then we want to use the current frame's
3318 cursor position, not our local idea of where the cursor ought to be. */
3319 if (f
!= updating_frame
)
3321 curs_x
= FRAME_CURSOR_X (f
);
3322 curs_y
= FRAME_CURSOR_Y (f
);
3325 /* If cursor is currently being shown and we don't want it to be
3326 or it is in the wrong place,
3327 or we want a hollow box and it's not so, (pout!)
3329 if (f
->phys_cursor_x
>= 0
3331 || f
->phys_cursor_x
!= curs_x
3332 || f
->phys_cursor_y
!= curs_y
3333 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3334 && (f
!= x_highlight_frame
))))
3336 /* Erase the cursor by redrawing the character underneath it. */
3337 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3338 f
->phys_cursor_glyph
,
3339 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3340 f
->phys_cursor_x
= -1;
3343 /* If we want to show a cursor,
3344 or we want a box cursor and it's not so,
3345 write it in the right place. */
3347 && (f
->phys_cursor_x
< 0
3348 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3349 && f
== x_highlight_frame
)))
3351 f
->phys_cursor_glyph
3352 = ((current_glyphs
->enable
[curs_y
]
3353 && curs_x
< current_glyphs
->used
[curs_y
])
3354 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3356 if (f
!= x_highlight_frame
)
3359 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3363 x_draw_single_glyph (f
, curs_y
, curs_x
,
3364 f
->phys_cursor_glyph
, 2);
3365 f
->display
.x
->current_cursor
= filled_box_cursor
;
3368 f
->phys_cursor_x
= curs_x
;
3369 f
->phys_cursor_y
= curs_y
;
3372 if (updating_frame
!= f
)
3376 x_display_cursor (f
, on
)
3380 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3381 x_display_box_cursor (f
, on
);
3382 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3383 x_display_bar_cursor (f
, on
);
3385 /* Those are the only two we have implemented! */
3391 /* Refresh bitmap kitchen sink icon for frame F
3392 when we get an expose event for it. */
3398 /* Normally, the window manager handles this function. */
3399 #else /* ! defined (HAVE_X11) */
3402 if (f
->display
.x
->icon_bitmap_flag
)
3403 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3404 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3405 icon_bitmap
, GXcopy
, AllPlanes
);
3408 extern struct frame
*selected_frame
;
3409 struct Lisp_String
*str
;
3410 unsigned char *string
;
3413 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3415 if (f
->display
.x
->icon_label
!= string
)
3417 f
->display
.x
->icon_label
= string
;
3418 XChangeWindow (f
->display
.x
->icon_desc
,
3419 XQueryWidth (string
, icon_font_info
->id
) + 10,
3420 icon_font_info
->height
+ 10);
3423 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3424 str
->size
, icon_font_info
->id
,
3425 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3428 #endif /* ! defined (HAVE_X11) */
3431 /* Make the x-window of frame F use the gnu icon bitmap. */
3440 if (FRAME_X_WINDOW (f
) == 0)
3445 XFreePixmap (x_current_display
, icon_bitmap
);
3448 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3449 gnu_bits
, gnu_width
, gnu_height
);
3450 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3451 f
->display
.x
->icon_bitmap_flag
= 1;
3452 #else /* ! defined (HAVE_X11) */
3453 if (f
->display
.x
->icon_desc
)
3455 XClearIconWindow (FRAME_X_WINDOW (f
));
3456 XDestroyWindow (f
->display
.x
->icon_desc
);
3459 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3460 0, 0, sink_width
, sink_height
,
3461 2, WhitePixmap
, (Pixmap
) NULL
);
3463 if (icon_window
== 0)
3466 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3467 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3469 f
->display
.x
->icon_desc
= icon_window
;
3470 f
->display
.x
->icon_bitmap_flag
= 1;
3472 if (icon_bitmap
== 0)
3474 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3475 #endif /* ! defined (HAVE_X11) */
3481 /* Make the x-window of frame F use a rectangle with text. */
3484 x_text_icon (f
, icon_name
)
3492 char *X_DefaultValue
;
3496 #define WhitePixel 1
3497 #endif /* WhitePixel */
3500 #define BlackPixel 0
3501 #endif /* BlackPixel */
3502 #endif /* HAVE_X11 */
3504 if (FRAME_X_WINDOW (f
) == 0)
3509 f
->display
.x
->icon_label
= icon_name
;
3511 if (! f
->display
.x
->icon_label
)
3512 f
->display
.x
->icon_label
= " *emacs* ";
3514 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3515 (char *) f
->display
.x
->icon_label
);
3517 f
->display
.x
->icon_bitmap_flag
= 0;
3518 x_wm_set_icon_pixmap (f
, 0);
3519 #else /* ! defined (HAVE_X11) */
3520 if (icon_font_info
== 0)
3522 = XGetFont (XGetDefault (XDISPLAY
3523 (char *) XSTRING (invocation_name
)->data
,
3526 if (f
->display
.x
->icon_desc
)
3528 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3529 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3533 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3535 if (! f
->display
.x
->icon_label
)
3536 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3538 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3539 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3540 f
->display
.x
->left_pos
,
3541 f
->display
.x
->top_pos
,
3542 width
+ 10, icon_font_info
->height
+ 10,
3543 2, BlackPixmap
, WhitePixmap
);
3545 if (icon_window
== 0)
3548 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3549 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3551 f
->display
.x
->icon_desc
= icon_window
;
3552 f
->display
.x
->icon_bitmap_flag
= 0;
3553 f
->display
.x
->icon_label
= 0;
3554 #endif /* ! defined (HAVE_X11) */
3559 /* Handling X errors. */
3561 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3562 X server's connection, or an error reported via the X protocol. */
3565 x_connection_closed ()
3570 shut_down_emacs (0);
3575 /* An X error handler which prints an error message and then kills
3576 Emacs. This is what's normally installed as Xlib's handler for
3579 x_error_quitter (display
, error
)
3585 /* Note that there is no real way portable across R3/R4 to get the
3586 original error handler. */
3588 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3589 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3590 buf
, error
->request_code
);
3592 /* While we're testing Emacs 19, we'll just dump core whenever we
3593 get an X error, so we can figure out why it happened. */
3596 x_connection_closed ();
3599 /* A handler for X IO errors which prints an error message and then
3600 kills Emacs. This is what is always installed as Xlib's handler
3603 x_io_error_quitter (display
)
3606 fprintf (stderr
, "Connection to X server %s lost.\n",
3607 XDisplayName (DisplayString (display
)));
3609 /* While we're testing Emacs 19, we'll just dump core whenever we
3610 get an X error, so we can figure out why it happened. */
3613 x_connection_closed ();
3616 /* A buffer for storing X error messages. */
3617 static char (*x_caught_error_message
)[200];
3619 /* An X error handler which stores the error message in
3620 x_caught_error_message. This is what's installed when
3621 x_catch_errors is in effect. */
3623 x_error_catcher (display
, error
)
3627 XGetErrorText (display
, error
->error_code
,
3628 *x_caught_error_message
, sizeof (*x_caught_error_message
));
3632 /* Begin trapping X errors.
3634 After calling this function, X protocol errors no longer cause
3635 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3637 Calling x_check_errors signals an Emacs error if an X error has
3638 occurred since the last call to x_catch_errors or x_check_errors.
3640 Calling x_uncatch_errors resumes the normal error handling. */
3642 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3647 /* Make sure any errors from previous requests have been dealt with. */
3648 XSync (x_current_display
, False
);
3650 /* Set up the error buffer. */
3651 x_caught_error_message
=
3652 (char (*)[]) xmalloc (sizeof (*x_caught_error_message
));
3653 (*x_caught_error_message
)[0] = '\0';
3655 /* Install our little error handler. */
3656 XHandleError (x_error_catcher
);
3659 /* If any X protocol errors have arrived since the last call to
3660 x_catch_errors or x_check_errors, signal an Emacs error using
3661 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3663 x_check_errors (format
)
3666 /* Make sure to catch any errors incurred so far. */
3667 XSync (x_current_display
, False
);
3669 if ((*x_caught_error_message
)[0])
3673 sprintf (buf
, format
, *x_caught_error_message
);
3674 free (x_caught_error_message
);
3676 x_uncatch_errors ();
3684 free (x_caught_error_message
);
3685 XHandleError (x_error_quitter
);
3689 static unsigned int x_wire_count
;
3692 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3697 /* Changing the font of the frame. */
3699 /* Set the font of the x-window specified by frame F
3700 to the font named NEWNAME. This is safe to use
3701 even before F has an actual x-window. */
3705 /* A table of all the fonts we have already loaded. */
3706 static XFontStruct
**x_font_table
;
3708 /* The current capacity of x_font_table. */
3709 static int x_font_table_size
;
3711 /* The number of fonts actually stored in x_font_table.
3712 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3713 0 <= n_fonts <= x_font_table_size. */
3716 x_new_font (f
, fontname
)
3718 register char *fontname
;
3722 int n_matching_fonts
;
3723 XFontStruct
*font_info
;
3726 /* Get a list of all the fonts that match this name. Once we
3727 have a list of matching fonts, we compare them against the fonts
3728 we already have by comparing font ids. */
3729 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3730 1024, &n_matching_fonts
,
3732 /* If the server couldn't find any fonts whose named matched fontname,
3733 return an error code. */
3734 if (n_matching_fonts
== 0)
3737 /* See if we've already loaded a matching font. */
3742 for (i
= 0; i
< n_fonts
; i
++)
3743 for (j
= 0; j
< n_matching_fonts
; j
++)
3744 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3752 /* If we have, just return it from the table. */
3754 f
->display
.x
->font
= x_font_table
[already_loaded
];
3756 /* Otherwise, load the font and add it to the table. */
3761 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
3765 /* Do we need to create the table? */
3766 if (x_font_table_size
== 0)
3768 x_font_table_size
= 16;
3770 = (XFontStruct
**) xmalloc (x_font_table_size
3771 * sizeof (x_font_table
[0]));
3773 /* Do we need to grow the table? */
3774 else if (n_fonts
>= x_font_table_size
)
3776 x_font_table_size
*= 2;
3778 = (XFontStruct
**) xrealloc (x_font_table
,
3780 * sizeof (x_font_table
[0])));
3783 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
3786 /* Free the information from XListFontsWithInfo. The data
3787 we actually retain comes from XLoadQueryFont. */
3788 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
3790 /* Now make the frame display the given font. */
3791 if (FRAME_X_WINDOW (f
) != 0)
3793 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
3794 f
->display
.x
->font
->fid
);
3795 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
3796 f
->display
.x
->font
->fid
);
3797 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
3798 f
->display
.x
->font
->fid
);
3800 x_set_window_size (f
, f
->width
, f
->height
);
3805 #else /* ! defined (HAVE_X11) */
3806 x_new_font (f
, newname
)
3808 register char *newname
;
3813 temp
= XGetFont (newname
);
3814 if (temp
== (FONT_TYPE
*) 0)
3817 if (f
->display
.x
->font
)
3818 XLoseFont (f
->display
.x
->font
);
3820 f
->display
.x
->font
= temp
;
3822 if (FRAME_X_WINDOW (f
) != 0)
3823 x_set_window_size (f
, f
->width
, f
->height
);
3827 #endif /* ! defined (HAVE_X11) */
3829 /* X Window sizes and positions. */
3831 x_calc_absolute_position (f
)
3835 if (f
->display
.x
->left_pos
< 0)
3836 f
->display
.x
->left_pos
3837 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
3839 if (f
->display
.x
->top_pos
< 0)
3840 f
->display
.x
->top_pos
3841 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
3842 #else /* ! defined (HAVE_X11) */
3843 WINDOWINFO_TYPE parentinfo
;
3845 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
3847 if (f
->display
.x
->left_pos
< 0)
3848 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
3849 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
3851 if (f
->display
.x
->top_pos
< 0)
3852 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
3853 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
3854 #endif /* ! defined (HAVE_X11) */
3857 x_set_offset (f
, xoff
, yoff
)
3859 register int xoff
, yoff
;
3861 f
->display
.x
->top_pos
= yoff
;
3862 f
->display
.x
->left_pos
= xoff
;
3863 x_calc_absolute_position (f
);
3866 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
3867 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
3869 x_wm_set_size_hint (f
, 0);
3870 #endif /* ! defined (HAVE_X11) */
3874 /* Call this to change the size of frame F's x-window. */
3876 x_set_window_size (f
, cols
, rows
)
3880 int pixelwidth
, pixelheight
;
3885 check_frame_size (f
, &rows
, &cols
);
3886 f
->display
.x
->vertical_scroll_bar_extra
=
3887 (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3888 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
3890 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3891 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3894 x_wm_set_size_hint (f
, 0);
3895 #endif /* ! defined (HAVE_X11) */
3896 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
3898 /* Now, strictly speaking, we can't be sure that this is accurate,
3899 but the window manager will get around to dealing with the size
3900 change request eventually, and we'll hear how it went when the
3901 ConfigureNotify event gets here.
3903 We could just not bother storing any of this information here,
3904 and let the ConfigureNotify event set everything up, but that
3905 might be kind of confusing to the lisp code, since size changes
3906 wouldn't be reported in the frame parameters until some random
3907 point in the future when the ConfigureNotify event arrives. */
3908 change_frame_size (f
, rows
, cols
, 0, 0);
3909 PIXEL_WIDTH (f
) = pixelwidth
;
3910 PIXEL_HEIGHT (f
) = pixelheight
;
3912 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3913 receive in the ConfigureNotify event; if we get what we asked
3914 for, then the event won't cause the screen to become garbaged, so
3915 we have to make sure to do it here. */
3916 SET_FRAME_GARBAGED (f
);
3923 x_set_resize_hint (f
)
3926 XSetResizeHint (FRAME_X_WINDOW (f
),
3927 2 * f
->display
.x
->internal_border_width
,
3928 2 * f
->display
.x
->internal_border_width
,
3929 FONT_WIDTH (f
->display
.x
->font
),
3930 FONT_HEIGHT (f
->display
.x
->font
));
3932 #endif /* HAVE_X11 */
3934 /* Mouse warping, focus shifting, raising and lowering. */
3936 x_set_mouse_position (f
, x
, y
)
3944 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
3945 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
3947 if (pix_x
< 0) pix_x
= 0;
3948 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3950 if (pix_y
< 0) pix_y
= 0;
3951 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3955 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
3960 x_focus_on_frame (f
)
3965 /* I don't think that the ICCCM allows programs to do things like this
3966 without the interaction of the window manager. Whatever you end up
3967 doing with this code, do it to x_unfocus_frame too. */
3968 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
3969 RevertToPointerRoot
, CurrentTime
);
3977 /* Look at the remarks in x_focus_on_frame. */
3978 if (x_focus_frame
== f
)
3979 XSetInputFocus (x_current_display
, PointerRoot
,
3980 RevertToPointerRoot
, CurrentTime
);
3984 #endif /* ! defined (HAVE_X11) */
3986 /* Raise frame F. */
3991 if (f
->async_visible
)
3994 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4000 /* Lower frame F. */
4005 if (f
->async_visible
)
4008 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4015 XTframe_raise_lower (f
, raise
)
4026 /* Change from withdrawn state to mapped state. */
4028 x_make_frame_visible (f
)
4035 if (! FRAME_VISIBLE_P (f
))
4038 if (! EQ (Vx_no_window_manager
, Qt
))
4039 x_wm_set_window_state (f
, NormalState
);
4041 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4042 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4043 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4044 #else /* ! defined (HAVE_X11) */
4045 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4046 if (f
->display
.x
->icon_desc
!= 0)
4047 XUnmapWindow (f
->display
.x
->icon_desc
);
4049 /* Handled by the MapNotify event for X11 */
4050 f
->async_visible
= 1;
4051 f
->async_iconified
= 0;
4053 /* NOTE: this may cause problems for the first frame. */
4055 #endif /* ! defined (HAVE_X11) */
4063 /* Change from mapped state to withdrawn state. */
4065 x_make_frame_invisible (f
)
4070 if (! f
->async_visible
)
4077 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4078 DefaultScreen (x_current_display
)))
4080 UNBLOCK_INPUT_RESIGNAL
;
4081 error ("can't notify window manager of window withdrawl");
4084 #else /* ! defined (HAVE_X11R4) */
4087 /* Tell the window manager what we're going to do. */
4088 if (! EQ (Vx_no_window_manager
, Qt
))
4092 unmap
.xunmap
.type
= UnmapNotify
;
4093 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4094 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4095 unmap
.xunmap
.from_configure
= False
;
4096 if (! XSendEvent (x_current_display
,
4097 DefaultRootWindow (x_current_display
),
4099 SubstructureRedirectMask
|SubstructureNotifyMask
,
4102 UNBLOCK_INPUT_RESIGNAL
;
4103 error ("can't notify window manager of withdrawal");
4107 /* Unmap the window ourselves. Cheeky! */
4108 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4110 #else /* ! defined (HAVE_X11) */
4112 XUnmapWindow (FRAME_X_WINDOW (f
));
4113 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4114 if (f
->display
.x
->icon_desc
!= 0)
4115 XUnmapWindow (f
->display
.x
->icon_desc
);
4117 #endif /* ! defined (HAVE_X11) */
4118 #endif /* ! defined (HAVE_X11R4) */
4124 /* Window manager communication. Created in Fx_open_connection. */
4125 extern Atom Xatom_wm_change_state
;
4127 /* Change window state from mapped to iconified. */
4134 if (f
->async_iconified
)
4140 /* Since we don't know which revision of X we're running, we'll use both
4141 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4143 /* X11R4: send a ClientMessage to the window manager using the
4144 WM_CHANGE_STATE type. */
4148 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4149 message
.xclient
.type
= ClientMessage
;
4150 message
.xclient
.message_type
= Xatom_wm_change_state
;
4151 message
.xclient
.format
= 32;
4152 message
.xclient
.data
.l
[0] = IconicState
;
4154 if (! XSendEvent (x_current_display
,
4155 DefaultRootWindow (x_current_display
),
4157 SubstructureRedirectMask
| SubstructureNotifyMask
,
4160 UNBLOCK_INPUT_RESIGNAL
;
4161 error ("Can't notify window manager of iconification.");
4165 /* X11R3: set the initial_state field of the window manager hints to
4167 x_wm_set_window_state (f
, IconicState
);
4169 f
->async_iconified
= 1;
4170 #else /* ! defined (HAVE_X11) */
4171 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4173 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4174 if (f
->display
.x
->icon_desc
!= 0)
4176 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4179 #endif /* ! defined (HAVE_X11) */
4185 /* Destroy the X window of frame F. */
4187 x_destroy_window (f
)
4192 if (f
->display
.x
->icon_desc
!= 0)
4193 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4194 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4197 free (f
->display
.x
);
4199 if (f
== x_focus_frame
)
4201 if (f
== x_highlight_frame
)
4202 x_highlight_frame
= 0;
4207 /* Manage event queues for X10. */
4211 /* Manage event queues.
4213 This code is only used by the X10 support.
4215 We cannot leave events in the X queue and get them when we are ready
4216 because X does not provide a subroutine to get only a certain kind
4217 of event but not block if there are no queued events of that kind.
4219 Therefore, we must examine events as they come in and copy events
4220 of certain kinds into our private queues.
4222 All ExposeRegion events are put in x_expose_queue.
4223 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4226 /* Write the event *P_XREP into the event queue *QUEUE.
4227 If the queue is full, do nothing, but return nonzero. */
4230 enqueue_event (p_xrep
, queue
)
4231 register XEvent
*p_xrep
;
4232 register struct event_queue
*queue
;
4234 int newindex
= queue
->windex
+ 1;
4235 if (newindex
== EVENT_BUFFER_SIZE
)
4237 if (newindex
== queue
->rindex
)
4239 queue
->xrep
[queue
->windex
] = *p_xrep
;
4240 queue
->windex
= newindex
;
4244 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4245 If *QUEUE is empty, do nothing and return 0. */
4248 dequeue_event (p_xrep
, queue
)
4249 register XEvent
*p_xrep
;
4250 register struct event_queue
*queue
;
4252 if (queue
->windex
== queue
->rindex
)
4254 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4255 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4260 /* Return the number of events buffered in *QUEUE. */
4263 queue_event_count (queue
)
4264 register struct event_queue
*queue
;
4266 int tem
= queue
->windex
- queue
->rindex
;
4269 return EVENT_BUFFER_SIZE
+ tem
;
4272 /* Return nonzero if mouse input is pending. */
4275 mouse_event_pending_p ()
4277 return queue_event_count (&x_mouse_queue
);
4279 #endif /* HAVE_X11 */
4281 /* Setting window manager hints. */
4285 x_wm_set_size_hint (f
, prompting
)
4289 XSizeHints size_hints
;
4290 Window window
= FRAME_X_WINDOW (f
);
4292 size_hints
.flags
= PResizeInc
| PMinSize
| PMaxSize
;
4294 flexlines
= f
->height
;
4296 size_hints
.x
= f
->display
.x
->left_pos
;
4297 size_hints
.y
= f
->display
.x
->top_pos
;
4298 size_hints
.height
= PIXEL_HEIGHT (f
);
4299 size_hints
.width
= PIXEL_WIDTH (f
);
4300 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4301 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4302 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4303 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4306 int base_width
, base_height
;
4308 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4309 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4312 int min_rows
= 0, min_cols
= 0;
4313 check_frame_size (f
, &min_rows
, &min_cols
);
4315 /* The window manager uses the base width hints to calculate the
4316 current number of rows and columns in the frame while
4317 resizing; min_width and min_height aren't useful for this
4318 purpose, since they might not give the dimensions for a
4319 zero-row, zero-column frame.
4321 We use the base_width and base_height members if we have
4322 them; otherwise, we set the min_width and min_height members
4323 to the size for a zero x zero frame. */
4326 size_hints
.flags
|= PBaseSize
;
4327 size_hints
.base_width
= base_width
;
4328 size_hints
.base_height
= base_height
;
4329 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4330 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4332 size_hints
.min_width
= base_width
;
4333 size_hints
.min_height
= base_height
;
4340 size_hints
.flags
|= prompting
;
4343 XSizeHints hints
; /* Sometimes I hate X Windows... */
4345 XGetNormalHints (x_current_display
, window
, &hints
);
4346 if (hints
.flags
& PSize
)
4347 size_hints
.flags
|= PSize
;
4348 if (hints
.flags
& PPosition
)
4349 size_hints
.flags
|= PPosition
;
4350 if (hints
.flags
& USPosition
)
4351 size_hints
.flags
|= USPosition
;
4352 if (hints
.flags
& USSize
)
4353 size_hints
.flags
|= USSize
;
4357 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4359 XSetNormalHints (x_current_display
, window
, &size_hints
);
4363 /* Used for IconicState or NormalState */
4364 x_wm_set_window_state (f
, state
)
4368 Window window
= FRAME_X_WINDOW (f
);
4370 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4371 f
->display
.x
->wm_hints
.initial_state
= state
;
4373 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4376 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4380 Window window
= FRAME_X_WINDOW (f
);
4384 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4385 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4388 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4390 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4393 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4397 Window window
= FRAME_X_WINDOW (f
);
4399 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4400 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4401 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4403 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4407 /* Initialization. */
4410 x_term_init (display_name
)
4416 extern int old_fcntl_owner
;
4417 #endif /* ! defined (F_SETOWN) */
4419 x_focus_frame
= x_highlight_frame
= 0;
4421 x_current_display
= XOpenDisplay (display_name
);
4422 if (x_current_display
== 0)
4423 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4428 int hostname_size
= 256;
4430 hostname
= (char *) xmalloc (hostname_size
);
4433 XSetAfterFunction (x_current_display
, x_trace_wire
);
4436 invocation_name
= Ffile_name_nondirectory (Fcar (Vcommand_line_args
));
4438 /* Try to get the host name; if the buffer is too short, try
4439 again. Apparently, the only indication gethostname gives of
4440 whether the buffer was large enough is the presence or absence
4441 of a '\0' in the string. Eech. */
4444 gethostname (hostname
, hostname_size
- 1);
4445 hostname
[hostname_size
- 1] = '\0';
4447 /* Was the buffer large enough for gethostname to store the '\0'? */
4448 if (strlen (hostname
) < hostname_size
- 1)
4451 hostname_size
<<= 1;
4452 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4454 x_id_name
= (char *) xmalloc (XSTRING (invocation_name
)->size
4457 sprintf (x_id_name
, "%s@%s", XSTRING (invocation_name
)->data
, hostname
);
4460 /* Figure out which modifier bits mean what. */
4461 x_find_modifier_meanings ();
4463 /* Get the scroll bar cursor. */
4464 x_vertical_scroll_bar_cursor
=
4465 XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4467 /* Watch for PropertyNotify events on the root window; we use them
4468 to figure out when to invalidate our cache of the cut buffers. */
4469 x_watch_cut_buffer_cache ();
4471 dup2 (ConnectionNumber (x_current_display
), 0);
4473 #ifndef SYSV_STREAMS
4474 /* Streams somehow keeps track of which descriptor number
4475 is being used to talk to X. So it is not safe to substitute
4476 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4477 close (ConnectionNumber (x_current_display
));
4478 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4479 * check the def of the macro;
4480 * it is a genuine lvalue */
4481 #endif /* SYSV_STREAMS */
4483 #endif /* ! defined (HAVE_X11) */
4486 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4487 #ifdef F_SETOWN_SOCK_NEG
4488 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4489 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4490 fcntl (0, F_SETOWN
, getpid ());
4491 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4492 #endif /* ! defined (F_SETOWN) */
4496 #endif /* ! defined (SIGIO) */
4498 /* Must use interrupt input because we cannot otherwise
4499 arrange for C-g to be noticed immediately.
4500 We cannot connect it to SIGINT. */
4501 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4503 expose_all_windows
= 0;
4505 clear_frame_hook
= XTclear_frame
;
4506 clear_end_of_line_hook
= XTclear_end_of_line
;
4507 ins_del_lines_hook
= XTins_del_lines
;
4508 change_line_highlight_hook
= XTchange_line_highlight
;
4509 insert_glyphs_hook
= XTinsert_glyphs
;
4510 write_glyphs_hook
= XTwrite_glyphs
;
4511 delete_glyphs_hook
= XTdelete_glyphs
;
4512 ring_bell_hook
= XTring_bell
;
4513 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4514 set_terminal_modes_hook
= XTset_terminal_modes
;
4515 update_begin_hook
= XTupdate_begin
;
4516 update_end_hook
= XTupdate_end
;
4517 set_terminal_window_hook
= XTset_terminal_window
;
4518 read_socket_hook
= XTread_socket
;
4519 cursor_to_hook
= XTcursor_to
;
4520 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4521 mouse_position_hook
= XTmouse_position
;
4522 frame_rehighlight_hook
= XTframe_rehighlight
;
4523 frame_raise_lower_hook
= XTframe_raise_lower
;
4524 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
4525 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
4526 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
4527 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
4529 scroll_region_ok
= 1; /* we'll scroll partial frames */
4530 char_ins_del_ok
= 0; /* just as fast to write the line */
4531 line_ins_del_ok
= 1; /* we'll just blt 'em */
4532 fast_clear_end_of_line
= 1; /* X does this well */
4533 memory_below_frame
= 0; /* we don't remember what scrolls
4537 /* Note that there is no real way portable across R3/R4 to get the
4538 original error handler. */
4539 XHandleError (x_error_quitter
);
4540 XHandleIOError (x_io_error_quitter
);
4542 /* Disable Window Change signals; they are handled by X events. */
4544 signal (SIGWINCH
, SIG_DFL
);
4545 #endif /* ! defined (SIGWINCH) */
4547 signal (SIGPIPE
, x_connection_closed
);
4553 staticpro (&invocation_name
);
4554 invocation_name
= Qnil
;
4556 staticpro (&last_mouse_scroll_bar
);
4558 #endif /* ! defined (HAVE_X11) */
4559 #endif /* ! defined (HAVE_X_WINDOWS) */