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.
28 #define NEW_SELECTIONS
35 #include "blockinput.h"
37 /* On 4.3 these lose if they come after xterm.h. */
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
44 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
55 #include <sys/ioctl.h>
57 #else /* ! defined (BSD) */
59 #include <sys/termio.h>
62 #endif /* ! defined (BSD) */
64 /* Allow m- file to inhibit use of FIONREAD. */
65 #ifdef BROKEN_FIONREAD
67 #endif /* ! defined (BROKEN_FIONREAD) */
69 /* We are unable to use interrupts if FIONREAD is not available,
70 so flush SIGIO so we won't try. */
74 #endif /* ! defined (SIGIO) */
84 #include <sys/param.h>
86 #include "dispextern.h"
87 #include "termhooks.h"
101 #define XMapWindow XMapRaised /* Raise them when mapping. */
102 #else /* ! defined (HAVE_X11) */
103 #include <X/Xkeyboard.h>
104 /*#include <X/Xproto.h> */
105 #endif /* ! defined (HAVE_X11) */
107 /* For sending Meta-characters. Do we need this? */
110 #define min(a,b) ((a)<(b) ? (a) : (b))
111 #define max(a,b) ((a)>(b) ? (a) : (b))
113 /* Nonzero means we must reprint all windows
114 because 1) we received an ExposeWindow event
115 or 2) we received too many ExposeRegion events to record.
117 This is never needed under X11. */
118 static int expose_all_windows
;
120 /* Nonzero means we must reprint all icon windows. */
122 static int expose_all_icons
;
125 /* ExposeRegion events, when received, are copied into this queue
126 for later processing. */
128 static struct event_queue x_expose_queue
;
130 /* ButtonPressed and ButtonReleased events, when received,
131 are copied into this queue for later processing. */
133 struct event_queue x_mouse_queue
;
134 #endif /* HAVE_X11 */
136 #if defined (SIGIO) && defined (FIONREAD)
137 int BLOCK_INPUT_mask
;
138 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
140 /* The id of a bitmap used for icon windows.
141 One such map is shared by all Emacs icon windows.
142 This is zero if we have not yet had a need to create the bitmap. */
144 static Bitmap icon_bitmap
;
146 /* Font used for text icons. */
148 static FONT_TYPE
*icon_font_info
;
150 /* Stuff for dealing with the main icon title. */
152 extern Lisp_Object Vcommand_line_args
;
153 char *hostname
, *x_id_name
;
155 /* This is the X connection that we are using. */
157 Display
*x_current_display
;
159 /* The cursor to use for vertical scroll bars on x_current_display. */
160 static Cursor x_vertical_scroll_bar_cursor
;
162 /* Frame being updated by update_frame. This is declared in term.c.
163 This is set by update_begin and looked at by all the
164 XT functions. It is zero while not inside an update.
165 In that case, the XT functions assume that `selected_frame'
166 is the frame to apply to. */
167 extern struct frame
*updating_frame
;
169 /* The frame (if any) which has the X window that has keyboard focus.
170 Zero if none. This is examined by Ffocus_frame in frame.c. Note
171 that a mere EnterNotify event can set this; if you need to know the
172 last frame specified in a FocusIn or FocusOut event, use
173 x_focus_event_frame. */
174 struct frame
*x_focus_frame
;
176 /* The last frame mentioned in a FocusIn or FocusOut event. This is
177 separate from x_focus_frame, because whether or not LeaveNotify
178 events cause us to lose focus depends on whether or not we have
179 received a FocusIn event for it. */
180 struct frame
*x_focus_event_frame
;
182 /* The frame which currently has the visual highlight, and should get
183 keyboard input (other sorts of input have the frame encoded in the
184 event). It points to the X focus frame's selected window's
185 frame. It differs from x_focus_frame when we're using a global
187 static struct frame
*x_highlight_frame
;
189 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
190 mouse is moved to inside of frame when frame is de-iconified. */
192 static int warp_mouse_on_deiconify
;
194 /* During an update, maximum vpos for ins/del line operations to affect. */
196 static int flexlines
;
198 /* During an update, nonzero if chars output now should be highlighted. */
200 static int highlight
;
202 /* Nominal cursor position -- where to draw output.
203 During an update, these are different from the cursor-box position. */
209 /* `t' if a mouse button is depressed. */
211 extern Lisp_Object Vmouse_depressed
;
213 /* Tells if a window manager is present or not. */
215 extern Lisp_Object Vx_no_window_manager
;
217 /* Timestamp that we requested selection data was made. */
218 extern Time requestor_time
;
220 /* ID of the window requesting selection data. */
221 extern Window requestor_window
;
223 /* Nonzero enables some debugging for the X interface code. */
226 #else /* ! defined (HAVE_X11) */
228 /* Bit patterns for the mouse cursor. */
230 short MouseCursor
[] = {
231 0x0000, 0x0008, 0x0018, 0x0038,
232 0x0078, 0x00f8, 0x01f8, 0x03f8,
233 0x07f8, 0x00f8, 0x00d8, 0x0188,
234 0x0180, 0x0300, 0x0300, 0x0000};
236 short MouseMask
[] = {
237 0x000c, 0x001c, 0x003c, 0x007c,
238 0x00fc, 0x01fc, 0x03fc, 0x07fc,
239 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
240 0x03cc, 0x0780, 0x0780, 0x0300};
242 static short grey_bits
[] = {
243 0x0005, 0x000a, 0x0005, 0x000a};
245 static Pixmap GreyPixmap
= 0;
246 #endif /* ! defined (HAVE_X11) */
248 /* From time to time we get info on an Emacs window, here. */
250 static WINDOWINFO_TYPE windowinfo
;
254 /* A mask of extra modifier bits to put into every keyboard char. */
255 extern int extra_keyboard_modifiers
;
257 extern Display
*XOpenDisplay ();
258 extern Window
XCreateWindow ();
260 extern Cursor
XCreateCursor ();
261 extern FONT_TYPE
*XOpenFont ();
263 static void flashback ();
266 static void dumpqueue ();
267 #endif /* HAVE_X11 */
270 static int XTcursor_to ();
271 static int XTclear_end_of_line ();
274 /* Starting and ending updates.
276 These hooks are called by update_frame at the beginning and end
277 of a frame update. We record in `updating_frame' the identity
278 of the frame being updated, so that the XT... functions do not
279 need to take a frame as argument. Most of the XT... functions
280 should never be called except during an update, the only exceptions
281 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
283 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
294 flexlines
= f
->height
;
300 #endif /* HAVE_X11 */
305 static void x_do_pending_expose ();
314 if (updating_frame
== 0
315 || updating_frame
!= f
)
321 x_do_pending_expose ();
322 #endif /* HAVE_X11 */
324 x_display_cursor (f
, 1);
330 /* External interface to control of standout mode.
331 Call this when about to modify line at position VPOS
332 and not change whether it is highlighted. */
334 XTreassert_line_highlight (new, vpos
)
340 /* Call this when about to modify line at position VPOS
341 and change whether it is highlighted. */
344 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
345 int new_highlight
, vpos
, first_unused_hpos
;
347 highlight
= new_highlight
;
348 XTcursor_to (vpos
, 0);
349 XTclear_end_of_line (updating_frame
->width
);
352 /* This is used when starting Emacs and when restarting after suspend.
353 When starting Emacs, no X window is mapped. And nothing must be done
354 to Emacs's own window if it is suspended (though that rarely happens). */
357 XTset_terminal_modes ()
361 /* This is called when exiting or suspending Emacs.
362 Exiting will make the X-windows go away, and suspending
363 requires no action. */
366 XTreset_terminal_modes ()
368 /* XTclear_frame (); */
371 /* Set the nominal cursor position of the frame.
372 This is where display update commands will take effect.
373 This does not affect the place where the cursor-box is displayed. */
376 XTcursor_to (row
, col
)
377 register int row
, col
;
385 if (updating_frame
== 0)
388 x_display_cursor (selected_frame
, 1);
394 /* Display a sequence of N glyphs found at GP.
395 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
396 HL is 1 if this text is highlighted, 2 if the cursor is on it.
398 FONT is the default font to use (for glyphs whose font-code is 0).
400 Since the display generation code is responsible for calling
401 compute_char_face and compute_glyph_face on everything it puts in
402 the display structure, we can assume that the face code on each
403 glyph is a valid index into FRAME_FACES (f), and the one to which
404 we can actually apply intern_face. */
407 /* This is the multi-face code. */
410 dumpglyphs (f
, left
, top
, gp
, n
, hl
)
413 register GLYPH
*gp
; /* Points to first GLYPH. */
414 register int n
; /* Number of glyphs to display. */
417 /* Holds characters to be displayed. */
418 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
419 register char *cp
; /* Steps through buf[]. */
420 register int tlen
= GLYPH_TABLE_LENGTH
;
421 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
422 Window window
= FRAME_X_WINDOW (f
);
424 extern struct face
*intern_face (/* FRAME_PTR, struct face * */);
428 /* Get the face-code of the next GLYPH. */
432 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
435 /* Find the run of consecutive glyphs with the same face-code.
436 Extract their character codes into BUF. */
441 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
442 if (GLYPH_FACE (g
) != cf
)
445 *cp
++ = GLYPH_CHAR (g
);
450 /* LEN gets the length of the run. */
453 /* Now output this run of chars, with the font and pixel values
454 determined by the face code CF. */
456 struct face
*face
= FRAME_DEFAULT_FACE (f
);
457 FONT_TYPE
*font
= FACE_FONT (face
);
458 GC gc
= FACE_GC (face
);
460 int gc_temporary
= 0;
462 /* First look at the face of the text itself. */
465 /* The face codes on the glyphs must be valid indices into the
466 frame's face table. */
467 if (cf
< 0 || cf
>= FRAME_N_FACES (f
))
471 face
= FRAME_MODE_LINE_FACE (f
);
473 face
= intern_face (f
, FRAME_FACES (f
) [cf
]);
474 font
= FACE_FONT (face
);
479 /* Then comes the distinction between modeline and normal text. */
484 face
= FRAME_MODE_LINE_FACE (f
);
485 font
= FACE_FONT (face
);
490 #define FACE_DEFAULT (~0)
492 /* Now override that if the cursor's on this character. */
493 if (hl
== 2 && (defaulted
494 || !(face
->font
&& (int) face
->font
!= FACE_DEFAULT
)))
496 gc
= f
->display
.x
->cursor_gc
;
498 /* Cursor on non-default face: must merge. */
504 xgcv
.background
= f
->display
.x
->cursor_pixel
;
505 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
506 xgcv
.font
= face
->font
->fid
;
507 xgcv
.graphics_exposures
= 0;
508 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
509 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
512 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
513 XSetStipple (x_current_display
, gc
, face
->stipple
);
518 XDrawImageString (x_current_display
, window
, gc
,
519 left
, top
+ FONT_BASE (font
), buf
, len
);
522 XFreeGC (x_current_display
, gc
);
524 /* We should probably check for XA_UNDERLINE_POSITION and
525 XA_UNDERLINE_THICKNESS properties on the font, but let's
526 just get the thing working, and come back to that. */
528 int underline_position
= 1;
530 if (font
->descent
<= underline_position
)
531 underline_position
= font
->descent
- 1;
534 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
538 + underline_position
),
539 len
* FONT_WIDTH (font
), 1);
542 left
+= len
* FONT_WIDTH (font
);
549 /* This is the old single-face code. */
552 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
555 register GLYPH
*gp
; /* Points to first GLYPH. */
556 register int n
; /* Number of glyphs to display. */
561 Window window
= FRAME_X_WINDOW (f
);
562 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
563 : (hl
? f
->display
.x
->reverse_gc
564 : f
->display
.x
->normal_gc
));
566 if (sizeof (GLYPH
) == sizeof (XChar2b
))
567 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
568 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
569 else if (sizeof (GLYPH
) == sizeof (unsigned char))
570 XDrawImageString (x_current_display
, window
, drawing_gc
,
571 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
573 /* What size of glyph ARE you using? And does X have a function to
579 /* Output some text at the nominal frame cursor position.
580 Advance the cursor over the text.
581 Output LEN glyphs at START.
583 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
584 controls the pixel values used for foreground and background. */
587 XTwrite_glyphs (start
, len
)
588 register GLYPH
*start
;
591 register int temp_length
;
601 /* If not within an update,
602 output at the frame's visible cursor. */
603 curs_x
= f
->cursor_x
;
604 curs_y
= f
->cursor_y
;
608 CHAR_TO_PIXEL_COL (f
, curs_x
),
609 CHAR_TO_PIXEL_ROW (f
, curs_y
),
610 start
, len
, highlight
);
612 /* If we drew on top of the cursor, note that it is turned off. */
613 if (curs_y
== f
->phys_cursor_y
614 && curs_x
<= f
->phys_cursor_x
615 && curs_x
+ len
> f
->phys_cursor_x
)
616 f
->phys_cursor_x
= -1;
618 if (updating_frame
== 0)
621 x_display_cursor (f
, 1);
630 /* Clear to the end of the line.
631 Erase the current text line from the nominal cursor position (inclusive)
632 to column FIRST_UNUSED (exclusive). The idea is that everything
633 from FIRST_UNUSED onward is already erased. */
636 XTclear_end_of_line (first_unused
)
637 register int first_unused
;
639 struct frame
*f
= updating_frame
;
645 if (curs_y
< 0 || curs_y
>= f
->height
)
647 if (first_unused
<= 0)
650 if (first_unused
>= f
->width
)
651 first_unused
= f
->width
;
655 /* Notice if the cursor will be cleared by this operation. */
656 if (curs_y
== f
->phys_cursor_y
657 && curs_x
<= f
->phys_cursor_x
658 && f
->phys_cursor_x
< first_unused
)
659 f
->phys_cursor_x
= -1;
662 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
663 CHAR_TO_PIXEL_COL (f
, curs_x
),
664 CHAR_TO_PIXEL_ROW (f
, curs_y
),
665 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
666 FONT_HEIGHT (f
->display
.x
->font
), False
);
668 #else /* ! defined (HAVE_X11) */
669 XPixSet (FRAME_X_WINDOW (f
),
670 CHAR_TO_PIXEL_COL (f
, curs_x
),
671 CHAR_TO_PIXEL_ROW (f
, curs_y
),
672 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
673 FONT_HEIGHT (f
->display
.x
->font
),
674 f
->display
.x
->background_pixel
);
675 #endif /* ! defined (HAVE_X11) */
684 struct frame
*f
= updating_frame
;
689 f
->phys_cursor_x
= -1; /* Cursor not visible. */
690 curs_x
= 0; /* Nominal cursor position is top left. */
695 XClear (FRAME_X_WINDOW (f
));
697 /* We have to clear the scroll bars, too. If we have changed
698 colors or something like that, then they should be notified. */
699 x_scroll_bar_clear (f
);
703 #endif /* HAVE_X11 */
709 /* Invert the middle quarter of the frame for .15 sec. */
711 /* We use the select system call to do the waiting, so we have to make sure
712 it's avaliable. If it isn't, we just won't do visual bells. */
713 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
715 /* Subtract the `struct timeval' values X and Y,
716 storing the result in RESULT.
717 Return 1 if the difference is negative, otherwise 0. */
720 timeval_subtract (result
, x
, y
)
721 struct timeval
*result
, x
, y
;
723 /* Perform the carry for the later subtraction by updating y.
724 This is safer because on some systems
725 the tv_sec member is unsigned. */
726 if (x
.tv_usec
< y
.tv_usec
)
728 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
729 y
.tv_usec
-= 1000000 * nsec
;
732 if (x
.tv_usec
- y
.tv_usec
> 1000000)
734 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
735 y
.tv_usec
+= 1000000 * nsec
;
739 /* Compute the time remaining to wait. tv_usec is certainly positive. */
740 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
741 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
743 /* Return indication of whether the result should be considered negative. */
744 return x
.tv_sec
< y
.tv_sec
;
755 /* Create a GC that will use the GXxor function to flip foreground pixels
756 into background pixels. */
760 values
.function
= GXxor
;
761 values
.foreground
= (f
->display
.x
->foreground_pixel
762 ^ f
->display
.x
->background_pixel
);
764 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
765 GCFunction
| GCForeground
, &values
);
769 int width
= PIXEL_WIDTH (f
);
770 int height
= PIXEL_HEIGHT (f
);
772 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
773 width
/4, height
/4, width
/2, height
/2);
774 XFlush (x_current_display
);
777 struct timeval wakeup
, now
;
779 gettimeofday (&wakeup
, (struct timezone
*) 0);
781 /* Compute time to wait until, propagating carry from usecs. */
782 wakeup
.tv_usec
+= 150000;
783 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
784 wakeup
.tv_usec
%= 1000000;
786 /* Keep waiting until past the time wakeup. */
789 struct timeval timeout
;
791 gettimeofday (&timeout
, (struct timezone
*)0);
793 /* In effect, timeout = wakeup - timeout.
794 Break if result would be negative. */
795 if (timeval_subtract (&timeout
, wakeup
, timeout
))
798 /* Try to wait that long--but we might wake up sooner. */
799 select (0, 0, 0, 0, &timeout
);
803 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
804 width
/4, height
/4, width
/2, height
/2);
805 XFreeGC (x_current_display
, gc
);
806 XFlush (x_current_display
);
816 /* Make audible bell. */
819 #define XRINGBELL XBell(x_current_display, 0)
820 #else /* ! defined (HAVE_X11) */
821 #define XRINGBELL XFeep(0);
822 #endif /* ! defined (HAVE_X11) */
826 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
828 XTflash (selected_frame
);
839 /* Insert and delete character.
840 These are not supposed to be used because we are supposed to turn
841 off the feature of using them. */
844 XTinsert_glyphs (start
, len
)
845 register char *start
;
858 /* Specify how many text lines, from the top of the window,
859 should be affected by insert-lines and delete-lines operations.
860 This, and those operations, are used only within an update
861 that is bounded by calls to XTupdate_begin and XTupdate_end. */
864 XTset_terminal_window (n
)
867 if (updating_frame
== 0)
870 if ((n
<= 0) || (n
> updating_frame
->height
))
871 flexlines
= updating_frame
->height
;
876 /* Perform an insert-lines operation.
877 Insert N lines at a vertical position curs_y. */
883 register int topregion
, bottomregion
;
884 register int length
, newtop
, mask
;
885 register struct frame
*f
= updating_frame
;
886 int intborder
= f
->display
.x
->internal_border_width
;
888 if (curs_y
>= flexlines
)
892 bottomregion
= flexlines
- (n
+ 1);
893 newtop
= topregion
+ n
;
894 length
= (bottomregion
- topregion
) + 1;
898 #endif /* HAVE_X11 */
900 if ((length
> 0) && (newtop
<= flexlines
))
903 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
904 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
905 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
906 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
907 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
908 CHAR_TO_PIXEL_ROW (f
, newtop
));
909 #else /* ! defined (HAVE_X11) */
910 XMoveArea (FRAME_X_WINDOW (f
),
911 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
912 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
913 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
914 length
* FONT_HEIGHT (f
->display
.x
->font
));
915 /* Now we must process any ExposeRegion events that occur
916 if the area being copied from is obscured.
917 We can't let it wait because further i/d operations
918 may want to copy this area to another area. */
920 #endif /* ! defined (HAVE_X11) */
923 newtop
= min (newtop
, (flexlines
- 1));
924 length
= newtop
- topregion
;
928 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
929 CHAR_TO_PIXEL_ROW (f
, topregion
),
930 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
931 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
932 #else /* ! defined (HAVE_X11) */
933 XPixSet (FRAME_X_WINDOW (f
),
935 CHAR_TO_PIXEL_ROW (f
, topregion
),
936 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
937 n
* FONT_HEIGHT (f
->display
.x
->font
),
938 f
->display
.x
->background_pixel
);
939 #endif /* ! defined (HAVE_X11) */
943 /* Perform a delete-lines operation, deleting N lines
944 at a vertical position curs_y. */
951 register struct frame
*f
= updating_frame
;
952 int intborder
= f
->display
.x
->internal_border_width
;
954 if (curs_y
>= flexlines
)
959 #endif /* HAVE_X11 */
961 if ((curs_y
+ n
) >= flexlines
)
963 if (flexlines
>= (curs_y
+ 1))
966 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
967 CHAR_TO_PIXEL_ROW (f
, curs_y
),
968 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
969 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
970 #else /* ! defined (HAVE_X11) */
971 XPixSet (FRAME_X_WINDOW (f
),
972 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
973 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
974 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
975 f
->display
.x
->background_pixel
);
976 #endif /* ! defined (HAVE_X11) */
982 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
983 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
985 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
986 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
987 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
988 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
989 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
991 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
992 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
993 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
994 #else /* ! defined (HAVE_X11) */
995 XMoveArea (FRAME_X_WINDOW (f
),
997 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
998 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
999 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1000 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
1001 /* Now we must process any ExposeRegion events that occur
1002 if the area being copied from is obscured.
1003 We can't let it wait because further i/d operations
1004 may want to copy this area to another area. */
1006 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1007 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1008 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1009 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
1010 #endif /* ! defined (HAVE_X11) */
1014 /* Perform an insert-lines or delete-lines operation,
1015 inserting N lines or deleting -N lines at vertical position VPOS. */
1017 XTins_del_lines (vpos
, n
)
1020 if (updating_frame
== 0)
1023 /* Hide the cursor. */
1024 x_display_cursor (updating_frame
, 0);
1026 XTcursor_to (vpos
, 0);
1037 /* Support routines for exposure events. */
1038 static void clear_cursor ();
1040 /* Output into a rectangle of an X-window (for frame F)
1041 the characters in f->phys_lines that overlap that rectangle.
1042 TOP and LEFT are the position of the upper left corner of the rectangle.
1043 ROWS and COLS are the size of the rectangle. */
1046 dumprectangle (f
, left
, top
, cols
, rows
)
1048 register int left
, top
, cols
, rows
;
1050 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1051 int cursor_cleared
= 0;
1055 if (FRAME_GARBAGED_P (f
))
1058 /* Express rectangle as four edges, instead of position-and-size. */
1059 bottom
= top
+ rows
;
1060 right
= left
+ cols
;
1062 #ifndef HAVE_X11 /* Window manger does this for X11. */
1064 int intborder
= f
->display
.x
->internal_border_width
;
1066 /* If the rectangle includes any of the internal border area,
1067 redisplay the border emphasis. */
1068 if (top
< intborder
|| left
< intborder
1069 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1070 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1073 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1075 /* Convert rectangle edges in pixels to edges in chars.
1076 Round down for left and top, up for right and bottom. */
1077 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1078 left
= PIXEL_TO_CHAR_COL (f
, left
);
1079 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1080 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1081 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1082 right
= PIXEL_TO_CHAR_COL (f
, right
);
1084 /* Clip the rectangle to what can be visible. */
1089 if (right
> f
->width
)
1091 if (bottom
> f
->height
)
1094 /* Get size in chars of the rectangle. */
1095 cols
= right
- left
;
1096 rows
= bottom
- top
;
1098 /* If rectangle has zero area, return. */
1099 if (rows
<= 0) return;
1100 if (cols
<= 0) return;
1102 /* Turn off the cursor if it is in the rectangle.
1103 We will turn it back on afterward. */
1104 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1105 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1111 /* Display the text in the rectangle, one text line at a time. */
1113 for (y
= top
; y
< bottom
; y
++)
1115 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1117 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1121 CHAR_TO_PIXEL_COL (f
, left
),
1122 CHAR_TO_PIXEL_ROW (f
, y
),
1123 line
, min (cols
, active_frame
->used
[y
] - left
),
1124 active_frame
->highlight
[y
]);
1127 /* Turn the cursor on if we turned it off. */
1130 x_display_cursor (f
, 1);
1134 /* Process all queued ExposeRegion events. */
1140 XExposeRegionEvent r
;
1142 while (dequeue_event (&r
, &x_expose_queue
))
1144 struct frame
*f
= x_window_to_frame (r
.window
);
1145 if (f
->display
.x
->icon_desc
== r
.window
)
1148 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1152 #endif /* HAVE_X11 */
1154 /* Process all expose events that are pending, for X10.
1155 Redraws the cursor if necessary on any frame that
1156 is not in the process of being updated with update_frame. */
1160 x_do_pending_expose ()
1164 Lisp_Object tail
, frame
;
1166 if (expose_all_windows
)
1168 expose_all_windows
= 0;
1169 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1171 register int temp_width
, temp_height
;
1174 frame
= XCONS (tail
)->car
;
1175 if (XGCTYPE (frame
) != Lisp_Frame
)
1178 if (! FRAME_X_P (f
))
1180 if (!f
->async_visible
)
1182 if (!f
->display
.x
->needs_exposure
)
1185 intborder
= f
->display
.x
->internal_border_width
;
1188 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1189 temp_width
= ((windowinfo
.width
- 2 * intborder
1190 - f
->display
.x
->v_scroll_bar_width
)
1191 / FONT_WIDTH (f
->display
.x
->font
));
1192 temp_height
= ((windowinfo
.height
- 2 * intborder
1193 - f
->display
.x
->h_scroll_bar_height
)
1194 / FONT_HEIGHT (f
->display
.x
->font
));
1195 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1197 change_frame_size (f
, max (1, temp_height
),
1198 max (1, temp_width
), 0, 1);
1199 x_resize_scroll_bars (f
);
1201 f
->display
.x
->left_pos
= windowinfo
.x
;
1202 f
->display
.x
->top_pos
= windowinfo
.y
;
1203 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1207 f
->display
.x
->needs_exposure
= 0;
1208 if (updating_frame
!= f
)
1209 x_display_cursor (f
, 1);
1214 /* Handle any individual-rectangle expose events queued
1215 for various windows. */
1218 #else /* ! defined (HAVE_X11) */
1220 #endif /* ! defined (HAVE_X11) */
1226 frame_highlight (frame
)
1227 struct frame
*frame
;
1229 if (! EQ (Vx_no_window_manager
, Qnil
))
1230 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1231 frame
->display
.x
->border_pixel
);
1232 x_display_cursor (frame
, 1);
1236 frame_unhighlight (frame
)
1237 struct frame
*frame
;
1239 if (! EQ (Vx_no_window_manager
, Qnil
))
1240 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1241 frame
->display
.x
->border_tile
);
1242 x_display_cursor (frame
, 1);
1244 #else /* ! defined (HAVE_X11) */
1245 /* Dump the border-emphasis of frame F.
1246 If F is selected, this is a lining of the same color as the border,
1247 just within the border, occupying a portion of the internal border.
1248 If F is not selected, it is background in the same place.
1249 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1251 ALWAYS = 1 is used when a frame becomes selected or deselected.
1252 In that case, we also turn the cursor off and on again
1253 so it will appear in the proper shape (solid if selected; else hollow.) */
1256 dumpborder (f
, always
)
1260 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1261 int width
= PIXEL_WIDTH (f
);
1262 int height
= PIXEL_HEIGHT (f
);
1265 if (f
!= selected_frame
)
1270 pixel
= f
->display
.x
->background_pixel
;
1274 pixel
= f
->display
.x
->border_pixel
;
1277 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1278 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1279 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1281 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1285 x_display_cursor (f
, 1);
1287 #endif /* ! defined (HAVE_X11) */
1289 static void XTframe_rehighlight ();
1291 /* The focus has changed. Update the frames as necessary to reflect
1292 the new situation. Note that we can't change the selected frame
1293 here, because the lisp code we are interrupting might become confused.
1294 Each event gets marked with the frame in which it occured, so the
1295 lisp code can tell when the switch took place by examining the events. */
1298 x_new_focus_frame (frame
)
1299 struct frame
*frame
;
1301 struct frame
*old_focus
= x_focus_frame
;
1302 int events_enqueued
= 0;
1304 if (frame
!= x_focus_frame
)
1306 /* Set this before calling other routines, so that they see
1307 the correct value of x_focus_frame. */
1308 x_focus_frame
= frame
;
1310 if (old_focus
&& old_focus
->auto_lower
)
1311 x_lower_frame (old_focus
);
1314 selected_frame
= frame
;
1315 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1316 Lisp_Frame
, selected_frame
);
1317 Fselect_window (selected_frame
->selected_window
);
1318 choose_minibuf_frame ();
1321 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1322 x_raise_frame (x_focus_frame
);
1325 XTframe_rehighlight ();
1329 /* The focus has changed, or we have redirected a frame's focus to
1330 another frame (this happens when a frame uses a surrogate
1331 minibuffer frame). Shift the highlight as appropriate. */
1333 XTframe_rehighlight ()
1335 struct frame
*old_highlight
= x_highlight_frame
;
1340 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1341 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1343 if (! FRAME_LIVE_P (x_highlight_frame
))
1345 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1346 x_highlight_frame
= x_focus_frame
;
1350 x_highlight_frame
= 0;
1352 if (x_highlight_frame
!= old_highlight
)
1355 frame_unhighlight (old_highlight
);
1356 if (x_highlight_frame
)
1357 frame_highlight (x_highlight_frame
);
1361 /* Mouse clicks and mouse movement. Rah. */
1364 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1365 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1366 that the glyph at X, Y occupies, if BOUNDS != 0. */
1368 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1370 register unsigned int pix_x
, pix_y
;
1371 register int *x
, *y
;
1374 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1375 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1379 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1380 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1381 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1382 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1385 if (pix_x
< 0) pix_x
= 0;
1386 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1388 if (pix_y
< 0) pix_y
= 0;
1389 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1395 /* Any buttons grabbed. */
1396 unsigned int x_mouse_grabbed
;
1398 /* Which modifier keys are on which modifier bits?
1400 With each keystroke, X returns eight bits indicating which modifier
1401 keys were held down when the key was pressed. The interpretation
1402 of the top five modifier bits depends on what keys are attached
1403 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1406 x_meta_mod_mask is a mask containing the bits used for the meta key.
1407 It may have more than one bit set, if more than one modifier bit
1408 has meta keys on it. Basically, if EVENT is a KeyPress event,
1409 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1411 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1412 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1413 only be affected by the lock modifier bit if XK_Shift_Lock is in
1414 use; XK_Caps_Lock should only affect alphabetic keys. With this
1415 arrangement, the lock modifier should shift the character if
1416 (EVENT.state & x_shift_lock_mask) != 0. */
1417 static int x_meta_mod_mask
, x_shift_lock_mask
;
1419 /* These are like x_meta_mod_mask, but for different modifiers. */
1420 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1422 /* Initialize mode_switch_bit and modifier_meaning. */
1424 x_find_modifier_meanings ()
1426 int min_code
, max_code
;
1429 XModifierKeymap
*mods
;
1431 x_meta_mod_mask
= 0;
1432 x_shift_lock_mask
= 0;
1434 x_super_mod_mask
= 0;
1435 x_hyper_mod_mask
= 0;
1438 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1440 min_code
= x_current_display
->min_keycode
;
1441 max_code
= x_current_display
->max_keycode
;
1444 syms
= XGetKeyboardMapping (x_current_display
,
1445 min_code
, max_code
- min_code
+ 1,
1447 mods
= XGetModifierMapping (x_current_display
);
1449 /* Scan the modifier table to see which modifier bits the Meta and
1450 Alt keysyms are on. */
1452 int row
, col
; /* The row and column in the modifier table. */
1454 for (row
= 3; row
< 8; row
++)
1455 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1458 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1460 /* Are any of this keycode's keysyms a meta key? */
1464 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1466 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1472 x_meta_mod_mask
|= (1 << row
);
1477 x_alt_mod_mask
|= (1 << row
);
1482 x_hyper_mod_mask
|= (1 << row
);
1487 x_super_mod_mask
|= (1 << row
);
1491 /* Ignore this if it's not on the lock modifier. */
1492 if ((1 << row
) == LockMask
)
1493 x_shift_lock_mask
= LockMask
;
1501 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1502 if (! x_meta_mod_mask
)
1504 x_meta_mod_mask
= x_alt_mod_mask
;
1508 XFree ((char *) syms
);
1509 XFreeModifiermap (mods
);
1513 /* Convert between the modifier bits X uses and the modifier bits
1516 x_x_to_emacs_modifiers (state
)
1519 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1520 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1521 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1522 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1523 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1524 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1528 x_emacs_to_x_modifiers (state
)
1531 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1532 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1533 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1534 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1535 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1536 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1539 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1541 If the event is a button press, then note that we have grabbed
1545 construct_mouse_click (result
, event
, f
)
1546 struct input_event
*result
;
1547 XButtonEvent
*event
;
1550 /* Make the event type no_event; we'll change that when we decide
1552 result
->kind
= mouse_click
;
1553 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1554 result
->timestamp
= event
->time
;
1555 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1556 | (event
->type
== ButtonRelease
1560 /* Notice if the mouse is still grabbed. */
1561 if (event
->type
== ButtonPress
)
1563 if (! x_mouse_grabbed
)
1564 Vmouse_depressed
= Qt
;
1565 x_mouse_grabbed
|= (1 << event
->button
);
1567 else if (event
->type
== ButtonRelease
)
1569 x_mouse_grabbed
&= ~(1 << event
->button
);
1570 if (!x_mouse_grabbed
)
1571 Vmouse_depressed
= Qnil
;
1577 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1578 XFASTINT (result
->x
) = column
;
1579 XFASTINT (result
->y
) = row
;
1580 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1585 /* Mouse movement. Rah.
1587 In order to avoid asking for motion events and then throwing most
1588 of them away or busy-polling the server for mouse positions, we ask
1589 the server for pointer motion hints. This means that we get only
1590 one event per group of mouse movements. "Groups" are delimited by
1591 other kinds of events (focus changes and button clicks, for
1592 example), or by XQueryPointer calls; when one of these happens, we
1593 get another MotionNotify event the next time the mouse moves. This
1594 is at least as efficient as getting motion events when mouse
1595 tracking is on, and I suspect only negligibly worse when tracking
1598 The silly O'Reilly & Associates Nutshell guides barely document
1599 pointer motion hints at all (I think you have to infer how they
1600 work from an example), and the description of XQueryPointer doesn't
1601 mention that calling it causes you to get another motion hint from
1602 the server, which is very important. */
1604 /* Where the mouse was last time we reported a mouse event. */
1605 static FRAME_PTR last_mouse_frame
;
1606 static XRectangle last_mouse_glyph
;
1608 /* The scroll bar in which the last X motion event occurred.
1610 If the last X motion event occured in a scroll bar, we set this
1611 so XTmouse_position can know whether to report a scroll bar motion or
1614 If the last X motion event didn't occur in a scroll bar, we set this
1615 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1616 static Lisp_Object last_mouse_scroll_bar
;
1618 /* This is a hack. We would really prefer that XTmouse_position would
1619 return the time associated with the position it returns, but there
1620 doesn't seem to be any way to wrest the timestamp from the server
1621 along with the position query. So, we just keep track of the time
1622 of the last movement we received, and return that in hopes that
1623 it's somewhat accurate. */
1624 static Time last_mouse_movement_time
;
1626 /* Function to report a mouse movement to the mainstream Emacs code.
1627 The input handler calls this.
1629 We have received a mouse movement event, which is given in *event.
1630 If the mouse is over a different glyph than it was last time, tell
1631 the mainstream emacs code by setting mouse_moved. If not, ask for
1632 another motion event, so we can check again the next time it moves. */
1634 note_mouse_movement (frame
, event
)
1636 XMotionEvent
*event
;
1639 last_mouse_movement_time
= event
->time
;
1641 /* Has the mouse moved off the glyph it was on at the last sighting? */
1642 if (event
->x
< last_mouse_glyph
.x
1643 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1644 || event
->y
< last_mouse_glyph
.y
1645 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1648 last_mouse_scroll_bar
= Qnil
;
1652 /* It's on the same glyph. Call XQueryPointer so we'll get an
1653 event the next time the mouse moves and we can see if it's
1654 *still* on the same glyph. */
1657 XQueryPointer (event
->display
, event
->window
,
1658 (Window
*) &dummy
, (Window
*) &dummy
,
1659 &dummy
, &dummy
, &dummy
, &dummy
,
1660 (unsigned int *) &dummy
);
1664 static struct scroll_bar
*x_window_to_scroll_bar ();
1665 static void x_scroll_bar_report_motion ();
1667 /* Return the current position of the mouse.
1669 If the mouse movement started in a scroll bar, set *f, *bar_window,
1670 and *part to the frame, window, and scroll bar part that the mouse
1671 is over. Set *x and *y to the portion and whole of the mouse's
1672 position on the scroll bar.
1674 If the mouse movement started elsewhere, set *f to the frame the
1675 mouse is on, *bar_window to nil, and *x and *y to the character cell
1678 Set *time to the server timestamp for the time at which the mouse
1679 was at this position.
1681 This clears the mouse_moved flag, so we can wait for the next mouse
1682 movement. This also calls XQueryPointer, which will cause the
1683 server to give us another MotionNotify when the mouse moves
1687 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1689 Lisp_Object
*bar_window
;
1690 enum scroll_bar_part
*part
;
1692 unsigned long *time
;
1696 if (! NILP (last_mouse_scroll_bar
))
1697 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1703 Window dummy_window
;
1707 last_mouse_scroll_bar
= Qnil
;
1709 /* Figure out which root window we're on. */
1710 XQueryPointer (x_current_display
,
1711 DefaultRootWindow (x_current_display
),
1713 /* The root window which contains the pointer. */
1716 /* Trash which we can't trust if the pointer is on
1717 a different screen. */
1720 /* The position on that root window. */
1723 /* More trash we can't trust. */
1726 /* Modifier keys and pointer buttons, about which
1728 (unsigned int *) &dummy
);
1730 /* Now we have a position on the root; find the innermost window
1731 containing the pointer. */
1735 int parent_x
, parent_y
;
1740 XTranslateCoordinates (x_current_display
,
1742 /* From-window, to-window. */
1745 /* From-position, to-position. */
1746 root_x
, root_y
, &win_x
, &win_y
,
1759 /* Now we know that:
1760 win is the innermost window containing the pointer
1761 (XTC says it has no child containing the pointer),
1762 win_x and win_y are the pointer's position in it
1763 (XTC did this the last time through), and
1764 parent_x and parent_y are the pointer's position in win's parent.
1765 (They are what win_x and win_y were when win was child.
1766 If win is the root window, it has no parent, and
1767 parent_{x,y} are invalid, but that's okay, because we'll
1768 never use them in that case.) */
1770 /* Is win one of our frames? */
1771 *f
= x_window_to_frame (win
);
1773 /* If not, is it one of our scroll bars? */
1776 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1780 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1788 pixel_to_glyph_coords (*f
, win_x
, win_y
, &win_x
, &win_y
,
1793 XSET (*x
, Lisp_Int
, win_x
);
1794 XSET (*y
, Lisp_Int
, win_y
);
1795 *time
= last_mouse_movement_time
;
1803 #else /* ! defined (HAVE_X11) */
1804 #define XEvent XKeyPressedEvent
1805 #endif /* ! defined (HAVE_X11) */
1807 /* Scroll bar support. */
1809 /* Given an X window ID, find the struct scroll_bar which manages it.
1810 This can be called in GC, so we have to make sure to strip off mark
1812 static struct scroll_bar
*
1813 x_window_to_scroll_bar (window_id
)
1816 Lisp_Object tail
, frame
;
1818 for (tail
= Vframe_list
;
1819 XGCTYPE (tail
) == Lisp_Cons
;
1820 tail
= XCONS (tail
)->cdr
)
1822 Lisp_Object frame
= XCONS (tail
)->car
;
1823 Lisp_Object bar
, condemned
;
1825 /* All elements of Vframe_list should be frames. */
1826 if (XGCTYPE (frame
) != Lisp_Frame
)
1829 /* Scan this frame's scroll bar list for a scroll bar with the
1831 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1832 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1833 /* This trick allows us to search both the ordinary and
1834 condemned scroll bar lists with one loop. */
1835 ! GC_NILP (bar
) || (bar
= condemned
,
1838 bar
= XSCROLL_BAR(bar
)->next
)
1839 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1840 return XSCROLL_BAR (bar
);
1846 /* Open a new X window to serve as a scroll bar, and return the
1847 scroll bar vector for it. */
1848 static struct scroll_bar
*
1849 x_scroll_bar_create (window
, top
, left
, width
, height
)
1850 struct window
*window
;
1851 int top
, left
, width
, height
;
1853 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1854 struct scroll_bar
*bar
=
1855 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1860 XSetWindowAttributes a
;
1863 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1864 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1865 | ButtonMotionMask
| PointerMotionHintMask
1867 a
.cursor
= x_vertical_scroll_bar_cursor
;
1869 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1871 SET_SCROLL_BAR_X_WINDOW
1873 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1875 /* Position and size of scroll bar. */
1876 left
, top
, width
, height
,
1878 /* Border width, depth, class, and visual. */
1879 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1885 XSET (bar
->window
, Lisp_Window
, window
);
1886 XSET (bar
->top
, Lisp_Int
, top
);
1887 XSET (bar
->left
, Lisp_Int
, left
);
1888 XSET (bar
->width
, Lisp_Int
, width
);
1889 XSET (bar
->height
, Lisp_Int
, height
);
1890 XSET (bar
->start
, Lisp_Int
, 0);
1891 XSET (bar
->end
, Lisp_Int
, 0);
1892 bar
->dragging
= Qnil
;
1894 /* Add bar to its frame's list of scroll bars. */
1895 bar
->next
= FRAME_SCROLL_BARS (frame
);
1897 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
1898 if (! NILP (bar
->next
))
1899 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1901 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
1908 /* Draw BAR's handle in the proper position.
1909 If the handle is already drawn from START to END, don't bother
1910 redrawing it, unless REBUILD is non-zero; in that case, always
1911 redraw it. (REBUILD is handy for drawing the handle after expose
1914 Normally, we want to constrain the start and end of the handle to
1915 fit inside its rectangle, but if the user is dragging the scroll bar
1916 handle, we want to let them drag it down all the way, so that the
1917 bar's top is as far down as it goes; otherwise, there's no way to
1918 move to the very end of the buffer. */
1920 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1921 struct scroll_bar
*bar
;
1925 int dragging
= ! NILP (bar
->dragging
);
1926 Window w
= SCROLL_BAR_X_WINDOW (bar
);
1927 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1929 /* If the display is already accurate, do nothing. */
1931 && start
== XINT (bar
->start
)
1932 && end
== XINT (bar
->end
))
1938 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
1939 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
1940 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
1942 /* Make sure the values are reasonable, and try to preserve
1943 the distance between start and end. */
1945 int length
= end
- start
;
1949 else if (start
> top_range
)
1951 end
= start
+ length
;
1955 else if (end
> top_range
&& ! dragging
)
1959 /* Store the adjusted setting in the scroll bar. */
1960 XSET (bar
->start
, Lisp_Int
, start
);
1961 XSET (bar
->end
, Lisp_Int
, end
);
1963 /* Clip the end position, just for display. */
1964 if (end
> top_range
)
1967 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1968 below top positions, to make sure the handle is always at least
1969 that many pixels tall. */
1970 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
1972 /* Draw the empty space above the handle. Note that we can't clear
1973 zero-height areas; that means "clear to end of window." */
1975 XClearArea (x_current_display
, w
,
1977 /* x, y, width, height, and exposures. */
1978 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1979 VERTICAL_SCROLL_BAR_TOP_BORDER
,
1980 inside_width
, start
,
1983 /* Draw the handle itself. */
1984 XFillRectangle (x_current_display
, w
, gc
,
1986 /* x, y, width, height */
1987 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1988 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
1989 inside_width
, end
- start
);
1992 /* Draw the empty space below the handle. Note that we can't
1993 clear zero-height areas; that means "clear to end of window." */
1994 if (end
< inside_height
)
1995 XClearArea (x_current_display
, w
,
1997 /* x, y, width, height, and exposures. */
1998 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1999 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2000 inside_width
, inside_height
- end
,
2008 /* Move a scroll bar around on the screen, to accomodate changing
2009 window configurations. */
2011 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2012 struct scroll_bar
*bar
;
2013 int top
, left
, width
, height
;
2019 unsigned int mask
= 0;
2026 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2027 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2028 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2029 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2032 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2036 XSET (bar
->left
, Lisp_Int
, left
);
2037 XSET (bar
->top
, Lisp_Int
, top
);
2038 XSET (bar
->width
, Lisp_Int
, width
);
2039 XSET (bar
->height
, Lisp_Int
, height
);
2044 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2047 x_scroll_bar_remove (bar
)
2048 struct scroll_bar
*bar
;
2050 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2054 /* Destroy the window. */
2055 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2057 /* Disassociate this scroll bar from its window. */
2058 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2063 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2064 that we are displaying PORTION characters out of a total of WHOLE
2065 characters, starting at POSITION. If WINDOW has no scroll bar,
2068 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2069 struct window
*window
;
2070 int portion
, whole
, position
;
2072 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2073 int top
= XINT (window
->top
);
2074 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2075 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2077 /* Where should this scroll bar be, pixelwise? */
2078 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2079 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2080 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2081 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2083 struct scroll_bar
*bar
;
2085 /* Does the scroll bar exist yet? */
2086 if (NILP (window
->vertical_scroll_bar
))
2087 bar
= x_scroll_bar_create (window
,
2088 pixel_top
, pixel_left
,
2089 pixel_width
, pixel_height
);
2092 /* It may just need to be moved and resized. */
2093 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2094 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2097 /* Set the scroll bar's current state, unless we're currently being
2099 if (NILP (bar
->dragging
))
2102 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2105 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2108 int start
= (position
* top_range
) / whole
;
2109 int end
= ((position
+ portion
) * top_range
) / whole
;
2111 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2115 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2119 /* The following three hooks are used when we're doing a thorough
2120 redisplay of the frame. We don't explicitly know which scroll bars
2121 are going to be deleted, because keeping track of when windows go
2122 away is a real pain - "Can you say set-window-configuration, boys
2123 and girls?" Instead, we just assert at the beginning of redisplay
2124 that *all* scroll bars are to be removed, and then save a scroll bar
2125 from the fiery pit when we actually redisplay its window. */
2127 /* Arrange for all scroll bars on FRAME to be removed at the next call
2128 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2129 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2131 XTcondemn_scroll_bars (frame
)
2134 /* The condemned list should be empty at this point; if it's not,
2135 then the rest of Emacs isn't using the condemn/redeem/judge
2136 protocol correctly. */
2137 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2140 /* Move them all to the "condemned" list. */
2141 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2142 FRAME_SCROLL_BARS (frame
) = Qnil
;
2145 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2146 Note that WINDOW isn't necessarily condemned at all. */
2148 XTredeem_scroll_bar (window
)
2149 struct window
*window
;
2151 struct scroll_bar
*bar
;
2153 /* We can't redeem this window's scroll bar if it doesn't have one. */
2154 if (NILP (window
->vertical_scroll_bar
))
2157 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2159 /* Unlink it from the condemned list. */
2161 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2163 if (NILP (bar
->prev
))
2165 /* If the prev pointer is nil, it must be the first in one of
2167 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2168 /* It's not condemned. Everything's fine. */
2170 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2171 window
->vertical_scroll_bar
))
2172 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2174 /* If its prev pointer is nil, it must be at the front of
2175 one or the other! */
2179 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2181 if (! NILP (bar
->next
))
2182 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2184 bar
->next
= FRAME_SCROLL_BARS (f
);
2186 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2187 if (! NILP (bar
->next
))
2188 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2192 /* Remove all scroll bars on FRAME that haven't been saved since the
2193 last call to `*condemn_scroll_bars_hook'. */
2195 XTjudge_scroll_bars (f
)
2198 Lisp_Object bar
, next
;
2200 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2202 /* Clear out the condemned list now so we won't try to process any
2203 more events on the hapless scroll bars. */
2204 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2206 for (; ! NILP (bar
); bar
= next
)
2208 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2210 x_scroll_bar_remove (b
);
2213 b
->next
= b
->prev
= Qnil
;
2216 /* Now there should be no references to the condemned scroll bars,
2217 and they should get garbage-collected. */
2221 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2223 This may be called from a signal handler, so we have to ignore GC
2226 x_scroll_bar_expose (bar
, event
)
2227 struct scroll_bar
*bar
;
2230 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2231 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2235 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2237 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2238 XDrawRectangle (x_current_display
, w
, gc
,
2240 /* x, y, width, height */
2241 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2243 /* Draw another line to make the extra-thick border on the right. */
2244 XFillRectangle (x_current_display
, w
, gc
,
2246 /* x, y, width, height */
2247 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2252 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2253 is set to something other than no_event, it is enqueued.
2255 This may be called from a signal handler, so we have to ignore GC
2258 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2259 struct scroll_bar
*bar
;
2261 struct input_event
*emacs_event
;
2263 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2266 emacs_event
->kind
= scroll_bar_click
;
2267 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2268 emacs_event
->modifiers
=
2269 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2270 | (event
->type
== ButtonRelease
2273 emacs_event
->frame_or_window
= bar
->window
;
2274 emacs_event
->timestamp
= event
->xbutton
.time
;
2276 int internal_height
=
2277 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2279 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2280 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2283 if (y
> top_range
) y
= top_range
;
2285 if (y
< XINT (bar
->start
))
2286 emacs_event
->part
= scroll_bar_above_handle
;
2287 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2288 emacs_event
->part
= scroll_bar_handle
;
2290 emacs_event
->part
= scroll_bar_below_handle
;
2292 /* If the user has just clicked on the handle, record where they're
2294 if (event
->type
== ButtonPress
2295 && emacs_event
->part
== scroll_bar_handle
)
2296 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2298 /* If the user has released the handle, set it to its final position. */
2299 if (event
->type
== ButtonRelease
2300 && ! NILP (bar
->dragging
))
2302 int new_start
= y
- XINT (bar
->dragging
);
2303 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2305 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2306 bar
->dragging
= Qnil
;
2309 /* Clicks on the handle are always reported as occuring at the top of
2311 if (emacs_event
->part
== scroll_bar_handle
)
2312 emacs_event
->x
= bar
->start
;
2314 XSET (emacs_event
->x
, Lisp_Int
, y
);
2316 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2320 /* Handle some mouse motion while someone is dragging the scroll bar.
2322 This may be called from a signal handler, so we have to ignore GC
2325 x_scroll_bar_note_movement (bar
, event
)
2326 struct scroll_bar
*bar
;
2329 last_mouse_movement_time
= event
->xmotion
.time
;
2332 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2334 /* If we're dragging the bar, display it. */
2335 if (! GC_NILP (bar
->dragging
))
2337 /* Where should the handle be now? */
2338 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2340 if (new_start
!= XINT (bar
->start
))
2342 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2344 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2348 /* Call XQueryPointer so we'll get an event the next time the mouse
2349 moves and we can see *still* on the same position. */
2353 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2354 (Window
*) &dummy
, (Window
*) &dummy
,
2355 &dummy
, &dummy
, &dummy
, &dummy
,
2356 (unsigned int *) &dummy
);
2360 /* Return information to the user about the current position of the mouse
2361 on the scroll bar. */
2363 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2365 Lisp_Object
*bar_window
;
2366 enum scroll_bar_part
*part
;
2368 unsigned long *time
;
2370 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2375 /* Get the mouse's position relative to the scroll bar window, and
2378 Window dummy_window
;
2380 unsigned int dummy_mask
;
2382 if (! XQueryPointer (x_current_display
,
2383 SCROLL_BAR_X_WINDOW (bar
),
2385 /* Root, child, root x and root y. */
2386 &dummy_window
, &dummy_window
,
2387 &dummy_coord
, &dummy_coord
,
2389 /* Position relative to scroll bar. */
2392 /* Mouse buttons and modifier keys. */
2401 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2402 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2404 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2406 if (! NILP (bar
->dragging
))
2407 win_y
-= XINT (bar
->dragging
);
2411 if (win_y
> top_range
)
2414 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2415 *bar_window
= bar
->window
;
2417 if (! NILP (bar
->dragging
))
2418 *part
= scroll_bar_handle
;
2419 else if (win_y
< XINT (bar
->start
))
2420 *part
= scroll_bar_above_handle
;
2421 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2422 *part
= scroll_bar_handle
;
2424 *part
= scroll_bar_below_handle
;
2426 XSET (*x
, Lisp_Int
, win_y
);
2427 XSET (*y
, Lisp_Int
, top_range
);
2428 *time
= last_mouse_movement_time
;
2432 last_mouse_scroll_bar
= Qnil
;
2439 /* The screen has been cleared so we may have changed foreground or
2440 background colors, and the scroll bars may need to be redrawn.
2441 Clear out the scroll bars, and ask for expose events, so we can
2444 x_scroll_bar_clear (f
)
2449 for (bar
= FRAME_SCROLL_BARS (f
);
2450 XTYPE (bar
) == Lisp_Vector
;
2451 bar
= XSCROLL_BAR (bar
)->next
)
2452 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2458 /* The main X event-reading loop - XTread_socket. */
2460 /* Timestamp of enter window event. This is only used by XTread_socket,
2461 but we have to put it out here, since static variables within functions
2462 sometimes don't work. */
2463 static Time enter_timestamp
;
2465 /* This holds the state XLookupString needs to implement dead keys
2466 and other tricks known as "compose processing". _X Window System_
2467 says that a portable program can't use this, but Stephen Gildea assures
2468 me that letting the compiler initialize it to zeros will work okay.
2470 This must be defined outside of XTread_socket, for the same reasons
2471 given for enter_timestamp, above. */
2472 static XComposeStatus compose_status
;
2474 /* Communication with window managers. */
2475 Atom Xatom_wm_protocols
;
2477 /* Kinds of protocol things we may receive. */
2478 Atom Xatom_wm_take_focus
;
2479 Atom Xatom_wm_save_yourself
;
2480 Atom Xatom_wm_delete_window
;
2482 /* Other WM communication */
2483 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2484 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2486 /* Window manager communication. */
2487 Atom Xatom_wm_change_state
;
2489 /* Record the last 100 characters stored
2490 to help debug the loss-of-chars-during-GC problem. */
2492 short temp_buffer
[100];
2494 /* Read events coming from the X server.
2495 This routine is called by the SIGIO handler.
2496 We return as soon as there are no more events to be read.
2498 Events representing keys are stored in buffer BUFP,
2499 which can hold up to NUMCHARS characters.
2500 We return the number of characters stored into the buffer,
2501 thus pretending to be `read'.
2503 WAITP is nonzero if we should block until input arrives.
2504 EXPECTED is nonzero if the caller knows input is available. */
2507 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2509 register struct input_event
*bufp
;
2510 register int numchars
;
2517 int items_pending
; /* How many items are in the X queue. */
2524 if (interrupt_input_blocked
)
2526 interrupt_input_pending
= 1;
2530 interrupt_input_pending
= 0;
2534 abort (); /* Don't think this happens. */
2537 /* If available, Xlib uses FIOSNBIO to make the socket
2538 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2539 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2540 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2541 fcntl (fileno (stdin
), F_SETFL
, 0);
2542 #endif /* ! defined (FIOSNBIO) */
2546 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2548 extern int read_alarm_should_throw
;
2549 read_alarm_should_throw
= 1;
2550 XPeekEvent (XDISPLAY
&event
);
2551 read_alarm_should_throw
= 0;
2553 #endif /* HAVE_SELECT */
2556 while (XStuffPending () != 0)
2558 XNextEvent (XDISPLAY
&event
);
2566 if (event
.xclient
.message_type
== Xatom_wm_protocols
2567 && event
.xclient
.format
== 32)
2569 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2571 f
= x_window_to_frame (event
.xclient
.window
);
2573 x_focus_on_frame (f
);
2574 /* Not certain about handling scroll bars here */
2576 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2578 /* Save state modify the WM_COMMAND property to
2579 something which can reinstate us. This notifies
2580 the session manager, who's looking for such a
2581 PropertyNotify. Can restart processing when
2582 a keyboard or mouse event arrives. */
2587 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2589 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2597 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2600 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2604 new_x
= event
.xclient
.data
.s
[0];
2605 new_y
= event
.xclient
.data
.s
[1];
2610 #ifdef NEW_SELECTIONS
2611 case SelectionNotify
:
2612 x_handle_selection_notify (&event
);
2616 case SelectionClear
: /* Someone has grabbed ownership. */
2617 #ifdef NEW_SELECTIONS
2619 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2624 bufp
->kind
= selection_clear_event
;
2625 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2626 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2627 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2634 x_disown_selection (event
.xselectionclear
.window
,
2635 event
.xselectionclear
.selection
,
2636 event
.xselectionclear
.time
);
2640 case SelectionRequest
: /* Someone wants our selection. */
2641 #ifdef NEW_SELECTIONS
2643 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2648 bufp
->kind
= selection_request_event
;
2649 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2650 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2651 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2652 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2653 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2654 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2661 x_answer_selection_request (event
);
2665 case PropertyNotify
:
2666 #ifdef NEW_SELECTIONS
2667 x_handle_property_notify (&event
);
2669 /* If we're being told about a root window property, then it's
2670 a cut buffer change. */
2671 if (event
.xproperty
.window
== ROOT_WINDOW
)
2672 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2674 /* Otherwise, we're probably handling an incremental
2675 selection transmission. */
2678 /* If we were to do this synchronously, there'd be no worry
2679 about re-selecting. */
2680 x_send_incremental (event
);
2686 f
= x_window_to_frame (event
.xexpose
.window
);
2689 if (f
->async_visible
== 0)
2691 f
->async_visible
= 1;
2692 f
->async_iconified
= 0;
2693 SET_FRAME_GARBAGED (f
);
2697 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2698 event
.xexpose
.x
, event
.xexpose
.y
,
2699 event
.xexpose
.width
, event
.xexpose
.height
);
2704 struct scroll_bar
*bar
2705 = x_window_to_scroll_bar (event
.xexpose
.window
);
2708 x_scroll_bar_expose (bar
, &event
);
2712 case GraphicsExpose
: /* This occurs when an XCopyArea's
2713 source area was obscured or not
2715 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2719 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2720 event
.xgraphicsexpose
.width
,
2721 event
.xgraphicsexpose
.height
);
2725 case NoExpose
: /* This occurs when an XCopyArea's
2726 source area was completely
2729 #else /* ! defined (HAVE_X11) */
2731 if (event
.subwindow
!= 0)
2732 break; /* duplicate event */
2733 f
= x_window_to_frame (event
.window
);
2734 if (event
.window
== f
->display
.x
->icon_desc
)
2737 f
->async_iconified
= 1;
2739 if (event
.window
== FRAME_X_WINDOW (f
))
2741 /* Say must check all windows' needs_exposure flags. */
2742 expose_all_windows
= 1;
2743 f
->display
.x
->needs_exposure
= 1;
2744 f
->async_visible
= 1;
2749 if (event
.subwindow
!= 0)
2750 break; /* duplicate event */
2751 f
= x_window_to_frame (event
.window
);
2752 if (event
.window
== f
->display
.x
->icon_desc
)
2757 /* If window already needs full redraw, ignore this rectangle. */
2758 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2760 /* Put the event on the queue of rectangles to redraw. */
2761 if (enqueue_event (&event
, &x_expose_queue
))
2762 /* If it is full, we can't record the rectangle,
2763 so redraw this entire window. */
2765 /* Say must check all windows' needs_exposure flags. */
2766 expose_all_windows
= 1;
2767 f
->display
.x
->needs_exposure
= 1;
2772 /* This should happen only when we are expecting it,
2773 in x_read_exposes. */
2775 #endif /* ! defined (HAVE_X11) */
2779 f
= x_window_to_frame (event
.xunmap
.window
);
2780 if (f
) /* F may no longer exist if
2781 the frame was deleted. */
2783 /* While a frame is unmapped, display generation is
2784 disabled; you don't want to spend time updating a
2785 display that won't ever be seen. */
2786 f
->async_visible
= 0;
2791 f
= x_window_to_frame (event
.xmap
.window
);
2794 f
->async_visible
= 1;
2795 f
->async_iconified
= 0;
2797 /* wait_reading_process_input will notice this and update
2798 the frame's display structures. */
2799 SET_FRAME_GARBAGED (f
);
2803 /* Turn off processing if we become fully obscured. */
2804 case VisibilityNotify
:
2807 #else /* ! defined (HAVE_X11) */
2809 f
= x_window_to_frame (event
.window
);
2810 if (event
.window
== f
->display
.x
->icon_desc
)
2811 f
->async_iconified
= 0;
2812 if (event
.window
== FRAME_X_WINDOW (f
))
2813 f
->async_visible
= 0;
2815 #endif /* ! defined (HAVE_X11) */
2819 f
= x_window_to_frame (event
.xkey
.window
);
2824 char copy_buffer
[80];
2828 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
2829 modifiers
= event
.xkey
.state
;
2831 /* This will have to go some day... */
2833 /* make_lispy_event turns chars into control chars.
2834 Don't do it here because XLookupString is too eager. */
2835 event
.xkey
.state
&= ~ControlMask
;
2837 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2840 /* Strip off the vendor-specific keysym bit, and take a shot
2841 at recognizing the codes. HP servers have extra keysyms
2842 that fit into the MiscFunctionKey category. */
2847 if ((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
2848 || keysym
== XK_Delete
2849 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2850 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < 0xff80 */
2851 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2852 || IsFunctionKey (keysym
)) /* 0xffbe <= x < 0xffe1 */
2854 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2856 temp_buffer
[temp_index
++] = keysym
;
2857 bufp
->kind
= non_ascii_keystroke
;
2858 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff00);
2859 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2860 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
2861 bufp
->timestamp
= event
.xkey
.time
;
2866 else if (numchars
> nbytes
)
2870 for (i
= 0; i
< nbytes
; i
++)
2872 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2874 temp_buffer
[temp_index
++] = copy_buffer
[i
];
2875 bufp
->kind
= ascii_keystroke
;
2876 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2877 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2878 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
2879 bufp
->timestamp
= event
.xkey
.time
;
2893 #else /* ! defined (HAVE_X11) */
2896 register char *where_mapping
;
2898 f
= x_window_to_frame (event
.window
);
2899 /* Ignore keys typed on icon windows. */
2900 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2902 where_mapping
= XLookupMapping (&event
, &nbytes
);
2903 /* Nasty fix for arrow keys */
2904 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2906 switch (event
.detail
& 0xff)
2908 case KC_CURSOR_LEFT
:
2909 where_mapping
= "\002";
2911 case KC_CURSOR_RIGHT
:
2912 where_mapping
= "\006";
2915 where_mapping
= "\020";
2917 case KC_CURSOR_DOWN
:
2918 where_mapping
= "\016";
2923 if (numchars
- nbytes
> 0)
2927 for (i
= 0; i
< nbytes
; i
++)
2929 bufp
->kind
= ascii_keystroke
;
2930 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2931 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2932 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2940 #endif /* ! defined (HAVE_X11) */
2944 /* Here's a possible interpretation of the whole
2945 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2946 FocusIn event, you have to get a FocusOut event before you
2947 relinquish the focus. If you haven't received a FocusIn event,
2948 then a mere LeaveNotify is enough to free you. */
2951 f
= x_window_to_frame (event
.xcrossing
.window
);
2953 if (event
.xcrossing
.focus
) /* Entered Window */
2955 /* Avoid nasty pop/raise loops. */
2956 if (f
&& (!(f
->auto_raise
)
2958 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
2960 x_new_focus_frame (f
);
2961 enter_timestamp
= event
.xcrossing
.time
;
2964 else if (f
== x_focus_frame
)
2965 x_new_focus_frame (0);
2970 f
= x_window_to_frame (event
.xfocus
.window
);
2971 if (event
.xfocus
.detail
!= NotifyPointer
)
2972 x_focus_event_frame
= f
;
2974 x_new_focus_frame (f
);
2979 f
= x_window_to_frame (event
.xcrossing
.window
);
2981 if (event
.xcrossing
.focus
)
2983 if (! x_focus_event_frame
)
2984 x_new_focus_frame (0);
2986 x_new_focus_frame (f
);
2990 if (f
== x_focus_event_frame
)
2991 x_focus_event_frame
= 0;
2992 if (f
== x_focus_frame
)
2993 x_new_focus_frame (0);
2998 f
= x_window_to_frame (event
.xfocus
.window
);
2999 if (event
.xfocus
.detail
!= NotifyPointer
3000 && f
== x_focus_event_frame
)
3001 x_focus_event_frame
= 0;
3002 if (f
&& f
== x_focus_frame
)
3003 x_new_focus_frame (0);
3006 #else /* ! defined (HAVE_X11) */
3009 if ((event
.detail
& 0xFF) == 1)
3010 break; /* Coming from our own subwindow */
3011 if (event
.subwindow
!= 0)
3012 break; /* Entering our own subwindow. */
3015 f
= x_window_to_frame (event
.window
);
3018 x_new_focus_frame (f
);
3023 if ((event
.detail
& 0xFF) == 1)
3024 break; /* Entering our own subwindow */
3025 if (event
.subwindow
!= 0)
3026 break; /* Leaving our own subwindow. */
3029 if (x_focus_frame
== 0
3030 && x_input_frame
!= 0
3031 && x_input_frame
== x_window_to_frame (event
.window
)
3032 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3037 frame_unhighlight (f
);
3040 #endif /* ! defined (HAVE_X11) */
3045 f
= x_window_to_frame (event
.xmotion
.window
);
3047 note_mouse_movement (f
, &event
.xmotion
);
3050 struct scroll_bar
*bar
=
3051 x_window_to_scroll_bar (event
.xmotion
.window
);
3054 x_scroll_bar_note_movement (bar
, &event
);
3059 case ConfigureNotify
:
3060 f
= x_window_to_frame (event
.xconfigure
.window
);
3063 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3064 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3066 /* Even if the number of character rows and columns has
3067 not changed, the font size may have changed, so we need
3068 to check the pixel dimensions as well. */
3069 if (columns
!= f
->width
3070 || rows
!= f
->height
3071 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3072 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3074 change_frame_size (f
, rows
, columns
, 0, 1);
3075 SET_FRAME_GARBAGED (f
);
3078 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3079 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3080 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3081 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3088 /* If we decide we want to generate an event to be seen
3089 by the rest of Emacs, we put it here. */
3090 struct input_event emacs_event
;
3091 emacs_event
.kind
= no_event
;
3093 f
= x_window_to_frame (event
.xbutton
.window
);
3096 if (!x_focus_frame
|| (f
== x_focus_frame
))
3097 construct_mouse_click (&emacs_event
,
3102 struct scroll_bar
*bar
=
3103 x_window_to_scroll_bar (event
.xbutton
.window
);
3106 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3109 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3111 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3119 #else /* ! defined (HAVE_X11) */
3121 case ButtonReleased
:
3122 f
= x_window_to_frame (event
.window
);
3125 if (event
.window
== f
->display
.x
->icon_desc
)
3127 x_make_frame_visible (f
);
3129 if (warp_mouse_on_deiconify
)
3130 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3133 if (event
.window
== FRAME_X_WINDOW (f
))
3139 enqueue_event (&event
, &x_mouse_queue
);
3142 bufp
->kind
= ascii_keystroke
;
3143 bufp
->code
= (char) 'X' & 037; /* C-x */
3144 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3145 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3148 bufp
->kind
= ascii_keystroke
;
3149 bufp
->code
= (char) 0; /* C-@ */
3150 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3151 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3158 #endif /* ! defined (HAVE_X11) */
3162 case CirculateNotify
:
3164 case CirculateRequest
:
3167 #endif /* ! defined (HAVE_X11) */
3170 /* Someone has changed the keyboard mapping - update the
3172 switch (event
.xmapping
.request
)
3174 case MappingModifier
:
3175 x_find_modifier_meanings ();
3176 /* This is meant to fall through. */
3177 case MappingKeyboard
:
3178 XRefreshKeyboardMapping (&event
.xmapping
);
3189 if (expected
&& ! event_found
)
3191 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3192 there is an EOF condition; in other words, that X has died.
3193 Act as if there had been a hangup. */
3195 int fd
= ConnectionNumber (x_current_display
);
3198 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3200 && !XStuffPending ())
3201 kill (getpid (), SIGHUP
);
3203 #endif /* ! defined (HAVE_SELECT) */
3207 if (updating_frame
== 0)
3208 x_do_pending_expose ();
3216 /* Read and process only Expose events
3217 until we get an ExposeCopy event; then return.
3218 This is used in insert/delete line.
3219 We assume input is already blocked. */
3225 XKeyPressedEvent event
;
3229 /* while there are more events*/
3230 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3234 if (event
.subwindow
!= 0)
3235 break; /* duplicate event */
3236 f
= x_window_to_frame (event
.window
);
3237 if (event
.window
== f
->display
.x
->icon_desc
)
3242 if (event
.window
== FRAME_X_WINDOW (f
))
3244 expose_all_windows
= 1;
3245 f
->display
.x
->needs_exposure
= 1;
3251 if (event
.subwindow
!= 0)
3252 break; /* duplicate event */
3253 f
= x_window_to_frame (event
.window
);
3254 if (event
.window
== f
->display
.x
->icon_desc
)
3259 /* If window already needs full redraw, ignore this rectangle. */
3260 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3262 /* Put the event on the queue of rectangles to redraw. */
3263 if (enqueue_event (&event
, &x_expose_queue
))
3264 /* If it is full, we can't record the rectangle,
3265 so redraw this entire window. */
3267 /* Say must check all windows' needs_exposure flags. */
3268 expose_all_windows
= 1;
3269 f
->display
.x
->needs_exposure
= 1;
3278 #endif /* HAVE_X11 */
3281 /* Drawing the cursor. */
3284 /* Draw a hollow box cursor. Don't change the inside of the box. */
3290 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3291 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3292 int width
= FONT_WIDTH (f
->display
.x
->font
);
3293 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3296 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3297 f
->display
.x
->cursor_gc
,
3298 left
, top
, width
- 1, height
- 1);
3299 #else /* ! defined (HAVE_X11) */
3300 XPixSet (FRAME_X_WINDOW (f
),
3301 left
, top
, width
, 1,
3302 f
->display
.x
->cursor_pixel
);
3304 XPixSet (FRAME_X_WINDOW (f
),
3305 left
, top
, 1, height
,
3306 f
->display
.x
->cursor_pixel
);
3308 XPixSet (FRAME_X_WINDOW (f
),
3309 left
+width
-1, top
, 1, height
,
3310 f
->display
.x
->cursor_pixel
);
3312 XPixSet (FRAME_X_WINDOW (f
),
3313 left
, top
+height
-1, width
, 1,
3314 f
->display
.x
->cursor_pixel
);
3315 #endif /* ! defined (HAVE_X11) */
3318 /* Clear the cursor of frame F to background color,
3319 and mark the cursor as not shown.
3320 This is used when the text where the cursor is
3321 is about to be rewritten. */
3329 if (! FRAME_VISIBLE_P (f
)
3330 || f
->phys_cursor_x
< 0)
3334 x_display_cursor (f
, 0);
3335 #else /* ! defined (HAVE_X11) */
3336 XPixSet (FRAME_X_WINDOW (f
),
3337 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3338 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3339 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3340 f
->display
.x
->background_pixel
);
3341 #endif /* ! defined (HAVE_X11) */
3342 f
->phys_cursor_x
= -1;
3345 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3346 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3350 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3357 CHAR_TO_PIXEL_COL (f
, column
),
3358 CHAR_TO_PIXEL_ROW (f
, row
),
3359 &glyph
, 1, highlight
);
3363 x_display_bar_cursor (f
, on
)
3367 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3369 /* This is pointless on invisible frames, and dangerous on garbaged
3370 frames; in the latter case, the frame may be in the midst of
3371 changing its size, and curs_x and curs_y may be off the frame. */
3372 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3375 if (! on
&& f
->phys_cursor_x
< 0)
3378 /* If we're not updating, then we want to use the current frame's
3379 cursor position, not our local idea of where the cursor ought to be. */
3380 if (f
!= updating_frame
)
3382 curs_x
= FRAME_CURSOR_X (f
);
3383 curs_y
= FRAME_CURSOR_Y (f
);
3386 /* If there is anything wrong with the current cursor state, remove it. */
3387 if (f
->phys_cursor_x
>= 0
3389 || f
->phys_cursor_x
!= curs_x
3390 || f
->phys_cursor_y
!= curs_y
3391 || f
->display
.x
->current_cursor
!= bar_cursor
))
3393 /* Erase the cursor by redrawing the character underneath it. */
3394 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3395 f
->phys_cursor_glyph
,
3396 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3397 f
->phys_cursor_x
= -1;
3400 /* If we now need a cursor in the new place or in the new form, do it so. */
3402 && (f
->phys_cursor_x
< 0
3403 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3405 f
->phys_cursor_glyph
3406 = ((current_glyphs
->enable
[curs_y
]
3407 && curs_x
< current_glyphs
->used
[curs_y
])
3408 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3410 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3411 f
->display
.x
->cursor_gc
,
3412 CHAR_TO_PIXEL_COL (f
, curs_x
),
3413 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3414 1, FONT_HEIGHT (f
->display
.x
->font
));
3416 f
->phys_cursor_x
= curs_x
;
3417 f
->phys_cursor_y
= curs_y
;
3419 f
->display
.x
->current_cursor
= bar_cursor
;
3422 if (updating_frame
!= f
)
3427 /* Turn the displayed cursor of frame F on or off according to ON.
3428 If ON is nonzero, where to put the cursor is specified
3429 by F->cursor_x and F->cursor_y. */
3432 x_display_box_cursor (f
, on
)
3436 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3438 /* This is pointless on invisible frames, and dangerous on garbaged
3439 frames; in the latter case, the frame may be in the midst of
3440 changing its size, and curs_x and curs_y may be off the frame. */
3441 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3444 /* If cursor is off and we want it off, return quickly. */
3445 if (!on
&& f
->phys_cursor_x
< 0)
3448 /* If we're not updating, then we want to use the current frame's
3449 cursor position, not our local idea of where the cursor ought to be. */
3450 if (f
!= updating_frame
)
3452 curs_x
= FRAME_CURSOR_X (f
);
3453 curs_y
= FRAME_CURSOR_Y (f
);
3456 /* If cursor is currently being shown and we don't want it to be
3457 or it is in the wrong place,
3458 or we want a hollow box and it's not so, (pout!)
3460 if (f
->phys_cursor_x
>= 0
3462 || f
->phys_cursor_x
!= curs_x
3463 || f
->phys_cursor_y
!= curs_y
3464 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3465 && (f
!= x_highlight_frame
))))
3467 /* Erase the cursor by redrawing the character underneath it. */
3468 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3469 f
->phys_cursor_glyph
,
3470 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3471 f
->phys_cursor_x
= -1;
3474 /* If we want to show a cursor,
3475 or we want a box cursor and it's not so,
3476 write it in the right place. */
3478 && (f
->phys_cursor_x
< 0
3479 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3480 && f
== x_highlight_frame
)))
3482 f
->phys_cursor_glyph
3483 = ((current_glyphs
->enable
[curs_y
]
3484 && curs_x
< current_glyphs
->used
[curs_y
])
3485 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3487 if (f
!= x_highlight_frame
)
3490 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3494 x_draw_single_glyph (f
, curs_y
, curs_x
,
3495 f
->phys_cursor_glyph
, 2);
3496 f
->display
.x
->current_cursor
= filled_box_cursor
;
3499 f
->phys_cursor_x
= curs_x
;
3500 f
->phys_cursor_y
= curs_y
;
3503 if (updating_frame
!= f
)
3507 x_display_cursor (f
, on
)
3511 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3512 x_display_box_cursor (f
, on
);
3513 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3514 x_display_bar_cursor (f
, on
);
3516 /* Those are the only two we have implemented! */
3522 /* Refresh bitmap kitchen sink icon for frame F
3523 when we get an expose event for it. */
3529 /* Normally, the window manager handles this function. */
3530 #else /* ! defined (HAVE_X11) */
3533 if (f
->display
.x
->icon_bitmap_flag
)
3534 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3535 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3536 icon_bitmap
, GXcopy
, AllPlanes
);
3539 extern struct frame
*selected_frame
;
3540 struct Lisp_String
*str
;
3541 unsigned char *string
;
3544 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3546 if (f
->display
.x
->icon_label
!= string
)
3548 f
->display
.x
->icon_label
= string
;
3549 XChangeWindow (f
->display
.x
->icon_desc
,
3550 XQueryWidth (string
, icon_font_info
->id
) + 10,
3551 icon_font_info
->height
+ 10);
3554 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3555 str
->size
, icon_font_info
->id
,
3556 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3559 #endif /* ! defined (HAVE_X11) */
3562 /* Make the x-window of frame F use the gnu icon bitmap. */
3571 if (FRAME_X_WINDOW (f
) == 0)
3576 XFreePixmap (x_current_display
, icon_bitmap
);
3579 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3580 gnu_bits
, gnu_width
, gnu_height
);
3581 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3582 f
->display
.x
->icon_bitmap_flag
= 1;
3583 #else /* ! defined (HAVE_X11) */
3584 if (f
->display
.x
->icon_desc
)
3586 XClearIconWindow (FRAME_X_WINDOW (f
));
3587 XDestroyWindow (f
->display
.x
->icon_desc
);
3590 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3591 0, 0, sink_width
, sink_height
,
3592 2, WhitePixmap
, (Pixmap
) NULL
);
3594 if (icon_window
== 0)
3597 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3598 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3600 f
->display
.x
->icon_desc
= icon_window
;
3601 f
->display
.x
->icon_bitmap_flag
= 1;
3603 if (icon_bitmap
== 0)
3605 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3606 #endif /* ! defined (HAVE_X11) */
3612 /* Make the x-window of frame F use a rectangle with text. */
3615 x_text_icon (f
, icon_name
)
3623 char *X_DefaultValue
;
3627 #define WhitePixel 1
3628 #endif /* WhitePixel */
3631 #define BlackPixel 0
3632 #endif /* BlackPixel */
3633 #endif /* HAVE_X11 */
3635 if (FRAME_X_WINDOW (f
) == 0)
3640 f
->display
.x
->icon_label
= icon_name
;
3642 if (! f
->display
.x
->icon_label
)
3643 f
->display
.x
->icon_label
= " *emacs* ";
3646 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3647 (char *) f
->display
.x
->icon_label
);
3650 f
->display
.x
->icon_bitmap_flag
= 0;
3651 x_wm_set_icon_pixmap (f
, 0);
3652 #else /* ! defined (HAVE_X11) */
3653 if (icon_font_info
== 0)
3655 = XGetFont (XGetDefault (XDISPLAY
3656 (char *) XSTRING (Vinvocation_name
)->data
,
3659 if (f
->display
.x
->icon_desc
)
3661 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3662 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3666 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3668 if (! f
->display
.x
->icon_label
)
3669 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3671 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3672 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3673 f
->display
.x
->left_pos
,
3674 f
->display
.x
->top_pos
,
3675 width
+ 10, icon_font_info
->height
+ 10,
3676 2, BlackPixmap
, WhitePixmap
);
3678 if (icon_window
== 0)
3681 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3682 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3684 f
->display
.x
->icon_desc
= icon_window
;
3685 f
->display
.x
->icon_bitmap_flag
= 0;
3686 f
->display
.x
->icon_label
= 0;
3687 #endif /* ! defined (HAVE_X11) */
3692 /* Handling X errors. */
3694 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3695 X server's connection, or an error reported via the X protocol. */
3698 x_connection_closed ()
3703 shut_down_emacs (0);
3708 /* An X error handler which prints an error message and then kills
3709 Emacs. This is what's normally installed as Xlib's handler for
3712 x_error_quitter (display
, error
)
3718 /* Note that there is no real way portable across R3/R4 to get the
3719 original error handler. */
3721 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3722 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3723 buf
, error
->request_code
);
3725 /* While we're testing Emacs 19, we'll just dump core whenever we
3726 get an X error, so we can figure out why it happened. */
3729 x_connection_closed ();
3732 /* A handler for X IO errors which prints an error message and then
3733 kills Emacs. This is what is always installed as Xlib's handler
3736 x_io_error_quitter (display
)
3739 fprintf (stderr
, "Connection to X server %s lost.\n",
3740 XDisplayName (DisplayString (display
)));
3742 /* While we're testing Emacs 19, we'll just dump core whenever we
3743 get an X error, so we can figure out why it happened. */
3746 x_connection_closed ();
3749 /* A buffer for storing X error messages. */
3750 static char (*x_caught_error_message
)[200];
3752 /* An X error handler which stores the error message in
3753 x_caught_error_message. This is what's installed when
3754 x_catch_errors is in effect. */
3756 x_error_catcher (display
, error
)
3760 XGetErrorText (display
, error
->error_code
,
3761 *x_caught_error_message
, sizeof (*x_caught_error_message
));
3765 /* Begin trapping X errors.
3767 After calling this function, X protocol errors no longer cause
3768 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3770 Calling x_check_errors signals an Emacs error if an X error has
3771 occurred since the last call to x_catch_errors or x_check_errors.
3773 Calling x_uncatch_errors resumes the normal error handling. */
3775 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3780 /* Make sure any errors from previous requests have been dealt with. */
3781 XSync (x_current_display
, False
);
3783 /* Set up the error buffer. */
3784 x_caught_error_message
=
3785 (char (*)[]) xmalloc (sizeof (*x_caught_error_message
));
3786 (*x_caught_error_message
)[0] = '\0';
3788 /* Install our little error handler. */
3789 XHandleError (x_error_catcher
);
3792 /* If any X protocol errors have arrived since the last call to
3793 x_catch_errors or x_check_errors, signal an Emacs error using
3794 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3796 x_check_errors (format
)
3799 /* Make sure to catch any errors incurred so far. */
3800 XSync (x_current_display
, False
);
3802 if ((*x_caught_error_message
)[0])
3806 sprintf (buf
, format
, *x_caught_error_message
);
3807 xfree (x_caught_error_message
);
3809 x_uncatch_errors ();
3817 xfree (x_caught_error_message
);
3818 XHandleError (x_error_quitter
);
3822 static unsigned int x_wire_count
;
3825 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3830 /* Changing the font of the frame. */
3832 /* Set the font of the x-window specified by frame F
3833 to the font named NEWNAME. This is safe to use
3834 even before F has an actual x-window. */
3838 /* A table of all the fonts we have already loaded. */
3839 static XFontStruct
**x_font_table
;
3841 /* The current capacity of x_font_table. */
3842 static int x_font_table_size
;
3844 /* The number of fonts actually stored in x_font_table.
3845 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3846 0 <= n_fonts <= x_font_table_size. */
3849 x_new_font (f
, fontname
)
3851 register char *fontname
;
3855 int n_matching_fonts
;
3856 XFontStruct
*font_info
;
3859 /* Get a list of all the fonts that match this name. Once we
3860 have a list of matching fonts, we compare them against the fonts
3861 we already have by comparing font ids. */
3862 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3863 1024, &n_matching_fonts
,
3865 /* If the server couldn't find any fonts whose named matched fontname,
3866 return an error code. */
3867 if (n_matching_fonts
== 0)
3870 /* See if we've already loaded a matching font. */
3875 for (i
= 0; i
< n_fonts
; i
++)
3876 for (j
= 0; j
< n_matching_fonts
; j
++)
3877 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3885 /* If we have, just return it from the table. */
3887 f
->display
.x
->font
= x_font_table
[already_loaded
];
3889 /* Otherwise, load the font and add it to the table. */
3894 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
3898 /* Do we need to create the table? */
3899 if (x_font_table_size
== 0)
3901 x_font_table_size
= 16;
3903 = (XFontStruct
**) xmalloc (x_font_table_size
3904 * sizeof (x_font_table
[0]));
3906 /* Do we need to grow the table? */
3907 else if (n_fonts
>= x_font_table_size
)
3909 x_font_table_size
*= 2;
3911 = (XFontStruct
**) xrealloc (x_font_table
,
3913 * sizeof (x_font_table
[0])));
3916 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
3919 /* Free the information from XListFontsWithInfo. The data
3920 we actually retain comes from XLoadQueryFont. */
3921 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
3923 /* Now make the frame display the given font. */
3924 if (FRAME_X_WINDOW (f
) != 0)
3926 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
3927 f
->display
.x
->font
->fid
);
3928 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
3929 f
->display
.x
->font
->fid
);
3930 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
3931 f
->display
.x
->font
->fid
);
3932 init_frame_faces (f
);
3934 x_set_window_size (f
, f
->width
, f
->height
);
3939 #else /* ! defined (HAVE_X11) */
3940 x_new_font (f
, newname
)
3942 register char *newname
;
3947 temp
= XGetFont (newname
);
3948 if (temp
== (FONT_TYPE
*) 0)
3951 if (f
->display
.x
->font
)
3952 XLoseFont (f
->display
.x
->font
);
3954 f
->display
.x
->font
= temp
;
3956 if (FRAME_X_WINDOW (f
) != 0)
3957 x_set_window_size (f
, f
->width
, f
->height
);
3961 #endif /* ! defined (HAVE_X11) */
3963 /* X Window sizes and positions. */
3965 x_calc_absolute_position (f
)
3969 if (f
->display
.x
->left_pos
< 0)
3970 f
->display
.x
->left_pos
3971 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
3973 if (f
->display
.x
->top_pos
< 0)
3974 f
->display
.x
->top_pos
3975 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
3976 #else /* ! defined (HAVE_X11) */
3977 WINDOWINFO_TYPE parentinfo
;
3979 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
3981 if (f
->display
.x
->left_pos
< 0)
3982 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
3983 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
3985 if (f
->display
.x
->top_pos
< 0)
3986 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
3987 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
3988 #endif /* ! defined (HAVE_X11) */
3991 x_set_offset (f
, xoff
, yoff
)
3993 register int xoff
, yoff
;
3995 f
->display
.x
->top_pos
= yoff
;
3996 f
->display
.x
->left_pos
= xoff
;
3997 x_calc_absolute_position (f
);
4000 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4001 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4003 x_wm_set_size_hint (f
, 0);
4004 #endif /* ! defined (HAVE_X11) */
4008 /* Call this to change the size of frame F's x-window. */
4010 x_set_window_size (f
, cols
, rows
)
4014 int pixelwidth
, pixelheight
;
4019 check_frame_size (f
, &rows
, &cols
);
4020 f
->display
.x
->vertical_scroll_bar_extra
=
4021 (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4022 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
4024 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4025 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4028 x_wm_set_size_hint (f
, 0);
4029 #endif /* ! defined (HAVE_X11) */
4030 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4032 /* Now, strictly speaking, we can't be sure that this is accurate,
4033 but the window manager will get around to dealing with the size
4034 change request eventually, and we'll hear how it went when the
4035 ConfigureNotify event gets here.
4037 We could just not bother storing any of this information here,
4038 and let the ConfigureNotify event set everything up, but that
4039 might be kind of confusing to the lisp code, since size changes
4040 wouldn't be reported in the frame parameters until some random
4041 point in the future when the ConfigureNotify event arrives. */
4042 change_frame_size (f
, rows
, cols
, 0, 0);
4043 PIXEL_WIDTH (f
) = pixelwidth
;
4044 PIXEL_HEIGHT (f
) = pixelheight
;
4046 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4047 receive in the ConfigureNotify event; if we get what we asked
4048 for, then the event won't cause the screen to become garbaged, so
4049 we have to make sure to do it here. */
4050 SET_FRAME_GARBAGED (f
);
4057 x_set_resize_hint (f
)
4060 XSetResizeHint (FRAME_X_WINDOW (f
),
4061 2 * f
->display
.x
->internal_border_width
,
4062 2 * f
->display
.x
->internal_border_width
,
4063 FONT_WIDTH (f
->display
.x
->font
),
4064 FONT_HEIGHT (f
->display
.x
->font
));
4066 #endif /* HAVE_X11 */
4068 /* Mouse warping, focus shifting, raising and lowering. */
4070 x_set_mouse_position (f
, x
, y
)
4078 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4079 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4081 if (pix_x
< 0) pix_x
= 0;
4082 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4084 if (pix_y
< 0) pix_y
= 0;
4085 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4089 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4094 x_focus_on_frame (f
)
4099 /* I don't think that the ICCCM allows programs to do things like this
4100 without the interaction of the window manager. Whatever you end up
4101 doing with this code, do it to x_unfocus_frame too. */
4102 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4103 RevertToPointerRoot
, CurrentTime
);
4111 /* Look at the remarks in x_focus_on_frame. */
4112 if (x_focus_frame
== f
)
4113 XSetInputFocus (x_current_display
, PointerRoot
,
4114 RevertToPointerRoot
, CurrentTime
);
4118 #endif /* ! defined (HAVE_X11) */
4120 /* Raise frame F. */
4125 if (f
->async_visible
)
4128 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4134 /* Lower frame F. */
4139 if (f
->async_visible
)
4142 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4149 XTframe_raise_lower (f
, raise
)
4160 /* Change from withdrawn state to mapped state. */
4162 x_make_frame_visible (f
)
4169 if (! FRAME_VISIBLE_P (f
))
4172 if (! EQ (Vx_no_window_manager
, Qt
))
4173 x_wm_set_window_state (f
, NormalState
);
4175 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4176 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4177 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4178 #else /* ! defined (HAVE_X11) */
4179 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4180 if (f
->display
.x
->icon_desc
!= 0)
4181 XUnmapWindow (f
->display
.x
->icon_desc
);
4183 /* Handled by the MapNotify event for X11 */
4184 f
->async_visible
= 1;
4185 f
->async_iconified
= 0;
4187 /* NOTE: this may cause problems for the first frame. */
4189 #endif /* ! defined (HAVE_X11) */
4197 /* Change from mapped state to withdrawn state. */
4199 x_make_frame_invisible (f
)
4204 if (! f
->async_visible
)
4211 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4212 DefaultScreen (x_current_display
)))
4214 UNBLOCK_INPUT_RESIGNAL
;
4215 error ("can't notify window manager of window withdrawl");
4218 #else /* ! defined (HAVE_X11R4) */
4221 /* Tell the window manager what we're going to do. */
4222 if (! EQ (Vx_no_window_manager
, Qt
))
4226 unmap
.xunmap
.type
= UnmapNotify
;
4227 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4228 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4229 unmap
.xunmap
.from_configure
= False
;
4230 if (! XSendEvent (x_current_display
,
4231 DefaultRootWindow (x_current_display
),
4233 SubstructureRedirectMask
|SubstructureNotifyMask
,
4236 UNBLOCK_INPUT_RESIGNAL
;
4237 error ("can't notify window manager of withdrawal");
4241 /* Unmap the window ourselves. Cheeky! */
4242 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4244 #else /* ! defined (HAVE_X11) */
4246 XUnmapWindow (FRAME_X_WINDOW (f
));
4247 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4248 if (f
->display
.x
->icon_desc
!= 0)
4249 XUnmapWindow (f
->display
.x
->icon_desc
);
4251 #endif /* ! defined (HAVE_X11) */
4252 #endif /* ! defined (HAVE_X11R4) */
4258 /* Change window state from mapped to iconified. */
4265 if (f
->async_iconified
)
4271 /* Since we don't know which revision of X we're running, we'll use both
4272 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4274 /* X11R4: send a ClientMessage to the window manager using the
4275 WM_CHANGE_STATE type. */
4279 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4280 message
.xclient
.type
= ClientMessage
;
4281 message
.xclient
.message_type
= Xatom_wm_change_state
;
4282 message
.xclient
.format
= 32;
4283 message
.xclient
.data
.l
[0] = IconicState
;
4285 if (! XSendEvent (x_current_display
,
4286 DefaultRootWindow (x_current_display
),
4288 SubstructureRedirectMask
| SubstructureNotifyMask
,
4291 UNBLOCK_INPUT_RESIGNAL
;
4292 error ("Can't notify window manager of iconification.");
4296 /* X11R3: set the initial_state field of the window manager hints to
4298 x_wm_set_window_state (f
, IconicState
);
4300 f
->async_iconified
= 1;
4301 #else /* ! defined (HAVE_X11) */
4302 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4304 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4305 if (f
->display
.x
->icon_desc
!= 0)
4307 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4310 #endif /* ! defined (HAVE_X11) */
4316 /* Destroy the X window of frame F. */
4318 x_destroy_window (f
)
4323 if (f
->display
.x
->icon_desc
!= 0)
4324 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4325 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4326 free_frame_faces (f
);
4329 xfree (f
->display
.x
);
4331 if (f
== x_focus_frame
)
4333 if (f
== x_highlight_frame
)
4334 x_highlight_frame
= 0;
4339 /* Manage event queues for X10. */
4343 /* Manage event queues.
4345 This code is only used by the X10 support.
4347 We cannot leave events in the X queue and get them when we are ready
4348 because X does not provide a subroutine to get only a certain kind
4349 of event but not block if there are no queued events of that kind.
4351 Therefore, we must examine events as they come in and copy events
4352 of certain kinds into our private queues.
4354 All ExposeRegion events are put in x_expose_queue.
4355 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4358 /* Write the event *P_XREP into the event queue *QUEUE.
4359 If the queue is full, do nothing, but return nonzero. */
4362 enqueue_event (p_xrep
, queue
)
4363 register XEvent
*p_xrep
;
4364 register struct event_queue
*queue
;
4366 int newindex
= queue
->windex
+ 1;
4367 if (newindex
== EVENT_BUFFER_SIZE
)
4369 if (newindex
== queue
->rindex
)
4371 queue
->xrep
[queue
->windex
] = *p_xrep
;
4372 queue
->windex
= newindex
;
4376 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4377 If *QUEUE is empty, do nothing and return 0. */
4380 dequeue_event (p_xrep
, queue
)
4381 register XEvent
*p_xrep
;
4382 register struct event_queue
*queue
;
4384 if (queue
->windex
== queue
->rindex
)
4386 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4387 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4392 /* Return the number of events buffered in *QUEUE. */
4395 queue_event_count (queue
)
4396 register struct event_queue
*queue
;
4398 int tem
= queue
->windex
- queue
->rindex
;
4401 return EVENT_BUFFER_SIZE
+ tem
;
4404 /* Return nonzero if mouse input is pending. */
4407 mouse_event_pending_p ()
4409 return queue_event_count (&x_mouse_queue
);
4411 #endif /* HAVE_X11 */
4413 /* Setting window manager hints. */
4417 x_wm_set_size_hint (f
, prompting
)
4421 XSizeHints size_hints
;
4422 Window window
= FRAME_X_WINDOW (f
);
4424 size_hints
.flags
= PResizeInc
| PMinSize
| PMaxSize
;
4426 flexlines
= f
->height
;
4428 size_hints
.x
= f
->display
.x
->left_pos
;
4429 size_hints
.y
= f
->display
.x
->top_pos
;
4430 size_hints
.height
= PIXEL_HEIGHT (f
);
4431 size_hints
.width
= PIXEL_WIDTH (f
);
4432 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4433 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4434 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4435 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4438 int base_width
, base_height
;
4440 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4441 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4444 int min_rows
= 0, min_cols
= 0;
4445 check_frame_size (f
, &min_rows
, &min_cols
);
4447 /* The window manager uses the base width hints to calculate the
4448 current number of rows and columns in the frame while
4449 resizing; min_width and min_height aren't useful for this
4450 purpose, since they might not give the dimensions for a
4451 zero-row, zero-column frame.
4453 We use the base_width and base_height members if we have
4454 them; otherwise, we set the min_width and min_height members
4455 to the size for a zero x zero frame. */
4458 size_hints
.flags
|= PBaseSize
;
4459 size_hints
.base_width
= base_width
;
4460 size_hints
.base_height
= base_height
;
4461 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4462 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4464 size_hints
.min_width
= base_width
;
4465 size_hints
.min_height
= base_height
;
4472 size_hints
.flags
|= prompting
;
4475 XSizeHints hints
; /* Sometimes I hate X Windows... */
4477 XGetNormalHints (x_current_display
, window
, &hints
);
4478 if (hints
.flags
& PSize
)
4479 size_hints
.flags
|= PSize
;
4480 if (hints
.flags
& PPosition
)
4481 size_hints
.flags
|= PPosition
;
4482 if (hints
.flags
& USPosition
)
4483 size_hints
.flags
|= USPosition
;
4484 if (hints
.flags
& USSize
)
4485 size_hints
.flags
|= USSize
;
4489 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4491 XSetNormalHints (x_current_display
, window
, &size_hints
);
4495 /* Used for IconicState or NormalState */
4496 x_wm_set_window_state (f
, state
)
4500 Window window
= FRAME_X_WINDOW (f
);
4502 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4503 f
->display
.x
->wm_hints
.initial_state
= state
;
4505 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4508 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4512 Window window
= FRAME_X_WINDOW (f
);
4516 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4517 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4520 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4522 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4525 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4529 Window window
= FRAME_X_WINDOW (f
);
4531 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4532 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4533 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4535 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4539 /* Initialization. */
4542 x_term_init (display_name
)
4548 extern int old_fcntl_owner
;
4549 #endif /* ! defined (F_SETOWN) */
4551 x_focus_frame
= x_highlight_frame
= 0;
4553 x_current_display
= XOpenDisplay (display_name
);
4554 if (x_current_display
== 0)
4555 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4560 int hostname_size
= 256;
4562 hostname
= (char *) xmalloc (hostname_size
);
4565 XSetAfterFunction (x_current_display
, x_trace_wire
);
4568 /* Try to get the host name; if the buffer is too short, try
4569 again. Apparently, the only indication gethostname gives of
4570 whether the buffer was large enough is the presence or absence
4571 of a '\0' in the string. Eech. */
4574 gethostname (hostname
, hostname_size
- 1);
4575 hostname
[hostname_size
- 1] = '\0';
4577 /* Was the buffer large enough for gethostname to store the '\0'? */
4578 if (strlen (hostname
) < hostname_size
- 1)
4581 hostname_size
<<= 1;
4582 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4584 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4587 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
4590 /* Figure out which modifier bits mean what. */
4591 x_find_modifier_meanings ();
4593 /* Get the scroll bar cursor. */
4594 x_vertical_scroll_bar_cursor
4595 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4598 /* Watch for PropertyNotify events on the root window; we use them
4599 to figure out when to invalidate our cache of the cut buffers. */
4600 x_watch_cut_buffer_cache ();
4603 if (ConnectionNumber (x_current_display
) != 0)
4605 dup2 (ConnectionNumber (x_current_display
), 0);
4607 #ifndef SYSV_STREAMS
4608 /* Streams somehow keeps track of which descriptor number
4609 is being used to talk to X. So it is not safe to substitute
4610 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4611 close (ConnectionNumber (x_current_display
));
4612 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4613 * check the def of the macro;
4614 * it is a genuine lvalue */
4615 #endif /* SYSV_STREAMS */
4618 #endif /* ! defined (HAVE_X11) */
4621 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4622 #ifdef F_SETOWN_SOCK_NEG
4623 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4624 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4625 fcntl (0, F_SETOWN
, getpid ());
4626 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4627 #endif /* ! defined (F_SETOWN) */
4631 #endif /* ! defined (SIGIO) */
4633 /* Must use interrupt input because we cannot otherwise
4634 arrange for C-g to be noticed immediately.
4635 We cannot connect it to SIGINT. */
4636 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4638 expose_all_windows
= 0;
4640 clear_frame_hook
= XTclear_frame
;
4641 clear_end_of_line_hook
= XTclear_end_of_line
;
4642 ins_del_lines_hook
= XTins_del_lines
;
4643 change_line_highlight_hook
= XTchange_line_highlight
;
4644 insert_glyphs_hook
= XTinsert_glyphs
;
4645 write_glyphs_hook
= XTwrite_glyphs
;
4646 delete_glyphs_hook
= XTdelete_glyphs
;
4647 ring_bell_hook
= XTring_bell
;
4648 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4649 set_terminal_modes_hook
= XTset_terminal_modes
;
4650 update_begin_hook
= XTupdate_begin
;
4651 update_end_hook
= XTupdate_end
;
4652 set_terminal_window_hook
= XTset_terminal_window
;
4653 read_socket_hook
= XTread_socket
;
4654 cursor_to_hook
= XTcursor_to
;
4655 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4656 mouse_position_hook
= XTmouse_position
;
4657 frame_rehighlight_hook
= XTframe_rehighlight
;
4658 frame_raise_lower_hook
= XTframe_raise_lower
;
4659 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
4660 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
4661 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
4662 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
4664 scroll_region_ok
= 1; /* we'll scroll partial frames */
4665 char_ins_del_ok
= 0; /* just as fast to write the line */
4666 line_ins_del_ok
= 1; /* we'll just blt 'em */
4667 fast_clear_end_of_line
= 1; /* X does this well */
4668 memory_below_frame
= 0; /* we don't remember what scrolls
4672 /* Note that there is no real way portable across R3/R4 to get the
4673 original error handler. */
4674 XHandleError (x_error_quitter
);
4675 XHandleIOError (x_io_error_quitter
);
4677 /* Disable Window Change signals; they are handled by X events. */
4679 signal (SIGWINCH
, SIG_DFL
);
4680 #endif /* ! defined (SIGWINCH) */
4682 signal (SIGPIPE
, x_connection_closed
);
4688 staticpro (&last_mouse_scroll_bar
);
4690 #endif /* ! defined (HAVE_X11) */
4691 #endif /* ! defined (HAVE_X_WINDOWS) */