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. */
661 XClear (FRAME_X_WINDOW (f
));
663 /* We have to clear the scrollbars, too. If we have changed
664 colors or something like that, then they should be notified. */
665 x_scrollbar_clear (f
);
669 #endif /* HAVE_X11 */
675 /* Invert the middle quarter of the frame for .15 sec. */
677 /* We use the select system call to do the waiting, so we have to make sure
678 it's avaliable. If it isn't, we just won't do visual bells. */
679 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
681 /* Subtract the `struct timeval' values X and Y,
682 storing the result in RESULT.
683 Return 1 if the difference is negative, otherwise 0. */
686 timeval_subtract (result
, x
, y
)
687 struct timeval
*result
, x
, y
;
689 /* Perform the carry for the later subtraction by updating y.
690 This is safer because on some systems
691 the tv_sec member is unsigned. */
692 if (x
.tv_usec
< y
.tv_usec
)
694 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
695 y
.tv_usec
-= 1000000 * nsec
;
698 if (x
.tv_usec
- y
.tv_usec
> 1000000)
700 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
701 y
.tv_usec
+= 1000000 * nsec
;
705 /* Compute the time remaining to wait. tv_usec is certainly positive. */
706 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
707 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
709 /* Return indication of whether the result should be considered negative. */
710 return x
.tv_sec
< y
.tv_sec
;
721 /* Create a GC that will use the GXxor function to flip foreground pixels
722 into background pixels. */
726 values
.function
= GXxor
;
727 values
.foreground
= (f
->display
.x
->foreground_pixel
728 ^ f
->display
.x
->background_pixel
);
730 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
731 GCFunction
| GCForeground
, &values
);
735 int width
= PIXEL_WIDTH (f
);
736 int height
= PIXEL_HEIGHT (f
);
738 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
739 width
/4, height
/4, width
/2, height
/2);
740 XFlush (x_current_display
);
743 struct timeval wakeup
, now
;
745 gettimeofday (&wakeup
, (struct timezone
*) 0);
747 /* Compute time to wait until, propagating carry from usecs. */
748 wakeup
.tv_usec
+= 150000;
749 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
750 wakeup
.tv_usec
%= 1000000;
752 /* Keep waiting until past the time wakeup. */
755 struct timeval timeout
;
757 gettimeofday (&timeout
, (struct timezone
*)0);
759 /* In effect, timeout = wakeup - timeout.
760 Break if result would be negative. */
761 if (timeval_subtract (&timeout
, wakeup
, timeout
))
764 /* Try to wait that long--but we might wake up sooner. */
765 select (0, 0, 0, 0, &timeout
);
769 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
770 width
/4, height
/4, width
/2, height
/2);
771 XFreeGC (x_current_display
, gc
);
772 XFlush (x_current_display
);
782 /* Make audible bell. */
785 #define XRINGBELL XBell(x_current_display, 0)
786 #else /* ! defined (HAVE_X11) */
787 #define XRINGBELL XFeep(0);
788 #endif /* ! defined (HAVE_X11) */
792 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
794 XTflash (selected_frame
);
805 /* Insert and delete character.
806 These are not supposed to be used because we are supposed to turn
807 off the feature of using them. */
810 XTinsert_glyphs (start
, len
)
811 register char *start
;
824 /* Specify how many text lines, from the top of the window,
825 should be affected by insert-lines and delete-lines operations.
826 This, and those operations, are used only within an update
827 that is bounded by calls to XTupdate_begin and XTupdate_end. */
830 XTset_terminal_window (n
)
833 if (updating_frame
== 0)
836 if ((n
<= 0) || (n
> updating_frame
->height
))
837 flexlines
= updating_frame
->height
;
842 /* Perform an insert-lines operation.
843 Insert N lines at a vertical position curs_y. */
849 register int topregion
, bottomregion
;
850 register int length
, newtop
, mask
;
851 register struct frame
*f
= updating_frame
;
852 int intborder
= f
->display
.x
->internal_border_width
;
854 if (curs_y
>= flexlines
)
858 bottomregion
= flexlines
- (n
+ 1);
859 newtop
= topregion
+ n
;
860 length
= (bottomregion
- topregion
) + 1;
864 #endif /* HAVE_X11 */
866 if ((length
> 0) && (newtop
<= flexlines
))
869 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
870 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
871 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
872 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
873 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
874 CHAR_TO_PIXEL_ROW (f
, newtop
));
875 #else /* ! defined (HAVE_X11) */
876 XMoveArea (FRAME_X_WINDOW (f
),
877 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
878 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
879 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
880 length
* FONT_HEIGHT (f
->display
.x
->font
));
881 /* Now we must process any ExposeRegion events that occur
882 if the area being copied from is obscured.
883 We can't let it wait because further i/d operations
884 may want to copy this area to another area. */
886 #endif /* ! defined (HAVE_X11) */
889 newtop
= min (newtop
, (flexlines
- 1));
890 length
= newtop
- topregion
;
894 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
895 CHAR_TO_PIXEL_ROW (f
, topregion
),
896 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
897 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
898 #else /* ! defined (HAVE_X11) */
899 XPixSet (FRAME_X_WINDOW (f
),
901 CHAR_TO_PIXEL_ROW (f
, topregion
),
902 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
903 n
* FONT_HEIGHT (f
->display
.x
->font
),
904 f
->display
.x
->background_pixel
);
905 #endif /* ! defined (HAVE_X11) */
909 /* Perform a delete-lines operation, deleting N lines
910 at a vertical position curs_y. */
917 register struct frame
*f
= updating_frame
;
918 int intborder
= f
->display
.x
->internal_border_width
;
920 if (curs_y
>= flexlines
)
925 #endif /* HAVE_X11 */
927 if ((curs_y
+ n
) >= flexlines
)
929 if (flexlines
>= (curs_y
+ 1))
932 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
933 CHAR_TO_PIXEL_ROW (f
, curs_y
),
934 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
935 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
936 #else /* ! defined (HAVE_X11) */
937 XPixSet (FRAME_X_WINDOW (f
),
938 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
939 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
940 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
941 f
->display
.x
->background_pixel
);
942 #endif /* ! defined (HAVE_X11) */
948 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
949 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
951 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
952 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
953 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
954 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
955 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
957 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
958 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
959 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
960 #else /* ! defined (HAVE_X11) */
961 XMoveArea (FRAME_X_WINDOW (f
),
963 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
964 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
965 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
966 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
967 /* Now we must process any ExposeRegion events that occur
968 if the area being copied from is obscured.
969 We can't let it wait because further i/d operations
970 may want to copy this area to another area. */
972 XPixSet (FRAME_X_WINDOW (f
), intborder
,
973 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
974 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
975 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
976 #endif /* ! defined (HAVE_X11) */
980 /* Perform an insert-lines or delete-lines operation,
981 inserting N lines or deleting -N lines at vertical position VPOS. */
983 XTins_del_lines (vpos
, n
)
986 if (updating_frame
== 0)
989 /* Hide the cursor. */
990 x_display_cursor (updating_frame
, 0);
992 XTcursor_to (vpos
, 0);
1003 /* Support routines for exposure events. */
1004 static void clear_cursor ();
1006 /* Output into a rectangle of an X-window (for frame F)
1007 the characters in f->phys_lines that overlap that rectangle.
1008 TOP and LEFT are the position of the upper left corner of the rectangle.
1009 ROWS and COLS are the size of the rectangle. */
1012 dumprectangle (f
, left
, top
, cols
, rows
)
1014 register int left
, top
, cols
, rows
;
1016 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1017 int cursor_cleared
= 0;
1021 if (FRAME_GARBAGED_P (f
))
1024 /* Express rectangle as four edges, instead of position-and-size. */
1025 bottom
= top
+ rows
;
1026 right
= left
+ cols
;
1028 #ifndef HAVE_X11 /* Window manger does this for X11. */
1030 int intborder
= f
->display
.x
->internal_border_width
;
1032 /* If the rectangle includes any of the internal border area,
1033 redisplay the border emphasis. */
1034 if (top
< intborder
|| left
< intborder
1035 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1036 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1039 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1041 /* Convert rectangle edges in pixels to edges in chars.
1042 Round down for left and top, up for right and bottom. */
1043 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1044 left
= PIXEL_TO_CHAR_COL (f
, left
);
1045 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1046 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1047 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1048 right
= PIXEL_TO_CHAR_COL (f
, right
);
1050 /* Clip the rectangle to what can be visible. */
1055 if (right
> f
->width
)
1057 if (bottom
> f
->height
)
1060 /* Get size in chars of the rectangle. */
1061 cols
= right
- left
;
1062 rows
= bottom
- top
;
1064 /* If rectangle has zero area, return. */
1065 if (rows
<= 0) return;
1066 if (cols
<= 0) return;
1068 /* Turn off the cursor if it is in the rectangle.
1069 We will turn it back on afterward. */
1070 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1071 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1077 /* Display the text in the rectangle, one text line at a time. */
1079 for (y
= top
; y
< bottom
; y
++)
1081 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1083 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1087 CHAR_TO_PIXEL_COL (f
, left
),
1088 CHAR_TO_PIXEL_ROW (f
, y
),
1089 line
, min (cols
, active_frame
->used
[y
] - left
),
1090 active_frame
->highlight
[y
], f
->display
.x
->font
);
1093 /* Turn the cursor on if we turned it off. */
1096 x_display_cursor (f
, 1);
1100 /* Process all queued ExposeRegion events. */
1106 XExposeRegionEvent r
;
1108 while (dequeue_event (&r
, &x_expose_queue
))
1110 struct frame
*f
= x_window_to_frame (r
.window
);
1111 if (f
->display
.x
->icon_desc
== r
.window
)
1114 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1118 #endif /* HAVE_X11 */
1120 /* Process all expose events that are pending, for X10.
1121 Redraws the cursor if necessary on any frame that
1122 is not in the process of being updated with update_frame. */
1126 x_do_pending_expose ()
1130 Lisp_Object tail
, frame
;
1132 if (expose_all_windows
)
1134 expose_all_windows
= 0;
1135 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1137 register int temp_width
, temp_height
;
1140 frame
= XCONS (tail
)->car
;
1141 if (XTYPE (frame
) != Lisp_Frame
)
1144 if (! FRAME_X_P (f
))
1146 if (!f
->async_visible
)
1148 if (!f
->display
.x
->needs_exposure
)
1151 intborder
= f
->display
.x
->internal_border_width
;
1154 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1155 temp_width
= ((windowinfo
.width
- 2 * intborder
1156 - f
->display
.x
->v_scrollbar_width
)
1157 / FONT_WIDTH (f
->display
.x
->font
));
1158 temp_height
= ((windowinfo
.height
- 2 * intborder
1159 - f
->display
.x
->h_scrollbar_height
)
1160 / FONT_HEIGHT (f
->display
.x
->font
));
1161 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1163 change_frame_size (f
, max (1, temp_height
),
1164 max (1, temp_width
), 0, 1);
1165 x_resize_scrollbars (f
);
1167 f
->display
.x
->left_pos
= windowinfo
.x
;
1168 f
->display
.x
->top_pos
= windowinfo
.y
;
1169 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1173 f
->display
.x
->needs_exposure
= 0;
1174 if (updating_frame
!= f
)
1175 x_display_cursor (f
, 1);
1180 /* Handle any individual-rectangle expose events queued
1181 for various windows. */
1184 #else /* ! defined (HAVE_X11) */
1186 #endif /* ! defined (HAVE_X11) */
1192 frame_highlight (frame
)
1193 struct frame
*frame
;
1195 if (! EQ (Vx_no_window_manager
, Qnil
))
1196 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1197 frame
->display
.x
->border_pixel
);
1198 x_display_cursor (frame
, 1);
1202 frame_unhighlight (frame
)
1203 struct frame
*frame
;
1205 if (! EQ (Vx_no_window_manager
, Qnil
))
1206 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1207 frame
->display
.x
->border_tile
);
1208 x_display_cursor (frame
, 1);
1210 #else /* ! defined (HAVE_X11) */
1211 /* Dump the border-emphasis of frame F.
1212 If F is selected, this is a lining of the same color as the border,
1213 just within the border, occupying a portion of the internal border.
1214 If F is not selected, it is background in the same place.
1215 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1217 ALWAYS = 1 is used when a frame becomes selected or deselected.
1218 In that case, we also turn the cursor off and on again
1219 so it will appear in the proper shape (solid if selected; else hollow.) */
1222 dumpborder (f
, always
)
1226 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1227 int width
= PIXEL_WIDTH (f
);
1228 int height
= PIXEL_HEIGHT (f
);
1231 if (f
!= selected_frame
)
1236 pixel
= f
->display
.x
->background_pixel
;
1240 pixel
= f
->display
.x
->border_pixel
;
1243 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1244 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1245 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1247 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1251 x_display_cursor (f
, 1);
1253 #endif /* ! defined (HAVE_X11) */
1255 static void XTframe_rehighlight ();
1257 /* The focus has changed. Update the frames as necessary to reflect
1258 the new situation. Note that we can't change the selected frame
1259 here, because the lisp code we are interrupting might become confused.
1260 Each event gets marked with the frame in which it occured, so the
1261 lisp code can tell when the switch took place by examining the events. */
1264 x_new_focus_frame (frame
)
1265 struct frame
*frame
;
1267 struct frame
*old_focus
= x_focus_frame
;
1268 int events_enqueued
= 0;
1270 if (frame
!= x_focus_frame
)
1272 /* Set this before calling other routines, so that they see
1273 the correct value of x_focus_frame. */
1274 x_focus_frame
= frame
;
1276 if (old_focus
&& old_focus
->auto_lower
)
1277 x_lower_frame (old_focus
);
1280 selected_frame
= frame
;
1281 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1282 Lisp_Frame
, selected_frame
);
1283 Fselect_window (selected_frame
->selected_window
);
1284 choose_minibuf_frame ();
1287 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1288 x_raise_frame (x_focus_frame
);
1291 XTframe_rehighlight ();
1295 /* The focus has changed, or we have redirected a frame's focus to
1296 another frame (this happens when a frame uses a surrogate
1297 minibuffer frame). Shift the highlight as appropriate. */
1299 XTframe_rehighlight ()
1301 struct frame
*old_highlight
= x_highlight_frame
;
1306 ((XTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1307 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1309 if (! FRAME_LIVE_P (x_highlight_frame
))
1311 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1312 x_highlight_frame
= x_focus_frame
;
1316 x_highlight_frame
= 0;
1318 if (x_highlight_frame
!= old_highlight
)
1321 frame_unhighlight (old_highlight
);
1322 if (x_highlight_frame
)
1323 frame_highlight (x_highlight_frame
);
1327 /* Mouse clicks and mouse movement. Rah. */
1330 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1331 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1332 that the glyph at X, Y occupies, if BOUNDS != 0. */
1334 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1336 register unsigned int pix_x
, pix_y
;
1337 register int *x
, *y
;
1340 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1341 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1345 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1346 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1347 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1348 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1351 if (pix_x
< 0) pix_x
= 0;
1352 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1354 if (pix_y
< 0) pix_y
= 0;
1355 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1361 /* Any buttons grabbed. */
1362 unsigned int x_mouse_grabbed
;
1364 /* Which modifier keys are on which modifier bits?
1366 With each keystroke, X returns eight bits indicating which modifier
1367 keys were held down when the key was pressed. The interpretation
1368 of the top five modifier bits depends on what keys are attached
1369 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1372 x_meta_mod_mask is a mask containing the bits used for the meta key.
1373 It may have more than one bit set, if more than one modifier bit
1374 has meta keys on it. Basically, if EVENT is a KeyPress event,
1375 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1377 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1378 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1379 only be affected by the lock modifier bit if XK_Shift_Lock is in
1380 use; XK_Caps_Lock should only affect alphabetic keys. With this
1381 arrangement, the lock modifier should shift the character if
1382 (EVENT.state & x_shift_lock_mask) != 0. */
1383 static int x_meta_mod_mask
, x_shift_lock_mask
;
1385 /* Initialize mode_switch_bit and modifier_meaning. */
1387 x_find_modifier_meanings ()
1389 int min_code
, max_code
;
1392 XModifierKeymap
*mods
;
1393 int alt_mod_mask
= 0;
1395 x_meta_mod_mask
= 0;
1396 x_shift_lock_mask
= 0;
1398 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1399 syms
= XGetKeyboardMapping (x_current_display
,
1400 min_code
, max_code
- min_code
+ 1,
1402 mods
= XGetModifierMapping (x_current_display
);
1404 /* Scan the modifier table to see which modifier bits the Meta and
1405 Alt keysyms are on. */
1407 int row
, col
; /* The row and column in the modifier table. */
1409 for (row
= 3; row
< 8; row
++)
1410 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1413 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1415 /* Are any of this keycode's keysyms a meta key? */
1419 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1421 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1427 x_meta_mod_mask
|= (1 << row
);
1432 alt_mod_mask
|= (1 << row
);
1436 /* Ignore this if it's not on the lock modifier. */
1437 if ((1 << row
) == LockMask
)
1438 x_shift_lock_mask
= LockMask
;
1446 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1447 if (! x_meta_mod_mask
)
1448 x_meta_mod_mask
= alt_mod_mask
;
1450 XFree ((char *) syms
);
1451 XFreeModifiermap (mods
);
1455 /* Convert a set of X modifier bits to the proper form for a
1456 struct input_event modifiers value. */
1459 x_convert_modifiers (state
)
1462 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1463 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1464 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0));
1467 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1469 If the event is a button press, then note that we have grabbed
1473 construct_mouse_click (result
, event
, f
)
1474 struct input_event
*result
;
1475 XButtonEvent
*event
;
1478 /* Make the event type no_event; we'll change that when we decide
1480 result
->kind
= mouse_click
;
1481 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1482 result
->timestamp
= event
->time
;
1483 result
->modifiers
= (x_convert_modifiers (event
->state
)
1484 | (event
->type
== ButtonRelease
1488 /* Notice if the mouse is still grabbed. */
1489 if (event
->type
== ButtonPress
)
1491 if (! x_mouse_grabbed
)
1492 Vmouse_depressed
= Qt
;
1493 x_mouse_grabbed
|= (1 << event
->button
);
1495 else if (event
->type
== ButtonRelease
)
1497 x_mouse_grabbed
&= ~(1 << event
->button
);
1498 if (!x_mouse_grabbed
)
1499 Vmouse_depressed
= Qnil
;
1505 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1506 XFASTINT (result
->x
) = column
;
1507 XFASTINT (result
->y
) = row
;
1508 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1513 /* Mouse movement. Rah.
1515 In order to avoid asking for motion events and then throwing most
1516 of them away or busy-polling the server for mouse positions, we ask
1517 the server for pointer motion hints. This means that we get only
1518 one event per group of mouse movements. "Groups" are delimited by
1519 other kinds of events (focus changes and button clicks, for
1520 example), or by XQueryPointer calls; when one of these happens, we
1521 get another MotionNotify event the next time the mouse moves. This
1522 is at least as efficient as getting motion events when mouse
1523 tracking is on, and I suspect only negligibly worse when tracking
1526 The silly O'Reilly & Associates Nutshell guides barely document
1527 pointer motion hints at all (I think you have to infer how they
1528 work from an example), and the description of XQueryPointer doesn't
1529 mention that calling it causes you to get another motion hint from
1530 the server, which is very important. */
1532 /* Where the mouse was last time we reported a mouse event. */
1533 static FRAME_PTR last_mouse_frame
;
1534 static XRectangle last_mouse_glyph
;
1536 /* The scrollbar in which the last X motion event occurred.
1538 If the last X motion event occured in a scrollbar, we set this
1539 so XTmouse_position can know whether to report a scrollbar motion or
1542 If the last X motion event didn't occur in a scrollbar, we set this
1543 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1544 static Lisp_Object last_mouse_scrollbar
;
1546 /* This is a hack. We would really prefer that XTmouse_position would
1547 return the time associated with the position it returns, but there
1548 doesn't seem to be any way to wrest the timestamp from the server
1549 along with the position query. So, we just keep track of the time
1550 of the last movement we received, and return that in hopes that
1551 it's somewhat accurate. */
1552 static Time last_mouse_movement_time
;
1554 /* Function to report a mouse movement to the mainstream Emacs code.
1555 The input handler calls this.
1557 We have received a mouse movement event, which is given in *event.
1558 If the mouse is over a different glyph than it was last time, tell
1559 the mainstream emacs code by setting mouse_moved. If not, ask for
1560 another motion event, so we can check again the next time it moves. */
1562 note_mouse_movement (frame
, event
)
1564 XMotionEvent
*event
;
1567 last_mouse_movement_time
= event
->time
;
1569 /* Has the mouse moved off the glyph it was on at the last sighting? */
1570 if (event
->x
< last_mouse_glyph
.x
1571 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1572 || event
->y
< last_mouse_glyph
.y
1573 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1576 last_mouse_scrollbar
= Qnil
;
1580 /* It's on the same glyph. Call XQueryPointer so we'll get an
1581 event the next time the mouse moves and we can see if it's
1582 *still* on the same glyph. */
1585 XQueryPointer (event
->display
, event
->window
,
1586 (Window
*) &dummy
, (Window
*) &dummy
,
1587 &dummy
, &dummy
, &dummy
, &dummy
,
1588 (unsigned int *) &dummy
);
1592 static struct scrollbar
*x_window_to_scrollbar ();
1593 static void x_scrollbar_report_motion ();
1595 /* Return the current position of the mouse.
1597 If the mouse movement started in a scrollbar, set *f, *bar_window,
1598 and *part to the frame, window, and scrollbar part that the mouse
1599 is over. Set *x and *y to the portion and whole of the mouse's
1600 position on the scrollbar.
1602 If the mouse movement started elsewhere, set *f to the frame the
1603 mouse is on, *bar_window to nil, and *x and *y to the character cell
1606 Set *time to the server timestamp for the time at which the mouse
1607 was at this position.
1609 This clears the mouse_moved flag, so we can wait for the next mouse
1610 movement. This also calls XQueryPointer, which will cause the
1611 server to give us another MotionNotify when the mouse moves
1615 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1617 Lisp_Object
*bar_window
;
1618 enum scrollbar_part
*part
;
1620 unsigned long *time
;
1624 if (! NILP (last_mouse_scrollbar
))
1625 x_scrollbar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1631 Window dummy_window
;
1635 last_mouse_scrollbar
= Qnil
;
1637 /* Figure out which root window we're on. */
1638 XQueryPointer (x_current_display
,
1639 DefaultRootWindow (x_current_display
),
1641 /* The root window which contains the pointer. */
1644 /* Trash which we can't trust if the pointer is on
1645 a different screen. */
1648 /* The position on that root window. */
1651 /* More trash we can't trust. */
1654 /* Modifier keys and pointer buttons, about which
1656 (unsigned int *) &dummy
);
1658 /* Now we have a position on the root; find the innermost window
1659 containing the pointer. */
1663 int parent_x
, parent_y
;
1668 XTranslateCoordinates (x_current_display
,
1670 /* From-window, to-window. */
1673 /* From-position, to-position. */
1674 root_x
, root_y
, &win_x
, &win_y
,
1687 /* Now we know that:
1688 win is the innermost window containing the pointer
1689 (XTC says it has no child containing the pointer),
1690 win_x and win_y are the pointer's position in it
1691 (XTC did this the last time through), and
1692 parent_x and parent_y are the pointer's position in win's parent.
1693 (They are what win_x and win_y were when win was child.
1694 If win is the root window, it has no parent, and
1695 parent_{x,y} are invalid, but that's okay, because we'll
1696 never use them in that case.) */
1698 /* Is win one of our frames? */
1699 *f
= x_window_to_frame (win
);
1701 /* If not, is it one of our scrollbars? */
1704 struct scrollbar
*bar
= x_window_to_scrollbar (win
);
1708 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1716 pixel_to_glyph_coords (*f
, win_x
, win_y
, &win_x
, &win_y
,
1721 XSET (*x
, Lisp_Int
, win_x
);
1722 XSET (*y
, Lisp_Int
, win_y
);
1723 *time
= last_mouse_movement_time
;
1731 #else /* ! defined (HAVE_X11) */
1732 #define XEvent XKeyPressedEvent
1733 #endif /* ! defined (HAVE_X11) */
1735 /* Scrollbar support. */
1737 /* Given an X window ID, find the struct scrollbar which manages it. */
1738 static struct scrollbar
*
1739 x_window_to_scrollbar (window_id
)
1742 Lisp_Object tail
, frame
;
1744 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1746 Lisp_Object frame
= XCONS (tail
)->car
;
1747 Lisp_Object bar
, condemned
;
1749 /* All elements of Vframe_list should be frames. */
1750 if (XTYPE (frame
) != Lisp_Frame
)
1753 /* Scan this frame's scrollbar list for a scrollbar with the
1755 condemned
= FRAME_CONDEMNED_SCROLLBARS (XFRAME (frame
));
1756 for (bar
= FRAME_SCROLLBARS (XFRAME (frame
));
1757 /* This trick allows us to search both the ordinary and
1758 condemned scrollbar lists with one loop. */
1759 ! NILP (bar
) || (bar
= condemned
, condemned
= Qnil
, ! NILP (bar
));
1760 bar
= XSCROLLBAR(bar
)->next
)
1761 if (SCROLLBAR_X_WINDOW (XSCROLLBAR (bar
)) == window_id
)
1762 return XSCROLLBAR (bar
);
1768 /* Open a new X window to serve as a scrollbar, and return the
1769 scrollbar vector for it. */
1770 static struct scrollbar
*
1771 x_scrollbar_create (window
, top
, left
, width
, height
)
1772 struct window
*window
;
1773 int top
, left
, width
, height
;
1775 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1776 struct scrollbar
*bar
=
1777 XSCROLLBAR (Fmake_vector (make_number (SCROLLBAR_VEC_SIZE
), Qnil
));
1782 XSetWindowAttributes a
;
1785 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1786 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1787 | ButtonMotionMask
| PointerMotionHintMask
1789 a
.cursor
= x_vertical_scrollbar_cursor
;
1791 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1793 SET_SCROLLBAR_X_WINDOW
1795 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1797 /* Position and size of scrollbar. */
1798 left
, top
, width
, height
,
1800 /* Border width, depth, class, and visual. */
1801 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1807 XSET (bar
->window
, Lisp_Window
, window
);
1808 XSET (bar
->top
, Lisp_Int
, top
);
1809 XSET (bar
->left
, Lisp_Int
, left
);
1810 XSET (bar
->width
, Lisp_Int
, width
);
1811 XSET (bar
->height
, Lisp_Int
, height
);
1812 XSET (bar
->start
, Lisp_Int
, 0);
1813 XSET (bar
->end
, Lisp_Int
, 0);
1814 bar
->dragging
= Qnil
;
1816 /* Add bar to its frame's list of scroll bars. */
1817 bar
->next
= FRAME_SCROLLBARS (frame
);
1819 XSET (FRAME_SCROLLBARS (frame
), Lisp_Vector
, bar
);
1820 if (! NILP (bar
->next
))
1821 XSET (XSCROLLBAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1823 XMapWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
));
1830 /* Draw BAR's handle in the proper position.
1831 If the handle is already drawn from START to END, don't bother
1832 redrawing it, unless REBUILD is non-zero; in that case, always
1833 redraw it. (REBUILD is handy for drawing the handle after expose
1836 Normally, we want to constrain the start and end of the handle to
1837 fit inside its rectangle, but if the user is dragging the scrollbar
1838 handle, we want to let them drag it down all the way, so that the
1839 bar's top is as far down as it goes; otherwise, there's no way to
1840 move to the very end of the buffer. */
1842 x_scrollbar_set_handle (bar
, start
, end
, rebuild
)
1843 struct scrollbar
*bar
;
1847 int dragging
= ! NILP (bar
->dragging
);
1848 Window w
= SCROLLBAR_X_WINDOW (bar
);
1849 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1851 /* If the display is already accurate, do nothing. */
1853 && start
== XINT (bar
->start
)
1854 && end
== XINT (bar
->end
))
1860 int inside_width
= VERTICAL_SCROLLBAR_INSIDE_WIDTH (XINT (bar
->width
));
1861 int inside_height
= VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
1862 int top_range
= VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
1864 /* Make sure the values are reasonable, and try to preserve
1865 the distance between start and end. */
1867 int length
= end
- start
;
1871 else if (start
> top_range
)
1873 end
= start
+ length
;
1877 else if (end
> top_range
&& ! dragging
)
1881 /* Store the adjusted setting in the scrollbar. */
1882 XSET (bar
->start
, Lisp_Int
, start
);
1883 XSET (bar
->end
, Lisp_Int
, end
);
1885 /* Clip the end position, just for display. */
1886 if (end
> top_range
)
1889 /* Draw bottom positions VERTICAL_SCROLLBAR_MIN_HANDLE pixels
1890 below top positions, to make sure the handle is always at least
1891 that many pixels tall. */
1892 end
+= VERTICAL_SCROLLBAR_MIN_HANDLE
;
1894 /* Draw the empty space above the handle. Note that we can't clear
1895 zero-height areas; that means "clear to end of window." */
1897 XClearArea (x_current_display
, w
,
1899 /* x, y, width, height, and exposures. */
1900 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1901 VERTICAL_SCROLLBAR_TOP_BORDER
,
1902 inside_width
, start
,
1905 /* Draw the handle itself. */
1906 XFillRectangle (x_current_display
, w
, gc
,
1908 /* x, y, width, height */
1909 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1910 VERTICAL_SCROLLBAR_TOP_BORDER
+ start
,
1911 inside_width
, end
- start
);
1914 /* Draw the empty space below the handle. Note that we can't
1915 clear zero-height areas; that means "clear to end of window." */
1916 if (end
< inside_height
)
1917 XClearArea (x_current_display
, w
,
1919 /* x, y, width, height, and exposures. */
1920 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1921 VERTICAL_SCROLLBAR_TOP_BORDER
+ end
,
1922 inside_width
, inside_height
- end
,
1930 /* Move a scrollbar around on the screen, to accomodate changing
1931 window configurations. */
1933 x_scrollbar_move (bar
, top
, left
, width
, height
)
1934 struct scrollbar
*bar
;
1935 int top
, left
, width
, height
;
1941 unsigned int mask
= 0;
1948 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
1949 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
1950 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
1951 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
1954 XConfigureWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
),
1958 XSET (bar
->left
, Lisp_Int
, left
);
1959 XSET (bar
->top
, Lisp_Int
, top
);
1960 XSET (bar
->width
, Lisp_Int
, width
);
1961 XSET (bar
->height
, Lisp_Int
, height
);
1966 /* Destroy the X window for BAR, and set its Emacs window's scrollbar
1969 x_scrollbar_remove (bar
)
1970 struct scrollbar
*bar
;
1972 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1976 /* Destroy the window. */
1977 XDestroyWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
));
1979 /* Disassociate this scrollbar from its window. */
1980 XWINDOW (bar
->window
)->vertical_scrollbar
= Qnil
;
1985 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1986 that we are displaying PORTION characters out of a total of WHOLE
1987 characters, starting at POSITION. If WINDOW has no scrollbar,
1990 XTset_vertical_scrollbar (window
, portion
, whole
, position
)
1991 struct window
*window
;
1992 int portion
, whole
, position
;
1994 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1995 int top
= XINT (window
->top
);
1996 int left
= WINDOW_VERTICAL_SCROLLBAR_COLUMN (window
);
1997 int height
= WINDOW_VERTICAL_SCROLLBAR_HEIGHT (window
);
1999 /* Where should this scrollbar be, pixelwise? */
2000 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2001 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2002 int pixel_width
= VERTICAL_SCROLLBAR_PIXEL_WIDTH (f
);
2003 int pixel_height
= VERTICAL_SCROLLBAR_PIXEL_HEIGHT (f
, height
);
2005 struct scrollbar
*bar
;
2007 /* Does the scrollbar exist yet? */
2008 if (NILP (window
->vertical_scrollbar
))
2009 bar
= x_scrollbar_create (window
,
2010 pixel_top
, pixel_left
,
2011 pixel_width
, pixel_height
);
2014 /* It may just need to be moved and resized. */
2015 bar
= XSCROLLBAR (window
->vertical_scrollbar
);
2016 x_scrollbar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2019 /* Set the scrollbar's current state, unless we're currently being
2021 if (NILP (bar
->dragging
))
2024 VERTICAL_SCROLLBAR_TOP_RANGE (pixel_height
);
2027 x_scrollbar_set_handle (bar
, 0, top_range
, 0);
2030 int start
= (position
* top_range
) / whole
;
2031 int end
= ((position
+ portion
) * top_range
) / whole
;
2033 x_scrollbar_set_handle (bar
, start
, end
, 0);
2037 XSET (window
->vertical_scrollbar
, Lisp_Vector
, bar
);
2041 /* The following three hooks are used when we're doing a thorough
2042 redisplay of the frame. We don't explicitly know which scrollbars
2043 are going to be deleted, because keeping track of when windows go
2044 away is a real pain - "Can you say set-window-configuration, boys
2045 and girls?" Instead, we just assert at the beginning of redisplay
2046 that *all* scrollbars are to be removed, and then save a scrollbar
2047 from the fiery pit when we actually redisplay its window. */
2049 /* Arrange for all scrollbars on FRAME to be removed at the next call
2050 to `*judge_scrollbars_hook'. A scrollbar may be spared if
2051 `*redeem_scrollbar_hook' is applied to its window before the judgement. */
2053 XTcondemn_scrollbars (frame
)
2056 /* The condemned list should be empty at this point; if it's not,
2057 then the rest of Emacs isn't using the condemn/redeem/judge
2058 protocol correctly. */
2059 if (! NILP (FRAME_CONDEMNED_SCROLLBARS (frame
)))
2062 /* Move them all to the "condemned" list. */
2063 FRAME_CONDEMNED_SCROLLBARS (frame
) = FRAME_SCROLLBARS (frame
);
2064 FRAME_SCROLLBARS (frame
) = Qnil
;
2067 /* Unmark WINDOW's scrollbar for deletion in this judgement cycle.
2068 Note that WINDOW isn't necessarily condemned at all. */
2070 XTredeem_scrollbar (window
)
2071 struct window
*window
;
2073 struct scrollbar
*bar
;
2075 /* We can't redeem this window's scrollbar if it doesn't have one. */
2076 if (NILP (window
->vertical_scrollbar
))
2079 bar
= XSCROLLBAR (window
->vertical_scrollbar
);
2081 /* Unlink it from the condemned list. */
2083 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2085 if (NILP (bar
->prev
))
2087 /* If the prev pointer is nil, it must be the first in one of
2089 if (EQ (FRAME_SCROLLBARS (f
), window
->vertical_scrollbar
))
2090 /* It's not condemned. Everything's fine. */
2092 else if (EQ (FRAME_CONDEMNED_SCROLLBARS (f
),
2093 window
->vertical_scrollbar
))
2094 FRAME_CONDEMNED_SCROLLBARS (f
) = bar
->next
;
2096 /* If its prev pointer is nil, it must be at the front of
2097 one or the other! */
2101 XSCROLLBAR (bar
->prev
)->next
= bar
->next
;
2103 if (! NILP (bar
->next
))
2104 XSCROLLBAR (bar
->next
)->prev
= bar
->prev
;
2106 bar
->next
= FRAME_SCROLLBARS (f
);
2108 XSET (FRAME_SCROLLBARS (f
), Lisp_Vector
, bar
);
2109 if (! NILP (bar
->next
))
2110 XSET (XSCROLLBAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2114 /* Remove all scrollbars on FRAME that haven't been saved since the
2115 last call to `*condemn_scrollbars_hook'. */
2117 XTjudge_scrollbars (f
)
2120 Lisp_Object bar
, next
;
2122 bar
= FRAME_CONDEMNED_SCROLLBARS (f
);
2124 /* Clear out the condemned list now so we won't try to process any
2125 more events on the hapless scrollbars. */
2126 FRAME_CONDEMNED_SCROLLBARS (f
) = Qnil
;
2128 for (; ! NILP (bar
); bar
= next
)
2130 struct scrollbar
*b
= XSCROLLBAR (bar
);
2132 x_scrollbar_remove (b
);
2135 b
->next
= b
->prev
= Qnil
;
2138 /* Now there should be no references to the condemned scrollbars,
2139 and they should get garbage-collected. */
2143 /* Handle an Expose or GraphicsExpose event on a scrollbar. */
2145 x_scrollbar_expose (bar
, event
)
2146 struct scrollbar
*bar
;
2149 Window w
= SCROLLBAR_X_WINDOW (bar
);
2150 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2154 x_scrollbar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2156 /* Draw a one-pixel border just inside the edges of the scrollbar. */
2157 XDrawRectangle (x_current_display
, w
, gc
,
2159 /* x, y, width, height */
2160 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2162 /* Draw another line to make the extra-thick border on the right. */
2163 XFillRectangle (x_current_display
, w
, gc
,
2165 /* x, y, width, height */
2166 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2171 /* Handle a mouse click on the scrollbar BAR. If *EMACS_EVENT's kind
2172 is set to something other than no_event, it is enqueued. */
2174 x_scrollbar_handle_click (bar
, event
, emacs_event
)
2175 struct scrollbar
*bar
;
2177 struct input_event
*emacs_event
;
2179 if (XTYPE (bar
->window
) != Lisp_Window
)
2182 emacs_event
->kind
= scrollbar_click
;
2183 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2184 emacs_event
->modifiers
=
2185 (x_convert_modifiers (event
->xbutton
.state
)
2186 | (event
->type
== ButtonRelease
2189 emacs_event
->frame_or_window
= bar
->window
;
2190 emacs_event
->timestamp
= event
->xbutton
.time
;
2192 int internal_height
=
2193 VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
2195 VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
2196 int y
= event
->xbutton
.y
- VERTICAL_SCROLLBAR_TOP_BORDER
;
2199 if (y
> top_range
) y
= top_range
;
2201 if (y
< XINT (bar
->start
))
2202 emacs_event
->part
= scrollbar_above_handle
;
2203 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLLBAR_MIN_HANDLE
)
2204 emacs_event
->part
= scrollbar_handle
;
2206 emacs_event
->part
= scrollbar_below_handle
;
2208 /* If the user has just clicked on the handle, record where they're
2210 if (event
->type
== ButtonPress
2211 && emacs_event
->part
== scrollbar_handle
)
2212 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2214 /* If the user has released the handle, set it to its final position. */
2215 if (event
->type
== ButtonRelease
2216 && ! NILP (bar
->dragging
))
2218 int new_start
= y
- XINT (bar
->dragging
);
2219 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2221 x_scrollbar_set_handle (bar
, new_start
, new_end
, 0);
2222 bar
->dragging
= Qnil
;
2225 /* Clicks on the handle are always reported as occuring at the top of
2227 if (emacs_event
->part
== scrollbar_handle
)
2228 emacs_event
->x
= bar
->start
;
2230 XSET (emacs_event
->x
, Lisp_Int
, y
);
2232 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2236 /* Handle some mouse motion while someone is dragging the scrollbar. */
2238 x_scrollbar_note_movement (bar
, event
)
2239 struct scrollbar
*bar
;
2242 last_mouse_movement_time
= event
->xmotion
.time
;
2245 XSET (last_mouse_scrollbar
, Lisp_Vector
, bar
);
2247 /* If we're dragging the bar, display it. */
2248 if (! NILP (bar
->dragging
))
2250 /* Where should the handle be now? */
2251 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2253 if (new_start
!= XINT (bar
->start
))
2255 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2257 x_scrollbar_set_handle (bar
, new_start
, new_end
, 0);
2261 /* Call XQueryPointer so we'll get an event the next time the mouse
2262 moves and we can see *still* on the same position. */
2266 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2267 (Window
*) &dummy
, (Window
*) &dummy
,
2268 &dummy
, &dummy
, &dummy
, &dummy
,
2269 (unsigned int *) &dummy
);
2273 /* Return information to the user about the current position of the mouse
2274 on the scrollbar. */
2276 x_scrollbar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2278 Lisp_Object
*bar_window
;
2279 enum scrollbar_part
*part
;
2281 unsigned long *time
;
2283 struct scrollbar
*bar
= XSCROLLBAR (last_mouse_scrollbar
);
2288 /* Get the mouse's position relative to the scrollbar window, and
2291 Window dummy_window
;
2293 unsigned int dummy_mask
;
2295 if (! XQueryPointer (x_current_display
,
2296 SCROLLBAR_X_WINDOW (bar
),
2298 /* Root, child, root x and root y. */
2299 &dummy_window
, &dummy_window
,
2300 &dummy_coord
, &dummy_coord
,
2302 /* Position relative to scrollbar. */
2305 /* Mouse buttons and modifier keys. */
2314 int inside_height
= VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
2315 int top_range
= VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
2317 win_y
-= VERTICAL_SCROLLBAR_TOP_BORDER
;
2319 if (! NILP (bar
->dragging
))
2320 win_y
-= XINT (bar
->dragging
);
2324 if (win_y
> top_range
)
2327 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2328 *bar_window
= bar
->window
;
2330 if (! NILP (bar
->dragging
))
2331 *part
= scrollbar_handle
;
2332 else if (win_y
< XINT (bar
->start
))
2333 *part
= scrollbar_above_handle
;
2334 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLLBAR_MIN_HANDLE
)
2335 *part
= scrollbar_handle
;
2337 *part
= scrollbar_below_handle
;
2339 XSET (*x
, Lisp_Int
, win_y
);
2340 XSET (*y
, Lisp_Int
, top_range
);
2341 *time
= last_mouse_movement_time
;
2345 last_mouse_scrollbar
= Qnil
;
2352 /* The screen has been cleared so we may have changed foreground or
2353 background colors, and the scrollbars may need to be redrawn.
2354 Clear out the scrollbars, and ask for expose events, so we can
2357 x_scrollbar_clear (f
)
2362 for (bar
= FRAME_SCROLLBARS (f
);
2363 XTYPE (bar
) == Lisp_Vector
;
2364 bar
= XSCROLLBAR (bar
)->next
)
2365 XClearArea (x_current_display
, SCROLLBAR_X_WINDOW (XSCROLLBAR (bar
)),
2371 /* The main X event-reading loop - XTread_socket. */
2373 /* Timestamp of enter window event. This is only used by XTread_socket,
2374 but we have to put it out here, since static variables within functions
2375 sometimes don't work. */
2376 static Time enter_timestamp
;
2378 /* This holds the state XLookupString needs to implement dead keys
2379 and other tricks known as "compose processing". _X Window System_
2380 says that a portable program can't use this, but Stephen Gildea assures
2381 me that letting the compiler initialize it to zeros will work okay.
2383 This must be defined outside of XTread_socket, for the same reasons
2384 given for enter_timestamp, above. */
2385 static XComposeStatus compose_status
;
2387 /* Communication with window managers. */
2388 Atom Xatom_wm_protocols
;
2390 /* Kinds of protocol things we may receive. */
2391 Atom Xatom_wm_take_focus
;
2392 Atom Xatom_wm_save_yourself
;
2393 Atom Xatom_wm_delete_window
;
2395 /* Other WM communication */
2396 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2397 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2399 /* Read events coming from the X server.
2400 This routine is called by the SIGIO handler.
2401 We return as soon as there are no more events to be read.
2403 Events representing keys are stored in buffer BUFP,
2404 which can hold up to NUMCHARS characters.
2405 We return the number of characters stored into the buffer,
2406 thus pretending to be `read'.
2408 WAITP is nonzero if we should block until input arrives.
2409 EXPECTED is nonzero if the caller knows input is available. */
2412 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2414 register struct input_event
*bufp
;
2415 register int numchars
;
2422 int items_pending
; /* How many items are in the X queue. */
2429 if (x_input_blocked
)
2431 x_pending_input
= 1;
2435 x_pending_input
= 0;
2439 abort (); /* Don't think this happens. */
2442 /* If available, Xlib uses FIOSNBIO to make the socket
2443 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2444 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2445 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2446 fcntl (fileno (stdin
), F_SETFL
, 0);
2447 #endif /* ! defined (FIOSNBIO) */
2451 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2453 extern int read_alarm_should_throw
;
2454 read_alarm_should_throw
= 1;
2455 XPeekEvent (XDISPLAY
&event
);
2456 read_alarm_should_throw
= 0;
2458 #endif /* HAVE_SELECT */
2461 while (XStuffPending () != 0)
2463 XNextEvent (XDISPLAY
&event
);
2471 if (event
.xclient
.message_type
== Xatom_wm_protocols
2472 && event
.xclient
.format
== 32)
2474 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2476 f
= x_window_to_frame (event
.xclient
.window
);
2478 x_focus_on_frame (f
);
2479 /* Not certain about handling scrollbars here */
2481 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2483 /* Save state modify the WM_COMMAND property to
2484 something which can reinstate us. This notifies
2485 the session manager, who's looking for such a
2486 PropertyNotify. Can restart processing when
2487 a keyboard or mouse event arrives. */
2492 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2494 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2502 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2505 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2509 new_x
= event
.xclient
.data
.s
[0];
2510 new_y
= event
.xclient
.data
.s
[1];
2515 case SelectionClear
: /* Someone has grabbed ownership. */
2516 x_disown_selection (event
.xselectionclear
.window
,
2517 event
.xselectionclear
.selection
,
2518 event
.xselectionclear
.time
);
2521 case SelectionRequest
: /* Someone wants our selection. */
2522 x_answer_selection_request (event
);
2525 case PropertyNotify
:
2527 /* If we're being told about a root window property, then it's
2528 a cut buffer change. */
2529 if (event
.xproperty
.window
== ROOT_WINDOW
)
2530 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2532 /* Otherwise, we're probably handling an incremental
2533 selection transmission. */
2536 /* If we were to do this synchronously, there'd be no worry
2537 about re-selecting. */
2538 x_send_incremental (event
);
2543 f
= x_window_to_frame (event
.xexpose
.window
);
2546 if (f
->async_visible
== 0)
2548 f
->async_visible
= 1;
2549 f
->async_iconified
= 0;
2550 SET_FRAME_GARBAGED (f
);
2554 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2555 event
.xexpose
.x
, event
.xexpose
.y
,
2556 event
.xexpose
.width
, event
.xexpose
.height
);
2561 struct scrollbar
*bar
2562 = x_window_to_scrollbar (event
.xexpose
.window
);
2565 x_scrollbar_expose (bar
, &event
);
2569 case GraphicsExpose
: /* This occurs when an XCopyArea's
2570 source area was obscured or not
2572 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2576 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2577 event
.xgraphicsexpose
.width
,
2578 event
.xgraphicsexpose
.height
);
2582 case NoExpose
: /* This occurs when an XCopyArea's
2583 source area was completely
2586 #else /* ! defined (HAVE_X11) */
2588 if (event
.subwindow
!= 0)
2589 break; /* duplicate event */
2590 f
= x_window_to_frame (event
.window
);
2591 if (event
.window
== f
->display
.x
->icon_desc
)
2594 f
->async_iconified
= 1;
2596 if (event
.window
== FRAME_X_WINDOW (f
))
2598 /* Say must check all windows' needs_exposure flags. */
2599 expose_all_windows
= 1;
2600 f
->display
.x
->needs_exposure
= 1;
2601 f
->async_visible
= 1;
2606 if (event
.subwindow
!= 0)
2607 break; /* duplicate event */
2608 f
= x_window_to_frame (event
.window
);
2609 if (event
.window
== f
->display
.x
->icon_desc
)
2614 /* If window already needs full redraw, ignore this rectangle. */
2615 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2617 /* Put the event on the queue of rectangles to redraw. */
2618 if (enqueue_event (&event
, &x_expose_queue
))
2619 /* If it is full, we can't record the rectangle,
2620 so redraw this entire window. */
2622 /* Say must check all windows' needs_exposure flags. */
2623 expose_all_windows
= 1;
2624 f
->display
.x
->needs_exposure
= 1;
2629 /* This should happen only when we are expecting it,
2630 in x_read_exposes. */
2632 #endif /* ! defined (HAVE_X11) */
2636 f
= x_window_to_frame (event
.xunmap
.window
);
2637 if (f
) /* F may no longer exist if
2638 the frame was deleted. */
2640 /* While a frame is unmapped, display generation is
2641 disabled; you don't want to spend time updating a
2642 display that won't ever be seen. */
2643 f
->async_visible
= 0;
2648 f
= x_window_to_frame (event
.xmap
.window
);
2651 f
->async_visible
= 1;
2652 f
->async_iconified
= 0;
2654 /* wait_reading_process_input will notice this and update
2655 the frame's display structures. */
2656 SET_FRAME_GARBAGED (f
);
2660 /* Turn off processing if we become fully obscured. */
2661 case VisibilityNotify
:
2664 #else /* ! defined (HAVE_X11) */
2666 f
= x_window_to_frame (event
.window
);
2667 if (event
.window
== f
->display
.x
->icon_desc
)
2668 f
->async_iconified
= 0;
2669 if (event
.window
== FRAME_X_WINDOW (f
))
2670 f
->async_visible
= 0;
2672 #endif /* ! defined (HAVE_X11) */
2676 f
= x_window_to_frame (event
.xkey
.window
);
2681 char copy_buffer
[80];
2682 int modifiers
= event
.xkey
.state
;
2684 /* Some keyboards generate different characters
2685 depending on the state of the meta key, in an attempt
2686 to support non-English typists. It would be nice to
2687 keep this functionality somehow, but for now, we will
2688 just clear the meta-key flag to get the 'pure' character. */
2689 event
.xkey
.state
&= ~Mod1Mask
;
2691 /* This will have to go some day... */
2693 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2696 /* Strip off the vendor-specific keysym bit, and take a shot
2697 at recognizing the codes. HP servers have extra keysyms
2698 that fit into the MiscFunctionKey category. */
2703 if (IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2704 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < 0xff80 */
2705 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2706 || IsFunctionKey (keysym
)) /* 0xffbe <= x < 0xffe1 */
2708 bufp
->kind
= non_ascii_keystroke
;
2709 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff50);
2710 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2711 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2712 bufp
->timestamp
= event
.xkey
.time
;
2717 else if (numchars
> nbytes
)
2723 if (modifiers
& x_meta_mod_mask
)
2724 *copy_buffer
|= METABIT
;
2725 bufp
->kind
= ascii_keystroke
;
2726 XSET (bufp
->code
, Lisp_Int
, *copy_buffer
);
2727 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2728 bufp
->timestamp
= event
.xkey
.time
;
2732 for (i
= nbytes
- 1; i
> 1; i
--)
2734 bufp
->kind
= ascii_keystroke
;
2735 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2736 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2737 bufp
->timestamp
= event
.xkey
.time
;
2747 #else /* ! defined (HAVE_X11) */
2750 register char *where_mapping
;
2752 f
= x_window_to_frame (event
.window
);
2753 /* Ignore keys typed on icon windows. */
2754 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2756 where_mapping
= XLookupMapping (&event
, &nbytes
);
2757 /* Nasty fix for arrow keys */
2758 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2760 switch (event
.detail
& 0xff)
2762 case KC_CURSOR_LEFT
:
2763 where_mapping
= "\002";
2765 case KC_CURSOR_RIGHT
:
2766 where_mapping
= "\006";
2769 where_mapping
= "\020";
2771 case KC_CURSOR_DOWN
:
2772 where_mapping
= "\016";
2777 if (numchars
- nbytes
> 0)
2781 for (i
= 0; i
< nbytes
; i
++)
2783 bufp
->kind
= ascii_keystroke
;
2784 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2785 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2786 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2794 #endif /* ! defined (HAVE_X11) */
2798 /* Here's a possible interpretation of the whole
2799 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2800 FocusIn event, you have to get a FocusOut event before you
2801 relinquish the focus. If you haven't received a FocusIn event,
2802 then a mere LeaveNotify is enough to free you. */
2805 f
= x_window_to_frame (event
.xcrossing
.window
);
2807 if (event
.xcrossing
.focus
) /* Entered Window */
2809 /* Avoid nasty pop/raise loops. */
2810 if (f
&& (!(f
->auto_raise
)
2812 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
2814 x_new_focus_frame (f
);
2815 enter_timestamp
= event
.xcrossing
.time
;
2818 else if (f
== x_focus_frame
)
2819 x_new_focus_frame (0);
2824 f
= x_window_to_frame (event
.xfocus
.window
);
2825 if (event
.xfocus
.detail
!= NotifyPointer
)
2826 x_focus_event_frame
= f
;
2828 x_new_focus_frame (f
);
2833 f
= x_window_to_frame (event
.xcrossing
.window
);
2835 if (event
.xcrossing
.focus
)
2837 if (! x_focus_event_frame
)
2838 x_new_focus_frame (0);
2840 x_new_focus_frame (f
);
2844 if (f
== x_focus_event_frame
)
2845 x_focus_event_frame
= 0;
2846 if (f
== x_focus_frame
)
2847 x_new_focus_frame (0);
2852 f
= x_window_to_frame (event
.xfocus
.window
);
2853 if (event
.xfocus
.detail
!= NotifyPointer
2854 && f
== x_focus_event_frame
)
2855 x_focus_event_frame
= 0;
2856 if (f
&& f
== x_focus_frame
)
2857 x_new_focus_frame (0);
2860 #else /* ! defined (HAVE_X11) */
2863 if ((event
.detail
& 0xFF) == 1)
2864 break; /* Coming from our own subwindow */
2865 if (event
.subwindow
!= 0)
2866 break; /* Entering our own subwindow. */
2869 f
= x_window_to_frame (event
.window
);
2872 x_new_focus_frame (f
);
2877 if ((event
.detail
& 0xFF) == 1)
2878 break; /* Entering our own subwindow */
2879 if (event
.subwindow
!= 0)
2880 break; /* Leaving our own subwindow. */
2883 if (x_focus_frame
== 0
2884 && x_input_frame
!= 0
2885 && x_input_frame
== x_window_to_frame (event
.window
)
2886 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
2891 frame_unhighlight (f
);
2894 #endif /* ! defined (HAVE_X11) */
2899 f
= x_window_to_frame (event
.xmotion
.window
);
2901 note_mouse_movement (f
, &event
.xmotion
);
2904 struct scrollbar
*bar
=
2905 x_window_to_scrollbar (event
.xmotion
.window
);
2908 x_scrollbar_note_movement (bar
, &event
);
2913 case ConfigureNotify
:
2914 f
= x_window_to_frame (event
.xconfigure
.window
);
2917 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
2918 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
2920 /* Even if the number of character rows and columns has
2921 not changed, the font size may have changed, so we need
2922 to check the pixel dimensions as well. */
2923 if (columns
!= f
->width
2924 || rows
!= f
->height
2925 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
2926 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
2928 change_frame_size (f
, rows
, columns
, 0, 1);
2929 SET_FRAME_GARBAGED (f
);
2932 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
2933 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
2934 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
2935 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
2942 /* If we decide we want to generate an event to be seen
2943 by the rest of Emacs, we put it here. */
2944 struct input_event emacs_event
;
2945 emacs_event
.kind
= no_event
;
2947 f
= x_window_to_frame (event
.xbutton
.window
);
2950 if (!x_focus_frame
|| (f
== x_focus_frame
))
2951 construct_mouse_click (&emacs_event
,
2952 &event
, f
, Qnil
, 0);
2956 struct scrollbar
*bar
=
2957 x_window_to_scrollbar (event
.xbutton
.window
);
2960 x_scrollbar_handle_click (bar
, &event
, &emacs_event
);
2963 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
2965 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
2973 #else /* ! defined (HAVE_X11) */
2975 case ButtonReleased
:
2976 f
= x_window_to_frame (event
.window
);
2979 if (event
.window
== f
->display
.x
->icon_desc
)
2981 x_make_frame_visible (f
);
2983 if (warp_mouse_on_deiconify
)
2984 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
2987 if (event
.window
== FRAME_X_WINDOW (f
))
2993 enqueue_event (&event
, &x_mouse_queue
);
2996 bufp
->kind
= ascii_keystroke
;
2997 bufp
->code
= (char) 'X' & 037; /* C-x */
2998 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2999 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3002 bufp
->kind
= ascii_keystroke
;
3003 bufp
->code
= (char) 0; /* C-@ */
3004 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3005 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3012 #endif /* ! defined (HAVE_X11) */
3016 case CirculateNotify
:
3018 case CirculateRequest
:
3021 #endif /* ! defined (HAVE_X11) */
3024 /* Someone has changed the keyboard mapping - update the
3026 switch (event
.xmapping
.request
)
3028 case MappingModifier
:
3029 x_find_modifier_meanings ();
3030 /* This is meant to fall through. */
3031 case MappingKeyboard
:
3032 XRefreshKeyboardMapping (&event
.xmapping
);
3043 if (expected
&& ! event_found
)
3045 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3046 there is an EOF condition; in other words, that X has died.
3047 Act as if there had been a hangup. */
3049 int fd
= ConnectionNumber (x_current_display
);
3052 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3054 && !XStuffPending ())
3055 kill (getpid (), SIGHUP
);
3057 #endif /* ! defined (HAVE_SELECT) */
3061 if (updating_frame
== 0)
3062 x_do_pending_expose ();
3070 /* Read and process only Expose events
3071 until we get an ExposeCopy event; then return.
3072 This is used in insert/delete line.
3073 We assume input is already blocked. */
3079 XKeyPressedEvent event
;
3083 /* while there are more events*/
3084 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3088 if (event
.subwindow
!= 0)
3089 break; /* duplicate event */
3090 f
= x_window_to_frame (event
.window
);
3091 if (event
.window
== f
->display
.x
->icon_desc
)
3096 if (event
.window
== FRAME_X_WINDOW (f
))
3098 expose_all_windows
= 1;
3099 f
->display
.x
->needs_exposure
= 1;
3105 if (event
.subwindow
!= 0)
3106 break; /* duplicate event */
3107 f
= x_window_to_frame (event
.window
);
3108 if (event
.window
== f
->display
.x
->icon_desc
)
3113 /* If window already needs full redraw, ignore this rectangle. */
3114 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3116 /* Put the event on the queue of rectangles to redraw. */
3117 if (enqueue_event (&event
, &x_expose_queue
))
3118 /* If it is full, we can't record the rectangle,
3119 so redraw this entire window. */
3121 /* Say must check all windows' needs_exposure flags. */
3122 expose_all_windows
= 1;
3123 f
->display
.x
->needs_exposure
= 1;
3132 #endif /* HAVE_X11 */
3135 /* Drawing the cursor. */
3138 /* Draw a hollow box cursor. Don't change the inside of the box. */
3144 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3145 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3146 int width
= FONT_WIDTH (f
->display
.x
->font
);
3147 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3150 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3151 f
->display
.x
->cursor_gc
,
3152 left
, top
, width
- 1, height
- 1);
3153 #else /* ! defined (HAVE_X11) */
3154 XPixSet (FRAME_X_WINDOW (f
),
3155 left
, top
, width
, 1,
3156 f
->display
.x
->cursor_pixel
);
3158 XPixSet (FRAME_X_WINDOW (f
),
3159 left
, top
, 1, height
,
3160 f
->display
.x
->cursor_pixel
);
3162 XPixSet (FRAME_X_WINDOW (f
),
3163 left
+width
-1, top
, 1, height
,
3164 f
->display
.x
->cursor_pixel
);
3166 XPixSet (FRAME_X_WINDOW (f
),
3167 left
, top
+height
-1, width
, 1,
3168 f
->display
.x
->cursor_pixel
);
3169 #endif /* ! defined (HAVE_X11) */
3172 /* Clear the cursor of frame F to background color,
3173 and mark the cursor as not shown.
3174 This is used when the text where the cursor is
3175 is about to be rewritten. */
3183 if (! FRAME_VISIBLE_P (f
)
3184 || f
->phys_cursor_x
< 0)
3188 x_display_cursor (f
, 0);
3189 #else /* ! defined (HAVE_X11) */
3190 XPixSet (FRAME_X_WINDOW (f
),
3191 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3192 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3193 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3194 f
->display
.x
->background_pixel
);
3195 #endif /* ! defined (HAVE_X11) */
3196 f
->phys_cursor_x
= -1;
3199 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3200 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3204 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3211 CHAR_TO_PIXEL_COL (f
, column
),
3212 CHAR_TO_PIXEL_ROW (f
, row
),
3213 &glyph
, 1, highlight
, f
->display
.x
->font
);
3217 x_display_bar_cursor (f
, on
)
3221 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3223 if (! FRAME_VISIBLE_P (f
))
3226 if (! on
&& f
->phys_cursor_x
< 0)
3229 /* If we're not updating, then we want to use the current frame's
3230 cursor position, not our local idea of where the cursor ought to be. */
3231 if (f
!= updating_frame
)
3233 curs_x
= FRAME_CURSOR_X (f
);
3234 curs_y
= FRAME_CURSOR_Y (f
);
3237 /* If there is anything wrong with the current cursor state, remove it. */
3238 if (f
->phys_cursor_x
>= 0
3240 || f
->phys_cursor_x
!= curs_x
3241 || f
->phys_cursor_y
!= curs_y
3242 || f
->display
.x
->current_cursor
!= bar_cursor
))
3244 /* Erase the cursor by redrawing the character underneath it. */
3245 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3246 f
->phys_cursor_glyph
,
3247 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3248 f
->phys_cursor_x
= -1;
3251 /* If we now need a cursor in the new place or in the new form, do it so. */
3253 && (f
->phys_cursor_x
< 0
3254 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3256 f
->phys_cursor_glyph
3257 = ((current_glyphs
->enable
[curs_y
]
3258 && curs_x
< current_glyphs
->used
[curs_y
])
3259 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3261 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3262 f
->display
.x
->cursor_gc
,
3263 CHAR_TO_PIXEL_COL (f
, curs_x
),
3264 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3265 1, FONT_HEIGHT (f
->display
.x
->font
));
3267 f
->phys_cursor_x
= curs_x
;
3268 f
->phys_cursor_y
= curs_y
;
3270 f
->display
.x
->current_cursor
= bar_cursor
;
3273 if (updating_frame
!= f
)
3278 /* Turn the displayed cursor of frame F on or off according to ON.
3279 If ON is nonzero, where to put the cursor is specified
3280 by F->cursor_x and F->cursor_y. */
3283 x_display_box_cursor (f
, on
)
3287 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3289 if (! FRAME_VISIBLE_P (f
))
3292 /* If cursor is off and we want it off, return quickly. */
3293 if (!on
&& f
->phys_cursor_x
< 0)
3296 /* If we're not updating, then we want to use the current frame's
3297 cursor position, not our local idea of where the cursor ought to be. */
3298 if (f
!= updating_frame
)
3300 curs_x
= FRAME_CURSOR_X (f
);
3301 curs_y
= FRAME_CURSOR_Y (f
);
3304 /* If cursor is currently being shown and we don't want it to be
3305 or it is in the wrong place,
3306 or we want a hollow box and it's not so, (pout!)
3308 if (f
->phys_cursor_x
>= 0
3310 || f
->phys_cursor_x
!= curs_x
3311 || f
->phys_cursor_y
!= curs_y
3312 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3313 && (f
!= x_highlight_frame
))))
3315 /* Erase the cursor by redrawing the character underneath it. */
3316 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3317 f
->phys_cursor_glyph
,
3318 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3319 f
->phys_cursor_x
= -1;
3322 /* If we want to show a cursor,
3323 or we want a box cursor and it's not so,
3324 write it in the right place. */
3326 && (f
->phys_cursor_x
< 0
3327 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3328 && f
== x_highlight_frame
)))
3330 f
->phys_cursor_glyph
3331 = ((current_glyphs
->enable
[curs_y
]
3332 && curs_x
< current_glyphs
->used
[curs_y
])
3333 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3335 if (f
!= x_highlight_frame
)
3338 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3342 x_draw_single_glyph (f
, curs_y
, curs_x
,
3343 f
->phys_cursor_glyph
, 2);
3344 f
->display
.x
->current_cursor
= filled_box_cursor
;
3347 f
->phys_cursor_x
= curs_x
;
3348 f
->phys_cursor_y
= curs_y
;
3351 if (updating_frame
!= f
)
3355 x_display_cursor (f
, on
)
3359 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3360 x_display_box_cursor (f
, on
);
3361 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3362 x_display_bar_cursor (f
, on
);
3364 /* Those are the only two we have implemented! */
3370 /* Refresh bitmap kitchen sink icon for frame F
3371 when we get an expose event for it. */
3377 /* Normally, the window manager handles this function. */
3378 #else /* ! defined (HAVE_X11) */
3381 if (f
->display
.x
->icon_bitmap_flag
)
3382 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3383 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3384 icon_bitmap
, GXcopy
, AllPlanes
);
3387 extern struct frame
*selected_frame
;
3388 struct Lisp_String
*str
;
3389 unsigned char *string
;
3392 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3394 if (f
->display
.x
->icon_label
!= string
)
3396 f
->display
.x
->icon_label
= string
;
3397 XChangeWindow (f
->display
.x
->icon_desc
,
3398 XQueryWidth (string
, icon_font_info
->id
) + 10,
3399 icon_font_info
->height
+ 10);
3402 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3403 str
->size
, icon_font_info
->id
,
3404 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3407 #endif /* ! defined (HAVE_X11) */
3410 /* Make the x-window of frame F use the gnu icon bitmap. */
3419 if (FRAME_X_WINDOW (f
) == 0)
3424 XFreePixmap (x_current_display
, icon_bitmap
);
3427 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3428 gnu_bits
, gnu_width
, gnu_height
);
3429 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3430 f
->display
.x
->icon_bitmap_flag
= 1;
3431 #else /* ! defined (HAVE_X11) */
3432 if (f
->display
.x
->icon_desc
)
3434 XClearIconWindow (FRAME_X_WINDOW (f
));
3435 XDestroyWindow (f
->display
.x
->icon_desc
);
3438 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3439 0, 0, sink_width
, sink_height
,
3440 2, WhitePixmap
, (Pixmap
) NULL
);
3442 if (icon_window
== 0)
3445 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3446 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3448 f
->display
.x
->icon_desc
= icon_window
;
3449 f
->display
.x
->icon_bitmap_flag
= 1;
3451 if (icon_bitmap
== 0)
3453 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3454 #endif /* ! defined (HAVE_X11) */
3460 /* Make the x-window of frame F use a rectangle with text. */
3463 x_text_icon (f
, icon_name
)
3471 char *X_DefaultValue
;
3475 #define WhitePixel 1
3476 #endif /* WhitePixel */
3479 #define BlackPixel 0
3480 #endif /* BlackPixel */
3481 #endif /* HAVE_X11 */
3483 if (FRAME_X_WINDOW (f
) == 0)
3488 f
->display
.x
->icon_label
= icon_name
;
3490 if (! f
->display
.x
->icon_label
)
3491 f
->display
.x
->icon_label
= " *emacs* ";
3493 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3494 (char *) f
->display
.x
->icon_label
);
3496 f
->display
.x
->icon_bitmap_flag
= 0;
3497 x_wm_set_icon_pixmap (f
, 0);
3498 #else /* ! defined (HAVE_X11) */
3499 if (icon_font_info
== 0)
3501 = XGetFont (XGetDefault (XDISPLAY
3502 (char *) XSTRING (invocation_name
)->data
,
3505 if (f
->display
.x
->icon_desc
)
3507 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3508 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3512 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3514 if (! f
->display
.x
->icon_label
)
3515 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3517 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3518 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3519 f
->display
.x
->left_pos
,
3520 f
->display
.x
->top_pos
,
3521 width
+ 10, icon_font_info
->height
+ 10,
3522 2, BlackPixmap
, WhitePixmap
);
3524 if (icon_window
== 0)
3527 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3528 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3530 f
->display
.x
->icon_desc
= icon_window
;
3531 f
->display
.x
->icon_bitmap_flag
= 0;
3532 f
->display
.x
->icon_label
= 0;
3533 #endif /* ! defined (HAVE_X11) */
3538 /* Handling X errors. */
3540 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3541 X server's connection, or an error reported via the X protocol. */
3544 x_connection_closed ()
3549 shut_down_emacs (0);
3554 /* An X error handler which prints an error message and then kills Emacs.
3555 This is what's normally installed as Xlib's handler for protocol and
3558 x_error_quitter (display
, error
)
3564 /* Note that there is no real way portable across R3/R4 to get the
3565 original error handler. */
3567 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3568 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3569 buf
, error
->request_code
);
3571 /* While we're testing Emacs 19, we'll just dump core whenever we
3572 get an X error, so we can figure out why it happened. */
3575 x_connection_closed ();
3578 /* A buffer for storing X error messages. */
3579 static char (*x_caught_error_message
)[200];
3581 /* An X error handler which stores the error message in
3582 x_caught_error_message. This is what's installed when
3583 x_catch_errors is in effect. */
3585 x_error_catcher (display
, error
)
3589 XGetErrorText (display
, error
->error_code
,
3590 *x_caught_error_message
, sizeof (*x_caught_error_message
));
3594 /* Begin trapping X errors.
3596 After calling this function, X protocol errors no longer cause
3597 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3599 Calling x_check_errors signals an Emacs error if an X error has
3600 occurred since the last call to x_catch_errors or x_check_errors.
3602 Calling x_uncatch_errors resumes the normal error handling. */
3604 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3609 /* Make sure any errors from previous requests have been dealt with. */
3610 XSync (x_current_display
, False
);
3612 /* Set up the error buffer. */
3613 x_caught_error_message
=
3614 (char (*)[]) xmalloc (sizeof (*x_caught_error_message
));
3615 (*x_caught_error_message
)[0] = '\0';
3617 /* Install our little error handler. */
3618 XHandleError (x_error_catcher
);
3621 /* If any X protocol errors have arrived since the last call to
3622 x_catch_errors or x_check_errors, signal an Emacs error using
3623 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3625 x_check_errors (format
)
3628 /* Make sure to catch any errors incurred so far. */
3629 XSync (x_current_display
, False
);
3631 if ((*x_caught_error_message
)[0])
3635 sprintf (buf
, format
, *x_caught_error_message
);
3636 free (x_caught_error_message
);
3638 x_uncatch_errors ();
3646 free (x_caught_error_message
);
3647 XHandleError (x_error_quitter
);
3651 static unsigned int x_wire_count
;
3654 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3659 /* Changing the font of the frame. */
3661 /* Set the font of the x-window specified by frame F
3662 to the font named NEWNAME. This is safe to use
3663 even before F has an actual x-window. */
3667 /* A table of all the fonts we have already loaded. */
3668 static XFontStruct
**x_font_table
;
3670 /* The current capacity of x_font_table. */
3671 static int x_font_table_size
;
3673 /* The number of fonts actually stored in x_font_table.
3674 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3675 0 <= n_fonts <= x_font_table_size. */
3678 x_new_font (f
, fontname
)
3680 register char *fontname
;
3684 int n_matching_fonts
;
3685 XFontStruct
*font_info
;
3688 /* Get a list of all the fonts that match this name. Once we
3689 have a list of matching fonts, we compare them against the fonts
3690 we already have by comparing font ids. */
3691 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3692 1024, &n_matching_fonts
,
3694 /* If the server couldn't find any fonts whose named matched fontname,
3695 return an error code. */
3696 if (n_matching_fonts
== 0)
3699 /* See if we've already loaded a matching font. */
3704 for (i
= 0; i
< n_fonts
; i
++)
3705 for (j
= 0; j
< n_matching_fonts
; j
++)
3706 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3714 /* If we have, just return it from the table. */
3716 f
->display
.x
->font
= x_font_table
[already_loaded
];
3718 /* Otherwise, load the font and add it to the table. */
3723 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
3727 /* Do we need to create the table? */
3728 if (x_font_table_size
== 0)
3730 x_font_table_size
= 16;
3732 = (XFontStruct
**) xmalloc (x_font_table_size
3733 * sizeof (x_font_table
[0]));
3735 /* Do we need to grow the table? */
3736 else if (n_fonts
>= x_font_table_size
)
3738 x_font_table_size
*= 2;
3740 = (XFontStruct
**) xrealloc (x_font_table
,
3742 * sizeof (x_font_table
[0])));
3745 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
3748 /* Free the information from XListFontsWithInfo. The data
3749 we actually retain comes from XLoadQueryFont. */
3750 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
3752 /* Now make the frame display the given font. */
3753 if (FRAME_X_WINDOW (f
) != 0)
3755 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
3756 f
->display
.x
->font
->fid
);
3757 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
3758 f
->display
.x
->font
->fid
);
3759 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
3760 f
->display
.x
->font
->fid
);
3762 x_set_window_size (f
, f
->width
, f
->height
);
3767 #else /* ! defined (HAVE_X11) */
3768 x_new_font (f
, newname
)
3770 register char *newname
;
3775 temp
= XGetFont (newname
);
3776 if (temp
== (FONT_TYPE
*) 0)
3779 if (f
->display
.x
->font
)
3780 XLoseFont (f
->display
.x
->font
);
3782 f
->display
.x
->font
= temp
;
3784 if (FRAME_X_WINDOW (f
) != 0)
3785 x_set_window_size (f
, f
->width
, f
->height
);
3789 #endif /* ! defined (HAVE_X11) */
3791 /* X Window sizes and positions. */
3793 x_calc_absolute_position (f
)
3797 if (f
->display
.x
->left_pos
< 0)
3798 f
->display
.x
->left_pos
3799 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
3801 if (f
->display
.x
->top_pos
< 0)
3802 f
->display
.x
->top_pos
3803 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
3804 #else /* ! defined (HAVE_X11) */
3805 WINDOWINFO_TYPE parentinfo
;
3807 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
3809 if (f
->display
.x
->left_pos
< 0)
3810 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
3811 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
3813 if (f
->display
.x
->top_pos
< 0)
3814 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
3815 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
3816 #endif /* ! defined (HAVE_X11) */
3819 x_set_offset (f
, xoff
, yoff
)
3821 register int xoff
, yoff
;
3823 f
->display
.x
->top_pos
= yoff
;
3824 f
->display
.x
->left_pos
= xoff
;
3825 x_calc_absolute_position (f
);
3828 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
3829 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
3831 x_wm_set_size_hint (f
, 0);
3832 #endif /* ! defined (HAVE_X11) */
3836 /* Call this to change the size of frame F's x-window. */
3838 x_set_window_size (f
, cols
, rows
)
3842 int pixelwidth
, pixelheight
;
3847 check_frame_size (f
, &rows
, &cols
);
3848 f
->display
.x
->vertical_scrollbar_extra
=
3849 (FRAME_HAS_VERTICAL_SCROLLBARS (f
)
3850 ? VERTICAL_SCROLLBAR_PIXEL_WIDTH (f
)
3852 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3853 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3856 x_wm_set_size_hint (f
, 0);
3857 #endif /* ! defined (HAVE_X11) */
3858 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
3860 /* Now, strictly speaking, we can't be sure that this is accurate,
3861 but the window manager will get around to dealing with the size
3862 change request eventually, and we'll hear how it went when the
3863 ConfigureNotify event gets here.
3865 We could just not bother storing any of this information here,
3866 and let the ConfigureNotify event set everything up, but that
3867 might be kind of confusing to the lisp code, since size changes
3868 wouldn't be reported in the frame parameters until some random
3869 point in the future when the ConfigureNotify event arrives. */
3870 FRAME_WIDTH (f
) = cols
;
3871 FRAME_HEIGHT (f
) = rows
;
3872 PIXEL_WIDTH (f
) = pixelwidth
;
3873 PIXEL_HEIGHT (f
) = pixelheight
;
3875 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3876 receive in the ConfigureNotify event; if we get what we asked
3877 for, then the event won't cause the screen to become garbaged, so
3878 we have to make sure to do it here. */
3879 SET_FRAME_GARBAGED (f
);
3886 x_set_resize_hint (f
)
3889 XSetResizeHint (FRAME_X_WINDOW (f
),
3890 2 * f
->display
.x
->internal_border_width
,
3891 2 * f
->display
.x
->internal_border_width
,
3892 FONT_WIDTH (f
->display
.x
->font
),
3893 FONT_HEIGHT (f
->display
.x
->font
));
3895 #endif /* HAVE_X11 */
3897 /* Mouse warping, focus shifting, raising and lowering. */
3899 x_set_mouse_position (f
, x
, y
)
3907 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
3908 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
3910 if (pix_x
< 0) pix_x
= 0;
3911 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3913 if (pix_y
< 0) pix_y
= 0;
3914 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3918 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
3923 x_focus_on_frame (f
)
3928 /* I don't think that the ICCCM allows programs to do things like this
3929 without the interaction of the window manager. Whatever you end up
3930 doing with this code, do it to x_unfocus_frame too. */
3931 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
3932 RevertToPointerRoot
, CurrentTime
);
3940 /* Look at the remarks in x_focus_on_frame. */
3941 if (x_focus_frame
== f
)
3942 XSetInputFocus (x_current_display
, PointerRoot
,
3943 RevertToPointerRoot
, CurrentTime
);
3947 #endif /* ! defined (HAVE_X11) */
3949 /* Raise frame F. */
3954 if (f
->async_visible
)
3957 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3963 /* Lower frame F. */
3968 if (f
->async_visible
)
3971 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3978 XTframe_raise_lower (f
, raise
)
3989 /* Change from withdrawn state to mapped state. */
3991 x_make_frame_visible (f
)
3998 if (! FRAME_VISIBLE_P (f
))
4001 if (! EQ (Vx_no_window_manager
, Qt
))
4002 x_wm_set_window_state (f
, NormalState
);
4004 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4005 if (FRAME_HAS_VERTICAL_SCROLLBARS (f
))
4006 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4007 #else /* ! defined (HAVE_X11) */
4008 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4009 if (f
->display
.x
->icon_desc
!= 0)
4010 XUnmapWindow (f
->display
.x
->icon_desc
);
4012 /* Handled by the MapNotify event for X11 */
4013 f
->async_visible
= 1;
4014 f
->async_iconified
= 0;
4016 /* NOTE: this may cause problems for the first frame. */
4018 #endif /* ! defined (HAVE_X11) */
4026 /* Change from mapped state to withdrawn state. */
4028 x_make_frame_invisible (f
)
4033 if (! f
->async_visible
)
4040 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4041 DefaultScreen (x_current_display
)))
4043 UNBLOCK_INPUT_RESIGNAL
;
4044 error ("can't notify window manager of window withdrawl");
4047 #else /* ! defined (HAVE_X11R4) */
4050 /* Tell the window manager what we're going to do. */
4051 if (! EQ (Vx_no_window_manager
, Qt
))
4055 unmap
.xunmap
.type
= UnmapNotify
;
4056 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4057 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4058 unmap
.xunmap
.from_configure
= False
;
4059 if (! XSendEvent (x_current_display
,
4060 DefaultRootWindow (x_current_display
),
4062 SubstructureRedirectMask
|SubstructureNotifyMask
,
4065 UNBLOCK_INPUT_RESIGNAL
;
4066 error ("can't notify window manager of withdrawal");
4070 /* Unmap the window ourselves. Cheeky! */
4071 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4073 #else /* ! defined (HAVE_X11) */
4075 XUnmapWindow (FRAME_X_WINDOW (f
));
4076 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4077 if (f
->display
.x
->icon_desc
!= 0)
4078 XUnmapWindow (f
->display
.x
->icon_desc
);
4080 #endif /* ! defined (HAVE_X11) */
4081 #endif /* ! defined (HAVE_X11R4) */
4087 /* Window manager communication. Created in Fx_open_connection. */
4088 extern Atom Xatom_wm_change_state
;
4090 /* Change window state from mapped to iconified. */
4097 if (f
->async_iconified
)
4103 /* Since we don't know which revision of X we're running, we'll use both
4104 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4106 /* X11R4: send a ClientMessage to the window manager using the
4107 WM_CHANGE_STATE type. */
4111 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4112 message
.xclient
.type
= ClientMessage
;
4113 message
.xclient
.message_type
= Xatom_wm_change_state
;
4114 message
.xclient
.format
= 32;
4115 message
.xclient
.data
.l
[0] = IconicState
;
4117 if (! XSendEvent (x_current_display
,
4118 DefaultRootWindow (x_current_display
),
4120 SubstructureRedirectMask
| SubstructureNotifyMask
,
4123 UNBLOCK_INPUT_RESIGNAL
;
4124 error ("Can't notify window manager of iconification.");
4128 /* X11R3: set the initial_state field of the window manager hints to
4130 x_wm_set_window_state (f
, IconicState
);
4132 f
->async_iconified
= 1;
4133 #else /* ! defined (HAVE_X11) */
4134 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4136 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4137 if (f
->display
.x
->icon_desc
!= 0)
4139 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4142 #endif /* ! defined (HAVE_X11) */
4148 /* Destroy the X window of frame F. */
4150 x_destroy_window (f
)
4155 if (f
->display
.x
->icon_desc
!= 0)
4156 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4157 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4160 free (f
->display
.x
);
4162 if (f
== x_focus_frame
)
4164 if (f
== x_highlight_frame
)
4165 x_highlight_frame
= 0;
4170 /* Manage event queues for X10. */
4174 /* Manage event queues.
4176 This code is only used by the X10 support.
4178 We cannot leave events in the X queue and get them when we are ready
4179 because X does not provide a subroutine to get only a certain kind
4180 of event but not block if there are no queued events of that kind.
4182 Therefore, we must examine events as they come in and copy events
4183 of certain kinds into our private queues.
4185 All ExposeRegion events are put in x_expose_queue.
4186 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4189 /* Write the event *P_XREP into the event queue *QUEUE.
4190 If the queue is full, do nothing, but return nonzero. */
4193 enqueue_event (p_xrep
, queue
)
4194 register XEvent
*p_xrep
;
4195 register struct event_queue
*queue
;
4197 int newindex
= queue
->windex
+ 1;
4198 if (newindex
== EVENT_BUFFER_SIZE
)
4200 if (newindex
== queue
->rindex
)
4202 queue
->xrep
[queue
->windex
] = *p_xrep
;
4203 queue
->windex
= newindex
;
4207 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4208 If *QUEUE is empty, do nothing and return 0. */
4211 dequeue_event (p_xrep
, queue
)
4212 register XEvent
*p_xrep
;
4213 register struct event_queue
*queue
;
4215 if (queue
->windex
== queue
->rindex
)
4217 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4218 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4223 /* Return the number of events buffered in *QUEUE. */
4226 queue_event_count (queue
)
4227 register struct event_queue
*queue
;
4229 int tem
= queue
->windex
- queue
->rindex
;
4232 return EVENT_BUFFER_SIZE
+ tem
;
4235 /* Return nonzero if mouse input is pending. */
4238 mouse_event_pending_p ()
4240 return queue_event_count (&x_mouse_queue
);
4242 #endif /* HAVE_X11 */
4244 /* Setting window manager hints. */
4248 x_wm_set_size_hint (f
, prompting
)
4252 XSizeHints size_hints
;
4253 Window window
= FRAME_X_WINDOW (f
);
4255 size_hints
.flags
= PResizeInc
| PMinSize
| PMaxSize
;
4257 flexlines
= f
->height
;
4259 size_hints
.x
= f
->display
.x
->left_pos
;
4260 size_hints
.y
= f
->display
.x
->top_pos
;
4261 size_hints
.height
= PIXEL_HEIGHT (f
);
4262 size_hints
.width
= PIXEL_WIDTH (f
);
4263 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4264 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4265 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4266 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4269 int base_width
, base_height
;
4271 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4272 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4275 int min_rows
= 0, min_cols
= 0;
4276 check_frame_size (f
, &min_rows
, &min_cols
);
4278 /* The window manager uses the base width hints to calculate the
4279 current number of rows and columns in the frame while
4280 resizing; min_width and min_height aren't useful for this
4281 purpose, since they might not give the dimensions for a
4282 zero-row, zero-column frame.
4284 We use the base_width and base_height members if we have
4285 them; otherwise, we set the min_width and min_height members
4286 to the size for a zero x zero frame. */
4289 size_hints
.flags
|= PBaseSize
;
4290 size_hints
.base_width
= base_width
;
4291 size_hints
.base_height
= base_height
;
4292 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4293 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4295 size_hints
.min_width
= base_width
;
4296 size_hints
.min_height
= base_height
;
4303 size_hints
.flags
|= prompting
;
4306 XSizeHints hints
; /* Sometimes I hate X Windows... */
4308 XGetNormalHints (x_current_display
, window
, &hints
);
4309 if (hints
.flags
& PSize
)
4310 size_hints
.flags
|= PSize
;
4311 if (hints
.flags
& PPosition
)
4312 size_hints
.flags
|= PPosition
;
4313 if (hints
.flags
& USPosition
)
4314 size_hints
.flags
|= USPosition
;
4315 if (hints
.flags
& USSize
)
4316 size_hints
.flags
|= USSize
;
4320 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4322 XSetNormalHints (x_current_display
, window
, &size_hints
);
4326 /* Used for IconicState or NormalState */
4327 x_wm_set_window_state (f
, state
)
4331 Window window
= FRAME_X_WINDOW (f
);
4333 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4334 f
->display
.x
->wm_hints
.initial_state
= state
;
4336 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4339 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4343 Window window
= FRAME_X_WINDOW (f
);
4347 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4348 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4351 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4353 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4356 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4360 Window window
= FRAME_X_WINDOW (f
);
4362 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4363 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4364 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4366 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4370 /* Initialization. */
4373 x_term_init (display_name
)
4379 extern int old_fcntl_owner
;
4380 #endif /* ! defined (F_SETOWN) */
4382 x_focus_frame
= x_highlight_frame
= 0;
4384 x_current_display
= XOpenDisplay (display_name
);
4385 if (x_current_display
== 0)
4386 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4391 int hostname_size
= 256;
4393 hostname
= (char *) xmalloc (hostname_size
);
4396 XSetAfterFunction (x_current_display
, x_trace_wire
);
4399 invocation_name
= Ffile_name_nondirectory (Fcar (Vcommand_line_args
));
4401 /* Try to get the host name; if the buffer is too short, try
4402 again. Apparently, the only indication gethostname gives of
4403 whether the buffer was large enough is the presence or absence
4404 of a '\0' in the string. Eech. */
4407 gethostname (hostname
, hostname_size
- 1);
4408 hostname
[hostname_size
- 1] = '\0';
4410 /* Was the buffer large enough for gethostname to store the '\0'? */
4411 if (strlen (hostname
) < hostname_size
- 1)
4414 hostname_size
<<= 1;
4415 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4417 x_id_name
= (char *) xmalloc (XSTRING (invocation_name
)->size
4420 sprintf (x_id_name
, "%s@%s", XSTRING (invocation_name
)->data
, hostname
);
4423 /* Figure out which modifier bits mean what. */
4424 x_find_modifier_meanings ();
4426 /* Get the scrollbar cursor. */
4427 x_vertical_scrollbar_cursor
=
4428 XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4430 /* Watch for PropertyNotify events on the root window; we use them
4431 to figure out when to invalidate our cache of the cut buffers. */
4432 x_watch_cut_buffer_cache ();
4434 dup2 (ConnectionNumber (x_current_display
), 0);
4436 #ifndef SYSV_STREAMS
4437 /* Streams somehow keeps track of which descriptor number
4438 is being used to talk to X. So it is not safe to substitute
4439 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4440 close (ConnectionNumber (x_current_display
));
4441 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4442 * check the def of the macro;
4443 * it is a genuine lvalue */
4444 #endif /* SYSV_STREAMS */
4446 #endif /* ! defined (HAVE_X11) */
4449 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4450 #ifdef F_SETOWN_SOCK_NEG
4451 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4452 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4453 fcntl (0, F_SETOWN
, getpid ());
4454 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4455 #endif /* ! defined (F_SETOWN) */
4459 #endif /* ! defined (SIGIO) */
4461 /* Must use interrupt input because we cannot otherwise
4462 arrange for C-g to be noticed immediately.
4463 We cannot connect it to SIGINT. */
4464 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4466 expose_all_windows
= 0;
4468 clear_frame_hook
= XTclear_frame
;
4469 clear_end_of_line_hook
= XTclear_end_of_line
;
4470 ins_del_lines_hook
= XTins_del_lines
;
4471 change_line_highlight_hook
= XTchange_line_highlight
;
4472 insert_glyphs_hook
= XTinsert_glyphs
;
4473 write_glyphs_hook
= XTwrite_glyphs
;
4474 delete_glyphs_hook
= XTdelete_glyphs
;
4475 ring_bell_hook
= XTring_bell
;
4476 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4477 set_terminal_modes_hook
= XTset_terminal_modes
;
4478 update_begin_hook
= XTupdate_begin
;
4479 update_end_hook
= XTupdate_end
;
4480 set_terminal_window_hook
= XTset_terminal_window
;
4481 read_socket_hook
= XTread_socket
;
4482 cursor_to_hook
= XTcursor_to
;
4483 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4484 mouse_position_hook
= XTmouse_position
;
4485 frame_rehighlight_hook
= XTframe_rehighlight
;
4486 frame_raise_lower_hook
= XTframe_raise_lower
;
4487 set_vertical_scrollbar_hook
= XTset_vertical_scrollbar
;
4488 condemn_scrollbars_hook
= XTcondemn_scrollbars
;
4489 redeem_scrollbar_hook
= XTredeem_scrollbar
;
4490 judge_scrollbars_hook
= XTjudge_scrollbars
;
4492 scroll_region_ok
= 1; /* we'll scroll partial frames */
4493 char_ins_del_ok
= 0; /* just as fast to write the line */
4494 line_ins_del_ok
= 1; /* we'll just blt 'em */
4495 fast_clear_end_of_line
= 1; /* X does this well */
4496 memory_below_frame
= 0; /* we don't remember what scrolls
4500 /* Note that there is no real way portable across R3/R4 to get the
4501 original error handler. */
4502 XHandleError (x_error_quitter
);
4503 XHandleIOError (x_error_quitter
);
4505 /* Disable Window Change signals; they are handled by X events. */
4507 signal (SIGWINCH
, SIG_DFL
);
4508 #endif /* ! defined (SIGWINCH) */
4510 signal (SIGPIPE
, x_connection_closed
);
4516 staticpro (&invocation_name
);
4517 invocation_name
= Qnil
;
4519 staticpro (&last_mouse_scrollbar
);
4521 #endif /* ! defined (HAVE_X11) */
4522 #endif /* ! defined (HAVE_X_WINDOWS) */