1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 #define NEW_SELECTIONS
30 /* On 4.3 these lose if they come after xterm.h. */
31 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
32 /* Putting these at the beginning seems to be standard for other .c files. */
41 #include "blockinput.h"
43 /* This may include sys/types.h, and that somehow loses
44 if this is not done before the other system files. */
46 #include <X11/cursorfont.h>
49 /* Load sys/types.h if not already loaded.
50 In some systems loading it twice is suicidal. */
52 #include <sys/types.h>
57 #include <sys/ioctl.h>
59 #else /* ! defined (BSD) */
63 #endif /* ! defined (BSD) */
73 #include <sys/param.h>
75 #include "dispextern.h"
76 #include "termhooks.h"
90 #define XMapWindow XMapRaised /* Raise them when mapping. */
91 #else /* ! defined (HAVE_X11) */
92 #include <X/Xkeyboard.h>
93 /*#include <X/Xproto.h> */
94 #endif /* ! defined (HAVE_X11) */
97 /* We could get this from param.h, but better not to depend on finding that.
98 And better not to risk that it might define other symbols used in this
101 #define MAXDESC FD_SETSIZE
105 #define SELECT_TYPE fd_set
106 #else /* no FD_SET */
108 #define SELECT_TYPE int
110 /* Define the macros to access a single-int bitmap of descriptors. */
111 #define FD_SET(n, p) (*(p) |= (1 << (n)))
112 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
113 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
114 #define FD_ZERO(p) (*(p) = 0)
115 #endif /* no FD_SET */
117 /* For sending Meta-characters. Do we need this? */
120 #define min(a,b) ((a)<(b) ? (a) : (b))
121 #define max(a,b) ((a)>(b) ? (a) : (b))
123 /* Nonzero means we must reprint all windows
124 because 1) we received an ExposeWindow event
125 or 2) we received too many ExposeRegion events to record.
127 This is never needed under X11. */
128 static int expose_all_windows
;
130 /* Nonzero means we must reprint all icon windows. */
132 static int expose_all_icons
;
135 /* ExposeRegion events, when received, are copied into this queue
136 for later processing. */
138 static struct event_queue x_expose_queue
;
140 /* ButtonPressed and ButtonReleased events, when received,
141 are copied into this queue for later processing. */
143 struct event_queue x_mouse_queue
;
144 #endif /* HAVE_X11 */
146 #if defined (SIGIO) && defined (FIONREAD)
147 int BLOCK_INPUT_mask
;
148 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
150 /* The id of a bitmap used for icon windows.
151 One such map is shared by all Emacs icon windows.
152 This is zero if we have not yet had a need to create the bitmap. */
154 static Bitmap icon_bitmap
;
156 /* Font used for text icons. */
158 static FONT_TYPE
*icon_font_info
;
160 /* Stuff for dealing with the main icon title. */
162 extern Lisp_Object Vcommand_line_args
;
163 char *hostname
, *x_id_name
;
165 /* This is the X connection that we are using. */
167 Display
*x_current_display
;
169 /* The cursor to use for vertical scroll bars on x_current_display. */
170 static Cursor x_vertical_scroll_bar_cursor
;
172 /* Frame being updated by update_frame. This is declared in term.c.
173 This is set by update_begin and looked at by all the
174 XT functions. It is zero while not inside an update.
175 In that case, the XT functions assume that `selected_frame'
176 is the frame to apply to. */
177 extern struct frame
*updating_frame
;
179 /* The frame (if any) which has the X window that has keyboard focus.
180 Zero if none. This is examined by Ffocus_frame in frame.c. Note
181 that a mere EnterNotify event can set this; if you need to know the
182 last frame specified in a FocusIn or FocusOut event, use
183 x_focus_event_frame. */
184 struct frame
*x_focus_frame
;
186 /* The last frame mentioned in a FocusIn or FocusOut event. This is
187 separate from x_focus_frame, because whether or not LeaveNotify
188 events cause us to lose focus depends on whether or not we have
189 received a FocusIn event for it. */
190 struct frame
*x_focus_event_frame
;
192 /* The frame which currently has the visual highlight, and should get
193 keyboard input (other sorts of input have the frame encoded in the
194 event). It points to the X focus frame's selected window's
195 frame. It differs from x_focus_frame when we're using a global
197 static struct frame
*x_highlight_frame
;
199 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
200 mouse is moved to inside of frame when frame is de-iconified. */
202 static int warp_mouse_on_deiconify
;
204 /* During an update, maximum vpos for ins/del line operations to affect. */
206 static int flexlines
;
208 /* During an update, nonzero if chars output now should be highlighted. */
210 static int highlight
;
212 /* Nominal cursor position -- where to draw output.
213 During an update, these are different from the cursor-box position. */
219 /* `t' if a mouse button is depressed. */
221 extern Lisp_Object Vmouse_depressed
;
223 /* Tells if a window manager is present or not. */
225 extern Lisp_Object Vx_no_window_manager
;
227 /* Timestamp that we requested selection data was made. */
228 extern Time requestor_time
;
230 /* ID of the window requesting selection data. */
231 extern Window requestor_window
;
233 /* Nonzero enables some debugging for the X interface code. */
236 #else /* ! defined (HAVE_X11) */
238 /* Bit patterns for the mouse cursor. */
240 short MouseCursor
[] = {
241 0x0000, 0x0008, 0x0018, 0x0038,
242 0x0078, 0x00f8, 0x01f8, 0x03f8,
243 0x07f8, 0x00f8, 0x00d8, 0x0188,
244 0x0180, 0x0300, 0x0300, 0x0000};
246 short MouseMask
[] = {
247 0x000c, 0x001c, 0x003c, 0x007c,
248 0x00fc, 0x01fc, 0x03fc, 0x07fc,
249 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
250 0x03cc, 0x0780, 0x0780, 0x0300};
252 static short grey_bits
[] = {
253 0x0005, 0x000a, 0x0005, 0x000a};
255 static Pixmap GreyPixmap
= 0;
256 #endif /* ! defined (HAVE_X11) */
258 /* From time to time we get info on an Emacs window, here. */
260 static WINDOWINFO_TYPE windowinfo
;
264 /* A mask of extra modifier bits to put into every keyboard char. */
265 extern int extra_keyboard_modifiers
;
267 extern Display
*XOpenDisplay ();
268 extern Window
XCreateWindow ();
270 extern Cursor
XCreateCursor ();
271 extern FONT_TYPE
*XOpenFont ();
273 static void flashback ();
274 static void redraw_previous_char ();
277 static void dumpqueue ();
278 #endif /* HAVE_X11 */
281 static int XTcursor_to ();
282 static int XTclear_end_of_line ();
285 /* Starting and ending updates.
287 These hooks are called by update_frame at the beginning and end
288 of a frame update. We record in `updating_frame' the identity
289 of the frame being updated, so that the XT... functions do not
290 need to take a frame as argument. Most of the XT... functions
291 should never be called except during an update, the only exceptions
292 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
294 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
305 flexlines
= f
->height
;
311 #endif /* HAVE_X11 */
316 static void x_do_pending_expose ();
325 if (updating_frame
== 0
326 || updating_frame
!= f
)
332 x_do_pending_expose ();
333 #endif /* HAVE_X11 */
335 x_display_cursor (f
, 1);
341 /* External interface to control of standout mode.
342 Call this when about to modify line at position VPOS
343 and not change whether it is highlighted. */
345 XTreassert_line_highlight (new, vpos
)
351 /* Call this when about to modify line at position VPOS
352 and change whether it is highlighted. */
355 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
356 int new_highlight
, vpos
, first_unused_hpos
;
358 highlight
= new_highlight
;
359 XTcursor_to (vpos
, 0);
360 XTclear_end_of_line (updating_frame
->width
);
363 /* This is used when starting Emacs and when restarting after suspend.
364 When starting Emacs, no X window is mapped. And nothing must be done
365 to Emacs's own window if it is suspended (though that rarely happens). */
368 XTset_terminal_modes ()
372 /* This is called when exiting or suspending Emacs.
373 Exiting will make the X-windows go away, and suspending
374 requires no action. */
377 XTreset_terminal_modes ()
379 /* XTclear_frame (); */
382 /* Set the nominal cursor position of the frame.
383 This is where display update commands will take effect.
384 This does not affect the place where the cursor-box is displayed. */
387 XTcursor_to (row
, col
)
388 register int row
, col
;
396 if (updating_frame
== 0)
399 x_display_cursor (selected_frame
, 1);
405 /* Display a sequence of N glyphs found at GP.
406 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
407 HL is 1 if this text is highlighted, 2 if the cursor is on it.
409 FONT is the default font to use (for glyphs whose font-code is 0).
411 Since the display generation code is responsible for calling
412 compute_char_face and compute_glyph_face on everything it puts in
413 the display structure, we can assume that the face code on each
414 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
415 to which we can actually apply intern_face. */
418 /* This is the multi-face code. */
421 dumpglyphs (f
, left
, top
, gp
, n
, hl
)
424 register GLYPH
*gp
; /* Points to first GLYPH. */
425 register int n
; /* Number of glyphs to display. */
428 /* Holds characters to be displayed. */
429 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
430 register char *cp
; /* Steps through buf[]. */
431 register int tlen
= GLYPH_TABLE_LENGTH
;
432 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
433 Window window
= FRAME_X_WINDOW (f
);
437 /* Get the face-code of the next GLYPH. */
441 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
444 /* Find the run of consecutive glyphs with the same face-code.
445 Extract their character codes into BUF. */
450 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
451 if (GLYPH_FACE (g
) != cf
)
454 *cp
++ = GLYPH_CHAR (g
);
459 /* LEN gets the length of the run. */
462 /* Now output this run of chars, with the font and pixel values
463 determined by the face code CF. */
465 struct face
*face
= FRAME_DEFAULT_FACE (f
);
466 FONT_TYPE
*font
= FACE_FONT (face
);
467 GC gc
= FACE_GC (face
);
469 int gc_temporary
= 0;
471 /* First look at the face of the text itself. */
474 /* The face codes on the glyphs must be valid indices into the
475 frame's face table. */
476 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
477 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
481 face
= FRAME_MODE_LINE_FACE (f
);
483 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
484 font
= FACE_FONT (face
);
489 /* Then comes the distinction between modeline and normal text. */
494 face
= FRAME_MODE_LINE_FACE (f
);
495 font
= FACE_FONT (face
);
500 #define FACE_DEFAULT (~0)
502 /* Now override that if the cursor's on this character. */
507 || (int) face
->font
== FACE_DEFAULT
)
509 gc
= f
->display
.x
->cursor_gc
;
511 /* Cursor on non-default face: must merge. */
517 xgcv
.background
= f
->display
.x
->cursor_pixel
;
518 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
519 xgcv
.font
= face
->font
->fid
;
520 xgcv
.graphics_exposures
= 0;
521 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
522 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
525 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
526 XSetStipple (x_current_display
, gc
, face
->stipple
);
532 if ((int) font
== FACE_DEFAULT
)
533 font
= f
->display
.x
->font
;
535 XDrawImageString (x_current_display
, window
, gc
,
536 left
, top
+ FONT_BASE (font
), buf
, len
);
539 XFreeGC (x_current_display
, gc
);
541 /* We should probably check for XA_UNDERLINE_POSITION and
542 XA_UNDERLINE_THICKNESS properties on the font, but let's
543 just get the thing working, and come back to that. */
545 int underline_position
= 1;
547 if (font
->descent
<= underline_position
)
548 underline_position
= font
->descent
- 1;
551 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
555 + underline_position
),
556 len
* FONT_WIDTH (font
), 1);
559 left
+= len
* FONT_WIDTH (font
);
566 /* This is the old single-face code. */
569 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
572 register GLYPH
*gp
; /* Points to first GLYPH. */
573 register int n
; /* Number of glyphs to display. */
578 Window window
= FRAME_X_WINDOW (f
);
579 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
580 : (hl
? f
->display
.x
->reverse_gc
581 : f
->display
.x
->normal_gc
));
583 if (sizeof (GLYPH
) == sizeof (XChar2b
))
584 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
585 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
586 else if (sizeof (GLYPH
) == sizeof (unsigned char))
587 XDrawImageString (x_current_display
, window
, drawing_gc
,
588 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
590 /* What size of glyph ARE you using? And does X have a function to
596 /* Output some text at the nominal frame cursor position.
597 Advance the cursor over the text.
598 Output LEN glyphs at START.
600 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
601 controls the pixel values used for foreground and background. */
604 XTwrite_glyphs (start
, len
)
605 register GLYPH
*start
;
608 register int temp_length
;
618 /* If not within an update,
619 output at the frame's visible cursor. */
620 curs_x
= f
->cursor_x
;
621 curs_y
= f
->cursor_y
;
625 CHAR_TO_PIXEL_COL (f
, curs_x
),
626 CHAR_TO_PIXEL_ROW (f
, curs_y
),
627 start
, len
, highlight
);
629 /* If we drew on top of the cursor, note that it is turned off. */
630 if (curs_y
== f
->phys_cursor_y
631 && curs_x
<= f
->phys_cursor_x
632 && curs_x
+ len
> f
->phys_cursor_x
)
633 f
->phys_cursor_x
= -1;
635 if (updating_frame
== 0)
638 x_display_cursor (f
, 1);
647 /* Clear to the end of the line.
648 Erase the current text line from the nominal cursor position (inclusive)
649 to column FIRST_UNUSED (exclusive). The idea is that everything
650 from FIRST_UNUSED onward is already erased. */
653 XTclear_end_of_line (first_unused
)
654 register int first_unused
;
656 struct frame
*f
= updating_frame
;
662 if (curs_y
< 0 || curs_y
>= f
->height
)
664 if (first_unused
<= 0)
667 if (first_unused
>= f
->width
)
668 first_unused
= f
->width
;
672 /* Notice if the cursor will be cleared by this operation. */
673 if (curs_y
== f
->phys_cursor_y
674 && curs_x
<= f
->phys_cursor_x
675 && f
->phys_cursor_x
< first_unused
)
676 f
->phys_cursor_x
= -1;
679 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
680 CHAR_TO_PIXEL_COL (f
, curs_x
),
681 CHAR_TO_PIXEL_ROW (f
, curs_y
),
682 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
683 FONT_HEIGHT (f
->display
.x
->font
), False
);
685 redraw_previous_char (f
, curs_x
, curs_y
);
687 #else /* ! defined (HAVE_X11) */
688 XPixSet (FRAME_X_WINDOW (f
),
689 CHAR_TO_PIXEL_COL (f
, curs_x
),
690 CHAR_TO_PIXEL_ROW (f
, curs_y
),
691 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
692 FONT_HEIGHT (f
->display
.x
->font
),
693 f
->display
.x
->background_pixel
);
694 #endif /* ! defined (HAVE_X11) */
699 /* Erase the character (if any) at the position just before X, Y in frame F,
700 then redraw it and the character before it.
701 This is necessary when we erase starting at X,
702 in case the character after X overlaps into the one before X. */
705 redraw_previous_char (f
, x
, y
)
709 /* Erase the character before the new ones, in case
710 what was here before overlaps it.
711 Reoutput that character, and the previous character
712 (in case the previous character overlaps it). */
718 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
719 CHAR_TO_PIXEL_COL (f
, x
- 1),
720 CHAR_TO_PIXEL_ROW (f
, y
),
721 FONT_WIDTH (f
->display
.x
->font
),
722 FONT_HEIGHT (f
->display
.x
->font
), False
);
724 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
725 CHAR_TO_PIXEL_ROW (f
, y
),
726 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
727 x
- start_x
, highlight
);
735 struct frame
*f
= updating_frame
;
740 f
->phys_cursor_x
= -1; /* Cursor not visible. */
741 curs_x
= 0; /* Nominal cursor position is top left. */
746 XClear (FRAME_X_WINDOW (f
));
748 /* We have to clear the scroll bars, too. If we have changed
749 colors or something like that, then they should be notified. */
750 x_scroll_bar_clear (f
);
754 #endif /* HAVE_X11 */
760 /* Invert the middle quarter of the frame for .15 sec. */
762 /* We use the select system call to do the waiting, so we have to make sure
763 it's available. If it isn't, we just won't do visual bells. */
764 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
766 /* Subtract the `struct timeval' values X and Y,
767 storing the result in RESULT.
768 Return 1 if the difference is negative, otherwise 0. */
771 timeval_subtract (result
, x
, y
)
772 struct timeval
*result
, x
, y
;
774 /* Perform the carry for the later subtraction by updating y.
775 This is safer because on some systems
776 the tv_sec member is unsigned. */
777 if (x
.tv_usec
< y
.tv_usec
)
779 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
780 y
.tv_usec
-= 1000000 * nsec
;
783 if (x
.tv_usec
- y
.tv_usec
> 1000000)
785 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
786 y
.tv_usec
+= 1000000 * nsec
;
790 /* Compute the time remaining to wait. tv_usec is certainly positive. */
791 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
792 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
794 /* Return indication of whether the result should be considered negative. */
795 return x
.tv_sec
< y
.tv_sec
;
806 /* Create a GC that will use the GXxor function to flip foreground pixels
807 into background pixels. */
811 values
.function
= GXxor
;
812 values
.foreground
= (f
->display
.x
->foreground_pixel
813 ^ f
->display
.x
->background_pixel
);
815 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
816 GCFunction
| GCForeground
, &values
);
820 int width
= PIXEL_WIDTH (f
);
821 int height
= PIXEL_HEIGHT (f
);
823 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
824 width
/4, height
/4, width
/2, height
/2);
825 XFlush (x_current_display
);
828 struct timeval wakeup
, now
;
830 gettimeofday (&wakeup
, (struct timezone
*) 0);
832 /* Compute time to wait until, propagating carry from usecs. */
833 wakeup
.tv_usec
+= 150000;
834 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
835 wakeup
.tv_usec
%= 1000000;
837 /* Keep waiting until past the time wakeup. */
840 struct timeval timeout
;
842 gettimeofday (&timeout
, (struct timezone
*)0);
844 /* In effect, timeout = wakeup - timeout.
845 Break if result would be negative. */
846 if (timeval_subtract (&timeout
, wakeup
, timeout
))
849 /* Try to wait that long--but we might wake up sooner. */
850 select (0, 0, 0, 0, &timeout
);
854 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
855 width
/4, height
/4, width
/2, height
/2);
856 XFreeGC (x_current_display
, gc
);
857 XFlush (x_current_display
);
867 /* Make audible bell. */
870 #define XRINGBELL XBell(x_current_display, 0)
871 #else /* ! defined (HAVE_X11) */
872 #define XRINGBELL XFeep(0);
873 #endif /* ! defined (HAVE_X11) */
877 if (x_current_display
== 0)
880 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
882 XTflash (selected_frame
);
893 /* Insert and delete character.
894 These are not supposed to be used because we are supposed to turn
895 off the feature of using them. */
898 XTinsert_glyphs (start
, len
)
899 register char *start
;
912 /* Specify how many text lines, from the top of the window,
913 should be affected by insert-lines and delete-lines operations.
914 This, and those operations, are used only within an update
915 that is bounded by calls to XTupdate_begin and XTupdate_end. */
918 XTset_terminal_window (n
)
921 if (updating_frame
== 0)
924 if ((n
<= 0) || (n
> updating_frame
->height
))
925 flexlines
= updating_frame
->height
;
930 /* Perform an insert-lines operation.
931 Insert N lines at a vertical position curs_y. */
937 register int topregion
, bottomregion
;
938 register int length
, newtop
, mask
;
939 register struct frame
*f
= updating_frame
;
940 int intborder
= f
->display
.x
->internal_border_width
;
942 if (curs_y
>= flexlines
)
946 bottomregion
= flexlines
- (n
+ 1);
947 newtop
= topregion
+ n
;
948 length
= (bottomregion
- topregion
) + 1;
952 #endif /* HAVE_X11 */
954 if ((length
> 0) && (newtop
<= flexlines
))
957 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
958 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
959 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
960 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
961 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
962 CHAR_TO_PIXEL_ROW (f
, newtop
));
963 #else /* ! defined (HAVE_X11) */
964 XMoveArea (FRAME_X_WINDOW (f
),
965 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
966 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
967 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
968 length
* FONT_HEIGHT (f
->display
.x
->font
));
969 /* Now we must process any ExposeRegion events that occur
970 if the area being copied from is obscured.
971 We can't let it wait because further i/d operations
972 may want to copy this area to another area. */
974 #endif /* ! defined (HAVE_X11) */
977 newtop
= min (newtop
, (flexlines
- 1));
978 length
= newtop
- topregion
;
982 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
983 CHAR_TO_PIXEL_ROW (f
, topregion
),
984 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
985 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
986 #else /* ! defined (HAVE_X11) */
987 XPixSet (FRAME_X_WINDOW (f
),
989 CHAR_TO_PIXEL_ROW (f
, topregion
),
990 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
991 n
* FONT_HEIGHT (f
->display
.x
->font
),
992 f
->display
.x
->background_pixel
);
993 #endif /* ! defined (HAVE_X11) */
997 /* Perform a delete-lines operation, deleting N lines
998 at a vertical position curs_y. */
1005 register struct frame
*f
= updating_frame
;
1006 int intborder
= f
->display
.x
->internal_border_width
;
1008 if (curs_y
>= flexlines
)
1013 #endif /* HAVE_X11 */
1015 if ((curs_y
+ n
) >= flexlines
)
1017 if (flexlines
>= (curs_y
+ 1))
1020 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1021 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1022 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1023 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
1024 #else /* ! defined (HAVE_X11) */
1025 XPixSet (FRAME_X_WINDOW (f
),
1026 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1027 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1028 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
1029 f
->display
.x
->background_pixel
);
1030 #endif /* ! defined (HAVE_X11) */
1036 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1037 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1039 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1040 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1041 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
1042 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1043 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1045 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1046 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1047 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
1048 #else /* ! defined (HAVE_X11) */
1049 XMoveArea (FRAME_X_WINDOW (f
),
1051 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1052 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1053 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1054 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
1055 /* Now we must process any ExposeRegion events that occur
1056 if the area being copied from is obscured.
1057 We can't let it wait because further i/d operations
1058 may want to copy this area to another area. */
1060 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1061 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1062 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1063 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
1064 #endif /* ! defined (HAVE_X11) */
1068 /* Perform an insert-lines or delete-lines operation,
1069 inserting N lines or deleting -N lines at vertical position VPOS. */
1071 XTins_del_lines (vpos
, n
)
1074 if (updating_frame
== 0)
1077 /* Hide the cursor. */
1078 x_display_cursor (updating_frame
, 0);
1080 XTcursor_to (vpos
, 0);
1091 /* Support routines for exposure events. */
1092 static void clear_cursor ();
1094 /* Output into a rectangle of an X-window (for frame F)
1095 the characters in f->phys_lines that overlap that rectangle.
1096 TOP and LEFT are the position of the upper left corner of the rectangle.
1097 ROWS and COLS are the size of the rectangle. */
1100 dumprectangle (f
, left
, top
, cols
, rows
)
1102 register int left
, top
, cols
, rows
;
1104 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1105 int cursor_cleared
= 0;
1109 if (FRAME_GARBAGED_P (f
))
1112 /* Express rectangle as four edges, instead of position-and-size. */
1113 bottom
= top
+ rows
;
1114 right
= left
+ cols
;
1116 #ifndef HAVE_X11 /* Window manger does this for X11. */
1118 int intborder
= f
->display
.x
->internal_border_width
;
1120 /* If the rectangle includes any of the internal border area,
1121 redisplay the border emphasis. */
1122 if (top
< intborder
|| left
< intborder
1123 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1124 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1127 #endif /* HAVE_X11 Window manger does this for X11. */
1129 /* Convert rectangle edges in pixels to edges in chars.
1130 Round down for left and top, up for right and bottom. */
1131 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1132 left
= PIXEL_TO_CHAR_COL (f
, left
);
1133 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1134 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1135 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1136 right
= PIXEL_TO_CHAR_COL (f
, right
);
1138 /* Clip the rectangle to what can be visible. */
1143 if (right
> f
->width
)
1145 if (bottom
> f
->height
)
1148 /* Get size in chars of the rectangle. */
1149 cols
= right
- left
;
1150 rows
= bottom
- top
;
1152 /* If rectangle has zero area, return. */
1153 if (rows
<= 0) return;
1154 if (cols
<= 0) return;
1156 /* Turn off the cursor if it is in the rectangle.
1157 We will turn it back on afterward. */
1158 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1159 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1165 /* Display the text in the rectangle, one text line at a time. */
1167 for (y
= top
; y
< bottom
; y
++)
1169 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1171 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1175 CHAR_TO_PIXEL_COL (f
, left
),
1176 CHAR_TO_PIXEL_ROW (f
, y
),
1177 line
, min (cols
, active_frame
->used
[y
] - left
),
1178 active_frame
->highlight
[y
]);
1181 /* Turn the cursor on if we turned it off. */
1184 x_display_cursor (f
, 1);
1188 /* Process all queued ExposeRegion events. */
1194 XExposeRegionEvent r
;
1196 while (dequeue_event (&r
, &x_expose_queue
))
1198 struct frame
*f
= x_window_to_frame (r
.window
);
1199 if (f
->display
.x
->icon_desc
== r
.window
)
1202 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1206 #endif /* HAVE_X11 */
1208 /* Process all expose events that are pending, for X10.
1209 Redraws the cursor if necessary on any frame that
1210 is not in the process of being updated with update_frame. */
1214 x_do_pending_expose ()
1218 Lisp_Object tail
, frame
;
1220 if (expose_all_windows
)
1222 expose_all_windows
= 0;
1223 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1225 register int temp_width
, temp_height
;
1228 frame
= XCONS (tail
)->car
;
1229 if (XGCTYPE (frame
) != Lisp_Frame
)
1232 if (! FRAME_X_P (f
))
1234 if (!f
->async_visible
)
1236 if (!f
->display
.x
->needs_exposure
)
1239 intborder
= f
->display
.x
->internal_border_width
;
1242 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1243 temp_width
= ((windowinfo
.width
- 2 * intborder
1244 - f
->display
.x
->v_scroll_bar_width
)
1245 / FONT_WIDTH (f
->display
.x
->font
));
1246 temp_height
= ((windowinfo
.height
- 2 * intborder
1247 - f
->display
.x
->h_scroll_bar_height
)
1248 / FONT_HEIGHT (f
->display
.x
->font
));
1249 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1251 change_frame_size (f
, max (1, temp_height
),
1252 max (1, temp_width
), 0, 1);
1253 x_resize_scroll_bars (f
);
1255 f
->display
.x
->left_pos
= windowinfo
.x
;
1256 f
->display
.x
->top_pos
= windowinfo
.y
;
1257 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1261 f
->display
.x
->needs_exposure
= 0;
1262 if (updating_frame
!= f
)
1263 x_display_cursor (f
, 1);
1268 /* Handle any individual-rectangle expose events queued
1269 for various windows. */
1272 #else /* ! defined (HAVE_X11) */
1274 #endif /* ! defined (HAVE_X11) */
1280 frame_highlight (frame
)
1281 struct frame
*frame
;
1283 /* We used to only do this if Vx_no_window_manager was non-nil, but
1284 the ICCCM (section 4.1.6) says that the window's border pixmap
1285 and border pixel are window attributes which are "private to the
1286 client", so we can always change it to whatever we want. */
1288 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1289 frame
->display
.x
->border_pixel
);
1291 x_display_cursor (frame
, 1);
1295 frame_unhighlight (frame
)
1296 struct frame
*frame
;
1298 /* We used to only do this if Vx_no_window_manager was non-nil, but
1299 the ICCCM (section 4.1.6) says that the window's border pixmap
1300 and border pixel are window attributes which are "private to the
1301 client", so we can always change it to whatever we want. */
1303 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1304 frame
->display
.x
->border_tile
);
1306 x_display_cursor (frame
, 1);
1308 #else /* ! defined (HAVE_X11) */
1309 /* Dump the border-emphasis of frame F.
1310 If F is selected, this is a lining of the same color as the border,
1311 just within the border, occupying a portion of the internal border.
1312 If F is not selected, it is background in the same place.
1313 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1315 ALWAYS = 1 is used when a frame becomes selected or deselected.
1316 In that case, we also turn the cursor off and on again
1317 so it will appear in the proper shape (solid if selected; else hollow.) */
1320 dumpborder (f
, always
)
1324 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1325 int width
= PIXEL_WIDTH (f
);
1326 int height
= PIXEL_HEIGHT (f
);
1329 if (f
!= selected_frame
)
1334 pixel
= f
->display
.x
->background_pixel
;
1338 pixel
= f
->display
.x
->border_pixel
;
1341 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1342 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1343 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1345 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1349 x_display_cursor (f
, 1);
1351 #endif /* ! defined (HAVE_X11) */
1353 static void XTframe_rehighlight ();
1355 /* The focus has changed. Update the frames as necessary to reflect
1356 the new situation. Note that we can't change the selected frame
1357 here, because the lisp code we are interrupting might become confused.
1358 Each event gets marked with the frame in which it occurred, so the
1359 lisp code can tell when the switch took place by examining the events. */
1362 x_new_focus_frame (frame
)
1363 struct frame
*frame
;
1365 struct frame
*old_focus
= x_focus_frame
;
1366 int events_enqueued
= 0;
1368 if (frame
!= x_focus_frame
)
1370 /* Set this before calling other routines, so that they see
1371 the correct value of x_focus_frame. */
1372 x_focus_frame
= frame
;
1374 if (old_focus
&& old_focus
->auto_lower
)
1375 x_lower_frame (old_focus
);
1378 selected_frame
= frame
;
1379 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1380 Lisp_Frame
, selected_frame
);
1381 Fselect_window (selected_frame
->selected_window
);
1382 choose_minibuf_frame ();
1385 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1386 x_raise_frame (x_focus_frame
);
1389 XTframe_rehighlight ();
1393 /* The focus has changed, or we have redirected a frame's focus to
1394 another frame (this happens when a frame uses a surrogate
1395 minibuffer frame). Shift the highlight as appropriate. */
1397 XTframe_rehighlight ()
1399 struct frame
*old_highlight
= x_highlight_frame
;
1404 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1405 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1407 if (! FRAME_LIVE_P (x_highlight_frame
))
1409 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1410 x_highlight_frame
= x_focus_frame
;
1414 x_highlight_frame
= 0;
1416 if (x_highlight_frame
!= old_highlight
)
1419 frame_unhighlight (old_highlight
);
1420 if (x_highlight_frame
)
1421 frame_highlight (x_highlight_frame
);
1425 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1427 /* Which modifier keys are on which modifier bits?
1429 With each keystroke, X returns eight bits indicating which modifier
1430 keys were held down when the key was pressed. The interpretation
1431 of the top five modifier bits depends on what keys are attached
1432 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1435 x_meta_mod_mask is a mask containing the bits used for the meta key.
1436 It may have more than one bit set, if more than one modifier bit
1437 has meta keys on it. Basically, if EVENT is a KeyPress event,
1438 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1440 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1441 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1442 only be affected by the lock modifier bit if XK_Shift_Lock is in
1443 use; XK_Caps_Lock should only affect alphabetic keys. With this
1444 arrangement, the lock modifier should shift the character if
1445 (EVENT.state & x_shift_lock_mask) != 0. */
1446 static int x_meta_mod_mask
, x_shift_lock_mask
;
1448 /* These are like x_meta_mod_mask, but for different modifiers. */
1449 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1451 /* Initialize mode_switch_bit and modifier_meaning. */
1453 x_find_modifier_meanings ()
1455 int min_code
, max_code
;
1458 XModifierKeymap
*mods
;
1460 x_meta_mod_mask
= 0;
1461 x_shift_lock_mask
= 0;
1463 x_super_mod_mask
= 0;
1464 x_hyper_mod_mask
= 0;
1467 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1469 min_code
= x_current_display
->min_keycode
;
1470 max_code
= x_current_display
->max_keycode
;
1473 syms
= XGetKeyboardMapping (x_current_display
,
1474 min_code
, max_code
- min_code
+ 1,
1476 mods
= XGetModifierMapping (x_current_display
);
1478 /* Scan the modifier table to see which modifier bits the Meta and
1479 Alt keysyms are on. */
1481 int row
, col
; /* The row and column in the modifier table. */
1483 for (row
= 3; row
< 8; row
++)
1484 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1487 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1489 /* Are any of this keycode's keysyms a meta key? */
1493 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1495 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1501 x_meta_mod_mask
|= (1 << row
);
1506 x_alt_mod_mask
|= (1 << row
);
1511 x_hyper_mod_mask
|= (1 << row
);
1516 x_super_mod_mask
|= (1 << row
);
1520 /* Ignore this if it's not on the lock modifier. */
1521 if ((1 << row
) == LockMask
)
1522 x_shift_lock_mask
= LockMask
;
1530 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1531 if (! x_meta_mod_mask
)
1533 x_meta_mod_mask
= x_alt_mod_mask
;
1537 /* If some keys are both alt and meta,
1538 make them just meta, not alt. */
1539 if (x_alt_mod_mask
& x_meta_mod_mask
)
1541 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1544 XFree ((char *) syms
);
1545 XFreeModifiermap (mods
);
1549 /* Convert between the modifier bits X uses and the modifier bits
1552 x_x_to_emacs_modifiers (state
)
1555 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1556 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1557 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1558 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1559 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1560 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1564 x_emacs_to_x_modifiers (state
)
1567 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1568 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1569 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1570 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1571 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1572 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1575 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1576 return as a function key. If you add a keysym to this, you should
1577 make sure that the tables make_lispy_event uses contain a suitable
1580 x_is_vendor_fkey (sym
)
1585 || (sym
== DXK_Remove
)
1591 /* Mouse clicks and mouse movement. Rah. */
1594 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1595 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1596 that the glyph at X, Y occupies, if BOUNDS != 0. */
1598 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1600 register unsigned int pix_x
, pix_y
;
1601 register int *x
, *y
;
1604 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1605 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1609 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1610 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1611 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1612 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1615 if (pix_x
< 0) pix_x
= 0;
1616 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1618 if (pix_y
< 0) pix_y
= 0;
1619 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1625 /* Any buttons grabbed. */
1626 unsigned int x_mouse_grabbed
;
1628 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1630 If the event is a button press, then note that we have grabbed
1634 construct_mouse_click (result
, event
, f
)
1635 struct input_event
*result
;
1636 XButtonEvent
*event
;
1639 /* Make the event type no_event; we'll change that when we decide
1641 result
->kind
= mouse_click
;
1642 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1643 result
->timestamp
= event
->time
;
1644 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1645 | (event
->type
== ButtonRelease
1649 /* Notice if the mouse is still grabbed. */
1650 if (event
->type
== ButtonPress
)
1652 if (! x_mouse_grabbed
)
1653 Vmouse_depressed
= Qt
;
1654 x_mouse_grabbed
|= (1 << event
->button
);
1656 else if (event
->type
== ButtonRelease
)
1658 x_mouse_grabbed
&= ~(1 << event
->button
);
1659 if (!x_mouse_grabbed
)
1660 Vmouse_depressed
= Qnil
;
1666 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1667 XFASTINT (result
->x
) = column
;
1668 XFASTINT (result
->y
) = row
;
1669 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1674 /* Mouse movement. Rah.
1676 In order to avoid asking for motion events and then throwing most
1677 of them away or busy-polling the server for mouse positions, we ask
1678 the server for pointer motion hints. This means that we get only
1679 one event per group of mouse movements. "Groups" are delimited by
1680 other kinds of events (focus changes and button clicks, for
1681 example), or by XQueryPointer calls; when one of these happens, we
1682 get another MotionNotify event the next time the mouse moves. This
1683 is at least as efficient as getting motion events when mouse
1684 tracking is on, and I suspect only negligibly worse when tracking
1687 The silly O'Reilly & Associates Nutshell guides barely document
1688 pointer motion hints at all (I think you have to infer how they
1689 work from an example), and the description of XQueryPointer doesn't
1690 mention that calling it causes you to get another motion hint from
1691 the server, which is very important. */
1693 /* Where the mouse was last time we reported a mouse event. */
1694 static FRAME_PTR last_mouse_frame
;
1695 static XRectangle last_mouse_glyph
;
1697 /* The scroll bar in which the last X motion event occurred.
1699 If the last X motion event occurred in a scroll bar, we set this
1700 so XTmouse_position can know whether to report a scroll bar motion or
1703 If the last X motion event didn't occur in a scroll bar, we set this
1704 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1705 static Lisp_Object last_mouse_scroll_bar
;
1707 /* This is a hack. We would really prefer that XTmouse_position would
1708 return the time associated with the position it returns, but there
1709 doesn't seem to be any way to wrest the timestamp from the server
1710 along with the position query. So, we just keep track of the time
1711 of the last movement we received, and return that in hopes that
1712 it's somewhat accurate. */
1713 static Time last_mouse_movement_time
;
1715 /* Function to report a mouse movement to the mainstream Emacs code.
1716 The input handler calls this.
1718 We have received a mouse movement event, which is given in *event.
1719 If the mouse is over a different glyph than it was last time, tell
1720 the mainstream emacs code by setting mouse_moved. If not, ask for
1721 another motion event, so we can check again the next time it moves. */
1723 note_mouse_movement (frame
, event
)
1725 XMotionEvent
*event
;
1728 last_mouse_movement_time
= event
->time
;
1730 /* Has the mouse moved off the glyph it was on at the last sighting? */
1731 if (event
->x
< last_mouse_glyph
.x
1732 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1733 || event
->y
< last_mouse_glyph
.y
1734 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1737 last_mouse_scroll_bar
= Qnil
;
1741 /* It's on the same glyph. Call XQueryPointer so we'll get an
1742 event the next time the mouse moves and we can see if it's
1743 *still* on the same glyph. */
1746 XQueryPointer (event
->display
, event
->window
,
1747 (Window
*) &dummy
, (Window
*) &dummy
,
1748 &dummy
, &dummy
, &dummy
, &dummy
,
1749 (unsigned int *) &dummy
);
1753 static struct scroll_bar
*x_window_to_scroll_bar ();
1754 static void x_scroll_bar_report_motion ();
1756 /* Return the current position of the mouse.
1758 If the mouse movement started in a scroll bar, set *f, *bar_window,
1759 and *part to the frame, window, and scroll bar part that the mouse
1760 is over. Set *x and *y to the portion and whole of the mouse's
1761 position on the scroll bar.
1763 If the mouse movement started elsewhere, set *f to the frame the
1764 mouse is on, *bar_window to nil, and *x and *y to the character cell
1767 Set *time to the server timestamp for the time at which the mouse
1768 was at this position.
1770 Don't store anything if we don't have a valid set of values to report.
1772 This clears the mouse_moved flag, so we can wait for the next mouse
1773 movement. This also calls XQueryPointer, which will cause the
1774 server to give us another MotionNotify when the mouse moves
1778 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1780 Lisp_Object
*bar_window
;
1781 enum scroll_bar_part
*part
;
1783 unsigned long *time
;
1789 if (! NILP (last_mouse_scroll_bar
))
1790 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1796 Window dummy_window
;
1800 last_mouse_scroll_bar
= Qnil
;
1802 /* Figure out which root window we're on. */
1803 XQueryPointer (x_current_display
,
1804 DefaultRootWindow (x_current_display
),
1806 /* The root window which contains the pointer. */
1809 /* Trash which we can't trust if the pointer is on
1810 a different screen. */
1813 /* The position on that root window. */
1816 /* More trash we can't trust. */
1819 /* Modifier keys and pointer buttons, about which
1821 (unsigned int *) &dummy
);
1823 /* Now we have a position on the root; find the innermost window
1824 containing the pointer. */
1828 int parent_x
, parent_y
;
1833 XTranslateCoordinates (x_current_display
,
1835 /* From-window, to-window. */
1838 /* From-position, to-position. */
1839 root_x
, root_y
, &win_x
, &win_y
,
1852 /* Now we know that:
1853 win is the innermost window containing the pointer
1854 (XTC says it has no child containing the pointer),
1855 win_x and win_y are the pointer's position in it
1856 (XTC did this the last time through), and
1857 parent_x and parent_y are the pointer's position in win's parent.
1858 (They are what win_x and win_y were when win was child.
1859 If win is the root window, it has no parent, and
1860 parent_{x,y} are invalid, but that's okay, because we'll
1861 never use them in that case.) */
1863 /* Is win one of our frames? */
1864 f1
= x_window_to_frame (win
);
1866 /* If not, is it one of our scroll bars? */
1869 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1873 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1881 /* Ok, we found a frame. Convert from pixels to characters
1882 and store all the values. */
1884 pixel_to_glyph_coords (f1
, win_x
, win_y
, &win_x
, &win_y
,
1890 XSET (*x
, Lisp_Int
, win_x
);
1891 XSET (*y
, Lisp_Int
, win_y
);
1892 *time
= last_mouse_movement_time
;
1900 #else /* ! defined (HAVE_X11) */
1901 #define XEvent XKeyPressedEvent
1902 #endif /* ! defined (HAVE_X11) */
1904 /* Scroll bar support. */
1906 /* Given an X window ID, find the struct scroll_bar which manages it.
1907 This can be called in GC, so we have to make sure to strip off mark
1909 static struct scroll_bar
*
1910 x_window_to_scroll_bar (window_id
)
1913 Lisp_Object tail
, frame
;
1915 for (tail
= Vframe_list
;
1916 XGCTYPE (tail
) == Lisp_Cons
;
1917 tail
= XCONS (tail
)->cdr
)
1919 Lisp_Object frame
= XCONS (tail
)->car
;
1920 Lisp_Object bar
, condemned
;
1922 /* All elements of Vframe_list should be frames. */
1923 if (XGCTYPE (frame
) != Lisp_Frame
)
1926 /* Scan this frame's scroll bar list for a scroll bar with the
1928 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1929 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1930 /* This trick allows us to search both the ordinary and
1931 condemned scroll bar lists with one loop. */
1932 ! GC_NILP (bar
) || (bar
= condemned
,
1935 bar
= XSCROLL_BAR(bar
)->next
)
1936 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1937 return XSCROLL_BAR (bar
);
1943 /* Open a new X window to serve as a scroll bar, and return the
1944 scroll bar vector for it. */
1945 static struct scroll_bar
*
1946 x_scroll_bar_create (window
, top
, left
, width
, height
)
1947 struct window
*window
;
1948 int top
, left
, width
, height
;
1950 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1951 struct scroll_bar
*bar
=
1952 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1957 XSetWindowAttributes a
;
1960 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1961 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1962 | ButtonMotionMask
| PointerMotionHintMask
1964 a
.cursor
= x_vertical_scroll_bar_cursor
;
1966 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1968 SET_SCROLL_BAR_X_WINDOW
1970 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1972 /* Position and size of scroll bar. */
1973 left
, top
, width
, height
,
1975 /* Border width, depth, class, and visual. */
1976 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1982 XSET (bar
->window
, Lisp_Window
, window
);
1983 XSET (bar
->top
, Lisp_Int
, top
);
1984 XSET (bar
->left
, Lisp_Int
, left
);
1985 XSET (bar
->width
, Lisp_Int
, width
);
1986 XSET (bar
->height
, Lisp_Int
, height
);
1987 XSET (bar
->start
, Lisp_Int
, 0);
1988 XSET (bar
->end
, Lisp_Int
, 0);
1989 bar
->dragging
= Qnil
;
1991 /* Add bar to its frame's list of scroll bars. */
1992 bar
->next
= FRAME_SCROLL_BARS (frame
);
1994 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
1995 if (! NILP (bar
->next
))
1996 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1998 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2005 /* Draw BAR's handle in the proper position.
2006 If the handle is already drawn from START to END, don't bother
2007 redrawing it, unless REBUILD is non-zero; in that case, always
2008 redraw it. (REBUILD is handy for drawing the handle after expose
2011 Normally, we want to constrain the start and end of the handle to
2012 fit inside its rectangle, but if the user is dragging the scroll bar
2013 handle, we want to let them drag it down all the way, so that the
2014 bar's top is as far down as it goes; otherwise, there's no way to
2015 move to the very end of the buffer. */
2017 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2018 struct scroll_bar
*bar
;
2022 int dragging
= ! NILP (bar
->dragging
);
2023 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2024 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2026 /* If the display is already accurate, do nothing. */
2028 && start
== XINT (bar
->start
)
2029 && end
== XINT (bar
->end
))
2035 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2036 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2037 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2039 /* Make sure the values are reasonable, and try to preserve
2040 the distance between start and end. */
2042 int length
= end
- start
;
2046 else if (start
> top_range
)
2048 end
= start
+ length
;
2052 else if (end
> top_range
&& ! dragging
)
2056 /* Store the adjusted setting in the scroll bar. */
2057 XSET (bar
->start
, Lisp_Int
, start
);
2058 XSET (bar
->end
, Lisp_Int
, end
);
2060 /* Clip the end position, just for display. */
2061 if (end
> top_range
)
2064 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2065 below top positions, to make sure the handle is always at least
2066 that many pixels tall. */
2067 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2069 /* Draw the empty space above the handle. Note that we can't clear
2070 zero-height areas; that means "clear to end of window." */
2072 XClearArea (x_current_display
, w
,
2074 /* x, y, width, height, and exposures. */
2075 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2076 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2077 inside_width
, start
,
2080 /* Draw the handle itself. */
2081 XFillRectangle (x_current_display
, w
, gc
,
2083 /* x, y, width, height */
2084 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2085 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2086 inside_width
, end
- start
);
2089 /* Draw the empty space below the handle. Note that we can't
2090 clear zero-height areas; that means "clear to end of window." */
2091 if (end
< inside_height
)
2092 XClearArea (x_current_display
, w
,
2094 /* x, y, width, height, and exposures. */
2095 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2096 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2097 inside_width
, inside_height
- end
,
2105 /* Move a scroll bar around on the screen, to accommodate changing
2106 window configurations. */
2108 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2109 struct scroll_bar
*bar
;
2110 int top
, left
, width
, height
;
2116 unsigned int mask
= 0;
2123 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2124 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2125 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2126 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2129 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2133 XSET (bar
->left
, Lisp_Int
, left
);
2134 XSET (bar
->top
, Lisp_Int
, top
);
2135 XSET (bar
->width
, Lisp_Int
, width
);
2136 XSET (bar
->height
, Lisp_Int
, height
);
2141 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2144 x_scroll_bar_remove (bar
)
2145 struct scroll_bar
*bar
;
2147 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2151 /* Destroy the window. */
2152 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2154 /* Disassociate this scroll bar from its window. */
2155 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2160 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2161 that we are displaying PORTION characters out of a total of WHOLE
2162 characters, starting at POSITION. If WINDOW has no scroll bar,
2165 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2166 struct window
*window
;
2167 int portion
, whole
, position
;
2169 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2170 int top
= XINT (window
->top
);
2171 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2172 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2174 /* Where should this scroll bar be, pixelwise? */
2175 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2176 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2177 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2178 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2180 struct scroll_bar
*bar
;
2182 /* Does the scroll bar exist yet? */
2183 if (NILP (window
->vertical_scroll_bar
))
2184 bar
= x_scroll_bar_create (window
,
2185 pixel_top
, pixel_left
,
2186 pixel_width
, pixel_height
);
2189 /* It may just need to be moved and resized. */
2190 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2191 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2194 /* Set the scroll bar's current state, unless we're currently being
2196 if (NILP (bar
->dragging
))
2199 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2202 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2205 int start
= ((double) position
* top_range
) / whole
;
2206 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2208 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2212 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2216 /* The following three hooks are used when we're doing a thorough
2217 redisplay of the frame. We don't explicitly know which scroll bars
2218 are going to be deleted, because keeping track of when windows go
2219 away is a real pain - "Can you say set-window-configuration, boys
2220 and girls?" Instead, we just assert at the beginning of redisplay
2221 that *all* scroll bars are to be removed, and then save a scroll bar
2222 from the fiery pit when we actually redisplay its window. */
2224 /* Arrange for all scroll bars on FRAME to be removed at the next call
2225 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2226 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2228 XTcondemn_scroll_bars (frame
)
2231 /* The condemned list should be empty at this point; if it's not,
2232 then the rest of Emacs isn't using the condemn/redeem/judge
2233 protocol correctly. */
2234 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2237 /* Move them all to the "condemned" list. */
2238 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2239 FRAME_SCROLL_BARS (frame
) = Qnil
;
2242 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2243 Note that WINDOW isn't necessarily condemned at all. */
2245 XTredeem_scroll_bar (window
)
2246 struct window
*window
;
2248 struct scroll_bar
*bar
;
2250 /* We can't redeem this window's scroll bar if it doesn't have one. */
2251 if (NILP (window
->vertical_scroll_bar
))
2254 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2256 /* Unlink it from the condemned list. */
2258 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2260 if (NILP (bar
->prev
))
2262 /* If the prev pointer is nil, it must be the first in one of
2264 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2265 /* It's not condemned. Everything's fine. */
2267 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2268 window
->vertical_scroll_bar
))
2269 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2271 /* If its prev pointer is nil, it must be at the front of
2272 one or the other! */
2276 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2278 if (! NILP (bar
->next
))
2279 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2281 bar
->next
= FRAME_SCROLL_BARS (f
);
2283 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2284 if (! NILP (bar
->next
))
2285 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2289 /* Remove all scroll bars on FRAME that haven't been saved since the
2290 last call to `*condemn_scroll_bars_hook'. */
2292 XTjudge_scroll_bars (f
)
2295 Lisp_Object bar
, next
;
2297 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2299 /* Clear out the condemned list now so we won't try to process any
2300 more events on the hapless scroll bars. */
2301 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2303 for (; ! NILP (bar
); bar
= next
)
2305 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2307 x_scroll_bar_remove (b
);
2310 b
->next
= b
->prev
= Qnil
;
2313 /* Now there should be no references to the condemned scroll bars,
2314 and they should get garbage-collected. */
2318 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2320 This may be called from a signal handler, so we have to ignore GC
2323 x_scroll_bar_expose (bar
, event
)
2324 struct scroll_bar
*bar
;
2327 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2328 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2332 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2334 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2335 XDrawRectangle (x_current_display
, w
, gc
,
2337 /* x, y, width, height */
2338 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2340 /* Draw another line to make the extra-thick border on the right. */
2341 XFillRectangle (x_current_display
, w
, gc
,
2343 /* x, y, width, height */
2344 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2349 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2350 is set to something other than no_event, it is enqueued.
2352 This may be called from a signal handler, so we have to ignore GC
2355 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2356 struct scroll_bar
*bar
;
2358 struct input_event
*emacs_event
;
2360 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2363 emacs_event
->kind
= scroll_bar_click
;
2364 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2365 emacs_event
->modifiers
=
2366 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2367 | (event
->type
== ButtonRelease
2370 emacs_event
->frame_or_window
= bar
->window
;
2371 emacs_event
->timestamp
= event
->xbutton
.time
;
2373 int internal_height
=
2374 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2376 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2377 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2380 if (y
> top_range
) y
= top_range
;
2382 if (y
< XINT (bar
->start
))
2383 emacs_event
->part
= scroll_bar_above_handle
;
2384 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2385 emacs_event
->part
= scroll_bar_handle
;
2387 emacs_event
->part
= scroll_bar_below_handle
;
2389 /* Just because the user has clicked on the handle doesn't mean
2390 they want to drag it. Lisp code needs to be able to decide
2391 whether or not we're dragging. */
2393 /* If the user has just clicked on the handle, record where they're
2395 if (event
->type
== ButtonPress
2396 && emacs_event
->part
== scroll_bar_handle
)
2397 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2400 /* If the user has released the handle, set it to its final position. */
2401 if (event
->type
== ButtonRelease
2402 && ! NILP (bar
->dragging
))
2404 int new_start
= y
- XINT (bar
->dragging
);
2405 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2407 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2408 bar
->dragging
= Qnil
;
2411 /* Same deal here as the other #if 0. */
2413 /* Clicks on the handle are always reported as occurring at the top of
2415 if (emacs_event
->part
== scroll_bar_handle
)
2416 emacs_event
->x
= bar
->start
;
2418 XSET (emacs_event
->x
, Lisp_Int
, y
);
2420 XSET (emacs_event
->x
, Lisp_Int
, y
);
2423 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2427 /* Handle some mouse motion while someone is dragging the scroll bar.
2429 This may be called from a signal handler, so we have to ignore GC
2432 x_scroll_bar_note_movement (bar
, event
)
2433 struct scroll_bar
*bar
;
2436 last_mouse_movement_time
= event
->xmotion
.time
;
2439 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2441 /* If we're dragging the bar, display it. */
2442 if (! GC_NILP (bar
->dragging
))
2444 /* Where should the handle be now? */
2445 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2447 if (new_start
!= XINT (bar
->start
))
2449 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2451 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2455 /* Call XQueryPointer so we'll get an event the next time the mouse
2456 moves and we can see *still* on the same position. */
2460 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2461 (Window
*) &dummy
, (Window
*) &dummy
,
2462 &dummy
, &dummy
, &dummy
, &dummy
,
2463 (unsigned int *) &dummy
);
2467 /* Return information to the user about the current position of the mouse
2468 on the scroll bar. */
2470 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2472 Lisp_Object
*bar_window
;
2473 enum scroll_bar_part
*part
;
2475 unsigned long *time
;
2477 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2479 Window dummy_window
;
2481 unsigned int dummy_mask
;
2485 /* Get the mouse's position relative to the scroll bar window, and
2487 if (! XQueryPointer (x_current_display
,
2488 SCROLL_BAR_X_WINDOW (bar
),
2490 /* Root, child, root x and root y. */
2491 &dummy_window
, &dummy_window
,
2492 &dummy_coord
, &dummy_coord
,
2494 /* Position relative to scroll bar. */
2497 /* Mouse buttons and modifier keys. */
2503 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2505 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2507 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2509 if (! NILP (bar
->dragging
))
2510 win_y
-= XINT (bar
->dragging
);
2514 if (win_y
> top_range
)
2517 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2518 *bar_window
= bar
->window
;
2520 if (! NILP (bar
->dragging
))
2521 *part
= scroll_bar_handle
;
2522 else if (win_y
< XINT (bar
->start
))
2523 *part
= scroll_bar_above_handle
;
2524 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2525 *part
= scroll_bar_handle
;
2527 *part
= scroll_bar_below_handle
;
2529 XSET (*x
, Lisp_Int
, win_y
);
2530 XSET (*y
, Lisp_Int
, top_range
);
2533 last_mouse_scroll_bar
= Qnil
;
2536 *time
= last_mouse_movement_time
;
2542 /* The screen has been cleared so we may have changed foreground or
2543 background colors, and the scroll bars may need to be redrawn.
2544 Clear out the scroll bars, and ask for expose events, so we can
2547 x_scroll_bar_clear (f
)
2552 for (bar
= FRAME_SCROLL_BARS (f
);
2553 XTYPE (bar
) == Lisp_Vector
;
2554 bar
= XSCROLL_BAR (bar
)->next
)
2555 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2561 /* The main X event-reading loop - XTread_socket. */
2563 /* Timestamp of enter window event. This is only used by XTread_socket,
2564 but we have to put it out here, since static variables within functions
2565 sometimes don't work. */
2566 static Time enter_timestamp
;
2568 /* This holds the state XLookupString needs to implement dead keys
2569 and other tricks known as "compose processing". _X Window System_
2570 says that a portable program can't use this, but Stephen Gildea assures
2571 me that letting the compiler initialize it to zeros will work okay.
2573 This must be defined outside of XTread_socket, for the same reasons
2574 given for enter_timestamp, above. */
2575 static XComposeStatus compose_status
;
2577 /* Communication with window managers. */
2578 Atom Xatom_wm_protocols
;
2580 /* Kinds of protocol things we may receive. */
2581 Atom Xatom_wm_take_focus
;
2582 Atom Xatom_wm_save_yourself
;
2583 Atom Xatom_wm_delete_window
;
2585 /* Other WM communication */
2586 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2587 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2589 /* Window manager communication. */
2590 Atom Xatom_wm_change_state
;
2592 /* Record the last 100 characters stored
2593 to help debug the loss-of-chars-during-GC problem. */
2595 short temp_buffer
[100];
2597 /* Read events coming from the X server.
2598 This routine is called by the SIGIO handler.
2599 We return as soon as there are no more events to be read.
2601 Events representing keys are stored in buffer BUFP,
2602 which can hold up to NUMCHARS characters.
2603 We return the number of characters stored into the buffer,
2604 thus pretending to be `read'.
2606 WAITP is nonzero if we should block until input arrives.
2607 EXPECTED is nonzero if the caller knows input is available. */
2610 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2612 register struct input_event
*bufp
;
2613 register int numchars
;
2620 int items_pending
; /* How many items are in the X queue. */
2623 int event_found
= 0;
2627 if (interrupt_input_blocked
)
2629 interrupt_input_pending
= 1;
2633 interrupt_input_pending
= 0;
2637 abort (); /* Don't think this happens. */
2640 /* If available, Xlib uses FIOSNBIO to make the socket
2641 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2642 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2643 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2644 fcntl (fileno (stdin
), F_SETFL
, 0);
2645 #endif /* ! defined (FIOSNBIO) */
2649 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2651 extern int read_alarm_should_throw
;
2652 read_alarm_should_throw
= 1;
2653 XPeekEvent (XDISPLAY
&event
);
2654 read_alarm_should_throw
= 0;
2656 #endif /* HAVE_SELECT */
2659 while (XStuffPending () != 0)
2661 XNextEvent (XDISPLAY
&event
);
2669 if (event
.xclient
.message_type
== Xatom_wm_protocols
2670 && event
.xclient
.format
== 32)
2672 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2674 f
= x_window_to_frame (event
.xclient
.window
);
2676 x_focus_on_frame (f
);
2677 /* Not certain about handling scroll bars here */
2679 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2681 /* Save state modify the WM_COMMAND property to
2682 something which can reinstate us. This notifies
2683 the session manager, who's looking for such a
2684 PropertyNotify. Can restart processing when
2685 a keyboard or mouse event arrives. */
2690 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2692 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2700 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2703 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2707 new_x
= event
.xclient
.data
.s
[0];
2708 new_y
= event
.xclient
.data
.s
[1];
2713 #ifdef NEW_SELECTIONS
2714 case SelectionNotify
:
2715 x_handle_selection_notify (&event
);
2719 case SelectionClear
: /* Someone has grabbed ownership. */
2720 #ifdef NEW_SELECTIONS
2722 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2727 bufp
->kind
= selection_clear_event
;
2728 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2729 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2730 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2737 x_disown_selection (event
.xselectionclear
.window
,
2738 event
.xselectionclear
.selection
,
2739 event
.xselectionclear
.time
);
2743 case SelectionRequest
: /* Someone wants our selection. */
2744 #ifdef NEW_SELECTIONS
2746 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2751 bufp
->kind
= selection_request_event
;
2752 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2753 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2754 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2755 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2756 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2757 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2764 x_answer_selection_request (event
);
2768 case PropertyNotify
:
2769 #ifdef NEW_SELECTIONS
2770 x_handle_property_notify (&event
);
2772 /* If we're being told about a root window property, then it's
2773 a cut buffer change. */
2774 if (event
.xproperty
.window
== ROOT_WINDOW
)
2775 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2777 /* Otherwise, we're probably handling an incremental
2778 selection transmission. */
2781 /* If we were to do this synchronously, there'd be no worry
2782 about re-selecting. */
2783 x_send_incremental (event
);
2788 case ReparentNotify
:
2789 f
= x_window_to_frame (event
.xreparent
.window
);
2791 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
2795 f
= x_window_to_frame (event
.xexpose
.window
);
2798 if (f
->async_visible
== 0)
2800 f
->async_visible
= 1;
2801 f
->async_iconified
= 0;
2802 SET_FRAME_GARBAGED (f
);
2806 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2807 event
.xexpose
.x
, event
.xexpose
.y
,
2808 event
.xexpose
.width
, event
.xexpose
.height
);
2813 struct scroll_bar
*bar
2814 = x_window_to_scroll_bar (event
.xexpose
.window
);
2817 x_scroll_bar_expose (bar
, &event
);
2821 case GraphicsExpose
: /* This occurs when an XCopyArea's
2822 source area was obscured or not
2824 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2828 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2829 event
.xgraphicsexpose
.width
,
2830 event
.xgraphicsexpose
.height
);
2834 case NoExpose
: /* This occurs when an XCopyArea's
2835 source area was completely
2838 #else /* ! defined (HAVE_X11) */
2840 if (event
.subwindow
!= 0)
2841 break; /* duplicate event */
2842 f
= x_window_to_frame (event
.window
);
2843 if (event
.window
== f
->display
.x
->icon_desc
)
2846 f
->async_iconified
= 1;
2848 if (event
.window
== FRAME_X_WINDOW (f
))
2850 /* Say must check all windows' needs_exposure flags. */
2851 expose_all_windows
= 1;
2852 f
->display
.x
->needs_exposure
= 1;
2853 f
->async_visible
= 1;
2858 if (event
.subwindow
!= 0)
2859 break; /* duplicate event */
2860 f
= x_window_to_frame (event
.window
);
2861 if (event
.window
== f
->display
.x
->icon_desc
)
2866 /* If window already needs full redraw, ignore this rectangle. */
2867 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2869 /* Put the event on the queue of rectangles to redraw. */
2870 if (enqueue_event (&event
, &x_expose_queue
))
2871 /* If it is full, we can't record the rectangle,
2872 so redraw this entire window. */
2874 /* Say must check all windows' needs_exposure flags. */
2875 expose_all_windows
= 1;
2876 f
->display
.x
->needs_exposure
= 1;
2881 /* This should happen only when we are expecting it,
2882 in x_read_exposes. */
2884 #endif /* ! defined (HAVE_X11) */
2888 f
= x_window_to_frame (event
.xunmap
.window
);
2889 if (f
) /* F may no longer exist if
2890 the frame was deleted. */
2892 /* While a frame is unmapped, display generation is
2893 disabled; you don't want to spend time updating a
2894 display that won't ever be seen. */
2895 f
->async_visible
= 0;
2896 /* The window manager never makes a window invisible
2897 ("withdrawn"); all it does is switch between visible
2898 and iconified. Frames get into the invisible state
2899 only through x_make_frame_invisible. */
2900 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
2901 f
->async_iconified
= 1;
2906 f
= x_window_to_frame (event
.xmap
.window
);
2909 f
->async_visible
= 1;
2910 f
->async_iconified
= 0;
2912 /* wait_reading_process_input will notice this and update
2913 the frame's display structures. */
2914 SET_FRAME_GARBAGED (f
);
2918 /* Turn off processing if we become fully obscured. */
2919 case VisibilityNotify
:
2922 #else /* ! defined (HAVE_X11) */
2924 f
= x_window_to_frame (event
.window
);
2925 if (event
.window
== f
->display
.x
->icon_desc
)
2926 f
->async_iconified
= 0;
2927 if (event
.window
== FRAME_X_WINDOW (f
))
2928 f
->async_visible
= 0;
2930 #endif /* ! defined (HAVE_X11) */
2934 f
= x_window_to_frame (event
.xkey
.window
);
2938 KeySym keysym
, orig_keysym
;
2939 /* al%imercury@uunet.uu.net says that making this 81 instead of
2940 80 fixed a bug whereby meta chars made his Emacs hang. */
2941 unsigned char copy_buffer
[81];
2945 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
2946 modifiers
= event
.xkey
.state
;
2948 /* This will have to go some day... */
2950 /* make_lispy_event turns chars into control chars.
2951 Don't do it here because XLookupString is too eager. */
2952 event
.xkey
.state
&= ~ControlMask
;
2954 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2957 /* Strip off the vendor-specific keysym bit, and take a shot
2958 at recognizing the codes. HP servers have extra keysyms
2959 that fit into the MiscFunctionKey category. */
2960 orig_keysym
= keysym
;
2965 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
2966 || keysym
== XK_Delete
2967 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2968 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
2970 /* This recognizes the "extended function keys".
2971 It seems there's no cleaner way.
2972 Test IsModifierKey to avoid handling mode_switch
2974 || ((unsigned) (keysym
) >= XK_Select
2975 && (unsigned)(keysym
) < XK_KP_Space
)
2977 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2978 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
2979 || x_is_vendor_fkey (orig_keysym
))
2980 && ! (IsModifierKey (orig_keysym
)
2982 #ifdef XK_Mode_switch
2983 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
2986 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
2988 #endif /* not HAVE_X11R5 */
2991 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2993 temp_buffer
[temp_index
++] = keysym
;
2994 bufp
->kind
= non_ascii_keystroke
;
2995 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff00);
2996 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2997 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
2998 bufp
->timestamp
= event
.xkey
.time
;
3003 else if (numchars
> nbytes
)
3007 for (i
= 0; i
< nbytes
; i
++)
3009 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3011 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3012 bufp
->kind
= ascii_keystroke
;
3013 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
3014 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3015 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3016 bufp
->timestamp
= event
.xkey
.time
;
3030 #else /* ! defined (HAVE_X11) */
3033 register char *where_mapping
;
3035 f
= x_window_to_frame (event
.window
);
3036 /* Ignore keys typed on icon windows. */
3037 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3039 where_mapping
= XLookupMapping (&event
, &nbytes
);
3040 /* Nasty fix for arrow keys */
3041 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3043 switch (event
.detail
& 0xff)
3045 case KC_CURSOR_LEFT
:
3046 where_mapping
= "\002";
3048 case KC_CURSOR_RIGHT
:
3049 where_mapping
= "\006";
3052 where_mapping
= "\020";
3054 case KC_CURSOR_DOWN
:
3055 where_mapping
= "\016";
3060 if (numchars
- nbytes
> 0)
3064 for (i
= 0; i
< nbytes
; i
++)
3066 bufp
->kind
= ascii_keystroke
;
3067 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
3068 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3069 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3077 #endif /* ! defined (HAVE_X11) */
3081 /* Here's a possible interpretation of the whole
3082 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3083 FocusIn event, you have to get a FocusOut event before you
3084 relinquish the focus. If you haven't received a FocusIn event,
3085 then a mere LeaveNotify is enough to free you. */
3088 f
= x_window_to_frame (event
.xcrossing
.window
);
3090 if (event
.xcrossing
.focus
) /* Entered Window */
3092 /* Avoid nasty pop/raise loops. */
3093 if (f
&& (!(f
->auto_raise
)
3095 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3097 x_new_focus_frame (f
);
3098 enter_timestamp
= event
.xcrossing
.time
;
3101 else if (f
== x_focus_frame
)
3102 x_new_focus_frame (0);
3107 f
= x_window_to_frame (event
.xfocus
.window
);
3108 if (event
.xfocus
.detail
!= NotifyPointer
)
3109 x_focus_event_frame
= f
;
3111 x_new_focus_frame (f
);
3116 f
= x_window_to_frame (event
.xcrossing
.window
);
3118 if (event
.xcrossing
.focus
)
3120 if (! x_focus_event_frame
)
3121 x_new_focus_frame (0);
3123 x_new_focus_frame (f
);
3127 if (f
== x_focus_event_frame
)
3128 x_focus_event_frame
= 0;
3129 if (f
== x_focus_frame
)
3130 x_new_focus_frame (0);
3135 f
= x_window_to_frame (event
.xfocus
.window
);
3136 if (event
.xfocus
.detail
!= NotifyPointer
3137 && f
== x_focus_event_frame
)
3138 x_focus_event_frame
= 0;
3139 if (f
&& f
== x_focus_frame
)
3140 x_new_focus_frame (0);
3143 #else /* ! defined (HAVE_X11) */
3146 if ((event
.detail
& 0xFF) == 1)
3147 break; /* Coming from our own subwindow */
3148 if (event
.subwindow
!= 0)
3149 break; /* Entering our own subwindow. */
3152 f
= x_window_to_frame (event
.window
);
3155 x_new_focus_frame (f
);
3160 if ((event
.detail
& 0xFF) == 1)
3161 break; /* Entering our own subwindow */
3162 if (event
.subwindow
!= 0)
3163 break; /* Leaving our own subwindow. */
3166 if (x_focus_frame
== 0
3167 && x_input_frame
!= 0
3168 && x_input_frame
== x_window_to_frame (event
.window
)
3169 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3174 frame_unhighlight (f
);
3177 #endif /* ! defined (HAVE_X11) */
3182 f
= x_window_to_frame (event
.xmotion
.window
);
3184 note_mouse_movement (f
, &event
.xmotion
);
3187 struct scroll_bar
*bar
=
3188 x_window_to_scroll_bar (event
.xmotion
.window
);
3191 x_scroll_bar_note_movement (bar
, &event
);
3196 case ConfigureNotify
:
3197 f
= x_window_to_frame (event
.xconfigure
.window
);
3200 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3201 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3203 /* Even if the number of character rows and columns has
3204 not changed, the font size may have changed, so we need
3205 to check the pixel dimensions as well. */
3206 if (columns
!= f
->width
3207 || rows
!= f
->height
3208 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3209 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3211 change_frame_size (f
, rows
, columns
, 0, 1);
3212 SET_FRAME_GARBAGED (f
);
3215 if (! event
.xconfigure
.send_event
)
3220 /* Find the position of the outside upper-left corner of
3221 the window, in the root coordinate system. Don't
3222 refer to the parent window here; we may be processing
3223 this event after the window manager has changed our
3224 parent, but before we have reached the ReparentNotify. */
3225 XTranslateCoordinates (x_current_display
,
3227 /* From-window, to-window. */
3228 f
->display
.x
->window_desc
,
3231 /* From-position, to-position. */
3232 -event
.xconfigure
.border_width
,
3233 -event
.xconfigure
.border_width
,
3238 event
.xconfigure
.x
= win_x
;
3239 event
.xconfigure
.y
= win_y
;
3242 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3243 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3244 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3245 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3252 /* If we decide we want to generate an event to be seen
3253 by the rest of Emacs, we put it here. */
3254 struct input_event emacs_event
;
3255 emacs_event
.kind
= no_event
;
3257 f
= x_window_to_frame (event
.xbutton
.window
);
3260 if (!x_focus_frame
|| (f
== x_focus_frame
))
3261 construct_mouse_click (&emacs_event
,
3266 struct scroll_bar
*bar
=
3267 x_window_to_scroll_bar (event
.xbutton
.window
);
3270 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3273 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3275 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3283 #else /* ! defined (HAVE_X11) */
3285 case ButtonReleased
:
3286 f
= x_window_to_frame (event
.window
);
3289 if (event
.window
== f
->display
.x
->icon_desc
)
3291 x_make_frame_visible (f
);
3293 if (warp_mouse_on_deiconify
)
3294 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3297 if (event
.window
== FRAME_X_WINDOW (f
))
3303 enqueue_event (&event
, &x_mouse_queue
);
3306 bufp
->kind
= ascii_keystroke
;
3307 bufp
->code
= (char) 'X' & 037; /* C-x */
3308 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3309 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3312 bufp
->kind
= ascii_keystroke
;
3313 bufp
->code
= (char) 0; /* C-@ */
3314 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3315 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3322 #endif /* ! defined (HAVE_X11) */
3326 case CirculateNotify
:
3328 case CirculateRequest
:
3331 #endif /* ! defined (HAVE_X11) */
3334 /* Someone has changed the keyboard mapping - update the
3336 switch (event
.xmapping
.request
)
3338 case MappingModifier
:
3339 x_find_modifier_meanings ();
3340 /* This is meant to fall through. */
3341 case MappingKeyboard
:
3342 XRefreshKeyboardMapping (&event
.xmapping
);
3352 if (expected
&& ! event_found
)
3354 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3355 there is an EOF condition; in other words, that X has died.
3356 Act as if there had been a hangup. */
3357 int fd
= ConnectionNumber (x_current_display
);
3363 EMACS_SET_SECS_USECS (timeout
, 0, 0);
3364 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0, &timeout
)
3365 && !XStuffPending ())
3366 kill (getpid (), SIGHUP
);
3368 #endif /* HAVE_SELECT */
3371 if (updating_frame
== 0)
3372 x_do_pending_expose ();
3380 /* Read and process only Expose events
3381 until we get an ExposeCopy event; then return.
3382 This is used in insert/delete line.
3383 We assume input is already blocked. */
3389 XKeyPressedEvent event
;
3393 /* while there are more events*/
3394 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3398 if (event
.subwindow
!= 0)
3399 break; /* duplicate event */
3400 f
= x_window_to_frame (event
.window
);
3401 if (event
.window
== f
->display
.x
->icon_desc
)
3406 if (event
.window
== FRAME_X_WINDOW (f
))
3408 expose_all_windows
= 1;
3409 f
->display
.x
->needs_exposure
= 1;
3415 if (event
.subwindow
!= 0)
3416 break; /* duplicate event */
3417 f
= x_window_to_frame (event
.window
);
3418 if (event
.window
== f
->display
.x
->icon_desc
)
3423 /* If window already needs full redraw, ignore this rectangle. */
3424 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3426 /* Put the event on the queue of rectangles to redraw. */
3427 if (enqueue_event (&event
, &x_expose_queue
))
3428 /* If it is full, we can't record the rectangle,
3429 so redraw this entire window. */
3431 /* Say must check all windows' needs_exposure flags. */
3432 expose_all_windows
= 1;
3433 f
->display
.x
->needs_exposure
= 1;
3442 #endif /* HAVE_X11 */
3445 /* Drawing the cursor. */
3448 /* Draw a hollow box cursor. Don't change the inside of the box. */
3454 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3455 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3456 int width
= FONT_WIDTH (f
->display
.x
->font
);
3457 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3460 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3461 f
->display
.x
->cursor_gc
,
3462 left
, top
, width
- 1, height
- 1);
3463 #else /* ! defined (HAVE_X11) */
3464 XPixSet (FRAME_X_WINDOW (f
),
3465 left
, top
, width
, 1,
3466 f
->display
.x
->cursor_pixel
);
3468 XPixSet (FRAME_X_WINDOW (f
),
3469 left
, top
, 1, height
,
3470 f
->display
.x
->cursor_pixel
);
3472 XPixSet (FRAME_X_WINDOW (f
),
3473 left
+width
-1, top
, 1, height
,
3474 f
->display
.x
->cursor_pixel
);
3476 XPixSet (FRAME_X_WINDOW (f
),
3477 left
, top
+height
-1, width
, 1,
3478 f
->display
.x
->cursor_pixel
);
3479 #endif /* ! defined (HAVE_X11) */
3482 /* Clear the cursor of frame F to background color,
3483 and mark the cursor as not shown.
3484 This is used when the text where the cursor is
3485 is about to be rewritten. */
3493 if (! FRAME_VISIBLE_P (f
)
3494 || f
->phys_cursor_x
< 0)
3498 x_display_cursor (f
, 0);
3499 #else /* ! defined (HAVE_X11) */
3500 XPixSet (FRAME_X_WINDOW (f
),
3501 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3502 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3503 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3504 f
->display
.x
->background_pixel
);
3505 #endif /* ! defined (HAVE_X11) */
3506 f
->phys_cursor_x
= -1;
3509 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3510 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3514 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3521 CHAR_TO_PIXEL_COL (f
, column
),
3522 CHAR_TO_PIXEL_ROW (f
, row
),
3523 &glyph
, 1, highlight
);
3527 x_display_bar_cursor (f
, on
)
3531 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3533 /* This is pointless on invisible frames, and dangerous on garbaged
3534 frames; in the latter case, the frame may be in the midst of
3535 changing its size, and curs_x and curs_y may be off the frame. */
3536 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3539 if (! on
&& f
->phys_cursor_x
< 0)
3542 /* If we're not updating, then we want to use the current frame's
3543 cursor position, not our local idea of where the cursor ought to be. */
3544 if (f
!= updating_frame
)
3546 curs_x
= FRAME_CURSOR_X (f
);
3547 curs_y
= FRAME_CURSOR_Y (f
);
3550 /* If there is anything wrong with the current cursor state, remove it. */
3551 if (f
->phys_cursor_x
>= 0
3553 || f
->phys_cursor_x
!= curs_x
3554 || f
->phys_cursor_y
!= curs_y
3555 || f
->display
.x
->current_cursor
!= bar_cursor
))
3557 /* Erase the cursor by redrawing the character underneath it. */
3558 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3559 f
->phys_cursor_glyph
,
3560 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3561 f
->phys_cursor_x
= -1;
3564 /* If we now need a cursor in the new place or in the new form, do it so. */
3566 && (f
->phys_cursor_x
< 0
3567 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3569 f
->phys_cursor_glyph
3570 = ((current_glyphs
->enable
[curs_y
]
3571 && curs_x
< current_glyphs
->used
[curs_y
])
3572 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3574 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3575 f
->display
.x
->cursor_gc
,
3576 CHAR_TO_PIXEL_COL (f
, curs_x
),
3577 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3578 1, FONT_HEIGHT (f
->display
.x
->font
));
3580 f
->phys_cursor_x
= curs_x
;
3581 f
->phys_cursor_y
= curs_y
;
3583 f
->display
.x
->current_cursor
= bar_cursor
;
3586 if (updating_frame
!= f
)
3591 /* Turn the displayed cursor of frame F on or off according to ON.
3592 If ON is nonzero, where to put the cursor is specified
3593 by F->cursor_x and F->cursor_y. */
3596 x_display_box_cursor (f
, on
)
3600 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3602 /* This is pointless on invisible frames, and dangerous on garbaged
3603 frames; in the latter case, the frame may be in the midst of
3604 changing its size, and curs_x and curs_y may be off the frame. */
3605 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3608 /* If cursor is off and we want it off, return quickly. */
3609 if (!on
&& f
->phys_cursor_x
< 0)
3612 /* If we're not updating, then we want to use the current frame's
3613 cursor position, not our local idea of where the cursor ought to be. */
3614 if (f
!= updating_frame
)
3616 curs_x
= FRAME_CURSOR_X (f
);
3617 curs_y
= FRAME_CURSOR_Y (f
);
3620 /* If cursor is currently being shown and we don't want it to be
3621 or it is in the wrong place,
3622 or we want a hollow box and it's not so, (pout!)
3624 if (f
->phys_cursor_x
>= 0
3626 || f
->phys_cursor_x
!= curs_x
3627 || f
->phys_cursor_y
!= curs_y
3628 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3629 && (f
!= x_highlight_frame
))))
3631 /* Erase the cursor by redrawing the character underneath it. */
3632 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3633 f
->phys_cursor_glyph
,
3634 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3635 f
->phys_cursor_x
= -1;
3638 /* If we want to show a cursor,
3639 or we want a box cursor and it's not so,
3640 write it in the right place. */
3642 && (f
->phys_cursor_x
< 0
3643 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3644 && f
== x_highlight_frame
)))
3646 f
->phys_cursor_glyph
3647 = ((current_glyphs
->enable
[curs_y
]
3648 && curs_x
< current_glyphs
->used
[curs_y
])
3649 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3651 if (f
!= x_highlight_frame
)
3654 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3658 x_draw_single_glyph (f
, curs_y
, curs_x
,
3659 f
->phys_cursor_glyph
, 2);
3660 f
->display
.x
->current_cursor
= filled_box_cursor
;
3663 f
->phys_cursor_x
= curs_x
;
3664 f
->phys_cursor_y
= curs_y
;
3667 if (updating_frame
!= f
)
3671 x_display_cursor (f
, on
)
3675 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3676 x_display_box_cursor (f
, on
);
3677 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3678 x_display_bar_cursor (f
, on
);
3680 /* Those are the only two we have implemented! */
3686 /* Refresh bitmap kitchen sink icon for frame F
3687 when we get an expose event for it. */
3693 /* Normally, the window manager handles this function. */
3694 #else /* ! defined (HAVE_X11) */
3697 if (f
->display
.x
->icon_bitmap_flag
)
3698 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3699 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3700 icon_bitmap
, GXcopy
, AllPlanes
);
3703 extern struct frame
*selected_frame
;
3704 struct Lisp_String
*str
;
3705 unsigned char *string
;
3708 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3710 if (f
->display
.x
->icon_label
!= string
)
3712 f
->display
.x
->icon_label
= string
;
3713 XChangeWindow (f
->display
.x
->icon_desc
,
3714 XQueryWidth (string
, icon_font_info
->id
) + 10,
3715 icon_font_info
->height
+ 10);
3718 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3719 str
->size
, icon_font_info
->id
,
3720 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3723 #endif /* ! defined (HAVE_X11) */
3726 /* Make the x-window of frame F use the gnu icon bitmap. */
3735 if (FRAME_X_WINDOW (f
) == 0)
3741 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3742 gnu_bits
, gnu_width
, gnu_height
);
3743 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3744 f
->display
.x
->icon_bitmap_flag
= 1;
3745 #else /* ! defined (HAVE_X11) */
3746 if (f
->display
.x
->icon_desc
)
3748 XClearIconWindow (FRAME_X_WINDOW (f
));
3749 XDestroyWindow (f
->display
.x
->icon_desc
);
3752 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3753 0, 0, sink_width
, sink_height
,
3754 2, WhitePixmap
, (Pixmap
) NULL
);
3756 if (icon_window
== 0)
3759 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3760 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3762 f
->display
.x
->icon_desc
= icon_window
;
3763 f
->display
.x
->icon_bitmap_flag
= 1;
3765 if (icon_bitmap
== 0)
3767 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3768 #endif /* ! defined (HAVE_X11) */
3774 /* Make the x-window of frame F use a rectangle with text. */
3777 x_text_icon (f
, icon_name
)
3785 char *X_DefaultValue
;
3789 #define WhitePixel 1
3790 #endif /* WhitePixel */
3793 #define BlackPixel 0
3794 #endif /* BlackPixel */
3795 #endif /* HAVE_X11 */
3797 if (FRAME_X_WINDOW (f
) == 0)
3802 f
->display
.x
->icon_label
= icon_name
;
3804 if (! f
->display
.x
->icon_label
)
3805 f
->display
.x
->icon_label
= " *emacs* ";
3808 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3809 (char *) f
->display
.x
->icon_label
);
3812 f
->display
.x
->icon_bitmap_flag
= 0;
3813 x_wm_set_icon_pixmap (f
, 0);
3814 #else /* ! defined (HAVE_X11) */
3815 if (icon_font_info
== 0)
3817 = XGetFont (XGetDefault (XDISPLAY
3818 (char *) XSTRING (Vinvocation_name
)->data
,
3821 if (f
->display
.x
->icon_desc
)
3823 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3824 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3828 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3830 if (! f
->display
.x
->icon_label
)
3831 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3833 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3834 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3835 f
->display
.x
->left_pos
,
3836 f
->display
.x
->top_pos
,
3837 width
+ 10, icon_font_info
->height
+ 10,
3838 2, BlackPixmap
, WhitePixmap
);
3840 if (icon_window
== 0)
3843 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3844 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3846 f
->display
.x
->icon_desc
= icon_window
;
3847 f
->display
.x
->icon_bitmap_flag
= 0;
3848 f
->display
.x
->icon_label
= 0;
3849 #endif /* ! defined (HAVE_X11) */
3854 /* Handling X errors. */
3856 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3857 X server's connection, or an error reported via the X protocol. */
3860 x_connection_closed ()
3865 shut_down_emacs (0, 1, Qnil
);
3870 /* An X error handler which prints an error message and then kills
3871 Emacs. This is what's normally installed as Xlib's handler for
3874 x_error_quitter (display
, error
)
3880 /* Note that there is no real way portable across R3/R4 to get the
3881 original error handler. */
3883 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3884 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3885 buf
, error
->request_code
);
3888 /* While we're testing Emacs 19, we'll just dump core whenever we
3889 get an X error, so we can figure out why it happened. */
3893 x_connection_closed ();
3896 /* A handler for X IO errors which prints an error message and then
3897 kills Emacs. This is what is always installed as Xlib's handler
3900 x_io_error_quitter (display
)
3903 fprintf (stderr
, "Connection to X server %s lost.\n",
3904 XDisplayName (DisplayString (display
)));
3907 /* While we're testing Emacs 19, we'll just dump core whenever we
3908 get an X error, so we can figure out why it happened. */
3912 x_connection_closed ();
3915 /* A buffer for storing X error messages. */
3916 static char *x_caught_error_message
;
3917 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
3919 /* An X error handler which stores the error message in
3920 x_caught_error_message. This is what's installed when
3921 x_catch_errors is in effect. */
3923 x_error_catcher (display
, error
)
3927 XGetErrorText (display
, error
->error_code
,
3928 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
3932 /* Begin trapping X errors.
3934 After calling this function, X protocol errors no longer cause
3935 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3937 Calling x_check_errors signals an Emacs error if an X error has
3938 occurred since the last call to x_catch_errors or x_check_errors.
3940 Calling x_uncatch_errors resumes the normal error handling. */
3942 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3947 /* Make sure any errors from previous requests have been dealt with. */
3948 XSync (x_current_display
, False
);
3950 /* Set up the error buffer. */
3951 x_caught_error_message
3952 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
3953 x_caught_error_message
[0] = '\0';
3955 /* Install our little error handler. */
3956 XHandleError (x_error_catcher
);
3959 /* If any X protocol errors have arrived since the last call to
3960 x_catch_errors or x_check_errors, signal an Emacs error using
3961 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3963 x_check_errors (format
)
3966 /* Make sure to catch any errors incurred so far. */
3967 XSync (x_current_display
, False
);
3969 if (x_caught_error_message
[0])
3971 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
3973 sprintf (buf
, format
, x_caught_error_message
);
3974 x_uncatch_errors ();
3982 xfree (x_caught_error_message
);
3983 x_caught_error_message
= 0;
3984 XHandleError (x_error_quitter
);
3988 static unsigned int x_wire_count
;
3991 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3996 /* Changing the font of the frame. */
3998 /* Set the font of the x-window specified by frame F
3999 to the font named NEWNAME. This is safe to use
4000 even before F has an actual x-window. */
4010 /* A table of all the fonts we have already loaded. */
4011 static struct font_info
*x_font_table
;
4013 /* The current capacity of x_font_table. */
4014 static int x_font_table_size
;
4016 /* The number of fonts actually stored in x_font_table.
4017 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4018 0 <= n_fonts <= x_font_table_size. */
4022 x_new_font (f
, fontname
)
4024 register char *fontname
;
4027 int n_matching_fonts
;
4028 XFontStruct
*font_info
;
4031 /* Get a list of all the fonts that match this name. Once we
4032 have a list of matching fonts, we compare them against the fonts
4033 we already have by comparing font ids. */
4034 font_names
= (char **) XListFonts (x_current_display
, fontname
,
4035 1024, &n_matching_fonts
);
4036 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4037 find any matches; font_names == 0 is the only clue. */
4039 n_matching_fonts
= 0;
4041 /* Don't just give up if n_matching_fonts is 0.
4042 Apparently there's a bug on Suns: XListFontsWithInfo can
4043 fail to find a font, but XLoadQueryFont may still find it. */
4045 /* See if we've already loaded a matching font. */
4046 already_loaded
= -1;
4047 if (n_matching_fonts
!= 0)
4051 for (i
= 0; i
< n_fonts
; i
++)
4052 for (j
= 0; j
< n_matching_fonts
; j
++)
4053 if (!strcmp (x_font_table
[i
].name
, font_names
[j
]))
4056 fontname
= font_names
[j
];
4062 /* If we have, just return it from the table. */
4063 if (already_loaded
>= 0)
4064 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
4066 /* Otherwise, load the font and add it to the table. */
4072 /* Try to find a character-cell font in the list. */
4074 /* A laudable goal, but this isn't how to do it. */
4075 for (i
= 0; i
< n_matching_fonts
; i
++)
4076 if (! font_info
[i
].per_char
)
4082 /* See comment above. */
4083 if (n_matching_fonts
!= 0)
4084 fontname
= font_names
[i
];
4086 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
4089 /* Free the information from XListFonts. */
4090 if (n_matching_fonts
)
4091 XFreeFontNames (font_names
);
4095 /* Do we need to create the table? */
4096 if (x_font_table_size
== 0)
4098 x_font_table_size
= 16;
4100 = (struct font_info
*) xmalloc (x_font_table_size
4101 * sizeof (x_font_table
[0]));
4103 /* Do we need to grow the table? */
4104 else if (n_fonts
>= x_font_table_size
)
4106 x_font_table_size
*= 2;
4108 = (struct font_info
*) xrealloc (x_font_table
,
4110 * sizeof (x_font_table
[0])));
4113 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4114 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4115 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
4118 /* Now make the frame display the given font. */
4119 if (FRAME_X_WINDOW (f
) != 0)
4121 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
4122 f
->display
.x
->font
->fid
);
4123 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
4124 f
->display
.x
->font
->fid
);
4125 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
4126 f
->display
.x
->font
->fid
);
4128 x_set_window_size (f
, f
->width
, f
->height
);
4132 Lisp_Object lispy_name
= build_string (fontname
);
4135 /* Free the information from XListFonts. The data
4136 we actually retain comes from XLoadQueryFont. */
4137 XFreeFontNames (font_names
);
4142 #else /* ! defined (HAVE_X11) */
4143 x_new_font (f
, newname
)
4145 register char *newname
;
4150 temp
= XGetFont (newname
);
4151 if (temp
== (FONT_TYPE
*) 0)
4154 if (f
->display
.x
->font
)
4155 XLoseFont (f
->display
.x
->font
);
4157 f
->display
.x
->font
= temp
;
4159 if (FRAME_X_WINDOW (f
) != 0)
4160 x_set_window_size (f
, f
->width
, f
->height
);
4164 #endif /* ! defined (HAVE_X11) */
4166 /* X Window sizes and positions. */
4168 x_calc_absolute_position (f
)
4173 int win_x
= 0, win_y
= 0;
4175 /* Find the position of the outside upper-left corner of
4176 the inner window, with respect to the outer window. */
4177 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
4180 XTranslateCoordinates (x_current_display
,
4182 /* From-window, to-window. */
4183 f
->display
.x
->window_desc
,
4184 f
->display
.x
->parent_desc
,
4186 /* From-position, to-position. */
4187 0, 0, &win_x
, &win_y
,
4194 /* Treat negative positions as relative to the leftmost bottommost
4195 position that fits on the screen. */
4196 if (f
->display
.x
->left_pos
< 0)
4197 f
->display
.x
->left_pos
= (x_screen_width
4198 - f
->display
.x
->border_width
- win_x
4200 + f
->display
.x
->left_pos
);
4202 if (f
->display
.x
->top_pos
< 0)
4203 f
->display
.x
->top_pos
= (x_screen_height
4204 - f
->display
.x
->border_width
- win_y
4206 + f
->display
.x
->top_pos
);
4208 #else /* ! defined (HAVE_X11) */
4209 WINDOWINFO_TYPE parentinfo
;
4211 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
4213 if (f
->display
.x
->left_pos
< 0)
4214 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
4215 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
4217 if (f
->display
.x
->top_pos
< 0)
4218 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
4219 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
4220 #endif /* ! defined (HAVE_X11) */
4223 x_set_offset (f
, xoff
, yoff
)
4225 register int xoff
, yoff
;
4227 f
->display
.x
->top_pos
= yoff
;
4228 f
->display
.x
->left_pos
= xoff
;
4229 x_calc_absolute_position (f
);
4232 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4233 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4235 x_wm_set_size_hint (f
, 0, xoff
, yoff
);
4236 #endif /* ! defined (HAVE_X11) */
4240 /* Call this to change the size of frame F's x-window. */
4242 x_set_window_size (f
, cols
, rows
)
4246 int pixelwidth
, pixelheight
;
4251 check_frame_size (f
, &rows
, &cols
);
4252 f
->display
.x
->vertical_scroll_bar_extra
4253 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4254 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
4256 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4257 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4260 x_wm_set_size_hint (f
, 0, 0, 0);
4261 #endif /* ! defined (HAVE_X11) */
4262 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4264 /* Now, strictly speaking, we can't be sure that this is accurate,
4265 but the window manager will get around to dealing with the size
4266 change request eventually, and we'll hear how it went when the
4267 ConfigureNotify event gets here.
4269 We could just not bother storing any of this information here,
4270 and let the ConfigureNotify event set everything up, but that
4271 might be kind of confusing to the lisp code, since size changes
4272 wouldn't be reported in the frame parameters until some random
4273 point in the future when the ConfigureNotify event arrives. */
4274 change_frame_size (f
, rows
, cols
, 0, 0);
4275 PIXEL_WIDTH (f
) = pixelwidth
;
4276 PIXEL_HEIGHT (f
) = pixelheight
;
4278 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4279 receive in the ConfigureNotify event; if we get what we asked
4280 for, then the event won't cause the screen to become garbaged, so
4281 we have to make sure to do it here. */
4282 SET_FRAME_GARBAGED (f
);
4289 x_set_resize_hint (f
)
4292 XSetResizeHint (FRAME_X_WINDOW (f
),
4293 2 * f
->display
.x
->internal_border_width
,
4294 2 * f
->display
.x
->internal_border_width
,
4295 FONT_WIDTH (f
->display
.x
->font
),
4296 FONT_HEIGHT (f
->display
.x
->font
));
4298 #endif /* HAVE_X11 */
4300 /* Mouse warping, focus shifting, raising and lowering. */
4302 x_set_mouse_position (f
, x
, y
)
4310 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4311 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4313 if (pix_x
< 0) pix_x
= 0;
4314 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4316 if (pix_y
< 0) pix_y
= 0;
4317 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4321 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4326 x_focus_on_frame (f
)
4331 /* I don't think that the ICCCM allows programs to do things like this
4332 without the interaction of the window manager. Whatever you end up
4333 doing with this code, do it to x_unfocus_frame too. */
4334 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4335 RevertToPointerRoot
, CurrentTime
);
4343 /* Look at the remarks in x_focus_on_frame. */
4344 if (x_focus_frame
== f
)
4345 XSetInputFocus (x_current_display
, PointerRoot
,
4346 RevertToPointerRoot
, CurrentTime
);
4350 #endif /* ! defined (HAVE_X11) */
4352 /* Raise frame F. */
4357 if (f
->async_visible
)
4360 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4366 /* Lower frame F. */
4371 if (f
->async_visible
)
4374 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4381 XTframe_raise_lower (f
, raise
)
4392 /* Change from withdrawn state to mapped state. */
4394 x_make_frame_visible (f
)
4401 if (! FRAME_VISIBLE_P (f
))
4404 if (! EQ (Vx_no_window_manager
, Qt
))
4405 x_wm_set_window_state (f
, NormalState
);
4407 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4408 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4409 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4410 #else /* ! defined (HAVE_X11) */
4411 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4412 if (f
->display
.x
->icon_desc
!= 0)
4413 XUnmapWindow (f
->display
.x
->icon_desc
);
4415 /* Handled by the MapNotify event for X11 */
4416 f
->async_visible
= 1;
4417 f
->async_iconified
= 0;
4419 /* NOTE: this may cause problems for the first frame. */
4421 #endif /* ! defined (HAVE_X11) */
4429 /* Change from mapped state to withdrawn state. */
4431 x_make_frame_invisible (f
)
4436 /* Don't keep the highlight on an invisible frame. */
4437 if (x_highlight_frame
== f
)
4438 x_highlight_frame
= 0;
4440 if (! f
->async_visible
&& ! f
->async_iconified
)
4447 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4448 DefaultScreen (x_current_display
)))
4450 UNBLOCK_INPUT_RESIGNAL
;
4451 error ("can't notify window manager of window withdrawal");
4454 #else /* ! defined (HAVE_X11R4) */
4457 /* Tell the window manager what we're going to do. */
4458 if (! EQ (Vx_no_window_manager
, Qt
))
4462 unmap
.xunmap
.type
= UnmapNotify
;
4463 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4464 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4465 unmap
.xunmap
.from_configure
= False
;
4466 if (! XSendEvent (x_current_display
,
4467 DefaultRootWindow (x_current_display
),
4469 SubstructureRedirectMask
|SubstructureNotifyMask
,
4472 UNBLOCK_INPUT_RESIGNAL
;
4473 error ("can't notify window manager of withdrawal");
4477 /* Unmap the window ourselves. Cheeky! */
4478 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4480 #else /* ! defined (HAVE_X11) */
4482 XUnmapWindow (FRAME_X_WINDOW (f
));
4483 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4484 if (f
->display
.x
->icon_desc
!= 0)
4485 XUnmapWindow (f
->display
.x
->icon_desc
);
4487 #endif /* ! defined (HAVE_X11) */
4488 #endif /* ! defined (HAVE_X11R4) */
4494 /* Change window state from mapped to iconified. */
4501 /* Don't keep the highlight on an invisible frame. */
4502 if (x_highlight_frame
== f
)
4503 x_highlight_frame
= 0;
4505 if (f
->async_iconified
)
4511 /* Since we don't know which revision of X we're running, we'll use both
4512 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4514 /* X11R4: send a ClientMessage to the window manager using the
4515 WM_CHANGE_STATE type. */
4519 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4520 message
.xclient
.type
= ClientMessage
;
4521 message
.xclient
.message_type
= Xatom_wm_change_state
;
4522 message
.xclient
.format
= 32;
4523 message
.xclient
.data
.l
[0] = IconicState
;
4525 if (! XSendEvent (x_current_display
,
4526 DefaultRootWindow (x_current_display
),
4528 SubstructureRedirectMask
| SubstructureNotifyMask
,
4531 UNBLOCK_INPUT_RESIGNAL
;
4532 error ("Can't notify window manager of iconification.");
4536 /* X11R3: set the initial_state field of the window manager hints to
4538 x_wm_set_window_state (f
, IconicState
);
4540 if (!FRAME_VISIBLE_P (f
))
4542 /* If the frame was withdrawn, before, we must map it. */
4543 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4544 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4545 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4548 f
->async_iconified
= 1;
4549 #else /* ! defined (HAVE_X11) */
4550 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4552 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4553 if (f
->display
.x
->icon_desc
!= 0)
4555 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4558 #endif /* ! defined (HAVE_X11) */
4564 /* Destroy the X window of frame F. */
4566 x_destroy_window (f
)
4571 if (f
->display
.x
->icon_desc
!= 0)
4572 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4573 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4574 free_frame_faces (f
);
4577 xfree (f
->display
.x
);
4579 if (f
== x_focus_frame
)
4581 if (f
== x_highlight_frame
)
4582 x_highlight_frame
= 0;
4587 /* Manage event queues for X10. */
4591 /* Manage event queues.
4593 This code is only used by the X10 support.
4595 We cannot leave events in the X queue and get them when we are ready
4596 because X does not provide a subroutine to get only a certain kind
4597 of event but not block if there are no queued events of that kind.
4599 Therefore, we must examine events as they come in and copy events
4600 of certain kinds into our private queues.
4602 All ExposeRegion events are put in x_expose_queue.
4603 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4606 /* Write the event *P_XREP into the event queue *QUEUE.
4607 If the queue is full, do nothing, but return nonzero. */
4610 enqueue_event (p_xrep
, queue
)
4611 register XEvent
*p_xrep
;
4612 register struct event_queue
*queue
;
4614 int newindex
= queue
->windex
+ 1;
4615 if (newindex
== EVENT_BUFFER_SIZE
)
4617 if (newindex
== queue
->rindex
)
4619 queue
->xrep
[queue
->windex
] = *p_xrep
;
4620 queue
->windex
= newindex
;
4624 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4625 If *QUEUE is empty, do nothing and return 0. */
4628 dequeue_event (p_xrep
, queue
)
4629 register XEvent
*p_xrep
;
4630 register struct event_queue
*queue
;
4632 if (queue
->windex
== queue
->rindex
)
4634 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4635 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4640 /* Return the number of events buffered in *QUEUE. */
4643 queue_event_count (queue
)
4644 register struct event_queue
*queue
;
4646 int tem
= queue
->windex
- queue
->rindex
;
4649 return EVENT_BUFFER_SIZE
+ tem
;
4652 /* Return nonzero if mouse input is pending. */
4655 mouse_event_pending_p ()
4657 return queue_event_count (&x_mouse_queue
);
4659 #endif /* HAVE_X11 */
4661 /* Setting window manager hints. */
4665 /* SPEC_X and SPEC_Y are the specified positions.
4666 We look only at their sign, to decide the gravity. */
4668 x_wm_set_size_hint (f
, prompting
, spec_x
, spec_y
)
4673 XSizeHints size_hints
;
4674 Window window
= FRAME_X_WINDOW (f
);
4676 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
4678 flexlines
= f
->height
;
4680 size_hints
.x
= f
->display
.x
->left_pos
;
4681 size_hints
.y
= f
->display
.x
->top_pos
;
4682 size_hints
.height
= PIXEL_HEIGHT (f
);
4683 size_hints
.width
= PIXEL_WIDTH (f
);
4684 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4685 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4687 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4688 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4691 int base_width
, base_height
;
4693 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4694 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4697 int min_rows
= 0, min_cols
= 0;
4698 check_frame_size (f
, &min_rows
, &min_cols
);
4700 /* The window manager uses the base width hints to calculate the
4701 current number of rows and columns in the frame while
4702 resizing; min_width and min_height aren't useful for this
4703 purpose, since they might not give the dimensions for a
4704 zero-row, zero-column frame.
4706 We use the base_width and base_height members if we have
4707 them; otherwise, we set the min_width and min_height members
4708 to the size for a zero x zero frame. */
4711 size_hints
.flags
|= PBaseSize
;
4712 size_hints
.base_width
= base_width
;
4713 size_hints
.base_height
= base_height
;
4714 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4715 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4717 size_hints
.min_width
= base_width
;
4718 size_hints
.min_height
= base_height
;
4725 size_hints
.flags
|= prompting
;
4728 XSizeHints hints
; /* Sometimes I hate X Windows... */
4730 if (XGetNormalHints (x_current_display
, window
, &hints
) == 0)
4732 if (hints
.flags
& PSize
)
4733 size_hints
.flags
|= PSize
;
4734 if (hints
.flags
& PPosition
)
4735 size_hints
.flags
|= PPosition
;
4736 if (hints
.flags
& USPosition
)
4737 size_hints
.flags
|= USPosition
;
4738 if (hints
.flags
& USSize
)
4739 size_hints
.flags
|= USSize
;
4741 #if defined (PWinGravity)
4742 switch (((spec_x
< 0) << 1) + (spec_y
< 0))
4745 size_hints
.win_gravity
= NorthWestGravity
;
4748 size_hints
.win_gravity
= SouthWestGravity
;
4751 size_hints
.win_gravity
= NorthEastGravity
;
4754 size_hints
.win_gravity
= SouthEastGravity
;
4757 size_hints
.flags
|= PWinGravity
;
4758 #endif /* PWinGravity */
4761 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4763 XSetNormalHints (x_current_display
, window
, &size_hints
);
4767 /* Used for IconicState or NormalState */
4768 x_wm_set_window_state (f
, state
)
4772 Window window
= FRAME_X_WINDOW (f
);
4774 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4775 f
->display
.x
->wm_hints
.initial_state
= state
;
4777 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4780 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4784 Window window
= FRAME_X_WINDOW (f
);
4788 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4789 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4792 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4794 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4797 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4801 Window window
= FRAME_X_WINDOW (f
);
4803 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4804 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4805 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4807 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4811 /* Initialization. */
4814 x_term_init (display_name
)
4819 #ifndef F_SETOWN_BUG
4821 extern int old_fcntl_owner
;
4822 #endif /* ! defined (F_SETOWN) */
4823 #endif /* F_SETOWN_BUG */
4825 x_focus_frame
= x_highlight_frame
= 0;
4827 x_current_display
= XOpenDisplay (display_name
);
4828 if (x_current_display
== 0)
4829 fatal ("X server %s not responding.\n\
4830 Check the DISPLAY environment variable or use \"-d\"\n",
4835 int hostname_size
= 256;
4837 hostname
= (char *) xmalloc (hostname_size
);
4840 XSetAfterFunction (x_current_display
, x_trace_wire
);
4843 /* Try to get the host name; if the buffer is too short, try
4844 again. Apparently, the only indication gethostname gives of
4845 whether the buffer was large enough is the presence or absence
4846 of a '\0' in the string. Eech. */
4849 gethostname (hostname
, hostname_size
- 1);
4850 hostname
[hostname_size
- 1] = '\0';
4852 /* Was the buffer large enough for gethostname to store the '\0'? */
4853 if (strlen (hostname
) < hostname_size
- 1)
4856 hostname_size
<<= 1;
4857 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4859 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4862 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
4865 /* Figure out which modifier bits mean what. */
4866 x_find_modifier_meanings ();
4868 /* Get the scroll bar cursor. */
4869 x_vertical_scroll_bar_cursor
4870 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4873 /* Watch for PropertyNotify events on the root window; we use them
4874 to figure out when to invalidate our cache of the cut buffers. */
4875 x_watch_cut_buffer_cache ();
4878 if (ConnectionNumber (x_current_display
) != 0)
4879 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
4880 change_input_fd (ConnectionNumber (x_current_display
));
4882 #endif /* ! defined (HAVE_X11) */
4884 #ifndef F_SETOWN_BUG
4886 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
4887 #ifdef F_SETOWN_SOCK_NEG
4888 /* stdin is a socket here */
4889 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
4890 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4891 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
4892 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4893 #endif /* ! defined (F_SETOWN) */
4894 #endif /* F_SETOWN_BUG */
4898 #endif /* ! defined (SIGIO) */
4900 expose_all_windows
= 0;
4902 clear_frame_hook
= XTclear_frame
;
4903 clear_end_of_line_hook
= XTclear_end_of_line
;
4904 ins_del_lines_hook
= XTins_del_lines
;
4905 change_line_highlight_hook
= XTchange_line_highlight
;
4906 insert_glyphs_hook
= XTinsert_glyphs
;
4907 write_glyphs_hook
= XTwrite_glyphs
;
4908 delete_glyphs_hook
= XTdelete_glyphs
;
4909 ring_bell_hook
= XTring_bell
;
4910 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4911 set_terminal_modes_hook
= XTset_terminal_modes
;
4912 update_begin_hook
= XTupdate_begin
;
4913 update_end_hook
= XTupdate_end
;
4914 set_terminal_window_hook
= XTset_terminal_window
;
4915 read_socket_hook
= XTread_socket
;
4916 cursor_to_hook
= XTcursor_to
;
4917 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4918 mouse_position_hook
= XTmouse_position
;
4919 frame_rehighlight_hook
= XTframe_rehighlight
;
4920 frame_raise_lower_hook
= XTframe_raise_lower
;
4921 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
4922 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
4923 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
4924 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
4926 scroll_region_ok
= 1; /* we'll scroll partial frames */
4927 char_ins_del_ok
= 0; /* just as fast to write the line */
4928 line_ins_del_ok
= 1; /* we'll just blt 'em */
4929 fast_clear_end_of_line
= 1; /* X does this well */
4930 memory_below_frame
= 0; /* we don't remember what scrolls
4934 /* Try to use interrupt input; if we can't, then start polling. */
4935 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4937 /* Note that there is no real way portable across R3/R4 to get the
4938 original error handler. */
4939 XHandleError (x_error_quitter
);
4940 XHandleIOError (x_io_error_quitter
);
4942 /* Disable Window Change signals; they are handled by X events. */
4944 signal (SIGWINCH
, SIG_DFL
);
4945 #endif /* ! defined (SIGWINCH) */
4947 signal (SIGPIPE
, x_connection_closed
);
4953 staticpro (&last_mouse_scroll_bar
);
4954 last_mouse_scroll_bar
= Qnil
;
4956 #endif /* ! defined (HAVE_X11) */
4957 #endif /* ! defined (HAVE_X_WINDOWS) */