1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 #define NEW_SELECTIONS
35 #include "blockinput.h"
37 /* On 4.3 these lose if they come after xterm.h. */
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
44 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
55 #include <sys/ioctl.h>
57 #else /* ! defined (BSD) */
59 #include <sys/termio.h>
62 #endif /* ! defined (BSD) */
64 /* Allow m- file to inhibit use of FIONREAD. */
65 #ifdef BROKEN_FIONREAD
67 #endif /* ! defined (BROKEN_FIONREAD) */
69 /* We are unable to use interrupts if FIONREAD is not available,
70 so flush SIGIO so we won't try. */
74 #endif /* ! defined (SIGIO) */
84 #include <sys/param.h>
86 #include "dispextern.h"
87 #include "termhooks.h"
101 #define XMapWindow XMapRaised /* Raise them when mapping. */
102 #else /* ! defined (HAVE_X11) */
103 #include <X/Xkeyboard.h>
104 /*#include <X/Xproto.h> */
105 #endif /* ! defined (HAVE_X11) */
107 /* For sending Meta-characters. Do we need this? */
110 #define min(a,b) ((a)<(b) ? (a) : (b))
111 #define max(a,b) ((a)>(b) ? (a) : (b))
113 /* Nonzero means we must reprint all windows
114 because 1) we received an ExposeWindow event
115 or 2) we received too many ExposeRegion events to record.
117 This is never needed under X11. */
118 static int expose_all_windows
;
120 /* Nonzero means we must reprint all icon windows. */
122 static int expose_all_icons
;
125 /* ExposeRegion events, when received, are copied into this queue
126 for later processing. */
128 static struct event_queue x_expose_queue
;
130 /* ButtonPressed and ButtonReleased events, when received,
131 are copied into this queue for later processing. */
133 struct event_queue x_mouse_queue
;
134 #endif /* HAVE_X11 */
136 #if defined (SIGIO) && defined (FIONREAD)
137 int BLOCK_INPUT_mask
;
138 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
140 /* The id of a bitmap used for icon windows.
141 One such map is shared by all Emacs icon windows.
142 This is zero if we have not yet had a need to create the bitmap. */
144 static Bitmap icon_bitmap
;
146 /* Font used for text icons. */
148 static FONT_TYPE
*icon_font_info
;
150 /* Stuff for dealing with the main icon title. */
152 extern Lisp_Object Vcommand_line_args
;
153 char *hostname
, *x_id_name
;
155 /* This is the X connection that we are using. */
157 Display
*x_current_display
;
159 /* The cursor to use for vertical scroll bars on x_current_display. */
160 static Cursor x_vertical_scroll_bar_cursor
;
162 /* Frame being updated by update_frame. This is declared in term.c.
163 This is set by update_begin and looked at by all the
164 XT functions. It is zero while not inside an update.
165 In that case, the XT functions assume that `selected_frame'
166 is the frame to apply to. */
167 extern struct frame
*updating_frame
;
169 /* The frame (if any) which has the X window that has keyboard focus.
170 Zero if none. This is examined by Ffocus_frame in frame.c. Note
171 that a mere EnterNotify event can set this; if you need to know the
172 last frame specified in a FocusIn or FocusOut event, use
173 x_focus_event_frame. */
174 struct frame
*x_focus_frame
;
176 /* The last frame mentioned in a FocusIn or FocusOut event. This is
177 separate from x_focus_frame, because whether or not LeaveNotify
178 events cause us to lose focus depends on whether or not we have
179 received a FocusIn event for it. */
180 struct frame
*x_focus_event_frame
;
182 /* The frame which currently has the visual highlight, and should get
183 keyboard input (other sorts of input have the frame encoded in the
184 event). It points to the X focus frame's selected window's
185 frame. It differs from x_focus_frame when we're using a global
187 static struct frame
*x_highlight_frame
;
189 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
190 mouse is moved to inside of frame when frame is de-iconified. */
192 static int warp_mouse_on_deiconify
;
194 /* During an update, maximum vpos for ins/del line operations to affect. */
196 static int flexlines
;
198 /* During an update, nonzero if chars output now should be highlighted. */
200 static int highlight
;
202 /* Nominal cursor position -- where to draw output.
203 During an update, these are different from the cursor-box position. */
209 /* `t' if a mouse button is depressed. */
211 extern Lisp_Object Vmouse_depressed
;
213 /* Tells if a window manager is present or not. */
215 extern Lisp_Object Vx_no_window_manager
;
217 /* Timestamp that we requested selection data was made. */
218 extern Time requestor_time
;
220 /* ID of the window requesting selection data. */
221 extern Window requestor_window
;
223 /* Nonzero enables some debugging for the X interface code. */
226 #else /* ! defined (HAVE_X11) */
228 /* Bit patterns for the mouse cursor. */
230 short MouseCursor
[] = {
231 0x0000, 0x0008, 0x0018, 0x0038,
232 0x0078, 0x00f8, 0x01f8, 0x03f8,
233 0x07f8, 0x00f8, 0x00d8, 0x0188,
234 0x0180, 0x0300, 0x0300, 0x0000};
236 short MouseMask
[] = {
237 0x000c, 0x001c, 0x003c, 0x007c,
238 0x00fc, 0x01fc, 0x03fc, 0x07fc,
239 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
240 0x03cc, 0x0780, 0x0780, 0x0300};
242 static short grey_bits
[] = {
243 0x0005, 0x000a, 0x0005, 0x000a};
245 static Pixmap GreyPixmap
= 0;
246 #endif /* ! defined (HAVE_X11) */
248 /* From time to time we get info on an Emacs window, here. */
250 static WINDOWINFO_TYPE windowinfo
;
254 /* See keyboard.c. */
255 extern int extra_keyboard_modifiers
;
257 extern Display
*XOpenDisplay ();
258 extern Window
XCreateWindow ();
260 extern Cursor
XCreateCursor ();
261 extern FONT_TYPE
*XOpenFont ();
263 static void flashback ();
266 static void dumpqueue ();
267 #endif /* HAVE_X11 */
270 static int XTcursor_to ();
271 static int XTclear_end_of_line ();
274 /* Starting and ending updates.
276 These hooks are called by update_frame at the beginning and end
277 of a frame update. We record in `updating_frame' the identity
278 of the frame being updated, so that the XT... functions do not
279 need to take a frame as argument. Most of the XT... functions
280 should never be called except during an update, the only exceptions
281 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
283 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
294 flexlines
= f
->height
;
300 #endif /* HAVE_X11 */
305 static void x_do_pending_expose ();
314 if (updating_frame
== 0
315 || updating_frame
!= f
)
321 x_do_pending_expose ();
322 #endif /* HAVE_X11 */
324 x_display_cursor (f
, 1);
330 /* External interface to control of standout mode.
331 Call this when about to modify line at position VPOS
332 and not change whether it is highlighted. */
334 XTreassert_line_highlight (new, vpos
)
340 /* Call this when about to modify line at position VPOS
341 and change whether it is highlighted. */
344 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
345 int new_highlight
, vpos
, first_unused_hpos
;
347 highlight
= new_highlight
;
348 XTcursor_to (vpos
, 0);
349 XTclear_end_of_line (updating_frame
->width
);
352 /* This is used when starting Emacs and when restarting after suspend.
353 When starting Emacs, no X window is mapped. And nothing must be done
354 to Emacs's own window if it is suspended (though that rarely happens). */
357 XTset_terminal_modes ()
361 /* This is called when exiting or suspending Emacs.
362 Exiting will make the X-windows go away, and suspending
363 requires no action. */
366 XTreset_terminal_modes ()
368 /* XTclear_frame (); */
371 /* Set the nominal cursor position of the frame.
372 This is where display update commands will take effect.
373 This does not affect the place where the cursor-box is displayed. */
376 XTcursor_to (row
, col
)
377 register int row
, col
;
385 if (updating_frame
== 0)
388 x_display_cursor (selected_frame
, 1);
394 /* Display a sequence of N glyphs found at GP.
395 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
396 HL is 1 if this text is highlighted, 2 if the cursor is on it.
398 FONT is the default font to use (for glyphs whose font-code is 0). */
401 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
404 register GLYPH
*gp
; /* Points to first GLYPH. */
405 register int n
; /* Number of glyphs to display. */
410 Window window
= FRAME_X_WINDOW (f
);
411 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
412 : (hl
? f
->display
.x
->reverse_gc
413 : f
->display
.x
->normal_gc
));
415 if (sizeof (GLYPH
) == sizeof (XChar2b
))
416 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
417 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
418 else if (sizeof (GLYPH
) == sizeof (unsigned char))
419 XDrawImageString (x_current_display
, window
, drawing_gc
,
420 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
422 /* What size of glyph ARE you using? And does X have a function to
429 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
432 register GLYPH
*gp
; /* Points to first GLYPH. */
433 register int n
; /* Number of glyphs to display. */
437 char buf
[f
->width
]; /* Holds characters to be displayed. */
438 register char *cp
; /* Steps through buf[]. */
439 register int tlen
= GLYPH_TABLE_LENGTH
;
440 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
441 Window window
= FRAME_X_WINDOW (f
);
442 int cursor_pixel
= f
->display
.x
->cursor_pixel
;
443 int fg_pixel
= f
->display
.x
->foreground_pixel
;
444 int bg_pixel
= f
->display
.x
->background_pixel
;
445 int intborder
= f
->display
.x
->internal_border_width
;
449 /* Get the face-code of the next GLYPH. */
453 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
454 g
= GLYPH_ALIAS (tbase
, g
);
458 /* Find the run of consecutive glyphs with the same face-code.
459 Extract their character codes into BUF. */
464 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
465 g
= GLYPH_ALIAS (tbase
, g
);
474 /* LEN gets the length of the run. */
477 /* Now output this run of chars, with the font and pixel values
478 determined by the face code CF. */
482 GC GC_cursor
= f
->display
.x
->cursor_gc
;
483 GC GC_reverse
= f
->display
.x
->reverse_gc
;
484 GC GC_normal
= f
->display
.x
->normal_gc
;
486 XDrawImageString (x_current_display
, window
,
489 : (hl
? GC_reverse
: GC_normal
)),
490 left
, top
+ FONT_BASE (font
), buf
, len
);
491 #else /* ! defined (HAVE_X11) */
492 XText (window
, left
, top
,
497 ? (cursor_pixel
== fg_pixel
? bg_pixel
: fg_pixel
)
498 : hl
? bg_pixel
: fg_pixel
),
499 (hl
== 2 ? cursor_pixel
500 : hl
? fg_pixel
: bg_pixel
));
501 #endif /* ! defined (HAVE_X11) */
506 if (FACE_IS_FONT (cf
))
507 XDrawImageString (x_current_display
, FRAME_X_WINDOW (f
),
509 left
, top
+ FONT_BASE (FACE_FONT (cf
)),
511 else if (FACE_IS_IMAGE (cf
))
512 XCopyPlane (x_current_display
, FACE_IMAGE (cf
),
514 f
->display
.x
->normal_gc
,
516 FACE_IMAGE_WIDTH (cf
),
517 FACE_IMAGE_HEIGHT (cf
), left
, top
);
520 #else /* ! defined (HAVE_X11) */
521 register struct face
*fp
= x_face_table
[cf
];
523 XText (window
, left
, top
,
528 ? (cursor_pixel
== fp
->fg
? fp
->bg
: fp
->fg
)
529 : hl
? fp
->bg
: fp
->fg
),
530 (hl
== 2 ? cursor_pixel
531 : hl
? fp
->fg
: fp
->bg
));
532 #endif /* ! defined (HAVE_X11) */
534 left
+= len
* FONT_WIDTH (font
);
539 /* Output some text at the nominal frame cursor position.
540 Advance the cursor over the text.
541 Output LEN glyphs at START.
543 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
544 controls the pixel values used for foreground and background. */
547 XTwrite_glyphs (start
, len
)
548 register GLYPH
*start
;
551 register int temp_length
;
561 /* If not within an update,
562 output at the frame's visible cursor. */
563 curs_x
= f
->cursor_x
;
564 curs_y
= f
->cursor_y
;
568 CHAR_TO_PIXEL_COL (f
, curs_x
),
569 CHAR_TO_PIXEL_ROW (f
, curs_y
),
570 start
, len
, highlight
, f
->display
.x
->font
);
572 /* If we drew on top of the cursor, note that it is turned off. */
573 if (curs_y
== f
->phys_cursor_y
574 && curs_x
<= f
->phys_cursor_x
575 && curs_x
+ len
> f
->phys_cursor_x
)
576 f
->phys_cursor_x
= -1;
578 if (updating_frame
== 0)
581 x_display_cursor (f
, 1);
590 /* Clear to the end of the line.
591 Erase the current text line from the nominal cursor position (inclusive)
592 to column FIRST_UNUSED (exclusive). The idea is that everything
593 from FIRST_UNUSED onward is already erased. */
596 XTclear_end_of_line (first_unused
)
597 register int first_unused
;
599 struct frame
*f
= updating_frame
;
605 if (curs_y
< 0 || curs_y
>= f
->height
)
607 if (first_unused
<= 0)
610 if (first_unused
>= f
->width
)
611 first_unused
= f
->width
;
615 /* Notice if the cursor will be cleared by this operation. */
616 if (curs_y
== f
->phys_cursor_y
617 && curs_x
<= f
->phys_cursor_x
618 && f
->phys_cursor_x
< first_unused
)
619 f
->phys_cursor_x
= -1;
622 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
623 CHAR_TO_PIXEL_COL (f
, curs_x
),
624 CHAR_TO_PIXEL_ROW (f
, curs_y
),
625 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
626 FONT_HEIGHT (f
->display
.x
->font
), False
);
628 #else /* ! defined (HAVE_X11) */
629 XPixSet (FRAME_X_WINDOW (f
),
630 CHAR_TO_PIXEL_COL (f
, curs_x
),
631 CHAR_TO_PIXEL_ROW (f
, curs_y
),
632 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
633 FONT_HEIGHT (f
->display
.x
->font
),
634 f
->display
.x
->background_pixel
);
635 #endif /* ! defined (HAVE_X11) */
644 struct frame
*f
= updating_frame
;
649 f
->phys_cursor_x
= -1; /* Cursor not visible. */
650 curs_x
= 0; /* Nominal cursor position is top left. */
655 XClear (FRAME_X_WINDOW (f
));
657 /* We have to clear the scroll bars, too. If we have changed
658 colors or something like that, then they should be notified. */
659 x_scroll_bar_clear (f
);
663 #endif /* HAVE_X11 */
669 /* Invert the middle quarter of the frame for .15 sec. */
671 /* We use the select system call to do the waiting, so we have to make sure
672 it's avaliable. If it isn't, we just won't do visual bells. */
673 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
675 /* Subtract the `struct timeval' values X and Y,
676 storing the result in RESULT.
677 Return 1 if the difference is negative, otherwise 0. */
680 timeval_subtract (result
, x
, y
)
681 struct timeval
*result
, x
, y
;
683 /* Perform the carry for the later subtraction by updating y.
684 This is safer because on some systems
685 the tv_sec member is unsigned. */
686 if (x
.tv_usec
< y
.tv_usec
)
688 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
689 y
.tv_usec
-= 1000000 * nsec
;
692 if (x
.tv_usec
- y
.tv_usec
> 1000000)
694 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
695 y
.tv_usec
+= 1000000 * nsec
;
699 /* Compute the time remaining to wait. tv_usec is certainly positive. */
700 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
701 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
703 /* Return indication of whether the result should be considered negative. */
704 return x
.tv_sec
< y
.tv_sec
;
715 /* Create a GC that will use the GXxor function to flip foreground pixels
716 into background pixels. */
720 values
.function
= GXxor
;
721 values
.foreground
= (f
->display
.x
->foreground_pixel
722 ^ f
->display
.x
->background_pixel
);
724 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
725 GCFunction
| GCForeground
, &values
);
729 int width
= PIXEL_WIDTH (f
);
730 int height
= PIXEL_HEIGHT (f
);
732 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
733 width
/4, height
/4, width
/2, height
/2);
734 XFlush (x_current_display
);
737 struct timeval wakeup
, now
;
739 gettimeofday (&wakeup
, (struct timezone
*) 0);
741 /* Compute time to wait until, propagating carry from usecs. */
742 wakeup
.tv_usec
+= 150000;
743 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
744 wakeup
.tv_usec
%= 1000000;
746 /* Keep waiting until past the time wakeup. */
749 struct timeval timeout
;
751 gettimeofday (&timeout
, (struct timezone
*)0);
753 /* In effect, timeout = wakeup - timeout.
754 Break if result would be negative. */
755 if (timeval_subtract (&timeout
, wakeup
, timeout
))
758 /* Try to wait that long--but we might wake up sooner. */
759 select (0, 0, 0, 0, &timeout
);
763 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
764 width
/4, height
/4, width
/2, height
/2);
765 XFreeGC (x_current_display
, gc
);
766 XFlush (x_current_display
);
776 /* Make audible bell. */
779 #define XRINGBELL XBell(x_current_display, 0)
780 #else /* ! defined (HAVE_X11) */
781 #define XRINGBELL XFeep(0);
782 #endif /* ! defined (HAVE_X11) */
786 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
788 XTflash (selected_frame
);
799 /* Insert and delete character.
800 These are not supposed to be used because we are supposed to turn
801 off the feature of using them. */
804 XTinsert_glyphs (start
, len
)
805 register char *start
;
818 /* Specify how many text lines, from the top of the window,
819 should be affected by insert-lines and delete-lines operations.
820 This, and those operations, are used only within an update
821 that is bounded by calls to XTupdate_begin and XTupdate_end. */
824 XTset_terminal_window (n
)
827 if (updating_frame
== 0)
830 if ((n
<= 0) || (n
> updating_frame
->height
))
831 flexlines
= updating_frame
->height
;
836 /* Perform an insert-lines operation.
837 Insert N lines at a vertical position curs_y. */
843 register int topregion
, bottomregion
;
844 register int length
, newtop
, mask
;
845 register struct frame
*f
= updating_frame
;
846 int intborder
= f
->display
.x
->internal_border_width
;
848 if (curs_y
>= flexlines
)
852 bottomregion
= flexlines
- (n
+ 1);
853 newtop
= topregion
+ n
;
854 length
= (bottomregion
- topregion
) + 1;
858 #endif /* HAVE_X11 */
860 if ((length
> 0) && (newtop
<= flexlines
))
863 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
864 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
865 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
866 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
867 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
868 CHAR_TO_PIXEL_ROW (f
, newtop
));
869 #else /* ! defined (HAVE_X11) */
870 XMoveArea (FRAME_X_WINDOW (f
),
871 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
872 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
873 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
874 length
* FONT_HEIGHT (f
->display
.x
->font
));
875 /* Now we must process any ExposeRegion events that occur
876 if the area being copied from is obscured.
877 We can't let it wait because further i/d operations
878 may want to copy this area to another area. */
880 #endif /* ! defined (HAVE_X11) */
883 newtop
= min (newtop
, (flexlines
- 1));
884 length
= newtop
- topregion
;
888 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
889 CHAR_TO_PIXEL_ROW (f
, topregion
),
890 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
891 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
892 #else /* ! defined (HAVE_X11) */
893 XPixSet (FRAME_X_WINDOW (f
),
895 CHAR_TO_PIXEL_ROW (f
, topregion
),
896 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
897 n
* FONT_HEIGHT (f
->display
.x
->font
),
898 f
->display
.x
->background_pixel
);
899 #endif /* ! defined (HAVE_X11) */
903 /* Perform a delete-lines operation, deleting N lines
904 at a vertical position curs_y. */
911 register struct frame
*f
= updating_frame
;
912 int intborder
= f
->display
.x
->internal_border_width
;
914 if (curs_y
>= flexlines
)
919 #endif /* HAVE_X11 */
921 if ((curs_y
+ n
) >= flexlines
)
923 if (flexlines
>= (curs_y
+ 1))
926 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
927 CHAR_TO_PIXEL_ROW (f
, curs_y
),
928 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
929 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
930 #else /* ! defined (HAVE_X11) */
931 XPixSet (FRAME_X_WINDOW (f
),
932 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
933 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
934 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
935 f
->display
.x
->background_pixel
);
936 #endif /* ! defined (HAVE_X11) */
942 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
943 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
945 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
946 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
947 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
948 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
949 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
951 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
952 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
953 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
954 #else /* ! defined (HAVE_X11) */
955 XMoveArea (FRAME_X_WINDOW (f
),
957 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
958 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
959 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
960 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
961 /* Now we must process any ExposeRegion events that occur
962 if the area being copied from is obscured.
963 We can't let it wait because further i/d operations
964 may want to copy this area to another area. */
966 XPixSet (FRAME_X_WINDOW (f
), intborder
,
967 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
968 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
969 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
970 #endif /* ! defined (HAVE_X11) */
974 /* Perform an insert-lines or delete-lines operation,
975 inserting N lines or deleting -N lines at vertical position VPOS. */
977 XTins_del_lines (vpos
, n
)
980 if (updating_frame
== 0)
983 /* Hide the cursor. */
984 x_display_cursor (updating_frame
, 0);
986 XTcursor_to (vpos
, 0);
997 /* Support routines for exposure events. */
998 static void clear_cursor ();
1000 /* Output into a rectangle of an X-window (for frame F)
1001 the characters in f->phys_lines that overlap that rectangle.
1002 TOP and LEFT are the position of the upper left corner of the rectangle.
1003 ROWS and COLS are the size of the rectangle. */
1006 dumprectangle (f
, left
, top
, cols
, rows
)
1008 register int left
, top
, cols
, rows
;
1010 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1011 int cursor_cleared
= 0;
1015 if (FRAME_GARBAGED_P (f
))
1018 /* Express rectangle as four edges, instead of position-and-size. */
1019 bottom
= top
+ rows
;
1020 right
= left
+ cols
;
1022 #ifndef HAVE_X11 /* Window manger does this for X11. */
1024 int intborder
= f
->display
.x
->internal_border_width
;
1026 /* If the rectangle includes any of the internal border area,
1027 redisplay the border emphasis. */
1028 if (top
< intborder
|| left
< intborder
1029 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1030 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1033 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1035 /* Convert rectangle edges in pixels to edges in chars.
1036 Round down for left and top, up for right and bottom. */
1037 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1038 left
= PIXEL_TO_CHAR_COL (f
, left
);
1039 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1040 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1041 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1042 right
= PIXEL_TO_CHAR_COL (f
, right
);
1044 /* Clip the rectangle to what can be visible. */
1049 if (right
> f
->width
)
1051 if (bottom
> f
->height
)
1054 /* Get size in chars of the rectangle. */
1055 cols
= right
- left
;
1056 rows
= bottom
- top
;
1058 /* If rectangle has zero area, return. */
1059 if (rows
<= 0) return;
1060 if (cols
<= 0) return;
1062 /* Turn off the cursor if it is in the rectangle.
1063 We will turn it back on afterward. */
1064 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1065 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1071 /* Display the text in the rectangle, one text line at a time. */
1073 for (y
= top
; y
< bottom
; y
++)
1075 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1077 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1081 CHAR_TO_PIXEL_COL (f
, left
),
1082 CHAR_TO_PIXEL_ROW (f
, y
),
1083 line
, min (cols
, active_frame
->used
[y
] - left
),
1084 active_frame
->highlight
[y
], f
->display
.x
->font
);
1087 /* Turn the cursor on if we turned it off. */
1090 x_display_cursor (f
, 1);
1094 /* Process all queued ExposeRegion events. */
1100 XExposeRegionEvent r
;
1102 while (dequeue_event (&r
, &x_expose_queue
))
1104 struct frame
*f
= x_window_to_frame (r
.window
);
1105 if (f
->display
.x
->icon_desc
== r
.window
)
1108 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1112 #endif /* HAVE_X11 */
1114 /* Process all expose events that are pending, for X10.
1115 Redraws the cursor if necessary on any frame that
1116 is not in the process of being updated with update_frame. */
1120 x_do_pending_expose ()
1124 Lisp_Object tail
, frame
;
1126 if (expose_all_windows
)
1128 expose_all_windows
= 0;
1129 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1131 register int temp_width
, temp_height
;
1134 frame
= XCONS (tail
)->car
;
1135 if (XGCTYPE (frame
) != Lisp_Frame
)
1138 if (! FRAME_X_P (f
))
1140 if (!f
->async_visible
)
1142 if (!f
->display
.x
->needs_exposure
)
1145 intborder
= f
->display
.x
->internal_border_width
;
1148 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1149 temp_width
= ((windowinfo
.width
- 2 * intborder
1150 - f
->display
.x
->v_scroll_bar_width
)
1151 / FONT_WIDTH (f
->display
.x
->font
));
1152 temp_height
= ((windowinfo
.height
- 2 * intborder
1153 - f
->display
.x
->h_scroll_bar_height
)
1154 / FONT_HEIGHT (f
->display
.x
->font
));
1155 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1157 change_frame_size (f
, max (1, temp_height
),
1158 max (1, temp_width
), 0, 1);
1159 x_resize_scroll_bars (f
);
1161 f
->display
.x
->left_pos
= windowinfo
.x
;
1162 f
->display
.x
->top_pos
= windowinfo
.y
;
1163 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1167 f
->display
.x
->needs_exposure
= 0;
1168 if (updating_frame
!= f
)
1169 x_display_cursor (f
, 1);
1174 /* Handle any individual-rectangle expose events queued
1175 for various windows. */
1178 #else /* ! defined (HAVE_X11) */
1180 #endif /* ! defined (HAVE_X11) */
1186 frame_highlight (frame
)
1187 struct frame
*frame
;
1189 if (! EQ (Vx_no_window_manager
, Qnil
))
1190 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1191 frame
->display
.x
->border_pixel
);
1192 x_display_cursor (frame
, 1);
1196 frame_unhighlight (frame
)
1197 struct frame
*frame
;
1199 if (! EQ (Vx_no_window_manager
, Qnil
))
1200 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1201 frame
->display
.x
->border_tile
);
1202 x_display_cursor (frame
, 1);
1204 #else /* ! defined (HAVE_X11) */
1205 /* Dump the border-emphasis of frame F.
1206 If F is selected, this is a lining of the same color as the border,
1207 just within the border, occupying a portion of the internal border.
1208 If F is not selected, it is background in the same place.
1209 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1211 ALWAYS = 1 is used when a frame becomes selected or deselected.
1212 In that case, we also turn the cursor off and on again
1213 so it will appear in the proper shape (solid if selected; else hollow.) */
1216 dumpborder (f
, always
)
1220 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1221 int width
= PIXEL_WIDTH (f
);
1222 int height
= PIXEL_HEIGHT (f
);
1225 if (f
!= selected_frame
)
1230 pixel
= f
->display
.x
->background_pixel
;
1234 pixel
= f
->display
.x
->border_pixel
;
1237 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1238 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1239 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1241 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1245 x_display_cursor (f
, 1);
1247 #endif /* ! defined (HAVE_X11) */
1249 static void XTframe_rehighlight ();
1251 /* The focus has changed. Update the frames as necessary to reflect
1252 the new situation. Note that we can't change the selected frame
1253 here, because the lisp code we are interrupting might become confused.
1254 Each event gets marked with the frame in which it occured, so the
1255 lisp code can tell when the switch took place by examining the events. */
1258 x_new_focus_frame (frame
)
1259 struct frame
*frame
;
1261 struct frame
*old_focus
= x_focus_frame
;
1262 int events_enqueued
= 0;
1264 if (frame
!= x_focus_frame
)
1266 /* Set this before calling other routines, so that they see
1267 the correct value of x_focus_frame. */
1268 x_focus_frame
= frame
;
1270 if (old_focus
&& old_focus
->auto_lower
)
1271 x_lower_frame (old_focus
);
1274 selected_frame
= frame
;
1275 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1276 Lisp_Frame
, selected_frame
);
1277 Fselect_window (selected_frame
->selected_window
);
1278 choose_minibuf_frame ();
1281 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1282 x_raise_frame (x_focus_frame
);
1285 XTframe_rehighlight ();
1289 /* The focus has changed, or we have redirected a frame's focus to
1290 another frame (this happens when a frame uses a surrogate
1291 minibuffer frame). Shift the highlight as appropriate. */
1293 XTframe_rehighlight ()
1295 struct frame
*old_highlight
= x_highlight_frame
;
1300 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1301 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1303 if (! FRAME_LIVE_P (x_highlight_frame
))
1305 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1306 x_highlight_frame
= x_focus_frame
;
1310 x_highlight_frame
= 0;
1312 if (x_highlight_frame
!= old_highlight
)
1315 frame_unhighlight (old_highlight
);
1316 if (x_highlight_frame
)
1317 frame_highlight (x_highlight_frame
);
1321 /* Mouse clicks and mouse movement. Rah. */
1324 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1325 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1326 that the glyph at X, Y occupies, if BOUNDS != 0. */
1328 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1330 register unsigned int pix_x
, pix_y
;
1331 register int *x
, *y
;
1334 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1335 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1339 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1340 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1341 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1342 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1345 if (pix_x
< 0) pix_x
= 0;
1346 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1348 if (pix_y
< 0) pix_y
= 0;
1349 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1355 /* Any buttons grabbed. */
1356 unsigned int x_mouse_grabbed
;
1358 /* Which modifier keys are on which modifier bits?
1360 With each keystroke, X returns eight bits indicating which modifier
1361 keys were held down when the key was pressed. The interpretation
1362 of the top five modifier bits depends on what keys are attached
1363 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1366 x_meta_mod_mask is a mask containing the bits used for the meta key.
1367 It may have more than one bit set, if more than one modifier bit
1368 has meta keys on it. Basically, if EVENT is a KeyPress event,
1369 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1371 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1372 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1373 only be affected by the lock modifier bit if XK_Shift_Lock is in
1374 use; XK_Caps_Lock should only affect alphabetic keys. With this
1375 arrangement, the lock modifier should shift the character if
1376 (EVENT.state & x_shift_lock_mask) != 0. */
1377 static int x_meta_mod_mask
, x_shift_lock_mask
;
1379 /* These are like x_meta_mod_mask, but for different modifiers. */
1380 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1382 /* Initialize mode_switch_bit and modifier_meaning. */
1384 x_find_modifier_meanings ()
1386 int min_code
, max_code
;
1389 XModifierKeymap
*mods
;
1391 x_meta_mod_mask
= 0;
1392 x_shift_lock_mask
= 0;
1394 x_super_mod_mask
= 0;
1395 x_hyper_mod_mask
= 0;
1398 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1400 min_code
= x_current_display
->min_keycode
;
1401 max_code
= x_current_display
->max_keycode
;
1404 syms
= XGetKeyboardMapping (x_current_display
,
1405 min_code
, max_code
- min_code
+ 1,
1407 mods
= XGetModifierMapping (x_current_display
);
1409 /* Scan the modifier table to see which modifier bits the Meta and
1410 Alt keysyms are on. */
1412 int row
, col
; /* The row and column in the modifier table. */
1414 for (row
= 3; row
< 8; row
++)
1415 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1418 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1420 /* Are any of this keycode's keysyms a meta key? */
1424 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1426 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1432 x_meta_mod_mask
|= (1 << row
);
1437 x_alt_mod_mask
|= (1 << row
);
1442 x_hyper_mod_mask
|= (1 << row
);
1447 x_super_mod_mask
|= (1 << row
);
1451 /* Ignore this if it's not on the lock modifier. */
1452 if ((1 << row
) == LockMask
)
1453 x_shift_lock_mask
= LockMask
;
1461 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1462 if (! x_meta_mod_mask
)
1464 x_meta_mod_mask
= x_alt_mod_mask
;
1468 XFree ((char *) syms
);
1469 XFreeModifiermap (mods
);
1473 /* Convert a set of X modifier bits to the proper form for a
1474 struct input_event modifiers value. */
1477 x_convert_modifiers (state
)
1480 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1481 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1482 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1483 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1484 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1485 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1488 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1490 If the event is a button press, then note that we have grabbed
1494 construct_mouse_click (result
, event
, f
)
1495 struct input_event
*result
;
1496 XButtonEvent
*event
;
1499 /* Make the event type no_event; we'll change that when we decide
1501 result
->kind
= mouse_click
;
1502 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1503 result
->timestamp
= event
->time
;
1504 result
->modifiers
= (x_convert_modifiers (event
->state
)
1505 | (event
->type
== ButtonRelease
1509 /* Notice if the mouse is still grabbed. */
1510 if (event
->type
== ButtonPress
)
1512 if (! x_mouse_grabbed
)
1513 Vmouse_depressed
= Qt
;
1514 x_mouse_grabbed
|= (1 << event
->button
);
1516 else if (event
->type
== ButtonRelease
)
1518 x_mouse_grabbed
&= ~(1 << event
->button
);
1519 if (!x_mouse_grabbed
)
1520 Vmouse_depressed
= Qnil
;
1526 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1527 XFASTINT (result
->x
) = column
;
1528 XFASTINT (result
->y
) = row
;
1529 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1534 /* Mouse movement. Rah.
1536 In order to avoid asking for motion events and then throwing most
1537 of them away or busy-polling the server for mouse positions, we ask
1538 the server for pointer motion hints. This means that we get only
1539 one event per group of mouse movements. "Groups" are delimited by
1540 other kinds of events (focus changes and button clicks, for
1541 example), or by XQueryPointer calls; when one of these happens, we
1542 get another MotionNotify event the next time the mouse moves. This
1543 is at least as efficient as getting motion events when mouse
1544 tracking is on, and I suspect only negligibly worse when tracking
1547 The silly O'Reilly & Associates Nutshell guides barely document
1548 pointer motion hints at all (I think you have to infer how they
1549 work from an example), and the description of XQueryPointer doesn't
1550 mention that calling it causes you to get another motion hint from
1551 the server, which is very important. */
1553 /* Where the mouse was last time we reported a mouse event. */
1554 static FRAME_PTR last_mouse_frame
;
1555 static XRectangle last_mouse_glyph
;
1557 /* The scroll bar in which the last X motion event occurred.
1559 If the last X motion event occured in a scroll bar, we set this
1560 so XTmouse_position can know whether to report a scroll bar motion or
1563 If the last X motion event didn't occur in a scroll bar, we set this
1564 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1565 static Lisp_Object last_mouse_scroll_bar
;
1567 /* This is a hack. We would really prefer that XTmouse_position would
1568 return the time associated with the position it returns, but there
1569 doesn't seem to be any way to wrest the timestamp from the server
1570 along with the position query. So, we just keep track of the time
1571 of the last movement we received, and return that in hopes that
1572 it's somewhat accurate. */
1573 static Time last_mouse_movement_time
;
1575 /* Function to report a mouse movement to the mainstream Emacs code.
1576 The input handler calls this.
1578 We have received a mouse movement event, which is given in *event.
1579 If the mouse is over a different glyph than it was last time, tell
1580 the mainstream emacs code by setting mouse_moved. If not, ask for
1581 another motion event, so we can check again the next time it moves. */
1583 note_mouse_movement (frame
, event
)
1585 XMotionEvent
*event
;
1588 last_mouse_movement_time
= event
->time
;
1590 /* Has the mouse moved off the glyph it was on at the last sighting? */
1591 if (event
->x
< last_mouse_glyph
.x
1592 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1593 || event
->y
< last_mouse_glyph
.y
1594 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1597 last_mouse_scroll_bar
= Qnil
;
1601 /* It's on the same glyph. Call XQueryPointer so we'll get an
1602 event the next time the mouse moves and we can see if it's
1603 *still* on the same glyph. */
1606 XQueryPointer (event
->display
, event
->window
,
1607 (Window
*) &dummy
, (Window
*) &dummy
,
1608 &dummy
, &dummy
, &dummy
, &dummy
,
1609 (unsigned int *) &dummy
);
1613 static struct scroll_bar
*x_window_to_scroll_bar ();
1614 static void x_scroll_bar_report_motion ();
1616 /* Return the current position of the mouse.
1618 If the mouse movement started in a scroll bar, set *f, *bar_window,
1619 and *part to the frame, window, and scroll bar part that the mouse
1620 is over. Set *x and *y to the portion and whole of the mouse's
1621 position on the scroll bar.
1623 If the mouse movement started elsewhere, set *f to the frame the
1624 mouse is on, *bar_window to nil, and *x and *y to the character cell
1627 Set *time to the server timestamp for the time at which the mouse
1628 was at this position.
1630 This clears the mouse_moved flag, so we can wait for the next mouse
1631 movement. This also calls XQueryPointer, which will cause the
1632 server to give us another MotionNotify when the mouse moves
1636 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1638 Lisp_Object
*bar_window
;
1639 enum scroll_bar_part
*part
;
1641 unsigned long *time
;
1645 if (! NILP (last_mouse_scroll_bar
))
1646 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1652 Window dummy_window
;
1656 last_mouse_scroll_bar
= Qnil
;
1658 /* Figure out which root window we're on. */
1659 XQueryPointer (x_current_display
,
1660 DefaultRootWindow (x_current_display
),
1662 /* The root window which contains the pointer. */
1665 /* Trash which we can't trust if the pointer is on
1666 a different screen. */
1669 /* The position on that root window. */
1672 /* More trash we can't trust. */
1675 /* Modifier keys and pointer buttons, about which
1677 (unsigned int *) &dummy
);
1679 /* Now we have a position on the root; find the innermost window
1680 containing the pointer. */
1684 int parent_x
, parent_y
;
1689 XTranslateCoordinates (x_current_display
,
1691 /* From-window, to-window. */
1694 /* From-position, to-position. */
1695 root_x
, root_y
, &win_x
, &win_y
,
1708 /* Now we know that:
1709 win is the innermost window containing the pointer
1710 (XTC says it has no child containing the pointer),
1711 win_x and win_y are the pointer's position in it
1712 (XTC did this the last time through), and
1713 parent_x and parent_y are the pointer's position in win's parent.
1714 (They are what win_x and win_y were when win was child.
1715 If win is the root window, it has no parent, and
1716 parent_{x,y} are invalid, but that's okay, because we'll
1717 never use them in that case.) */
1719 /* Is win one of our frames? */
1720 *f
= x_window_to_frame (win
);
1722 /* If not, is it one of our scroll bars? */
1725 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1729 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1737 pixel_to_glyph_coords (*f
, win_x
, win_y
, &win_x
, &win_y
,
1742 XSET (*x
, Lisp_Int
, win_x
);
1743 XSET (*y
, Lisp_Int
, win_y
);
1744 *time
= last_mouse_movement_time
;
1752 #else /* ! defined (HAVE_X11) */
1753 #define XEvent XKeyPressedEvent
1754 #endif /* ! defined (HAVE_X11) */
1756 /* Scroll bar support. */
1758 /* Given an X window ID, find the struct scroll_bar which manages it.
1759 This can be called in GC, so we have to make sure to strip off mark
1761 static struct scroll_bar
*
1762 x_window_to_scroll_bar (window_id
)
1765 Lisp_Object tail
, frame
;
1767 for (tail
= Vframe_list
;
1768 XGCTYPE (tail
) == Lisp_Cons
;
1769 tail
= XCONS (tail
)->cdr
)
1771 Lisp_Object frame
= XCONS (tail
)->car
;
1772 Lisp_Object bar
, condemned
;
1774 /* All elements of Vframe_list should be frames. */
1775 if (XGCTYPE (frame
) != Lisp_Frame
)
1778 /* Scan this frame's scroll bar list for a scroll bar with the
1780 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1781 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1782 /* This trick allows us to search both the ordinary and
1783 condemned scroll bar lists with one loop. */
1784 ! GC_NILP (bar
) || (bar
= condemned
,
1787 bar
= XSCROLL_BAR(bar
)->next
)
1788 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1789 return XSCROLL_BAR (bar
);
1795 /* Open a new X window to serve as a scroll bar, and return the
1796 scroll bar vector for it. */
1797 static struct scroll_bar
*
1798 x_scroll_bar_create (window
, top
, left
, width
, height
)
1799 struct window
*window
;
1800 int top
, left
, width
, height
;
1802 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1803 struct scroll_bar
*bar
=
1804 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1809 XSetWindowAttributes a
;
1812 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1813 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1814 | ButtonMotionMask
| PointerMotionHintMask
1816 a
.cursor
= x_vertical_scroll_bar_cursor
;
1818 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1820 SET_SCROLL_BAR_X_WINDOW
1822 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1824 /* Position and size of scroll bar. */
1825 left
, top
, width
, height
,
1827 /* Border width, depth, class, and visual. */
1828 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1834 XSET (bar
->window
, Lisp_Window
, window
);
1835 XSET (bar
->top
, Lisp_Int
, top
);
1836 XSET (bar
->left
, Lisp_Int
, left
);
1837 XSET (bar
->width
, Lisp_Int
, width
);
1838 XSET (bar
->height
, Lisp_Int
, height
);
1839 XSET (bar
->start
, Lisp_Int
, 0);
1840 XSET (bar
->end
, Lisp_Int
, 0);
1841 bar
->dragging
= Qnil
;
1843 /* Add bar to its frame's list of scroll bars. */
1844 bar
->next
= FRAME_SCROLL_BARS (frame
);
1846 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
1847 if (! NILP (bar
->next
))
1848 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1850 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
1857 /* Draw BAR's handle in the proper position.
1858 If the handle is already drawn from START to END, don't bother
1859 redrawing it, unless REBUILD is non-zero; in that case, always
1860 redraw it. (REBUILD is handy for drawing the handle after expose
1863 Normally, we want to constrain the start and end of the handle to
1864 fit inside its rectangle, but if the user is dragging the scroll bar
1865 handle, we want to let them drag it down all the way, so that the
1866 bar's top is as far down as it goes; otherwise, there's no way to
1867 move to the very end of the buffer. */
1869 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1870 struct scroll_bar
*bar
;
1874 int dragging
= ! NILP (bar
->dragging
);
1875 Window w
= SCROLL_BAR_X_WINDOW (bar
);
1876 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1878 /* If the display is already accurate, do nothing. */
1880 && start
== XINT (bar
->start
)
1881 && end
== XINT (bar
->end
))
1887 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
1888 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
1889 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
1891 /* Make sure the values are reasonable, and try to preserve
1892 the distance between start and end. */
1894 int length
= end
- start
;
1898 else if (start
> top_range
)
1900 end
= start
+ length
;
1904 else if (end
> top_range
&& ! dragging
)
1908 /* Store the adjusted setting in the scroll bar. */
1909 XSET (bar
->start
, Lisp_Int
, start
);
1910 XSET (bar
->end
, Lisp_Int
, end
);
1912 /* Clip the end position, just for display. */
1913 if (end
> top_range
)
1916 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1917 below top positions, to make sure the handle is always at least
1918 that many pixels tall. */
1919 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
1921 /* Draw the empty space above the handle. Note that we can't clear
1922 zero-height areas; that means "clear to end of window." */
1924 XClearArea (x_current_display
, w
,
1926 /* x, y, width, height, and exposures. */
1927 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1928 VERTICAL_SCROLL_BAR_TOP_BORDER
,
1929 inside_width
, start
,
1932 /* Draw the handle itself. */
1933 XFillRectangle (x_current_display
, w
, gc
,
1935 /* x, y, width, height */
1936 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1937 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
1938 inside_width
, end
- start
);
1941 /* Draw the empty space below the handle. Note that we can't
1942 clear zero-height areas; that means "clear to end of window." */
1943 if (end
< inside_height
)
1944 XClearArea (x_current_display
, w
,
1946 /* x, y, width, height, and exposures. */
1947 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1948 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
1949 inside_width
, inside_height
- end
,
1957 /* Move a scroll bar around on the screen, to accomodate changing
1958 window configurations. */
1960 x_scroll_bar_move (bar
, top
, left
, width
, height
)
1961 struct scroll_bar
*bar
;
1962 int top
, left
, width
, height
;
1968 unsigned int mask
= 0;
1975 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
1976 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
1977 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
1978 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
1981 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
1985 XSET (bar
->left
, Lisp_Int
, left
);
1986 XSET (bar
->top
, Lisp_Int
, top
);
1987 XSET (bar
->width
, Lisp_Int
, width
);
1988 XSET (bar
->height
, Lisp_Int
, height
);
1993 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
1996 x_scroll_bar_remove (bar
)
1997 struct scroll_bar
*bar
;
1999 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2003 /* Destroy the window. */
2004 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2006 /* Disassociate this scroll bar from its window. */
2007 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2012 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2013 that we are displaying PORTION characters out of a total of WHOLE
2014 characters, starting at POSITION. If WINDOW has no scroll bar,
2017 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2018 struct window
*window
;
2019 int portion
, whole
, position
;
2021 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2022 int top
= XINT (window
->top
);
2023 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2024 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2026 /* Where should this scroll bar be, pixelwise? */
2027 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2028 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2029 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2030 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2032 struct scroll_bar
*bar
;
2034 /* Does the scroll bar exist yet? */
2035 if (NILP (window
->vertical_scroll_bar
))
2036 bar
= x_scroll_bar_create (window
,
2037 pixel_top
, pixel_left
,
2038 pixel_width
, pixel_height
);
2041 /* It may just need to be moved and resized. */
2042 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2043 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2046 /* Set the scroll bar's current state, unless we're currently being
2048 if (NILP (bar
->dragging
))
2051 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2054 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2057 int start
= (position
* top_range
) / whole
;
2058 int end
= ((position
+ portion
) * top_range
) / whole
;
2060 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2064 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2068 /* The following three hooks are used when we're doing a thorough
2069 redisplay of the frame. We don't explicitly know which scroll bars
2070 are going to be deleted, because keeping track of when windows go
2071 away is a real pain - "Can you say set-window-configuration, boys
2072 and girls?" Instead, we just assert at the beginning of redisplay
2073 that *all* scroll bars are to be removed, and then save a scroll bar
2074 from the fiery pit when we actually redisplay its window. */
2076 /* Arrange for all scroll bars on FRAME to be removed at the next call
2077 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2078 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2080 XTcondemn_scroll_bars (frame
)
2083 /* The condemned list should be empty at this point; if it's not,
2084 then the rest of Emacs isn't using the condemn/redeem/judge
2085 protocol correctly. */
2086 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2089 /* Move them all to the "condemned" list. */
2090 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2091 FRAME_SCROLL_BARS (frame
) = Qnil
;
2094 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2095 Note that WINDOW isn't necessarily condemned at all. */
2097 XTredeem_scroll_bar (window
)
2098 struct window
*window
;
2100 struct scroll_bar
*bar
;
2102 /* We can't redeem this window's scroll bar if it doesn't have one. */
2103 if (NILP (window
->vertical_scroll_bar
))
2106 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2108 /* Unlink it from the condemned list. */
2110 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2112 if (NILP (bar
->prev
))
2114 /* If the prev pointer is nil, it must be the first in one of
2116 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2117 /* It's not condemned. Everything's fine. */
2119 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2120 window
->vertical_scroll_bar
))
2121 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2123 /* If its prev pointer is nil, it must be at the front of
2124 one or the other! */
2128 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2130 if (! NILP (bar
->next
))
2131 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2133 bar
->next
= FRAME_SCROLL_BARS (f
);
2135 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2136 if (! NILP (bar
->next
))
2137 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2141 /* Remove all scroll bars on FRAME that haven't been saved since the
2142 last call to `*condemn_scroll_bars_hook'. */
2144 XTjudge_scroll_bars (f
)
2147 Lisp_Object bar
, next
;
2149 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2151 /* Clear out the condemned list now so we won't try to process any
2152 more events on the hapless scroll bars. */
2153 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2155 for (; ! NILP (bar
); bar
= next
)
2157 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2159 x_scroll_bar_remove (b
);
2162 b
->next
= b
->prev
= Qnil
;
2165 /* Now there should be no references to the condemned scroll bars,
2166 and they should get garbage-collected. */
2170 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2172 This may be called from a signal handler, so we have to ignore GC
2175 x_scroll_bar_expose (bar
, event
)
2176 struct scroll_bar
*bar
;
2179 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2180 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2184 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2186 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2187 XDrawRectangle (x_current_display
, w
, gc
,
2189 /* x, y, width, height */
2190 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2192 /* Draw another line to make the extra-thick border on the right. */
2193 XFillRectangle (x_current_display
, w
, gc
,
2195 /* x, y, width, height */
2196 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2201 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2202 is set to something other than no_event, it is enqueued.
2204 This may be called from a signal handler, so we have to ignore GC
2207 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2208 struct scroll_bar
*bar
;
2210 struct input_event
*emacs_event
;
2212 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2215 emacs_event
->kind
= scroll_bar_click
;
2216 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2217 emacs_event
->modifiers
=
2218 (x_convert_modifiers (event
->xbutton
.state
)
2219 | (event
->type
== ButtonRelease
2222 emacs_event
->frame_or_window
= bar
->window
;
2223 emacs_event
->timestamp
= event
->xbutton
.time
;
2225 int internal_height
=
2226 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2228 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2229 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2232 if (y
> top_range
) y
= top_range
;
2234 if (y
< XINT (bar
->start
))
2235 emacs_event
->part
= scroll_bar_above_handle
;
2236 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2237 emacs_event
->part
= scroll_bar_handle
;
2239 emacs_event
->part
= scroll_bar_below_handle
;
2241 /* If the user has just clicked on the handle, record where they're
2243 if (event
->type
== ButtonPress
2244 && emacs_event
->part
== scroll_bar_handle
)
2245 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2247 /* If the user has released the handle, set it to its final position. */
2248 if (event
->type
== ButtonRelease
2249 && ! NILP (bar
->dragging
))
2251 int new_start
= y
- XINT (bar
->dragging
);
2252 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2254 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2255 bar
->dragging
= Qnil
;
2258 /* Clicks on the handle are always reported as occuring at the top of
2260 if (emacs_event
->part
== scroll_bar_handle
)
2261 emacs_event
->x
= bar
->start
;
2263 XSET (emacs_event
->x
, Lisp_Int
, y
);
2265 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2269 /* Handle some mouse motion while someone is dragging the scroll bar.
2271 This may be called from a signal handler, so we have to ignore GC
2274 x_scroll_bar_note_movement (bar
, event
)
2275 struct scroll_bar
*bar
;
2278 last_mouse_movement_time
= event
->xmotion
.time
;
2281 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2283 /* If we're dragging the bar, display it. */
2284 if (! GC_NILP (bar
->dragging
))
2286 /* Where should the handle be now? */
2287 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2289 if (new_start
!= XINT (bar
->start
))
2291 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2293 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2297 /* Call XQueryPointer so we'll get an event the next time the mouse
2298 moves and we can see *still* on the same position. */
2302 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2303 (Window
*) &dummy
, (Window
*) &dummy
,
2304 &dummy
, &dummy
, &dummy
, &dummy
,
2305 (unsigned int *) &dummy
);
2309 /* Return information to the user about the current position of the mouse
2310 on the scroll bar. */
2312 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2314 Lisp_Object
*bar_window
;
2315 enum scroll_bar_part
*part
;
2317 unsigned long *time
;
2319 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2324 /* Get the mouse's position relative to the scroll bar window, and
2327 Window dummy_window
;
2329 unsigned int dummy_mask
;
2331 if (! XQueryPointer (x_current_display
,
2332 SCROLL_BAR_X_WINDOW (bar
),
2334 /* Root, child, root x and root y. */
2335 &dummy_window
, &dummy_window
,
2336 &dummy_coord
, &dummy_coord
,
2338 /* Position relative to scroll bar. */
2341 /* Mouse buttons and modifier keys. */
2350 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2351 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2353 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2355 if (! NILP (bar
->dragging
))
2356 win_y
-= XINT (bar
->dragging
);
2360 if (win_y
> top_range
)
2363 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2364 *bar_window
= bar
->window
;
2366 if (! NILP (bar
->dragging
))
2367 *part
= scroll_bar_handle
;
2368 else if (win_y
< XINT (bar
->start
))
2369 *part
= scroll_bar_above_handle
;
2370 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2371 *part
= scroll_bar_handle
;
2373 *part
= scroll_bar_below_handle
;
2375 XSET (*x
, Lisp_Int
, win_y
);
2376 XSET (*y
, Lisp_Int
, top_range
);
2377 *time
= last_mouse_movement_time
;
2381 last_mouse_scroll_bar
= Qnil
;
2388 /* The screen has been cleared so we may have changed foreground or
2389 background colors, and the scroll bars may need to be redrawn.
2390 Clear out the scroll bars, and ask for expose events, so we can
2393 x_scroll_bar_clear (f
)
2398 for (bar
= FRAME_SCROLL_BARS (f
);
2399 XTYPE (bar
) == Lisp_Vector
;
2400 bar
= XSCROLL_BAR (bar
)->next
)
2401 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2407 /* The main X event-reading loop - XTread_socket. */
2409 /* Timestamp of enter window event. This is only used by XTread_socket,
2410 but we have to put it out here, since static variables within functions
2411 sometimes don't work. */
2412 static Time enter_timestamp
;
2414 /* This holds the state XLookupString needs to implement dead keys
2415 and other tricks known as "compose processing". _X Window System_
2416 says that a portable program can't use this, but Stephen Gildea assures
2417 me that letting the compiler initialize it to zeros will work okay.
2419 This must be defined outside of XTread_socket, for the same reasons
2420 given for enter_timestamp, above. */
2421 static XComposeStatus compose_status
;
2423 /* Communication with window managers. */
2424 Atom Xatom_wm_protocols
;
2426 /* Kinds of protocol things we may receive. */
2427 Atom Xatom_wm_take_focus
;
2428 Atom Xatom_wm_save_yourself
;
2429 Atom Xatom_wm_delete_window
;
2431 /* Other WM communication */
2432 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2433 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2435 /* Window manager communication. */
2436 Atom Xatom_wm_change_state
;
2438 /* Record the last 100 characters stored
2439 to help debug the loss-of-chars-during-GC problem. */
2441 short temp_buffer
[100];
2443 /* Read events coming from the X server.
2444 This routine is called by the SIGIO handler.
2445 We return as soon as there are no more events to be read.
2447 Events representing keys are stored in buffer BUFP,
2448 which can hold up to NUMCHARS characters.
2449 We return the number of characters stored into the buffer,
2450 thus pretending to be `read'.
2452 WAITP is nonzero if we should block until input arrives.
2453 EXPECTED is nonzero if the caller knows input is available. */
2456 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2458 register struct input_event
*bufp
;
2459 register int numchars
;
2466 int items_pending
; /* How many items are in the X queue. */
2473 if (interrupt_input_blocked
)
2475 interrupt_input_pending
= 1;
2479 interrupt_input_pending
= 0;
2483 abort (); /* Don't think this happens. */
2486 /* If available, Xlib uses FIOSNBIO to make the socket
2487 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2488 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2489 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2490 fcntl (fileno (stdin
), F_SETFL
, 0);
2491 #endif /* ! defined (FIOSNBIO) */
2495 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2497 extern int read_alarm_should_throw
;
2498 read_alarm_should_throw
= 1;
2499 XPeekEvent (XDISPLAY
&event
);
2500 read_alarm_should_throw
= 0;
2502 #endif /* HAVE_SELECT */
2505 while (XStuffPending () != 0)
2507 XNextEvent (XDISPLAY
&event
);
2515 if (event
.xclient
.message_type
== Xatom_wm_protocols
2516 && event
.xclient
.format
== 32)
2518 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2520 f
= x_window_to_frame (event
.xclient
.window
);
2522 x_focus_on_frame (f
);
2523 /* Not certain about handling scroll bars here */
2525 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2527 /* Save state modify the WM_COMMAND property to
2528 something which can reinstate us. This notifies
2529 the session manager, who's looking for such a
2530 PropertyNotify. Can restart processing when
2531 a keyboard or mouse event arrives. */
2536 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2538 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2546 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2549 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2553 new_x
= event
.xclient
.data
.s
[0];
2554 new_y
= event
.xclient
.data
.s
[1];
2559 #ifdef NEW_SELECTIONS
2560 case SelectionNotify
:
2561 x_handle_selection_notify (&event
);
2565 case SelectionClear
: /* Someone has grabbed ownership. */
2566 #ifdef NEW_SELECTIONS
2568 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2573 bufp
->kind
= selection_clear_event
;
2574 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2575 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2576 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2583 x_disown_selection (event
.xselectionclear
.window
,
2584 event
.xselectionclear
.selection
,
2585 event
.xselectionclear
.time
);
2589 case SelectionRequest
: /* Someone wants our selection. */
2590 #ifdef NEW_SELECTIONS
2592 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2597 bufp
->kind
= selection_request_event
;
2598 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2599 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2600 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2601 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2602 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2603 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2610 x_answer_selection_request (event
);
2614 case PropertyNotify
:
2615 #ifdef NEW_SELECTIONS
2616 x_handle_property_notify (&event
);
2618 /* If we're being told about a root window property, then it's
2619 a cut buffer change. */
2620 if (event
.xproperty
.window
== ROOT_WINDOW
)
2621 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2623 /* Otherwise, we're probably handling an incremental
2624 selection transmission. */
2627 /* If we were to do this synchronously, there'd be no worry
2628 about re-selecting. */
2629 x_send_incremental (event
);
2635 f
= x_window_to_frame (event
.xexpose
.window
);
2638 if (f
->async_visible
== 0)
2640 f
->async_visible
= 1;
2641 f
->async_iconified
= 0;
2642 SET_FRAME_GARBAGED (f
);
2646 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2647 event
.xexpose
.x
, event
.xexpose
.y
,
2648 event
.xexpose
.width
, event
.xexpose
.height
);
2653 struct scroll_bar
*bar
2654 = x_window_to_scroll_bar (event
.xexpose
.window
);
2657 x_scroll_bar_expose (bar
, &event
);
2661 case GraphicsExpose
: /* This occurs when an XCopyArea's
2662 source area was obscured or not
2664 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2668 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2669 event
.xgraphicsexpose
.width
,
2670 event
.xgraphicsexpose
.height
);
2674 case NoExpose
: /* This occurs when an XCopyArea's
2675 source area was completely
2678 #else /* ! defined (HAVE_X11) */
2680 if (event
.subwindow
!= 0)
2681 break; /* duplicate event */
2682 f
= x_window_to_frame (event
.window
);
2683 if (event
.window
== f
->display
.x
->icon_desc
)
2686 f
->async_iconified
= 1;
2688 if (event
.window
== FRAME_X_WINDOW (f
))
2690 /* Say must check all windows' needs_exposure flags. */
2691 expose_all_windows
= 1;
2692 f
->display
.x
->needs_exposure
= 1;
2693 f
->async_visible
= 1;
2698 if (event
.subwindow
!= 0)
2699 break; /* duplicate event */
2700 f
= x_window_to_frame (event
.window
);
2701 if (event
.window
== f
->display
.x
->icon_desc
)
2706 /* If window already needs full redraw, ignore this rectangle. */
2707 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2709 /* Put the event on the queue of rectangles to redraw. */
2710 if (enqueue_event (&event
, &x_expose_queue
))
2711 /* If it is full, we can't record the rectangle,
2712 so redraw this entire window. */
2714 /* Say must check all windows' needs_exposure flags. */
2715 expose_all_windows
= 1;
2716 f
->display
.x
->needs_exposure
= 1;
2721 /* This should happen only when we are expecting it,
2722 in x_read_exposes. */
2724 #endif /* ! defined (HAVE_X11) */
2728 f
= x_window_to_frame (event
.xunmap
.window
);
2729 if (f
) /* F may no longer exist if
2730 the frame was deleted. */
2732 /* While a frame is unmapped, display generation is
2733 disabled; you don't want to spend time updating a
2734 display that won't ever be seen. */
2735 f
->async_visible
= 0;
2740 f
= x_window_to_frame (event
.xmap
.window
);
2743 f
->async_visible
= 1;
2744 f
->async_iconified
= 0;
2746 /* wait_reading_process_input will notice this and update
2747 the frame's display structures. */
2748 SET_FRAME_GARBAGED (f
);
2752 /* Turn off processing if we become fully obscured. */
2753 case VisibilityNotify
:
2756 #else /* ! defined (HAVE_X11) */
2758 f
= x_window_to_frame (event
.window
);
2759 if (event
.window
== f
->display
.x
->icon_desc
)
2760 f
->async_iconified
= 0;
2761 if (event
.window
== FRAME_X_WINDOW (f
))
2762 f
->async_visible
= 0;
2764 #endif /* ! defined (HAVE_X11) */
2768 f
= x_window_to_frame (event
.xkey
.window
);
2773 char copy_buffer
[80];
2776 event
.xkey
.state
|= extra_keyboard_modifiers
;
2777 modifiers
= event
.xkey
.state
;
2779 /* Some keyboards generate different characters
2780 depending on the state of the meta key, in an attempt
2781 to support non-English typists. It would be nice to
2782 keep this functionality somehow, but for now, we will
2783 just clear the meta-key flag to get the 'pure' character. */
2784 event
.xkey
.state
&= ~Mod1Mask
;
2786 /* This will have to go some day... */
2788 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2791 /* Strip off the vendor-specific keysym bit, and take a shot
2792 at recognizing the codes. HP servers have extra keysyms
2793 that fit into the MiscFunctionKey category. */
2798 if ((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
2799 || keysym
== XK_Delete
2800 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2801 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < 0xff80 */
2802 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2803 || IsFunctionKey (keysym
)) /* 0xffbe <= x < 0xffe1 */
2805 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2807 temp_buffer
[temp_index
++] = keysym
;
2808 bufp
->kind
= non_ascii_keystroke
;
2809 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff00);
2810 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2811 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2812 bufp
->timestamp
= event
.xkey
.time
;
2817 else if (numchars
> nbytes
)
2821 for (i
= 0; i
< nbytes
; i
++)
2823 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2825 temp_buffer
[temp_index
++] = copy_buffer
[i
];
2826 bufp
->kind
= ascii_keystroke
;
2827 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2828 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2829 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2830 bufp
->timestamp
= event
.xkey
.time
;
2844 #else /* ! defined (HAVE_X11) */
2847 register char *where_mapping
;
2849 f
= x_window_to_frame (event
.window
);
2850 /* Ignore keys typed on icon windows. */
2851 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2853 where_mapping
= XLookupMapping (&event
, &nbytes
);
2854 /* Nasty fix for arrow keys */
2855 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2857 switch (event
.detail
& 0xff)
2859 case KC_CURSOR_LEFT
:
2860 where_mapping
= "\002";
2862 case KC_CURSOR_RIGHT
:
2863 where_mapping
= "\006";
2866 where_mapping
= "\020";
2868 case KC_CURSOR_DOWN
:
2869 where_mapping
= "\016";
2874 if (numchars
- nbytes
> 0)
2878 for (i
= 0; i
< nbytes
; i
++)
2880 bufp
->kind
= ascii_keystroke
;
2881 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2882 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2883 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2891 #endif /* ! defined (HAVE_X11) */
2895 /* Here's a possible interpretation of the whole
2896 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2897 FocusIn event, you have to get a FocusOut event before you
2898 relinquish the focus. If you haven't received a FocusIn event,
2899 then a mere LeaveNotify is enough to free you. */
2902 f
= x_window_to_frame (event
.xcrossing
.window
);
2904 if (event
.xcrossing
.focus
) /* Entered Window */
2906 /* Avoid nasty pop/raise loops. */
2907 if (f
&& (!(f
->auto_raise
)
2909 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
2911 x_new_focus_frame (f
);
2912 enter_timestamp
= event
.xcrossing
.time
;
2915 else if (f
== x_focus_frame
)
2916 x_new_focus_frame (0);
2921 f
= x_window_to_frame (event
.xfocus
.window
);
2922 if (event
.xfocus
.detail
!= NotifyPointer
)
2923 x_focus_event_frame
= f
;
2925 x_new_focus_frame (f
);
2930 f
= x_window_to_frame (event
.xcrossing
.window
);
2932 if (event
.xcrossing
.focus
)
2934 if (! x_focus_event_frame
)
2935 x_new_focus_frame (0);
2937 x_new_focus_frame (f
);
2941 if (f
== x_focus_event_frame
)
2942 x_focus_event_frame
= 0;
2943 if (f
== x_focus_frame
)
2944 x_new_focus_frame (0);
2949 f
= x_window_to_frame (event
.xfocus
.window
);
2950 if (event
.xfocus
.detail
!= NotifyPointer
2951 && f
== x_focus_event_frame
)
2952 x_focus_event_frame
= 0;
2953 if (f
&& f
== x_focus_frame
)
2954 x_new_focus_frame (0);
2957 #else /* ! defined (HAVE_X11) */
2960 if ((event
.detail
& 0xFF) == 1)
2961 break; /* Coming from our own subwindow */
2962 if (event
.subwindow
!= 0)
2963 break; /* Entering our own subwindow. */
2966 f
= x_window_to_frame (event
.window
);
2969 x_new_focus_frame (f
);
2974 if ((event
.detail
& 0xFF) == 1)
2975 break; /* Entering our own subwindow */
2976 if (event
.subwindow
!= 0)
2977 break; /* Leaving our own subwindow. */
2980 if (x_focus_frame
== 0
2981 && x_input_frame
!= 0
2982 && x_input_frame
== x_window_to_frame (event
.window
)
2983 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
2988 frame_unhighlight (f
);
2991 #endif /* ! defined (HAVE_X11) */
2996 f
= x_window_to_frame (event
.xmotion
.window
);
2998 note_mouse_movement (f
, &event
.xmotion
);
3001 struct scroll_bar
*bar
=
3002 x_window_to_scroll_bar (event
.xmotion
.window
);
3005 x_scroll_bar_note_movement (bar
, &event
);
3010 case ConfigureNotify
:
3011 f
= x_window_to_frame (event
.xconfigure
.window
);
3014 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3015 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3017 /* Even if the number of character rows and columns has
3018 not changed, the font size may have changed, so we need
3019 to check the pixel dimensions as well. */
3020 if (columns
!= f
->width
3021 || rows
!= f
->height
3022 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3023 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3025 change_frame_size (f
, rows
, columns
, 0, 1);
3026 SET_FRAME_GARBAGED (f
);
3029 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3030 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3031 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3032 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3039 /* If we decide we want to generate an event to be seen
3040 by the rest of Emacs, we put it here. */
3041 struct input_event emacs_event
;
3042 emacs_event
.kind
= no_event
;
3044 f
= x_window_to_frame (event
.xbutton
.window
);
3047 if (!x_focus_frame
|| (f
== x_focus_frame
))
3048 construct_mouse_click (&emacs_event
,
3053 struct scroll_bar
*bar
=
3054 x_window_to_scroll_bar (event
.xbutton
.window
);
3057 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3060 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3062 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3070 #else /* ! defined (HAVE_X11) */
3072 case ButtonReleased
:
3073 f
= x_window_to_frame (event
.window
);
3076 if (event
.window
== f
->display
.x
->icon_desc
)
3078 x_make_frame_visible (f
);
3080 if (warp_mouse_on_deiconify
)
3081 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3084 if (event
.window
== FRAME_X_WINDOW (f
))
3090 enqueue_event (&event
, &x_mouse_queue
);
3093 bufp
->kind
= ascii_keystroke
;
3094 bufp
->code
= (char) 'X' & 037; /* C-x */
3095 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3096 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3099 bufp
->kind
= ascii_keystroke
;
3100 bufp
->code
= (char) 0; /* C-@ */
3101 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3102 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3109 #endif /* ! defined (HAVE_X11) */
3113 case CirculateNotify
:
3115 case CirculateRequest
:
3118 #endif /* ! defined (HAVE_X11) */
3121 /* Someone has changed the keyboard mapping - update the
3123 switch (event
.xmapping
.request
)
3125 case MappingModifier
:
3126 x_find_modifier_meanings ();
3127 /* This is meant to fall through. */
3128 case MappingKeyboard
:
3129 XRefreshKeyboardMapping (&event
.xmapping
);
3140 if (expected
&& ! event_found
)
3142 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3143 there is an EOF condition; in other words, that X has died.
3144 Act as if there had been a hangup. */
3146 int fd
= ConnectionNumber (x_current_display
);
3149 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3151 && !XStuffPending ())
3152 kill (getpid (), SIGHUP
);
3154 #endif /* ! defined (HAVE_SELECT) */
3158 if (updating_frame
== 0)
3159 x_do_pending_expose ();
3167 /* Read and process only Expose events
3168 until we get an ExposeCopy event; then return.
3169 This is used in insert/delete line.
3170 We assume input is already blocked. */
3176 XKeyPressedEvent event
;
3180 /* while there are more events*/
3181 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3185 if (event
.subwindow
!= 0)
3186 break; /* duplicate event */
3187 f
= x_window_to_frame (event
.window
);
3188 if (event
.window
== f
->display
.x
->icon_desc
)
3193 if (event
.window
== FRAME_X_WINDOW (f
))
3195 expose_all_windows
= 1;
3196 f
->display
.x
->needs_exposure
= 1;
3202 if (event
.subwindow
!= 0)
3203 break; /* duplicate event */
3204 f
= x_window_to_frame (event
.window
);
3205 if (event
.window
== f
->display
.x
->icon_desc
)
3210 /* If window already needs full redraw, ignore this rectangle. */
3211 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3213 /* Put the event on the queue of rectangles to redraw. */
3214 if (enqueue_event (&event
, &x_expose_queue
))
3215 /* If it is full, we can't record the rectangle,
3216 so redraw this entire window. */
3218 /* Say must check all windows' needs_exposure flags. */
3219 expose_all_windows
= 1;
3220 f
->display
.x
->needs_exposure
= 1;
3229 #endif /* HAVE_X11 */
3232 /* Drawing the cursor. */
3235 /* Draw a hollow box cursor. Don't change the inside of the box. */
3241 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3242 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3243 int width
= FONT_WIDTH (f
->display
.x
->font
);
3244 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3247 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3248 f
->display
.x
->cursor_gc
,
3249 left
, top
, width
- 1, height
- 1);
3250 #else /* ! defined (HAVE_X11) */
3251 XPixSet (FRAME_X_WINDOW (f
),
3252 left
, top
, width
, 1,
3253 f
->display
.x
->cursor_pixel
);
3255 XPixSet (FRAME_X_WINDOW (f
),
3256 left
, top
, 1, height
,
3257 f
->display
.x
->cursor_pixel
);
3259 XPixSet (FRAME_X_WINDOW (f
),
3260 left
+width
-1, top
, 1, height
,
3261 f
->display
.x
->cursor_pixel
);
3263 XPixSet (FRAME_X_WINDOW (f
),
3264 left
, top
+height
-1, width
, 1,
3265 f
->display
.x
->cursor_pixel
);
3266 #endif /* ! defined (HAVE_X11) */
3269 /* Clear the cursor of frame F to background color,
3270 and mark the cursor as not shown.
3271 This is used when the text where the cursor is
3272 is about to be rewritten. */
3280 if (! FRAME_VISIBLE_P (f
)
3281 || f
->phys_cursor_x
< 0)
3285 x_display_cursor (f
, 0);
3286 #else /* ! defined (HAVE_X11) */
3287 XPixSet (FRAME_X_WINDOW (f
),
3288 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3289 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3290 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3291 f
->display
.x
->background_pixel
);
3292 #endif /* ! defined (HAVE_X11) */
3293 f
->phys_cursor_x
= -1;
3296 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3297 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3301 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3308 CHAR_TO_PIXEL_COL (f
, column
),
3309 CHAR_TO_PIXEL_ROW (f
, row
),
3310 &glyph
, 1, highlight
, f
->display
.x
->font
);
3314 x_display_bar_cursor (f
, on
)
3318 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3320 /* This is pointless on invisible frames, and dangerous on garbaged
3321 frames; in the latter case, the frame may be in the midst of
3322 changing its size, and curs_x and curs_y may be off the frame. */
3323 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3326 if (! on
&& f
->phys_cursor_x
< 0)
3329 /* If we're not updating, then we want to use the current frame's
3330 cursor position, not our local idea of where the cursor ought to be. */
3331 if (f
!= updating_frame
)
3333 curs_x
= FRAME_CURSOR_X (f
);
3334 curs_y
= FRAME_CURSOR_Y (f
);
3337 /* If there is anything wrong with the current cursor state, remove it. */
3338 if (f
->phys_cursor_x
>= 0
3340 || f
->phys_cursor_x
!= curs_x
3341 || f
->phys_cursor_y
!= curs_y
3342 || f
->display
.x
->current_cursor
!= bar_cursor
))
3344 /* Erase the cursor by redrawing the character underneath it. */
3345 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3346 f
->phys_cursor_glyph
,
3347 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3348 f
->phys_cursor_x
= -1;
3351 /* If we now need a cursor in the new place or in the new form, do it so. */
3353 && (f
->phys_cursor_x
< 0
3354 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3356 f
->phys_cursor_glyph
3357 = ((current_glyphs
->enable
[curs_y
]
3358 && curs_x
< current_glyphs
->used
[curs_y
])
3359 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3361 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3362 f
->display
.x
->cursor_gc
,
3363 CHAR_TO_PIXEL_COL (f
, curs_x
),
3364 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3365 1, FONT_HEIGHT (f
->display
.x
->font
));
3367 f
->phys_cursor_x
= curs_x
;
3368 f
->phys_cursor_y
= curs_y
;
3370 f
->display
.x
->current_cursor
= bar_cursor
;
3373 if (updating_frame
!= f
)
3378 /* Turn the displayed cursor of frame F on or off according to ON.
3379 If ON is nonzero, where to put the cursor is specified
3380 by F->cursor_x and F->cursor_y. */
3383 x_display_box_cursor (f
, on
)
3387 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3389 /* This is pointless on invisible frames, and dangerous on garbaged
3390 frames; in the latter case, the frame may be in the midst of
3391 changing its size, and curs_x and curs_y may be off the frame. */
3392 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3395 /* If cursor is off and we want it off, return quickly. */
3396 if (!on
&& f
->phys_cursor_x
< 0)
3399 /* If we're not updating, then we want to use the current frame's
3400 cursor position, not our local idea of where the cursor ought to be. */
3401 if (f
!= updating_frame
)
3403 curs_x
= FRAME_CURSOR_X (f
);
3404 curs_y
= FRAME_CURSOR_Y (f
);
3407 /* If cursor is currently being shown and we don't want it to be
3408 or it is in the wrong place,
3409 or we want a hollow box and it's not so, (pout!)
3411 if (f
->phys_cursor_x
>= 0
3413 || f
->phys_cursor_x
!= curs_x
3414 || f
->phys_cursor_y
!= curs_y
3415 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3416 && (f
!= x_highlight_frame
))))
3418 /* Erase the cursor by redrawing the character underneath it. */
3419 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3420 f
->phys_cursor_glyph
,
3421 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3422 f
->phys_cursor_x
= -1;
3425 /* If we want to show a cursor,
3426 or we want a box cursor and it's not so,
3427 write it in the right place. */
3429 && (f
->phys_cursor_x
< 0
3430 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3431 && f
== x_highlight_frame
)))
3433 f
->phys_cursor_glyph
3434 = ((current_glyphs
->enable
[curs_y
]
3435 && curs_x
< current_glyphs
->used
[curs_y
])
3436 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3438 if (f
!= x_highlight_frame
)
3441 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3445 x_draw_single_glyph (f
, curs_y
, curs_x
,
3446 f
->phys_cursor_glyph
, 2);
3447 f
->display
.x
->current_cursor
= filled_box_cursor
;
3450 f
->phys_cursor_x
= curs_x
;
3451 f
->phys_cursor_y
= curs_y
;
3454 if (updating_frame
!= f
)
3458 x_display_cursor (f
, on
)
3462 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3463 x_display_box_cursor (f
, on
);
3464 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3465 x_display_bar_cursor (f
, on
);
3467 /* Those are the only two we have implemented! */
3473 /* Refresh bitmap kitchen sink icon for frame F
3474 when we get an expose event for it. */
3480 /* Normally, the window manager handles this function. */
3481 #else /* ! defined (HAVE_X11) */
3484 if (f
->display
.x
->icon_bitmap_flag
)
3485 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3486 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3487 icon_bitmap
, GXcopy
, AllPlanes
);
3490 extern struct frame
*selected_frame
;
3491 struct Lisp_String
*str
;
3492 unsigned char *string
;
3495 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3497 if (f
->display
.x
->icon_label
!= string
)
3499 f
->display
.x
->icon_label
= string
;
3500 XChangeWindow (f
->display
.x
->icon_desc
,
3501 XQueryWidth (string
, icon_font_info
->id
) + 10,
3502 icon_font_info
->height
+ 10);
3505 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3506 str
->size
, icon_font_info
->id
,
3507 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3510 #endif /* ! defined (HAVE_X11) */
3513 /* Make the x-window of frame F use the gnu icon bitmap. */
3522 if (FRAME_X_WINDOW (f
) == 0)
3527 XFreePixmap (x_current_display
, icon_bitmap
);
3530 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3531 gnu_bits
, gnu_width
, gnu_height
);
3532 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3533 f
->display
.x
->icon_bitmap_flag
= 1;
3534 #else /* ! defined (HAVE_X11) */
3535 if (f
->display
.x
->icon_desc
)
3537 XClearIconWindow (FRAME_X_WINDOW (f
));
3538 XDestroyWindow (f
->display
.x
->icon_desc
);
3541 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3542 0, 0, sink_width
, sink_height
,
3543 2, WhitePixmap
, (Pixmap
) NULL
);
3545 if (icon_window
== 0)
3548 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3549 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3551 f
->display
.x
->icon_desc
= icon_window
;
3552 f
->display
.x
->icon_bitmap_flag
= 1;
3554 if (icon_bitmap
== 0)
3556 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3557 #endif /* ! defined (HAVE_X11) */
3563 /* Make the x-window of frame F use a rectangle with text. */
3566 x_text_icon (f
, icon_name
)
3574 char *X_DefaultValue
;
3578 #define WhitePixel 1
3579 #endif /* WhitePixel */
3582 #define BlackPixel 0
3583 #endif /* BlackPixel */
3584 #endif /* HAVE_X11 */
3586 if (FRAME_X_WINDOW (f
) == 0)
3591 f
->display
.x
->icon_label
= icon_name
;
3593 if (! f
->display
.x
->icon_label
)
3594 f
->display
.x
->icon_label
= " *emacs* ";
3596 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3597 (char *) f
->display
.x
->icon_label
);
3599 f
->display
.x
->icon_bitmap_flag
= 0;
3600 x_wm_set_icon_pixmap (f
, 0);
3601 #else /* ! defined (HAVE_X11) */
3602 if (icon_font_info
== 0)
3604 = XGetFont (XGetDefault (XDISPLAY
3605 (char *) XSTRING (Vinvocation_name
)->data
,
3608 if (f
->display
.x
->icon_desc
)
3610 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3611 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3615 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3617 if (! f
->display
.x
->icon_label
)
3618 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3620 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3621 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3622 f
->display
.x
->left_pos
,
3623 f
->display
.x
->top_pos
,
3624 width
+ 10, icon_font_info
->height
+ 10,
3625 2, BlackPixmap
, WhitePixmap
);
3627 if (icon_window
== 0)
3630 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3631 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3633 f
->display
.x
->icon_desc
= icon_window
;
3634 f
->display
.x
->icon_bitmap_flag
= 0;
3635 f
->display
.x
->icon_label
= 0;
3636 #endif /* ! defined (HAVE_X11) */
3641 /* Handling X errors. */
3643 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3644 X server's connection, or an error reported via the X protocol. */
3647 x_connection_closed ()
3652 shut_down_emacs (0);
3657 /* An X error handler which prints an error message and then kills
3658 Emacs. This is what's normally installed as Xlib's handler for
3661 x_error_quitter (display
, error
)
3667 /* Note that there is no real way portable across R3/R4 to get the
3668 original error handler. */
3670 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3671 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3672 buf
, error
->request_code
);
3674 /* While we're testing Emacs 19, we'll just dump core whenever we
3675 get an X error, so we can figure out why it happened. */
3678 x_connection_closed ();
3681 /* A handler for X IO errors which prints an error message and then
3682 kills Emacs. This is what is always installed as Xlib's handler
3685 x_io_error_quitter (display
)
3688 fprintf (stderr
, "Connection to X server %s lost.\n",
3689 XDisplayName (DisplayString (display
)));
3691 /* While we're testing Emacs 19, we'll just dump core whenever we
3692 get an X error, so we can figure out why it happened. */
3695 x_connection_closed ();
3698 /* A buffer for storing X error messages. */
3699 static char (*x_caught_error_message
)[200];
3701 /* An X error handler which stores the error message in
3702 x_caught_error_message. This is what's installed when
3703 x_catch_errors is in effect. */
3705 x_error_catcher (display
, error
)
3709 XGetErrorText (display
, error
->error_code
,
3710 *x_caught_error_message
, sizeof (*x_caught_error_message
));
3714 /* Begin trapping X errors.
3716 After calling this function, X protocol errors no longer cause
3717 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3719 Calling x_check_errors signals an Emacs error if an X error has
3720 occurred since the last call to x_catch_errors or x_check_errors.
3722 Calling x_uncatch_errors resumes the normal error handling. */
3724 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3729 /* Make sure any errors from previous requests have been dealt with. */
3730 XSync (x_current_display
, False
);
3732 /* Set up the error buffer. */
3733 x_caught_error_message
=
3734 (char (*)[]) xmalloc (sizeof (*x_caught_error_message
));
3735 (*x_caught_error_message
)[0] = '\0';
3737 /* Install our little error handler. */
3738 XHandleError (x_error_catcher
);
3741 /* If any X protocol errors have arrived since the last call to
3742 x_catch_errors or x_check_errors, signal an Emacs error using
3743 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3745 x_check_errors (format
)
3748 /* Make sure to catch any errors incurred so far. */
3749 XSync (x_current_display
, False
);
3751 if ((*x_caught_error_message
)[0])
3755 sprintf (buf
, format
, *x_caught_error_message
);
3756 xfree (x_caught_error_message
);
3758 x_uncatch_errors ();
3766 xfree (x_caught_error_message
);
3767 XHandleError (x_error_quitter
);
3771 static unsigned int x_wire_count
;
3774 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3779 /* Changing the font of the frame. */
3781 /* Set the font of the x-window specified by frame F
3782 to the font named NEWNAME. This is safe to use
3783 even before F has an actual x-window. */
3787 /* A table of all the fonts we have already loaded. */
3788 static XFontStruct
**x_font_table
;
3790 /* The current capacity of x_font_table. */
3791 static int x_font_table_size
;
3793 /* The number of fonts actually stored in x_font_table.
3794 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3795 0 <= n_fonts <= x_font_table_size. */
3798 x_new_font (f
, fontname
)
3800 register char *fontname
;
3804 int n_matching_fonts
;
3805 XFontStruct
*font_info
;
3808 /* Get a list of all the fonts that match this name. Once we
3809 have a list of matching fonts, we compare them against the fonts
3810 we already have by comparing font ids. */
3811 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3812 1024, &n_matching_fonts
,
3814 /* If the server couldn't find any fonts whose named matched fontname,
3815 return an error code. */
3816 if (n_matching_fonts
== 0)
3819 /* See if we've already loaded a matching font. */
3824 for (i
= 0; i
< n_fonts
; i
++)
3825 for (j
= 0; j
< n_matching_fonts
; j
++)
3826 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3834 /* If we have, just return it from the table. */
3836 f
->display
.x
->font
= x_font_table
[already_loaded
];
3838 /* Otherwise, load the font and add it to the table. */
3843 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
3847 /* Do we need to create the table? */
3848 if (x_font_table_size
== 0)
3850 x_font_table_size
= 16;
3852 = (XFontStruct
**) xmalloc (x_font_table_size
3853 * sizeof (x_font_table
[0]));
3855 /* Do we need to grow the table? */
3856 else if (n_fonts
>= x_font_table_size
)
3858 x_font_table_size
*= 2;
3860 = (XFontStruct
**) xrealloc (x_font_table
,
3862 * sizeof (x_font_table
[0])));
3865 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
3868 /* Free the information from XListFontsWithInfo. The data
3869 we actually retain comes from XLoadQueryFont. */
3870 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
3872 /* Now make the frame display the given font. */
3873 if (FRAME_X_WINDOW (f
) != 0)
3875 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
3876 f
->display
.x
->font
->fid
);
3877 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
3878 f
->display
.x
->font
->fid
);
3879 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
3880 f
->display
.x
->font
->fid
);
3882 x_set_window_size (f
, f
->width
, f
->height
);
3887 #else /* ! defined (HAVE_X11) */
3888 x_new_font (f
, newname
)
3890 register char *newname
;
3895 temp
= XGetFont (newname
);
3896 if (temp
== (FONT_TYPE
*) 0)
3899 if (f
->display
.x
->font
)
3900 XLoseFont (f
->display
.x
->font
);
3902 f
->display
.x
->font
= temp
;
3904 if (FRAME_X_WINDOW (f
) != 0)
3905 x_set_window_size (f
, f
->width
, f
->height
);
3909 #endif /* ! defined (HAVE_X11) */
3911 /* X Window sizes and positions. */
3913 x_calc_absolute_position (f
)
3917 if (f
->display
.x
->left_pos
< 0)
3918 f
->display
.x
->left_pos
3919 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
3921 if (f
->display
.x
->top_pos
< 0)
3922 f
->display
.x
->top_pos
3923 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
3924 #else /* ! defined (HAVE_X11) */
3925 WINDOWINFO_TYPE parentinfo
;
3927 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
3929 if (f
->display
.x
->left_pos
< 0)
3930 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
3931 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
3933 if (f
->display
.x
->top_pos
< 0)
3934 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
3935 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
3936 #endif /* ! defined (HAVE_X11) */
3939 x_set_offset (f
, xoff
, yoff
)
3941 register int xoff
, yoff
;
3943 f
->display
.x
->top_pos
= yoff
;
3944 f
->display
.x
->left_pos
= xoff
;
3945 x_calc_absolute_position (f
);
3948 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
3949 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
3951 x_wm_set_size_hint (f
, 0);
3952 #endif /* ! defined (HAVE_X11) */
3956 /* Call this to change the size of frame F's x-window. */
3958 x_set_window_size (f
, cols
, rows
)
3962 int pixelwidth
, pixelheight
;
3967 check_frame_size (f
, &rows
, &cols
);
3968 f
->display
.x
->vertical_scroll_bar_extra
=
3969 (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3970 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
3972 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3973 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3976 x_wm_set_size_hint (f
, 0);
3977 #endif /* ! defined (HAVE_X11) */
3978 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
3980 /* Now, strictly speaking, we can't be sure that this is accurate,
3981 but the window manager will get around to dealing with the size
3982 change request eventually, and we'll hear how it went when the
3983 ConfigureNotify event gets here.
3985 We could just not bother storing any of this information here,
3986 and let the ConfigureNotify event set everything up, but that
3987 might be kind of confusing to the lisp code, since size changes
3988 wouldn't be reported in the frame parameters until some random
3989 point in the future when the ConfigureNotify event arrives. */
3990 change_frame_size (f
, rows
, cols
, 0, 0);
3991 PIXEL_WIDTH (f
) = pixelwidth
;
3992 PIXEL_HEIGHT (f
) = pixelheight
;
3994 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3995 receive in the ConfigureNotify event; if we get what we asked
3996 for, then the event won't cause the screen to become garbaged, so
3997 we have to make sure to do it here. */
3998 SET_FRAME_GARBAGED (f
);
4005 x_set_resize_hint (f
)
4008 XSetResizeHint (FRAME_X_WINDOW (f
),
4009 2 * f
->display
.x
->internal_border_width
,
4010 2 * f
->display
.x
->internal_border_width
,
4011 FONT_WIDTH (f
->display
.x
->font
),
4012 FONT_HEIGHT (f
->display
.x
->font
));
4014 #endif /* HAVE_X11 */
4016 /* Mouse warping, focus shifting, raising and lowering. */
4018 x_set_mouse_position (f
, x
, y
)
4026 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4027 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4029 if (pix_x
< 0) pix_x
= 0;
4030 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4032 if (pix_y
< 0) pix_y
= 0;
4033 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4037 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4042 x_focus_on_frame (f
)
4047 /* I don't think that the ICCCM allows programs to do things like this
4048 without the interaction of the window manager. Whatever you end up
4049 doing with this code, do it to x_unfocus_frame too. */
4050 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4051 RevertToPointerRoot
, CurrentTime
);
4059 /* Look at the remarks in x_focus_on_frame. */
4060 if (x_focus_frame
== f
)
4061 XSetInputFocus (x_current_display
, PointerRoot
,
4062 RevertToPointerRoot
, CurrentTime
);
4066 #endif /* ! defined (HAVE_X11) */
4068 /* Raise frame F. */
4073 if (f
->async_visible
)
4076 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4082 /* Lower frame F. */
4087 if (f
->async_visible
)
4090 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4097 XTframe_raise_lower (f
, raise
)
4108 /* Change from withdrawn state to mapped state. */
4110 x_make_frame_visible (f
)
4117 if (! FRAME_VISIBLE_P (f
))
4120 if (! EQ (Vx_no_window_manager
, Qt
))
4121 x_wm_set_window_state (f
, NormalState
);
4123 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4124 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4125 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4126 #else /* ! defined (HAVE_X11) */
4127 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4128 if (f
->display
.x
->icon_desc
!= 0)
4129 XUnmapWindow (f
->display
.x
->icon_desc
);
4131 /* Handled by the MapNotify event for X11 */
4132 f
->async_visible
= 1;
4133 f
->async_iconified
= 0;
4135 /* NOTE: this may cause problems for the first frame. */
4137 #endif /* ! defined (HAVE_X11) */
4145 /* Change from mapped state to withdrawn state. */
4147 x_make_frame_invisible (f
)
4152 if (! f
->async_visible
)
4159 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4160 DefaultScreen (x_current_display
)))
4162 UNBLOCK_INPUT_RESIGNAL
;
4163 error ("can't notify window manager of window withdrawl");
4166 #else /* ! defined (HAVE_X11R4) */
4169 /* Tell the window manager what we're going to do. */
4170 if (! EQ (Vx_no_window_manager
, Qt
))
4174 unmap
.xunmap
.type
= UnmapNotify
;
4175 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4176 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4177 unmap
.xunmap
.from_configure
= False
;
4178 if (! XSendEvent (x_current_display
,
4179 DefaultRootWindow (x_current_display
),
4181 SubstructureRedirectMask
|SubstructureNotifyMask
,
4184 UNBLOCK_INPUT_RESIGNAL
;
4185 error ("can't notify window manager of withdrawal");
4189 /* Unmap the window ourselves. Cheeky! */
4190 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4192 #else /* ! defined (HAVE_X11) */
4194 XUnmapWindow (FRAME_X_WINDOW (f
));
4195 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4196 if (f
->display
.x
->icon_desc
!= 0)
4197 XUnmapWindow (f
->display
.x
->icon_desc
);
4199 #endif /* ! defined (HAVE_X11) */
4200 #endif /* ! defined (HAVE_X11R4) */
4206 /* Change window state from mapped to iconified. */
4213 if (f
->async_iconified
)
4219 /* Since we don't know which revision of X we're running, we'll use both
4220 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4222 /* X11R4: send a ClientMessage to the window manager using the
4223 WM_CHANGE_STATE type. */
4227 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4228 message
.xclient
.type
= ClientMessage
;
4229 message
.xclient
.message_type
= Xatom_wm_change_state
;
4230 message
.xclient
.format
= 32;
4231 message
.xclient
.data
.l
[0] = IconicState
;
4233 if (! XSendEvent (x_current_display
,
4234 DefaultRootWindow (x_current_display
),
4236 SubstructureRedirectMask
| SubstructureNotifyMask
,
4239 UNBLOCK_INPUT_RESIGNAL
;
4240 error ("Can't notify window manager of iconification.");
4244 /* X11R3: set the initial_state field of the window manager hints to
4246 x_wm_set_window_state (f
, IconicState
);
4248 f
->async_iconified
= 1;
4249 #else /* ! defined (HAVE_X11) */
4250 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4252 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4253 if (f
->display
.x
->icon_desc
!= 0)
4255 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4258 #endif /* ! defined (HAVE_X11) */
4264 /* Destroy the X window of frame F. */
4266 x_destroy_window (f
)
4271 if (f
->display
.x
->icon_desc
!= 0)
4272 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4273 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4276 xfree (f
->display
.x
);
4278 if (f
== x_focus_frame
)
4280 if (f
== x_highlight_frame
)
4281 x_highlight_frame
= 0;
4286 /* Manage event queues for X10. */
4290 /* Manage event queues.
4292 This code is only used by the X10 support.
4294 We cannot leave events in the X queue and get them when we are ready
4295 because X does not provide a subroutine to get only a certain kind
4296 of event but not block if there are no queued events of that kind.
4298 Therefore, we must examine events as they come in and copy events
4299 of certain kinds into our private queues.
4301 All ExposeRegion events are put in x_expose_queue.
4302 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4305 /* Write the event *P_XREP into the event queue *QUEUE.
4306 If the queue is full, do nothing, but return nonzero. */
4309 enqueue_event (p_xrep
, queue
)
4310 register XEvent
*p_xrep
;
4311 register struct event_queue
*queue
;
4313 int newindex
= queue
->windex
+ 1;
4314 if (newindex
== EVENT_BUFFER_SIZE
)
4316 if (newindex
== queue
->rindex
)
4318 queue
->xrep
[queue
->windex
] = *p_xrep
;
4319 queue
->windex
= newindex
;
4323 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4324 If *QUEUE is empty, do nothing and return 0. */
4327 dequeue_event (p_xrep
, queue
)
4328 register XEvent
*p_xrep
;
4329 register struct event_queue
*queue
;
4331 if (queue
->windex
== queue
->rindex
)
4333 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4334 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4339 /* Return the number of events buffered in *QUEUE. */
4342 queue_event_count (queue
)
4343 register struct event_queue
*queue
;
4345 int tem
= queue
->windex
- queue
->rindex
;
4348 return EVENT_BUFFER_SIZE
+ tem
;
4351 /* Return nonzero if mouse input is pending. */
4354 mouse_event_pending_p ()
4356 return queue_event_count (&x_mouse_queue
);
4358 #endif /* HAVE_X11 */
4360 /* Setting window manager hints. */
4364 x_wm_set_size_hint (f
, prompting
)
4368 XSizeHints size_hints
;
4369 Window window
= FRAME_X_WINDOW (f
);
4371 size_hints
.flags
= PResizeInc
| PMinSize
| PMaxSize
;
4373 flexlines
= f
->height
;
4375 size_hints
.x
= f
->display
.x
->left_pos
;
4376 size_hints
.y
= f
->display
.x
->top_pos
;
4377 size_hints
.height
= PIXEL_HEIGHT (f
);
4378 size_hints
.width
= PIXEL_WIDTH (f
);
4379 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4380 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4381 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4382 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4385 int base_width
, base_height
;
4387 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4388 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4391 int min_rows
= 0, min_cols
= 0;
4392 check_frame_size (f
, &min_rows
, &min_cols
);
4394 /* The window manager uses the base width hints to calculate the
4395 current number of rows and columns in the frame while
4396 resizing; min_width and min_height aren't useful for this
4397 purpose, since they might not give the dimensions for a
4398 zero-row, zero-column frame.
4400 We use the base_width and base_height members if we have
4401 them; otherwise, we set the min_width and min_height members
4402 to the size for a zero x zero frame. */
4405 size_hints
.flags
|= PBaseSize
;
4406 size_hints
.base_width
= base_width
;
4407 size_hints
.base_height
= base_height
;
4408 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4409 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4411 size_hints
.min_width
= base_width
;
4412 size_hints
.min_height
= base_height
;
4419 size_hints
.flags
|= prompting
;
4422 XSizeHints hints
; /* Sometimes I hate X Windows... */
4424 XGetNormalHints (x_current_display
, window
, &hints
);
4425 if (hints
.flags
& PSize
)
4426 size_hints
.flags
|= PSize
;
4427 if (hints
.flags
& PPosition
)
4428 size_hints
.flags
|= PPosition
;
4429 if (hints
.flags
& USPosition
)
4430 size_hints
.flags
|= USPosition
;
4431 if (hints
.flags
& USSize
)
4432 size_hints
.flags
|= USSize
;
4436 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4438 XSetNormalHints (x_current_display
, window
, &size_hints
);
4442 /* Used for IconicState or NormalState */
4443 x_wm_set_window_state (f
, state
)
4447 Window window
= FRAME_X_WINDOW (f
);
4449 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4450 f
->display
.x
->wm_hints
.initial_state
= state
;
4452 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4455 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4459 Window window
= FRAME_X_WINDOW (f
);
4463 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4464 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4467 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4469 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4472 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4476 Window window
= FRAME_X_WINDOW (f
);
4478 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4479 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4480 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4482 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4486 /* Initialization. */
4489 x_term_init (display_name
)
4495 extern int old_fcntl_owner
;
4496 #endif /* ! defined (F_SETOWN) */
4498 x_focus_frame
= x_highlight_frame
= 0;
4500 x_current_display
= XOpenDisplay (display_name
);
4501 if (x_current_display
== 0)
4502 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4507 int hostname_size
= 256;
4509 hostname
= (char *) xmalloc (hostname_size
);
4512 XSetAfterFunction (x_current_display
, x_trace_wire
);
4515 /* Try to get the host name; if the buffer is too short, try
4516 again. Apparently, the only indication gethostname gives of
4517 whether the buffer was large enough is the presence or absence
4518 of a '\0' in the string. Eech. */
4521 gethostname (hostname
, hostname_size
- 1);
4522 hostname
[hostname_size
- 1] = '\0';
4524 /* Was the buffer large enough for gethostname to store the '\0'? */
4525 if (strlen (hostname
) < hostname_size
- 1)
4528 hostname_size
<<= 1;
4529 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4531 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4534 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
4537 /* Figure out which modifier bits mean what. */
4538 x_find_modifier_meanings ();
4540 /* Get the scroll bar cursor. */
4541 x_vertical_scroll_bar_cursor
4542 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4545 /* Watch for PropertyNotify events on the root window; we use them
4546 to figure out when to invalidate our cache of the cut buffers. */
4547 x_watch_cut_buffer_cache ();
4550 if (ConnectionNumber (x_current_display
) != 0)
4552 dup2 (ConnectionNumber (x_current_display
), 0);
4554 #ifndef SYSV_STREAMS
4555 /* Streams somehow keeps track of which descriptor number
4556 is being used to talk to X. So it is not safe to substitute
4557 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4558 close (ConnectionNumber (x_current_display
));
4559 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4560 * check the def of the macro;
4561 * it is a genuine lvalue */
4562 #endif /* SYSV_STREAMS */
4565 #endif /* ! defined (HAVE_X11) */
4568 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4569 #ifdef F_SETOWN_SOCK_NEG
4570 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4571 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4572 fcntl (0, F_SETOWN
, getpid ());
4573 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4574 #endif /* ! defined (F_SETOWN) */
4578 #endif /* ! defined (SIGIO) */
4580 /* Must use interrupt input because we cannot otherwise
4581 arrange for C-g to be noticed immediately.
4582 We cannot connect it to SIGINT. */
4583 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4585 expose_all_windows
= 0;
4587 clear_frame_hook
= XTclear_frame
;
4588 clear_end_of_line_hook
= XTclear_end_of_line
;
4589 ins_del_lines_hook
= XTins_del_lines
;
4590 change_line_highlight_hook
= XTchange_line_highlight
;
4591 insert_glyphs_hook
= XTinsert_glyphs
;
4592 write_glyphs_hook
= XTwrite_glyphs
;
4593 delete_glyphs_hook
= XTdelete_glyphs
;
4594 ring_bell_hook
= XTring_bell
;
4595 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4596 set_terminal_modes_hook
= XTset_terminal_modes
;
4597 update_begin_hook
= XTupdate_begin
;
4598 update_end_hook
= XTupdate_end
;
4599 set_terminal_window_hook
= XTset_terminal_window
;
4600 read_socket_hook
= XTread_socket
;
4601 cursor_to_hook
= XTcursor_to
;
4602 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4603 mouse_position_hook
= XTmouse_position
;
4604 frame_rehighlight_hook
= XTframe_rehighlight
;
4605 frame_raise_lower_hook
= XTframe_raise_lower
;
4606 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
4607 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
4608 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
4609 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
4611 scroll_region_ok
= 1; /* we'll scroll partial frames */
4612 char_ins_del_ok
= 0; /* just as fast to write the line */
4613 line_ins_del_ok
= 1; /* we'll just blt 'em */
4614 fast_clear_end_of_line
= 1; /* X does this well */
4615 memory_below_frame
= 0; /* we don't remember what scrolls
4619 /* Note that there is no real way portable across R3/R4 to get the
4620 original error handler. */
4621 XHandleError (x_error_quitter
);
4622 XHandleIOError (x_io_error_quitter
);
4624 /* Disable Window Change signals; they are handled by X events. */
4626 signal (SIGWINCH
, SIG_DFL
);
4627 #endif /* ! defined (SIGWINCH) */
4629 signal (SIGPIPE
, x_connection_closed
);
4635 staticpro (&last_mouse_scroll_bar
);
4637 #endif /* ! defined (HAVE_X11) */
4638 #endif /* ! defined (HAVE_X_WINDOWS) */