1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 #define NEW_SELECTIONS
30 /* On 4.3 these lose if they come after xterm.h. */
31 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
32 /* Putting these at the beginning seems to be standard for other .c files. */
41 #include "blockinput.h"
43 /* This may include sys/types.h, and that somehow loses
44 if this is not done before the other system files. */
46 #include <X11/cursorfont.h>
49 /* Load sys/types.h if not already loaded.
50 In some systems loading it twice is suicidal. */
52 #include <sys/types.h>
57 #include <sys/ioctl.h>
59 #else /* ! defined (BSD) */
63 #endif /* ! defined (BSD) */
73 #include <sys/param.h>
75 #include "dispextern.h"
76 #include "termhooks.h"
90 #define XMapWindow XMapRaised /* Raise them when mapping. */
91 #else /* ! defined (HAVE_X11) */
92 #include <X/Xkeyboard.h>
93 /*#include <X/Xproto.h> */
94 #endif /* ! defined (HAVE_X11) */
96 /* For sending Meta-characters. Do we need this? */
99 #define min(a,b) ((a)<(b) ? (a) : (b))
100 #define max(a,b) ((a)>(b) ? (a) : (b))
102 /* Nonzero means we must reprint all windows
103 because 1) we received an ExposeWindow event
104 or 2) we received too many ExposeRegion events to record.
106 This is never needed under X11. */
107 static int expose_all_windows
;
109 /* Nonzero means we must reprint all icon windows. */
111 static int expose_all_icons
;
114 /* ExposeRegion events, when received, are copied into this queue
115 for later processing. */
117 static struct event_queue x_expose_queue
;
119 /* ButtonPressed and ButtonReleased events, when received,
120 are copied into this queue for later processing. */
122 struct event_queue x_mouse_queue
;
123 #endif /* HAVE_X11 */
125 #if defined (SIGIO) && defined (FIONREAD)
126 int BLOCK_INPUT_mask
;
127 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
129 /* The id of a bitmap used for icon windows.
130 One such map is shared by all Emacs icon windows.
131 This is zero if we have not yet had a need to create the bitmap. */
133 static Bitmap icon_bitmap
;
135 /* Font used for text icons. */
137 static FONT_TYPE
*icon_font_info
;
139 /* Stuff for dealing with the main icon title. */
141 extern Lisp_Object Vcommand_line_args
;
142 char *hostname
, *x_id_name
;
144 /* This is the X connection that we are using. */
146 Display
*x_current_display
;
148 /* The cursor to use for vertical scroll bars on x_current_display. */
149 static Cursor x_vertical_scroll_bar_cursor
;
151 /* Frame being updated by update_frame. This is declared in term.c.
152 This is set by update_begin and looked at by all the
153 XT functions. It is zero while not inside an update.
154 In that case, the XT functions assume that `selected_frame'
155 is the frame to apply to. */
156 extern struct frame
*updating_frame
;
158 /* The frame (if any) which has the X window that has keyboard focus.
159 Zero if none. This is examined by Ffocus_frame in frame.c. Note
160 that a mere EnterNotify event can set this; if you need to know the
161 last frame specified in a FocusIn or FocusOut event, use
162 x_focus_event_frame. */
163 struct frame
*x_focus_frame
;
165 /* The last frame mentioned in a FocusIn or FocusOut event. This is
166 separate from x_focus_frame, because whether or not LeaveNotify
167 events cause us to lose focus depends on whether or not we have
168 received a FocusIn event for it. */
169 struct frame
*x_focus_event_frame
;
171 /* The frame which currently has the visual highlight, and should get
172 keyboard input (other sorts of input have the frame encoded in the
173 event). It points to the X focus frame's selected window's
174 frame. It differs from x_focus_frame when we're using a global
176 static struct frame
*x_highlight_frame
;
178 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
179 mouse is moved to inside of frame when frame is de-iconified. */
181 static int warp_mouse_on_deiconify
;
183 /* During an update, maximum vpos for ins/del line operations to affect. */
185 static int flexlines
;
187 /* During an update, nonzero if chars output now should be highlighted. */
189 static int highlight
;
191 /* Nominal cursor position -- where to draw output.
192 During an update, these are different from the cursor-box position. */
198 /* `t' if a mouse button is depressed. */
200 extern Lisp_Object Vmouse_depressed
;
202 /* Tells if a window manager is present or not. */
204 extern Lisp_Object Vx_no_window_manager
;
206 /* Timestamp that we requested selection data was made. */
207 extern Time requestor_time
;
209 /* ID of the window requesting selection data. */
210 extern Window requestor_window
;
212 /* Nonzero enables some debugging for the X interface code. */
215 #else /* ! defined (HAVE_X11) */
217 /* Bit patterns for the mouse cursor. */
219 short MouseCursor
[] = {
220 0x0000, 0x0008, 0x0018, 0x0038,
221 0x0078, 0x00f8, 0x01f8, 0x03f8,
222 0x07f8, 0x00f8, 0x00d8, 0x0188,
223 0x0180, 0x0300, 0x0300, 0x0000};
225 short MouseMask
[] = {
226 0x000c, 0x001c, 0x003c, 0x007c,
227 0x00fc, 0x01fc, 0x03fc, 0x07fc,
228 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
229 0x03cc, 0x0780, 0x0780, 0x0300};
231 static short grey_bits
[] = {
232 0x0005, 0x000a, 0x0005, 0x000a};
234 static Pixmap GreyPixmap
= 0;
235 #endif /* ! defined (HAVE_X11) */
237 /* From time to time we get info on an Emacs window, here. */
239 static WINDOWINFO_TYPE windowinfo
;
243 /* A mask of extra modifier bits to put into every keyboard char. */
244 extern int extra_keyboard_modifiers
;
246 extern Display
*XOpenDisplay ();
247 extern Window
XCreateWindow ();
249 extern Cursor
XCreateCursor ();
250 extern FONT_TYPE
*XOpenFont ();
252 static void flashback ();
255 static void dumpqueue ();
256 #endif /* HAVE_X11 */
259 static int XTcursor_to ();
260 static int XTclear_end_of_line ();
263 /* Starting and ending updates.
265 These hooks are called by update_frame at the beginning and end
266 of a frame update. We record in `updating_frame' the identity
267 of the frame being updated, so that the XT... functions do not
268 need to take a frame as argument. Most of the XT... functions
269 should never be called except during an update, the only exceptions
270 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
272 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
283 flexlines
= f
->height
;
289 #endif /* HAVE_X11 */
294 static void x_do_pending_expose ();
303 if (updating_frame
== 0
304 || updating_frame
!= f
)
310 x_do_pending_expose ();
311 #endif /* HAVE_X11 */
313 x_display_cursor (f
, 1);
319 /* External interface to control of standout mode.
320 Call this when about to modify line at position VPOS
321 and not change whether it is highlighted. */
323 XTreassert_line_highlight (new, vpos
)
329 /* Call this when about to modify line at position VPOS
330 and change whether it is highlighted. */
333 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
334 int new_highlight
, vpos
, first_unused_hpos
;
336 highlight
= new_highlight
;
337 XTcursor_to (vpos
, 0);
338 XTclear_end_of_line (updating_frame
->width
);
341 /* This is used when starting Emacs and when restarting after suspend.
342 When starting Emacs, no X window is mapped. And nothing must be done
343 to Emacs's own window if it is suspended (though that rarely happens). */
346 XTset_terminal_modes ()
350 /* This is called when exiting or suspending Emacs.
351 Exiting will make the X-windows go away, and suspending
352 requires no action. */
355 XTreset_terminal_modes ()
357 /* XTclear_frame (); */
360 /* Set the nominal cursor position of the frame.
361 This is where display update commands will take effect.
362 This does not affect the place where the cursor-box is displayed. */
365 XTcursor_to (row
, col
)
366 register int row
, col
;
374 if (updating_frame
== 0)
377 x_display_cursor (selected_frame
, 1);
383 /* Display a sequence of N glyphs found at GP.
384 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
385 HL is 1 if this text is highlighted, 2 if the cursor is on it.
387 FONT is the default font to use (for glyphs whose font-code is 0).
389 Since the display generation code is responsible for calling
390 compute_char_face and compute_glyph_face on everything it puts in
391 the display structure, we can assume that the face code on each
392 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
393 to which we can actually apply intern_face. */
396 /* This is the multi-face code. */
399 dumpglyphs (f
, left
, top
, gp
, n
, hl
)
402 register GLYPH
*gp
; /* Points to first GLYPH. */
403 register int n
; /* Number of glyphs to display. */
406 /* Holds characters to be displayed. */
407 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
408 register char *cp
; /* Steps through buf[]. */
409 register int tlen
= GLYPH_TABLE_LENGTH
;
410 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
411 Window window
= FRAME_X_WINDOW (f
);
415 /* Get the face-code of the next GLYPH. */
419 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
422 /* Find the run of consecutive glyphs with the same face-code.
423 Extract their character codes into BUF. */
428 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
429 if (GLYPH_FACE (g
) != cf
)
432 *cp
++ = GLYPH_CHAR (g
);
437 /* LEN gets the length of the run. */
440 /* Now output this run of chars, with the font and pixel values
441 determined by the face code CF. */
443 struct face
*face
= FRAME_DEFAULT_FACE (f
);
444 FONT_TYPE
*font
= FACE_FONT (face
);
445 GC gc
= FACE_GC (face
);
447 int gc_temporary
= 0;
449 /* First look at the face of the text itself. */
452 /* The face codes on the glyphs must be valid indices into the
453 frame's face table. */
454 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
455 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
459 face
= FRAME_MODE_LINE_FACE (f
);
461 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
462 font
= FACE_FONT (face
);
467 /* Then comes the distinction between modeline and normal text. */
472 face
= FRAME_MODE_LINE_FACE (f
);
473 font
= FACE_FONT (face
);
478 #define FACE_DEFAULT (~0)
480 /* Now override that if the cursor's on this character. */
485 || (int) face
->font
== FACE_DEFAULT
)
487 gc
= f
->display
.x
->cursor_gc
;
489 /* Cursor on non-default face: must merge. */
495 xgcv
.background
= f
->display
.x
->cursor_pixel
;
496 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
497 xgcv
.font
= face
->font
->fid
;
498 xgcv
.graphics_exposures
= 0;
499 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
500 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
503 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
504 XSetStipple (x_current_display
, gc
, face
->stipple
);
510 if ((int) font
== FACE_DEFAULT
)
511 font
= f
->display
.x
->font
;
513 XDrawImageString (x_current_display
, window
, gc
,
514 left
, top
+ FONT_BASE (font
), buf
, len
);
517 XFreeGC (x_current_display
, gc
);
519 /* We should probably check for XA_UNDERLINE_POSITION and
520 XA_UNDERLINE_THICKNESS properties on the font, but let's
521 just get the thing working, and come back to that. */
523 int underline_position
= 1;
525 if (font
->descent
<= underline_position
)
526 underline_position
= font
->descent
- 1;
529 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
533 + underline_position
),
534 len
* FONT_WIDTH (font
), 1);
537 left
+= len
* FONT_WIDTH (font
);
544 /* This is the old single-face code. */
547 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
550 register GLYPH
*gp
; /* Points to first GLYPH. */
551 register int n
; /* Number of glyphs to display. */
556 Window window
= FRAME_X_WINDOW (f
);
557 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
558 : (hl
? f
->display
.x
->reverse_gc
559 : f
->display
.x
->normal_gc
));
561 if (sizeof (GLYPH
) == sizeof (XChar2b
))
562 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
563 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
564 else if (sizeof (GLYPH
) == sizeof (unsigned char))
565 XDrawImageString (x_current_display
, window
, drawing_gc
,
566 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
568 /* What size of glyph ARE you using? And does X have a function to
574 /* Output some text at the nominal frame cursor position.
575 Advance the cursor over the text.
576 Output LEN glyphs at START.
578 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
579 controls the pixel values used for foreground and background. */
582 XTwrite_glyphs (start
, len
)
583 register GLYPH
*start
;
586 register int temp_length
;
596 /* If not within an update,
597 output at the frame's visible cursor. */
598 curs_x
= f
->cursor_x
;
599 curs_y
= f
->cursor_y
;
603 CHAR_TO_PIXEL_COL (f
, curs_x
),
604 CHAR_TO_PIXEL_ROW (f
, curs_y
),
605 start
, len
, highlight
);
607 /* If we drew on top of the cursor, note that it is turned off. */
608 if (curs_y
== f
->phys_cursor_y
609 && curs_x
<= f
->phys_cursor_x
610 && curs_x
+ len
> f
->phys_cursor_x
)
611 f
->phys_cursor_x
= -1;
613 if (updating_frame
== 0)
616 x_display_cursor (f
, 1);
625 /* Clear to the end of the line.
626 Erase the current text line from the nominal cursor position (inclusive)
627 to column FIRST_UNUSED (exclusive). The idea is that everything
628 from FIRST_UNUSED onward is already erased. */
631 XTclear_end_of_line (first_unused
)
632 register int first_unused
;
634 struct frame
*f
= updating_frame
;
640 if (curs_y
< 0 || curs_y
>= f
->height
)
642 if (first_unused
<= 0)
645 if (first_unused
>= f
->width
)
646 first_unused
= f
->width
;
650 /* Notice if the cursor will be cleared by this operation. */
651 if (curs_y
== f
->phys_cursor_y
652 && curs_x
<= f
->phys_cursor_x
653 && f
->phys_cursor_x
< first_unused
)
654 f
->phys_cursor_x
= -1;
657 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
658 CHAR_TO_PIXEL_COL (f
, curs_x
),
659 CHAR_TO_PIXEL_ROW (f
, curs_y
),
660 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
661 FONT_HEIGHT (f
->display
.x
->font
), False
);
663 #else /* ! defined (HAVE_X11) */
664 XPixSet (FRAME_X_WINDOW (f
),
665 CHAR_TO_PIXEL_COL (f
, curs_x
),
666 CHAR_TO_PIXEL_ROW (f
, curs_y
),
667 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
668 FONT_HEIGHT (f
->display
.x
->font
),
669 f
->display
.x
->background_pixel
);
670 #endif /* ! defined (HAVE_X11) */
679 struct frame
*f
= updating_frame
;
684 f
->phys_cursor_x
= -1; /* Cursor not visible. */
685 curs_x
= 0; /* Nominal cursor position is top left. */
690 XClear (FRAME_X_WINDOW (f
));
692 /* We have to clear the scroll bars, too. If we have changed
693 colors or something like that, then they should be notified. */
694 x_scroll_bar_clear (f
);
698 #endif /* HAVE_X11 */
704 /* Invert the middle quarter of the frame for .15 sec. */
706 /* We use the select system call to do the waiting, so we have to make sure
707 it's available. If it isn't, we just won't do visual bells. */
708 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
710 /* Subtract the `struct timeval' values X and Y,
711 storing the result in RESULT.
712 Return 1 if the difference is negative, otherwise 0. */
715 timeval_subtract (result
, x
, y
)
716 struct timeval
*result
, x
, y
;
718 /* Perform the carry for the later subtraction by updating y.
719 This is safer because on some systems
720 the tv_sec member is unsigned. */
721 if (x
.tv_usec
< y
.tv_usec
)
723 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
724 y
.tv_usec
-= 1000000 * nsec
;
727 if (x
.tv_usec
- y
.tv_usec
> 1000000)
729 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
730 y
.tv_usec
+= 1000000 * nsec
;
734 /* Compute the time remaining to wait. tv_usec is certainly positive. */
735 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
736 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
738 /* Return indication of whether the result should be considered negative. */
739 return x
.tv_sec
< y
.tv_sec
;
750 /* Create a GC that will use the GXxor function to flip foreground pixels
751 into background pixels. */
755 values
.function
= GXxor
;
756 values
.foreground
= (f
->display
.x
->foreground_pixel
757 ^ f
->display
.x
->background_pixel
);
759 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
760 GCFunction
| GCForeground
, &values
);
764 int width
= PIXEL_WIDTH (f
);
765 int height
= PIXEL_HEIGHT (f
);
767 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
768 width
/4, height
/4, width
/2, height
/2);
769 XFlush (x_current_display
);
772 struct timeval wakeup
, now
;
774 gettimeofday (&wakeup
, (struct timezone
*) 0);
776 /* Compute time to wait until, propagating carry from usecs. */
777 wakeup
.tv_usec
+= 150000;
778 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
779 wakeup
.tv_usec
%= 1000000;
781 /* Keep waiting until past the time wakeup. */
784 struct timeval timeout
;
786 gettimeofday (&timeout
, (struct timezone
*)0);
788 /* In effect, timeout = wakeup - timeout.
789 Break if result would be negative. */
790 if (timeval_subtract (&timeout
, wakeup
, timeout
))
793 /* Try to wait that long--but we might wake up sooner. */
794 select (0, 0, 0, 0, &timeout
);
798 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
799 width
/4, height
/4, width
/2, height
/2);
800 XFreeGC (x_current_display
, gc
);
801 XFlush (x_current_display
);
811 /* Make audible bell. */
814 #define XRINGBELL XBell(x_current_display, 0)
815 #else /* ! defined (HAVE_X11) */
816 #define XRINGBELL XFeep(0);
817 #endif /* ! defined (HAVE_X11) */
821 if (x_current_display
== 0)
824 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
826 XTflash (selected_frame
);
837 /* Insert and delete character.
838 These are not supposed to be used because we are supposed to turn
839 off the feature of using them. */
842 XTinsert_glyphs (start
, len
)
843 register char *start
;
856 /* Specify how many text lines, from the top of the window,
857 should be affected by insert-lines and delete-lines operations.
858 This, and those operations, are used only within an update
859 that is bounded by calls to XTupdate_begin and XTupdate_end. */
862 XTset_terminal_window (n
)
865 if (updating_frame
== 0)
868 if ((n
<= 0) || (n
> updating_frame
->height
))
869 flexlines
= updating_frame
->height
;
874 /* Perform an insert-lines operation.
875 Insert N lines at a vertical position curs_y. */
881 register int topregion
, bottomregion
;
882 register int length
, newtop
, mask
;
883 register struct frame
*f
= updating_frame
;
884 int intborder
= f
->display
.x
->internal_border_width
;
886 if (curs_y
>= flexlines
)
890 bottomregion
= flexlines
- (n
+ 1);
891 newtop
= topregion
+ n
;
892 length
= (bottomregion
- topregion
) + 1;
896 #endif /* HAVE_X11 */
898 if ((length
> 0) && (newtop
<= flexlines
))
901 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
902 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
903 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
904 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
905 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
906 CHAR_TO_PIXEL_ROW (f
, newtop
));
907 #else /* ! defined (HAVE_X11) */
908 XMoveArea (FRAME_X_WINDOW (f
),
909 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
910 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
911 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
912 length
* FONT_HEIGHT (f
->display
.x
->font
));
913 /* Now we must process any ExposeRegion events that occur
914 if the area being copied from is obscured.
915 We can't let it wait because further i/d operations
916 may want to copy this area to another area. */
918 #endif /* ! defined (HAVE_X11) */
921 newtop
= min (newtop
, (flexlines
- 1));
922 length
= newtop
- topregion
;
926 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
927 CHAR_TO_PIXEL_ROW (f
, topregion
),
928 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
929 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
930 #else /* ! defined (HAVE_X11) */
931 XPixSet (FRAME_X_WINDOW (f
),
933 CHAR_TO_PIXEL_ROW (f
, topregion
),
934 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
935 n
* FONT_HEIGHT (f
->display
.x
->font
),
936 f
->display
.x
->background_pixel
);
937 #endif /* ! defined (HAVE_X11) */
941 /* Perform a delete-lines operation, deleting N lines
942 at a vertical position curs_y. */
949 register struct frame
*f
= updating_frame
;
950 int intborder
= f
->display
.x
->internal_border_width
;
952 if (curs_y
>= flexlines
)
957 #endif /* HAVE_X11 */
959 if ((curs_y
+ n
) >= flexlines
)
961 if (flexlines
>= (curs_y
+ 1))
964 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
965 CHAR_TO_PIXEL_ROW (f
, curs_y
),
966 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
967 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
968 #else /* ! defined (HAVE_X11) */
969 XPixSet (FRAME_X_WINDOW (f
),
970 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
971 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
972 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
973 f
->display
.x
->background_pixel
);
974 #endif /* ! defined (HAVE_X11) */
980 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
981 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
983 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
984 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
985 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
986 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
987 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
989 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
990 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
991 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
992 #else /* ! defined (HAVE_X11) */
993 XMoveArea (FRAME_X_WINDOW (f
),
995 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
996 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
997 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
998 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
999 /* Now we must process any ExposeRegion events that occur
1000 if the area being copied from is obscured.
1001 We can't let it wait because further i/d operations
1002 may want to copy this area to another area. */
1004 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1005 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1006 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1007 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
1008 #endif /* ! defined (HAVE_X11) */
1012 /* Perform an insert-lines or delete-lines operation,
1013 inserting N lines or deleting -N lines at vertical position VPOS. */
1015 XTins_del_lines (vpos
, n
)
1018 if (updating_frame
== 0)
1021 /* Hide the cursor. */
1022 x_display_cursor (updating_frame
, 0);
1024 XTcursor_to (vpos
, 0);
1035 /* Support routines for exposure events. */
1036 static void clear_cursor ();
1038 /* Output into a rectangle of an X-window (for frame F)
1039 the characters in f->phys_lines that overlap that rectangle.
1040 TOP and LEFT are the position of the upper left corner of the rectangle.
1041 ROWS and COLS are the size of the rectangle. */
1044 dumprectangle (f
, left
, top
, cols
, rows
)
1046 register int left
, top
, cols
, rows
;
1048 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1049 int cursor_cleared
= 0;
1053 if (FRAME_GARBAGED_P (f
))
1056 /* Express rectangle as four edges, instead of position-and-size. */
1057 bottom
= top
+ rows
;
1058 right
= left
+ cols
;
1060 #ifndef HAVE_X11 /* Window manger does this for X11. */
1062 int intborder
= f
->display
.x
->internal_border_width
;
1064 /* If the rectangle includes any of the internal border area,
1065 redisplay the border emphasis. */
1066 if (top
< intborder
|| left
< intborder
1067 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1068 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1071 #endif /* HAVE_X11 Window manger does this for X11. */
1073 /* Convert rectangle edges in pixels to edges in chars.
1074 Round down for left and top, up for right and bottom. */
1075 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1076 left
= PIXEL_TO_CHAR_COL (f
, left
);
1077 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1078 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1079 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1080 right
= PIXEL_TO_CHAR_COL (f
, right
);
1082 /* Clip the rectangle to what can be visible. */
1087 if (right
> f
->width
)
1089 if (bottom
> f
->height
)
1092 /* Get size in chars of the rectangle. */
1093 cols
= right
- left
;
1094 rows
= bottom
- top
;
1096 /* If rectangle has zero area, return. */
1097 if (rows
<= 0) return;
1098 if (cols
<= 0) return;
1100 /* Turn off the cursor if it is in the rectangle.
1101 We will turn it back on afterward. */
1102 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1103 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1109 /* Display the text in the rectangle, one text line at a time. */
1111 for (y
= top
; y
< bottom
; y
++)
1113 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1115 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1119 CHAR_TO_PIXEL_COL (f
, left
),
1120 CHAR_TO_PIXEL_ROW (f
, y
),
1121 line
, min (cols
, active_frame
->used
[y
] - left
),
1122 active_frame
->highlight
[y
]);
1125 /* Turn the cursor on if we turned it off. */
1128 x_display_cursor (f
, 1);
1132 /* Process all queued ExposeRegion events. */
1138 XExposeRegionEvent r
;
1140 while (dequeue_event (&r
, &x_expose_queue
))
1142 struct frame
*f
= x_window_to_frame (r
.window
);
1143 if (f
->display
.x
->icon_desc
== r
.window
)
1146 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1150 #endif /* HAVE_X11 */
1152 /* Process all expose events that are pending, for X10.
1153 Redraws the cursor if necessary on any frame that
1154 is not in the process of being updated with update_frame. */
1158 x_do_pending_expose ()
1162 Lisp_Object tail
, frame
;
1164 if (expose_all_windows
)
1166 expose_all_windows
= 0;
1167 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1169 register int temp_width
, temp_height
;
1172 frame
= XCONS (tail
)->car
;
1173 if (XGCTYPE (frame
) != Lisp_Frame
)
1176 if (! FRAME_X_P (f
))
1178 if (!f
->async_visible
)
1180 if (!f
->display
.x
->needs_exposure
)
1183 intborder
= f
->display
.x
->internal_border_width
;
1186 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1187 temp_width
= ((windowinfo
.width
- 2 * intborder
1188 - f
->display
.x
->v_scroll_bar_width
)
1189 / FONT_WIDTH (f
->display
.x
->font
));
1190 temp_height
= ((windowinfo
.height
- 2 * intborder
1191 - f
->display
.x
->h_scroll_bar_height
)
1192 / FONT_HEIGHT (f
->display
.x
->font
));
1193 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1195 change_frame_size (f
, max (1, temp_height
),
1196 max (1, temp_width
), 0, 1);
1197 x_resize_scroll_bars (f
);
1199 f
->display
.x
->left_pos
= windowinfo
.x
;
1200 f
->display
.x
->top_pos
= windowinfo
.y
;
1201 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1205 f
->display
.x
->needs_exposure
= 0;
1206 if (updating_frame
!= f
)
1207 x_display_cursor (f
, 1);
1212 /* Handle any individual-rectangle expose events queued
1213 for various windows. */
1216 #else /* ! defined (HAVE_X11) */
1218 #endif /* ! defined (HAVE_X11) */
1224 frame_highlight (frame
)
1225 struct frame
*frame
;
1227 if (! EQ (Vx_no_window_manager
, Qnil
))
1228 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1229 frame
->display
.x
->border_pixel
);
1230 x_display_cursor (frame
, 1);
1234 frame_unhighlight (frame
)
1235 struct frame
*frame
;
1237 if (! EQ (Vx_no_window_manager
, Qnil
))
1238 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1239 frame
->display
.x
->border_tile
);
1240 x_display_cursor (frame
, 1);
1242 #else /* ! defined (HAVE_X11) */
1243 /* Dump the border-emphasis of frame F.
1244 If F is selected, this is a lining of the same color as the border,
1245 just within the border, occupying a portion of the internal border.
1246 If F is not selected, it is background in the same place.
1247 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1249 ALWAYS = 1 is used when a frame becomes selected or deselected.
1250 In that case, we also turn the cursor off and on again
1251 so it will appear in the proper shape (solid if selected; else hollow.) */
1254 dumpborder (f
, always
)
1258 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1259 int width
= PIXEL_WIDTH (f
);
1260 int height
= PIXEL_HEIGHT (f
);
1263 if (f
!= selected_frame
)
1268 pixel
= f
->display
.x
->background_pixel
;
1272 pixel
= f
->display
.x
->border_pixel
;
1275 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1276 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1277 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1279 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1283 x_display_cursor (f
, 1);
1285 #endif /* ! defined (HAVE_X11) */
1287 static void XTframe_rehighlight ();
1289 /* The focus has changed. Update the frames as necessary to reflect
1290 the new situation. Note that we can't change the selected frame
1291 here, because the lisp code we are interrupting might become confused.
1292 Each event gets marked with the frame in which it occurred, so the
1293 lisp code can tell when the switch took place by examining the events. */
1296 x_new_focus_frame (frame
)
1297 struct frame
*frame
;
1299 struct frame
*old_focus
= x_focus_frame
;
1300 int events_enqueued
= 0;
1302 if (frame
!= x_focus_frame
)
1304 /* Set this before calling other routines, so that they see
1305 the correct value of x_focus_frame. */
1306 x_focus_frame
= frame
;
1308 if (old_focus
&& old_focus
->auto_lower
)
1309 x_lower_frame (old_focus
);
1312 selected_frame
= frame
;
1313 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1314 Lisp_Frame
, selected_frame
);
1315 Fselect_window (selected_frame
->selected_window
);
1316 choose_minibuf_frame ();
1319 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1320 x_raise_frame (x_focus_frame
);
1323 XTframe_rehighlight ();
1327 /* The focus has changed, or we have redirected a frame's focus to
1328 another frame (this happens when a frame uses a surrogate
1329 minibuffer frame). Shift the highlight as appropriate. */
1331 XTframe_rehighlight ()
1333 struct frame
*old_highlight
= x_highlight_frame
;
1338 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1339 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1341 if (! FRAME_LIVE_P (x_highlight_frame
))
1343 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1344 x_highlight_frame
= x_focus_frame
;
1348 x_highlight_frame
= 0;
1350 if (x_highlight_frame
!= old_highlight
)
1353 frame_unhighlight (old_highlight
);
1354 if (x_highlight_frame
)
1355 frame_highlight (x_highlight_frame
);
1359 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1361 /* Which modifier keys are on which modifier bits?
1363 With each keystroke, X returns eight bits indicating which modifier
1364 keys were held down when the key was pressed. The interpretation
1365 of the top five modifier bits depends on what keys are attached
1366 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1369 x_meta_mod_mask is a mask containing the bits used for the meta key.
1370 It may have more than one bit set, if more than one modifier bit
1371 has meta keys on it. Basically, if EVENT is a KeyPress event,
1372 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1374 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1375 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1376 only be affected by the lock modifier bit if XK_Shift_Lock is in
1377 use; XK_Caps_Lock should only affect alphabetic keys. With this
1378 arrangement, the lock modifier should shift the character if
1379 (EVENT.state & x_shift_lock_mask) != 0. */
1380 static int x_meta_mod_mask
, x_shift_lock_mask
;
1382 /* These are like x_meta_mod_mask, but for different modifiers. */
1383 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1385 /* Initialize mode_switch_bit and modifier_meaning. */
1387 x_find_modifier_meanings ()
1389 int min_code
, max_code
;
1392 XModifierKeymap
*mods
;
1394 x_meta_mod_mask
= 0;
1395 x_shift_lock_mask
= 0;
1397 x_super_mod_mask
= 0;
1398 x_hyper_mod_mask
= 0;
1401 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1403 min_code
= x_current_display
->min_keycode
;
1404 max_code
= x_current_display
->max_keycode
;
1407 syms
= XGetKeyboardMapping (x_current_display
,
1408 min_code
, max_code
- min_code
+ 1,
1410 mods
= XGetModifierMapping (x_current_display
);
1412 /* Scan the modifier table to see which modifier bits the Meta and
1413 Alt keysyms are on. */
1415 int row
, col
; /* The row and column in the modifier table. */
1417 for (row
= 3; row
< 8; row
++)
1418 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1421 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1423 /* Are any of this keycode's keysyms a meta key? */
1427 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1429 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1435 x_meta_mod_mask
|= (1 << row
);
1440 x_alt_mod_mask
|= (1 << row
);
1445 x_hyper_mod_mask
|= (1 << row
);
1450 x_super_mod_mask
|= (1 << row
);
1454 /* Ignore this if it's not on the lock modifier. */
1455 if ((1 << row
) == LockMask
)
1456 x_shift_lock_mask
= LockMask
;
1464 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1465 if (! x_meta_mod_mask
)
1467 x_meta_mod_mask
= x_alt_mod_mask
;
1471 /* If some keys are both alt and meta,
1472 make them just meta, not alt. */
1473 if (x_alt_mod_mask
& x_meta_mod_mask
)
1475 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1478 XFree ((char *) syms
);
1479 XFreeModifiermap (mods
);
1483 /* Convert between the modifier bits X uses and the modifier bits
1486 x_x_to_emacs_modifiers (state
)
1489 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1490 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1491 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1492 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1493 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1494 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1498 x_emacs_to_x_modifiers (state
)
1501 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1502 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1503 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1504 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1505 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1506 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1509 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1510 return as a function key. If you add a keysym to this, you should
1511 make sure that the tables make_lispy_event uses contain a suitable
1514 x_is_vendor_fkey (sym
)
1519 || (sym
== DXK_Remove
)
1525 /* Mouse clicks and mouse movement. Rah. */
1528 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1529 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1530 that the glyph at X, Y occupies, if BOUNDS != 0. */
1532 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1534 register unsigned int pix_x
, pix_y
;
1535 register int *x
, *y
;
1538 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1539 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1543 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1544 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1545 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1546 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1549 if (pix_x
< 0) pix_x
= 0;
1550 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1552 if (pix_y
< 0) pix_y
= 0;
1553 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1559 /* Any buttons grabbed. */
1560 unsigned int x_mouse_grabbed
;
1562 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1564 If the event is a button press, then note that we have grabbed
1568 construct_mouse_click (result
, event
, f
)
1569 struct input_event
*result
;
1570 XButtonEvent
*event
;
1573 /* Make the event type no_event; we'll change that when we decide
1575 result
->kind
= mouse_click
;
1576 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1577 result
->timestamp
= event
->time
;
1578 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1579 | (event
->type
== ButtonRelease
1583 /* Notice if the mouse is still grabbed. */
1584 if (event
->type
== ButtonPress
)
1586 if (! x_mouse_grabbed
)
1587 Vmouse_depressed
= Qt
;
1588 x_mouse_grabbed
|= (1 << event
->button
);
1590 else if (event
->type
== ButtonRelease
)
1592 x_mouse_grabbed
&= ~(1 << event
->button
);
1593 if (!x_mouse_grabbed
)
1594 Vmouse_depressed
= Qnil
;
1600 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1601 XFASTINT (result
->x
) = column
;
1602 XFASTINT (result
->y
) = row
;
1603 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1608 /* Mouse movement. Rah.
1610 In order to avoid asking for motion events and then throwing most
1611 of them away or busy-polling the server for mouse positions, we ask
1612 the server for pointer motion hints. This means that we get only
1613 one event per group of mouse movements. "Groups" are delimited by
1614 other kinds of events (focus changes and button clicks, for
1615 example), or by XQueryPointer calls; when one of these happens, we
1616 get another MotionNotify event the next time the mouse moves. This
1617 is at least as efficient as getting motion events when mouse
1618 tracking is on, and I suspect only negligibly worse when tracking
1621 The silly O'Reilly & Associates Nutshell guides barely document
1622 pointer motion hints at all (I think you have to infer how they
1623 work from an example), and the description of XQueryPointer doesn't
1624 mention that calling it causes you to get another motion hint from
1625 the server, which is very important. */
1627 /* Where the mouse was last time we reported a mouse event. */
1628 static FRAME_PTR last_mouse_frame
;
1629 static XRectangle last_mouse_glyph
;
1631 /* The scroll bar in which the last X motion event occurred.
1633 If the last X motion event occurred in a scroll bar, we set this
1634 so XTmouse_position can know whether to report a scroll bar motion or
1637 If the last X motion event didn't occur in a scroll bar, we set this
1638 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1639 static Lisp_Object last_mouse_scroll_bar
;
1641 /* This is a hack. We would really prefer that XTmouse_position would
1642 return the time associated with the position it returns, but there
1643 doesn't seem to be any way to wrest the timestamp from the server
1644 along with the position query. So, we just keep track of the time
1645 of the last movement we received, and return that in hopes that
1646 it's somewhat accurate. */
1647 static Time last_mouse_movement_time
;
1649 /* Function to report a mouse movement to the mainstream Emacs code.
1650 The input handler calls this.
1652 We have received a mouse movement event, which is given in *event.
1653 If the mouse is over a different glyph than it was last time, tell
1654 the mainstream emacs code by setting mouse_moved. If not, ask for
1655 another motion event, so we can check again the next time it moves. */
1657 note_mouse_movement (frame
, event
)
1659 XMotionEvent
*event
;
1662 last_mouse_movement_time
= event
->time
;
1664 /* Has the mouse moved off the glyph it was on at the last sighting? */
1665 if (event
->x
< last_mouse_glyph
.x
1666 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1667 || event
->y
< last_mouse_glyph
.y
1668 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1671 last_mouse_scroll_bar
= Qnil
;
1675 /* It's on the same glyph. Call XQueryPointer so we'll get an
1676 event the next time the mouse moves and we can see if it's
1677 *still* on the same glyph. */
1680 XQueryPointer (event
->display
, event
->window
,
1681 (Window
*) &dummy
, (Window
*) &dummy
,
1682 &dummy
, &dummy
, &dummy
, &dummy
,
1683 (unsigned int *) &dummy
);
1687 static struct scroll_bar
*x_window_to_scroll_bar ();
1688 static void x_scroll_bar_report_motion ();
1690 /* Return the current position of the mouse.
1692 If the mouse movement started in a scroll bar, set *f, *bar_window,
1693 and *part to the frame, window, and scroll bar part that the mouse
1694 is over. Set *x and *y to the portion and whole of the mouse's
1695 position on the scroll bar.
1697 If the mouse movement started elsewhere, set *f to the frame the
1698 mouse is on, *bar_window to nil, and *x and *y to the character cell
1701 Set *time to the server timestamp for the time at which the mouse
1702 was at this position.
1704 Don't store anything if we don't have a valid set of values to report.
1706 This clears the mouse_moved flag, so we can wait for the next mouse
1707 movement. This also calls XQueryPointer, which will cause the
1708 server to give us another MotionNotify when the mouse moves
1712 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1714 Lisp_Object
*bar_window
;
1715 enum scroll_bar_part
*part
;
1717 unsigned long *time
;
1723 if (! NILP (last_mouse_scroll_bar
))
1724 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1730 Window dummy_window
;
1734 last_mouse_scroll_bar
= Qnil
;
1736 /* Figure out which root window we're on. */
1737 XQueryPointer (x_current_display
,
1738 DefaultRootWindow (x_current_display
),
1740 /* The root window which contains the pointer. */
1743 /* Trash which we can't trust if the pointer is on
1744 a different screen. */
1747 /* The position on that root window. */
1750 /* More trash we can't trust. */
1753 /* Modifier keys and pointer buttons, about which
1755 (unsigned int *) &dummy
);
1757 /* Now we have a position on the root; find the innermost window
1758 containing the pointer. */
1762 int parent_x
, parent_y
;
1767 XTranslateCoordinates (x_current_display
,
1769 /* From-window, to-window. */
1772 /* From-position, to-position. */
1773 root_x
, root_y
, &win_x
, &win_y
,
1786 /* Now we know that:
1787 win is the innermost window containing the pointer
1788 (XTC says it has no child containing the pointer),
1789 win_x and win_y are the pointer's position in it
1790 (XTC did this the last time through), and
1791 parent_x and parent_y are the pointer's position in win's parent.
1792 (They are what win_x and win_y were when win was child.
1793 If win is the root window, it has no parent, and
1794 parent_{x,y} are invalid, but that's okay, because we'll
1795 never use them in that case.) */
1797 /* Is win one of our frames? */
1798 f1
= x_window_to_frame (win
);
1800 /* If not, is it one of our scroll bars? */
1803 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1807 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1815 /* Ok, we found a frame. Convert from pixels to characters
1816 and store all the values. */
1818 pixel_to_glyph_coords (f1
, win_x
, win_y
, &win_x
, &win_y
,
1824 XSET (*x
, Lisp_Int
, win_x
);
1825 XSET (*y
, Lisp_Int
, win_y
);
1826 *time
= last_mouse_movement_time
;
1834 #else /* ! defined (HAVE_X11) */
1835 #define XEvent XKeyPressedEvent
1836 #endif /* ! defined (HAVE_X11) */
1838 /* Scroll bar support. */
1840 /* Given an X window ID, find the struct scroll_bar which manages it.
1841 This can be called in GC, so we have to make sure to strip off mark
1843 static struct scroll_bar
*
1844 x_window_to_scroll_bar (window_id
)
1847 Lisp_Object tail
, frame
;
1849 for (tail
= Vframe_list
;
1850 XGCTYPE (tail
) == Lisp_Cons
;
1851 tail
= XCONS (tail
)->cdr
)
1853 Lisp_Object frame
= XCONS (tail
)->car
;
1854 Lisp_Object bar
, condemned
;
1856 /* All elements of Vframe_list should be frames. */
1857 if (XGCTYPE (frame
) != Lisp_Frame
)
1860 /* Scan this frame's scroll bar list for a scroll bar with the
1862 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1863 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1864 /* This trick allows us to search both the ordinary and
1865 condemned scroll bar lists with one loop. */
1866 ! GC_NILP (bar
) || (bar
= condemned
,
1869 bar
= XSCROLL_BAR(bar
)->next
)
1870 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1871 return XSCROLL_BAR (bar
);
1877 /* Open a new X window to serve as a scroll bar, and return the
1878 scroll bar vector for it. */
1879 static struct scroll_bar
*
1880 x_scroll_bar_create (window
, top
, left
, width
, height
)
1881 struct window
*window
;
1882 int top
, left
, width
, height
;
1884 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1885 struct scroll_bar
*bar
=
1886 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1891 XSetWindowAttributes a
;
1894 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1895 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1896 | ButtonMotionMask
| PointerMotionHintMask
1898 a
.cursor
= x_vertical_scroll_bar_cursor
;
1900 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1902 SET_SCROLL_BAR_X_WINDOW
1904 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1906 /* Position and size of scroll bar. */
1907 left
, top
, width
, height
,
1909 /* Border width, depth, class, and visual. */
1910 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1916 XSET (bar
->window
, Lisp_Window
, window
);
1917 XSET (bar
->top
, Lisp_Int
, top
);
1918 XSET (bar
->left
, Lisp_Int
, left
);
1919 XSET (bar
->width
, Lisp_Int
, width
);
1920 XSET (bar
->height
, Lisp_Int
, height
);
1921 XSET (bar
->start
, Lisp_Int
, 0);
1922 XSET (bar
->end
, Lisp_Int
, 0);
1923 bar
->dragging
= Qnil
;
1925 /* Add bar to its frame's list of scroll bars. */
1926 bar
->next
= FRAME_SCROLL_BARS (frame
);
1928 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
1929 if (! NILP (bar
->next
))
1930 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1932 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
1939 /* Draw BAR's handle in the proper position.
1940 If the handle is already drawn from START to END, don't bother
1941 redrawing it, unless REBUILD is non-zero; in that case, always
1942 redraw it. (REBUILD is handy for drawing the handle after expose
1945 Normally, we want to constrain the start and end of the handle to
1946 fit inside its rectangle, but if the user is dragging the scroll bar
1947 handle, we want to let them drag it down all the way, so that the
1948 bar's top is as far down as it goes; otherwise, there's no way to
1949 move to the very end of the buffer. */
1951 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1952 struct scroll_bar
*bar
;
1956 int dragging
= ! NILP (bar
->dragging
);
1957 Window w
= SCROLL_BAR_X_WINDOW (bar
);
1958 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1960 /* If the display is already accurate, do nothing. */
1962 && start
== XINT (bar
->start
)
1963 && end
== XINT (bar
->end
))
1969 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
1970 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
1971 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
1973 /* Make sure the values are reasonable, and try to preserve
1974 the distance between start and end. */
1976 int length
= end
- start
;
1980 else if (start
> top_range
)
1982 end
= start
+ length
;
1986 else if (end
> top_range
&& ! dragging
)
1990 /* Store the adjusted setting in the scroll bar. */
1991 XSET (bar
->start
, Lisp_Int
, start
);
1992 XSET (bar
->end
, Lisp_Int
, end
);
1994 /* Clip the end position, just for display. */
1995 if (end
> top_range
)
1998 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1999 below top positions, to make sure the handle is always at least
2000 that many pixels tall. */
2001 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2003 /* Draw the empty space above the handle. Note that we can't clear
2004 zero-height areas; that means "clear to end of window." */
2006 XClearArea (x_current_display
, w
,
2008 /* x, y, width, height, and exposures. */
2009 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2010 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2011 inside_width
, start
,
2014 /* Draw the handle itself. */
2015 XFillRectangle (x_current_display
, w
, gc
,
2017 /* x, y, width, height */
2018 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2019 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2020 inside_width
, end
- start
);
2023 /* Draw the empty space below the handle. Note that we can't
2024 clear zero-height areas; that means "clear to end of window." */
2025 if (end
< inside_height
)
2026 XClearArea (x_current_display
, w
,
2028 /* x, y, width, height, and exposures. */
2029 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2030 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2031 inside_width
, inside_height
- end
,
2039 /* Move a scroll bar around on the screen, to accommodate changing
2040 window configurations. */
2042 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2043 struct scroll_bar
*bar
;
2044 int top
, left
, width
, height
;
2050 unsigned int mask
= 0;
2057 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2058 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2059 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2060 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2063 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2067 XSET (bar
->left
, Lisp_Int
, left
);
2068 XSET (bar
->top
, Lisp_Int
, top
);
2069 XSET (bar
->width
, Lisp_Int
, width
);
2070 XSET (bar
->height
, Lisp_Int
, height
);
2075 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2078 x_scroll_bar_remove (bar
)
2079 struct scroll_bar
*bar
;
2081 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2085 /* Destroy the window. */
2086 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2088 /* Disassociate this scroll bar from its window. */
2089 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2094 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2095 that we are displaying PORTION characters out of a total of WHOLE
2096 characters, starting at POSITION. If WINDOW has no scroll bar,
2099 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2100 struct window
*window
;
2101 int portion
, whole
, position
;
2103 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2104 int top
= XINT (window
->top
);
2105 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2106 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2108 /* Where should this scroll bar be, pixelwise? */
2109 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2110 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2111 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2112 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2114 struct scroll_bar
*bar
;
2116 /* Does the scroll bar exist yet? */
2117 if (NILP (window
->vertical_scroll_bar
))
2118 bar
= x_scroll_bar_create (window
,
2119 pixel_top
, pixel_left
,
2120 pixel_width
, pixel_height
);
2123 /* It may just need to be moved and resized. */
2124 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2125 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2128 /* Set the scroll bar's current state, unless we're currently being
2130 if (NILP (bar
->dragging
))
2133 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2136 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2139 int start
= ((double) position
* top_range
) / whole
;
2140 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2142 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2146 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2150 /* The following three hooks are used when we're doing a thorough
2151 redisplay of the frame. We don't explicitly know which scroll bars
2152 are going to be deleted, because keeping track of when windows go
2153 away is a real pain - "Can you say set-window-configuration, boys
2154 and girls?" Instead, we just assert at the beginning of redisplay
2155 that *all* scroll bars are to be removed, and then save a scroll bar
2156 from the fiery pit when we actually redisplay its window. */
2158 /* Arrange for all scroll bars on FRAME to be removed at the next call
2159 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2160 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2162 XTcondemn_scroll_bars (frame
)
2165 /* The condemned list should be empty at this point; if it's not,
2166 then the rest of Emacs isn't using the condemn/redeem/judge
2167 protocol correctly. */
2168 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2171 /* Move them all to the "condemned" list. */
2172 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2173 FRAME_SCROLL_BARS (frame
) = Qnil
;
2176 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2177 Note that WINDOW isn't necessarily condemned at all. */
2179 XTredeem_scroll_bar (window
)
2180 struct window
*window
;
2182 struct scroll_bar
*bar
;
2184 /* We can't redeem this window's scroll bar if it doesn't have one. */
2185 if (NILP (window
->vertical_scroll_bar
))
2188 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2190 /* Unlink it from the condemned list. */
2192 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2194 if (NILP (bar
->prev
))
2196 /* If the prev pointer is nil, it must be the first in one of
2198 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2199 /* It's not condemned. Everything's fine. */
2201 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2202 window
->vertical_scroll_bar
))
2203 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2205 /* If its prev pointer is nil, it must be at the front of
2206 one or the other! */
2210 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2212 if (! NILP (bar
->next
))
2213 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2215 bar
->next
= FRAME_SCROLL_BARS (f
);
2217 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2218 if (! NILP (bar
->next
))
2219 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2223 /* Remove all scroll bars on FRAME that haven't been saved since the
2224 last call to `*condemn_scroll_bars_hook'. */
2226 XTjudge_scroll_bars (f
)
2229 Lisp_Object bar
, next
;
2231 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2233 /* Clear out the condemned list now so we won't try to process any
2234 more events on the hapless scroll bars. */
2235 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2237 for (; ! NILP (bar
); bar
= next
)
2239 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2241 x_scroll_bar_remove (b
);
2244 b
->next
= b
->prev
= Qnil
;
2247 /* Now there should be no references to the condemned scroll bars,
2248 and they should get garbage-collected. */
2252 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2254 This may be called from a signal handler, so we have to ignore GC
2257 x_scroll_bar_expose (bar
, event
)
2258 struct scroll_bar
*bar
;
2261 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2262 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2266 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2268 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2269 XDrawRectangle (x_current_display
, w
, gc
,
2271 /* x, y, width, height */
2272 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2274 /* Draw another line to make the extra-thick border on the right. */
2275 XFillRectangle (x_current_display
, w
, gc
,
2277 /* x, y, width, height */
2278 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2283 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2284 is set to something other than no_event, it is enqueued.
2286 This may be called from a signal handler, so we have to ignore GC
2289 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2290 struct scroll_bar
*bar
;
2292 struct input_event
*emacs_event
;
2294 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2297 emacs_event
->kind
= scroll_bar_click
;
2298 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2299 emacs_event
->modifiers
=
2300 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2301 | (event
->type
== ButtonRelease
2304 emacs_event
->frame_or_window
= bar
->window
;
2305 emacs_event
->timestamp
= event
->xbutton
.time
;
2307 int internal_height
=
2308 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2310 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2311 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2314 if (y
> top_range
) y
= top_range
;
2316 if (y
< XINT (bar
->start
))
2317 emacs_event
->part
= scroll_bar_above_handle
;
2318 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2319 emacs_event
->part
= scroll_bar_handle
;
2321 emacs_event
->part
= scroll_bar_below_handle
;
2323 /* Just because the user has clicked on the handle doesn't mean
2324 they want to drag it. Lisp code needs to be able to decide
2325 whether or not we're dragging. */
2327 /* If the user has just clicked on the handle, record where they're
2329 if (event
->type
== ButtonPress
2330 && emacs_event
->part
== scroll_bar_handle
)
2331 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2334 /* If the user has released the handle, set it to its final position. */
2335 if (event
->type
== ButtonRelease
2336 && ! NILP (bar
->dragging
))
2338 int new_start
= y
- XINT (bar
->dragging
);
2339 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2341 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2342 bar
->dragging
= Qnil
;
2345 /* Same deal here as the other #if 0. */
2347 /* Clicks on the handle are always reported as occurring at the top of
2349 if (emacs_event
->part
== scroll_bar_handle
)
2350 emacs_event
->x
= bar
->start
;
2352 XSET (emacs_event
->x
, Lisp_Int
, y
);
2354 XSET (emacs_event
->x
, Lisp_Int
, y
);
2357 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2361 /* Handle some mouse motion while someone is dragging the scroll bar.
2363 This may be called from a signal handler, so we have to ignore GC
2366 x_scroll_bar_note_movement (bar
, event
)
2367 struct scroll_bar
*bar
;
2370 last_mouse_movement_time
= event
->xmotion
.time
;
2373 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2375 /* If we're dragging the bar, display it. */
2376 if (! GC_NILP (bar
->dragging
))
2378 /* Where should the handle be now? */
2379 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2381 if (new_start
!= XINT (bar
->start
))
2383 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2385 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2389 /* Call XQueryPointer so we'll get an event the next time the mouse
2390 moves and we can see *still* on the same position. */
2394 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2395 (Window
*) &dummy
, (Window
*) &dummy
,
2396 &dummy
, &dummy
, &dummy
, &dummy
,
2397 (unsigned int *) &dummy
);
2401 /* Return information to the user about the current position of the mouse
2402 on the scroll bar. */
2404 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2406 Lisp_Object
*bar_window
;
2407 enum scroll_bar_part
*part
;
2409 unsigned long *time
;
2411 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2413 Window dummy_window
;
2415 unsigned int dummy_mask
;
2419 /* Get the mouse's position relative to the scroll bar window, and
2421 if (! XQueryPointer (x_current_display
,
2422 SCROLL_BAR_X_WINDOW (bar
),
2424 /* Root, child, root x and root y. */
2425 &dummy_window
, &dummy_window
,
2426 &dummy_coord
, &dummy_coord
,
2428 /* Position relative to scroll bar. */
2431 /* Mouse buttons and modifier keys. */
2437 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2439 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2441 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2443 if (! NILP (bar
->dragging
))
2444 win_y
-= XINT (bar
->dragging
);
2448 if (win_y
> top_range
)
2451 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2452 *bar_window
= bar
->window
;
2454 if (! NILP (bar
->dragging
))
2455 *part
= scroll_bar_handle
;
2456 else if (win_y
< XINT (bar
->start
))
2457 *part
= scroll_bar_above_handle
;
2458 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2459 *part
= scroll_bar_handle
;
2461 *part
= scroll_bar_below_handle
;
2463 XSET (*x
, Lisp_Int
, win_y
);
2464 XSET (*y
, Lisp_Int
, top_range
);
2467 last_mouse_scroll_bar
= Qnil
;
2470 *time
= last_mouse_movement_time
;
2476 /* The screen has been cleared so we may have changed foreground or
2477 background colors, and the scroll bars may need to be redrawn.
2478 Clear out the scroll bars, and ask for expose events, so we can
2481 x_scroll_bar_clear (f
)
2486 for (bar
= FRAME_SCROLL_BARS (f
);
2487 XTYPE (bar
) == Lisp_Vector
;
2488 bar
= XSCROLL_BAR (bar
)->next
)
2489 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2495 /* The main X event-reading loop - XTread_socket. */
2497 /* Timestamp of enter window event. This is only used by XTread_socket,
2498 but we have to put it out here, since static variables within functions
2499 sometimes don't work. */
2500 static Time enter_timestamp
;
2502 /* This holds the state XLookupString needs to implement dead keys
2503 and other tricks known as "compose processing". _X Window System_
2504 says that a portable program can't use this, but Stephen Gildea assures
2505 me that letting the compiler initialize it to zeros will work okay.
2507 This must be defined outside of XTread_socket, for the same reasons
2508 given for enter_timestamp, above. */
2509 static XComposeStatus compose_status
;
2511 /* Communication with window managers. */
2512 Atom Xatom_wm_protocols
;
2514 /* Kinds of protocol things we may receive. */
2515 Atom Xatom_wm_take_focus
;
2516 Atom Xatom_wm_save_yourself
;
2517 Atom Xatom_wm_delete_window
;
2519 /* Other WM communication */
2520 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2521 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2523 /* Window manager communication. */
2524 Atom Xatom_wm_change_state
;
2526 /* Record the last 100 characters stored
2527 to help debug the loss-of-chars-during-GC problem. */
2529 short temp_buffer
[100];
2531 /* Read events coming from the X server.
2532 This routine is called by the SIGIO handler.
2533 We return as soon as there are no more events to be read.
2535 Events representing keys are stored in buffer BUFP,
2536 which can hold up to NUMCHARS characters.
2537 We return the number of characters stored into the buffer,
2538 thus pretending to be `read'.
2540 WAITP is nonzero if we should block until input arrives.
2541 EXPECTED is nonzero if the caller knows input is available. */
2544 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2546 register struct input_event
*bufp
;
2547 register int numchars
;
2554 int items_pending
; /* How many items are in the X queue. */
2561 if (interrupt_input_blocked
)
2563 interrupt_input_pending
= 1;
2567 interrupt_input_pending
= 0;
2571 abort (); /* Don't think this happens. */
2574 /* If available, Xlib uses FIOSNBIO to make the socket
2575 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2576 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2577 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2578 fcntl (fileno (stdin
), F_SETFL
, 0);
2579 #endif /* ! defined (FIOSNBIO) */
2583 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2585 extern int read_alarm_should_throw
;
2586 read_alarm_should_throw
= 1;
2587 XPeekEvent (XDISPLAY
&event
);
2588 read_alarm_should_throw
= 0;
2590 #endif /* HAVE_SELECT */
2593 while (XStuffPending () != 0)
2595 XNextEvent (XDISPLAY
&event
);
2603 if (event
.xclient
.message_type
== Xatom_wm_protocols
2604 && event
.xclient
.format
== 32)
2606 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2608 f
= x_window_to_frame (event
.xclient
.window
);
2610 x_focus_on_frame (f
);
2611 /* Not certain about handling scroll bars here */
2613 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2615 /* Save state modify the WM_COMMAND property to
2616 something which can reinstate us. This notifies
2617 the session manager, who's looking for such a
2618 PropertyNotify. Can restart processing when
2619 a keyboard or mouse event arrives. */
2624 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2626 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2634 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2637 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2641 new_x
= event
.xclient
.data
.s
[0];
2642 new_y
= event
.xclient
.data
.s
[1];
2647 #ifdef NEW_SELECTIONS
2648 case SelectionNotify
:
2649 x_handle_selection_notify (&event
);
2653 case SelectionClear
: /* Someone has grabbed ownership. */
2654 #ifdef NEW_SELECTIONS
2656 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2661 bufp
->kind
= selection_clear_event
;
2662 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2663 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2664 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2671 x_disown_selection (event
.xselectionclear
.window
,
2672 event
.xselectionclear
.selection
,
2673 event
.xselectionclear
.time
);
2677 case SelectionRequest
: /* Someone wants our selection. */
2678 #ifdef NEW_SELECTIONS
2680 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2685 bufp
->kind
= selection_request_event
;
2686 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2687 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2688 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2689 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2690 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2691 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2698 x_answer_selection_request (event
);
2702 case PropertyNotify
:
2703 #ifdef NEW_SELECTIONS
2704 x_handle_property_notify (&event
);
2706 /* If we're being told about a root window property, then it's
2707 a cut buffer change. */
2708 if (event
.xproperty
.window
== ROOT_WINDOW
)
2709 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2711 /* Otherwise, we're probably handling an incremental
2712 selection transmission. */
2715 /* If we were to do this synchronously, there'd be no worry
2716 about re-selecting. */
2717 x_send_incremental (event
);
2722 case ReparentNotify
:
2723 f
= x_window_to_frame (event
.xreparent
.window
);
2725 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
2729 f
= x_window_to_frame (event
.xexpose
.window
);
2732 if (f
->async_visible
== 0)
2734 f
->async_visible
= 1;
2735 f
->async_iconified
= 0;
2736 SET_FRAME_GARBAGED (f
);
2740 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2741 event
.xexpose
.x
, event
.xexpose
.y
,
2742 event
.xexpose
.width
, event
.xexpose
.height
);
2747 struct scroll_bar
*bar
2748 = x_window_to_scroll_bar (event
.xexpose
.window
);
2751 x_scroll_bar_expose (bar
, &event
);
2755 case GraphicsExpose
: /* This occurs when an XCopyArea's
2756 source area was obscured or not
2758 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2762 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2763 event
.xgraphicsexpose
.width
,
2764 event
.xgraphicsexpose
.height
);
2768 case NoExpose
: /* This occurs when an XCopyArea's
2769 source area was completely
2772 #else /* ! defined (HAVE_X11) */
2774 if (event
.subwindow
!= 0)
2775 break; /* duplicate event */
2776 f
= x_window_to_frame (event
.window
);
2777 if (event
.window
== f
->display
.x
->icon_desc
)
2780 f
->async_iconified
= 1;
2782 if (event
.window
== FRAME_X_WINDOW (f
))
2784 /* Say must check all windows' needs_exposure flags. */
2785 expose_all_windows
= 1;
2786 f
->display
.x
->needs_exposure
= 1;
2787 f
->async_visible
= 1;
2792 if (event
.subwindow
!= 0)
2793 break; /* duplicate event */
2794 f
= x_window_to_frame (event
.window
);
2795 if (event
.window
== f
->display
.x
->icon_desc
)
2800 /* If window already needs full redraw, ignore this rectangle. */
2801 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2803 /* Put the event on the queue of rectangles to redraw. */
2804 if (enqueue_event (&event
, &x_expose_queue
))
2805 /* If it is full, we can't record the rectangle,
2806 so redraw this entire window. */
2808 /* Say must check all windows' needs_exposure flags. */
2809 expose_all_windows
= 1;
2810 f
->display
.x
->needs_exposure
= 1;
2815 /* This should happen only when we are expecting it,
2816 in x_read_exposes. */
2818 #endif /* ! defined (HAVE_X11) */
2822 f
= x_window_to_frame (event
.xunmap
.window
);
2823 if (f
) /* F may no longer exist if
2824 the frame was deleted. */
2826 /* While a frame is unmapped, display generation is
2827 disabled; you don't want to spend time updating a
2828 display that won't ever be seen. */
2829 f
->async_visible
= 0;
2830 /* The window manager never makes a window invisible
2831 ("withdrawn"); all it does is switch between visible
2832 and iconified. Frames get into the invisible state
2833 only through x_make_frame_invisible.
2834 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
2835 f->async_iconified = 1;
2840 f = x_window_to_frame (event.xmap.window);
2843 f->async_visible = 1;
2844 f->async_iconified = 0;
2846 /* wait_reading_process_input will notice this and update
2847 the frame's display structures. */
2848 SET_FRAME_GARBAGED (f
);
2852 /* Turn off processing if we become fully obscured. */
2853 case VisibilityNotify
:
2856 #else /* ! defined (HAVE_X11) */
2858 f
= x_window_to_frame (event
.window
);
2859 if (event
.window
== f
->display
.x
->icon_desc
)
2860 f
->async_iconified
= 0;
2861 if (event
.window
== FRAME_X_WINDOW (f
))
2862 f
->async_visible
= 0;
2864 #endif /* ! defined (HAVE_X11) */
2868 f
= x_window_to_frame (event
.xkey
.window
);
2872 KeySym keysym
, orig_keysym
;
2873 char copy_buffer
[80];
2877 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
2878 modifiers
= event
.xkey
.state
;
2880 /* This will have to go some day... */
2882 /* make_lispy_event turns chars into control chars.
2883 Don't do it here because XLookupString is too eager. */
2884 event
.xkey
.state
&= ~ControlMask
;
2886 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2889 /* Strip off the vendor-specific keysym bit, and take a shot
2890 at recognizing the codes. HP servers have extra keysyms
2891 that fit into the MiscFunctionKey category. */
2892 orig_keysym
= keysym
;
2897 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
2898 || keysym
== XK_Delete
2899 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2900 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
2902 /* This recognizes the "extended function keys".
2903 It seems there's no cleaner way.
2904 Test IsModifierKey to avoid handling mode_switch
2906 || ((unsigned) (keysym
) >= XK_Select
2907 && (unsigned)(keysym
) < XK_KP_Space
)
2909 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2910 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
2911 || x_is_vendor_fkey (orig_keysym
))
2912 && ! IsModifierKey (orig_keysym
)) /* wherever */
2914 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2916 temp_buffer
[temp_index
++] = keysym
;
2917 bufp
->kind
= non_ascii_keystroke
;
2918 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff00);
2919 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2920 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
2921 bufp
->timestamp
= event
.xkey
.time
;
2926 else if (numchars
> nbytes
)
2930 for (i
= 0; i
< nbytes
; i
++)
2932 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2934 temp_buffer
[temp_index
++] = copy_buffer
[i
];
2935 bufp
->kind
= ascii_keystroke
;
2936 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2937 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2938 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
2939 bufp
->timestamp
= event
.xkey
.time
;
2953 #else /* ! defined (HAVE_X11) */
2956 register char *where_mapping
;
2958 f
= x_window_to_frame (event
.window
);
2959 /* Ignore keys typed on icon windows. */
2960 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2962 where_mapping
= XLookupMapping (&event
, &nbytes
);
2963 /* Nasty fix for arrow keys */
2964 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2966 switch (event
.detail
& 0xff)
2968 case KC_CURSOR_LEFT
:
2969 where_mapping
= "\002";
2971 case KC_CURSOR_RIGHT
:
2972 where_mapping
= "\006";
2975 where_mapping
= "\020";
2977 case KC_CURSOR_DOWN
:
2978 where_mapping
= "\016";
2983 if (numchars
- nbytes
> 0)
2987 for (i
= 0; i
< nbytes
; i
++)
2989 bufp
->kind
= ascii_keystroke
;
2990 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2991 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2992 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3000 #endif /* ! defined (HAVE_X11) */
3004 /* Here's a possible interpretation of the whole
3005 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3006 FocusIn event, you have to get a FocusOut event before you
3007 relinquish the focus. If you haven't received a FocusIn event,
3008 then a mere LeaveNotify is enough to free you. */
3011 f
= x_window_to_frame (event
.xcrossing
.window
);
3013 if (event
.xcrossing
.focus
) /* Entered Window */
3015 /* Avoid nasty pop/raise loops. */
3016 if (f
&& (!(f
->auto_raise
)
3018 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3020 x_new_focus_frame (f
);
3021 enter_timestamp
= event
.xcrossing
.time
;
3024 else if (f
== x_focus_frame
)
3025 x_new_focus_frame (0);
3030 f
= x_window_to_frame (event
.xfocus
.window
);
3031 if (event
.xfocus
.detail
!= NotifyPointer
)
3032 x_focus_event_frame
= f
;
3034 x_new_focus_frame (f
);
3039 f
= x_window_to_frame (event
.xcrossing
.window
);
3041 if (event
.xcrossing
.focus
)
3043 if (! x_focus_event_frame
)
3044 x_new_focus_frame (0);
3046 x_new_focus_frame (f
);
3050 if (f
== x_focus_event_frame
)
3051 x_focus_event_frame
= 0;
3052 if (f
== x_focus_frame
)
3053 x_new_focus_frame (0);
3058 f
= x_window_to_frame (event
.xfocus
.window
);
3059 if (event
.xfocus
.detail
!= NotifyPointer
3060 && f
== x_focus_event_frame
)
3061 x_focus_event_frame
= 0;
3062 if (f
&& f
== x_focus_frame
)
3063 x_new_focus_frame (0);
3066 #else /* ! defined (HAVE_X11) */
3069 if ((event
.detail
& 0xFF) == 1)
3070 break; /* Coming from our own subwindow */
3071 if (event
.subwindow
!= 0)
3072 break; /* Entering our own subwindow. */
3075 f
= x_window_to_frame (event
.window
);
3078 x_new_focus_frame (f
);
3083 if ((event
.detail
& 0xFF) == 1)
3084 break; /* Entering our own subwindow */
3085 if (event
.subwindow
!= 0)
3086 break; /* Leaving our own subwindow. */
3089 if (x_focus_frame
== 0
3090 && x_input_frame
!= 0
3091 && x_input_frame
== x_window_to_frame (event
.window
)
3092 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3097 frame_unhighlight (f
);
3100 #endif /* ! defined (HAVE_X11) */
3105 f
= x_window_to_frame (event
.xmotion
.window
);
3107 note_mouse_movement (f
, &event
.xmotion
);
3110 struct scroll_bar
*bar
=
3111 x_window_to_scroll_bar (event
.xmotion
.window
);
3114 x_scroll_bar_note_movement (bar
, &event
);
3119 case ConfigureNotify
:
3120 f
= x_window_to_frame (event
.xconfigure
.window
);
3123 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3124 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3126 /* Even if the number of character rows and columns has
3127 not changed, the font size may have changed, so we need
3128 to check the pixel dimensions as well. */
3129 if (columns
!= f
->width
3130 || rows
!= f
->height
3131 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3132 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3134 change_frame_size (f
, rows
, columns
, 0, 1);
3135 SET_FRAME_GARBAGED (f
);
3138 if (! event
.xconfigure
.send_event
)
3143 /* Coords are relative to the parent.
3144 Convert them to root-relative. */
3145 XTranslateCoordinates (x_current_display
,
3147 /* From-window, to-window. */
3148 f
->display
.x
->parent_desc
,
3151 /* From-position, to-position. */
3158 event
.xconfigure
.x
= win_x
;
3159 event
.xconfigure
.y
= win_y
;
3162 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3163 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3164 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3165 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3172 /* If we decide we want to generate an event to be seen
3173 by the rest of Emacs, we put it here. */
3174 struct input_event emacs_event
;
3175 emacs_event
.kind
= no_event
;
3177 f
= x_window_to_frame (event
.xbutton
.window
);
3180 if (!x_focus_frame
|| (f
== x_focus_frame
))
3181 construct_mouse_click (&emacs_event
,
3186 struct scroll_bar
*bar
=
3187 x_window_to_scroll_bar (event
.xbutton
.window
);
3190 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3193 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3195 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3203 #else /* ! defined (HAVE_X11) */
3205 case ButtonReleased
:
3206 f
= x_window_to_frame (event
.window
);
3209 if (event
.window
== f
->display
.x
->icon_desc
)
3211 x_make_frame_visible (f
);
3213 if (warp_mouse_on_deiconify
)
3214 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3217 if (event
.window
== FRAME_X_WINDOW (f
))
3223 enqueue_event (&event
, &x_mouse_queue
);
3226 bufp
->kind
= ascii_keystroke
;
3227 bufp
->code
= (char) 'X' & 037; /* C-x */
3228 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3229 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3232 bufp
->kind
= ascii_keystroke
;
3233 bufp
->code
= (char) 0; /* C-@ */
3234 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3235 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3242 #endif /* ! defined (HAVE_X11) */
3246 case CirculateNotify
:
3248 case CirculateRequest
:
3251 #endif /* ! defined (HAVE_X11) */
3254 /* Someone has changed the keyboard mapping - update the
3256 switch (event
.xmapping
.request
)
3258 case MappingModifier
:
3259 x_find_modifier_meanings ();
3260 /* This is meant to fall through. */
3261 case MappingKeyboard
:
3262 XRefreshKeyboardMapping (&event
.xmapping
);
3273 if (expected
&& ! event_found
)
3275 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3276 there is an EOF condition; in other words, that X has died.
3277 Act as if there had been a hangup. */
3279 int fd
= ConnectionNumber (x_current_display
);
3282 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3284 && !XStuffPending ())
3285 kill (getpid (), SIGHUP
);
3287 #endif /* ! defined (HAVE_SELECT) */
3291 if (updating_frame
== 0)
3292 x_do_pending_expose ();
3300 /* Read and process only Expose events
3301 until we get an ExposeCopy event; then return.
3302 This is used in insert/delete line.
3303 We assume input is already blocked. */
3309 XKeyPressedEvent event
;
3313 /* while there are more events*/
3314 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3318 if (event
.subwindow
!= 0)
3319 break; /* duplicate event */
3320 f
= x_window_to_frame (event
.window
);
3321 if (event
.window
== f
->display
.x
->icon_desc
)
3326 if (event
.window
== FRAME_X_WINDOW (f
))
3328 expose_all_windows
= 1;
3329 f
->display
.x
->needs_exposure
= 1;
3335 if (event
.subwindow
!= 0)
3336 break; /* duplicate event */
3337 f
= x_window_to_frame (event
.window
);
3338 if (event
.window
== f
->display
.x
->icon_desc
)
3343 /* If window already needs full redraw, ignore this rectangle. */
3344 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3346 /* Put the event on the queue of rectangles to redraw. */
3347 if (enqueue_event (&event
, &x_expose_queue
))
3348 /* If it is full, we can't record the rectangle,
3349 so redraw this entire window. */
3351 /* Say must check all windows' needs_exposure flags. */
3352 expose_all_windows
= 1;
3353 f
->display
.x
->needs_exposure
= 1;
3362 #endif /* HAVE_X11 */
3365 /* Drawing the cursor. */
3368 /* Draw a hollow box cursor. Don't change the inside of the box. */
3374 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3375 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3376 int width
= FONT_WIDTH (f
->display
.x
->font
);
3377 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3380 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3381 f
->display
.x
->cursor_gc
,
3382 left
, top
, width
- 1, height
- 1);
3383 #else /* ! defined (HAVE_X11) */
3384 XPixSet (FRAME_X_WINDOW (f
),
3385 left
, top
, width
, 1,
3386 f
->display
.x
->cursor_pixel
);
3388 XPixSet (FRAME_X_WINDOW (f
),
3389 left
, top
, 1, height
,
3390 f
->display
.x
->cursor_pixel
);
3392 XPixSet (FRAME_X_WINDOW (f
),
3393 left
+width
-1, top
, 1, height
,
3394 f
->display
.x
->cursor_pixel
);
3396 XPixSet (FRAME_X_WINDOW (f
),
3397 left
, top
+height
-1, width
, 1,
3398 f
->display
.x
->cursor_pixel
);
3399 #endif /* ! defined (HAVE_X11) */
3402 /* Clear the cursor of frame F to background color,
3403 and mark the cursor as not shown.
3404 This is used when the text where the cursor is
3405 is about to be rewritten. */
3413 if (! FRAME_VISIBLE_P (f
)
3414 || f
->phys_cursor_x
< 0)
3418 x_display_cursor (f
, 0);
3419 #else /* ! defined (HAVE_X11) */
3420 XPixSet (FRAME_X_WINDOW (f
),
3421 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3422 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3423 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3424 f
->display
.x
->background_pixel
);
3425 #endif /* ! defined (HAVE_X11) */
3426 f
->phys_cursor_x
= -1;
3429 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3430 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3434 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3441 CHAR_TO_PIXEL_COL (f
, column
),
3442 CHAR_TO_PIXEL_ROW (f
, row
),
3443 &glyph
, 1, highlight
);
3447 x_display_bar_cursor (f
, on
)
3451 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3453 /* This is pointless on invisible frames, and dangerous on garbaged
3454 frames; in the latter case, the frame may be in the midst of
3455 changing its size, and curs_x and curs_y may be off the frame. */
3456 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3459 if (! on
&& f
->phys_cursor_x
< 0)
3462 /* If we're not updating, then we want to use the current frame's
3463 cursor position, not our local idea of where the cursor ought to be. */
3464 if (f
!= updating_frame
)
3466 curs_x
= FRAME_CURSOR_X (f
);
3467 curs_y
= FRAME_CURSOR_Y (f
);
3470 /* If there is anything wrong with the current cursor state, remove it. */
3471 if (f
->phys_cursor_x
>= 0
3473 || f
->phys_cursor_x
!= curs_x
3474 || f
->phys_cursor_y
!= curs_y
3475 || f
->display
.x
->current_cursor
!= bar_cursor
))
3477 /* Erase the cursor by redrawing the character underneath it. */
3478 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3479 f
->phys_cursor_glyph
,
3480 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3481 f
->phys_cursor_x
= -1;
3484 /* If we now need a cursor in the new place or in the new form, do it so. */
3486 && (f
->phys_cursor_x
< 0
3487 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3489 f
->phys_cursor_glyph
3490 = ((current_glyphs
->enable
[curs_y
]
3491 && curs_x
< current_glyphs
->used
[curs_y
])
3492 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3494 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3495 f
->display
.x
->cursor_gc
,
3496 CHAR_TO_PIXEL_COL (f
, curs_x
),
3497 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3498 1, FONT_HEIGHT (f
->display
.x
->font
));
3500 f
->phys_cursor_x
= curs_x
;
3501 f
->phys_cursor_y
= curs_y
;
3503 f
->display
.x
->current_cursor
= bar_cursor
;
3506 if (updating_frame
!= f
)
3511 /* Turn the displayed cursor of frame F on or off according to ON.
3512 If ON is nonzero, where to put the cursor is specified
3513 by F->cursor_x and F->cursor_y. */
3516 x_display_box_cursor (f
, on
)
3520 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3522 /* This is pointless on invisible frames, and dangerous on garbaged
3523 frames; in the latter case, the frame may be in the midst of
3524 changing its size, and curs_x and curs_y may be off the frame. */
3525 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3528 /* If cursor is off and we want it off, return quickly. */
3529 if (!on
&& f
->phys_cursor_x
< 0)
3532 /* If we're not updating, then we want to use the current frame's
3533 cursor position, not our local idea of where the cursor ought to be. */
3534 if (f
!= updating_frame
)
3536 curs_x
= FRAME_CURSOR_X (f
);
3537 curs_y
= FRAME_CURSOR_Y (f
);
3540 /* If cursor is currently being shown and we don't want it to be
3541 or it is in the wrong place,
3542 or we want a hollow box and it's not so, (pout!)
3544 if (f
->phys_cursor_x
>= 0
3546 || f
->phys_cursor_x
!= curs_x
3547 || f
->phys_cursor_y
!= curs_y
3548 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3549 && (f
!= x_highlight_frame
))))
3551 /* Erase the cursor by redrawing the character underneath it. */
3552 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3553 f
->phys_cursor_glyph
,
3554 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3555 f
->phys_cursor_x
= -1;
3558 /* If we want to show a cursor,
3559 or we want a box cursor and it's not so,
3560 write it in the right place. */
3562 && (f
->phys_cursor_x
< 0
3563 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3564 && f
== x_highlight_frame
)))
3566 f
->phys_cursor_glyph
3567 = ((current_glyphs
->enable
[curs_y
]
3568 && curs_x
< current_glyphs
->used
[curs_y
])
3569 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3571 if (f
!= x_highlight_frame
)
3574 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3578 x_draw_single_glyph (f
, curs_y
, curs_x
,
3579 f
->phys_cursor_glyph
, 2);
3580 f
->display
.x
->current_cursor
= filled_box_cursor
;
3583 f
->phys_cursor_x
= curs_x
;
3584 f
->phys_cursor_y
= curs_y
;
3587 if (updating_frame
!= f
)
3591 x_display_cursor (f
, on
)
3595 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3596 x_display_box_cursor (f
, on
);
3597 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3598 x_display_bar_cursor (f
, on
);
3600 /* Those are the only two we have implemented! */
3606 /* Refresh bitmap kitchen sink icon for frame F
3607 when we get an expose event for it. */
3613 /* Normally, the window manager handles this function. */
3614 #else /* ! defined (HAVE_X11) */
3617 if (f
->display
.x
->icon_bitmap_flag
)
3618 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3619 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3620 icon_bitmap
, GXcopy
, AllPlanes
);
3623 extern struct frame
*selected_frame
;
3624 struct Lisp_String
*str
;
3625 unsigned char *string
;
3628 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3630 if (f
->display
.x
->icon_label
!= string
)
3632 f
->display
.x
->icon_label
= string
;
3633 XChangeWindow (f
->display
.x
->icon_desc
,
3634 XQueryWidth (string
, icon_font_info
->id
) + 10,
3635 icon_font_info
->height
+ 10);
3638 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3639 str
->size
, icon_font_info
->id
,
3640 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3643 #endif /* ! defined (HAVE_X11) */
3646 /* Make the x-window of frame F use the gnu icon bitmap. */
3655 if (FRAME_X_WINDOW (f
) == 0)
3661 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3662 gnu_bits
, gnu_width
, gnu_height
);
3663 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3664 f
->display
.x
->icon_bitmap_flag
= 1;
3665 #else /* ! defined (HAVE_X11) */
3666 if (f
->display
.x
->icon_desc
)
3668 XClearIconWindow (FRAME_X_WINDOW (f
));
3669 XDestroyWindow (f
->display
.x
->icon_desc
);
3672 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3673 0, 0, sink_width
, sink_height
,
3674 2, WhitePixmap
, (Pixmap
) NULL
);
3676 if (icon_window
== 0)
3679 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3680 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3682 f
->display
.x
->icon_desc
= icon_window
;
3683 f
->display
.x
->icon_bitmap_flag
= 1;
3685 if (icon_bitmap
== 0)
3687 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3688 #endif /* ! defined (HAVE_X11) */
3694 /* Make the x-window of frame F use a rectangle with text. */
3697 x_text_icon (f
, icon_name
)
3705 char *X_DefaultValue
;
3709 #define WhitePixel 1
3710 #endif /* WhitePixel */
3713 #define BlackPixel 0
3714 #endif /* BlackPixel */
3715 #endif /* HAVE_X11 */
3717 if (FRAME_X_WINDOW (f
) == 0)
3722 f
->display
.x
->icon_label
= icon_name
;
3724 if (! f
->display
.x
->icon_label
)
3725 f
->display
.x
->icon_label
= " *emacs* ";
3728 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3729 (char *) f
->display
.x
->icon_label
);
3732 f
->display
.x
->icon_bitmap_flag
= 0;
3733 x_wm_set_icon_pixmap (f
, 0);
3734 #else /* ! defined (HAVE_X11) */
3735 if (icon_font_info
== 0)
3737 = XGetFont (XGetDefault (XDISPLAY
3738 (char *) XSTRING (Vinvocation_name
)->data
,
3741 if (f
->display
.x
->icon_desc
)
3743 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3744 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3748 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3750 if (! f
->display
.x
->icon_label
)
3751 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3753 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3754 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3755 f
->display
.x
->left_pos
,
3756 f
->display
.x
->top_pos
,
3757 width
+ 10, icon_font_info
->height
+ 10,
3758 2, BlackPixmap
, WhitePixmap
);
3760 if (icon_window
== 0)
3763 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3764 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3766 f
->display
.x
->icon_desc
= icon_window
;
3767 f
->display
.x
->icon_bitmap_flag
= 0;
3768 f
->display
.x
->icon_label
= 0;
3769 #endif /* ! defined (HAVE_X11) */
3774 /* Handling X errors. */
3776 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3777 X server's connection, or an error reported via the X protocol. */
3780 x_connection_closed ()
3785 shut_down_emacs (0, 1, Qnil
);
3790 /* An X error handler which prints an error message and then kills
3791 Emacs. This is what's normally installed as Xlib's handler for
3794 x_error_quitter (display
, error
)
3800 /* Note that there is no real way portable across R3/R4 to get the
3801 original error handler. */
3803 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3804 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3805 buf
, error
->request_code
);
3808 /* While we're testing Emacs 19, we'll just dump core whenever we
3809 get an X error, so we can figure out why it happened. */
3813 x_connection_closed ();
3816 /* A handler for X IO errors which prints an error message and then
3817 kills Emacs. This is what is always installed as Xlib's handler
3820 x_io_error_quitter (display
)
3823 fprintf (stderr
, "Connection to X server %s lost.\n",
3824 XDisplayName (DisplayString (display
)));
3827 /* While we're testing Emacs 19, we'll just dump core whenever we
3828 get an X error, so we can figure out why it happened. */
3832 x_connection_closed ();
3835 /* A buffer for storing X error messages. */
3836 static char *x_caught_error_message
;
3837 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
3839 /* An X error handler which stores the error message in
3840 x_caught_error_message. This is what's installed when
3841 x_catch_errors is in effect. */
3843 x_error_catcher (display
, error
)
3847 XGetErrorText (display
, error
->error_code
,
3848 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
3852 /* Begin trapping X errors.
3854 After calling this function, X protocol errors no longer cause
3855 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3857 Calling x_check_errors signals an Emacs error if an X error has
3858 occurred since the last call to x_catch_errors or x_check_errors.
3860 Calling x_uncatch_errors resumes the normal error handling. */
3862 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3867 /* Make sure any errors from previous requests have been dealt with. */
3868 XSync (x_current_display
, False
);
3870 /* Set up the error buffer. */
3871 x_caught_error_message
3872 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
3873 x_caught_error_message
[0] = '\0';
3875 /* Install our little error handler. */
3876 XHandleError (x_error_catcher
);
3879 /* If any X protocol errors have arrived since the last call to
3880 x_catch_errors or x_check_errors, signal an Emacs error using
3881 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3883 x_check_errors (format
)
3886 /* Make sure to catch any errors incurred so far. */
3887 XSync (x_current_display
, False
);
3889 if (x_caught_error_message
[0])
3891 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
3893 sprintf (buf
, format
, x_caught_error_message
);
3894 x_uncatch_errors ();
3902 xfree (x_caught_error_message
);
3903 x_caught_error_message
= 0;
3904 XHandleError (x_error_quitter
);
3908 static unsigned int x_wire_count
;
3911 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3916 /* Changing the font of the frame. */
3918 /* Set the font of the x-window specified by frame F
3919 to the font named NEWNAME. This is safe to use
3920 even before F has an actual x-window. */
3924 /* A table of all the fonts we have already loaded. */
3925 static XFontStruct
**x_font_table
;
3927 /* The current capacity of x_font_table. */
3928 static int x_font_table_size
;
3930 /* The number of fonts actually stored in x_font_table.
3931 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3932 0 <= n_fonts <= x_font_table_size. */
3936 x_new_font (f
, fontname
)
3938 register char *fontname
;
3941 int n_matching_fonts
;
3942 XFontStruct
*font_info
;
3945 /* Get a list of all the fonts that match this name. Once we
3946 have a list of matching fonts, we compare them against the fonts
3947 we already have by comparing font ids. */
3948 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3949 1024, &n_matching_fonts
,
3951 /* Apparently it doesn't set n_matching_fonts to zero when it can't
3952 find any matches; font_names == 0 is the only clue. */
3954 n_matching_fonts
= 0;
3956 /* Don't just give up if n_matching_fonts is 0.
3957 Apparently there's a bug on Suns: XListFontsWithInfo can
3958 fail to find a font, but XLoadQueryFont may still find it. */
3960 /* See if we've already loaded a matching font. */
3961 already_loaded
= -1;
3962 if (n_matching_fonts
!= 0)
3966 for (i
= 0; i
< n_fonts
; i
++)
3967 for (j
= 0; j
< n_matching_fonts
; j
++)
3968 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3971 fontname
= font_names
[j
];
3977 /* If we have, just return it from the table. */
3978 if (already_loaded
> 0)
3979 f
->display
.x
->font
= x_font_table
[already_loaded
];
3981 /* Otherwise, load the font and add it to the table. */
3987 /* Try to find a character-cell font in the list. */
3989 /* A laudable goal, but this isn't how to do it. */
3990 for (i
= 0; i
< n_matching_fonts
; i
++)
3991 if (! font_info
[i
].per_char
)
3997 /* See comment above. */
3998 if (n_matching_fonts
!= 0)
3999 fontname
= font_names
[i
];
4001 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
4004 /* Free the information from XListFontsWithInfo. */
4005 if (n_matching_fonts
)
4006 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
4010 /* Do we need to create the table? */
4011 if (x_font_table_size
== 0)
4013 x_font_table_size
= 16;
4015 = (XFontStruct
**) xmalloc (x_font_table_size
4016 * sizeof (x_font_table
[0]));
4018 /* Do we need to grow the table? */
4019 else if (n_fonts
>= x_font_table_size
)
4021 x_font_table_size
*= 2;
4023 = (XFontStruct
**) xrealloc (x_font_table
,
4025 * sizeof (x_font_table
[0])));
4028 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
4031 /* Now make the frame display the given font. */
4032 if (FRAME_X_WINDOW (f
) != 0)
4034 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
4035 f
->display
.x
->font
->fid
);
4036 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
4037 f
->display
.x
->font
->fid
);
4038 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
4039 f
->display
.x
->font
->fid
);
4041 x_set_window_size (f
, f
->width
, f
->height
);
4045 Lisp_Object lispy_name
= build_string (fontname
);
4048 /* Free the information from XListFontsWithInfo. The data
4049 we actually retain comes from XLoadQueryFont. */
4050 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
4055 #else /* ! defined (HAVE_X11) */
4056 x_new_font (f
, newname
)
4058 register char *newname
;
4063 temp
= XGetFont (newname
);
4064 if (temp
== (FONT_TYPE
*) 0)
4067 if (f
->display
.x
->font
)
4068 XLoseFont (f
->display
.x
->font
);
4070 f
->display
.x
->font
= temp
;
4072 if (FRAME_X_WINDOW (f
) != 0)
4073 x_set_window_size (f
, f
->width
, f
->height
);
4077 #endif /* ! defined (HAVE_X11) */
4079 /* X Window sizes and positions. */
4081 x_calc_absolute_position (f
)
4085 if (f
->display
.x
->left_pos
< 0)
4086 f
->display
.x
->left_pos
4087 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
4089 if (f
->display
.x
->top_pos
< 0)
4090 f
->display
.x
->top_pos
4091 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
4092 #else /* ! defined (HAVE_X11) */
4093 WINDOWINFO_TYPE parentinfo
;
4095 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
4097 if (f
->display
.x
->left_pos
< 0)
4098 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
4099 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
4101 if (f
->display
.x
->top_pos
< 0)
4102 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
4103 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
4104 #endif /* ! defined (HAVE_X11) */
4107 x_set_offset (f
, xoff
, yoff
)
4109 register int xoff
, yoff
;
4111 f
->display
.x
->top_pos
= yoff
;
4112 f
->display
.x
->left_pos
= xoff
;
4113 x_calc_absolute_position (f
);
4116 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4117 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4119 x_wm_set_size_hint (f
, 0);
4120 #endif /* ! defined (HAVE_X11) */
4124 /* Call this to change the size of frame F's x-window. */
4126 x_set_window_size (f
, cols
, rows
)
4130 int pixelwidth
, pixelheight
;
4135 check_frame_size (f
, &rows
, &cols
);
4136 f
->display
.x
->vertical_scroll_bar_extra
=
4137 (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4138 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
4140 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4141 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4144 x_wm_set_size_hint (f
, 0);
4145 #endif /* ! defined (HAVE_X11) */
4146 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4148 /* Now, strictly speaking, we can't be sure that this is accurate,
4149 but the window manager will get around to dealing with the size
4150 change request eventually, and we'll hear how it went when the
4151 ConfigureNotify event gets here.
4153 We could just not bother storing any of this information here,
4154 and let the ConfigureNotify event set everything up, but that
4155 might be kind of confusing to the lisp code, since size changes
4156 wouldn't be reported in the frame parameters until some random
4157 point in the future when the ConfigureNotify event arrives. */
4158 change_frame_size (f
, rows
, cols
, 0, 0);
4159 PIXEL_WIDTH (f
) = pixelwidth
;
4160 PIXEL_HEIGHT (f
) = pixelheight
;
4162 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4163 receive in the ConfigureNotify event; if we get what we asked
4164 for, then the event won't cause the screen to become garbaged, so
4165 we have to make sure to do it here. */
4166 SET_FRAME_GARBAGED (f
);
4173 x_set_resize_hint (f
)
4176 XSetResizeHint (FRAME_X_WINDOW (f
),
4177 2 * f
->display
.x
->internal_border_width
,
4178 2 * f
->display
.x
->internal_border_width
,
4179 FONT_WIDTH (f
->display
.x
->font
),
4180 FONT_HEIGHT (f
->display
.x
->font
));
4182 #endif /* HAVE_X11 */
4184 /* Mouse warping, focus shifting, raising and lowering. */
4186 x_set_mouse_position (f
, x
, y
)
4194 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4195 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4197 if (pix_x
< 0) pix_x
= 0;
4198 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4200 if (pix_y
< 0) pix_y
= 0;
4201 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4205 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4210 x_focus_on_frame (f
)
4215 /* I don't think that the ICCCM allows programs to do things like this
4216 without the interaction of the window manager. Whatever you end up
4217 doing with this code, do it to x_unfocus_frame too. */
4218 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4219 RevertToPointerRoot
, CurrentTime
);
4227 /* Look at the remarks in x_focus_on_frame. */
4228 if (x_focus_frame
== f
)
4229 XSetInputFocus (x_current_display
, PointerRoot
,
4230 RevertToPointerRoot
, CurrentTime
);
4234 #endif /* ! defined (HAVE_X11) */
4236 /* Raise frame F. */
4241 if (f
->async_visible
)
4244 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4250 /* Lower frame F. */
4255 if (f
->async_visible
)
4258 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4265 XTframe_raise_lower (f
, raise
)
4276 /* Change from withdrawn state to mapped state. */
4278 x_make_frame_visible (f
)
4285 if (! FRAME_VISIBLE_P (f
))
4288 if (! EQ (Vx_no_window_manager
, Qt
))
4289 x_wm_set_window_state (f
, NormalState
);
4291 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4292 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4293 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4294 #else /* ! defined (HAVE_X11) */
4295 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4296 if (f
->display
.x
->icon_desc
!= 0)
4297 XUnmapWindow (f
->display
.x
->icon_desc
);
4299 /* Handled by the MapNotify event for X11 */
4300 f
->async_visible
= 1;
4301 f
->async_iconified
= 0;
4303 /* NOTE: this may cause problems for the first frame. */
4305 #endif /* ! defined (HAVE_X11) */
4313 /* Change from mapped state to withdrawn state. */
4315 x_make_frame_invisible (f
)
4320 /* Don't keep the highlight on an invisible frame. */
4321 if (x_highlight_frame
== f
)
4322 x_highlight_frame
= 0;
4324 if (! f
->async_visible
&& ! f
->async_iconified
)
4331 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4332 DefaultScreen (x_current_display
)))
4334 UNBLOCK_INPUT_RESIGNAL
;
4335 error ("can't notify window manager of window withdrawal");
4338 #else /* ! defined (HAVE_X11R4) */
4341 /* Tell the window manager what we're going to do. */
4342 if (! EQ (Vx_no_window_manager
, Qt
))
4346 unmap
.xunmap
.type
= UnmapNotify
;
4347 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4348 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4349 unmap
.xunmap
.from_configure
= False
;
4350 if (! XSendEvent (x_current_display
,
4351 DefaultRootWindow (x_current_display
),
4353 SubstructureRedirectMask
|SubstructureNotifyMask
,
4356 UNBLOCK_INPUT_RESIGNAL
;
4357 error ("can't notify window manager of withdrawal");
4361 /* Unmap the window ourselves. Cheeky! */
4362 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4364 #else /* ! defined (HAVE_X11) */
4366 XUnmapWindow (FRAME_X_WINDOW (f
));
4367 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4368 if (f
->display
.x
->icon_desc
!= 0)
4369 XUnmapWindow (f
->display
.x
->icon_desc
);
4371 #endif /* ! defined (HAVE_X11) */
4372 #endif /* ! defined (HAVE_X11R4) */
4378 /* Change window state from mapped to iconified. */
4385 /* Don't keep the highlight on an invisible frame. */
4386 if (x_highlight_frame
== f
)
4387 x_highlight_frame
= 0;
4389 if (f
->async_iconified
)
4395 /* Since we don't know which revision of X we're running, we'll use both
4396 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4398 /* X11R4: send a ClientMessage to the window manager using the
4399 WM_CHANGE_STATE type. */
4403 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4404 message
.xclient
.type
= ClientMessage
;
4405 message
.xclient
.message_type
= Xatom_wm_change_state
;
4406 message
.xclient
.format
= 32;
4407 message
.xclient
.data
.l
[0] = IconicState
;
4409 if (! XSendEvent (x_current_display
,
4410 DefaultRootWindow (x_current_display
),
4412 SubstructureRedirectMask
| SubstructureNotifyMask
,
4415 UNBLOCK_INPUT_RESIGNAL
;
4416 error ("Can't notify window manager of iconification.");
4420 /* X11R3: set the initial_state field of the window manager hints to
4422 x_wm_set_window_state (f
, IconicState
);
4424 f
->async_iconified
= 1;
4425 #else /* ! defined (HAVE_X11) */
4426 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4428 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4429 if (f
->display
.x
->icon_desc
!= 0)
4431 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4434 #endif /* ! defined (HAVE_X11) */
4440 /* Destroy the X window of frame F. */
4442 x_destroy_window (f
)
4447 if (f
->display
.x
->icon_desc
!= 0)
4448 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4449 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4450 free_frame_faces (f
);
4453 xfree (f
->display
.x
);
4455 if (f
== x_focus_frame
)
4457 if (f
== x_highlight_frame
)
4458 x_highlight_frame
= 0;
4463 /* Manage event queues for X10. */
4467 /* Manage event queues.
4469 This code is only used by the X10 support.
4471 We cannot leave events in the X queue and get them when we are ready
4472 because X does not provide a subroutine to get only a certain kind
4473 of event but not block if there are no queued events of that kind.
4475 Therefore, we must examine events as they come in and copy events
4476 of certain kinds into our private queues.
4478 All ExposeRegion events are put in x_expose_queue.
4479 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4482 /* Write the event *P_XREP into the event queue *QUEUE.
4483 If the queue is full, do nothing, but return nonzero. */
4486 enqueue_event (p_xrep
, queue
)
4487 register XEvent
*p_xrep
;
4488 register struct event_queue
*queue
;
4490 int newindex
= queue
->windex
+ 1;
4491 if (newindex
== EVENT_BUFFER_SIZE
)
4493 if (newindex
== queue
->rindex
)
4495 queue
->xrep
[queue
->windex
] = *p_xrep
;
4496 queue
->windex
= newindex
;
4500 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4501 If *QUEUE is empty, do nothing and return 0. */
4504 dequeue_event (p_xrep
, queue
)
4505 register XEvent
*p_xrep
;
4506 register struct event_queue
*queue
;
4508 if (queue
->windex
== queue
->rindex
)
4510 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4511 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4516 /* Return the number of events buffered in *QUEUE. */
4519 queue_event_count (queue
)
4520 register struct event_queue
*queue
;
4522 int tem
= queue
->windex
- queue
->rindex
;
4525 return EVENT_BUFFER_SIZE
+ tem
;
4528 /* Return nonzero if mouse input is pending. */
4531 mouse_event_pending_p ()
4533 return queue_event_count (&x_mouse_queue
);
4535 #endif /* HAVE_X11 */
4537 /* Setting window manager hints. */
4541 x_wm_set_size_hint (f
, prompting
)
4545 XSizeHints size_hints
;
4546 Window window
= FRAME_X_WINDOW (f
);
4548 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
4550 flexlines
= f
->height
;
4552 size_hints
.x
= f
->display
.x
->left_pos
;
4553 size_hints
.y
= f
->display
.x
->top_pos
;
4554 size_hints
.height
= PIXEL_HEIGHT (f
);
4555 size_hints
.width
= PIXEL_WIDTH (f
);
4556 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4557 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4559 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4560 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4563 int base_width
, base_height
;
4565 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4566 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4569 int min_rows
= 0, min_cols
= 0;
4570 check_frame_size (f
, &min_rows
, &min_cols
);
4572 /* The window manager uses the base width hints to calculate the
4573 current number of rows and columns in the frame while
4574 resizing; min_width and min_height aren't useful for this
4575 purpose, since they might not give the dimensions for a
4576 zero-row, zero-column frame.
4578 We use the base_width and base_height members if we have
4579 them; otherwise, we set the min_width and min_height members
4580 to the size for a zero x zero frame. */
4583 size_hints
.flags
|= PBaseSize
;
4584 size_hints
.base_width
= base_width
;
4585 size_hints
.base_height
= base_height
;
4586 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4587 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4589 size_hints
.min_width
= base_width
;
4590 size_hints
.min_height
= base_height
;
4597 size_hints
.flags
|= prompting
;
4600 XSizeHints hints
; /* Sometimes I hate X Windows... */
4602 if (XGetNormalHints (x_current_display
, window
, &hints
) == 0)
4604 if (hints
.flags
& PSize
)
4605 size_hints
.flags
|= PSize
;
4606 if (hints
.flags
& PPosition
)
4607 size_hints
.flags
|= PPosition
;
4608 if (hints
.flags
& USPosition
)
4609 size_hints
.flags
|= USPosition
;
4610 if (hints
.flags
& USSize
)
4611 size_hints
.flags
|= USSize
;
4615 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4617 XSetNormalHints (x_current_display
, window
, &size_hints
);
4621 /* Used for IconicState or NormalState */
4622 x_wm_set_window_state (f
, state
)
4626 Window window
= FRAME_X_WINDOW (f
);
4628 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4629 f
->display
.x
->wm_hints
.initial_state
= state
;
4631 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4634 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4638 Window window
= FRAME_X_WINDOW (f
);
4642 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4643 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4646 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4648 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4651 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4655 Window window
= FRAME_X_WINDOW (f
);
4657 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4658 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4659 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4661 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4665 /* Initialization. */
4668 x_term_init (display_name
)
4674 extern int old_fcntl_owner
;
4675 #endif /* ! defined (F_SETOWN) */
4677 x_focus_frame
= x_highlight_frame
= 0;
4679 x_current_display
= XOpenDisplay (display_name
);
4680 if (x_current_display
== 0)
4681 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4686 int hostname_size
= 256;
4688 hostname
= (char *) xmalloc (hostname_size
);
4691 XSetAfterFunction (x_current_display
, x_trace_wire
);
4694 /* Try to get the host name; if the buffer is too short, try
4695 again. Apparently, the only indication gethostname gives of
4696 whether the buffer was large enough is the presence or absence
4697 of a '\0' in the string. Eech. */
4700 gethostname (hostname
, hostname_size
- 1);
4701 hostname
[hostname_size
- 1] = '\0';
4703 /* Was the buffer large enough for gethostname to store the '\0'? */
4704 if (strlen (hostname
) < hostname_size
- 1)
4707 hostname_size
<<= 1;
4708 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4710 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4713 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
4716 /* Figure out which modifier bits mean what. */
4717 x_find_modifier_meanings ();
4719 /* Get the scroll bar cursor. */
4720 x_vertical_scroll_bar_cursor
4721 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4724 /* Watch for PropertyNotify events on the root window; we use them
4725 to figure out when to invalidate our cache of the cut buffers. */
4726 x_watch_cut_buffer_cache ();
4729 if (ConnectionNumber (x_current_display
) != 0)
4731 dup2 (ConnectionNumber (x_current_display
), 0);
4733 #ifndef SYSV_STREAMS
4734 /* Streams somehow keeps track of which descriptor number
4735 is being used to talk to X. So it is not safe to substitute
4736 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4737 close (ConnectionNumber (x_current_display
));
4738 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4739 * check the def of the macro;
4740 * it is a genuine lvalue */
4741 #endif /* SYSV_STREAMS */
4744 #endif /* ! defined (HAVE_X11) */
4747 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4748 #ifdef F_SETOWN_SOCK_NEG
4749 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4750 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4751 fcntl (0, F_SETOWN
, getpid ());
4752 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4753 #endif /* ! defined (F_SETOWN) */
4757 #endif /* ! defined (SIGIO) */
4759 /* Must use interrupt input because we cannot otherwise
4760 arrange for C-g to be noticed immediately.
4761 We cannot connect it to SIGINT. */
4762 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4764 expose_all_windows
= 0;
4766 clear_frame_hook
= XTclear_frame
;
4767 clear_end_of_line_hook
= XTclear_end_of_line
;
4768 ins_del_lines_hook
= XTins_del_lines
;
4769 change_line_highlight_hook
= XTchange_line_highlight
;
4770 insert_glyphs_hook
= XTinsert_glyphs
;
4771 write_glyphs_hook
= XTwrite_glyphs
;
4772 delete_glyphs_hook
= XTdelete_glyphs
;
4773 ring_bell_hook
= XTring_bell
;
4774 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4775 set_terminal_modes_hook
= XTset_terminal_modes
;
4776 update_begin_hook
= XTupdate_begin
;
4777 update_end_hook
= XTupdate_end
;
4778 set_terminal_window_hook
= XTset_terminal_window
;
4779 read_socket_hook
= XTread_socket
;
4780 cursor_to_hook
= XTcursor_to
;
4781 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4782 mouse_position_hook
= XTmouse_position
;
4783 frame_rehighlight_hook
= XTframe_rehighlight
;
4784 frame_raise_lower_hook
= XTframe_raise_lower
;
4785 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
4786 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
4787 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
4788 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
4790 scroll_region_ok
= 1; /* we'll scroll partial frames */
4791 char_ins_del_ok
= 0; /* just as fast to write the line */
4792 line_ins_del_ok
= 1; /* we'll just blt 'em */
4793 fast_clear_end_of_line
= 1; /* X does this well */
4794 memory_below_frame
= 0; /* we don't remember what scrolls
4798 /* Note that there is no real way portable across R3/R4 to get the
4799 original error handler. */
4800 XHandleError (x_error_quitter
);
4801 XHandleIOError (x_io_error_quitter
);
4803 /* Disable Window Change signals; they are handled by X events. */
4805 signal (SIGWINCH
, SIG_DFL
);
4806 #endif /* ! defined (SIGWINCH) */
4808 signal (SIGPIPE
, x_connection_closed
);
4814 staticpro (&last_mouse_scroll_bar
);
4816 #endif /* ! defined (HAVE_X11) */
4817 #endif /* ! defined (HAVE_X_WINDOWS) */