1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 #define NEW_SELECTIONS
36 /* On 4.3 these lose if they come after xterm.h. */
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
56 #else /* ! defined (BSD) */
58 #include <sys/termio.h>
61 #endif /* ! defined (BSD) */
63 /* Allow m- file to inhibit use of FIONREAD. */
64 #ifdef BROKEN_FIONREAD
66 #endif /* ! defined (BROKEN_FIONREAD) */
68 /* We are unable to use interrupts if FIONREAD is not available,
69 so flush SIGIO so we won't try. */
73 #endif /* ! defined (SIGIO) */
83 #include <sys/param.h>
85 #include "dispextern.h"
86 #include "termhooks.h"
100 #define XMapWindow XMapRaised /* Raise them when mapping. */
101 #else /* ! defined (HAVE_X11) */
102 #include <X/Xkeyboard.h>
103 /*#include <X/Xproto.h> */
104 #endif /* ! defined (HAVE_X11) */
106 /* For sending Meta-characters. Do we need this? */
109 #define min(a,b) ((a)<(b) ? (a) : (b))
110 #define max(a,b) ((a)>(b) ? (a) : (b))
112 /* Nonzero means we must reprint all windows
113 because 1) we received an ExposeWindow event
114 or 2) we received too many ExposeRegion events to record.
116 This is never needed under X11. */
117 static int expose_all_windows
;
119 /* Nonzero means we must reprint all icon windows. */
121 static int expose_all_icons
;
124 /* ExposeRegion events, when received, are copied into this queue
125 for later processing. */
127 static struct event_queue x_expose_queue
;
129 /* ButtonPressed and ButtonReleased events, when received,
130 are copied into this queue for later processing. */
132 struct event_queue x_mouse_queue
;
133 #endif /* HAVE_X11 */
135 /* Nonzero after BLOCK_INPUT; prevents input events from being
136 processed until later. */
140 #if defined (SIGIO) && defined (FIONREAD)
141 int BLOCK_INPUT_mask
;
142 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
144 /* Nonzero if input events came in while x_input_blocked was nonzero.
145 UNBLOCK_INPUT checks for this. */
149 /* The id of a bitmap used for icon windows.
150 One such map is shared by all Emacs icon windows.
151 This is zero if we have not yet had a need to create the bitmap. */
153 static Bitmap icon_bitmap
;
155 /* Font used for text icons. */
157 static FONT_TYPE
*icon_font_info
;
159 /* Stuff for dealing with the main icon title. */
161 extern Lisp_Object Vcommand_line_args
;
162 char *hostname
, *x_id_name
;
164 /* This is the X connection that we are using. */
166 Display
*x_current_display
;
168 /* The cursor to use for vertical scroll bars on x_current_display. */
169 static Cursor x_vertical_scroll_bar_cursor
;
171 /* Frame being updated by update_frame. */
172 /* This is set by XTupdate_begin and looked at by all the
173 XT functions. It is zero while not inside an update.
174 In that case, the XT functions assume that `selected_frame'
175 is the frame to apply to. */
177 static struct frame
*updating_frame
;
179 /* The frame (if any) which has the X window that has keyboard focus.
180 Zero if none. This is examined by Ffocus_frame in frame.c. Note
181 that a mere EnterNotify event can set this; if you need to know the
182 last frame specified in a FocusIn or FocusOut event, use
183 x_focus_event_frame. */
184 struct frame
*x_focus_frame
;
186 /* The last frame mentioned in a FocusIn or FocusOut event. This is
187 separate from x_focus_frame, because whether or not LeaveNotify
188 events cause us to lose focus depends on whether or not we have
189 received a FocusIn event for it. */
190 struct frame
*x_focus_event_frame
;
192 /* The frame which currently has the visual highlight, and should get
193 keyboard input (other sorts of input have the frame encoded in the
194 event). It points to the X focus frame's selected window's
195 frame. It differs from x_focus_frame when we're using a global
197 static struct frame
*x_highlight_frame
;
199 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
200 mouse is moved to inside of frame when frame is de-iconified. */
202 static int warp_mouse_on_deiconify
;
204 /* During an update, maximum vpos for ins/del line operations to affect. */
206 static int flexlines
;
208 /* During an update, nonzero if chars output now should be highlighted. */
210 static int highlight
;
212 /* Nominal cursor position -- where to draw output.
213 During an update, these are different from the cursor-box position. */
219 /* `t' if a mouse button is depressed. */
221 extern Lisp_Object Vmouse_depressed
;
223 /* Tells if a window manager is present or not. */
225 extern Lisp_Object Vx_no_window_manager
;
227 /* Timestamp that we requested selection data was made. */
228 extern Time requestor_time
;
230 /* ID of the window requesting selection data. */
231 extern Window requestor_window
;
233 /* Nonzero enables some debugging for the X interface code. */
236 #else /* ! defined (HAVE_X11) */
238 /* Bit patterns for the mouse cursor. */
240 short MouseCursor
[] = {
241 0x0000, 0x0008, 0x0018, 0x0038,
242 0x0078, 0x00f8, 0x01f8, 0x03f8,
243 0x07f8, 0x00f8, 0x00d8, 0x0188,
244 0x0180, 0x0300, 0x0300, 0x0000};
246 short MouseMask
[] = {
247 0x000c, 0x001c, 0x003c, 0x007c,
248 0x00fc, 0x01fc, 0x03fc, 0x07fc,
249 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
250 0x03cc, 0x0780, 0x0780, 0x0300};
252 static short grey_bits
[] = {
253 0x0005, 0x000a, 0x0005, 0x000a};
255 static Pixmap GreyPixmap
= 0;
256 #endif /* ! defined (HAVE_X11) */
258 /* From time to time we get info on an Emacs window, here. */
260 static WINDOWINFO_TYPE windowinfo
;
264 /* See keyboard.c. */
265 extern int extra_keyboard_modifiers
;
267 extern Display
*XOpenDisplay ();
268 extern Window
XCreateWindow ();
270 extern Cursor
XCreateCursor ();
271 extern FONT_TYPE
*XOpenFont ();
273 static void flashback ();
276 static void dumpqueue ();
277 #endif /* HAVE_X11 */
280 static int XTcursor_to ();
281 static int XTclear_end_of_line ();
284 /* Starting and ending updates.
286 These hooks are called by update_frame at the beginning and end
287 of a frame update. We record in `updating_frame' the identity
288 of the frame being updated, so that the XT... functions do not
289 need to take a frame as argument. Most of the XT... functions
290 should never be called except during an update, the only exceptions
291 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
293 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
305 flexlines
= f
->height
;
311 #endif /* HAVE_X11 */
316 static void x_do_pending_expose ();
325 if (updating_frame
== 0
326 || updating_frame
!= f
)
332 x_do_pending_expose ();
333 #endif /* HAVE_X11 */
335 x_display_cursor (f
, 1);
342 /* External interface to control of standout mode.
343 Call this when about to modify line at position VPOS
344 and not change whether it is highlighted. */
346 XTreassert_line_highlight (new, vpos
)
352 /* Call this when about to modify line at position VPOS
353 and change whether it is highlighted. */
356 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
357 int new_highlight
, vpos
, first_unused_hpos
;
359 highlight
= new_highlight
;
360 XTcursor_to (vpos
, 0);
361 XTclear_end_of_line (updating_frame
->width
);
364 /* This is used when starting Emacs and when restarting after suspend.
365 When starting Emacs, no X window is mapped. And nothing must be done
366 to Emacs's own window if it is suspended (though that rarely happens). */
369 XTset_terminal_modes ()
373 /* This is called when exiting or suspending Emacs.
374 Exiting will make the X-windows go away, and suspending
375 requires no action. */
378 XTreset_terminal_modes ()
380 /* XTclear_frame (); */
383 /* Set the nominal cursor position of the frame.
384 This is where display update commands will take effect.
385 This does not affect the place where the cursor-box is displayed. */
388 XTcursor_to (row
, col
)
389 register int row
, col
;
397 if (updating_frame
== 0)
400 x_display_cursor (selected_frame
, 1);
406 /* Display a sequence of N glyphs found at GP.
407 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
408 HL is 1 if this text is highlighted, 2 if the cursor is on it.
410 FONT is the default font to use (for glyphs whose font-code is 0). */
413 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
416 register GLYPH
*gp
; /* Points to first GLYPH. */
417 register int n
; /* Number of glyphs to display. */
422 Window window
= FRAME_X_WINDOW (f
);
423 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
424 : (hl
? f
->display
.x
->reverse_gc
425 : f
->display
.x
->normal_gc
));
427 if (sizeof (GLYPH
) == sizeof (XChar2b
))
428 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
429 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
430 else if (sizeof (GLYPH
) == sizeof (unsigned char))
431 XDrawImageString (x_current_display
, window
, drawing_gc
,
432 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
434 /* What size of glyph ARE you using? And does X have a function to
441 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
444 register GLYPH
*gp
; /* Points to first GLYPH. */
445 register int n
; /* Number of glyphs to display. */
449 char buf
[f
->width
]; /* Holds characters to be displayed. */
450 register char *cp
; /* Steps through buf[]. */
451 register int tlen
= GLYPH_TABLE_LENGTH
;
452 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
453 Window window
= FRAME_X_WINDOW (f
);
454 int cursor_pixel
= f
->display
.x
->cursor_pixel
;
455 int fg_pixel
= f
->display
.x
->foreground_pixel
;
456 int bg_pixel
= f
->display
.x
->background_pixel
;
457 int intborder
= f
->display
.x
->internal_border_width
;
461 /* Get the face-code of the next GLYPH. */
465 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
466 g
= GLYPH_ALIAS (tbase
, g
);
470 /* Find the run of consecutive glyphs with the same face-code.
471 Extract their character codes into BUF. */
476 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
477 g
= GLYPH_ALIAS (tbase
, g
);
486 /* LEN gets the length of the run. */
489 /* Now output this run of chars, with the font and pixel values
490 determined by the face code CF. */
494 GC GC_cursor
= f
->display
.x
->cursor_gc
;
495 GC GC_reverse
= f
->display
.x
->reverse_gc
;
496 GC GC_normal
= f
->display
.x
->normal_gc
;
498 XDrawImageString (x_current_display
, window
,
501 : (hl
? GC_reverse
: GC_normal
)),
502 left
, top
+ FONT_BASE (font
), buf
, len
);
503 #else /* ! defined (HAVE_X11) */
504 XText (window
, left
, top
,
509 ? (cursor_pixel
== fg_pixel
? bg_pixel
: fg_pixel
)
510 : hl
? bg_pixel
: fg_pixel
),
511 (hl
== 2 ? cursor_pixel
512 : hl
? fg_pixel
: bg_pixel
));
513 #endif /* ! defined (HAVE_X11) */
518 if (FACE_IS_FONT (cf
))
519 XDrawImageString (x_current_display
, FRAME_X_WINDOW (f
),
521 left
, top
+ FONT_BASE (FACE_FONT (cf
)),
523 else if (FACE_IS_IMAGE (cf
))
524 XCopyPlane (x_current_display
, FACE_IMAGE (cf
),
526 f
->display
.x
->normal_gc
,
528 FACE_IMAGE_WIDTH (cf
),
529 FACE_IMAGE_HEIGHT (cf
), left
, top
);
532 #else /* ! defined (HAVE_X11) */
533 register struct face
*fp
= x_face_table
[cf
];
535 XText (window
, left
, top
,
540 ? (cursor_pixel
== fp
->fg
? fp
->bg
: fp
->fg
)
541 : hl
? fp
->bg
: fp
->fg
),
542 (hl
== 2 ? cursor_pixel
543 : hl
? fp
->fg
: fp
->bg
));
544 #endif /* ! defined (HAVE_X11) */
546 left
+= len
* FONT_WIDTH (font
);
551 /* Output some text at the nominal frame cursor position.
552 Advance the cursor over the text.
553 Output LEN glyphs at START.
555 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
556 controls the pixel values used for foreground and background. */
559 XTwrite_glyphs (start
, len
)
560 register GLYPH
*start
;
563 register int temp_length
;
573 /* If not within an update,
574 output at the frame's visible cursor. */
575 curs_x
= f
->cursor_x
;
576 curs_y
= f
->cursor_y
;
580 CHAR_TO_PIXEL_COL (f
, curs_x
),
581 CHAR_TO_PIXEL_ROW (f
, curs_y
),
582 start
, len
, highlight
, f
->display
.x
->font
);
584 /* If we drew on top of the cursor, note that it is turned off. */
585 if (curs_y
== f
->phys_cursor_y
586 && curs_x
<= f
->phys_cursor_x
587 && curs_x
+ len
> f
->phys_cursor_x
)
588 f
->phys_cursor_x
= -1;
590 if (updating_frame
== 0)
593 x_display_cursor (f
, 1);
602 /* Clear to the end of the line.
603 Erase the current text line from the nominal cursor position (inclusive)
604 to column FIRST_UNUSED (exclusive). The idea is that everything
605 from FIRST_UNUSED onward is already erased. */
608 XTclear_end_of_line (first_unused
)
609 register int first_unused
;
611 struct frame
*f
= updating_frame
;
617 if (curs_y
< 0 || curs_y
>= f
->height
)
619 if (first_unused
<= 0)
622 if (first_unused
>= f
->width
)
623 first_unused
= f
->width
;
627 /* Notice if the cursor will be cleared by this operation. */
628 if (curs_y
== f
->phys_cursor_y
629 && curs_x
<= f
->phys_cursor_x
630 && f
->phys_cursor_x
< first_unused
)
631 f
->phys_cursor_x
= -1;
634 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
635 CHAR_TO_PIXEL_COL (f
, curs_x
),
636 CHAR_TO_PIXEL_ROW (f
, curs_y
),
637 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
638 FONT_HEIGHT (f
->display
.x
->font
), False
);
640 #else /* ! defined (HAVE_X11) */
641 XPixSet (FRAME_X_WINDOW (f
),
642 CHAR_TO_PIXEL_COL (f
, curs_x
),
643 CHAR_TO_PIXEL_ROW (f
, curs_y
),
644 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
645 FONT_HEIGHT (f
->display
.x
->font
),
646 f
->display
.x
->background_pixel
);
647 #endif /* ! defined (HAVE_X11) */
656 struct frame
*f
= updating_frame
;
661 f
->phys_cursor_x
= -1; /* Cursor not visible. */
662 curs_x
= 0; /* Nominal cursor position is top left. */
667 XClear (FRAME_X_WINDOW (f
));
669 /* We have to clear the scroll bars, too. If we have changed
670 colors or something like that, then they should be notified. */
671 x_scroll_bar_clear (f
);
675 #endif /* HAVE_X11 */
681 /* Invert the middle quarter of the frame for .15 sec. */
683 /* We use the select system call to do the waiting, so we have to make sure
684 it's avaliable. If it isn't, we just won't do visual bells. */
685 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
687 /* Subtract the `struct timeval' values X and Y,
688 storing the result in RESULT.
689 Return 1 if the difference is negative, otherwise 0. */
692 timeval_subtract (result
, x
, y
)
693 struct timeval
*result
, x
, y
;
695 /* Perform the carry for the later subtraction by updating y.
696 This is safer because on some systems
697 the tv_sec member is unsigned. */
698 if (x
.tv_usec
< y
.tv_usec
)
700 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
701 y
.tv_usec
-= 1000000 * nsec
;
704 if (x
.tv_usec
- y
.tv_usec
> 1000000)
706 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
707 y
.tv_usec
+= 1000000 * nsec
;
711 /* Compute the time remaining to wait. tv_usec is certainly positive. */
712 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
713 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
715 /* Return indication of whether the result should be considered negative. */
716 return x
.tv_sec
< y
.tv_sec
;
727 /* Create a GC that will use the GXxor function to flip foreground pixels
728 into background pixels. */
732 values
.function
= GXxor
;
733 values
.foreground
= (f
->display
.x
->foreground_pixel
734 ^ f
->display
.x
->background_pixel
);
736 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
737 GCFunction
| GCForeground
, &values
);
741 int width
= PIXEL_WIDTH (f
);
742 int height
= PIXEL_HEIGHT (f
);
744 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
745 width
/4, height
/4, width
/2, height
/2);
746 XFlush (x_current_display
);
749 struct timeval wakeup
, now
;
751 gettimeofday (&wakeup
, (struct timezone
*) 0);
753 /* Compute time to wait until, propagating carry from usecs. */
754 wakeup
.tv_usec
+= 150000;
755 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
756 wakeup
.tv_usec
%= 1000000;
758 /* Keep waiting until past the time wakeup. */
761 struct timeval timeout
;
763 gettimeofday (&timeout
, (struct timezone
*)0);
765 /* In effect, timeout = wakeup - timeout.
766 Break if result would be negative. */
767 if (timeval_subtract (&timeout
, wakeup
, timeout
))
770 /* Try to wait that long--but we might wake up sooner. */
771 select (0, 0, 0, 0, &timeout
);
775 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
776 width
/4, height
/4, width
/2, height
/2);
777 XFreeGC (x_current_display
, gc
);
778 XFlush (x_current_display
);
788 /* Make audible bell. */
791 #define XRINGBELL XBell(x_current_display, 0)
792 #else /* ! defined (HAVE_X11) */
793 #define XRINGBELL XFeep(0);
794 #endif /* ! defined (HAVE_X11) */
798 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
800 XTflash (selected_frame
);
811 /* Insert and delete character.
812 These are not supposed to be used because we are supposed to turn
813 off the feature of using them. */
816 XTinsert_glyphs (start
, len
)
817 register char *start
;
830 /* Specify how many text lines, from the top of the window,
831 should be affected by insert-lines and delete-lines operations.
832 This, and those operations, are used only within an update
833 that is bounded by calls to XTupdate_begin and XTupdate_end. */
836 XTset_terminal_window (n
)
839 if (updating_frame
== 0)
842 if ((n
<= 0) || (n
> updating_frame
->height
))
843 flexlines
= updating_frame
->height
;
848 /* Perform an insert-lines operation.
849 Insert N lines at a vertical position curs_y. */
855 register int topregion
, bottomregion
;
856 register int length
, newtop
, mask
;
857 register struct frame
*f
= updating_frame
;
858 int intborder
= f
->display
.x
->internal_border_width
;
860 if (curs_y
>= flexlines
)
864 bottomregion
= flexlines
- (n
+ 1);
865 newtop
= topregion
+ n
;
866 length
= (bottomregion
- topregion
) + 1;
870 #endif /* HAVE_X11 */
872 if ((length
> 0) && (newtop
<= flexlines
))
875 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
876 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
877 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
878 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
879 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
880 CHAR_TO_PIXEL_ROW (f
, newtop
));
881 #else /* ! defined (HAVE_X11) */
882 XMoveArea (FRAME_X_WINDOW (f
),
883 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
884 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
885 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
886 length
* FONT_HEIGHT (f
->display
.x
->font
));
887 /* Now we must process any ExposeRegion events that occur
888 if the area being copied from is obscured.
889 We can't let it wait because further i/d operations
890 may want to copy this area to another area. */
892 #endif /* ! defined (HAVE_X11) */
895 newtop
= min (newtop
, (flexlines
- 1));
896 length
= newtop
- topregion
;
900 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
901 CHAR_TO_PIXEL_ROW (f
, topregion
),
902 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
903 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
904 #else /* ! defined (HAVE_X11) */
905 XPixSet (FRAME_X_WINDOW (f
),
907 CHAR_TO_PIXEL_ROW (f
, topregion
),
908 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
909 n
* FONT_HEIGHT (f
->display
.x
->font
),
910 f
->display
.x
->background_pixel
);
911 #endif /* ! defined (HAVE_X11) */
915 /* Perform a delete-lines operation, deleting N lines
916 at a vertical position curs_y. */
923 register struct frame
*f
= updating_frame
;
924 int intborder
= f
->display
.x
->internal_border_width
;
926 if (curs_y
>= flexlines
)
931 #endif /* HAVE_X11 */
933 if ((curs_y
+ n
) >= flexlines
)
935 if (flexlines
>= (curs_y
+ 1))
938 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
939 CHAR_TO_PIXEL_ROW (f
, curs_y
),
940 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
941 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
942 #else /* ! defined (HAVE_X11) */
943 XPixSet (FRAME_X_WINDOW (f
),
944 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
945 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
946 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
947 f
->display
.x
->background_pixel
);
948 #endif /* ! defined (HAVE_X11) */
954 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
955 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
957 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
958 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
959 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
960 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
961 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
963 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
964 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
965 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
966 #else /* ! defined (HAVE_X11) */
967 XMoveArea (FRAME_X_WINDOW (f
),
969 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
970 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
971 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
972 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
973 /* Now we must process any ExposeRegion events that occur
974 if the area being copied from is obscured.
975 We can't let it wait because further i/d operations
976 may want to copy this area to another area. */
978 XPixSet (FRAME_X_WINDOW (f
), intborder
,
979 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
980 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
981 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
982 #endif /* ! defined (HAVE_X11) */
986 /* Perform an insert-lines or delete-lines operation,
987 inserting N lines or deleting -N lines at vertical position VPOS. */
989 XTins_del_lines (vpos
, n
)
992 if (updating_frame
== 0)
995 /* Hide the cursor. */
996 x_display_cursor (updating_frame
, 0);
998 XTcursor_to (vpos
, 0);
1009 /* Support routines for exposure events. */
1010 static void clear_cursor ();
1012 /* Output into a rectangle of an X-window (for frame F)
1013 the characters in f->phys_lines that overlap that rectangle.
1014 TOP and LEFT are the position of the upper left corner of the rectangle.
1015 ROWS and COLS are the size of the rectangle. */
1018 dumprectangle (f
, left
, top
, cols
, rows
)
1020 register int left
, top
, cols
, rows
;
1022 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1023 int cursor_cleared
= 0;
1027 if (FRAME_GARBAGED_P (f
))
1030 /* Express rectangle as four edges, instead of position-and-size. */
1031 bottom
= top
+ rows
;
1032 right
= left
+ cols
;
1034 #ifndef HAVE_X11 /* Window manger does this for X11. */
1036 int intborder
= f
->display
.x
->internal_border_width
;
1038 /* If the rectangle includes any of the internal border area,
1039 redisplay the border emphasis. */
1040 if (top
< intborder
|| left
< intborder
1041 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1042 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1045 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1047 /* Convert rectangle edges in pixels to edges in chars.
1048 Round down for left and top, up for right and bottom. */
1049 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1050 left
= PIXEL_TO_CHAR_COL (f
, left
);
1051 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1052 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1053 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1054 right
= PIXEL_TO_CHAR_COL (f
, right
);
1056 /* Clip the rectangle to what can be visible. */
1061 if (right
> f
->width
)
1063 if (bottom
> f
->height
)
1066 /* Get size in chars of the rectangle. */
1067 cols
= right
- left
;
1068 rows
= bottom
- top
;
1070 /* If rectangle has zero area, return. */
1071 if (rows
<= 0) return;
1072 if (cols
<= 0) return;
1074 /* Turn off the cursor if it is in the rectangle.
1075 We will turn it back on afterward. */
1076 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1077 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1083 /* Display the text in the rectangle, one text line at a time. */
1085 for (y
= top
; y
< bottom
; y
++)
1087 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1089 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1093 CHAR_TO_PIXEL_COL (f
, left
),
1094 CHAR_TO_PIXEL_ROW (f
, y
),
1095 line
, min (cols
, active_frame
->used
[y
] - left
),
1096 active_frame
->highlight
[y
], f
->display
.x
->font
);
1099 /* Turn the cursor on if we turned it off. */
1102 x_display_cursor (f
, 1);
1106 /* Process all queued ExposeRegion events. */
1112 XExposeRegionEvent r
;
1114 while (dequeue_event (&r
, &x_expose_queue
))
1116 struct frame
*f
= x_window_to_frame (r
.window
);
1117 if (f
->display
.x
->icon_desc
== r
.window
)
1120 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1124 #endif /* HAVE_X11 */
1126 /* Process all expose events that are pending, for X10.
1127 Redraws the cursor if necessary on any frame that
1128 is not in the process of being updated with update_frame. */
1132 x_do_pending_expose ()
1136 Lisp_Object tail
, frame
;
1138 if (expose_all_windows
)
1140 expose_all_windows
= 0;
1141 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1143 register int temp_width
, temp_height
;
1146 frame
= XCONS (tail
)->car
;
1147 if (XGCTYPE (frame
) != Lisp_Frame
)
1150 if (! FRAME_X_P (f
))
1152 if (!f
->async_visible
)
1154 if (!f
->display
.x
->needs_exposure
)
1157 intborder
= f
->display
.x
->internal_border_width
;
1160 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1161 temp_width
= ((windowinfo
.width
- 2 * intborder
1162 - f
->display
.x
->v_scroll_bar_width
)
1163 / FONT_WIDTH (f
->display
.x
->font
));
1164 temp_height
= ((windowinfo
.height
- 2 * intborder
1165 - f
->display
.x
->h_scroll_bar_height
)
1166 / FONT_HEIGHT (f
->display
.x
->font
));
1167 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1169 change_frame_size (f
, max (1, temp_height
),
1170 max (1, temp_width
), 0, 1);
1171 x_resize_scroll_bars (f
);
1173 f
->display
.x
->left_pos
= windowinfo
.x
;
1174 f
->display
.x
->top_pos
= windowinfo
.y
;
1175 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1179 f
->display
.x
->needs_exposure
= 0;
1180 if (updating_frame
!= f
)
1181 x_display_cursor (f
, 1);
1186 /* Handle any individual-rectangle expose events queued
1187 for various windows. */
1190 #else /* ! defined (HAVE_X11) */
1192 #endif /* ! defined (HAVE_X11) */
1198 frame_highlight (frame
)
1199 struct frame
*frame
;
1201 if (! EQ (Vx_no_window_manager
, Qnil
))
1202 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1203 frame
->display
.x
->border_pixel
);
1204 x_display_cursor (frame
, 1);
1208 frame_unhighlight (frame
)
1209 struct frame
*frame
;
1211 if (! EQ (Vx_no_window_manager
, Qnil
))
1212 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1213 frame
->display
.x
->border_tile
);
1214 x_display_cursor (frame
, 1);
1216 #else /* ! defined (HAVE_X11) */
1217 /* Dump the border-emphasis of frame F.
1218 If F is selected, this is a lining of the same color as the border,
1219 just within the border, occupying a portion of the internal border.
1220 If F is not selected, it is background in the same place.
1221 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1223 ALWAYS = 1 is used when a frame becomes selected or deselected.
1224 In that case, we also turn the cursor off and on again
1225 so it will appear in the proper shape (solid if selected; else hollow.) */
1228 dumpborder (f
, always
)
1232 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1233 int width
= PIXEL_WIDTH (f
);
1234 int height
= PIXEL_HEIGHT (f
);
1237 if (f
!= selected_frame
)
1242 pixel
= f
->display
.x
->background_pixel
;
1246 pixel
= f
->display
.x
->border_pixel
;
1249 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1250 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1251 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1253 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1257 x_display_cursor (f
, 1);
1259 #endif /* ! defined (HAVE_X11) */
1261 static void XTframe_rehighlight ();
1263 /* The focus has changed. Update the frames as necessary to reflect
1264 the new situation. Note that we can't change the selected frame
1265 here, because the lisp code we are interrupting might become confused.
1266 Each event gets marked with the frame in which it occured, so the
1267 lisp code can tell when the switch took place by examining the events. */
1270 x_new_focus_frame (frame
)
1271 struct frame
*frame
;
1273 struct frame
*old_focus
= x_focus_frame
;
1274 int events_enqueued
= 0;
1276 if (frame
!= x_focus_frame
)
1278 /* Set this before calling other routines, so that they see
1279 the correct value of x_focus_frame. */
1280 x_focus_frame
= frame
;
1282 if (old_focus
&& old_focus
->auto_lower
)
1283 x_lower_frame (old_focus
);
1286 selected_frame
= frame
;
1287 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1288 Lisp_Frame
, selected_frame
);
1289 Fselect_window (selected_frame
->selected_window
);
1290 choose_minibuf_frame ();
1293 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1294 x_raise_frame (x_focus_frame
);
1297 XTframe_rehighlight ();
1301 /* The focus has changed, or we have redirected a frame's focus to
1302 another frame (this happens when a frame uses a surrogate
1303 minibuffer frame). Shift the highlight as appropriate. */
1305 XTframe_rehighlight ()
1307 struct frame
*old_highlight
= x_highlight_frame
;
1312 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1313 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1315 if (! FRAME_LIVE_P (x_highlight_frame
))
1317 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1318 x_highlight_frame
= x_focus_frame
;
1322 x_highlight_frame
= 0;
1324 if (x_highlight_frame
!= old_highlight
)
1327 frame_unhighlight (old_highlight
);
1328 if (x_highlight_frame
)
1329 frame_highlight (x_highlight_frame
);
1333 /* Mouse clicks and mouse movement. Rah. */
1336 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1337 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1338 that the glyph at X, Y occupies, if BOUNDS != 0. */
1340 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1342 register unsigned int pix_x
, pix_y
;
1343 register int *x
, *y
;
1346 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1347 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1351 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1352 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1353 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1354 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1357 if (pix_x
< 0) pix_x
= 0;
1358 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1360 if (pix_y
< 0) pix_y
= 0;
1361 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1367 /* Any buttons grabbed. */
1368 unsigned int x_mouse_grabbed
;
1370 /* Which modifier keys are on which modifier bits?
1372 With each keystroke, X returns eight bits indicating which modifier
1373 keys were held down when the key was pressed. The interpretation
1374 of the top five modifier bits depends on what keys are attached
1375 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1378 x_meta_mod_mask is a mask containing the bits used for the meta key.
1379 It may have more than one bit set, if more than one modifier bit
1380 has meta keys on it. Basically, if EVENT is a KeyPress event,
1381 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1383 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1384 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1385 only be affected by the lock modifier bit if XK_Shift_Lock is in
1386 use; XK_Caps_Lock should only affect alphabetic keys. With this
1387 arrangement, the lock modifier should shift the character if
1388 (EVENT.state & x_shift_lock_mask) != 0. */
1389 static int x_meta_mod_mask
, x_shift_lock_mask
;
1391 /* These are like x_meta_mod_mask, but for different modifiers. */
1392 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1394 /* Initialize mode_switch_bit and modifier_meaning. */
1396 x_find_modifier_meanings ()
1398 int min_code
, max_code
;
1401 XModifierKeymap
*mods
;
1403 x_meta_mod_mask
= 0;
1404 x_shift_lock_mask
= 0;
1406 x_super_mod_mask
= 0;
1407 x_hyper_mod_mask
= 0;
1410 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1412 min_code
= x_current_display
->min_keycode
;
1413 max_code
= x_current_display
->max_keycode
;
1416 syms
= XGetKeyboardMapping (x_current_display
,
1417 min_code
, max_code
- min_code
+ 1,
1419 mods
= XGetModifierMapping (x_current_display
);
1421 /* Scan the modifier table to see which modifier bits the Meta and
1422 Alt keysyms are on. */
1424 int row
, col
; /* The row and column in the modifier table. */
1426 for (row
= 3; row
< 8; row
++)
1427 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1430 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1432 /* Are any of this keycode's keysyms a meta key? */
1436 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1438 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1444 x_meta_mod_mask
|= (1 << row
);
1449 x_alt_mod_mask
|= (1 << row
);
1454 x_hyper_mod_mask
|= (1 << row
);
1459 x_super_mod_mask
|= (1 << row
);
1463 /* Ignore this if it's not on the lock modifier. */
1464 if ((1 << row
) == LockMask
)
1465 x_shift_lock_mask
= LockMask
;
1473 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1474 if (! x_meta_mod_mask
)
1476 x_meta_mod_mask
= x_alt_mod_mask
;
1480 XFree ((char *) syms
);
1481 XFreeModifiermap (mods
);
1485 /* Convert a set of X modifier bits to the proper form for a
1486 struct input_event modifiers value. */
1489 x_convert_modifiers (state
)
1492 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1493 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1494 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1495 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1496 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1497 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1500 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1502 If the event is a button press, then note that we have grabbed
1506 construct_mouse_click (result
, event
, f
)
1507 struct input_event
*result
;
1508 XButtonEvent
*event
;
1511 /* Make the event type no_event; we'll change that when we decide
1513 result
->kind
= mouse_click
;
1514 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1515 result
->timestamp
= event
->time
;
1516 result
->modifiers
= (x_convert_modifiers (event
->state
)
1517 | (event
->type
== ButtonRelease
1521 /* Notice if the mouse is still grabbed. */
1522 if (event
->type
== ButtonPress
)
1524 if (! x_mouse_grabbed
)
1525 Vmouse_depressed
= Qt
;
1526 x_mouse_grabbed
|= (1 << event
->button
);
1528 else if (event
->type
== ButtonRelease
)
1530 x_mouse_grabbed
&= ~(1 << event
->button
);
1531 if (!x_mouse_grabbed
)
1532 Vmouse_depressed
= Qnil
;
1538 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1539 XFASTINT (result
->x
) = column
;
1540 XFASTINT (result
->y
) = row
;
1541 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1546 /* Mouse movement. Rah.
1548 In order to avoid asking for motion events and then throwing most
1549 of them away or busy-polling the server for mouse positions, we ask
1550 the server for pointer motion hints. This means that we get only
1551 one event per group of mouse movements. "Groups" are delimited by
1552 other kinds of events (focus changes and button clicks, for
1553 example), or by XQueryPointer calls; when one of these happens, we
1554 get another MotionNotify event the next time the mouse moves. This
1555 is at least as efficient as getting motion events when mouse
1556 tracking is on, and I suspect only negligibly worse when tracking
1559 The silly O'Reilly & Associates Nutshell guides barely document
1560 pointer motion hints at all (I think you have to infer how they
1561 work from an example), and the description of XQueryPointer doesn't
1562 mention that calling it causes you to get another motion hint from
1563 the server, which is very important. */
1565 /* Where the mouse was last time we reported a mouse event. */
1566 static FRAME_PTR last_mouse_frame
;
1567 static XRectangle last_mouse_glyph
;
1569 /* The scroll bar in which the last X motion event occurred.
1571 If the last X motion event occured in a scroll bar, we set this
1572 so XTmouse_position can know whether to report a scroll bar motion or
1575 If the last X motion event didn't occur in a scroll bar, we set this
1576 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1577 static Lisp_Object last_mouse_scroll_bar
;
1579 /* This is a hack. We would really prefer that XTmouse_position would
1580 return the time associated with the position it returns, but there
1581 doesn't seem to be any way to wrest the timestamp from the server
1582 along with the position query. So, we just keep track of the time
1583 of the last movement we received, and return that in hopes that
1584 it's somewhat accurate. */
1585 static Time last_mouse_movement_time
;
1587 /* Function to report a mouse movement to the mainstream Emacs code.
1588 The input handler calls this.
1590 We have received a mouse movement event, which is given in *event.
1591 If the mouse is over a different glyph than it was last time, tell
1592 the mainstream emacs code by setting mouse_moved. If not, ask for
1593 another motion event, so we can check again the next time it moves. */
1595 note_mouse_movement (frame
, event
)
1597 XMotionEvent
*event
;
1600 last_mouse_movement_time
= event
->time
;
1602 /* Has the mouse moved off the glyph it was on at the last sighting? */
1603 if (event
->x
< last_mouse_glyph
.x
1604 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1605 || event
->y
< last_mouse_glyph
.y
1606 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1609 last_mouse_scroll_bar
= Qnil
;
1613 /* It's on the same glyph. Call XQueryPointer so we'll get an
1614 event the next time the mouse moves and we can see if it's
1615 *still* on the same glyph. */
1618 XQueryPointer (event
->display
, event
->window
,
1619 (Window
*) &dummy
, (Window
*) &dummy
,
1620 &dummy
, &dummy
, &dummy
, &dummy
,
1621 (unsigned int *) &dummy
);
1625 static struct scroll_bar
*x_window_to_scroll_bar ();
1626 static void x_scroll_bar_report_motion ();
1628 /* Return the current position of the mouse.
1630 If the mouse movement started in a scroll bar, set *f, *bar_window,
1631 and *part to the frame, window, and scroll bar part that the mouse
1632 is over. Set *x and *y to the portion and whole of the mouse's
1633 position on the scroll bar.
1635 If the mouse movement started elsewhere, set *f to the frame the
1636 mouse is on, *bar_window to nil, and *x and *y to the character cell
1639 Set *time to the server timestamp for the time at which the mouse
1640 was at this position.
1642 This clears the mouse_moved flag, so we can wait for the next mouse
1643 movement. This also calls XQueryPointer, which will cause the
1644 server to give us another MotionNotify when the mouse moves
1648 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1650 Lisp_Object
*bar_window
;
1651 enum scroll_bar_part
*part
;
1653 unsigned long *time
;
1657 if (! NILP (last_mouse_scroll_bar
))
1658 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1664 Window dummy_window
;
1668 last_mouse_scroll_bar
= Qnil
;
1670 /* Figure out which root window we're on. */
1671 XQueryPointer (x_current_display
,
1672 DefaultRootWindow (x_current_display
),
1674 /* The root window which contains the pointer. */
1677 /* Trash which we can't trust if the pointer is on
1678 a different screen. */
1681 /* The position on that root window. */
1684 /* More trash we can't trust. */
1687 /* Modifier keys and pointer buttons, about which
1689 (unsigned int *) &dummy
);
1691 /* Now we have a position on the root; find the innermost window
1692 containing the pointer. */
1696 int parent_x
, parent_y
;
1701 XTranslateCoordinates (x_current_display
,
1703 /* From-window, to-window. */
1706 /* From-position, to-position. */
1707 root_x
, root_y
, &win_x
, &win_y
,
1720 /* Now we know that:
1721 win is the innermost window containing the pointer
1722 (XTC says it has no child containing the pointer),
1723 win_x and win_y are the pointer's position in it
1724 (XTC did this the last time through), and
1725 parent_x and parent_y are the pointer's position in win's parent.
1726 (They are what win_x and win_y were when win was child.
1727 If win is the root window, it has no parent, and
1728 parent_{x,y} are invalid, but that's okay, because we'll
1729 never use them in that case.) */
1731 /* Is win one of our frames? */
1732 *f
= x_window_to_frame (win
);
1734 /* If not, is it one of our scroll bars? */
1737 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1741 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1749 pixel_to_glyph_coords (*f
, win_x
, win_y
, &win_x
, &win_y
,
1754 XSET (*x
, Lisp_Int
, win_x
);
1755 XSET (*y
, Lisp_Int
, win_y
);
1756 *time
= last_mouse_movement_time
;
1764 #else /* ! defined (HAVE_X11) */
1765 #define XEvent XKeyPressedEvent
1766 #endif /* ! defined (HAVE_X11) */
1768 /* Scroll bar support. */
1770 /* Given an X window ID, find the struct scroll_bar which manages it.
1771 This can be called in GC, so we have to make sure to strip off mark
1773 static struct scroll_bar
*
1774 x_window_to_scroll_bar (window_id
)
1777 Lisp_Object tail
, frame
;
1779 for (tail
= Vframe_list
;
1780 XGCTYPE (tail
) == Lisp_Cons
;
1781 tail
= XCONS (tail
)->cdr
)
1783 Lisp_Object frame
= XCONS (tail
)->car
;
1784 Lisp_Object bar
, condemned
;
1786 /* All elements of Vframe_list should be frames. */
1787 if (XGCTYPE (frame
) != Lisp_Frame
)
1790 /* Scan this frame's scroll bar list for a scroll bar with the
1792 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1793 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1794 /* This trick allows us to search both the ordinary and
1795 condemned scroll bar lists with one loop. */
1796 ! GC_NILP (bar
) || (bar
= condemned
,
1799 bar
= XSCROLL_BAR(bar
)->next
)
1800 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1801 return XSCROLL_BAR (bar
);
1807 /* Open a new X window to serve as a scroll bar, and return the
1808 scroll bar vector for it. */
1809 static struct scroll_bar
*
1810 x_scroll_bar_create (window
, top
, left
, width
, height
)
1811 struct window
*window
;
1812 int top
, left
, width
, height
;
1814 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1815 struct scroll_bar
*bar
=
1816 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1821 XSetWindowAttributes a
;
1824 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1825 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1826 | ButtonMotionMask
| PointerMotionHintMask
1828 a
.cursor
= x_vertical_scroll_bar_cursor
;
1830 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1832 SET_SCROLL_BAR_X_WINDOW
1834 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1836 /* Position and size of scroll bar. */
1837 left
, top
, width
, height
,
1839 /* Border width, depth, class, and visual. */
1840 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1846 XSET (bar
->window
, Lisp_Window
, window
);
1847 XSET (bar
->top
, Lisp_Int
, top
);
1848 XSET (bar
->left
, Lisp_Int
, left
);
1849 XSET (bar
->width
, Lisp_Int
, width
);
1850 XSET (bar
->height
, Lisp_Int
, height
);
1851 XSET (bar
->start
, Lisp_Int
, 0);
1852 XSET (bar
->end
, Lisp_Int
, 0);
1853 bar
->dragging
= Qnil
;
1855 /* Add bar to its frame's list of scroll bars. */
1856 bar
->next
= FRAME_SCROLL_BARS (frame
);
1858 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
1859 if (! NILP (bar
->next
))
1860 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1862 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
1869 /* Draw BAR's handle in the proper position.
1870 If the handle is already drawn from START to END, don't bother
1871 redrawing it, unless REBUILD is non-zero; in that case, always
1872 redraw it. (REBUILD is handy for drawing the handle after expose
1875 Normally, we want to constrain the start and end of the handle to
1876 fit inside its rectangle, but if the user is dragging the scroll bar
1877 handle, we want to let them drag it down all the way, so that the
1878 bar's top is as far down as it goes; otherwise, there's no way to
1879 move to the very end of the buffer. */
1881 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1882 struct scroll_bar
*bar
;
1886 int dragging
= ! NILP (bar
->dragging
);
1887 Window w
= SCROLL_BAR_X_WINDOW (bar
);
1888 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1890 /* If the display is already accurate, do nothing. */
1892 && start
== XINT (bar
->start
)
1893 && end
== XINT (bar
->end
))
1899 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
1900 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
1901 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
1903 /* Make sure the values are reasonable, and try to preserve
1904 the distance between start and end. */
1906 int length
= end
- start
;
1910 else if (start
> top_range
)
1912 end
= start
+ length
;
1916 else if (end
> top_range
&& ! dragging
)
1920 /* Store the adjusted setting in the scroll bar. */
1921 XSET (bar
->start
, Lisp_Int
, start
);
1922 XSET (bar
->end
, Lisp_Int
, end
);
1924 /* Clip the end position, just for display. */
1925 if (end
> top_range
)
1928 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1929 below top positions, to make sure the handle is always at least
1930 that many pixels tall. */
1931 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
1933 /* Draw the empty space above the handle. Note that we can't clear
1934 zero-height areas; that means "clear to end of window." */
1936 XClearArea (x_current_display
, w
,
1938 /* x, y, width, height, and exposures. */
1939 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1940 VERTICAL_SCROLL_BAR_TOP_BORDER
,
1941 inside_width
, start
,
1944 /* Draw the handle itself. */
1945 XFillRectangle (x_current_display
, w
, gc
,
1947 /* x, y, width, height */
1948 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1949 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
1950 inside_width
, end
- start
);
1953 /* Draw the empty space below the handle. Note that we can't
1954 clear zero-height areas; that means "clear to end of window." */
1955 if (end
< inside_height
)
1956 XClearArea (x_current_display
, w
,
1958 /* x, y, width, height, and exposures. */
1959 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1960 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
1961 inside_width
, inside_height
- end
,
1969 /* Move a scroll bar around on the screen, to accomodate changing
1970 window configurations. */
1972 x_scroll_bar_move (bar
, top
, left
, width
, height
)
1973 struct scroll_bar
*bar
;
1974 int top
, left
, width
, height
;
1980 unsigned int mask
= 0;
1987 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
1988 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
1989 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
1990 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
1993 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
1997 XSET (bar
->left
, Lisp_Int
, left
);
1998 XSET (bar
->top
, Lisp_Int
, top
);
1999 XSET (bar
->width
, Lisp_Int
, width
);
2000 XSET (bar
->height
, Lisp_Int
, height
);
2005 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2008 x_scroll_bar_remove (bar
)
2009 struct scroll_bar
*bar
;
2011 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2015 /* Destroy the window. */
2016 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2018 /* Disassociate this scroll bar from its window. */
2019 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2024 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2025 that we are displaying PORTION characters out of a total of WHOLE
2026 characters, starting at POSITION. If WINDOW has no scroll bar,
2029 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2030 struct window
*window
;
2031 int portion
, whole
, position
;
2033 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2034 int top
= XINT (window
->top
);
2035 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2036 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2038 /* Where should this scroll bar be, pixelwise? */
2039 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2040 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2041 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2042 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2044 struct scroll_bar
*bar
;
2046 /* Does the scroll bar exist yet? */
2047 if (NILP (window
->vertical_scroll_bar
))
2048 bar
= x_scroll_bar_create (window
,
2049 pixel_top
, pixel_left
,
2050 pixel_width
, pixel_height
);
2053 /* It may just need to be moved and resized. */
2054 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2055 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2058 /* Set the scroll bar's current state, unless we're currently being
2060 if (NILP (bar
->dragging
))
2063 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2066 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2069 int start
= (position
* top_range
) / whole
;
2070 int end
= ((position
+ portion
) * top_range
) / whole
;
2072 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2076 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2080 /* The following three hooks are used when we're doing a thorough
2081 redisplay of the frame. We don't explicitly know which scroll bars
2082 are going to be deleted, because keeping track of when windows go
2083 away is a real pain - "Can you say set-window-configuration, boys
2084 and girls?" Instead, we just assert at the beginning of redisplay
2085 that *all* scroll bars are to be removed, and then save a scroll bar
2086 from the fiery pit when we actually redisplay its window. */
2088 /* Arrange for all scroll bars on FRAME to be removed at the next call
2089 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2090 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2092 XTcondemn_scroll_bars (frame
)
2095 /* The condemned list should be empty at this point; if it's not,
2096 then the rest of Emacs isn't using the condemn/redeem/judge
2097 protocol correctly. */
2098 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2101 /* Move them all to the "condemned" list. */
2102 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2103 FRAME_SCROLL_BARS (frame
) = Qnil
;
2106 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2107 Note that WINDOW isn't necessarily condemned at all. */
2109 XTredeem_scroll_bar (window
)
2110 struct window
*window
;
2112 struct scroll_bar
*bar
;
2114 /* We can't redeem this window's scroll bar if it doesn't have one. */
2115 if (NILP (window
->vertical_scroll_bar
))
2118 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2120 /* Unlink it from the condemned list. */
2122 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2124 if (NILP (bar
->prev
))
2126 /* If the prev pointer is nil, it must be the first in one of
2128 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2129 /* It's not condemned. Everything's fine. */
2131 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2132 window
->vertical_scroll_bar
))
2133 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2135 /* If its prev pointer is nil, it must be at the front of
2136 one or the other! */
2140 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2142 if (! NILP (bar
->next
))
2143 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2145 bar
->next
= FRAME_SCROLL_BARS (f
);
2147 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2148 if (! NILP (bar
->next
))
2149 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2153 /* Remove all scroll bars on FRAME that haven't been saved since the
2154 last call to `*condemn_scroll_bars_hook'. */
2156 XTjudge_scroll_bars (f
)
2159 Lisp_Object bar
, next
;
2161 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2163 /* Clear out the condemned list now so we won't try to process any
2164 more events on the hapless scroll bars. */
2165 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2167 for (; ! NILP (bar
); bar
= next
)
2169 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2171 x_scroll_bar_remove (b
);
2174 b
->next
= b
->prev
= Qnil
;
2177 /* Now there should be no references to the condemned scroll bars,
2178 and they should get garbage-collected. */
2182 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2184 This may be called from a signal handler, so we have to ignore GC
2187 x_scroll_bar_expose (bar
, event
)
2188 struct scroll_bar
*bar
;
2191 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2192 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2196 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2198 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2199 XDrawRectangle (x_current_display
, w
, gc
,
2201 /* x, y, width, height */
2202 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2204 /* Draw another line to make the extra-thick border on the right. */
2205 XFillRectangle (x_current_display
, w
, gc
,
2207 /* x, y, width, height */
2208 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2213 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2214 is set to something other than no_event, it is enqueued.
2216 This may be called from a signal handler, so we have to ignore GC
2219 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2220 struct scroll_bar
*bar
;
2222 struct input_event
*emacs_event
;
2224 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2227 emacs_event
->kind
= scroll_bar_click
;
2228 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2229 emacs_event
->modifiers
=
2230 (x_convert_modifiers (event
->xbutton
.state
)
2231 | (event
->type
== ButtonRelease
2234 emacs_event
->frame_or_window
= bar
->window
;
2235 emacs_event
->timestamp
= event
->xbutton
.time
;
2237 int internal_height
=
2238 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2240 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2241 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2244 if (y
> top_range
) y
= top_range
;
2246 if (y
< XINT (bar
->start
))
2247 emacs_event
->part
= scroll_bar_above_handle
;
2248 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2249 emacs_event
->part
= scroll_bar_handle
;
2251 emacs_event
->part
= scroll_bar_below_handle
;
2253 /* If the user has just clicked on the handle, record where they're
2255 if (event
->type
== ButtonPress
2256 && emacs_event
->part
== scroll_bar_handle
)
2257 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2259 /* If the user has released the handle, set it to its final position. */
2260 if (event
->type
== ButtonRelease
2261 && ! NILP (bar
->dragging
))
2263 int new_start
= y
- XINT (bar
->dragging
);
2264 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2266 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2267 bar
->dragging
= Qnil
;
2270 /* Clicks on the handle are always reported as occuring at the top of
2272 if (emacs_event
->part
== scroll_bar_handle
)
2273 emacs_event
->x
= bar
->start
;
2275 XSET (emacs_event
->x
, Lisp_Int
, y
);
2277 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2281 /* Handle some mouse motion while someone is dragging the scroll bar.
2283 This may be called from a signal handler, so we have to ignore GC
2286 x_scroll_bar_note_movement (bar
, event
)
2287 struct scroll_bar
*bar
;
2290 last_mouse_movement_time
= event
->xmotion
.time
;
2293 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2295 /* If we're dragging the bar, display it. */
2296 if (! GC_NILP (bar
->dragging
))
2298 /* Where should the handle be now? */
2299 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2301 if (new_start
!= XINT (bar
->start
))
2303 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2305 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2309 /* Call XQueryPointer so we'll get an event the next time the mouse
2310 moves and we can see *still* on the same position. */
2314 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2315 (Window
*) &dummy
, (Window
*) &dummy
,
2316 &dummy
, &dummy
, &dummy
, &dummy
,
2317 (unsigned int *) &dummy
);
2321 /* Return information to the user about the current position of the mouse
2322 on the scroll bar. */
2324 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2326 Lisp_Object
*bar_window
;
2327 enum scroll_bar_part
*part
;
2329 unsigned long *time
;
2331 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2336 /* Get the mouse's position relative to the scroll bar window, and
2339 Window dummy_window
;
2341 unsigned int dummy_mask
;
2343 if (! XQueryPointer (x_current_display
,
2344 SCROLL_BAR_X_WINDOW (bar
),
2346 /* Root, child, root x and root y. */
2347 &dummy_window
, &dummy_window
,
2348 &dummy_coord
, &dummy_coord
,
2350 /* Position relative to scroll bar. */
2353 /* Mouse buttons and modifier keys. */
2362 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2363 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2365 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2367 if (! NILP (bar
->dragging
))
2368 win_y
-= XINT (bar
->dragging
);
2372 if (win_y
> top_range
)
2375 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2376 *bar_window
= bar
->window
;
2378 if (! NILP (bar
->dragging
))
2379 *part
= scroll_bar_handle
;
2380 else if (win_y
< XINT (bar
->start
))
2381 *part
= scroll_bar_above_handle
;
2382 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2383 *part
= scroll_bar_handle
;
2385 *part
= scroll_bar_below_handle
;
2387 XSET (*x
, Lisp_Int
, win_y
);
2388 XSET (*y
, Lisp_Int
, top_range
);
2389 *time
= last_mouse_movement_time
;
2393 last_mouse_scroll_bar
= Qnil
;
2400 /* The screen has been cleared so we may have changed foreground or
2401 background colors, and the scroll bars may need to be redrawn.
2402 Clear out the scroll bars, and ask for expose events, so we can
2405 x_scroll_bar_clear (f
)
2410 for (bar
= FRAME_SCROLL_BARS (f
);
2411 XTYPE (bar
) == Lisp_Vector
;
2412 bar
= XSCROLL_BAR (bar
)->next
)
2413 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2419 /* The main X event-reading loop - XTread_socket. */
2421 /* Timestamp of enter window event. This is only used by XTread_socket,
2422 but we have to put it out here, since static variables within functions
2423 sometimes don't work. */
2424 static Time enter_timestamp
;
2426 /* This holds the state XLookupString needs to implement dead keys
2427 and other tricks known as "compose processing". _X Window System_
2428 says that a portable program can't use this, but Stephen Gildea assures
2429 me that letting the compiler initialize it to zeros will work okay.
2431 This must be defined outside of XTread_socket, for the same reasons
2432 given for enter_timestamp, above. */
2433 static XComposeStatus compose_status
;
2435 /* Communication with window managers. */
2436 Atom Xatom_wm_protocols
;
2438 /* Kinds of protocol things we may receive. */
2439 Atom Xatom_wm_take_focus
;
2440 Atom Xatom_wm_save_yourself
;
2441 Atom Xatom_wm_delete_window
;
2443 /* Other WM communication */
2444 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2445 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2447 /* Window manager communication. */
2448 Atom Xatom_wm_change_state
;
2450 /* Record the last 100 characters stored
2451 to help debug the loss-of-chars-during-GC problem. */
2453 short temp_buffer
[100];
2455 /* Read events coming from the X server.
2456 This routine is called by the SIGIO handler.
2457 We return as soon as there are no more events to be read.
2459 Events representing keys are stored in buffer BUFP,
2460 which can hold up to NUMCHARS characters.
2461 We return the number of characters stored into the buffer,
2462 thus pretending to be `read'.
2464 WAITP is nonzero if we should block until input arrives.
2465 EXPECTED is nonzero if the caller knows input is available. */
2468 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2470 register struct input_event
*bufp
;
2471 register int numchars
;
2478 int items_pending
; /* How many items are in the X queue. */
2485 if (x_input_blocked
)
2487 x_pending_input
= 1;
2491 x_pending_input
= 0;
2495 abort (); /* Don't think this happens. */
2498 /* If available, Xlib uses FIOSNBIO to make the socket
2499 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2500 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2501 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2502 fcntl (fileno (stdin
), F_SETFL
, 0);
2503 #endif /* ! defined (FIOSNBIO) */
2507 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2509 extern int read_alarm_should_throw
;
2510 read_alarm_should_throw
= 1;
2511 XPeekEvent (XDISPLAY
&event
);
2512 read_alarm_should_throw
= 0;
2514 #endif /* HAVE_SELECT */
2517 while (XStuffPending () != 0)
2519 XNextEvent (XDISPLAY
&event
);
2527 if (event
.xclient
.message_type
== Xatom_wm_protocols
2528 && event
.xclient
.format
== 32)
2530 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2532 f
= x_window_to_frame (event
.xclient
.window
);
2534 x_focus_on_frame (f
);
2535 /* Not certain about handling scroll bars here */
2537 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2539 /* Save state modify the WM_COMMAND property to
2540 something which can reinstate us. This notifies
2541 the session manager, who's looking for such a
2542 PropertyNotify. Can restart processing when
2543 a keyboard or mouse event arrives. */
2548 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2550 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2558 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2561 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2565 new_x
= event
.xclient
.data
.s
[0];
2566 new_y
= event
.xclient
.data
.s
[1];
2571 #ifdef NEW_SELECTIONS
2572 case SelectionNotify
:
2573 x_handle_selection_notify (&event
);
2577 case SelectionClear
: /* Someone has grabbed ownership. */
2578 #ifdef NEW_SELECTIONS
2580 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2585 bufp
->kind
= selection_clear_event
;
2586 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2587 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2588 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2595 x_disown_selection (event
.xselectionclear
.window
,
2596 event
.xselectionclear
.selection
,
2597 event
.xselectionclear
.time
);
2601 case SelectionRequest
: /* Someone wants our selection. */
2602 #ifdef NEW_SELECTIONS
2604 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2609 bufp
->kind
= selection_request_event
;
2610 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2611 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2612 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2613 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2614 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2615 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2622 x_answer_selection_request (event
);
2626 case PropertyNotify
:
2627 #ifdef NEW_SELECTIONS
2628 x_handle_property_notify (&event
);
2630 /* If we're being told about a root window property, then it's
2631 a cut buffer change. */
2632 if (event
.xproperty
.window
== ROOT_WINDOW
)
2633 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2635 /* Otherwise, we're probably handling an incremental
2636 selection transmission. */
2639 /* If we were to do this synchronously, there'd be no worry
2640 about re-selecting. */
2641 x_send_incremental (event
);
2647 f
= x_window_to_frame (event
.xexpose
.window
);
2650 if (f
->async_visible
== 0)
2652 f
->async_visible
= 1;
2653 f
->async_iconified
= 0;
2654 SET_FRAME_GARBAGED (f
);
2658 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2659 event
.xexpose
.x
, event
.xexpose
.y
,
2660 event
.xexpose
.width
, event
.xexpose
.height
);
2665 struct scroll_bar
*bar
2666 = x_window_to_scroll_bar (event
.xexpose
.window
);
2669 x_scroll_bar_expose (bar
, &event
);
2673 case GraphicsExpose
: /* This occurs when an XCopyArea's
2674 source area was obscured or not
2676 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2680 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2681 event
.xgraphicsexpose
.width
,
2682 event
.xgraphicsexpose
.height
);
2686 case NoExpose
: /* This occurs when an XCopyArea's
2687 source area was completely
2690 #else /* ! defined (HAVE_X11) */
2692 if (event
.subwindow
!= 0)
2693 break; /* duplicate event */
2694 f
= x_window_to_frame (event
.window
);
2695 if (event
.window
== f
->display
.x
->icon_desc
)
2698 f
->async_iconified
= 1;
2700 if (event
.window
== FRAME_X_WINDOW (f
))
2702 /* Say must check all windows' needs_exposure flags. */
2703 expose_all_windows
= 1;
2704 f
->display
.x
->needs_exposure
= 1;
2705 f
->async_visible
= 1;
2710 if (event
.subwindow
!= 0)
2711 break; /* duplicate event */
2712 f
= x_window_to_frame (event
.window
);
2713 if (event
.window
== f
->display
.x
->icon_desc
)
2718 /* If window already needs full redraw, ignore this rectangle. */
2719 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2721 /* Put the event on the queue of rectangles to redraw. */
2722 if (enqueue_event (&event
, &x_expose_queue
))
2723 /* If it is full, we can't record the rectangle,
2724 so redraw this entire window. */
2726 /* Say must check all windows' needs_exposure flags. */
2727 expose_all_windows
= 1;
2728 f
->display
.x
->needs_exposure
= 1;
2733 /* This should happen only when we are expecting it,
2734 in x_read_exposes. */
2736 #endif /* ! defined (HAVE_X11) */
2740 f
= x_window_to_frame (event
.xunmap
.window
);
2741 if (f
) /* F may no longer exist if
2742 the frame was deleted. */
2744 /* While a frame is unmapped, display generation is
2745 disabled; you don't want to spend time updating a
2746 display that won't ever be seen. */
2747 f
->async_visible
= 0;
2752 f
= x_window_to_frame (event
.xmap
.window
);
2755 f
->async_visible
= 1;
2756 f
->async_iconified
= 0;
2758 /* wait_reading_process_input will notice this and update
2759 the frame's display structures. */
2760 SET_FRAME_GARBAGED (f
);
2764 /* Turn off processing if we become fully obscured. */
2765 case VisibilityNotify
:
2768 #else /* ! defined (HAVE_X11) */
2770 f
= x_window_to_frame (event
.window
);
2771 if (event
.window
== f
->display
.x
->icon_desc
)
2772 f
->async_iconified
= 0;
2773 if (event
.window
== FRAME_X_WINDOW (f
))
2774 f
->async_visible
= 0;
2776 #endif /* ! defined (HAVE_X11) */
2780 f
= x_window_to_frame (event
.xkey
.window
);
2785 char copy_buffer
[80];
2788 event
.xkey
.state
|= extra_keyboard_modifiers
;
2789 modifiers
= event
.xkey
.state
;
2791 /* Some keyboards generate different characters
2792 depending on the state of the meta key, in an attempt
2793 to support non-English typists. It would be nice to
2794 keep this functionality somehow, but for now, we will
2795 just clear the meta-key flag to get the 'pure' character. */
2796 event
.xkey
.state
&= ~Mod1Mask
;
2798 /* This will have to go some day... */
2800 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2803 /* Strip off the vendor-specific keysym bit, and take a shot
2804 at recognizing the codes. HP servers have extra keysyms
2805 that fit into the MiscFunctionKey category. */
2810 if ((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
2811 || keysym
== XK_Delete
2812 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2813 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < 0xff80 */
2814 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2815 || IsFunctionKey (keysym
)) /* 0xffbe <= x < 0xffe1 */
2817 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2819 temp_buffer
[temp_index
++] = keysym
;
2820 bufp
->kind
= non_ascii_keystroke
;
2821 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff00);
2822 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2823 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2824 bufp
->timestamp
= event
.xkey
.time
;
2829 else if (numchars
> nbytes
)
2833 for (i
= 0; i
< nbytes
; i
++)
2835 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2837 temp_buffer
[temp_index
++] = copy_buffer
[i
];
2838 bufp
->kind
= ascii_keystroke
;
2839 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2840 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2841 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2842 bufp
->timestamp
= event
.xkey
.time
;
2856 #else /* ! defined (HAVE_X11) */
2859 register char *where_mapping
;
2861 f
= x_window_to_frame (event
.window
);
2862 /* Ignore keys typed on icon windows. */
2863 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2865 where_mapping
= XLookupMapping (&event
, &nbytes
);
2866 /* Nasty fix for arrow keys */
2867 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2869 switch (event
.detail
& 0xff)
2871 case KC_CURSOR_LEFT
:
2872 where_mapping
= "\002";
2874 case KC_CURSOR_RIGHT
:
2875 where_mapping
= "\006";
2878 where_mapping
= "\020";
2880 case KC_CURSOR_DOWN
:
2881 where_mapping
= "\016";
2886 if (numchars
- nbytes
> 0)
2890 for (i
= 0; i
< nbytes
; i
++)
2892 bufp
->kind
= ascii_keystroke
;
2893 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2894 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2895 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2903 #endif /* ! defined (HAVE_X11) */
2907 /* Here's a possible interpretation of the whole
2908 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2909 FocusIn event, you have to get a FocusOut event before you
2910 relinquish the focus. If you haven't received a FocusIn event,
2911 then a mere LeaveNotify is enough to free you. */
2914 f
= x_window_to_frame (event
.xcrossing
.window
);
2916 if (event
.xcrossing
.focus
) /* Entered Window */
2918 /* Avoid nasty pop/raise loops. */
2919 if (f
&& (!(f
->auto_raise
)
2921 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
2923 x_new_focus_frame (f
);
2924 enter_timestamp
= event
.xcrossing
.time
;
2927 else if (f
== x_focus_frame
)
2928 x_new_focus_frame (0);
2933 f
= x_window_to_frame (event
.xfocus
.window
);
2934 if (event
.xfocus
.detail
!= NotifyPointer
)
2935 x_focus_event_frame
= f
;
2937 x_new_focus_frame (f
);
2942 f
= x_window_to_frame (event
.xcrossing
.window
);
2944 if (event
.xcrossing
.focus
)
2946 if (! x_focus_event_frame
)
2947 x_new_focus_frame (0);
2949 x_new_focus_frame (f
);
2953 if (f
== x_focus_event_frame
)
2954 x_focus_event_frame
= 0;
2955 if (f
== x_focus_frame
)
2956 x_new_focus_frame (0);
2961 f
= x_window_to_frame (event
.xfocus
.window
);
2962 if (event
.xfocus
.detail
!= NotifyPointer
2963 && f
== x_focus_event_frame
)
2964 x_focus_event_frame
= 0;
2965 if (f
&& f
== x_focus_frame
)
2966 x_new_focus_frame (0);
2969 #else /* ! defined (HAVE_X11) */
2972 if ((event
.detail
& 0xFF) == 1)
2973 break; /* Coming from our own subwindow */
2974 if (event
.subwindow
!= 0)
2975 break; /* Entering our own subwindow. */
2978 f
= x_window_to_frame (event
.window
);
2981 x_new_focus_frame (f
);
2986 if ((event
.detail
& 0xFF) == 1)
2987 break; /* Entering our own subwindow */
2988 if (event
.subwindow
!= 0)
2989 break; /* Leaving our own subwindow. */
2992 if (x_focus_frame
== 0
2993 && x_input_frame
!= 0
2994 && x_input_frame
== x_window_to_frame (event
.window
)
2995 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3000 frame_unhighlight (f
);
3003 #endif /* ! defined (HAVE_X11) */
3008 f
= x_window_to_frame (event
.xmotion
.window
);
3010 note_mouse_movement (f
, &event
.xmotion
);
3013 struct scroll_bar
*bar
=
3014 x_window_to_scroll_bar (event
.xmotion
.window
);
3017 x_scroll_bar_note_movement (bar
, &event
);
3022 case ConfigureNotify
:
3023 f
= x_window_to_frame (event
.xconfigure
.window
);
3026 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3027 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3029 /* Even if the number of character rows and columns has
3030 not changed, the font size may have changed, so we need
3031 to check the pixel dimensions as well. */
3032 if (columns
!= f
->width
3033 || rows
!= f
->height
3034 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3035 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3037 change_frame_size (f
, rows
, columns
, 0, 1);
3038 SET_FRAME_GARBAGED (f
);
3041 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3042 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3043 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3044 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3051 /* If we decide we want to generate an event to be seen
3052 by the rest of Emacs, we put it here. */
3053 struct input_event emacs_event
;
3054 emacs_event
.kind
= no_event
;
3056 f
= x_window_to_frame (event
.xbutton
.window
);
3059 if (!x_focus_frame
|| (f
== x_focus_frame
))
3060 construct_mouse_click (&emacs_event
,
3065 struct scroll_bar
*bar
=
3066 x_window_to_scroll_bar (event
.xbutton
.window
);
3069 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3072 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3074 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3082 #else /* ! defined (HAVE_X11) */
3084 case ButtonReleased
:
3085 f
= x_window_to_frame (event
.window
);
3088 if (event
.window
== f
->display
.x
->icon_desc
)
3090 x_make_frame_visible (f
);
3092 if (warp_mouse_on_deiconify
)
3093 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3096 if (event
.window
== FRAME_X_WINDOW (f
))
3102 enqueue_event (&event
, &x_mouse_queue
);
3105 bufp
->kind
= ascii_keystroke
;
3106 bufp
->code
= (char) 'X' & 037; /* C-x */
3107 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3108 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3111 bufp
->kind
= ascii_keystroke
;
3112 bufp
->code
= (char) 0; /* C-@ */
3113 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3114 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3121 #endif /* ! defined (HAVE_X11) */
3125 case CirculateNotify
:
3127 case CirculateRequest
:
3130 #endif /* ! defined (HAVE_X11) */
3133 /* Someone has changed the keyboard mapping - update the
3135 switch (event
.xmapping
.request
)
3137 case MappingModifier
:
3138 x_find_modifier_meanings ();
3139 /* This is meant to fall through. */
3140 case MappingKeyboard
:
3141 XRefreshKeyboardMapping (&event
.xmapping
);
3152 if (expected
&& ! event_found
)
3154 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3155 there is an EOF condition; in other words, that X has died.
3156 Act as if there had been a hangup. */
3158 int fd
= ConnectionNumber (x_current_display
);
3161 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3163 && !XStuffPending ())
3164 kill (getpid (), SIGHUP
);
3166 #endif /* ! defined (HAVE_SELECT) */
3170 if (updating_frame
== 0)
3171 x_do_pending_expose ();
3179 /* Read and process only Expose events
3180 until we get an ExposeCopy event; then return.
3181 This is used in insert/delete line.
3182 We assume input is already blocked. */
3188 XKeyPressedEvent event
;
3192 /* while there are more events*/
3193 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3197 if (event
.subwindow
!= 0)
3198 break; /* duplicate event */
3199 f
= x_window_to_frame (event
.window
);
3200 if (event
.window
== f
->display
.x
->icon_desc
)
3205 if (event
.window
== FRAME_X_WINDOW (f
))
3207 expose_all_windows
= 1;
3208 f
->display
.x
->needs_exposure
= 1;
3214 if (event
.subwindow
!= 0)
3215 break; /* duplicate event */
3216 f
= x_window_to_frame (event
.window
);
3217 if (event
.window
== f
->display
.x
->icon_desc
)
3222 /* If window already needs full redraw, ignore this rectangle. */
3223 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3225 /* Put the event on the queue of rectangles to redraw. */
3226 if (enqueue_event (&event
, &x_expose_queue
))
3227 /* If it is full, we can't record the rectangle,
3228 so redraw this entire window. */
3230 /* Say must check all windows' needs_exposure flags. */
3231 expose_all_windows
= 1;
3232 f
->display
.x
->needs_exposure
= 1;
3241 #endif /* HAVE_X11 */
3244 /* Drawing the cursor. */
3247 /* Draw a hollow box cursor. Don't change the inside of the box. */
3253 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3254 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3255 int width
= FONT_WIDTH (f
->display
.x
->font
);
3256 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3259 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3260 f
->display
.x
->cursor_gc
,
3261 left
, top
, width
- 1, height
- 1);
3262 #else /* ! defined (HAVE_X11) */
3263 XPixSet (FRAME_X_WINDOW (f
),
3264 left
, top
, width
, 1,
3265 f
->display
.x
->cursor_pixel
);
3267 XPixSet (FRAME_X_WINDOW (f
),
3268 left
, top
, 1, height
,
3269 f
->display
.x
->cursor_pixel
);
3271 XPixSet (FRAME_X_WINDOW (f
),
3272 left
+width
-1, top
, 1, height
,
3273 f
->display
.x
->cursor_pixel
);
3275 XPixSet (FRAME_X_WINDOW (f
),
3276 left
, top
+height
-1, width
, 1,
3277 f
->display
.x
->cursor_pixel
);
3278 #endif /* ! defined (HAVE_X11) */
3281 /* Clear the cursor of frame F to background color,
3282 and mark the cursor as not shown.
3283 This is used when the text where the cursor is
3284 is about to be rewritten. */
3292 if (! FRAME_VISIBLE_P (f
)
3293 || f
->phys_cursor_x
< 0)
3297 x_display_cursor (f
, 0);
3298 #else /* ! defined (HAVE_X11) */
3299 XPixSet (FRAME_X_WINDOW (f
),
3300 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3301 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3302 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3303 f
->display
.x
->background_pixel
);
3304 #endif /* ! defined (HAVE_X11) */
3305 f
->phys_cursor_x
= -1;
3308 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3309 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3313 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3320 CHAR_TO_PIXEL_COL (f
, column
),
3321 CHAR_TO_PIXEL_ROW (f
, row
),
3322 &glyph
, 1, highlight
, f
->display
.x
->font
);
3326 x_display_bar_cursor (f
, on
)
3330 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3332 /* This is pointless on invisible frames, and dangerous on garbaged
3333 frames; in the latter case, the frame may be in the midst of
3334 changing its size, and curs_x and curs_y may be off the frame. */
3335 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3338 if (! on
&& f
->phys_cursor_x
< 0)
3341 /* If we're not updating, then we want to use the current frame's
3342 cursor position, not our local idea of where the cursor ought to be. */
3343 if (f
!= updating_frame
)
3345 curs_x
= FRAME_CURSOR_X (f
);
3346 curs_y
= FRAME_CURSOR_Y (f
);
3349 /* If there is anything wrong with the current cursor state, remove it. */
3350 if (f
->phys_cursor_x
>= 0
3352 || f
->phys_cursor_x
!= curs_x
3353 || f
->phys_cursor_y
!= curs_y
3354 || f
->display
.x
->current_cursor
!= bar_cursor
))
3356 /* Erase the cursor by redrawing the character underneath it. */
3357 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3358 f
->phys_cursor_glyph
,
3359 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3360 f
->phys_cursor_x
= -1;
3363 /* If we now need a cursor in the new place or in the new form, do it so. */
3365 && (f
->phys_cursor_x
< 0
3366 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3368 f
->phys_cursor_glyph
3369 = ((current_glyphs
->enable
[curs_y
]
3370 && curs_x
< current_glyphs
->used
[curs_y
])
3371 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3373 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3374 f
->display
.x
->cursor_gc
,
3375 CHAR_TO_PIXEL_COL (f
, curs_x
),
3376 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3377 1, FONT_HEIGHT (f
->display
.x
->font
));
3379 f
->phys_cursor_x
= curs_x
;
3380 f
->phys_cursor_y
= curs_y
;
3382 f
->display
.x
->current_cursor
= bar_cursor
;
3385 if (updating_frame
!= f
)
3390 /* Turn the displayed cursor of frame F on or off according to ON.
3391 If ON is nonzero, where to put the cursor is specified
3392 by F->cursor_x and F->cursor_y. */
3395 x_display_box_cursor (f
, on
)
3399 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3401 /* This is pointless on invisible frames, and dangerous on garbaged
3402 frames; in the latter case, the frame may be in the midst of
3403 changing its size, and curs_x and curs_y may be off the frame. */
3404 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3407 /* If cursor is off and we want it off, return quickly. */
3408 if (!on
&& f
->phys_cursor_x
< 0)
3411 /* If we're not updating, then we want to use the current frame's
3412 cursor position, not our local idea of where the cursor ought to be. */
3413 if (f
!= updating_frame
)
3415 curs_x
= FRAME_CURSOR_X (f
);
3416 curs_y
= FRAME_CURSOR_Y (f
);
3419 /* If cursor is currently being shown and we don't want it to be
3420 or it is in the wrong place,
3421 or we want a hollow box and it's not so, (pout!)
3423 if (f
->phys_cursor_x
>= 0
3425 || f
->phys_cursor_x
!= curs_x
3426 || f
->phys_cursor_y
!= curs_y
3427 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3428 && (f
!= x_highlight_frame
))))
3430 /* Erase the cursor by redrawing the character underneath it. */
3431 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3432 f
->phys_cursor_glyph
,
3433 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3434 f
->phys_cursor_x
= -1;
3437 /* If we want to show a cursor,
3438 or we want a box cursor and it's not so,
3439 write it in the right place. */
3441 && (f
->phys_cursor_x
< 0
3442 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3443 && f
== x_highlight_frame
)))
3445 f
->phys_cursor_glyph
3446 = ((current_glyphs
->enable
[curs_y
]
3447 && curs_x
< current_glyphs
->used
[curs_y
])
3448 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3450 if (f
!= x_highlight_frame
)
3453 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3457 x_draw_single_glyph (f
, curs_y
, curs_x
,
3458 f
->phys_cursor_glyph
, 2);
3459 f
->display
.x
->current_cursor
= filled_box_cursor
;
3462 f
->phys_cursor_x
= curs_x
;
3463 f
->phys_cursor_y
= curs_y
;
3466 if (updating_frame
!= f
)
3470 x_display_cursor (f
, on
)
3474 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3475 x_display_box_cursor (f
, on
);
3476 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3477 x_display_bar_cursor (f
, on
);
3479 /* Those are the only two we have implemented! */
3485 /* Refresh bitmap kitchen sink icon for frame F
3486 when we get an expose event for it. */
3492 /* Normally, the window manager handles this function. */
3493 #else /* ! defined (HAVE_X11) */
3496 if (f
->display
.x
->icon_bitmap_flag
)
3497 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3498 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3499 icon_bitmap
, GXcopy
, AllPlanes
);
3502 extern struct frame
*selected_frame
;
3503 struct Lisp_String
*str
;
3504 unsigned char *string
;
3507 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3509 if (f
->display
.x
->icon_label
!= string
)
3511 f
->display
.x
->icon_label
= string
;
3512 XChangeWindow (f
->display
.x
->icon_desc
,
3513 XQueryWidth (string
, icon_font_info
->id
) + 10,
3514 icon_font_info
->height
+ 10);
3517 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3518 str
->size
, icon_font_info
->id
,
3519 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3522 #endif /* ! defined (HAVE_X11) */
3525 /* Make the x-window of frame F use the gnu icon bitmap. */
3534 if (FRAME_X_WINDOW (f
) == 0)
3539 XFreePixmap (x_current_display
, icon_bitmap
);
3542 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3543 gnu_bits
, gnu_width
, gnu_height
);
3544 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3545 f
->display
.x
->icon_bitmap_flag
= 1;
3546 #else /* ! defined (HAVE_X11) */
3547 if (f
->display
.x
->icon_desc
)
3549 XClearIconWindow (FRAME_X_WINDOW (f
));
3550 XDestroyWindow (f
->display
.x
->icon_desc
);
3553 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3554 0, 0, sink_width
, sink_height
,
3555 2, WhitePixmap
, (Pixmap
) NULL
);
3557 if (icon_window
== 0)
3560 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3561 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3563 f
->display
.x
->icon_desc
= icon_window
;
3564 f
->display
.x
->icon_bitmap_flag
= 1;
3566 if (icon_bitmap
== 0)
3568 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3569 #endif /* ! defined (HAVE_X11) */
3575 /* Make the x-window of frame F use a rectangle with text. */
3578 x_text_icon (f
, icon_name
)
3586 char *X_DefaultValue
;
3590 #define WhitePixel 1
3591 #endif /* WhitePixel */
3594 #define BlackPixel 0
3595 #endif /* BlackPixel */
3596 #endif /* HAVE_X11 */
3598 if (FRAME_X_WINDOW (f
) == 0)
3603 f
->display
.x
->icon_label
= icon_name
;
3605 if (! f
->display
.x
->icon_label
)
3606 f
->display
.x
->icon_label
= " *emacs* ";
3608 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3609 (char *) f
->display
.x
->icon_label
);
3611 f
->display
.x
->icon_bitmap_flag
= 0;
3612 x_wm_set_icon_pixmap (f
, 0);
3613 #else /* ! defined (HAVE_X11) */
3614 if (icon_font_info
== 0)
3616 = XGetFont (XGetDefault (XDISPLAY
3617 (char *) XSTRING (Vinvocation_name
)->data
,
3620 if (f
->display
.x
->icon_desc
)
3622 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3623 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3627 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3629 if (! f
->display
.x
->icon_label
)
3630 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3632 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3633 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3634 f
->display
.x
->left_pos
,
3635 f
->display
.x
->top_pos
,
3636 width
+ 10, icon_font_info
->height
+ 10,
3637 2, BlackPixmap
, WhitePixmap
);
3639 if (icon_window
== 0)
3642 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3643 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3645 f
->display
.x
->icon_desc
= icon_window
;
3646 f
->display
.x
->icon_bitmap_flag
= 0;
3647 f
->display
.x
->icon_label
= 0;
3648 #endif /* ! defined (HAVE_X11) */
3653 /* Handling X errors. */
3655 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3656 X server's connection, or an error reported via the X protocol. */
3659 x_connection_closed ()
3664 shut_down_emacs (0);
3669 /* An X error handler which prints an error message and then kills
3670 Emacs. This is what's normally installed as Xlib's handler for
3673 x_error_quitter (display
, error
)
3679 /* Note that there is no real way portable across R3/R4 to get the
3680 original error handler. */
3682 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3683 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3684 buf
, error
->request_code
);
3686 /* While we're testing Emacs 19, we'll just dump core whenever we
3687 get an X error, so we can figure out why it happened. */
3690 x_connection_closed ();
3693 /* A handler for X IO errors which prints an error message and then
3694 kills Emacs. This is what is always installed as Xlib's handler
3697 x_io_error_quitter (display
)
3700 fprintf (stderr
, "Connection to X server %s lost.\n",
3701 XDisplayName (DisplayString (display
)));
3703 /* While we're testing Emacs 19, we'll just dump core whenever we
3704 get an X error, so we can figure out why it happened. */
3707 x_connection_closed ();
3710 /* A buffer for storing X error messages. */
3711 static char (*x_caught_error_message
)[200];
3713 /* An X error handler which stores the error message in
3714 x_caught_error_message. This is what's installed when
3715 x_catch_errors is in effect. */
3717 x_error_catcher (display
, error
)
3721 XGetErrorText (display
, error
->error_code
,
3722 *x_caught_error_message
, sizeof (*x_caught_error_message
));
3726 /* Begin trapping X errors.
3728 After calling this function, X protocol errors no longer cause
3729 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3731 Calling x_check_errors signals an Emacs error if an X error has
3732 occurred since the last call to x_catch_errors or x_check_errors.
3734 Calling x_uncatch_errors resumes the normal error handling. */
3736 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3741 /* Make sure any errors from previous requests have been dealt with. */
3742 XSync (x_current_display
, False
);
3744 /* Set up the error buffer. */
3745 x_caught_error_message
=
3746 (char (*)[]) xmalloc (sizeof (*x_caught_error_message
));
3747 (*x_caught_error_message
)[0] = '\0';
3749 /* Install our little error handler. */
3750 XHandleError (x_error_catcher
);
3753 /* If any X protocol errors have arrived since the last call to
3754 x_catch_errors or x_check_errors, signal an Emacs error using
3755 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3757 x_check_errors (format
)
3760 /* Make sure to catch any errors incurred so far. */
3761 XSync (x_current_display
, False
);
3763 if ((*x_caught_error_message
)[0])
3767 sprintf (buf
, format
, *x_caught_error_message
);
3768 free (x_caught_error_message
);
3770 x_uncatch_errors ();
3778 free (x_caught_error_message
);
3779 XHandleError (x_error_quitter
);
3783 static unsigned int x_wire_count
;
3786 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3791 /* Changing the font of the frame. */
3793 /* Set the font of the x-window specified by frame F
3794 to the font named NEWNAME. This is safe to use
3795 even before F has an actual x-window. */
3799 /* A table of all the fonts we have already loaded. */
3800 static XFontStruct
**x_font_table
;
3802 /* The current capacity of x_font_table. */
3803 static int x_font_table_size
;
3805 /* The number of fonts actually stored in x_font_table.
3806 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3807 0 <= n_fonts <= x_font_table_size. */
3810 x_new_font (f
, fontname
)
3812 register char *fontname
;
3816 int n_matching_fonts
;
3817 XFontStruct
*font_info
;
3820 /* Get a list of all the fonts that match this name. Once we
3821 have a list of matching fonts, we compare them against the fonts
3822 we already have by comparing font ids. */
3823 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3824 1024, &n_matching_fonts
,
3826 /* If the server couldn't find any fonts whose named matched fontname,
3827 return an error code. */
3828 if (n_matching_fonts
== 0)
3831 /* See if we've already loaded a matching font. */
3836 for (i
= 0; i
< n_fonts
; i
++)
3837 for (j
= 0; j
< n_matching_fonts
; j
++)
3838 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3846 /* If we have, just return it from the table. */
3848 f
->display
.x
->font
= x_font_table
[already_loaded
];
3850 /* Otherwise, load the font and add it to the table. */
3855 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
3859 /* Do we need to create the table? */
3860 if (x_font_table_size
== 0)
3862 x_font_table_size
= 16;
3864 = (XFontStruct
**) xmalloc (x_font_table_size
3865 * sizeof (x_font_table
[0]));
3867 /* Do we need to grow the table? */
3868 else if (n_fonts
>= x_font_table_size
)
3870 x_font_table_size
*= 2;
3872 = (XFontStruct
**) xrealloc (x_font_table
,
3874 * sizeof (x_font_table
[0])));
3877 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
3880 /* Free the information from XListFontsWithInfo. The data
3881 we actually retain comes from XLoadQueryFont. */
3882 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
3884 /* Now make the frame display the given font. */
3885 if (FRAME_X_WINDOW (f
) != 0)
3887 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
3888 f
->display
.x
->font
->fid
);
3889 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
3890 f
->display
.x
->font
->fid
);
3891 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
3892 f
->display
.x
->font
->fid
);
3894 x_set_window_size (f
, f
->width
, f
->height
);
3899 #else /* ! defined (HAVE_X11) */
3900 x_new_font (f
, newname
)
3902 register char *newname
;
3907 temp
= XGetFont (newname
);
3908 if (temp
== (FONT_TYPE
*) 0)
3911 if (f
->display
.x
->font
)
3912 XLoseFont (f
->display
.x
->font
);
3914 f
->display
.x
->font
= temp
;
3916 if (FRAME_X_WINDOW (f
) != 0)
3917 x_set_window_size (f
, f
->width
, f
->height
);
3921 #endif /* ! defined (HAVE_X11) */
3923 /* X Window sizes and positions. */
3925 x_calc_absolute_position (f
)
3929 if (f
->display
.x
->left_pos
< 0)
3930 f
->display
.x
->left_pos
3931 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
3933 if (f
->display
.x
->top_pos
< 0)
3934 f
->display
.x
->top_pos
3935 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
3936 #else /* ! defined (HAVE_X11) */
3937 WINDOWINFO_TYPE parentinfo
;
3939 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
3941 if (f
->display
.x
->left_pos
< 0)
3942 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
3943 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
3945 if (f
->display
.x
->top_pos
< 0)
3946 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
3947 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
3948 #endif /* ! defined (HAVE_X11) */
3951 x_set_offset (f
, xoff
, yoff
)
3953 register int xoff
, yoff
;
3955 f
->display
.x
->top_pos
= yoff
;
3956 f
->display
.x
->left_pos
= xoff
;
3957 x_calc_absolute_position (f
);
3960 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
3961 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
3963 x_wm_set_size_hint (f
, 0);
3964 #endif /* ! defined (HAVE_X11) */
3968 /* Call this to change the size of frame F's x-window. */
3970 x_set_window_size (f
, cols
, rows
)
3974 int pixelwidth
, pixelheight
;
3979 check_frame_size (f
, &rows
, &cols
);
3980 f
->display
.x
->vertical_scroll_bar_extra
=
3981 (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3982 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
3984 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3985 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3988 x_wm_set_size_hint (f
, 0);
3989 #endif /* ! defined (HAVE_X11) */
3990 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
3992 /* Now, strictly speaking, we can't be sure that this is accurate,
3993 but the window manager will get around to dealing with the size
3994 change request eventually, and we'll hear how it went when the
3995 ConfigureNotify event gets here.
3997 We could just not bother storing any of this information here,
3998 and let the ConfigureNotify event set everything up, but that
3999 might be kind of confusing to the lisp code, since size changes
4000 wouldn't be reported in the frame parameters until some random
4001 point in the future when the ConfigureNotify event arrives. */
4002 change_frame_size (f
, rows
, cols
, 0, 0);
4003 PIXEL_WIDTH (f
) = pixelwidth
;
4004 PIXEL_HEIGHT (f
) = pixelheight
;
4006 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4007 receive in the ConfigureNotify event; if we get what we asked
4008 for, then the event won't cause the screen to become garbaged, so
4009 we have to make sure to do it here. */
4010 SET_FRAME_GARBAGED (f
);
4017 x_set_resize_hint (f
)
4020 XSetResizeHint (FRAME_X_WINDOW (f
),
4021 2 * f
->display
.x
->internal_border_width
,
4022 2 * f
->display
.x
->internal_border_width
,
4023 FONT_WIDTH (f
->display
.x
->font
),
4024 FONT_HEIGHT (f
->display
.x
->font
));
4026 #endif /* HAVE_X11 */
4028 /* Mouse warping, focus shifting, raising and lowering. */
4030 x_set_mouse_position (f
, x
, y
)
4038 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4039 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4041 if (pix_x
< 0) pix_x
= 0;
4042 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4044 if (pix_y
< 0) pix_y
= 0;
4045 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4049 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4054 x_focus_on_frame (f
)
4059 /* I don't think that the ICCCM allows programs to do things like this
4060 without the interaction of the window manager. Whatever you end up
4061 doing with this code, do it to x_unfocus_frame too. */
4062 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4063 RevertToPointerRoot
, CurrentTime
);
4071 /* Look at the remarks in x_focus_on_frame. */
4072 if (x_focus_frame
== f
)
4073 XSetInputFocus (x_current_display
, PointerRoot
,
4074 RevertToPointerRoot
, CurrentTime
);
4078 #endif /* ! defined (HAVE_X11) */
4080 /* Raise frame F. */
4085 if (f
->async_visible
)
4088 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4094 /* Lower frame F. */
4099 if (f
->async_visible
)
4102 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4109 XTframe_raise_lower (f
, raise
)
4120 /* Change from withdrawn state to mapped state. */
4122 x_make_frame_visible (f
)
4129 if (! FRAME_VISIBLE_P (f
))
4132 if (! EQ (Vx_no_window_manager
, Qt
))
4133 x_wm_set_window_state (f
, NormalState
);
4135 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4136 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4137 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4138 #else /* ! defined (HAVE_X11) */
4139 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4140 if (f
->display
.x
->icon_desc
!= 0)
4141 XUnmapWindow (f
->display
.x
->icon_desc
);
4143 /* Handled by the MapNotify event for X11 */
4144 f
->async_visible
= 1;
4145 f
->async_iconified
= 0;
4147 /* NOTE: this may cause problems for the first frame. */
4149 #endif /* ! defined (HAVE_X11) */
4157 /* Change from mapped state to withdrawn state. */
4159 x_make_frame_invisible (f
)
4164 if (! f
->async_visible
)
4171 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4172 DefaultScreen (x_current_display
)))
4174 UNBLOCK_INPUT_RESIGNAL
;
4175 error ("can't notify window manager of window withdrawl");
4178 #else /* ! defined (HAVE_X11R4) */
4181 /* Tell the window manager what we're going to do. */
4182 if (! EQ (Vx_no_window_manager
, Qt
))
4186 unmap
.xunmap
.type
= UnmapNotify
;
4187 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4188 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4189 unmap
.xunmap
.from_configure
= False
;
4190 if (! XSendEvent (x_current_display
,
4191 DefaultRootWindow (x_current_display
),
4193 SubstructureRedirectMask
|SubstructureNotifyMask
,
4196 UNBLOCK_INPUT_RESIGNAL
;
4197 error ("can't notify window manager of withdrawal");
4201 /* Unmap the window ourselves. Cheeky! */
4202 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4204 #else /* ! defined (HAVE_X11) */
4206 XUnmapWindow (FRAME_X_WINDOW (f
));
4207 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4208 if (f
->display
.x
->icon_desc
!= 0)
4209 XUnmapWindow (f
->display
.x
->icon_desc
);
4211 #endif /* ! defined (HAVE_X11) */
4212 #endif /* ! defined (HAVE_X11R4) */
4218 /* Change window state from mapped to iconified. */
4225 if (f
->async_iconified
)
4231 /* Since we don't know which revision of X we're running, we'll use both
4232 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4234 /* X11R4: send a ClientMessage to the window manager using the
4235 WM_CHANGE_STATE type. */
4239 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4240 message
.xclient
.type
= ClientMessage
;
4241 message
.xclient
.message_type
= Xatom_wm_change_state
;
4242 message
.xclient
.format
= 32;
4243 message
.xclient
.data
.l
[0] = IconicState
;
4245 if (! XSendEvent (x_current_display
,
4246 DefaultRootWindow (x_current_display
),
4248 SubstructureRedirectMask
| SubstructureNotifyMask
,
4251 UNBLOCK_INPUT_RESIGNAL
;
4252 error ("Can't notify window manager of iconification.");
4256 /* X11R3: set the initial_state field of the window manager hints to
4258 x_wm_set_window_state (f
, IconicState
);
4260 f
->async_iconified
= 1;
4261 #else /* ! defined (HAVE_X11) */
4262 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4264 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4265 if (f
->display
.x
->icon_desc
!= 0)
4267 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4270 #endif /* ! defined (HAVE_X11) */
4276 /* Destroy the X window of frame F. */
4278 x_destroy_window (f
)
4283 if (f
->display
.x
->icon_desc
!= 0)
4284 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4285 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4288 free (f
->display
.x
);
4290 if (f
== x_focus_frame
)
4292 if (f
== x_highlight_frame
)
4293 x_highlight_frame
= 0;
4298 /* Manage event queues for X10. */
4302 /* Manage event queues.
4304 This code is only used by the X10 support.
4306 We cannot leave events in the X queue and get them when we are ready
4307 because X does not provide a subroutine to get only a certain kind
4308 of event but not block if there are no queued events of that kind.
4310 Therefore, we must examine events as they come in and copy events
4311 of certain kinds into our private queues.
4313 All ExposeRegion events are put in x_expose_queue.
4314 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4317 /* Write the event *P_XREP into the event queue *QUEUE.
4318 If the queue is full, do nothing, but return nonzero. */
4321 enqueue_event (p_xrep
, queue
)
4322 register XEvent
*p_xrep
;
4323 register struct event_queue
*queue
;
4325 int newindex
= queue
->windex
+ 1;
4326 if (newindex
== EVENT_BUFFER_SIZE
)
4328 if (newindex
== queue
->rindex
)
4330 queue
->xrep
[queue
->windex
] = *p_xrep
;
4331 queue
->windex
= newindex
;
4335 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4336 If *QUEUE is empty, do nothing and return 0. */
4339 dequeue_event (p_xrep
, queue
)
4340 register XEvent
*p_xrep
;
4341 register struct event_queue
*queue
;
4343 if (queue
->windex
== queue
->rindex
)
4345 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4346 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4351 /* Return the number of events buffered in *QUEUE. */
4354 queue_event_count (queue
)
4355 register struct event_queue
*queue
;
4357 int tem
= queue
->windex
- queue
->rindex
;
4360 return EVENT_BUFFER_SIZE
+ tem
;
4363 /* Return nonzero if mouse input is pending. */
4366 mouse_event_pending_p ()
4368 return queue_event_count (&x_mouse_queue
);
4370 #endif /* HAVE_X11 */
4372 /* Setting window manager hints. */
4376 x_wm_set_size_hint (f
, prompting
)
4380 XSizeHints size_hints
;
4381 Window window
= FRAME_X_WINDOW (f
);
4383 size_hints
.flags
= PResizeInc
| PMinSize
| PMaxSize
;
4385 flexlines
= f
->height
;
4387 size_hints
.x
= f
->display
.x
->left_pos
;
4388 size_hints
.y
= f
->display
.x
->top_pos
;
4389 size_hints
.height
= PIXEL_HEIGHT (f
);
4390 size_hints
.width
= PIXEL_WIDTH (f
);
4391 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4392 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4393 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4394 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4397 int base_width
, base_height
;
4399 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4400 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4403 int min_rows
= 0, min_cols
= 0;
4404 check_frame_size (f
, &min_rows
, &min_cols
);
4406 /* The window manager uses the base width hints to calculate the
4407 current number of rows and columns in the frame while
4408 resizing; min_width and min_height aren't useful for this
4409 purpose, since they might not give the dimensions for a
4410 zero-row, zero-column frame.
4412 We use the base_width and base_height members if we have
4413 them; otherwise, we set the min_width and min_height members
4414 to the size for a zero x zero frame. */
4417 size_hints
.flags
|= PBaseSize
;
4418 size_hints
.base_width
= base_width
;
4419 size_hints
.base_height
= base_height
;
4420 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4421 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4423 size_hints
.min_width
= base_width
;
4424 size_hints
.min_height
= base_height
;
4431 size_hints
.flags
|= prompting
;
4434 XSizeHints hints
; /* Sometimes I hate X Windows... */
4436 XGetNormalHints (x_current_display
, window
, &hints
);
4437 if (hints
.flags
& PSize
)
4438 size_hints
.flags
|= PSize
;
4439 if (hints
.flags
& PPosition
)
4440 size_hints
.flags
|= PPosition
;
4441 if (hints
.flags
& USPosition
)
4442 size_hints
.flags
|= USPosition
;
4443 if (hints
.flags
& USSize
)
4444 size_hints
.flags
|= USSize
;
4448 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4450 XSetNormalHints (x_current_display
, window
, &size_hints
);
4454 /* Used for IconicState or NormalState */
4455 x_wm_set_window_state (f
, state
)
4459 Window window
= FRAME_X_WINDOW (f
);
4461 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4462 f
->display
.x
->wm_hints
.initial_state
= state
;
4464 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4467 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4471 Window window
= FRAME_X_WINDOW (f
);
4475 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4476 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4479 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4481 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4484 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4488 Window window
= FRAME_X_WINDOW (f
);
4490 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4491 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4492 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4494 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4498 /* Initialization. */
4501 x_term_init (display_name
)
4507 extern int old_fcntl_owner
;
4508 #endif /* ! defined (F_SETOWN) */
4510 x_focus_frame
= x_highlight_frame
= 0;
4512 x_current_display
= XOpenDisplay (display_name
);
4513 if (x_current_display
== 0)
4514 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4519 int hostname_size
= 256;
4521 hostname
= (char *) xmalloc (hostname_size
);
4524 XSetAfterFunction (x_current_display
, x_trace_wire
);
4527 /* Try to get the host name; if the buffer is too short, try
4528 again. Apparently, the only indication gethostname gives of
4529 whether the buffer was large enough is the presence or absence
4530 of a '\0' in the string. Eech. */
4533 gethostname (hostname
, hostname_size
- 1);
4534 hostname
[hostname_size
- 1] = '\0';
4536 /* Was the buffer large enough for gethostname to store the '\0'? */
4537 if (strlen (hostname
) < hostname_size
- 1)
4540 hostname_size
<<= 1;
4541 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4543 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4546 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
4549 /* Figure out which modifier bits mean what. */
4550 x_find_modifier_meanings ();
4552 /* Get the scroll bar cursor. */
4553 x_vertical_scroll_bar_cursor
4554 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4557 /* Watch for PropertyNotify events on the root window; we use them
4558 to figure out when to invalidate our cache of the cut buffers. */
4559 x_watch_cut_buffer_cache ();
4562 if (ConnectionNumber (x_current_display
) != 0)
4564 dup2 (ConnectionNumber (x_current_display
), 0);
4566 #ifndef SYSV_STREAMS
4567 /* Streams somehow keeps track of which descriptor number
4568 is being used to talk to X. So it is not safe to substitute
4569 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4570 close (ConnectionNumber (x_current_display
));
4571 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4572 * check the def of the macro;
4573 * it is a genuine lvalue */
4574 #endif /* SYSV_STREAMS */
4577 #endif /* ! defined (HAVE_X11) */
4580 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4581 #ifdef F_SETOWN_SOCK_NEG
4582 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4583 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4584 fcntl (0, F_SETOWN
, getpid ());
4585 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4586 #endif /* ! defined (F_SETOWN) */
4590 #endif /* ! defined (SIGIO) */
4592 /* Must use interrupt input because we cannot otherwise
4593 arrange for C-g to be noticed immediately.
4594 We cannot connect it to SIGINT. */
4595 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4597 expose_all_windows
= 0;
4599 clear_frame_hook
= XTclear_frame
;
4600 clear_end_of_line_hook
= XTclear_end_of_line
;
4601 ins_del_lines_hook
= XTins_del_lines
;
4602 change_line_highlight_hook
= XTchange_line_highlight
;
4603 insert_glyphs_hook
= XTinsert_glyphs
;
4604 write_glyphs_hook
= XTwrite_glyphs
;
4605 delete_glyphs_hook
= XTdelete_glyphs
;
4606 ring_bell_hook
= XTring_bell
;
4607 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4608 set_terminal_modes_hook
= XTset_terminal_modes
;
4609 update_begin_hook
= XTupdate_begin
;
4610 update_end_hook
= XTupdate_end
;
4611 set_terminal_window_hook
= XTset_terminal_window
;
4612 read_socket_hook
= XTread_socket
;
4613 cursor_to_hook
= XTcursor_to
;
4614 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4615 mouse_position_hook
= XTmouse_position
;
4616 frame_rehighlight_hook
= XTframe_rehighlight
;
4617 frame_raise_lower_hook
= XTframe_raise_lower
;
4618 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
4619 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
4620 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
4621 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
4623 scroll_region_ok
= 1; /* we'll scroll partial frames */
4624 char_ins_del_ok
= 0; /* just as fast to write the line */
4625 line_ins_del_ok
= 1; /* we'll just blt 'em */
4626 fast_clear_end_of_line
= 1; /* X does this well */
4627 memory_below_frame
= 0; /* we don't remember what scrolls
4631 /* Note that there is no real way portable across R3/R4 to get the
4632 original error handler. */
4633 XHandleError (x_error_quitter
);
4634 XHandleIOError (x_io_error_quitter
);
4636 /* Disable Window Change signals; they are handled by X events. */
4638 signal (SIGWINCH
, SIG_DFL
);
4639 #endif /* ! defined (SIGWINCH) */
4641 signal (SIGPIPE
, x_connection_closed
);
4647 staticpro (&last_mouse_scroll_bar
);
4649 #endif /* ! defined (HAVE_X11) */
4650 #endif /* ! defined (HAVE_X_WINDOWS) */