1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
34 /* On 4.3 these lose if they come after xterm.h. */
38 /* This may include sys/types.h, and that somehow loses
39 if this is not done before the other system files. */
41 #include <X11/cursorfont.h>
44 /* Load sys/types.h if not already loaded.
45 In some systems loading it twice is suicidal. */
47 #include <sys/types.h>
52 #include <sys/ioctl.h>
54 #else /* ! defined (BSD) */
55 #include <sys/termio.h>
57 #endif /* ! defined (BSD) */
59 /* Allow m- file to inhibit use of FIONREAD. */
60 #ifdef BROKEN_FIONREAD
62 #endif /* ! defined (BROKEN_FIONREAD) */
64 /* We are unable to use interrupts if FIONREAD is not available,
65 so flush SIGIO so we won't try. */
69 #endif /* ! defined (SIGIO) */
79 #include <sys/param.h>
81 #include "dispextern.h"
82 #include "termhooks.h"
96 #define XMapWindow XMapRaised /* Raise them when mapping. */
97 #else /* ! defined (HAVE_X11) */
98 #include <X/Xkeyboard.h>
99 /*#include <X/Xproto.h> */
100 #endif /* ! defined (HAVE_X11) */
102 /* For sending Meta-characters. Do we need this? */
105 #define min(a,b) ((a)<(b) ? (a) : (b))
106 #define max(a,b) ((a)>(b) ? (a) : (b))
108 /* Nonzero means we must reprint all windows
109 because 1) we received an ExposeWindow event
110 or 2) we received too many ExposeRegion events to record.
112 This is never needed under X11. */
113 static int expose_all_windows
;
115 /* Nonzero means we must reprint all icon windows. */
117 static int expose_all_icons
;
120 /* ExposeRegion events, when received, are copied into this queue
121 for later processing. */
123 static struct event_queue x_expose_queue
;
125 /* ButtonPressed and ButtonReleased events, when received,
126 are copied into this queue for later processing. */
128 struct event_queue x_mouse_queue
;
129 #endif /* HAVE_X11 */
131 /* Nonzero after BLOCK_INPUT; prevents input events from being
132 processed until later. */
136 #if defined (SIGIO) && defined (FIONREAD)
137 int BLOCK_INPUT_mask
;
138 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
140 /* Nonzero if input events came in while x_input_blocked was nonzero.
141 UNBLOCK_INPUT checks for this. */
145 /* The id of a bitmap used for icon windows.
146 One such map is shared by all Emacs icon windows.
147 This is zero if we have not yet had a need to create the bitmap. */
149 static Bitmap icon_bitmap
;
151 /* Font used for text icons. */
153 static FONT_TYPE
*icon_font_info
;
155 /* Stuff for dealing with the main icon title. */
157 extern Lisp_Object Vcommand_line_args
;
158 char *hostname
, *x_id_name
;
159 Lisp_Object invocation_name
;
161 /* This is the X connection that we are using. */
163 Display
*x_current_display
;
165 /* The cursor to use for vertical scrollbars on x_current_display. */
166 static Cursor x_vertical_scrollbar_cursor
;
168 /* Frame being updated by update_frame. */
169 /* This is set by XTupdate_begin and looked at by all the
170 XT functions. It is zero while not inside an update.
171 In that case, the XT functions assume that `selected_frame'
172 is the frame to apply to. */
174 static struct frame
*updating_frame
;
176 /* The frame (if any) which has the X window that has keyboard focus.
177 Zero if none. This is examined by Ffocus_frame in frame.c. Note
178 that a mere EnterNotify event can set this; if you need to know the
179 last frame specified in a FocusIn or FocusOut event, use
180 x_focus_event_frame. */
181 struct frame
*x_focus_frame
;
183 /* The last frame mentioned in a FocusIn or FocusOut event. This is
184 separate from x_focus_frame, because whether or not LeaveNotify
185 events cause us to lose focus depends on whether or not we have
186 received a FocusIn event for it. */
187 struct frame
*x_focus_event_frame
;
189 /* The frame which currently has the visual highlight, and should get
190 keyboard input (other sorts of input have the frame encoded in the
191 event). It points to the X focus frame's selected window's
192 frame. It differs from x_focus_frame when we're using a global
194 static struct frame
*x_highlight_frame
;
196 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
197 mouse is moved to inside of frame when frame is de-iconified. */
199 static int warp_mouse_on_deiconify
;
201 /* During an update, maximum vpos for ins/del line operations to affect. */
203 static int flexlines
;
205 /* During an update, nonzero if chars output now should be highlighted. */
207 static int highlight
;
209 /* Nominal cursor position -- where to draw output.
210 During an update, these are different from the cursor-box position. */
216 /* `t' if a mouse button is depressed. */
218 extern Lisp_Object Vmouse_depressed
;
220 /* Tells if a window manager is present or not. */
222 extern Lisp_Object Vx_no_window_manager
;
224 /* Timestamp that we requested selection data was made. */
225 extern Time requestor_time
;
227 /* ID of the window requesting selection data. */
228 extern Window requestor_window
;
230 /* Nonzero enables some debugging for the X interface code. */
233 #else /* ! defined (HAVE_X11) */
235 /* Bit patterns for the mouse cursor. */
237 short MouseCursor
[] = {
238 0x0000, 0x0008, 0x0018, 0x0038,
239 0x0078, 0x00f8, 0x01f8, 0x03f8,
240 0x07f8, 0x00f8, 0x00d8, 0x0188,
241 0x0180, 0x0300, 0x0300, 0x0000};
243 short MouseMask
[] = {
244 0x000c, 0x001c, 0x003c, 0x007c,
245 0x00fc, 0x01fc, 0x03fc, 0x07fc,
246 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
247 0x03cc, 0x0780, 0x0780, 0x0300};
249 static short grey_bits
[] = {
250 0x0005, 0x000a, 0x0005, 0x000a};
252 static Pixmap GreyPixmap
= 0;
253 #endif /* ! defined (HAVE_X11) */
255 /* From time to time we get info on an Emacs window, here. */
257 static WINDOWINFO_TYPE windowinfo
;
261 extern Display
*XOpenDisplay ();
262 extern Window
XCreateWindow ();
264 extern Cursor
XCreateCursor ();
265 extern FONT_TYPE
*XOpenFont ();
267 static void flashback ();
270 static void dumpqueue ();
271 #endif /* HAVE_X11 */
274 static int XTcursor_to ();
275 static int XTclear_end_of_line ();
278 /* Starting and ending updates.
280 These hooks are called by update_frame at the beginning and end
281 of a frame update. We record in `updating_frame' the identity
282 of the frame being updated, so that the XT... functions do not
283 need to take a frame as argument. Most of the XT... functions
284 should never be called except during an update, the only exceptions
285 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
287 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
299 flexlines
= f
->height
;
305 #endif /* HAVE_X11 */
310 static void x_do_pending_expose ();
319 if (updating_frame
== 0
320 || updating_frame
!= f
)
326 x_do_pending_expose ();
327 #endif /* HAVE_X11 */
329 x_display_cursor (f
, 1);
336 /* External interface to control of standout mode.
337 Call this when about to modify line at position VPOS
338 and not change whether it is highlighted. */
340 XTreassert_line_highlight (new, vpos
)
346 /* Call this when about to modify line at position VPOS
347 and change whether it is highlighted. */
350 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
351 int new_highlight
, vpos
, first_unused_hpos
;
353 highlight
= new_highlight
;
354 XTcursor_to (vpos
, 0);
355 XTclear_end_of_line (updating_frame
->width
);
358 /* This is used when starting Emacs and when restarting after suspend.
359 When starting Emacs, no X window is mapped. And nothing must be done
360 to Emacs's own window if it is suspended (though that rarely happens). */
363 XTset_terminal_modes ()
367 /* This is called when exiting or suspending Emacs.
368 Exiting will make the X-windows go away, and suspending
369 requires no action. */
372 XTreset_terminal_modes ()
374 /* XTclear_frame (); */
377 /* Set the nominal cursor position of the frame.
378 This is where display update commands will take effect.
379 This does not affect the place where the cursor-box is displayed. */
382 XTcursor_to (row
, col
)
383 register int row
, col
;
391 if (updating_frame
== 0)
394 x_display_cursor (selected_frame
, 1);
400 /* Display a sequence of N glyphs found at GP.
401 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
402 HL is 1 if this text is highlighted, 2 if the cursor is on it.
404 FONT is the default font to use (for glyphs whose font-code is 0). */
407 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
410 register GLYPH
*gp
; /* Points to first GLYPH. */
411 register int n
; /* Number of glyphs to display. */
416 Window window
= FRAME_X_WINDOW (f
);
417 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
418 : (hl
? f
->display
.x
->reverse_gc
419 : f
->display
.x
->normal_gc
));
421 if (sizeof (GLYPH
) == sizeof (XChar2b
))
422 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
423 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
424 else if (sizeof (GLYPH
) == sizeof (unsigned char))
425 XDrawImageString (x_current_display
, window
, drawing_gc
,
426 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
428 /* What size of glyph ARE you using? And does X have a function to
435 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
438 register GLYPH
*gp
; /* Points to first GLYPH. */
439 register int n
; /* Number of glyphs to display. */
443 char buf
[f
->width
]; /* Holds characters to be displayed. */
444 register char *cp
; /* Steps through buf[]. */
445 register int tlen
= GLYPH_TABLE_LENGTH
;
446 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
447 Window window
= FRAME_X_WINDOW (f
);
448 int cursor_pixel
= f
->display
.x
->cursor_pixel
;
449 int fg_pixel
= f
->display
.x
->foreground_pixel
;
450 int bg_pixel
= f
->display
.x
->background_pixel
;
451 int intborder
= f
->display
.x
->internal_border_width
;
455 /* Get the face-code of the next GLYPH. */
459 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
460 g
= GLYPH_ALIAS (tbase
, g
);
464 /* Find the run of consecutive glyphs with the same face-code.
465 Extract their character codes into BUF. */
470 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
471 g
= GLYPH_ALIAS (tbase
, g
);
480 /* LEN gets the length of the run. */
483 /* Now output this run of chars, with the font and pixel values
484 determined by the face code CF. */
488 GC GC_cursor
= f
->display
.x
->cursor_gc
;
489 GC GC_reverse
= f
->display
.x
->reverse_gc
;
490 GC GC_normal
= f
->display
.x
->normal_gc
;
492 XDrawImageString (x_current_display
, window
,
495 : (hl
? GC_reverse
: GC_normal
)),
496 left
, top
+ FONT_BASE (font
), buf
, len
);
497 #else /* ! defined (HAVE_X11) */
498 XText (window
, left
, top
,
503 ? (cursor_pixel
== fg_pixel
? bg_pixel
: fg_pixel
)
504 : hl
? bg_pixel
: fg_pixel
),
505 (hl
== 2 ? cursor_pixel
506 : hl
? fg_pixel
: bg_pixel
));
507 #endif /* ! defined (HAVE_X11) */
512 if (FACE_IS_FONT (cf
))
513 XDrawImageString (x_current_display
, FRAME_X_WINDOW (f
),
515 left
, top
+ FONT_BASE (FACE_FONT (cf
)),
517 else if (FACE_IS_IMAGE (cf
))
518 XCopyPlane (x_current_display
, FACE_IMAGE (cf
),
520 f
->display
.x
->normal_gc
,
522 FACE_IMAGE_WIDTH (cf
),
523 FACE_IMAGE_HEIGHT (cf
), left
, top
);
526 #else /* ! defined (HAVE_X11) */
527 register struct face
*fp
= x_face_table
[cf
];
529 XText (window
, left
, top
,
534 ? (cursor_pixel
== fp
->fg
? fp
->bg
: fp
->fg
)
535 : hl
? fp
->bg
: fp
->fg
),
536 (hl
== 2 ? cursor_pixel
537 : hl
? fp
->fg
: fp
->bg
));
538 #endif /* ! defined (HAVE_X11) */
540 left
+= len
* FONT_WIDTH (font
);
545 /* Output some text at the nominal frame cursor position.
546 Advance the cursor over the text.
547 Output LEN glyphs at START.
549 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
550 controls the pixel values used for foreground and background. */
553 XTwrite_glyphs (start
, len
)
554 register GLYPH
*start
;
557 register int temp_length
;
567 /* If not within an update,
568 output at the frame's visible cursor. */
569 curs_x
= f
->cursor_x
;
570 curs_y
= f
->cursor_y
;
574 CHAR_TO_PIXEL_COL (f
, curs_x
),
575 CHAR_TO_PIXEL_ROW (f
, curs_y
),
576 start
, len
, highlight
, f
->display
.x
->font
);
578 /* If we drew on top of the cursor, note that it is turned off. */
579 if (curs_y
== f
->phys_cursor_y
580 && curs_x
<= f
->phys_cursor_x
581 && curs_x
+ len
> f
->phys_cursor_x
)
582 f
->phys_cursor_x
= -1;
584 if (updating_frame
== 0)
587 x_display_cursor (f
, 1);
596 /* Clear to the end of the line.
597 Erase the current text line from the nominal cursor position (inclusive)
598 to column FIRST_UNUSED (exclusive). The idea is that everything
599 from FIRST_UNUSED onward is already erased. */
602 XTclear_end_of_line (first_unused
)
603 register int first_unused
;
605 struct frame
*f
= updating_frame
;
611 if (curs_y
< 0 || curs_y
>= f
->height
)
613 if (first_unused
<= 0)
616 if (first_unused
>= f
->width
)
617 first_unused
= f
->width
;
621 /* Notice if the cursor will be cleared by this operation. */
622 if (curs_y
== f
->phys_cursor_y
623 && curs_x
<= f
->phys_cursor_x
624 && f
->phys_cursor_x
< first_unused
)
625 f
->phys_cursor_x
= -1;
628 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
629 CHAR_TO_PIXEL_COL (f
, curs_x
),
630 CHAR_TO_PIXEL_ROW (f
, curs_y
),
631 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
632 FONT_HEIGHT (f
->display
.x
->font
), False
);
634 #else /* ! defined (HAVE_X11) */
635 XPixSet (FRAME_X_WINDOW (f
),
636 CHAR_TO_PIXEL_COL (f
, curs_x
),
637 CHAR_TO_PIXEL_ROW (f
, curs_y
),
638 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
639 FONT_HEIGHT (f
->display
.x
->font
),
640 f
->display
.x
->background_pixel
);
641 #endif /* ! defined (HAVE_X11) */
650 struct frame
*f
= updating_frame
;
655 f
->phys_cursor_x
= -1; /* Cursor not visible. */
656 curs_x
= 0; /* Nominal cursor position is top left. */
660 XClear (FRAME_X_WINDOW (f
));
663 #endif /* HAVE_X11 */
668 /* Paint horzontal bars down the frame for a visible bell.
669 Note that this may be way too slow on some machines. */
674 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
678 if (updating_frame
!= 0)
684 for (i
= f
->height
* FONT_HEIGHT (f
->display
.x
->font
) - 10;
686 i
-= 100) /* Should be NO LOWER than 75 for speed reasons. */
687 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
688 f
->display
.x
->cursor_gc
,
689 0, i
, f
->width
* FONT_WIDTH (f
->display
.x
->font
)
690 + 2 * f
->display
.x
->internal_border_width
, 25);
693 x
= (f
->width
* FONT_WIDTH (f
->display
.x
->font
)) / 4;
694 y
= (f
->height
* FONT_HEIGHT (f
->display
.x
->font
)) / 4;
695 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
696 f
->display
.x
->cursor_gc
,
698 dumpglyphs (f
, (x
+ f
->display
.x
->internal_border_width
),
699 (y
+ f
->display
.x
->internal_border_width
),
700 &active_frame
->glyphs
[(f
->height
/ 4) + 1][(f
->width
/ 4)],
701 1, 0, f
->display
.x
->font
);
703 #else /* ! defined (HAVE_X11) */
704 for (i
= f
->height
* FONT_HEIGHT (f
->display
.x
->font
) - 10;
707 XPixFill (FRAME_X_WINDOW (f
), 0, i
,
708 f
->width
* FONT_WIDTH (f
->display
.x
->font
)
709 + 2 * f
->display
.x
->internal_border_width
, 10,
710 WHITE_PIX_DEFAULT
, ClipModeClipped
, GXinvert
, AllPlanes
);
711 #endif /* ! defined (HAVE_X11) */
717 /* Flip background and forground colors of the frame. */
724 unsigned long pix_temp
;
726 x_display_cursor (f
, 0);
727 XClearWindow (x_current_display
, FRAME_X_WINDOW (f
));
728 temp
= f
->display
.x
->normal_gc
;
729 f
->display
.x
->normal_gc
= f
->display
.x
->reverse_gc
;
730 f
->display
.x
->reverse_gc
= temp
;
731 pix_temp
= f
->display
.x
->foreground_pixel
;
732 f
->display
.x
->foreground_pixel
= f
->display
.x
->background_pixel
;
733 f
->display
.x
->background_pixel
= pix_temp
;
735 XSetWindowBackground (x_current_display
, FRAME_X_WINDOW (f
),
736 f
->display
.x
->background_pixel
);
737 if (f
->display
.x
->background_pixel
== f
->display
.x
->cursor_pixel
)
739 f
->display
.x
->cursor_pixel
= f
->display
.x
->foreground_pixel
;
740 XSetBackground (x_current_display
, f
->display
.x
->cursor_gc
,
741 f
->display
.x
->cursor_pixel
);
742 XSetForeground (x_current_display
, f
->display
.x
->cursor_gc
,
743 f
->display
.x
->background_pixel
);
746 #endif /* ! defined (HAVE_X11) */
749 /* Make audible bell. */
752 #define XRINGBELL XBell(x_current_display, 0)
753 #else /* ! defined (HAVE_X11) */
754 #define XRINGBELL XFeep(0);
755 #endif /* ! defined (HAVE_X11) */
761 XTflash (selected_frame
);
764 x_invert_frame (selected_frame
);
765 x_invert_frame (selected_frame
);
776 /* Insert and delete character.
777 These are not supposed to be used because we are supposed to turn
778 off the feature of using them. */
781 XTinsert_glyphs (start
, len
)
782 register char *start
;
795 /* Specify how many text lines, from the top of the window,
796 should be affected by insert-lines and delete-lines operations.
797 This, and those operations, are used only within an update
798 that is bounded by calls to XTupdate_begin and XTupdate_end. */
801 XTset_terminal_window (n
)
804 if (updating_frame
== 0)
807 if ((n
<= 0) || (n
> updating_frame
->height
))
808 flexlines
= updating_frame
->height
;
813 /* Perform an insert-lines operation.
814 Insert N lines at a vertical position curs_y. */
820 register int topregion
, bottomregion
;
821 register int length
, newtop
, mask
;
822 register struct frame
*f
= updating_frame
;
823 int intborder
= f
->display
.x
->internal_border_width
;
825 if (curs_y
>= flexlines
)
829 bottomregion
= flexlines
- (n
+ 1);
830 newtop
= topregion
+ n
;
831 length
= (bottomregion
- topregion
) + 1;
835 #endif /* HAVE_X11 */
837 if ((length
> 0) && (newtop
<= flexlines
))
840 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
841 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
842 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
843 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
844 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
845 CHAR_TO_PIXEL_ROW (f
, newtop
));
846 #else /* ! defined (HAVE_X11) */
847 XMoveArea (FRAME_X_WINDOW (f
),
848 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
849 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
850 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
851 length
* FONT_HEIGHT (f
->display
.x
->font
));
852 /* Now we must process any ExposeRegion events that occur
853 if the area being copied from is obscured.
854 We can't let it wait because further i/d operations
855 may want to copy this area to another area. */
857 #endif /* ! defined (HAVE_X11) */
860 newtop
= min (newtop
, (flexlines
- 1));
861 length
= newtop
- topregion
;
865 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
866 CHAR_TO_PIXEL_ROW (f
, topregion
),
867 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
868 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
869 #else /* ! defined (HAVE_X11) */
870 XPixSet (FRAME_X_WINDOW (f
),
872 CHAR_TO_PIXEL_ROW (f
, topregion
),
873 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
874 n
* FONT_HEIGHT (f
->display
.x
->font
),
875 f
->display
.x
->background_pixel
);
876 #endif /* ! defined (HAVE_X11) */
880 /* Perform a delete-lines operation, deleting N lines
881 at a vertical position curs_y. */
888 register struct frame
*f
= updating_frame
;
889 int intborder
= f
->display
.x
->internal_border_width
;
891 if (curs_y
>= flexlines
)
896 #endif /* HAVE_X11 */
898 if ((curs_y
+ n
) >= flexlines
)
900 if (flexlines
>= (curs_y
+ 1))
903 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
904 CHAR_TO_PIXEL_ROW (f
, curs_y
),
905 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
906 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
907 #else /* ! defined (HAVE_X11) */
908 XPixSet (FRAME_X_WINDOW (f
),
909 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
910 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
911 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
912 f
->display
.x
->background_pixel
);
913 #endif /* ! defined (HAVE_X11) */
919 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
920 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
922 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
923 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
924 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
925 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
926 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
928 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
929 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
930 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
931 #else /* ! defined (HAVE_X11) */
932 XMoveArea (FRAME_X_WINDOW (f
),
934 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
935 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
936 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
937 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
938 /* Now we must process any ExposeRegion events that occur
939 if the area being copied from is obscured.
940 We can't let it wait because further i/d operations
941 may want to copy this area to another area. */
943 XPixSet (FRAME_X_WINDOW (f
), intborder
,
944 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
945 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
946 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
947 #endif /* ! defined (HAVE_X11) */
951 /* Perform an insert-lines or delete-lines operation,
952 inserting N lines or deleting -N lines at vertical position VPOS. */
954 XTins_del_lines (vpos
, n
)
957 if (updating_frame
== 0)
960 /* Hide the cursor. */
961 x_display_cursor (updating_frame
, 0);
963 XTcursor_to (vpos
, 0);
974 /* Support routines for exposure events. */
975 static void clear_cursor ();
977 /* Output into a rectangle of an X-window (for frame F)
978 the characters in f->phys_lines that overlap that rectangle.
979 TOP and LEFT are the position of the upper left corner of the rectangle.
980 ROWS and COLS are the size of the rectangle. */
983 dumprectangle (f
, left
, top
, cols
, rows
)
985 register int left
, top
, cols
, rows
;
987 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
988 int cursor_cleared
= 0;
992 if (FRAME_GARBAGED_P (f
))
995 /* Express rectangle as four edges, instead of position-and-size. */
999 #ifndef HAVE_X11 /* Window manger does this for X11. */
1001 int intborder
= f
->display
.x
->internal_border_width
;
1003 /* If the rectangle includes any of the internal border area,
1004 redisplay the border emphasis. */
1005 if (top
< intborder
|| left
< intborder
1006 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1007 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1010 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1012 /* Convert rectangle edges in pixels to edges in chars.
1013 Round down for left and top, up for right and bottom. */
1014 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1015 left
= PIXEL_TO_CHAR_COL (f
, left
);
1016 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1017 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1018 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1019 right
= PIXEL_TO_CHAR_COL (f
, right
);
1021 /* Clip the rectangle to what can be visible. */
1026 if (right
> f
->width
)
1028 if (bottom
> f
->height
)
1031 /* Get size in chars of the rectangle. */
1032 cols
= right
- left
;
1033 rows
= bottom
- top
;
1035 /* If rectangle has zero area, return. */
1036 if (rows
<= 0) return;
1037 if (cols
<= 0) return;
1039 /* Turn off the cursor if it is in the rectangle.
1040 We will turn it back on afterward. */
1041 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1042 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1048 /* Display the text in the rectangle, one text line at a time. */
1050 for (y
= top
; y
< bottom
; y
++)
1052 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1054 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1058 CHAR_TO_PIXEL_COL (f
, left
),
1059 CHAR_TO_PIXEL_ROW (f
, y
),
1060 line
, min (cols
, active_frame
->used
[y
] - left
),
1061 active_frame
->highlight
[y
], f
->display
.x
->font
);
1064 /* Turn the cursor on if we turned it off. */
1067 x_display_cursor (f
, 1);
1071 /* Process all queued ExposeRegion events. */
1077 XExposeRegionEvent r
;
1079 while (dequeue_event (&r
, &x_expose_queue
))
1081 struct frame
*f
= x_window_to_frame (r
.window
);
1082 if (f
->display
.x
->icon_desc
== r
.window
)
1085 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1089 #endif /* HAVE_X11 */
1091 /* Process all expose events that are pending, for X10.
1092 Redraws the cursor if necessary on any frame that
1093 is not in the process of being updated with update_frame. */
1097 x_do_pending_expose ()
1101 Lisp_Object tail
, frame
;
1103 if (expose_all_windows
)
1105 expose_all_windows
= 0;
1106 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1108 register int temp_width
, temp_height
;
1111 frame
= XCONS (tail
)->car
;
1112 if (XTYPE (frame
) != Lisp_Frame
)
1115 if (! FRAME_X_P (f
))
1117 if (!f
->async_visible
)
1119 if (!f
->display
.x
->needs_exposure
)
1122 intborder
= f
->display
.x
->internal_border_width
;
1125 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1126 temp_width
= ((windowinfo
.width
- 2 * intborder
1127 - f
->display
.x
->v_scrollbar_width
)
1128 / FONT_WIDTH (f
->display
.x
->font
));
1129 temp_height
= ((windowinfo
.height
- 2 * intborder
1130 - f
->display
.x
->h_scrollbar_height
)
1131 / FONT_HEIGHT (f
->display
.x
->font
));
1132 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1134 change_frame_size (f
, max (1, temp_height
),
1135 max (1, temp_width
), 0, 1);
1136 x_resize_scrollbars (f
);
1138 f
->display
.x
->left_pos
= windowinfo
.x
;
1139 f
->display
.x
->top_pos
= windowinfo
.y
;
1140 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1144 f
->display
.x
->needs_exposure
= 0;
1145 if (updating_frame
!= f
)
1146 x_display_cursor (f
, 1);
1151 /* Handle any individual-rectangle expose events queued
1152 for various windows. */
1155 #else /* ! defined (HAVE_X11) */
1157 #endif /* ! defined (HAVE_X11) */
1163 frame_highlight (frame
)
1164 struct frame
*frame
;
1166 if (! EQ (Vx_no_window_manager
, Qnil
))
1167 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1168 frame
->display
.x
->border_pixel
);
1169 x_display_cursor (frame
, 1);
1173 frame_unhighlight (frame
)
1174 struct frame
*frame
;
1176 if (! EQ (Vx_no_window_manager
, Qnil
))
1177 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1178 frame
->display
.x
->border_tile
);
1179 x_display_cursor (frame
, 1);
1181 #else /* ! defined (HAVE_X11) */
1182 /* Dump the border-emphasis of frame F.
1183 If F is selected, this is a lining of the same color as the border,
1184 just within the border, occupying a portion of the internal border.
1185 If F is not selected, it is background in the same place.
1186 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1188 ALWAYS = 1 is used when a frame becomes selected or deselected.
1189 In that case, we also turn the cursor off and on again
1190 so it will appear in the proper shape (solid if selected; else hollow.) */
1193 dumpborder (f
, always
)
1197 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1198 int width
= PIXEL_WIDTH (f
);
1199 int height
= PIXEL_HEIGHT (f
);
1202 if (f
!= selected_frame
)
1207 pixel
= f
->display
.x
->background_pixel
;
1211 pixel
= f
->display
.x
->border_pixel
;
1214 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1215 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1216 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1218 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1222 x_display_cursor (f
, 1);
1224 #endif /* ! defined (HAVE_X11) */
1226 static void XTframe_rehighlight ();
1228 /* The focus has changed. Update the frames as necessary to reflect
1229 the new situation. Note that we can't change the selected frame
1230 here, because the lisp code we are interrupting might become confused.
1231 Each event gets marked with the frame in which it occured, so the
1232 lisp code can tell when the switch took place by examining the events. */
1235 x_new_focus_frame (frame
)
1236 struct frame
*frame
;
1238 struct frame
*old_focus
= x_focus_frame
;
1239 int events_enqueued
= 0;
1241 if (frame
!= x_focus_frame
)
1243 /* Set this before calling other routines, so that they see
1244 the correct value of x_focus_frame. */
1245 x_focus_frame
= frame
;
1247 if (old_focus
&& old_focus
->auto_lower
)
1248 x_lower_frame (old_focus
);
1251 selected_frame
= frame
;
1252 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1253 Lisp_Frame
, selected_frame
);
1254 Fselect_window (selected_frame
->selected_window
);
1255 choose_minibuf_frame ();
1258 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1259 x_raise_frame (x_focus_frame
);
1262 XTframe_rehighlight ();
1266 /* The focus has changed, or we have redirected a frame's focus to
1267 another frame (this happens when a frame uses a surrogate
1268 minibuffer frame). Shift the highlight as appropriate. */
1270 XTframe_rehighlight ()
1272 struct frame
*old_highlight
= x_highlight_frame
;
1277 ((XTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1278 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1280 if (! FRAME_LIVE_P (x_highlight_frame
))
1282 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1283 x_highlight_frame
= x_focus_frame
;
1287 x_highlight_frame
= 0;
1289 if (x_highlight_frame
!= old_highlight
)
1292 frame_unhighlight (old_highlight
);
1293 if (x_highlight_frame
)
1294 frame_highlight (x_highlight_frame
);
1298 /* Mouse clicks and mouse movement. Rah. */
1301 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1302 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1303 that the glyph at X, Y occupies, if BOUNDS != 0. */
1305 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1307 register unsigned int pix_x
, pix_y
;
1308 register int *x
, *y
;
1311 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1312 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1316 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1317 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1318 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1319 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1322 if (pix_x
< 0) pix_x
= 0;
1323 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1325 if (pix_y
< 0) pix_y
= 0;
1326 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1332 /* Any buttons grabbed. */
1333 unsigned int x_mouse_grabbed
;
1335 /* Which modifier keys are on which modifier bits?
1337 With each keystroke, X returns eight bits indicating which modifier
1338 keys were held down when the key was pressed. The interpretation
1339 of the top five modifier bits depends on what keys are attached
1340 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1343 x_meta_mod_mask is a mask containing the bits used for the meta key.
1344 It may have more than one bit set, if more than one modifier bit
1345 has meta keys on it. Basically, if EVENT is a KeyPress event,
1346 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1348 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1349 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1350 only be affected by the lock modifier bit if XK_Shift_Lock is in
1351 use; XK_Caps_Lock should only affect alphabetic keys. With this
1352 arrangement, the lock modifier should shift the character if
1353 (EVENT.state & x_shift_lock_mask) != 0. */
1354 static int x_meta_mod_mask
, x_shift_lock_mask
;
1356 /* Initialize mode_switch_bit and modifier_meaning. */
1358 x_find_modifier_meanings ()
1360 int min_code
, max_code
;
1363 XModifierKeymap
*mods
;
1364 int alt_mod_mask
= 0;
1366 x_meta_mod_mask
= 0;
1367 x_shift_lock_mask
= 0;
1369 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1370 syms
= XGetKeyboardMapping (x_current_display
,
1371 min_code
, max_code
- min_code
+ 1,
1373 mods
= XGetModifierMapping (x_current_display
);
1375 /* Scan the modifier table to see which modifier bits the Meta and
1376 Alt keysyms are on. */
1378 int row
, col
; /* The row and column in the modifier table. */
1380 for (row
= 3; row
< 8; row
++)
1381 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1384 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1386 /* Are any of this keycode's keysyms a meta key? */
1390 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1392 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1398 x_meta_mod_mask
|= (1 << row
);
1403 alt_mod_mask
|= (1 << row
);
1407 /* Ignore this if it's not on the lock modifier. */
1408 if ((1 << row
) == LockMask
)
1409 x_shift_lock_mask
= LockMask
;
1417 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1418 if (! x_meta_mod_mask
)
1419 x_meta_mod_mask
= alt_mod_mask
;
1421 XFree ((char *) syms
);
1422 XFreeModifiermap (mods
);
1426 /* Convert a set of X modifier bits to the proper form for a
1427 struct input_event modifiers value. */
1430 x_convert_modifiers (state
)
1433 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1434 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1435 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0));
1438 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1440 If the event is a button press, then note that we have grabbed
1444 construct_mouse_click (result
, event
, f
)
1445 struct input_event
*result
;
1446 XButtonEvent
*event
;
1449 /* Make the event type no_event; we'll change that when we decide
1451 result
->kind
= mouse_click
;
1452 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1453 result
->timestamp
= event
->time
;
1454 result
->modifiers
= (x_convert_modifiers (event
->state
)
1455 | (event
->type
== ButtonRelease
1459 /* Notice if the mouse is still grabbed. */
1460 if (event
->type
== ButtonPress
)
1462 if (! x_mouse_grabbed
)
1463 Vmouse_depressed
= Qt
;
1464 x_mouse_grabbed
|= (1 << event
->button
);
1466 else if (event
->type
== ButtonRelease
)
1468 x_mouse_grabbed
&= ~(1 << event
->button
);
1469 if (!x_mouse_grabbed
)
1470 Vmouse_depressed
= Qnil
;
1476 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1477 XFASTINT (result
->x
) = column
;
1478 XFASTINT (result
->y
) = row
;
1479 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1484 /* Mouse movement. Rah.
1486 In order to avoid asking for motion events and then throwing most
1487 of them away or busy-polling the server for mouse positions, we ask
1488 the server for pointer motion hints. This means that we get only
1489 one event per group of mouse movements. "Groups" are delimited by
1490 other kinds of events (focus changes and button clicks, for
1491 example), or by XQueryPointer calls; when one of these happens, we
1492 get another MotionNotify event the next time the mouse moves. This
1493 is at least as efficient as getting motion events when mouse
1494 tracking is on, and I suspect only negligibly worse when tracking
1497 The silly O'Reilly & Associates Nutshell guides barely document
1498 pointer motion hints at all (I think you have to infer how they
1499 work from an example), and the description of XQueryPointer doesn't
1500 mention that calling it causes you to get another motion hint from
1501 the server, which is very important. */
1503 /* Where the mouse was last time we reported a mouse event. */
1504 static FRAME_PTR last_mouse_frame
;
1505 static XRectangle last_mouse_glyph
;
1507 /* The scrollbar in which the last X motion event occurred.
1509 If the last X motion event occured in a scrollbar, we set this
1510 so XTmouse_position can know whether to report a scrollbar motion or
1513 If the last X motion event didn't occur in a scrollbar, we set this
1514 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1515 static Lisp_Object last_mouse_scrollbar
;
1517 /* This is a hack. We would really prefer that XTmouse_position would
1518 return the time associated with the position it returns, but there
1519 doesn't seem to be any way to wrest the timestamp from the server
1520 along with the position query. So, we just keep track of the time
1521 of the last movement we received, and return that in hopes that
1522 it's somewhat accurate. */
1523 static Time last_mouse_movement_time
;
1525 /* Function to report a mouse movement to the mainstream Emacs code.
1526 The input handler calls this.
1528 We have received a mouse movement event, which is given in *event.
1529 If the mouse is over a different glyph than it was last time, tell
1530 the mainstream emacs code by setting mouse_moved. If not, ask for
1531 another motion event, so we can check again the next time it moves. */
1533 note_mouse_movement (frame
, event
)
1535 XMotionEvent
*event
;
1538 last_mouse_movement_time
= event
->time
;
1540 /* Has the mouse moved off the glyph it was on at the last sighting? */
1541 if (event
->x
< last_mouse_glyph
.x
1542 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1543 || event
->y
< last_mouse_glyph
.y
1544 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1547 last_mouse_scrollbar
= Qnil
;
1551 /* It's on the same glyph. Call XQueryPointer so we'll get an
1552 event the next time the mouse moves and we can see if it's
1553 *still* on the same glyph. */
1556 XQueryPointer (event
->display
, event
->window
,
1557 (Window
*) &dummy
, (Window
*) &dummy
,
1558 &dummy
, &dummy
, &dummy
, &dummy
,
1559 (unsigned int *) &dummy
);
1563 static struct scrollbar
*x_window_to_scrollbar ();
1564 static void x_scrollbar_report_motion ();
1566 /* Return the current position of the mouse.
1568 If the mouse movement started in a scrollbar, set *f, *bar_window,
1569 and *part to the frame, window, and scrollbar part that the mouse
1570 is over. Set *x and *y to the portion and whole of the mouse's
1571 position on the scrollbar.
1573 If the mouse movement started elsewhere, set *f to the frame the
1574 mouse is on, *bar_window to nil, and *x and *y to the character cell
1577 Set *time to the server timestamp for the time at which the mouse
1578 was at this position.
1580 This clears the mouse_moved flag, so we can wait for the next mouse
1581 movement. This also calls XQueryPointer, which will cause the
1582 server to give us another MotionNotify when the mouse moves
1586 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1588 Lisp_Object
*bar_window
;
1589 enum scrollbar_part
*part
;
1591 unsigned long *time
;
1595 if (! NILP (last_mouse_scrollbar
))
1596 x_scrollbar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1602 Window dummy_window
;
1606 last_mouse_scrollbar
= Qnil
;
1608 /* Figure out which root window we're on. */
1609 XQueryPointer (x_current_display
,
1610 DefaultRootWindow (x_current_display
),
1612 /* The root window which contains the pointer. */
1615 /* Trash which we can't trust if the pointer is on
1616 a different screen. */
1619 /* The position on that root window. */
1622 /* More trash we can't trust. */
1625 /* Modifier keys and pointer buttons, about which
1627 (unsigned int *) &dummy
);
1629 /* Now we have a position on the root; find the innermost window
1630 containing the pointer. */
1634 int parent_x
, parent_y
;
1639 XTranslateCoordinates (x_current_display
,
1641 /* From-window, to-window. */
1644 /* From-position, to-position. */
1645 root_x
, root_y
, &win_x
, &win_y
,
1658 /* Now we know that:
1659 win is the innermost window containing the pointer
1660 (XTC says it has no child containing the pointer),
1661 win_x and win_y are the pointer's position in it
1662 (XTC did this the last time through), and
1663 parent_x and parent_y are the pointer's position in win's parent.
1664 (They are what win_x and win_y were when win was child.
1665 If win is the root window, it has no parent, and
1666 parent_{x,y} are invalid, but that's okay, because we'll
1667 never use them in that case.) */
1669 /* Is win one of our frames? */
1670 *f
= x_window_to_frame (win
);
1672 /* If not, is it one of our scrollbars? */
1675 struct scrollbar
*bar
= x_window_to_scrollbar (win
);
1679 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1687 pixel_to_glyph_coords (*f
, win_x
, win_y
, &win_x
, &win_y
,
1692 XSET (*x
, Lisp_Int
, win_x
);
1693 XSET (*y
, Lisp_Int
, win_y
);
1694 *time
= last_mouse_movement_time
;
1702 #else /* ! defined (HAVE_X11) */
1703 #define XEvent XKeyPressedEvent
1704 #endif /* ! defined (HAVE_X11) */
1706 /* Scrollbar support. */
1708 /* Given an X window ID, find the struct scrollbar which manages it. */
1709 static struct scrollbar
*
1710 x_window_to_scrollbar (window_id
)
1713 Lisp_Object tail
, frame
;
1715 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1717 Lisp_Object frame
= XCONS (tail
)->car
;
1718 Lisp_Object bar
, condemned
;
1720 /* All elements of Vframe_list should be frames. */
1721 if (XTYPE (frame
) != Lisp_Frame
)
1724 /* Scan this frame's scrollbar list for a scrollbar with the
1726 condemned
= FRAME_CONDEMNED_SCROLLBARS (XFRAME (frame
));
1727 for (bar
= FRAME_SCROLLBARS (XFRAME (frame
));
1728 /* This trick allows us to search both the ordinary and
1729 condemned scrollbar lists with one loop. */
1730 ! NILP (bar
) || (bar
= condemned
, condemned
= Qnil
, ! NILP (bar
));
1731 bar
= XSCROLLBAR(bar
)->next
)
1732 if (SCROLLBAR_X_WINDOW (XSCROLLBAR (bar
)) == window_id
)
1733 return XSCROLLBAR (bar
);
1739 /* Open a new X window to serve as a scrollbar, and return the
1740 scrollbar vector for it. */
1741 static struct scrollbar
*
1742 x_scrollbar_create (window
, top
, left
, width
, height
)
1743 struct window
*window
;
1744 int top
, left
, width
, height
;
1746 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1747 struct scrollbar
*bar
=
1748 XSCROLLBAR (Fmake_vector (make_number (SCROLLBAR_VEC_SIZE
), Qnil
));
1753 XSetWindowAttributes a
;
1756 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1757 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1758 | ButtonMotionMask
| PointerMotionHintMask
1760 a
.cursor
= x_vertical_scrollbar_cursor
;
1761 a
.win_gravity
= EastGravity
;
1763 mask
= (CWBackPixel
| CWEventMask
| CWCursor
| CWWinGravity
);
1765 SET_SCROLLBAR_X_WINDOW
1767 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1769 /* Position and size of scrollbar. */
1770 left
, top
, width
, height
,
1772 /* Border width, depth, class, and visual. */
1773 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1779 XSET (bar
->window
, Lisp_Window
, window
);
1780 XSET (bar
->top
, Lisp_Int
, top
);
1781 XSET (bar
->left
, Lisp_Int
, left
);
1782 XSET (bar
->width
, Lisp_Int
, width
);
1783 XSET (bar
->height
, Lisp_Int
, height
);
1784 XSET (bar
->start
, Lisp_Int
, 0);
1785 XSET (bar
->end
, Lisp_Int
, 0);
1786 bar
->dragging
= Qnil
;
1788 /* Add bar to its frame's list of scroll bars. */
1789 bar
->next
= FRAME_SCROLLBARS (frame
);
1791 XSET (FRAME_SCROLLBARS (frame
), Lisp_Vector
, bar
);
1792 if (! NILP (bar
->next
))
1793 XSET (XSCROLLBAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1795 XMapWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
));
1802 /* Draw BAR's handle in the proper position.
1803 If the handle is already drawn from START to END, don't bother
1804 redrawing it, unless REBUILD is non-zero; in that case, always
1805 redraw it. (REBUILD is handy for drawing the handle after expose
1808 Normally, we want to constrain the start and end of the handle to
1809 fit inside its rectangle, but if the user is dragging the scrollbar
1810 handle, we want to let them drag it down all the way, so that the
1811 bar's top is as far down as it goes; otherwise, there's no way to
1812 move to the very end of the buffer. */
1814 x_scrollbar_set_handle (bar
, start
, end
, rebuild
)
1815 struct scrollbar
*bar
;
1819 int dragging
= ! NILP (bar
->dragging
);
1820 Window w
= SCROLLBAR_X_WINDOW (bar
);
1821 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1823 /* If the display is already accurate, do nothing. */
1825 && start
== XINT (bar
->start
)
1826 && end
== XINT (bar
->end
))
1832 int inside_width
= VERTICAL_SCROLLBAR_INSIDE_WIDTH (XINT (bar
->width
));
1833 int inside_height
= VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
1834 int top_range
= VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
1836 /* Make sure the values are reasonable, and try to preserve
1837 the distance between start and end. */
1839 int length
= end
- start
;
1843 else if (start
> top_range
)
1845 end
= start
+ length
;
1849 else if (end
> top_range
&& ! dragging
)
1853 /* Store the adjusted setting in the scrollbar. */
1854 XSET (bar
->start
, Lisp_Int
, start
);
1855 XSET (bar
->end
, Lisp_Int
, end
);
1857 /* Clip the end position, just for display. */
1858 if (end
> top_range
)
1861 /* Draw bottom positions VERTICAL_SCROLLBAR_MIN_HANDLE pixels
1862 below top positions, to make sure the handle is always at least
1863 that many pixels tall. */
1864 end
+= VERTICAL_SCROLLBAR_MIN_HANDLE
;
1866 /* Draw the empty space above the handle. Note that we can't clear
1867 zero-height areas; that means "clear to end of window." */
1869 XClearArea (x_current_display
, w
,
1871 /* x, y, width, height, and exposures. */
1872 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1873 VERTICAL_SCROLLBAR_TOP_BORDER
,
1874 inside_width
, start
,
1877 /* Draw the handle itself. */
1878 XFillRectangle (x_current_display
, w
, gc
,
1880 /* x, y, width, height */
1881 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1882 VERTICAL_SCROLLBAR_TOP_BORDER
+ start
,
1883 inside_width
, end
- start
);
1886 /* Draw the empty space below the handle. Note that we can't
1887 clear zero-height areas; that means "clear to end of window." */
1888 if (end
< inside_height
)
1889 XClearArea (x_current_display
, w
,
1891 /* x, y, width, height, and exposures. */
1892 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1893 VERTICAL_SCROLLBAR_TOP_BORDER
+ end
,
1894 inside_width
, inside_height
- end
,
1902 /* Move a scrollbar around on the screen, to accomodate changing
1903 window configurations. */
1905 x_scrollbar_move (bar
, top
, left
, width
, height
)
1906 struct scrollbar
*bar
;
1907 int top
, left
, width
, height
;
1913 unsigned int mask
= 0;
1920 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
1921 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
1922 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
1923 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
1926 XConfigureWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
),
1930 XSET (bar
->left
, Lisp_Int
, left
);
1931 XSET (bar
->top
, Lisp_Int
, top
);
1932 XSET (bar
->width
, Lisp_Int
, width
);
1933 XSET (bar
->height
, Lisp_Int
, height
);
1938 /* Destroy the X window for BAR, and set its Emacs window's scrollbar
1941 x_scrollbar_remove (bar
)
1942 struct scrollbar
*bar
;
1944 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1948 /* Destroy the window. */
1949 XDestroyWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
));
1951 /* Disassociate this scrollbar from its window. */
1952 XWINDOW (bar
->window
)->vertical_scrollbar
= Qnil
;
1957 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1958 that we are displaying PORTION characters out of a total of WHOLE
1959 characters, starting at POSITION. If WINDOW has no scrollbar,
1962 XTset_vertical_scrollbar (window
, portion
, whole
, position
)
1963 struct window
*window
;
1964 int portion
, whole
, position
;
1966 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1967 int top
= XINT (window
->top
);
1968 int left
= WINDOW_VERTICAL_SCROLLBAR_COLUMN (window
);
1969 int height
= WINDOW_VERTICAL_SCROLLBAR_HEIGHT (window
);
1971 /* Where should this scrollbar be, pixelwise? */
1972 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
1973 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
1974 int pixel_width
= VERTICAL_SCROLLBAR_PIXEL_WIDTH (f
);
1975 int pixel_height
= VERTICAL_SCROLLBAR_PIXEL_HEIGHT (f
, height
);
1977 struct scrollbar
*bar
;
1979 /* Does the scrollbar exist yet? */
1980 if (NILP (window
->vertical_scrollbar
))
1981 bar
= x_scrollbar_create (window
,
1982 pixel_top
, pixel_left
,
1983 pixel_width
, pixel_height
);
1986 /* It may just need to be moved and resized. */
1987 bar
= XSCROLLBAR (window
->vertical_scrollbar
);
1988 x_scrollbar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
1991 /* Set the scrollbar's current state, unless we're currently being
1993 if (NILP (bar
->dragging
))
1996 VERTICAL_SCROLLBAR_TOP_RANGE (pixel_height
);
1999 x_scrollbar_set_handle (bar
, 0, top_range
, 0);
2002 int start
= (position
* top_range
) / whole
;
2003 int end
= ((position
+ portion
) * top_range
) / whole
;
2005 x_scrollbar_set_handle (bar
, start
, end
, 0);
2009 XSET (window
->vertical_scrollbar
, Lisp_Vector
, bar
);
2013 /* The following three hooks are used when we're doing a thorough
2014 redisplay of the frame. We don't explicitly know which scrollbars
2015 are going to be deleted, because keeping track of when windows go
2016 away is a real pain - "Can you say set-window-configuration, boys
2017 and girls?" Instead, we just assert at the beginning of redisplay
2018 that *all* scrollbars are to be removed, and then save a scrollbar
2019 from the fiery pit when we actually redisplay its window. */
2021 /* Arrange for all scrollbars on FRAME to be removed at the next call
2022 to `*judge_scrollbars_hook'. A scrollbar may be spared if
2023 `*redeem_scrollbar_hook' is applied to its window before the judgement. */
2025 XTcondemn_scrollbars (frame
)
2028 /* The condemned list should be empty at this point; if it's not,
2029 then the rest of Emacs isn't using the condemn/redeem/judge
2030 protocol correctly. */
2031 if (! NILP (FRAME_CONDEMNED_SCROLLBARS (frame
)))
2034 /* Move them all to the "condemned" list. */
2035 FRAME_CONDEMNED_SCROLLBARS (frame
) = FRAME_SCROLLBARS (frame
);
2036 FRAME_SCROLLBARS (frame
) = Qnil
;
2039 /* Unmark WINDOW's scrollbar for deletion in this judgement cycle.
2040 Note that WINDOW isn't necessarily condemned at all. */
2042 XTredeem_scrollbar (window
)
2043 struct window
*window
;
2045 struct scrollbar
*bar
;
2047 /* We can't redeem this window's scrollbar if it doesn't have one. */
2048 if (NILP (window
->vertical_scrollbar
))
2051 bar
= XSCROLLBAR (window
->vertical_scrollbar
);
2053 /* Unlink it from the condemned list. */
2055 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2057 if (NILP (bar
->prev
))
2059 /* If the prev pointer is nil, it must be the first in one of
2061 if (EQ (FRAME_SCROLLBARS (f
), window
->vertical_scrollbar
))
2062 /* It's not condemned. Everything's fine. */
2064 else if (EQ (FRAME_CONDEMNED_SCROLLBARS (f
),
2065 window
->vertical_scrollbar
))
2066 FRAME_CONDEMNED_SCROLLBARS (f
) = bar
->next
;
2068 /* If its prev pointer is nil, it must be at the front of
2069 one or the other! */
2073 XSCROLLBAR (bar
->prev
)->next
= bar
->next
;
2075 if (! NILP (bar
->next
))
2076 XSCROLLBAR (bar
->next
)->prev
= bar
->prev
;
2078 bar
->next
= FRAME_SCROLLBARS (f
);
2080 XSET (FRAME_SCROLLBARS (f
), Lisp_Vector
, bar
);
2081 if (! NILP (bar
->next
))
2082 XSET (XSCROLLBAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2086 /* Remove all scrollbars on FRAME that haven't been saved since the
2087 last call to `*condemn_scrollbars_hook'. */
2089 XTjudge_scrollbars (f
)
2092 Lisp_Object bar
, next
;
2094 bar
= FRAME_CONDEMNED_SCROLLBARS (f
);
2096 /* Clear out the condemned list now so we won't try to process any
2097 more events on the hapless scrollbars. */
2098 FRAME_CONDEMNED_SCROLLBARS (f
) = Qnil
;
2100 for (; ! NILP (bar
); bar
= next
)
2102 struct scrollbar
*b
= XSCROLLBAR (bar
);
2104 x_scrollbar_remove (b
);
2107 b
->next
= b
->prev
= Qnil
;
2110 /* Now there should be no references to the condemned scrollbars,
2111 and they should get garbage-collected. */
2115 /* Handle an Expose or GraphicsExpose event on a scrollbar. */
2117 x_scrollbar_expose (bar
, event
)
2118 struct scrollbar
*bar
;
2121 Window w
= SCROLLBAR_X_WINDOW (bar
);
2122 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2126 x_scrollbar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2128 /* Draw a one-pixel border just inside the edges of the scrollbar. */
2129 XDrawRectangle (x_current_display
, w
, gc
,
2131 /* x, y, width, height */
2132 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2134 /* Draw another line to make the extra-thick border on the right. */
2135 XFillRectangle (x_current_display
, w
, gc
,
2137 /* x, y, width, height */
2138 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2143 /* Handle a mouse click on the scrollbar BAR. If *EMACS_EVENT's kind
2144 is set to something other than no_event, it is enqueued. */
2146 x_scrollbar_handle_click (bar
, event
, emacs_event
)
2147 struct scrollbar
*bar
;
2149 struct input_event
*emacs_event
;
2151 if (XTYPE (bar
->window
) != Lisp_Window
)
2154 emacs_event
->kind
= scrollbar_click
;
2155 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2156 emacs_event
->modifiers
=
2157 (x_convert_modifiers (event
->xbutton
.state
)
2158 | (event
->type
== ButtonRelease
2161 emacs_event
->frame_or_window
= bar
->window
;
2162 emacs_event
->timestamp
= event
->xbutton
.time
;
2164 int internal_height
=
2165 VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
2167 VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
2168 int y
= event
->xbutton
.y
- VERTICAL_SCROLLBAR_TOP_BORDER
;
2171 if (y
> top_range
) y
= top_range
;
2173 if (y
< XINT (bar
->start
))
2174 emacs_event
->part
= scrollbar_above_handle
;
2175 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLLBAR_MIN_HANDLE
)
2176 emacs_event
->part
= scrollbar_handle
;
2178 emacs_event
->part
= scrollbar_below_handle
;
2180 /* If the user has just clicked on the handle, record where they're
2182 if (event
->type
== ButtonPress
2183 && emacs_event
->part
== scrollbar_handle
)
2184 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2186 /* If the user has released the handle, set it to its final position. */
2187 if (event
->type
== ButtonRelease
2188 && ! NILP (bar
->dragging
))
2190 int new_start
= y
- XINT (bar
->dragging
);
2191 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2193 x_scrollbar_set_handle (bar
, new_start
, new_end
, 0);
2194 bar
->dragging
= Qnil
;
2197 /* Clicks on the handle are always reported as occuring at the top of
2199 if (emacs_event
->part
== scrollbar_handle
)
2200 emacs_event
->x
= bar
->start
;
2202 XSET (emacs_event
->x
, Lisp_Int
, y
);
2204 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2208 /* Handle some mouse motion while someone is dragging the scrollbar. */
2210 x_scrollbar_note_movement (bar
, event
)
2211 struct scrollbar
*bar
;
2214 last_mouse_movement_time
= event
->xmotion
.time
;
2217 XSET (last_mouse_scrollbar
, Lisp_Vector
, bar
);
2219 /* If we're dragging the bar, display it. */
2220 if (! NILP (bar
->dragging
))
2222 /* Where should the handle be now? */
2223 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2225 if (new_start
!= XINT (bar
->start
))
2227 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2229 x_scrollbar_set_handle (bar
, new_start
, new_end
, 0);
2233 /* Call XQueryPointer so we'll get an event the next time the mouse
2234 moves and we can see *still* on the same position. */
2238 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2239 (Window
*) &dummy
, (Window
*) &dummy
,
2240 &dummy
, &dummy
, &dummy
, &dummy
,
2241 (unsigned int *) &dummy
);
2245 /* Return information to the user about the current position of the mouse
2246 on the scrollbar. */
2248 x_scrollbar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2250 Lisp_Object
*bar_window
;
2251 enum scrollbar_part
*part
;
2253 unsigned long *time
;
2255 struct scrollbar
*bar
= XSCROLLBAR (last_mouse_scrollbar
);
2260 /* Get the mouse's position relative to the scrollbar window, and
2263 Window dummy_window
;
2265 unsigned int dummy_mask
;
2267 if (! XQueryPointer (x_current_display
,
2268 SCROLLBAR_X_WINDOW (bar
),
2270 /* Root, child, root x and root y. */
2271 &dummy_window
, &dummy_window
,
2272 &dummy_coord
, &dummy_coord
,
2274 /* Position relative to scrollbar. */
2277 /* Mouse buttons and modifier keys. */
2286 int inside_height
= VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
2287 int top_range
= VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
2289 win_y
-= VERTICAL_SCROLLBAR_TOP_BORDER
;
2291 if (! NILP (bar
->dragging
))
2292 win_y
-= XINT (bar
->dragging
);
2296 if (win_y
> top_range
)
2299 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2300 *bar_window
= bar
->window
;
2302 if (! NILP (bar
->dragging
))
2303 *part
= scrollbar_handle
;
2304 else if (win_y
< XINT (bar
->start
))
2305 *part
= scrollbar_above_handle
;
2306 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLLBAR_MIN_HANDLE
)
2307 *part
= scrollbar_handle
;
2309 *part
= scrollbar_below_handle
;
2311 XSET (*x
, Lisp_Int
, win_y
);
2312 XSET (*y
, Lisp_Int
, top_range
);
2313 *time
= last_mouse_movement_time
;
2317 last_mouse_scrollbar
= Qnil
;
2325 /* The main X event-reading loop - XTread_socket. */
2327 /* Timestamp of enter window event. This is only used by XTread_socket,
2328 but we have to put it out here, since static variables within functions
2329 sometimes don't work. */
2330 static Time enter_timestamp
;
2332 /* This holds the state XLookupString needs to implement dead keys
2333 and other tricks known as "compose processing". _X Window System_
2334 says that a portable program can't use this, but Stephen Gildea assures
2335 me that letting the compiler initialize it to zeros will work okay.
2337 This must be defined outside of XTread_socket, for the same reasons
2338 given for enter_timestamp, above. */
2339 static XComposeStatus compose_status
;
2341 /* Communication with window managers. */
2342 Atom Xatom_wm_protocols
;
2344 /* Kinds of protocol things we may receive. */
2345 Atom Xatom_wm_take_focus
;
2346 Atom Xatom_wm_save_yourself
;
2347 Atom Xatom_wm_delete_window
;
2349 /* Other WM communication */
2350 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2351 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2353 /* Read events coming from the X server.
2354 This routine is called by the SIGIO handler.
2355 We return as soon as there are no more events to be read.
2357 Events representing keys are stored in buffer BUFP,
2358 which can hold up to NUMCHARS characters.
2359 We return the number of characters stored into the buffer,
2360 thus pretending to be `read'.
2362 WAITP is nonzero if we should block until input arrives.
2363 EXPECTED is nonzero if the caller knows input is available. */
2366 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2368 register struct input_event
*bufp
;
2369 register int numchars
;
2376 int items_pending
; /* How many items are in the X queue. */
2383 if (x_input_blocked
)
2385 x_pending_input
= 1;
2389 x_pending_input
= 0;
2393 abort (); /* Don't think this happens. */
2396 /* If available, Xlib uses FIOSNBIO to make the socket
2397 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2398 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2399 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2400 fcntl (fileno (stdin
), F_SETFL
, 0);
2401 #endif /* ! defined (FIOSNBIO) */
2405 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2407 extern int read_alarm_should_throw
;
2408 read_alarm_should_throw
= 1;
2409 XPeekEvent (XDISPLAY
&event
);
2410 read_alarm_should_throw
= 0;
2412 #endif /* HAVE_SELECT */
2415 while (XStuffPending () != 0)
2417 XNextEvent (XDISPLAY
&event
);
2425 if (event
.xclient
.message_type
== Xatom_wm_protocols
2426 && event
.xclient
.format
== 32)
2428 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2430 f
= x_window_to_frame (event
.xclient
.window
);
2432 x_focus_on_frame (f
);
2433 /* Not certain about handling scrollbars here */
2435 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2437 /* Save state modify the WM_COMMAND property to
2438 something which can reinstate us. This notifies
2439 the session manager, who's looking for such a
2440 PropertyNotify. Can restart processing when
2441 a keyboard or mouse event arrives. */
2446 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2448 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2456 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2459 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2463 new_x
= event
.xclient
.data
.s
[0];
2464 new_y
= event
.xclient
.data
.s
[1];
2469 case SelectionClear
: /* Someone has grabbed ownership. */
2470 x_disown_selection (event
.xselectionclear
.window
,
2471 event
.xselectionclear
.selection
,
2472 event
.xselectionclear
.time
);
2475 case SelectionRequest
: /* Someone wants our selection. */
2476 x_answer_selection_request (event
);
2479 case PropertyNotify
:
2481 /* If we're being told about a root window property, then it's
2482 a cut buffer change. */
2483 if (event
.xproperty
.window
== ROOT_WINDOW
)
2484 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2486 /* Otherwise, we're probably handling an incremental
2487 selection transmission. */
2490 /* If we were to do this synchronously, there'd be no worry
2491 about re-selecting. */
2492 x_send_incremental (event
);
2497 f
= x_window_to_frame (event
.xexpose
.window
);
2500 if (f
->async_visible
== 0)
2502 f
->async_visible
= 1;
2503 f
->async_iconified
= 0;
2504 SET_FRAME_GARBAGED (f
);
2508 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2509 event
.xexpose
.x
, event
.xexpose
.y
,
2510 event
.xexpose
.width
, event
.xexpose
.height
);
2515 struct scrollbar
*bar
2516 = x_window_to_scrollbar (event
.xexpose
.window
);
2519 x_scrollbar_expose (bar
, &event
);
2523 case GraphicsExpose
: /* This occurs when an XCopyArea's
2524 source area was obscured or not
2526 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2530 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2531 event
.xgraphicsexpose
.width
,
2532 event
.xgraphicsexpose
.height
);
2536 case NoExpose
: /* This occurs when an XCopyArea's
2537 source area was completely
2540 #else /* ! defined (HAVE_X11) */
2542 if (event
.subwindow
!= 0)
2543 break; /* duplicate event */
2544 f
= x_window_to_frame (event
.window
);
2545 if (event
.window
== f
->display
.x
->icon_desc
)
2548 f
->async_iconified
= 1;
2550 if (event
.window
== FRAME_X_WINDOW (f
))
2552 /* Say must check all windows' needs_exposure flags. */
2553 expose_all_windows
= 1;
2554 f
->display
.x
->needs_exposure
= 1;
2555 f
->async_visible
= 1;
2560 if (event
.subwindow
!= 0)
2561 break; /* duplicate event */
2562 f
= x_window_to_frame (event
.window
);
2563 if (event
.window
== f
->display
.x
->icon_desc
)
2568 /* If window already needs full redraw, ignore this rectangle. */
2569 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2571 /* Put the event on the queue of rectangles to redraw. */
2572 if (enqueue_event (&event
, &x_expose_queue
))
2573 /* If it is full, we can't record the rectangle,
2574 so redraw this entire window. */
2576 /* Say must check all windows' needs_exposure flags. */
2577 expose_all_windows
= 1;
2578 f
->display
.x
->needs_exposure
= 1;
2583 /* This should happen only when we are expecting it,
2584 in x_read_exposes. */
2586 #endif /* ! defined (HAVE_X11) */
2590 f
= x_window_to_frame (event
.xunmap
.window
);
2591 if (f
) /* F may no longer exist if
2592 the frame was deleted. */
2594 /* While a frame is unmapped, display generation is
2595 disabled; you don't want to spend time updating a
2596 display that won't ever be seen. */
2597 f
->async_visible
= 0;
2602 f
= x_window_to_frame (event
.xmap
.window
);
2605 f
->async_visible
= 1;
2606 f
->async_iconified
= 0;
2608 /* wait_reading_process_input will notice this and update
2609 the frame's display structures. */
2610 SET_FRAME_GARBAGED (f
);
2614 /* Turn off processing if we become fully obscured. */
2615 case VisibilityNotify
:
2618 #else /* ! defined (HAVE_X11) */
2620 f
= x_window_to_frame (event
.window
);
2621 if (event
.window
== f
->display
.x
->icon_desc
)
2622 f
->async_iconified
= 0;
2623 if (event
.window
== FRAME_X_WINDOW (f
))
2624 f
->async_visible
= 0;
2626 #endif /* ! defined (HAVE_X11) */
2630 f
= x_window_to_frame (event
.xkey
.window
);
2635 char copy_buffer
[80];
2636 int modifiers
= event
.xkey
.state
;
2638 /* Some keyboards generate different characters
2639 depending on the state of the meta key, in an attempt
2640 to support non-English typists. It would be nice to
2641 keep this functionality somehow, but for now, we will
2642 just clear the meta-key flag to get the 'pure' character. */
2643 event
.xkey
.state
&= ~Mod1Mask
;
2645 /* This will have to go some day... */
2647 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2650 /* Strip off the vendor-specific keysym bit, and take a shot
2651 at recognizing the codes. HP servers have extra keysyms
2652 that fit into the MiscFunctionKey category. */
2657 if (IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2658 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < 0xff80 */
2659 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2660 || IsFunctionKey (keysym
)) /* 0xffbe <= x < 0xffe1 */
2662 bufp
->kind
= non_ascii_keystroke
;
2663 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff50);
2664 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2665 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2666 bufp
->timestamp
= event
.xkey
.time
;
2671 else if (numchars
> nbytes
)
2677 if (modifiers
& x_meta_mod_mask
)
2678 *copy_buffer
|= METABIT
;
2679 bufp
->kind
= ascii_keystroke
;
2680 XSET (bufp
->code
, Lisp_Int
, *copy_buffer
);
2681 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2682 bufp
->timestamp
= event
.xkey
.time
;
2686 for (i
= nbytes
- 1; i
> 1; i
--)
2688 bufp
->kind
= ascii_keystroke
;
2689 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2690 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2691 bufp
->timestamp
= event
.xkey
.time
;
2701 #else /* ! defined (HAVE_X11) */
2704 register char *where_mapping
;
2706 f
= x_window_to_frame (event
.window
);
2707 /* Ignore keys typed on icon windows. */
2708 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2710 where_mapping
= XLookupMapping (&event
, &nbytes
);
2711 /* Nasty fix for arrow keys */
2712 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2714 switch (event
.detail
& 0xff)
2716 case KC_CURSOR_LEFT
:
2717 where_mapping
= "\002";
2719 case KC_CURSOR_RIGHT
:
2720 where_mapping
= "\006";
2723 where_mapping
= "\020";
2725 case KC_CURSOR_DOWN
:
2726 where_mapping
= "\016";
2731 if (numchars
- nbytes
> 0)
2735 for (i
= 0; i
< nbytes
; i
++)
2737 bufp
->kind
= ascii_keystroke
;
2738 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2739 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2740 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2748 #endif /* ! defined (HAVE_X11) */
2752 /* Here's a possible interpretation of the whole
2753 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2754 FocusIn event, you have to get a FocusOut event before you
2755 relinquish the focus. If you haven't received a FocusIn event,
2756 then a mere LeaveNotify is enough to free you. */
2759 f
= x_window_to_frame (event
.xcrossing
.window
);
2761 if (event
.xcrossing
.focus
) /* Entered Window */
2763 /* Avoid nasty pop/raise loops. */
2764 if (f
&& (!(f
->auto_raise
)
2766 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
2768 x_new_focus_frame (f
);
2769 enter_timestamp
= event
.xcrossing
.time
;
2772 else if (f
== x_focus_frame
)
2773 x_new_focus_frame (0);
2778 f
= x_window_to_frame (event
.xfocus
.window
);
2779 if (event
.xfocus
.detail
!= NotifyPointer
)
2780 x_focus_event_frame
= f
;
2782 x_new_focus_frame (f
);
2787 f
= x_window_to_frame (event
.xcrossing
.window
);
2789 if (event
.xcrossing
.focus
)
2791 if (! x_focus_event_frame
)
2792 x_new_focus_frame (0);
2794 x_new_focus_frame (f
);
2798 if (f
== x_focus_event_frame
)
2799 x_focus_event_frame
= 0;
2800 if (f
== x_focus_frame
)
2801 x_new_focus_frame (0);
2806 f
= x_window_to_frame (event
.xfocus
.window
);
2807 if (event
.xfocus
.detail
!= NotifyPointer
2808 && f
== x_focus_event_frame
)
2809 x_focus_event_frame
= 0;
2810 if (f
&& f
== x_focus_frame
)
2811 x_new_focus_frame (0);
2814 #else /* ! defined (HAVE_X11) */
2817 if ((event
.detail
& 0xFF) == 1)
2818 break; /* Coming from our own subwindow */
2819 if (event
.subwindow
!= 0)
2820 break; /* Entering our own subwindow. */
2823 f
= x_window_to_frame (event
.window
);
2826 x_new_focus_frame (f
);
2831 if ((event
.detail
& 0xFF) == 1)
2832 break; /* Entering our own subwindow */
2833 if (event
.subwindow
!= 0)
2834 break; /* Leaving our own subwindow. */
2837 if (x_focus_frame
== 0
2838 && x_input_frame
!= 0
2839 && x_input_frame
== x_window_to_frame (event
.window
)
2840 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
2845 frame_unhighlight (f
);
2848 #endif /* ! defined (HAVE_X11) */
2853 f
= x_window_to_frame (event
.xmotion
.window
);
2855 note_mouse_movement (f
, &event
.xmotion
);
2858 struct scrollbar
*bar
=
2859 x_window_to_scrollbar (event
.xmotion
.window
);
2862 x_scrollbar_note_movement (bar
, &event
);
2867 case ConfigureNotify
:
2870 f
= x_window_to_frame (event
.xconfigure
.window
);
2874 columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
2875 rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
2877 /* Even if the number of character rows and columns has
2878 not changed, the font size may have changed, so we need
2879 to check the pixel dimensions as well. */
2880 if (columns
!= f
->width
2881 || rows
!= f
->height
2882 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
2883 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
2885 change_frame_size (f
, rows
, columns
, 0, 1);
2886 SET_FRAME_GARBAGED (f
);
2889 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
2890 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
2891 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
2892 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
2899 /* If we decide we want to generate an event to be seen
2900 by the rest of Emacs, we put it here. */
2901 struct input_event emacs_event
;
2902 emacs_event
.kind
= no_event
;
2904 f
= x_window_to_frame (event
.xbutton
.window
);
2907 if (!x_focus_frame
|| (f
== x_focus_frame
))
2908 construct_mouse_click (&emacs_event
,
2909 &event
, f
, Qnil
, 0);
2913 struct scrollbar
*bar
=
2914 x_window_to_scrollbar (event
.xbutton
.window
);
2917 x_scrollbar_handle_click (bar
, &event
, &emacs_event
);
2920 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
2922 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
2930 #else /* ! defined (HAVE_X11) */
2932 case ButtonReleased
:
2933 f
= x_window_to_frame (event
.window
);
2936 if (event
.window
== f
->display
.x
->icon_desc
)
2938 x_make_frame_visible (f
);
2940 if (warp_mouse_on_deiconify
)
2941 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
2944 if (event
.window
== FRAME_X_WINDOW (f
))
2950 enqueue_event (&event
, &x_mouse_queue
);
2953 bufp
->kind
= ascii_keystroke
;
2954 bufp
->code
= (char) 'X' & 037; /* C-x */
2955 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2956 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2959 bufp
->kind
= ascii_keystroke
;
2960 bufp
->code
= (char) 0; /* C-@ */
2961 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2962 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2969 #endif /* ! defined (HAVE_X11) */
2973 case CirculateNotify
:
2975 case CirculateRequest
:
2978 #endif /* ! defined (HAVE_X11) */
2981 /* Someone has changed the keyboard mapping - update the
2983 switch (event
.xmapping
.request
)
2985 case MappingModifier
:
2986 x_find_modifier_meanings ();
2987 /* This is meant to fall through. */
2988 case MappingKeyboard
:
2989 XRefreshKeyboardMapping (&event
.xmapping
);
3000 if (expected
&& ! event_found
)
3002 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3003 there is an EOF condition; in other words, that X has died.
3004 Act as if there had been a hangup. */
3006 int fd
= ConnectionNumber (x_current_display
);
3009 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3011 && !XStuffPending ())
3012 kill (getpid (), SIGHUP
);
3014 #endif /* ! defined (HAVE_SELECT) */
3018 if (updating_frame
== 0)
3019 x_do_pending_expose ();
3027 /* Read and process only Expose events
3028 until we get an ExposeCopy event; then return.
3029 This is used in insert/delete line.
3030 We assume input is already blocked. */
3036 XKeyPressedEvent event
;
3040 /* while there are more events*/
3041 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3045 if (event
.subwindow
!= 0)
3046 break; /* duplicate event */
3047 f
= x_window_to_frame (event
.window
);
3048 if (event
.window
== f
->display
.x
->icon_desc
)
3053 if (event
.window
== FRAME_X_WINDOW (f
))
3055 expose_all_windows
= 1;
3056 f
->display
.x
->needs_exposure
= 1;
3062 if (event
.subwindow
!= 0)
3063 break; /* duplicate event */
3064 f
= x_window_to_frame (event
.window
);
3065 if (event
.window
== f
->display
.x
->icon_desc
)
3070 /* If window already needs full redraw, ignore this rectangle. */
3071 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3073 /* Put the event on the queue of rectangles to redraw. */
3074 if (enqueue_event (&event
, &x_expose_queue
))
3075 /* If it is full, we can't record the rectangle,
3076 so redraw this entire window. */
3078 /* Say must check all windows' needs_exposure flags. */
3079 expose_all_windows
= 1;
3080 f
->display
.x
->needs_exposure
= 1;
3089 #endif /* HAVE_X11 */
3092 /* Drawing the cursor. */
3095 /* Draw a hollow box cursor. Don't change the inside of the box. */
3101 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3102 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3103 int width
= FONT_WIDTH (f
->display
.x
->font
);
3104 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3107 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3108 f
->display
.x
->cursor_gc
,
3109 left
, top
, width
- 1, height
- 1);
3110 #else /* ! defined (HAVE_X11) */
3111 XPixSet (FRAME_X_WINDOW (f
),
3112 left
, top
, width
, 1,
3113 f
->display
.x
->cursor_pixel
);
3115 XPixSet (FRAME_X_WINDOW (f
),
3116 left
, top
, 1, height
,
3117 f
->display
.x
->cursor_pixel
);
3119 XPixSet (FRAME_X_WINDOW (f
),
3120 left
+width
-1, top
, 1, height
,
3121 f
->display
.x
->cursor_pixel
);
3123 XPixSet (FRAME_X_WINDOW (f
),
3124 left
, top
+height
-1, width
, 1,
3125 f
->display
.x
->cursor_pixel
);
3126 #endif /* ! defined (HAVE_X11) */
3129 /* Clear the cursor of frame F to background color,
3130 and mark the cursor as not shown.
3131 This is used when the text where the cursor is
3132 is about to be rewritten. */
3140 if (! FRAME_VISIBLE_P (f
)
3141 || f
->phys_cursor_x
< 0)
3145 x_display_cursor (f
, 0);
3146 #else /* ! defined (HAVE_X11) */
3147 XPixSet (FRAME_X_WINDOW (f
),
3148 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3149 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3150 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3151 f
->display
.x
->background_pixel
);
3152 #endif /* ! defined (HAVE_X11) */
3153 f
->phys_cursor_x
= -1;
3157 x_display_bar_cursor (f
, on
)
3161 register int phys_x
= f
->phys_cursor_x
;
3162 register int phys_y
= f
->phys_cursor_y
;
3167 if (! FRAME_VISIBLE_P (f
) || (! on
&& f
->phys_cursor_x
< 0))
3172 (!on
|| phys_x
!= f
->cursor_x
|| phys_y
!= f
->cursor_y
))
3174 x1
= CHAR_TO_PIXEL_COL (f
, phys_x
);
3175 y1
= CHAR_TO_PIXEL_ROW (f
, phys_y
) - 1;
3176 y2
= y1
+ FONT_HEIGHT (f
->display
.x
->font
) + 1;
3178 XDrawLine (x_current_display
, FRAME_X_WINDOW (f
),
3179 f
->display
.x
->reverse_gc
, x1
, y1
, x1
, y2
);
3181 f
->phys_cursor_x
= phys_x
= -1;
3184 if (on
&& f
== x_highlight_frame
)
3186 x1
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3187 y1
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
) - 1;
3188 y2
= y1
+ FONT_HEIGHT (f
->display
.x
->font
) + 1;
3190 XDrawLine (x_current_display
, FRAME_X_WINDOW (f
),
3191 f
->display
.x
->cursor_gc
, x1
, y1
, x1
, y2
);
3193 f
->phys_cursor_x
= f
->cursor_x
;
3194 f
->phys_cursor_y
= f
->cursor_y
;
3196 #else /* ! defined (HAVE_X11) */
3198 #endif /* ! defined (HAVE_X11) */
3202 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3203 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3207 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3214 CHAR_TO_PIXEL_COL (f
, column
),
3215 CHAR_TO_PIXEL_ROW (f
, row
),
3216 &glyph
, 1, highlight
, f
->display
.x
->font
);
3219 /* Turn the displayed cursor of frame F on or off according to ON.
3220 If ON is nonzero, where to put the cursor is specified
3221 by F->cursor_x and F->cursor_y. */
3224 x_display_box_cursor (f
, on
)
3228 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3230 /* If we're not updating, then we want to use the current frame's
3231 cursor position, not our local idea of where the cursor ought to be. */
3232 if (f
!= updating_frame
)
3234 curs_x
= FRAME_CURSOR_X (f
);
3235 curs_y
= FRAME_CURSOR_Y (f
);
3238 if (! FRAME_VISIBLE_P (f
))
3241 /* If cursor is off and we want it off, return quickly. */
3242 if (!on
&& f
->phys_cursor_x
< 0)
3245 /* If cursor is currently being shown and we don't want it to be
3246 or it is in the wrong place,
3247 or we want a hollow box and it's not so, (pout!)
3249 if (f
->phys_cursor_x
>= 0
3251 || f
->phys_cursor_x
!= curs_x
3252 || f
->phys_cursor_y
!= curs_y
3253 || (f
->display
.x
->text_cursor_kind
!= hollow_box_cursor
3254 && (f
!= x_highlight_frame
))))
3256 /* Erase the cursor by redrawing the character underneath it. */
3257 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3258 f
->phys_cursor_glyph
,
3259 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3260 f
->phys_cursor_x
= -1;
3263 /* If we want to show a cursor,
3264 or we want a box cursor and it's not so,
3265 write it in the right place. */
3267 && (f
->phys_cursor_x
< 0
3268 || (f
->display
.x
->text_cursor_kind
!= filled_box_cursor
3269 && f
== x_highlight_frame
)))
3271 f
->phys_cursor_glyph
3272 = ((current_glyphs
->enable
[curs_y
]
3273 && curs_x
< current_glyphs
->used
[curs_y
])
3274 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3276 if (f
!= x_highlight_frame
)
3279 f
->display
.x
->text_cursor_kind
= hollow_box_cursor
;
3283 x_draw_single_glyph (f
, curs_y
, curs_x
,
3284 f
->phys_cursor_glyph
, 2);
3285 f
->display
.x
->text_cursor_kind
= filled_box_cursor
;
3288 f
->phys_cursor_x
= curs_x
;
3289 f
->phys_cursor_y
= curs_y
;
3292 if (updating_frame
!= f
)
3296 extern Lisp_Object Vbar_cursor
;
3298 x_display_cursor (f
, on
)
3302 if (EQ (Vbar_cursor
, Qnil
))
3303 x_display_box_cursor (f
, on
);
3305 x_display_bar_cursor (f
, on
);
3310 /* Refresh bitmap kitchen sink icon for frame F
3311 when we get an expose event for it. */
3317 /* Normally, the window manager handles this function. */
3318 #else /* ! defined (HAVE_X11) */
3321 if (f
->display
.x
->icon_bitmap_flag
)
3322 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3323 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3324 icon_bitmap
, GXcopy
, AllPlanes
);
3327 extern struct frame
*selected_frame
;
3328 struct Lisp_String
*str
;
3329 unsigned char *string
;
3332 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3334 if (f
->display
.x
->icon_label
!= string
)
3336 f
->display
.x
->icon_label
= string
;
3337 XChangeWindow (f
->display
.x
->icon_desc
,
3338 XQueryWidth (string
, icon_font_info
->id
) + 10,
3339 icon_font_info
->height
+ 10);
3342 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3343 str
->size
, icon_font_info
->id
,
3344 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3347 #endif /* ! defined (HAVE_X11) */
3350 /* Make the x-window of frame F use the kitchen-sink icon
3351 that's a window generated by Emacs. */
3360 if (FRAME_X_WINDOW (f
) == 0)
3365 XFreePixmap (x_current_display
, icon_bitmap
);
3368 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3369 gnu_bits
, gnu_width
, gnu_height
);
3370 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3371 f
->display
.x
->icon_bitmap_flag
= 1;
3372 #else /* ! defined (HAVE_X11) */
3373 if (f
->display
.x
->icon_desc
)
3375 XClearIconWindow (FRAME_X_WINDOW (f
));
3376 XDestroyWindow (f
->display
.x
->icon_desc
);
3379 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3380 0, 0, sink_width
, sink_height
,
3381 2, WhitePixmap
, (Pixmap
) NULL
);
3383 if (icon_window
== 0)
3386 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3387 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3389 f
->display
.x
->icon_desc
= icon_window
;
3390 f
->display
.x
->icon_bitmap_flag
= 1;
3392 if (icon_bitmap
== 0)
3394 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3395 #endif /* ! defined (HAVE_X11) */
3401 /* Make the x-window of frame F use a rectangle with text. */
3404 x_text_icon (f
, icon_name
)
3412 char *X_DefaultValue
;
3416 #define WhitePixel 1
3417 #endif /* WhitePixel */
3420 #define BlackPixel 0
3421 #endif /* BlackPixel */
3422 #endif /* HAVE_X11 */
3424 if (FRAME_X_WINDOW (f
) == 0)
3427 if (icon_font_info
== 0)
3429 = XGetFont (XGetDefault (XDISPLAY
3430 (char *) XSTRING (invocation_name
)->data
,
3435 f
->display
.x
->icon_label
= icon_name
;
3437 if (! f
->display
.x
->icon_label
)
3438 f
->display
.x
->icon_label
= " *emacs* ";
3440 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3441 (char *) f
->display
.x
->icon_label
);
3443 f
->display
.x
->icon_bitmap_flag
= 0;
3444 x_wm_set_icon_pixmap (f
, 0);
3445 #else /* ! defined (HAVE_X11) */
3446 if (f
->display
.x
->icon_desc
)
3448 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3449 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3453 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3455 if (! f
->display
.x
->icon_label
)
3456 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3458 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3459 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3460 f
->display
.x
->left_pos
,
3461 f
->display
.x
->top_pos
,
3462 width
+ 10, icon_font_info
->height
+ 10,
3463 2, BlackPixmap
, WhitePixmap
);
3465 if (icon_window
== 0)
3468 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3469 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3471 f
->display
.x
->icon_desc
= icon_window
;
3472 f
->display
.x
->icon_bitmap_flag
= 0;
3473 f
->display
.x
->icon_label
= 0;
3474 #endif /* ! defined (HAVE_X11) */
3479 /* Handling X errors. */
3481 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3482 X server's connection, or an error reported via the X protocol. */
3485 x_connection_closed ()
3490 shut_down_emacs (0);
3495 /* An X error handler which prints an error message and then kills Emacs.
3496 This is what's normally installed as Xlib's handler for protocol and
3499 x_error_quitter (display
, error
)
3505 /* Note that there is no real way portable across R3/R4 to get the
3506 original error handler. */
3508 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3509 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3510 buf
, error
->request_code
);
3512 /* While we're testing Emacs 19, we'll just dump core whenever we
3513 get an X error, so we can figure out why it happened. */
3516 x_connection_closed ();
3519 /* A buffer for storing X error messages. */
3520 static char (*x_caught_error_message
)[200];
3522 /* An X error handler which stores the error message in
3523 x_caught_error_message. This is what's installed when
3524 x_catch_errors is in effect. */
3526 x_error_catcher (display
, error
)
3530 XGetErrorText (display
, error
->error_code
,
3531 *x_caught_error_message
, sizeof (*x_caught_error_message
));
3535 /* Begin trapping X errors.
3537 After calling this function, X protocol errors no longer cause
3538 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3540 Calling x_check_errors signals an Emacs error if an X error has
3541 occurred since the last call to x_catch_errors or x_check_errors.
3543 Calling x_uncatch_errors resumes the normal error handling. */
3545 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3550 /* Make sure any errors from previous requests have been dealt with. */
3551 XSync (x_current_display
, False
);
3553 /* Set up the error buffer. */
3554 x_caught_error_message
=
3555 (char (*)[]) xmalloc (sizeof (*x_caught_error_message
));
3556 (*x_caught_error_message
)[0] = '\0';
3558 /* Install our little error handler. */
3559 XHandleError (x_error_catcher
);
3562 /* If any X protocol errors have arrived since the last call to
3563 x_catch_errors or x_check_errors, signal an Emacs error using
3564 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3566 x_check_errors (format
)
3569 /* Make sure to catch any errors incurred so far. */
3570 XSync (x_current_display
, False
);
3572 if ((*x_caught_error_message
)[0])
3576 sprintf (buf
, format
, *x_caught_error_message
);
3577 free (x_caught_error_message
);
3579 x_uncatch_errors ();
3587 free (x_caught_error_message
);
3588 XHandleError (x_error_quitter
);
3592 static unsigned int x_wire_count
;
3595 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3600 /* Changing the font of the frame. */
3602 /* Set the font of the x-window specified by frame F
3603 to the font named NEWNAME. This is safe to use
3604 even before F has an actual x-window. */
3608 /* A table of all the fonts we have already loaded. */
3609 static XFontStruct
**x_font_table
;
3611 /* The current capacity of x_font_table. */
3612 static int x_font_table_size
;
3614 /* The number of fonts actually stored in x_font_table.
3615 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3616 0 <= n_fonts <= x_font_table_size. */
3619 x_new_font (f
, fontname
)
3621 register char *fontname
;
3625 int n_matching_fonts
;
3626 XFontStruct
*font_info
;
3629 /* Get a list of all the fonts that match this name. Once we
3630 have a list of matching fonts, we compare them against the fonts
3631 we already have by comparing font ids. */
3632 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3633 1024, &n_matching_fonts
,
3635 /* If the server couldn't find any fonts whose named matched fontname,
3636 return an error code. */
3637 if (n_matching_fonts
== 0)
3640 /* See if we've already loaded a matching font. */
3645 for (i
= 0; i
< n_fonts
; i
++)
3646 for (j
= 0; j
< n_matching_fonts
; j
++)
3647 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3655 /* If we have, just return it from the table. */
3657 f
->display
.x
->font
= x_font_table
[already_loaded
];
3659 /* Otherwise, load the font and add it to the table. */
3664 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
3668 /* Do we need to create the table? */
3669 if (x_font_table_size
== 0)
3671 x_font_table_size
= 16;
3673 = (XFontStruct
**) xmalloc (x_font_table_size
3674 * sizeof (x_font_table
[0]));
3676 /* Do we need to grow the table? */
3677 else if (n_fonts
>= x_font_table_size
)
3679 x_font_table_size
*= 2;
3681 = (XFontStruct
**) xrealloc (x_font_table
,
3683 * sizeof (x_font_table
[0])));
3686 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
3689 /* Free the information from XListFontsWithInfo. The data
3690 we actually retain comes from XLoadQueryFont. */
3691 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
3693 /* Now make the frame display the given font. */
3694 if (FRAME_X_WINDOW (f
) != 0)
3696 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
3697 f
->display
.x
->font
->fid
);
3698 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
3699 f
->display
.x
->font
->fid
);
3700 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
3701 f
->display
.x
->font
->fid
);
3703 x_set_window_size (f
, f
->width
, f
->height
);
3708 #else /* ! defined (HAVE_X11) */
3709 x_new_font (f
, newname
)
3711 register char *newname
;
3716 temp
= XGetFont (newname
);
3717 if (temp
== (FONT_TYPE
*) 0)
3720 if (f
->display
.x
->font
)
3721 XLoseFont (f
->display
.x
->font
);
3723 f
->display
.x
->font
= temp
;
3725 if (FRAME_X_WINDOW (f
) != 0)
3726 x_set_window_size (f
, f
->width
, f
->height
);
3730 #endif /* ! defined (HAVE_X11) */
3732 /* X Window sizes and positions. */
3734 x_calc_absolute_position (f
)
3738 if (f
->display
.x
->left_pos
< 0)
3739 f
->display
.x
->left_pos
3740 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
3742 if (f
->display
.x
->top_pos
< 0)
3743 f
->display
.x
->top_pos
3744 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
3745 #else /* ! defined (HAVE_X11) */
3746 WINDOWINFO_TYPE parentinfo
;
3748 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
3750 if (f
->display
.x
->left_pos
< 0)
3751 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
3752 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
3754 if (f
->display
.x
->top_pos
< 0)
3755 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
3756 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
3757 #endif /* ! defined (HAVE_X11) */
3760 x_set_offset (f
, xoff
, yoff
)
3762 register int xoff
, yoff
;
3764 f
->display
.x
->top_pos
= yoff
;
3765 f
->display
.x
->left_pos
= xoff
;
3766 x_calc_absolute_position (f
);
3769 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
3770 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
3772 x_wm_set_size_hint (f
, 0);
3773 #endif /* ! defined (HAVE_X11) */
3777 /* Call this to change the size of frame F's x-window. */
3779 x_set_window_size (f
, cols
, rows
)
3783 int pixelwidth
, pixelheight
;
3788 check_frame_size (f
, &rows
, &cols
);
3789 f
->display
.x
->vertical_scrollbar_extra
=
3790 (FRAME_HAS_VERTICAL_SCROLLBARS (f
)
3791 ? VERTICAL_SCROLLBAR_PIXEL_WIDTH (f
)
3793 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3794 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3797 x_wm_set_size_hint (f
, 0);
3798 #endif /* ! defined (HAVE_X11) */
3799 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
3801 /* Now, strictly speaking, we can't be sure that this is accurate,
3802 but the window manager will get around to dealing with the size
3803 change request eventually, and we'll hear how it went when the
3804 ConfigureNotify event gets here. */
3805 FRAME_WIDTH (f
) = cols
;
3806 FRAME_HEIGHT (f
) = rows
;
3807 PIXEL_WIDTH (f
) = pixelwidth
;
3808 PIXEL_HEIGHT (f
) = pixelheight
;
3815 x_set_resize_hint (f
)
3818 XSetResizeHint (FRAME_X_WINDOW (f
),
3819 2 * f
->display
.x
->internal_border_width
,
3820 2 * f
->display
.x
->internal_border_width
,
3821 FONT_WIDTH (f
->display
.x
->font
),
3822 FONT_HEIGHT (f
->display
.x
->font
));
3824 #endif /* HAVE_X11 */
3826 /* Mouse warping, focus shifting, raising and lowering. */
3828 x_set_mouse_position (f
, x
, y
)
3836 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
3837 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
3839 if (pix_x
< 0) pix_x
= 0;
3840 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3842 if (pix_y
< 0) pix_y
= 0;
3843 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3847 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
3852 x_focus_on_frame (f
)
3857 /* I don't think that the ICCCM allows programs to do things like this
3858 without the interaction of the window manager. Whatever you end up
3859 doing with this code, do it to x_unfocus_frame too. */
3860 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
3861 RevertToPointerRoot
, CurrentTime
);
3869 /* Look at the remarks in x_focus_on_frame. */
3870 if (x_focus_frame
== f
)
3871 XSetInputFocus (x_current_display
, PointerRoot
,
3872 RevertToPointerRoot
, CurrentTime
);
3876 #endif /* ! defined (HAVE_X11) */
3878 /* Raise frame F. */
3883 if (f
->async_visible
)
3886 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3892 /* Lower frame F. */
3897 if (f
->async_visible
)
3900 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3906 /* Change from withdrawn state to mapped state. */
3908 x_make_frame_visible (f
)
3915 if (! FRAME_VISIBLE_P (f
))
3918 if (! EQ (Vx_no_window_manager
, Qt
))
3919 x_wm_set_window_state (f
, NormalState
);
3921 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3922 if (FRAME_HAS_VERTICAL_SCROLLBARS (f
))
3923 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
3924 #else /* ! defined (HAVE_X11) */
3925 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3926 if (f
->display
.x
->icon_desc
!= 0)
3927 XUnmapWindow (f
->display
.x
->icon_desc
);
3929 /* Handled by the MapNotify event for X11 */
3930 f
->async_visible
= 1;
3931 f
->async_iconified
= 0;
3933 /* NOTE: this may cause problems for the first frame. */
3935 #endif /* ! defined (HAVE_X11) */
3943 /* Change from mapped state to withdrawn state. */
3945 x_make_frame_invisible (f
)
3950 if (! f
->async_visible
)
3957 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
3958 DefaultScreen (x_current_display
)))
3960 UNBLOCK_INPUT_RESIGNAL
;
3961 error ("can't notify window manager of window withdrawl");
3964 #else /* ! defined (HAVE_X11R4) */
3967 /* Tell the window manager what we're going to do. */
3968 if (! EQ (Vx_no_window_manager
, Qt
))
3972 unmap
.xunmap
.type
= UnmapNotify
;
3973 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
3974 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
3975 unmap
.xunmap
.from_configure
= False
;
3976 if (! XSendEvent (x_current_display
,
3977 DefaultRootWindow (x_current_display
),
3979 SubstructureRedirectMask
|SubstructureNotifyMask
,
3982 UNBLOCK_INPUT_RESIGNAL
;
3983 error ("can't notify window manager of withdrawal");
3987 /* Unmap the window ourselves. Cheeky! */
3988 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
3990 #else /* ! defined (HAVE_X11) */
3992 XUnmapWindow (FRAME_X_WINDOW (f
));
3993 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
3994 if (f
->display
.x
->icon_desc
!= 0)
3995 XUnmapWindow (f
->display
.x
->icon_desc
);
3997 #endif /* ! defined (HAVE_X11) */
3998 #endif /* ! defined (HAVE_X11R4) */
4004 /* Window manager communication. Created in Fx_open_connection. */
4005 extern Atom Xatom_wm_change_state
;
4007 /* Change window state from mapped to iconified. */
4014 if (f
->async_iconified
)
4020 /* Since we don't know which revision of X we're running, we'll use both
4021 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4023 /* X11R4: send a ClientMessage to the window manager using the
4024 WM_CHANGE_STATE type. */
4028 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4029 message
.xclient
.type
= ClientMessage
;
4030 message
.xclient
.message_type
= Xatom_wm_change_state
;
4031 message
.xclient
.format
= 32;
4032 message
.xclient
.data
.l
[0] = IconicState
;
4034 if (! XSendEvent (x_current_display
,
4035 DefaultRootWindow (x_current_display
),
4037 SubstructureRedirectMask
| SubstructureNotifyMask
,
4040 UNBLOCK_INPUT_RESIGNAL
;
4041 error ("Can't notify window manager of iconification.");
4045 /* X11R3: set the initial_state field of the window manager hints to
4047 x_wm_set_window_state (f
, IconicState
);
4049 f
->async_iconified
= 1;
4050 #else /* ! defined (HAVE_X11) */
4051 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4053 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4054 if (f
->display
.x
->icon_desc
!= 0)
4056 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4059 #endif /* ! defined (HAVE_X11) */
4065 /* Destroy the X window of frame F. */
4067 x_destroy_window (f
)
4072 if (f
->display
.x
->icon_desc
!= 0)
4073 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4074 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4077 free (f
->display
.x
);
4079 if (f
== x_focus_frame
)
4081 if (f
== x_highlight_frame
)
4082 x_highlight_frame
= 0;
4087 /* Manage event queues for X10. */
4091 /* Manage event queues.
4093 This code is only used by the X10 support.
4095 We cannot leave events in the X queue and get them when we are ready
4096 because X does not provide a subroutine to get only a certain kind
4097 of event but not block if there are no queued events of that kind.
4099 Therefore, we must examine events as they come in and copy events
4100 of certain kinds into our private queues.
4102 All ExposeRegion events are put in x_expose_queue.
4103 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4106 /* Write the event *P_XREP into the event queue *QUEUE.
4107 If the queue is full, do nothing, but return nonzero. */
4110 enqueue_event (p_xrep
, queue
)
4111 register XEvent
*p_xrep
;
4112 register struct event_queue
*queue
;
4114 int newindex
= queue
->windex
+ 1;
4115 if (newindex
== EVENT_BUFFER_SIZE
)
4117 if (newindex
== queue
->rindex
)
4119 queue
->xrep
[queue
->windex
] = *p_xrep
;
4120 queue
->windex
= newindex
;
4124 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4125 If *QUEUE is empty, do nothing and return 0. */
4128 dequeue_event (p_xrep
, queue
)
4129 register XEvent
*p_xrep
;
4130 register struct event_queue
*queue
;
4132 if (queue
->windex
== queue
->rindex
)
4134 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4135 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4140 /* Return the number of events buffered in *QUEUE. */
4143 queue_event_count (queue
)
4144 register struct event_queue
*queue
;
4146 int tem
= queue
->windex
- queue
->rindex
;
4149 return EVENT_BUFFER_SIZE
+ tem
;
4152 /* Return nonzero if mouse input is pending. */
4155 mouse_event_pending_p ()
4157 return queue_event_count (&x_mouse_queue
);
4159 #endif /* HAVE_X11 */
4161 /* Setting window manager hints. */
4165 x_wm_set_size_hint (f
, prompting
)
4169 XSizeHints size_hints
;
4170 Window window
= FRAME_X_WINDOW (f
);
4172 size_hints
.flags
= PResizeInc
| PMinSize
| PMaxSize
;
4174 flexlines
= f
->height
;
4176 size_hints
.x
= f
->display
.x
->left_pos
;
4177 size_hints
.y
= f
->display
.x
->top_pos
;
4178 size_hints
.height
= PIXEL_HEIGHT (f
);
4179 size_hints
.width
= PIXEL_WIDTH (f
);
4180 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4181 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4182 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4183 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4186 int base_width
, base_height
;
4188 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4189 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4192 int min_rows
= 0, min_cols
= 0;
4193 check_frame_size (f
, &min_rows
, &min_cols
);
4195 /* The window manager uses the base width hints to calculate the
4196 current number of rows and columns in the frame while
4197 resizing; min_width and min_height aren't useful for this
4198 purpose, since they might not give the dimensions for a
4199 zero-row, zero-column frame.
4201 We use the base_width and base_height members if we have
4202 them; otherwise, we set the min_width and min_height members
4203 to the size for a zero x zero frame. */
4206 size_hints
.flags
|= PBaseSize
;
4207 size_hints
.base_width
= base_width
;
4208 size_hints
.base_height
= base_height
;
4209 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4210 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4212 size_hints
.min_width
= base_width
;
4213 size_hints
.min_height
= base_height
;
4220 size_hints
.flags
|= prompting
;
4223 XSizeHints hints
; /* Sometimes I hate X Windows... */
4225 XGetNormalHints (x_current_display
, window
, &hints
);
4226 if (hints
.flags
& PSize
)
4227 size_hints
.flags
|= PSize
;
4228 if (hints
.flags
& PPosition
)
4229 size_hints
.flags
|= PPosition
;
4230 if (hints
.flags
& USPosition
)
4231 size_hints
.flags
|= USPosition
;
4232 if (hints
.flags
& USSize
)
4233 size_hints
.flags
|= USSize
;
4237 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4239 XSetNormalHints (x_current_display
, window
, &size_hints
);
4243 /* Used for IconicState or NormalState */
4244 x_wm_set_window_state (f
, state
)
4248 Window window
= FRAME_X_WINDOW (f
);
4250 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4251 f
->display
.x
->wm_hints
.initial_state
= state
;
4253 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4256 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4260 Window window
= FRAME_X_WINDOW (f
);
4262 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4263 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
? icon_pixmap
: None
;
4265 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4268 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4272 Window window
= FRAME_X_WINDOW (f
);
4274 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4275 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4276 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4278 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4282 /* Initialization. */
4285 x_term_init (display_name
)
4291 extern int old_fcntl_owner
;
4292 #endif /* ! defined (F_SETOWN) */
4294 x_focus_frame
= x_highlight_frame
= 0;
4296 x_current_display
= XOpenDisplay (display_name
);
4297 if (x_current_display
== 0)
4298 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4303 int hostname_size
= 256;
4305 hostname
= (char *) xmalloc (hostname_size
);
4308 XSetAfterFunction (x_current_display
, x_trace_wire
);
4311 invocation_name
= Ffile_name_nondirectory (Fcar (Vcommand_line_args
));
4313 /* Try to get the host name; if the buffer is too short, try
4314 again. Apparently, the only indication gethostname gives of
4315 whether the buffer was large enough is the presence or absence
4316 of a '\0' in the string. Eech. */
4319 gethostname (hostname
, hostname_size
- 1);
4320 hostname
[hostname_size
- 1] = '\0';
4322 /* Was the buffer large enough for gethostname to store the '\0'? */
4323 if (strlen (hostname
) < hostname_size
- 1)
4326 hostname_size
<<= 1;
4327 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4329 x_id_name
= (char *) xmalloc (XSTRING (invocation_name
)->size
4332 sprintf (x_id_name
, "%s@%s", XSTRING (invocation_name
)->data
, hostname
);
4335 /* Figure out which modifier bits mean what. */
4336 x_find_modifier_meanings ();
4338 /* Get the scrollbar cursor. */
4339 x_vertical_scrollbar_cursor
=
4340 XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4342 /* Watch for PropertyNotify events on the root window; we use them
4343 to figure out when to invalidate our cache of the cut buffers. */
4344 x_watch_cut_buffer_cache ();
4346 dup2 (ConnectionNumber (x_current_display
), 0);
4348 #ifndef SYSV_STREAMS
4349 /* Streams somehow keeps track of which descriptor number
4350 is being used to talk to X. So it is not safe to substitute
4351 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4352 close (ConnectionNumber (x_current_display
));
4353 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4354 * check the def of the macro;
4355 * it is a genuine lvalue */
4356 #endif /* SYSV_STREAMS */
4358 #endif /* ! defined (HAVE_X11) */
4361 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4362 #ifdef F_SETOWN_SOCK_NEG
4363 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4364 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4365 fcntl (0, F_SETOWN
, getpid ());
4366 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4367 #endif /* ! defined (F_SETOWN) */
4371 #endif /* ! defined (SIGIO) */
4373 /* Must use interrupt input because we cannot otherwise
4374 arrange for C-g to be noticed immediately.
4375 We cannot connect it to SIGINT. */
4376 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4378 expose_all_windows
= 0;
4380 clear_frame_hook
= XTclear_frame
;
4381 clear_end_of_line_hook
= XTclear_end_of_line
;
4382 ins_del_lines_hook
= XTins_del_lines
;
4383 change_line_highlight_hook
= XTchange_line_highlight
;
4384 insert_glyphs_hook
= XTinsert_glyphs
;
4385 write_glyphs_hook
= XTwrite_glyphs
;
4386 delete_glyphs_hook
= XTdelete_glyphs
;
4387 ring_bell_hook
= XTring_bell
;
4388 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4389 set_terminal_modes_hook
= XTset_terminal_modes
;
4390 update_begin_hook
= XTupdate_begin
;
4391 update_end_hook
= XTupdate_end
;
4392 set_terminal_window_hook
= XTset_terminal_window
;
4393 read_socket_hook
= XTread_socket
;
4394 cursor_to_hook
= XTcursor_to
;
4395 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4396 mouse_position_hook
= XTmouse_position
;
4397 frame_rehighlight_hook
= XTframe_rehighlight
;
4398 set_vertical_scrollbar_hook
= XTset_vertical_scrollbar
;
4399 condemn_scrollbars_hook
= XTcondemn_scrollbars
;
4400 redeem_scrollbar_hook
= XTredeem_scrollbar
;
4401 judge_scrollbars_hook
= XTjudge_scrollbars
;
4403 scroll_region_ok
= 1; /* we'll scroll partial frames */
4404 char_ins_del_ok
= 0; /* just as fast to write the line */
4405 line_ins_del_ok
= 1; /* we'll just blt 'em */
4406 fast_clear_end_of_line
= 1; /* X does this well */
4407 memory_below_frame
= 0; /* we don't remember what scrolls
4411 /* Note that there is no real way portable across R3/R4 to get the
4412 original error handler. */
4413 XHandleError (x_error_quitter
);
4414 XHandleIOError (x_error_quitter
);
4416 /* Disable Window Change signals; they are handled by X events. */
4418 signal (SIGWINCH
, SIG_DFL
);
4419 #endif /* ! defined (SIGWINCH) */
4421 signal (SIGPIPE
, x_connection_closed
);
4427 staticpro (&invocation_name
);
4428 invocation_name
= Qnil
;
4430 staticpro (&last_mouse_scrollbar
);
4432 #endif /* ! defined (HAVE_X11) */
4433 #endif /* ! defined (HAVE_X_WINDOWS) */