1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
34 /* On 4.3 these lose if they come after xterm.h. */
38 /* This may include sys/types.h, and that somehow loses
39 if this is not done before the other system files. */
41 #include <X11/cursorfont.h>
44 /* Load sys/types.h if not already loaded.
45 In some systems loading it twice is suicidal. */
47 #include <sys/types.h>
52 #include <sys/ioctl.h>
54 #else /* ! defined (BSD) */
55 #include <sys/termio.h>
57 #endif /* ! defined (BSD) */
59 /* Allow m- file to inhibit use of FIONREAD. */
60 #ifdef BROKEN_FIONREAD
62 #endif /* ! defined (BROKEN_FIONREAD) */
64 /* We are unable to use interrupts if FIONREAD is not available,
65 so flush SIGIO so we won't try. */
69 #endif /* ! defined (SIGIO) */
79 #include <sys/param.h>
81 #include "dispextern.h"
82 #include "termhooks.h"
96 #define XMapWindow XMapRaised /* Raise them when mapping. */
97 #else /* ! defined (HAVE_X11) */
98 #include <X/Xkeyboard.h>
99 /*#include <X/Xproto.h> */
100 #endif /* ! defined (HAVE_X11) */
102 /* For sending Meta-characters. Do we need this? */
105 #define min(a,b) ((a)<(b) ? (a) : (b))
106 #define max(a,b) ((a)>(b) ? (a) : (b))
108 /* Nonzero means we must reprint all windows
109 because 1) we received an ExposeWindow event
110 or 2) we received too many ExposeRegion events to record.
112 This is never needed under X11. */
113 static int expose_all_windows
;
115 /* Nonzero means we must reprint all icon windows. */
117 static int expose_all_icons
;
120 /* ExposeRegion events, when received, are copied into this queue
121 for later processing. */
123 static struct event_queue x_expose_queue
;
125 /* ButtonPressed and ButtonReleased events, when received,
126 are copied into this queue for later processing. */
128 struct event_queue x_mouse_queue
;
129 #endif /* HAVE_X11 */
131 /* Nonzero after BLOCK_INPUT; prevents input events from being
132 processed until later. */
136 #if defined (SIGIO) && defined (FIONREAD)
137 int BLOCK_INPUT_mask
;
138 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
140 /* Nonzero if input events came in while x_input_blocked was nonzero.
141 UNBLOCK_INPUT checks for this. */
145 /* The id of a bitmap used for icon windows.
146 One such map is shared by all Emacs icon windows.
147 This is zero if we have not yet had a need to create the bitmap. */
149 static Bitmap icon_bitmap
;
151 /* Font used for text icons. */
153 static FONT_TYPE
*icon_font_info
;
155 /* Stuff for dealing with the main icon title. */
157 extern Lisp_Object Vcommand_line_args
;
158 char *hostname
, *x_id_name
;
159 Lisp_Object invocation_name
;
161 /* This is the X connection that we are using. */
163 Display
*x_current_display
;
165 /* The cursor to use for vertical scrollbars on x_current_display. */
166 static Cursor x_vertical_scrollbar_cursor
;
168 /* Frame being updated by update_frame. */
169 /* This is set by XTupdate_begin and looked at by all the
170 XT functions. It is zero while not inside an update.
171 In that case, the XT functions assume that `selected_frame'
172 is the frame to apply to. */
174 static struct frame
*updating_frame
;
176 /* The frame (if any) which has the X window that has keyboard focus.
177 Zero if none. This is examined by Ffocus_frame in frame.c. Note
178 that a mere EnterNotify event can set this; if you need to know the
179 last frame specified in a FocusIn or FocusOut event, use
180 x_focus_event_frame. */
181 struct frame
*x_focus_frame
;
183 /* The last frame mentioned in a FocusIn or FocusOut event. This is
184 separate from x_focus_frame, because whether or not LeaveNotify
185 events cause us to lose focus depends on whether or not we have
186 received a FocusIn event for it. */
187 struct frame
*x_focus_event_frame
;
189 /* The frame which currently has the visual highlight, and should get
190 keyboard input (other sorts of input have the frame encoded in the
191 event). It points to the X focus frame's selected window's
192 frame. It differs from x_focus_frame when we're using a global
194 static struct frame
*x_highlight_frame
;
196 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
197 mouse is moved to inside of frame when frame is de-iconified. */
199 static int warp_mouse_on_deiconify
;
201 /* During an update, maximum vpos for ins/del line operations to affect. */
203 static int flexlines
;
205 /* During an update, nonzero if chars output now should be highlighted. */
207 static int highlight
;
209 /* Nominal cursor position -- where to draw output.
210 During an update, these are different from the cursor-box position. */
216 /* `t' if a mouse button is depressed. */
218 extern Lisp_Object Vmouse_depressed
;
220 /* Tells if a window manager is present or not. */
222 extern Lisp_Object Vx_no_window_manager
;
224 /* Timestamp that we requested selection data was made. */
225 extern Time requestor_time
;
227 /* ID of the window requesting selection data. */
228 extern Window requestor_window
;
230 /* Nonzero enables some debugging for the X interface code. */
233 #else /* ! defined (HAVE_X11) */
235 /* Bit patterns for the mouse cursor. */
237 short MouseCursor
[] = {
238 0x0000, 0x0008, 0x0018, 0x0038,
239 0x0078, 0x00f8, 0x01f8, 0x03f8,
240 0x07f8, 0x00f8, 0x00d8, 0x0188,
241 0x0180, 0x0300, 0x0300, 0x0000};
243 short MouseMask
[] = {
244 0x000c, 0x001c, 0x003c, 0x007c,
245 0x00fc, 0x01fc, 0x03fc, 0x07fc,
246 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
247 0x03cc, 0x0780, 0x0780, 0x0300};
249 static short grey_bits
[] = {
250 0x0005, 0x000a, 0x0005, 0x000a};
252 static Pixmap GreyPixmap
= 0;
253 #endif /* ! defined (HAVE_X11) */
255 /* From time to time we get info on an Emacs window, here. */
257 static WINDOWINFO_TYPE windowinfo
;
261 /* See keyboard.c. */
262 extern int extra_keyboard_modifiers
;
264 extern Display
*XOpenDisplay ();
265 extern Window
XCreateWindow ();
267 extern Cursor
XCreateCursor ();
268 extern FONT_TYPE
*XOpenFont ();
270 static void flashback ();
273 static void dumpqueue ();
274 #endif /* HAVE_X11 */
277 static int XTcursor_to ();
278 static int XTclear_end_of_line ();
281 /* Starting and ending updates.
283 These hooks are called by update_frame at the beginning and end
284 of a frame update. We record in `updating_frame' the identity
285 of the frame being updated, so that the XT... functions do not
286 need to take a frame as argument. Most of the XT... functions
287 should never be called except during an update, the only exceptions
288 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
290 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
302 flexlines
= f
->height
;
308 #endif /* HAVE_X11 */
313 static void x_do_pending_expose ();
322 if (updating_frame
== 0
323 || updating_frame
!= f
)
329 x_do_pending_expose ();
330 #endif /* HAVE_X11 */
332 x_display_cursor (f
, 1);
339 /* External interface to control of standout mode.
340 Call this when about to modify line at position VPOS
341 and not change whether it is highlighted. */
343 XTreassert_line_highlight (new, vpos
)
349 /* Call this when about to modify line at position VPOS
350 and change whether it is highlighted. */
353 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
354 int new_highlight
, vpos
, first_unused_hpos
;
356 highlight
= new_highlight
;
357 XTcursor_to (vpos
, 0);
358 XTclear_end_of_line (updating_frame
->width
);
361 /* This is used when starting Emacs and when restarting after suspend.
362 When starting Emacs, no X window is mapped. And nothing must be done
363 to Emacs's own window if it is suspended (though that rarely happens). */
366 XTset_terminal_modes ()
370 /* This is called when exiting or suspending Emacs.
371 Exiting will make the X-windows go away, and suspending
372 requires no action. */
375 XTreset_terminal_modes ()
377 /* XTclear_frame (); */
380 /* Set the nominal cursor position of the frame.
381 This is where display update commands will take effect.
382 This does not affect the place where the cursor-box is displayed. */
385 XTcursor_to (row
, col
)
386 register int row
, col
;
394 if (updating_frame
== 0)
397 x_display_cursor (selected_frame
, 1);
403 /* Display a sequence of N glyphs found at GP.
404 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
405 HL is 1 if this text is highlighted, 2 if the cursor is on it.
407 FONT is the default font to use (for glyphs whose font-code is 0). */
410 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
413 register GLYPH
*gp
; /* Points to first GLYPH. */
414 register int n
; /* Number of glyphs to display. */
419 Window window
= FRAME_X_WINDOW (f
);
420 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
421 : (hl
? f
->display
.x
->reverse_gc
422 : f
->display
.x
->normal_gc
));
424 if (sizeof (GLYPH
) == sizeof (XChar2b
))
425 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
426 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
427 else if (sizeof (GLYPH
) == sizeof (unsigned char))
428 XDrawImageString (x_current_display
, window
, drawing_gc
,
429 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
431 /* What size of glyph ARE you using? And does X have a function to
438 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
441 register GLYPH
*gp
; /* Points to first GLYPH. */
442 register int n
; /* Number of glyphs to display. */
446 char buf
[f
->width
]; /* Holds characters to be displayed. */
447 register char *cp
; /* Steps through buf[]. */
448 register int tlen
= GLYPH_TABLE_LENGTH
;
449 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
450 Window window
= FRAME_X_WINDOW (f
);
451 int cursor_pixel
= f
->display
.x
->cursor_pixel
;
452 int fg_pixel
= f
->display
.x
->foreground_pixel
;
453 int bg_pixel
= f
->display
.x
->background_pixel
;
454 int intborder
= f
->display
.x
->internal_border_width
;
458 /* Get the face-code of the next GLYPH. */
462 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
463 g
= GLYPH_ALIAS (tbase
, g
);
467 /* Find the run of consecutive glyphs with the same face-code.
468 Extract their character codes into BUF. */
473 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
474 g
= GLYPH_ALIAS (tbase
, g
);
483 /* LEN gets the length of the run. */
486 /* Now output this run of chars, with the font and pixel values
487 determined by the face code CF. */
491 GC GC_cursor
= f
->display
.x
->cursor_gc
;
492 GC GC_reverse
= f
->display
.x
->reverse_gc
;
493 GC GC_normal
= f
->display
.x
->normal_gc
;
495 XDrawImageString (x_current_display
, window
,
498 : (hl
? GC_reverse
: GC_normal
)),
499 left
, top
+ FONT_BASE (font
), buf
, len
);
500 #else /* ! defined (HAVE_X11) */
501 XText (window
, left
, top
,
506 ? (cursor_pixel
== fg_pixel
? bg_pixel
: fg_pixel
)
507 : hl
? bg_pixel
: fg_pixel
),
508 (hl
== 2 ? cursor_pixel
509 : hl
? fg_pixel
: bg_pixel
));
510 #endif /* ! defined (HAVE_X11) */
515 if (FACE_IS_FONT (cf
))
516 XDrawImageString (x_current_display
, FRAME_X_WINDOW (f
),
518 left
, top
+ FONT_BASE (FACE_FONT (cf
)),
520 else if (FACE_IS_IMAGE (cf
))
521 XCopyPlane (x_current_display
, FACE_IMAGE (cf
),
523 f
->display
.x
->normal_gc
,
525 FACE_IMAGE_WIDTH (cf
),
526 FACE_IMAGE_HEIGHT (cf
), left
, top
);
529 #else /* ! defined (HAVE_X11) */
530 register struct face
*fp
= x_face_table
[cf
];
532 XText (window
, left
, top
,
537 ? (cursor_pixel
== fp
->fg
? fp
->bg
: fp
->fg
)
538 : hl
? fp
->bg
: fp
->fg
),
539 (hl
== 2 ? cursor_pixel
540 : hl
? fp
->fg
: fp
->bg
));
541 #endif /* ! defined (HAVE_X11) */
543 left
+= len
* FONT_WIDTH (font
);
548 /* Output some text at the nominal frame cursor position.
549 Advance the cursor over the text.
550 Output LEN glyphs at START.
552 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
553 controls the pixel values used for foreground and background. */
556 XTwrite_glyphs (start
, len
)
557 register GLYPH
*start
;
560 register int temp_length
;
570 /* If not within an update,
571 output at the frame's visible cursor. */
572 curs_x
= f
->cursor_x
;
573 curs_y
= f
->cursor_y
;
577 CHAR_TO_PIXEL_COL (f
, curs_x
),
578 CHAR_TO_PIXEL_ROW (f
, curs_y
),
579 start
, len
, highlight
, f
->display
.x
->font
);
581 /* If we drew on top of the cursor, note that it is turned off. */
582 if (curs_y
== f
->phys_cursor_y
583 && curs_x
<= f
->phys_cursor_x
584 && curs_x
+ len
> f
->phys_cursor_x
)
585 f
->phys_cursor_x
= -1;
587 if (updating_frame
== 0)
590 x_display_cursor (f
, 1);
599 /* Clear to the end of the line.
600 Erase the current text line from the nominal cursor position (inclusive)
601 to column FIRST_UNUSED (exclusive). The idea is that everything
602 from FIRST_UNUSED onward is already erased. */
605 XTclear_end_of_line (first_unused
)
606 register int first_unused
;
608 struct frame
*f
= updating_frame
;
614 if (curs_y
< 0 || curs_y
>= f
->height
)
616 if (first_unused
<= 0)
619 if (first_unused
>= f
->width
)
620 first_unused
= f
->width
;
624 /* Notice if the cursor will be cleared by this operation. */
625 if (curs_y
== f
->phys_cursor_y
626 && curs_x
<= f
->phys_cursor_x
627 && f
->phys_cursor_x
< first_unused
)
628 f
->phys_cursor_x
= -1;
631 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
632 CHAR_TO_PIXEL_COL (f
, curs_x
),
633 CHAR_TO_PIXEL_ROW (f
, curs_y
),
634 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
635 FONT_HEIGHT (f
->display
.x
->font
), False
);
637 #else /* ! defined (HAVE_X11) */
638 XPixSet (FRAME_X_WINDOW (f
),
639 CHAR_TO_PIXEL_COL (f
, curs_x
),
640 CHAR_TO_PIXEL_ROW (f
, curs_y
),
641 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
642 FONT_HEIGHT (f
->display
.x
->font
),
643 f
->display
.x
->background_pixel
);
644 #endif /* ! defined (HAVE_X11) */
653 struct frame
*f
= updating_frame
;
658 f
->phys_cursor_x
= -1; /* Cursor not visible. */
659 curs_x
= 0; /* Nominal cursor position is top left. */
664 XClear (FRAME_X_WINDOW (f
));
666 /* We have to clear the scrollbars, too. If we have changed
667 colors or something like that, then they should be notified. */
668 x_scrollbar_clear (f
);
672 #endif /* HAVE_X11 */
678 /* Invert the middle quarter of the frame for .15 sec. */
680 /* We use the select system call to do the waiting, so we have to make sure
681 it's avaliable. If it isn't, we just won't do visual bells. */
682 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
684 /* Subtract the `struct timeval' values X and Y,
685 storing the result in RESULT.
686 Return 1 if the difference is negative, otherwise 0. */
689 timeval_subtract (result
, x
, y
)
690 struct timeval
*result
, x
, y
;
692 /* Perform the carry for the later subtraction by updating y.
693 This is safer because on some systems
694 the tv_sec member is unsigned. */
695 if (x
.tv_usec
< y
.tv_usec
)
697 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
698 y
.tv_usec
-= 1000000 * nsec
;
701 if (x
.tv_usec
- y
.tv_usec
> 1000000)
703 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
704 y
.tv_usec
+= 1000000 * nsec
;
708 /* Compute the time remaining to wait. tv_usec is certainly positive. */
709 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
710 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
712 /* Return indication of whether the result should be considered negative. */
713 return x
.tv_sec
< y
.tv_sec
;
724 /* Create a GC that will use the GXxor function to flip foreground pixels
725 into background pixels. */
729 values
.function
= GXxor
;
730 values
.foreground
= (f
->display
.x
->foreground_pixel
731 ^ f
->display
.x
->background_pixel
);
733 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
734 GCFunction
| GCForeground
, &values
);
738 int width
= PIXEL_WIDTH (f
);
739 int height
= PIXEL_HEIGHT (f
);
741 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
742 width
/4, height
/4, width
/2, height
/2);
743 XFlush (x_current_display
);
746 struct timeval wakeup
, now
;
748 gettimeofday (&wakeup
, (struct timezone
*) 0);
750 /* Compute time to wait until, propagating carry from usecs. */
751 wakeup
.tv_usec
+= 150000;
752 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
753 wakeup
.tv_usec
%= 1000000;
755 /* Keep waiting until past the time wakeup. */
758 struct timeval timeout
;
760 gettimeofday (&timeout
, (struct timezone
*)0);
762 /* In effect, timeout = wakeup - timeout.
763 Break if result would be negative. */
764 if (timeval_subtract (&timeout
, wakeup
, timeout
))
767 /* Try to wait that long--but we might wake up sooner. */
768 select (0, 0, 0, 0, &timeout
);
772 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
773 width
/4, height
/4, width
/2, height
/2);
774 XFreeGC (x_current_display
, gc
);
775 XFlush (x_current_display
);
785 /* Make audible bell. */
788 #define XRINGBELL XBell(x_current_display, 0)
789 #else /* ! defined (HAVE_X11) */
790 #define XRINGBELL XFeep(0);
791 #endif /* ! defined (HAVE_X11) */
795 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
797 XTflash (selected_frame
);
808 /* Insert and delete character.
809 These are not supposed to be used because we are supposed to turn
810 off the feature of using them. */
813 XTinsert_glyphs (start
, len
)
814 register char *start
;
827 /* Specify how many text lines, from the top of the window,
828 should be affected by insert-lines and delete-lines operations.
829 This, and those operations, are used only within an update
830 that is bounded by calls to XTupdate_begin and XTupdate_end. */
833 XTset_terminal_window (n
)
836 if (updating_frame
== 0)
839 if ((n
<= 0) || (n
> updating_frame
->height
))
840 flexlines
= updating_frame
->height
;
845 /* Perform an insert-lines operation.
846 Insert N lines at a vertical position curs_y. */
852 register int topregion
, bottomregion
;
853 register int length
, newtop
, mask
;
854 register struct frame
*f
= updating_frame
;
855 int intborder
= f
->display
.x
->internal_border_width
;
857 if (curs_y
>= flexlines
)
861 bottomregion
= flexlines
- (n
+ 1);
862 newtop
= topregion
+ n
;
863 length
= (bottomregion
- topregion
) + 1;
867 #endif /* HAVE_X11 */
869 if ((length
> 0) && (newtop
<= flexlines
))
872 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
873 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
874 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
875 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
876 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
877 CHAR_TO_PIXEL_ROW (f
, newtop
));
878 #else /* ! defined (HAVE_X11) */
879 XMoveArea (FRAME_X_WINDOW (f
),
880 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
881 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
882 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
883 length
* FONT_HEIGHT (f
->display
.x
->font
));
884 /* Now we must process any ExposeRegion events that occur
885 if the area being copied from is obscured.
886 We can't let it wait because further i/d operations
887 may want to copy this area to another area. */
889 #endif /* ! defined (HAVE_X11) */
892 newtop
= min (newtop
, (flexlines
- 1));
893 length
= newtop
- topregion
;
897 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
898 CHAR_TO_PIXEL_ROW (f
, topregion
),
899 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
900 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
901 #else /* ! defined (HAVE_X11) */
902 XPixSet (FRAME_X_WINDOW (f
),
904 CHAR_TO_PIXEL_ROW (f
, topregion
),
905 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
906 n
* FONT_HEIGHT (f
->display
.x
->font
),
907 f
->display
.x
->background_pixel
);
908 #endif /* ! defined (HAVE_X11) */
912 /* Perform a delete-lines operation, deleting N lines
913 at a vertical position curs_y. */
920 register struct frame
*f
= updating_frame
;
921 int intborder
= f
->display
.x
->internal_border_width
;
923 if (curs_y
>= flexlines
)
928 #endif /* HAVE_X11 */
930 if ((curs_y
+ n
) >= flexlines
)
932 if (flexlines
>= (curs_y
+ 1))
935 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
936 CHAR_TO_PIXEL_ROW (f
, curs_y
),
937 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
938 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
939 #else /* ! defined (HAVE_X11) */
940 XPixSet (FRAME_X_WINDOW (f
),
941 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
942 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
943 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
944 f
->display
.x
->background_pixel
);
945 #endif /* ! defined (HAVE_X11) */
951 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
952 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
954 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
955 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
956 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
957 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
958 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
960 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
961 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
962 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
963 #else /* ! defined (HAVE_X11) */
964 XMoveArea (FRAME_X_WINDOW (f
),
966 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
967 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
968 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
969 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
970 /* Now we must process any ExposeRegion events that occur
971 if the area being copied from is obscured.
972 We can't let it wait because further i/d operations
973 may want to copy this area to another area. */
975 XPixSet (FRAME_X_WINDOW (f
), intborder
,
976 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
977 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
978 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
979 #endif /* ! defined (HAVE_X11) */
983 /* Perform an insert-lines or delete-lines operation,
984 inserting N lines or deleting -N lines at vertical position VPOS. */
986 XTins_del_lines (vpos
, n
)
989 if (updating_frame
== 0)
992 /* Hide the cursor. */
993 x_display_cursor (updating_frame
, 0);
995 XTcursor_to (vpos
, 0);
1006 /* Support routines for exposure events. */
1007 static void clear_cursor ();
1009 /* Output into a rectangle of an X-window (for frame F)
1010 the characters in f->phys_lines that overlap that rectangle.
1011 TOP and LEFT are the position of the upper left corner of the rectangle.
1012 ROWS and COLS are the size of the rectangle. */
1015 dumprectangle (f
, left
, top
, cols
, rows
)
1017 register int left
, top
, cols
, rows
;
1019 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1020 int cursor_cleared
= 0;
1024 if (FRAME_GARBAGED_P (f
))
1027 /* Express rectangle as four edges, instead of position-and-size. */
1028 bottom
= top
+ rows
;
1029 right
= left
+ cols
;
1031 #ifndef HAVE_X11 /* Window manger does this for X11. */
1033 int intborder
= f
->display
.x
->internal_border_width
;
1035 /* If the rectangle includes any of the internal border area,
1036 redisplay the border emphasis. */
1037 if (top
< intborder
|| left
< intborder
1038 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1039 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1042 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1044 /* Convert rectangle edges in pixels to edges in chars.
1045 Round down for left and top, up for right and bottom. */
1046 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1047 left
= PIXEL_TO_CHAR_COL (f
, left
);
1048 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1049 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1050 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1051 right
= PIXEL_TO_CHAR_COL (f
, right
);
1053 /* Clip the rectangle to what can be visible. */
1058 if (right
> f
->width
)
1060 if (bottom
> f
->height
)
1063 /* Get size in chars of the rectangle. */
1064 cols
= right
- left
;
1065 rows
= bottom
- top
;
1067 /* If rectangle has zero area, return. */
1068 if (rows
<= 0) return;
1069 if (cols
<= 0) return;
1071 /* Turn off the cursor if it is in the rectangle.
1072 We will turn it back on afterward. */
1073 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1074 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1080 /* Display the text in the rectangle, one text line at a time. */
1082 for (y
= top
; y
< bottom
; y
++)
1084 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1086 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1090 CHAR_TO_PIXEL_COL (f
, left
),
1091 CHAR_TO_PIXEL_ROW (f
, y
),
1092 line
, min (cols
, active_frame
->used
[y
] - left
),
1093 active_frame
->highlight
[y
], f
->display
.x
->font
);
1096 /* Turn the cursor on if we turned it off. */
1099 x_display_cursor (f
, 1);
1103 /* Process all queued ExposeRegion events. */
1109 XExposeRegionEvent r
;
1111 while (dequeue_event (&r
, &x_expose_queue
))
1113 struct frame
*f
= x_window_to_frame (r
.window
);
1114 if (f
->display
.x
->icon_desc
== r
.window
)
1117 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1121 #endif /* HAVE_X11 */
1123 /* Process all expose events that are pending, for X10.
1124 Redraws the cursor if necessary on any frame that
1125 is not in the process of being updated with update_frame. */
1129 x_do_pending_expose ()
1133 Lisp_Object tail
, frame
;
1135 if (expose_all_windows
)
1137 expose_all_windows
= 0;
1138 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1140 register int temp_width
, temp_height
;
1143 frame
= XCONS (tail
)->car
;
1144 if (XTYPE (frame
) != Lisp_Frame
)
1147 if (! FRAME_X_P (f
))
1149 if (!f
->async_visible
)
1151 if (!f
->display
.x
->needs_exposure
)
1154 intborder
= f
->display
.x
->internal_border_width
;
1157 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1158 temp_width
= ((windowinfo
.width
- 2 * intborder
1159 - f
->display
.x
->v_scrollbar_width
)
1160 / FONT_WIDTH (f
->display
.x
->font
));
1161 temp_height
= ((windowinfo
.height
- 2 * intborder
1162 - f
->display
.x
->h_scrollbar_height
)
1163 / FONT_HEIGHT (f
->display
.x
->font
));
1164 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1166 change_frame_size (f
, max (1, temp_height
),
1167 max (1, temp_width
), 0, 1);
1168 x_resize_scrollbars (f
);
1170 f
->display
.x
->left_pos
= windowinfo
.x
;
1171 f
->display
.x
->top_pos
= windowinfo
.y
;
1172 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1176 f
->display
.x
->needs_exposure
= 0;
1177 if (updating_frame
!= f
)
1178 x_display_cursor (f
, 1);
1183 /* Handle any individual-rectangle expose events queued
1184 for various windows. */
1187 #else /* ! defined (HAVE_X11) */
1189 #endif /* ! defined (HAVE_X11) */
1195 frame_highlight (frame
)
1196 struct frame
*frame
;
1198 if (! EQ (Vx_no_window_manager
, Qnil
))
1199 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1200 frame
->display
.x
->border_pixel
);
1201 x_display_cursor (frame
, 1);
1205 frame_unhighlight (frame
)
1206 struct frame
*frame
;
1208 if (! EQ (Vx_no_window_manager
, Qnil
))
1209 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1210 frame
->display
.x
->border_tile
);
1211 x_display_cursor (frame
, 1);
1213 #else /* ! defined (HAVE_X11) */
1214 /* Dump the border-emphasis of frame F.
1215 If F is selected, this is a lining of the same color as the border,
1216 just within the border, occupying a portion of the internal border.
1217 If F is not selected, it is background in the same place.
1218 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1220 ALWAYS = 1 is used when a frame becomes selected or deselected.
1221 In that case, we also turn the cursor off and on again
1222 so it will appear in the proper shape (solid if selected; else hollow.) */
1225 dumpborder (f
, always
)
1229 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1230 int width
= PIXEL_WIDTH (f
);
1231 int height
= PIXEL_HEIGHT (f
);
1234 if (f
!= selected_frame
)
1239 pixel
= f
->display
.x
->background_pixel
;
1243 pixel
= f
->display
.x
->border_pixel
;
1246 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1247 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1248 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1250 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1254 x_display_cursor (f
, 1);
1256 #endif /* ! defined (HAVE_X11) */
1258 static void XTframe_rehighlight ();
1260 /* The focus has changed. Update the frames as necessary to reflect
1261 the new situation. Note that we can't change the selected frame
1262 here, because the lisp code we are interrupting might become confused.
1263 Each event gets marked with the frame in which it occured, so the
1264 lisp code can tell when the switch took place by examining the events. */
1267 x_new_focus_frame (frame
)
1268 struct frame
*frame
;
1270 struct frame
*old_focus
= x_focus_frame
;
1271 int events_enqueued
= 0;
1273 if (frame
!= x_focus_frame
)
1275 /* Set this before calling other routines, so that they see
1276 the correct value of x_focus_frame. */
1277 x_focus_frame
= frame
;
1279 if (old_focus
&& old_focus
->auto_lower
)
1280 x_lower_frame (old_focus
);
1283 selected_frame
= frame
;
1284 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1285 Lisp_Frame
, selected_frame
);
1286 Fselect_window (selected_frame
->selected_window
);
1287 choose_minibuf_frame ();
1290 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1291 x_raise_frame (x_focus_frame
);
1294 XTframe_rehighlight ();
1298 /* The focus has changed, or we have redirected a frame's focus to
1299 another frame (this happens when a frame uses a surrogate
1300 minibuffer frame). Shift the highlight as appropriate. */
1302 XTframe_rehighlight ()
1304 struct frame
*old_highlight
= x_highlight_frame
;
1309 ((XTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1310 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1312 if (! FRAME_LIVE_P (x_highlight_frame
))
1314 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1315 x_highlight_frame
= x_focus_frame
;
1319 x_highlight_frame
= 0;
1321 if (x_highlight_frame
!= old_highlight
)
1324 frame_unhighlight (old_highlight
);
1325 if (x_highlight_frame
)
1326 frame_highlight (x_highlight_frame
);
1330 /* Mouse clicks and mouse movement. Rah. */
1333 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1334 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1335 that the glyph at X, Y occupies, if BOUNDS != 0. */
1337 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1339 register unsigned int pix_x
, pix_y
;
1340 register int *x
, *y
;
1343 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1344 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1348 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1349 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1350 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1351 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1354 if (pix_x
< 0) pix_x
= 0;
1355 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1357 if (pix_y
< 0) pix_y
= 0;
1358 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1364 /* Any buttons grabbed. */
1365 unsigned int x_mouse_grabbed
;
1367 /* Which modifier keys are on which modifier bits?
1369 With each keystroke, X returns eight bits indicating which modifier
1370 keys were held down when the key was pressed. The interpretation
1371 of the top five modifier bits depends on what keys are attached
1372 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1375 x_meta_mod_mask is a mask containing the bits used for the meta key.
1376 It may have more than one bit set, if more than one modifier bit
1377 has meta keys on it. Basically, if EVENT is a KeyPress event,
1378 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1380 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1381 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1382 only be affected by the lock modifier bit if XK_Shift_Lock is in
1383 use; XK_Caps_Lock should only affect alphabetic keys. With this
1384 arrangement, the lock modifier should shift the character if
1385 (EVENT.state & x_shift_lock_mask) != 0. */
1386 static int x_meta_mod_mask
, x_shift_lock_mask
;
1388 /* Initialize mode_switch_bit and modifier_meaning. */
1390 x_find_modifier_meanings ()
1392 int min_code
, max_code
;
1395 XModifierKeymap
*mods
;
1396 int alt_mod_mask
= 0;
1398 x_meta_mod_mask
= 0;
1399 x_shift_lock_mask
= 0;
1401 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1402 syms
= XGetKeyboardMapping (x_current_display
,
1403 min_code
, max_code
- min_code
+ 1,
1405 mods
= XGetModifierMapping (x_current_display
);
1407 /* Scan the modifier table to see which modifier bits the Meta and
1408 Alt keysyms are on. */
1410 int row
, col
; /* The row and column in the modifier table. */
1412 for (row
= 3; row
< 8; row
++)
1413 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1416 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1418 /* Are any of this keycode's keysyms a meta key? */
1422 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1424 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1430 x_meta_mod_mask
|= (1 << row
);
1435 alt_mod_mask
|= (1 << row
);
1439 /* Ignore this if it's not on the lock modifier. */
1440 if ((1 << row
) == LockMask
)
1441 x_shift_lock_mask
= LockMask
;
1449 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1450 if (! x_meta_mod_mask
)
1451 x_meta_mod_mask
= alt_mod_mask
;
1453 XFree ((char *) syms
);
1454 XFreeModifiermap (mods
);
1458 /* Convert a set of X modifier bits to the proper form for a
1459 struct input_event modifiers value. */
1462 x_convert_modifiers (state
)
1465 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1466 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1467 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0));
1470 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1472 If the event is a button press, then note that we have grabbed
1476 construct_mouse_click (result
, event
, f
)
1477 struct input_event
*result
;
1478 XButtonEvent
*event
;
1481 /* Make the event type no_event; we'll change that when we decide
1483 result
->kind
= mouse_click
;
1484 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1485 result
->timestamp
= event
->time
;
1486 result
->modifiers
= (x_convert_modifiers (event
->state
)
1487 | (event
->type
== ButtonRelease
1491 /* Notice if the mouse is still grabbed. */
1492 if (event
->type
== ButtonPress
)
1494 if (! x_mouse_grabbed
)
1495 Vmouse_depressed
= Qt
;
1496 x_mouse_grabbed
|= (1 << event
->button
);
1498 else if (event
->type
== ButtonRelease
)
1500 x_mouse_grabbed
&= ~(1 << event
->button
);
1501 if (!x_mouse_grabbed
)
1502 Vmouse_depressed
= Qnil
;
1508 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1509 XFASTINT (result
->x
) = column
;
1510 XFASTINT (result
->y
) = row
;
1511 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1516 /* Mouse movement. Rah.
1518 In order to avoid asking for motion events and then throwing most
1519 of them away or busy-polling the server for mouse positions, we ask
1520 the server for pointer motion hints. This means that we get only
1521 one event per group of mouse movements. "Groups" are delimited by
1522 other kinds of events (focus changes and button clicks, for
1523 example), or by XQueryPointer calls; when one of these happens, we
1524 get another MotionNotify event the next time the mouse moves. This
1525 is at least as efficient as getting motion events when mouse
1526 tracking is on, and I suspect only negligibly worse when tracking
1529 The silly O'Reilly & Associates Nutshell guides barely document
1530 pointer motion hints at all (I think you have to infer how they
1531 work from an example), and the description of XQueryPointer doesn't
1532 mention that calling it causes you to get another motion hint from
1533 the server, which is very important. */
1535 /* Where the mouse was last time we reported a mouse event. */
1536 static FRAME_PTR last_mouse_frame
;
1537 static XRectangle last_mouse_glyph
;
1539 /* The scrollbar in which the last X motion event occurred.
1541 If the last X motion event occured in a scrollbar, we set this
1542 so XTmouse_position can know whether to report a scrollbar motion or
1545 If the last X motion event didn't occur in a scrollbar, we set this
1546 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1547 static Lisp_Object last_mouse_scrollbar
;
1549 /* This is a hack. We would really prefer that XTmouse_position would
1550 return the time associated with the position it returns, but there
1551 doesn't seem to be any way to wrest the timestamp from the server
1552 along with the position query. So, we just keep track of the time
1553 of the last movement we received, and return that in hopes that
1554 it's somewhat accurate. */
1555 static Time last_mouse_movement_time
;
1557 /* Function to report a mouse movement to the mainstream Emacs code.
1558 The input handler calls this.
1560 We have received a mouse movement event, which is given in *event.
1561 If the mouse is over a different glyph than it was last time, tell
1562 the mainstream emacs code by setting mouse_moved. If not, ask for
1563 another motion event, so we can check again the next time it moves. */
1565 note_mouse_movement (frame
, event
)
1567 XMotionEvent
*event
;
1570 last_mouse_movement_time
= event
->time
;
1572 /* Has the mouse moved off the glyph it was on at the last sighting? */
1573 if (event
->x
< last_mouse_glyph
.x
1574 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1575 || event
->y
< last_mouse_glyph
.y
1576 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1579 last_mouse_scrollbar
= Qnil
;
1583 /* It's on the same glyph. Call XQueryPointer so we'll get an
1584 event the next time the mouse moves and we can see if it's
1585 *still* on the same glyph. */
1588 XQueryPointer (event
->display
, event
->window
,
1589 (Window
*) &dummy
, (Window
*) &dummy
,
1590 &dummy
, &dummy
, &dummy
, &dummy
,
1591 (unsigned int *) &dummy
);
1595 static struct scrollbar
*x_window_to_scrollbar ();
1596 static void x_scrollbar_report_motion ();
1598 /* Return the current position of the mouse.
1600 If the mouse movement started in a scrollbar, set *f, *bar_window,
1601 and *part to the frame, window, and scrollbar part that the mouse
1602 is over. Set *x and *y to the portion and whole of the mouse's
1603 position on the scrollbar.
1605 If the mouse movement started elsewhere, set *f to the frame the
1606 mouse is on, *bar_window to nil, and *x and *y to the character cell
1609 Set *time to the server timestamp for the time at which the mouse
1610 was at this position.
1612 This clears the mouse_moved flag, so we can wait for the next mouse
1613 movement. This also calls XQueryPointer, which will cause the
1614 server to give us another MotionNotify when the mouse moves
1618 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1620 Lisp_Object
*bar_window
;
1621 enum scrollbar_part
*part
;
1623 unsigned long *time
;
1627 if (! NILP (last_mouse_scrollbar
))
1628 x_scrollbar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1634 Window dummy_window
;
1638 last_mouse_scrollbar
= Qnil
;
1640 /* Figure out which root window we're on. */
1641 XQueryPointer (x_current_display
,
1642 DefaultRootWindow (x_current_display
),
1644 /* The root window which contains the pointer. */
1647 /* Trash which we can't trust if the pointer is on
1648 a different screen. */
1651 /* The position on that root window. */
1654 /* More trash we can't trust. */
1657 /* Modifier keys and pointer buttons, about which
1659 (unsigned int *) &dummy
);
1661 /* Now we have a position on the root; find the innermost window
1662 containing the pointer. */
1666 int parent_x
, parent_y
;
1671 XTranslateCoordinates (x_current_display
,
1673 /* From-window, to-window. */
1676 /* From-position, to-position. */
1677 root_x
, root_y
, &win_x
, &win_y
,
1690 /* Now we know that:
1691 win is the innermost window containing the pointer
1692 (XTC says it has no child containing the pointer),
1693 win_x and win_y are the pointer's position in it
1694 (XTC did this the last time through), and
1695 parent_x and parent_y are the pointer's position in win's parent.
1696 (They are what win_x and win_y were when win was child.
1697 If win is the root window, it has no parent, and
1698 parent_{x,y} are invalid, but that's okay, because we'll
1699 never use them in that case.) */
1701 /* Is win one of our frames? */
1702 *f
= x_window_to_frame (win
);
1704 /* If not, is it one of our scrollbars? */
1707 struct scrollbar
*bar
= x_window_to_scrollbar (win
);
1711 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1719 pixel_to_glyph_coords (*f
, win_x
, win_y
, &win_x
, &win_y
,
1724 XSET (*x
, Lisp_Int
, win_x
);
1725 XSET (*y
, Lisp_Int
, win_y
);
1726 *time
= last_mouse_movement_time
;
1734 #else /* ! defined (HAVE_X11) */
1735 #define XEvent XKeyPressedEvent
1736 #endif /* ! defined (HAVE_X11) */
1738 /* Scrollbar support. */
1740 /* Given an X window ID, find the struct scrollbar which manages it. */
1741 static struct scrollbar
*
1742 x_window_to_scrollbar (window_id
)
1745 Lisp_Object tail
, frame
;
1747 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1749 Lisp_Object frame
= XCONS (tail
)->car
;
1750 Lisp_Object bar
, condemned
;
1752 /* All elements of Vframe_list should be frames. */
1753 if (XTYPE (frame
) != Lisp_Frame
)
1756 /* Scan this frame's scrollbar list for a scrollbar with the
1758 condemned
= FRAME_CONDEMNED_SCROLLBARS (XFRAME (frame
));
1759 for (bar
= FRAME_SCROLLBARS (XFRAME (frame
));
1760 /* This trick allows us to search both the ordinary and
1761 condemned scrollbar lists with one loop. */
1762 ! NILP (bar
) || (bar
= condemned
, condemned
= Qnil
, ! NILP (bar
));
1763 bar
= XSCROLLBAR(bar
)->next
)
1764 if (SCROLLBAR_X_WINDOW (XSCROLLBAR (bar
)) == window_id
)
1765 return XSCROLLBAR (bar
);
1771 /* Open a new X window to serve as a scrollbar, and return the
1772 scrollbar vector for it. */
1773 static struct scrollbar
*
1774 x_scrollbar_create (window
, top
, left
, width
, height
)
1775 struct window
*window
;
1776 int top
, left
, width
, height
;
1778 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1779 struct scrollbar
*bar
=
1780 XSCROLLBAR (Fmake_vector (make_number (SCROLLBAR_VEC_SIZE
), Qnil
));
1785 XSetWindowAttributes a
;
1788 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1789 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1790 | ButtonMotionMask
| PointerMotionHintMask
1792 a
.cursor
= x_vertical_scrollbar_cursor
;
1794 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1796 SET_SCROLLBAR_X_WINDOW
1798 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1800 /* Position and size of scrollbar. */
1801 left
, top
, width
, height
,
1803 /* Border width, depth, class, and visual. */
1804 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1810 XSET (bar
->window
, Lisp_Window
, window
);
1811 XSET (bar
->top
, Lisp_Int
, top
);
1812 XSET (bar
->left
, Lisp_Int
, left
);
1813 XSET (bar
->width
, Lisp_Int
, width
);
1814 XSET (bar
->height
, Lisp_Int
, height
);
1815 XSET (bar
->start
, Lisp_Int
, 0);
1816 XSET (bar
->end
, Lisp_Int
, 0);
1817 bar
->dragging
= Qnil
;
1819 /* Add bar to its frame's list of scroll bars. */
1820 bar
->next
= FRAME_SCROLLBARS (frame
);
1822 XSET (FRAME_SCROLLBARS (frame
), Lisp_Vector
, bar
);
1823 if (! NILP (bar
->next
))
1824 XSET (XSCROLLBAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1826 XMapWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
));
1833 /* Draw BAR's handle in the proper position.
1834 If the handle is already drawn from START to END, don't bother
1835 redrawing it, unless REBUILD is non-zero; in that case, always
1836 redraw it. (REBUILD is handy for drawing the handle after expose
1839 Normally, we want to constrain the start and end of the handle to
1840 fit inside its rectangle, but if the user is dragging the scrollbar
1841 handle, we want to let them drag it down all the way, so that the
1842 bar's top is as far down as it goes; otherwise, there's no way to
1843 move to the very end of the buffer. */
1845 x_scrollbar_set_handle (bar
, start
, end
, rebuild
)
1846 struct scrollbar
*bar
;
1850 int dragging
= ! NILP (bar
->dragging
);
1851 Window w
= SCROLLBAR_X_WINDOW (bar
);
1852 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1854 /* If the display is already accurate, do nothing. */
1856 && start
== XINT (bar
->start
)
1857 && end
== XINT (bar
->end
))
1863 int inside_width
= VERTICAL_SCROLLBAR_INSIDE_WIDTH (XINT (bar
->width
));
1864 int inside_height
= VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
1865 int top_range
= VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
1867 /* Make sure the values are reasonable, and try to preserve
1868 the distance between start and end. */
1870 int length
= end
- start
;
1874 else if (start
> top_range
)
1876 end
= start
+ length
;
1880 else if (end
> top_range
&& ! dragging
)
1884 /* Store the adjusted setting in the scrollbar. */
1885 XSET (bar
->start
, Lisp_Int
, start
);
1886 XSET (bar
->end
, Lisp_Int
, end
);
1888 /* Clip the end position, just for display. */
1889 if (end
> top_range
)
1892 /* Draw bottom positions VERTICAL_SCROLLBAR_MIN_HANDLE pixels
1893 below top positions, to make sure the handle is always at least
1894 that many pixels tall. */
1895 end
+= VERTICAL_SCROLLBAR_MIN_HANDLE
;
1897 /* Draw the empty space above the handle. Note that we can't clear
1898 zero-height areas; that means "clear to end of window." */
1900 XClearArea (x_current_display
, w
,
1902 /* x, y, width, height, and exposures. */
1903 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1904 VERTICAL_SCROLLBAR_TOP_BORDER
,
1905 inside_width
, start
,
1908 /* Draw the handle itself. */
1909 XFillRectangle (x_current_display
, w
, gc
,
1911 /* x, y, width, height */
1912 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1913 VERTICAL_SCROLLBAR_TOP_BORDER
+ start
,
1914 inside_width
, end
- start
);
1917 /* Draw the empty space below the handle. Note that we can't
1918 clear zero-height areas; that means "clear to end of window." */
1919 if (end
< inside_height
)
1920 XClearArea (x_current_display
, w
,
1922 /* x, y, width, height, and exposures. */
1923 VERTICAL_SCROLLBAR_LEFT_BORDER
,
1924 VERTICAL_SCROLLBAR_TOP_BORDER
+ end
,
1925 inside_width
, inside_height
- end
,
1933 /* Move a scrollbar around on the screen, to accomodate changing
1934 window configurations. */
1936 x_scrollbar_move (bar
, top
, left
, width
, height
)
1937 struct scrollbar
*bar
;
1938 int top
, left
, width
, height
;
1944 unsigned int mask
= 0;
1951 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
1952 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
1953 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
1954 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
1957 XConfigureWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
),
1961 XSET (bar
->left
, Lisp_Int
, left
);
1962 XSET (bar
->top
, Lisp_Int
, top
);
1963 XSET (bar
->width
, Lisp_Int
, width
);
1964 XSET (bar
->height
, Lisp_Int
, height
);
1969 /* Destroy the X window for BAR, and set its Emacs window's scrollbar
1972 x_scrollbar_remove (bar
)
1973 struct scrollbar
*bar
;
1975 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1979 /* Destroy the window. */
1980 XDestroyWindow (x_current_display
, SCROLLBAR_X_WINDOW (bar
));
1982 /* Disassociate this scrollbar from its window. */
1983 XWINDOW (bar
->window
)->vertical_scrollbar
= Qnil
;
1988 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1989 that we are displaying PORTION characters out of a total of WHOLE
1990 characters, starting at POSITION. If WINDOW has no scrollbar,
1993 XTset_vertical_scrollbar (window
, portion
, whole
, position
)
1994 struct window
*window
;
1995 int portion
, whole
, position
;
1997 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1998 int top
= XINT (window
->top
);
1999 int left
= WINDOW_VERTICAL_SCROLLBAR_COLUMN (window
);
2000 int height
= WINDOW_VERTICAL_SCROLLBAR_HEIGHT (window
);
2002 /* Where should this scrollbar be, pixelwise? */
2003 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2004 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2005 int pixel_width
= VERTICAL_SCROLLBAR_PIXEL_WIDTH (f
);
2006 int pixel_height
= VERTICAL_SCROLLBAR_PIXEL_HEIGHT (f
, height
);
2008 struct scrollbar
*bar
;
2010 /* Does the scrollbar exist yet? */
2011 if (NILP (window
->vertical_scrollbar
))
2012 bar
= x_scrollbar_create (window
,
2013 pixel_top
, pixel_left
,
2014 pixel_width
, pixel_height
);
2017 /* It may just need to be moved and resized. */
2018 bar
= XSCROLLBAR (window
->vertical_scrollbar
);
2019 x_scrollbar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2022 /* Set the scrollbar's current state, unless we're currently being
2024 if (NILP (bar
->dragging
))
2027 VERTICAL_SCROLLBAR_TOP_RANGE (pixel_height
);
2030 x_scrollbar_set_handle (bar
, 0, top_range
, 0);
2033 int start
= (position
* top_range
) / whole
;
2034 int end
= ((position
+ portion
) * top_range
) / whole
;
2036 x_scrollbar_set_handle (bar
, start
, end
, 0);
2040 XSET (window
->vertical_scrollbar
, Lisp_Vector
, bar
);
2044 /* The following three hooks are used when we're doing a thorough
2045 redisplay of the frame. We don't explicitly know which scrollbars
2046 are going to be deleted, because keeping track of when windows go
2047 away is a real pain - "Can you say set-window-configuration, boys
2048 and girls?" Instead, we just assert at the beginning of redisplay
2049 that *all* scrollbars are to be removed, and then save a scrollbar
2050 from the fiery pit when we actually redisplay its window. */
2052 /* Arrange for all scrollbars on FRAME to be removed at the next call
2053 to `*judge_scrollbars_hook'. A scrollbar may be spared if
2054 `*redeem_scrollbar_hook' is applied to its window before the judgement. */
2056 XTcondemn_scrollbars (frame
)
2059 /* The condemned list should be empty at this point; if it's not,
2060 then the rest of Emacs isn't using the condemn/redeem/judge
2061 protocol correctly. */
2062 if (! NILP (FRAME_CONDEMNED_SCROLLBARS (frame
)))
2065 /* Move them all to the "condemned" list. */
2066 FRAME_CONDEMNED_SCROLLBARS (frame
) = FRAME_SCROLLBARS (frame
);
2067 FRAME_SCROLLBARS (frame
) = Qnil
;
2070 /* Unmark WINDOW's scrollbar for deletion in this judgement cycle.
2071 Note that WINDOW isn't necessarily condemned at all. */
2073 XTredeem_scrollbar (window
)
2074 struct window
*window
;
2076 struct scrollbar
*bar
;
2078 /* We can't redeem this window's scrollbar if it doesn't have one. */
2079 if (NILP (window
->vertical_scrollbar
))
2082 bar
= XSCROLLBAR (window
->vertical_scrollbar
);
2084 /* Unlink it from the condemned list. */
2086 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2088 if (NILP (bar
->prev
))
2090 /* If the prev pointer is nil, it must be the first in one of
2092 if (EQ (FRAME_SCROLLBARS (f
), window
->vertical_scrollbar
))
2093 /* It's not condemned. Everything's fine. */
2095 else if (EQ (FRAME_CONDEMNED_SCROLLBARS (f
),
2096 window
->vertical_scrollbar
))
2097 FRAME_CONDEMNED_SCROLLBARS (f
) = bar
->next
;
2099 /* If its prev pointer is nil, it must be at the front of
2100 one or the other! */
2104 XSCROLLBAR (bar
->prev
)->next
= bar
->next
;
2106 if (! NILP (bar
->next
))
2107 XSCROLLBAR (bar
->next
)->prev
= bar
->prev
;
2109 bar
->next
= FRAME_SCROLLBARS (f
);
2111 XSET (FRAME_SCROLLBARS (f
), Lisp_Vector
, bar
);
2112 if (! NILP (bar
->next
))
2113 XSET (XSCROLLBAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2117 /* Remove all scrollbars on FRAME that haven't been saved since the
2118 last call to `*condemn_scrollbars_hook'. */
2120 XTjudge_scrollbars (f
)
2123 Lisp_Object bar
, next
;
2125 bar
= FRAME_CONDEMNED_SCROLLBARS (f
);
2127 /* Clear out the condemned list now so we won't try to process any
2128 more events on the hapless scrollbars. */
2129 FRAME_CONDEMNED_SCROLLBARS (f
) = Qnil
;
2131 for (; ! NILP (bar
); bar
= next
)
2133 struct scrollbar
*b
= XSCROLLBAR (bar
);
2135 x_scrollbar_remove (b
);
2138 b
->next
= b
->prev
= Qnil
;
2141 /* Now there should be no references to the condemned scrollbars,
2142 and they should get garbage-collected. */
2146 /* Handle an Expose or GraphicsExpose event on a scrollbar. */
2148 x_scrollbar_expose (bar
, event
)
2149 struct scrollbar
*bar
;
2152 Window w
= SCROLLBAR_X_WINDOW (bar
);
2153 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2157 x_scrollbar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2159 /* Draw a one-pixel border just inside the edges of the scrollbar. */
2160 XDrawRectangle (x_current_display
, w
, gc
,
2162 /* x, y, width, height */
2163 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2165 /* Draw another line to make the extra-thick border on the right. */
2166 XFillRectangle (x_current_display
, w
, gc
,
2168 /* x, y, width, height */
2169 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2174 /* Handle a mouse click on the scrollbar BAR. If *EMACS_EVENT's kind
2175 is set to something other than no_event, it is enqueued. */
2177 x_scrollbar_handle_click (bar
, event
, emacs_event
)
2178 struct scrollbar
*bar
;
2180 struct input_event
*emacs_event
;
2182 if (XTYPE (bar
->window
) != Lisp_Window
)
2185 emacs_event
->kind
= scrollbar_click
;
2186 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2187 emacs_event
->modifiers
=
2188 (x_convert_modifiers (event
->xbutton
.state
)
2189 | (event
->type
== ButtonRelease
2192 emacs_event
->frame_or_window
= bar
->window
;
2193 emacs_event
->timestamp
= event
->xbutton
.time
;
2195 int internal_height
=
2196 VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
2198 VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
2199 int y
= event
->xbutton
.y
- VERTICAL_SCROLLBAR_TOP_BORDER
;
2202 if (y
> top_range
) y
= top_range
;
2204 if (y
< XINT (bar
->start
))
2205 emacs_event
->part
= scrollbar_above_handle
;
2206 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLLBAR_MIN_HANDLE
)
2207 emacs_event
->part
= scrollbar_handle
;
2209 emacs_event
->part
= scrollbar_below_handle
;
2211 /* If the user has just clicked on the handle, record where they're
2213 if (event
->type
== ButtonPress
2214 && emacs_event
->part
== scrollbar_handle
)
2215 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2217 /* If the user has released the handle, set it to its final position. */
2218 if (event
->type
== ButtonRelease
2219 && ! NILP (bar
->dragging
))
2221 int new_start
= y
- XINT (bar
->dragging
);
2222 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2224 x_scrollbar_set_handle (bar
, new_start
, new_end
, 0);
2225 bar
->dragging
= Qnil
;
2228 /* Clicks on the handle are always reported as occuring at the top of
2230 if (emacs_event
->part
== scrollbar_handle
)
2231 emacs_event
->x
= bar
->start
;
2233 XSET (emacs_event
->x
, Lisp_Int
, y
);
2235 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2239 /* Handle some mouse motion while someone is dragging the scrollbar. */
2241 x_scrollbar_note_movement (bar
, event
)
2242 struct scrollbar
*bar
;
2245 last_mouse_movement_time
= event
->xmotion
.time
;
2248 XSET (last_mouse_scrollbar
, Lisp_Vector
, bar
);
2250 /* If we're dragging the bar, display it. */
2251 if (! NILP (bar
->dragging
))
2253 /* Where should the handle be now? */
2254 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2256 if (new_start
!= XINT (bar
->start
))
2258 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2260 x_scrollbar_set_handle (bar
, new_start
, new_end
, 0);
2264 /* Call XQueryPointer so we'll get an event the next time the mouse
2265 moves and we can see *still* on the same position. */
2269 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2270 (Window
*) &dummy
, (Window
*) &dummy
,
2271 &dummy
, &dummy
, &dummy
, &dummy
,
2272 (unsigned int *) &dummy
);
2276 /* Return information to the user about the current position of the mouse
2277 on the scrollbar. */
2279 x_scrollbar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2281 Lisp_Object
*bar_window
;
2282 enum scrollbar_part
*part
;
2284 unsigned long *time
;
2286 struct scrollbar
*bar
= XSCROLLBAR (last_mouse_scrollbar
);
2291 /* Get the mouse's position relative to the scrollbar window, and
2294 Window dummy_window
;
2296 unsigned int dummy_mask
;
2298 if (! XQueryPointer (x_current_display
,
2299 SCROLLBAR_X_WINDOW (bar
),
2301 /* Root, child, root x and root y. */
2302 &dummy_window
, &dummy_window
,
2303 &dummy_coord
, &dummy_coord
,
2305 /* Position relative to scrollbar. */
2308 /* Mouse buttons and modifier keys. */
2317 int inside_height
= VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar
->height
));
2318 int top_range
= VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar
->height
));
2320 win_y
-= VERTICAL_SCROLLBAR_TOP_BORDER
;
2322 if (! NILP (bar
->dragging
))
2323 win_y
-= XINT (bar
->dragging
);
2327 if (win_y
> top_range
)
2330 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2331 *bar_window
= bar
->window
;
2333 if (! NILP (bar
->dragging
))
2334 *part
= scrollbar_handle
;
2335 else if (win_y
< XINT (bar
->start
))
2336 *part
= scrollbar_above_handle
;
2337 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLLBAR_MIN_HANDLE
)
2338 *part
= scrollbar_handle
;
2340 *part
= scrollbar_below_handle
;
2342 XSET (*x
, Lisp_Int
, win_y
);
2343 XSET (*y
, Lisp_Int
, top_range
);
2344 *time
= last_mouse_movement_time
;
2348 last_mouse_scrollbar
= Qnil
;
2355 /* The screen has been cleared so we may have changed foreground or
2356 background colors, and the scrollbars may need to be redrawn.
2357 Clear out the scrollbars, and ask for expose events, so we can
2360 x_scrollbar_clear (f
)
2365 for (bar
= FRAME_SCROLLBARS (f
);
2366 XTYPE (bar
) == Lisp_Vector
;
2367 bar
= XSCROLLBAR (bar
)->next
)
2368 XClearArea (x_current_display
, SCROLLBAR_X_WINDOW (XSCROLLBAR (bar
)),
2374 /* The main X event-reading loop - XTread_socket. */
2376 /* Timestamp of enter window event. This is only used by XTread_socket,
2377 but we have to put it out here, since static variables within functions
2378 sometimes don't work. */
2379 static Time enter_timestamp
;
2381 /* This holds the state XLookupString needs to implement dead keys
2382 and other tricks known as "compose processing". _X Window System_
2383 says that a portable program can't use this, but Stephen Gildea assures
2384 me that letting the compiler initialize it to zeros will work okay.
2386 This must be defined outside of XTread_socket, for the same reasons
2387 given for enter_timestamp, above. */
2388 static XComposeStatus compose_status
;
2390 /* Communication with window managers. */
2391 Atom Xatom_wm_protocols
;
2393 /* Kinds of protocol things we may receive. */
2394 Atom Xatom_wm_take_focus
;
2395 Atom Xatom_wm_save_yourself
;
2396 Atom Xatom_wm_delete_window
;
2398 /* Other WM communication */
2399 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2400 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2402 /* Read events coming from the X server.
2403 This routine is called by the SIGIO handler.
2404 We return as soon as there are no more events to be read.
2406 Events representing keys are stored in buffer BUFP,
2407 which can hold up to NUMCHARS characters.
2408 We return the number of characters stored into the buffer,
2409 thus pretending to be `read'.
2411 WAITP is nonzero if we should block until input arrives.
2412 EXPECTED is nonzero if the caller knows input is available. */
2415 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2417 register struct input_event
*bufp
;
2418 register int numchars
;
2425 int items_pending
; /* How many items are in the X queue. */
2432 if (x_input_blocked
)
2434 x_pending_input
= 1;
2438 x_pending_input
= 0;
2442 abort (); /* Don't think this happens. */
2445 /* If available, Xlib uses FIOSNBIO to make the socket
2446 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2447 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2448 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2449 fcntl (fileno (stdin
), F_SETFL
, 0);
2450 #endif /* ! defined (FIOSNBIO) */
2454 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2456 extern int read_alarm_should_throw
;
2457 read_alarm_should_throw
= 1;
2458 XPeekEvent (XDISPLAY
&event
);
2459 read_alarm_should_throw
= 0;
2461 #endif /* HAVE_SELECT */
2464 while (XStuffPending () != 0)
2466 XNextEvent (XDISPLAY
&event
);
2474 if (event
.xclient
.message_type
== Xatom_wm_protocols
2475 && event
.xclient
.format
== 32)
2477 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2479 f
= x_window_to_frame (event
.xclient
.window
);
2481 x_focus_on_frame (f
);
2482 /* Not certain about handling scrollbars here */
2484 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2486 /* Save state modify the WM_COMMAND property to
2487 something which can reinstate us. This notifies
2488 the session manager, who's looking for such a
2489 PropertyNotify. Can restart processing when
2490 a keyboard or mouse event arrives. */
2495 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2497 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2505 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2508 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2512 new_x
= event
.xclient
.data
.s
[0];
2513 new_y
= event
.xclient
.data
.s
[1];
2518 case SelectionClear
: /* Someone has grabbed ownership. */
2519 x_disown_selection (event
.xselectionclear
.window
,
2520 event
.xselectionclear
.selection
,
2521 event
.xselectionclear
.time
);
2524 case SelectionRequest
: /* Someone wants our selection. */
2525 x_answer_selection_request (event
);
2528 case PropertyNotify
:
2530 /* If we're being told about a root window property, then it's
2531 a cut buffer change. */
2532 if (event
.xproperty
.window
== ROOT_WINDOW
)
2533 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2535 /* Otherwise, we're probably handling an incremental
2536 selection transmission. */
2539 /* If we were to do this synchronously, there'd be no worry
2540 about re-selecting. */
2541 x_send_incremental (event
);
2546 f
= x_window_to_frame (event
.xexpose
.window
);
2549 if (f
->async_visible
== 0)
2551 f
->async_visible
= 1;
2552 f
->async_iconified
= 0;
2553 SET_FRAME_GARBAGED (f
);
2557 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2558 event
.xexpose
.x
, event
.xexpose
.y
,
2559 event
.xexpose
.width
, event
.xexpose
.height
);
2564 struct scrollbar
*bar
2565 = x_window_to_scrollbar (event
.xexpose
.window
);
2568 x_scrollbar_expose (bar
, &event
);
2572 case GraphicsExpose
: /* This occurs when an XCopyArea's
2573 source area was obscured or not
2575 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2579 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2580 event
.xgraphicsexpose
.width
,
2581 event
.xgraphicsexpose
.height
);
2585 case NoExpose
: /* This occurs when an XCopyArea's
2586 source area was completely
2589 #else /* ! defined (HAVE_X11) */
2591 if (event
.subwindow
!= 0)
2592 break; /* duplicate event */
2593 f
= x_window_to_frame (event
.window
);
2594 if (event
.window
== f
->display
.x
->icon_desc
)
2597 f
->async_iconified
= 1;
2599 if (event
.window
== FRAME_X_WINDOW (f
))
2601 /* Say must check all windows' needs_exposure flags. */
2602 expose_all_windows
= 1;
2603 f
->display
.x
->needs_exposure
= 1;
2604 f
->async_visible
= 1;
2609 if (event
.subwindow
!= 0)
2610 break; /* duplicate event */
2611 f
= x_window_to_frame (event
.window
);
2612 if (event
.window
== f
->display
.x
->icon_desc
)
2617 /* If window already needs full redraw, ignore this rectangle. */
2618 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2620 /* Put the event on the queue of rectangles to redraw. */
2621 if (enqueue_event (&event
, &x_expose_queue
))
2622 /* If it is full, we can't record the rectangle,
2623 so redraw this entire window. */
2625 /* Say must check all windows' needs_exposure flags. */
2626 expose_all_windows
= 1;
2627 f
->display
.x
->needs_exposure
= 1;
2632 /* This should happen only when we are expecting it,
2633 in x_read_exposes. */
2635 #endif /* ! defined (HAVE_X11) */
2639 f
= x_window_to_frame (event
.xunmap
.window
);
2640 if (f
) /* F may no longer exist if
2641 the frame was deleted. */
2643 /* While a frame is unmapped, display generation is
2644 disabled; you don't want to spend time updating a
2645 display that won't ever be seen. */
2646 f
->async_visible
= 0;
2651 f
= x_window_to_frame (event
.xmap
.window
);
2654 f
->async_visible
= 1;
2655 f
->async_iconified
= 0;
2657 /* wait_reading_process_input will notice this and update
2658 the frame's display structures. */
2659 SET_FRAME_GARBAGED (f
);
2663 /* Turn off processing if we become fully obscured. */
2664 case VisibilityNotify
:
2667 #else /* ! defined (HAVE_X11) */
2669 f
= x_window_to_frame (event
.window
);
2670 if (event
.window
== f
->display
.x
->icon_desc
)
2671 f
->async_iconified
= 0;
2672 if (event
.window
== FRAME_X_WINDOW (f
))
2673 f
->async_visible
= 0;
2675 #endif /* ! defined (HAVE_X11) */
2679 f
= x_window_to_frame (event
.xkey
.window
);
2684 char copy_buffer
[80];
2687 event
.xkey
.state
|= extra_keyboard_modifiers
;
2688 modifiers
= event
.xkey
.state
;
2690 /* Some keyboards generate different characters
2691 depending on the state of the meta key, in an attempt
2692 to support non-English typists. It would be nice to
2693 keep this functionality somehow, but for now, we will
2694 just clear the meta-key flag to get the 'pure' character. */
2695 event
.xkey
.state
&= ~Mod1Mask
;
2697 /* This will have to go some day... */
2699 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2702 /* Strip off the vendor-specific keysym bit, and take a shot
2703 at recognizing the codes. HP servers have extra keysyms
2704 that fit into the MiscFunctionKey category. */
2709 if (IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2710 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < 0xff80 */
2711 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2712 || IsFunctionKey (keysym
)) /* 0xffbe <= x < 0xffe1 */
2714 bufp
->kind
= non_ascii_keystroke
;
2715 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff50);
2716 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2717 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2718 bufp
->timestamp
= event
.xkey
.time
;
2723 else if (numchars
> nbytes
)
2729 if (modifiers
& x_meta_mod_mask
)
2730 *copy_buffer
|= METABIT
;
2731 bufp
->kind
= ascii_keystroke
;
2732 XSET (bufp
->code
, Lisp_Int
, *copy_buffer
);
2733 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2734 bufp
->timestamp
= event
.xkey
.time
;
2738 for (i
= nbytes
- 1; i
> 1; i
--)
2740 bufp
->kind
= ascii_keystroke
;
2741 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2742 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2743 bufp
->timestamp
= event
.xkey
.time
;
2753 #else /* ! defined (HAVE_X11) */
2756 register char *where_mapping
;
2758 f
= x_window_to_frame (event
.window
);
2759 /* Ignore keys typed on icon windows. */
2760 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2762 where_mapping
= XLookupMapping (&event
, &nbytes
);
2763 /* Nasty fix for arrow keys */
2764 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2766 switch (event
.detail
& 0xff)
2768 case KC_CURSOR_LEFT
:
2769 where_mapping
= "\002";
2771 case KC_CURSOR_RIGHT
:
2772 where_mapping
= "\006";
2775 where_mapping
= "\020";
2777 case KC_CURSOR_DOWN
:
2778 where_mapping
= "\016";
2783 if (numchars
- nbytes
> 0)
2787 for (i
= 0; i
< nbytes
; i
++)
2789 bufp
->kind
= ascii_keystroke
;
2790 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2791 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2792 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2800 #endif /* ! defined (HAVE_X11) */
2804 /* Here's a possible interpretation of the whole
2805 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2806 FocusIn event, you have to get a FocusOut event before you
2807 relinquish the focus. If you haven't received a FocusIn event,
2808 then a mere LeaveNotify is enough to free you. */
2811 f
= x_window_to_frame (event
.xcrossing
.window
);
2813 if (event
.xcrossing
.focus
) /* Entered Window */
2815 /* Avoid nasty pop/raise loops. */
2816 if (f
&& (!(f
->auto_raise
)
2818 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
2820 x_new_focus_frame (f
);
2821 enter_timestamp
= event
.xcrossing
.time
;
2824 else if (f
== x_focus_frame
)
2825 x_new_focus_frame (0);
2830 f
= x_window_to_frame (event
.xfocus
.window
);
2831 if (event
.xfocus
.detail
!= NotifyPointer
)
2832 x_focus_event_frame
= f
;
2834 x_new_focus_frame (f
);
2839 f
= x_window_to_frame (event
.xcrossing
.window
);
2841 if (event
.xcrossing
.focus
)
2843 if (! x_focus_event_frame
)
2844 x_new_focus_frame (0);
2846 x_new_focus_frame (f
);
2850 if (f
== x_focus_event_frame
)
2851 x_focus_event_frame
= 0;
2852 if (f
== x_focus_frame
)
2853 x_new_focus_frame (0);
2858 f
= x_window_to_frame (event
.xfocus
.window
);
2859 if (event
.xfocus
.detail
!= NotifyPointer
2860 && f
== x_focus_event_frame
)
2861 x_focus_event_frame
= 0;
2862 if (f
&& f
== x_focus_frame
)
2863 x_new_focus_frame (0);
2866 #else /* ! defined (HAVE_X11) */
2869 if ((event
.detail
& 0xFF) == 1)
2870 break; /* Coming from our own subwindow */
2871 if (event
.subwindow
!= 0)
2872 break; /* Entering our own subwindow. */
2875 f
= x_window_to_frame (event
.window
);
2878 x_new_focus_frame (f
);
2883 if ((event
.detail
& 0xFF) == 1)
2884 break; /* Entering our own subwindow */
2885 if (event
.subwindow
!= 0)
2886 break; /* Leaving our own subwindow. */
2889 if (x_focus_frame
== 0
2890 && x_input_frame
!= 0
2891 && x_input_frame
== x_window_to_frame (event
.window
)
2892 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
2897 frame_unhighlight (f
);
2900 #endif /* ! defined (HAVE_X11) */
2905 f
= x_window_to_frame (event
.xmotion
.window
);
2907 note_mouse_movement (f
, &event
.xmotion
);
2910 struct scrollbar
*bar
=
2911 x_window_to_scrollbar (event
.xmotion
.window
);
2914 x_scrollbar_note_movement (bar
, &event
);
2919 case ConfigureNotify
:
2920 f
= x_window_to_frame (event
.xconfigure
.window
);
2923 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
2924 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
2926 /* Even if the number of character rows and columns has
2927 not changed, the font size may have changed, so we need
2928 to check the pixel dimensions as well. */
2929 if (columns
!= f
->width
2930 || rows
!= f
->height
2931 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
2932 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
2934 change_frame_size (f
, rows
, columns
, 0, 1);
2935 SET_FRAME_GARBAGED (f
);
2938 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
2939 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
2940 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
2941 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
2948 /* If we decide we want to generate an event to be seen
2949 by the rest of Emacs, we put it here. */
2950 struct input_event emacs_event
;
2951 emacs_event
.kind
= no_event
;
2953 f
= x_window_to_frame (event
.xbutton
.window
);
2956 if (!x_focus_frame
|| (f
== x_focus_frame
))
2957 construct_mouse_click (&emacs_event
,
2958 &event
, f
, Qnil
, 0);
2962 struct scrollbar
*bar
=
2963 x_window_to_scrollbar (event
.xbutton
.window
);
2966 x_scrollbar_handle_click (bar
, &event
, &emacs_event
);
2969 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
2971 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
2979 #else /* ! defined (HAVE_X11) */
2981 case ButtonReleased
:
2982 f
= x_window_to_frame (event
.window
);
2985 if (event
.window
== f
->display
.x
->icon_desc
)
2987 x_make_frame_visible (f
);
2989 if (warp_mouse_on_deiconify
)
2990 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
2993 if (event
.window
== FRAME_X_WINDOW (f
))
2999 enqueue_event (&event
, &x_mouse_queue
);
3002 bufp
->kind
= ascii_keystroke
;
3003 bufp
->code
= (char) 'X' & 037; /* C-x */
3004 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3005 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3008 bufp
->kind
= ascii_keystroke
;
3009 bufp
->code
= (char) 0; /* C-@ */
3010 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3011 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3018 #endif /* ! defined (HAVE_X11) */
3022 case CirculateNotify
:
3024 case CirculateRequest
:
3027 #endif /* ! defined (HAVE_X11) */
3030 /* Someone has changed the keyboard mapping - update the
3032 switch (event
.xmapping
.request
)
3034 case MappingModifier
:
3035 x_find_modifier_meanings ();
3036 /* This is meant to fall through. */
3037 case MappingKeyboard
:
3038 XRefreshKeyboardMapping (&event
.xmapping
);
3049 if (expected
&& ! event_found
)
3051 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3052 there is an EOF condition; in other words, that X has died.
3053 Act as if there had been a hangup. */
3055 int fd
= ConnectionNumber (x_current_display
);
3058 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3060 && !XStuffPending ())
3061 kill (getpid (), SIGHUP
);
3063 #endif /* ! defined (HAVE_SELECT) */
3067 if (updating_frame
== 0)
3068 x_do_pending_expose ();
3076 /* Read and process only Expose events
3077 until we get an ExposeCopy event; then return.
3078 This is used in insert/delete line.
3079 We assume input is already blocked. */
3085 XKeyPressedEvent event
;
3089 /* while there are more events*/
3090 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3094 if (event
.subwindow
!= 0)
3095 break; /* duplicate event */
3096 f
= x_window_to_frame (event
.window
);
3097 if (event
.window
== f
->display
.x
->icon_desc
)
3102 if (event
.window
== FRAME_X_WINDOW (f
))
3104 expose_all_windows
= 1;
3105 f
->display
.x
->needs_exposure
= 1;
3111 if (event
.subwindow
!= 0)
3112 break; /* duplicate event */
3113 f
= x_window_to_frame (event
.window
);
3114 if (event
.window
== f
->display
.x
->icon_desc
)
3119 /* If window already needs full redraw, ignore this rectangle. */
3120 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3122 /* Put the event on the queue of rectangles to redraw. */
3123 if (enqueue_event (&event
, &x_expose_queue
))
3124 /* If it is full, we can't record the rectangle,
3125 so redraw this entire window. */
3127 /* Say must check all windows' needs_exposure flags. */
3128 expose_all_windows
= 1;
3129 f
->display
.x
->needs_exposure
= 1;
3138 #endif /* HAVE_X11 */
3141 /* Drawing the cursor. */
3144 /* Draw a hollow box cursor. Don't change the inside of the box. */
3150 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3151 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3152 int width
= FONT_WIDTH (f
->display
.x
->font
);
3153 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3156 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3157 f
->display
.x
->cursor_gc
,
3158 left
, top
, width
- 1, height
- 1);
3159 #else /* ! defined (HAVE_X11) */
3160 XPixSet (FRAME_X_WINDOW (f
),
3161 left
, top
, width
, 1,
3162 f
->display
.x
->cursor_pixel
);
3164 XPixSet (FRAME_X_WINDOW (f
),
3165 left
, top
, 1, height
,
3166 f
->display
.x
->cursor_pixel
);
3168 XPixSet (FRAME_X_WINDOW (f
),
3169 left
+width
-1, top
, 1, height
,
3170 f
->display
.x
->cursor_pixel
);
3172 XPixSet (FRAME_X_WINDOW (f
),
3173 left
, top
+height
-1, width
, 1,
3174 f
->display
.x
->cursor_pixel
);
3175 #endif /* ! defined (HAVE_X11) */
3178 /* Clear the cursor of frame F to background color,
3179 and mark the cursor as not shown.
3180 This is used when the text where the cursor is
3181 is about to be rewritten. */
3189 if (! FRAME_VISIBLE_P (f
)
3190 || f
->phys_cursor_x
< 0)
3194 x_display_cursor (f
, 0);
3195 #else /* ! defined (HAVE_X11) */
3196 XPixSet (FRAME_X_WINDOW (f
),
3197 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3198 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3199 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3200 f
->display
.x
->background_pixel
);
3201 #endif /* ! defined (HAVE_X11) */
3202 f
->phys_cursor_x
= -1;
3205 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3206 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3210 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3217 CHAR_TO_PIXEL_COL (f
, column
),
3218 CHAR_TO_PIXEL_ROW (f
, row
),
3219 &glyph
, 1, highlight
, f
->display
.x
->font
);
3223 x_display_bar_cursor (f
, on
)
3227 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3229 if (! FRAME_VISIBLE_P (f
))
3232 if (! on
&& f
->phys_cursor_x
< 0)
3235 /* If we're not updating, then we want to use the current frame's
3236 cursor position, not our local idea of where the cursor ought to be. */
3237 if (f
!= updating_frame
)
3239 curs_x
= FRAME_CURSOR_X (f
);
3240 curs_y
= FRAME_CURSOR_Y (f
);
3243 /* If there is anything wrong with the current cursor state, remove it. */
3244 if (f
->phys_cursor_x
>= 0
3246 || f
->phys_cursor_x
!= curs_x
3247 || f
->phys_cursor_y
!= curs_y
3248 || f
->display
.x
->current_cursor
!= bar_cursor
))
3250 /* Erase the cursor by redrawing the character underneath it. */
3251 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3252 f
->phys_cursor_glyph
,
3253 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3254 f
->phys_cursor_x
= -1;
3257 /* If we now need a cursor in the new place or in the new form, do it so. */
3259 && (f
->phys_cursor_x
< 0
3260 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3262 f
->phys_cursor_glyph
3263 = ((current_glyphs
->enable
[curs_y
]
3264 && curs_x
< current_glyphs
->used
[curs_y
])
3265 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3267 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3268 f
->display
.x
->cursor_gc
,
3269 CHAR_TO_PIXEL_COL (f
, curs_x
),
3270 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3271 1, FONT_HEIGHT (f
->display
.x
->font
));
3273 f
->phys_cursor_x
= curs_x
;
3274 f
->phys_cursor_y
= curs_y
;
3276 f
->display
.x
->current_cursor
= bar_cursor
;
3279 if (updating_frame
!= f
)
3284 /* Turn the displayed cursor of frame F on or off according to ON.
3285 If ON is nonzero, where to put the cursor is specified
3286 by F->cursor_x and F->cursor_y. */
3289 x_display_box_cursor (f
, on
)
3293 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3295 if (! FRAME_VISIBLE_P (f
))
3298 /* If cursor is off and we want it off, return quickly. */
3299 if (!on
&& f
->phys_cursor_x
< 0)
3302 /* If we're not updating, then we want to use the current frame's
3303 cursor position, not our local idea of where the cursor ought to be. */
3304 if (f
!= updating_frame
)
3306 curs_x
= FRAME_CURSOR_X (f
);
3307 curs_y
= FRAME_CURSOR_Y (f
);
3310 /* If cursor is currently being shown and we don't want it to be
3311 or it is in the wrong place,
3312 or we want a hollow box and it's not so, (pout!)
3314 if (f
->phys_cursor_x
>= 0
3316 || f
->phys_cursor_x
!= curs_x
3317 || f
->phys_cursor_y
!= curs_y
3318 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3319 && (f
!= x_highlight_frame
))))
3321 /* Erase the cursor by redrawing the character underneath it. */
3322 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3323 f
->phys_cursor_glyph
,
3324 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3325 f
->phys_cursor_x
= -1;
3328 /* If we want to show a cursor,
3329 or we want a box cursor and it's not so,
3330 write it in the right place. */
3332 && (f
->phys_cursor_x
< 0
3333 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3334 && f
== x_highlight_frame
)))
3336 f
->phys_cursor_glyph
3337 = ((current_glyphs
->enable
[curs_y
]
3338 && curs_x
< current_glyphs
->used
[curs_y
])
3339 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3341 if (f
!= x_highlight_frame
)
3344 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3348 x_draw_single_glyph (f
, curs_y
, curs_x
,
3349 f
->phys_cursor_glyph
, 2);
3350 f
->display
.x
->current_cursor
= filled_box_cursor
;
3353 f
->phys_cursor_x
= curs_x
;
3354 f
->phys_cursor_y
= curs_y
;
3357 if (updating_frame
!= f
)
3361 x_display_cursor (f
, on
)
3365 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3366 x_display_box_cursor (f
, on
);
3367 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3368 x_display_bar_cursor (f
, on
);
3370 /* Those are the only two we have implemented! */
3376 /* Refresh bitmap kitchen sink icon for frame F
3377 when we get an expose event for it. */
3383 /* Normally, the window manager handles this function. */
3384 #else /* ! defined (HAVE_X11) */
3387 if (f
->display
.x
->icon_bitmap_flag
)
3388 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3389 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3390 icon_bitmap
, GXcopy
, AllPlanes
);
3393 extern struct frame
*selected_frame
;
3394 struct Lisp_String
*str
;
3395 unsigned char *string
;
3398 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3400 if (f
->display
.x
->icon_label
!= string
)
3402 f
->display
.x
->icon_label
= string
;
3403 XChangeWindow (f
->display
.x
->icon_desc
,
3404 XQueryWidth (string
, icon_font_info
->id
) + 10,
3405 icon_font_info
->height
+ 10);
3408 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3409 str
->size
, icon_font_info
->id
,
3410 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3413 #endif /* ! defined (HAVE_X11) */
3416 /* Make the x-window of frame F use the gnu icon bitmap. */
3425 if (FRAME_X_WINDOW (f
) == 0)
3430 XFreePixmap (x_current_display
, icon_bitmap
);
3433 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3434 gnu_bits
, gnu_width
, gnu_height
);
3435 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3436 f
->display
.x
->icon_bitmap_flag
= 1;
3437 #else /* ! defined (HAVE_X11) */
3438 if (f
->display
.x
->icon_desc
)
3440 XClearIconWindow (FRAME_X_WINDOW (f
));
3441 XDestroyWindow (f
->display
.x
->icon_desc
);
3444 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3445 0, 0, sink_width
, sink_height
,
3446 2, WhitePixmap
, (Pixmap
) NULL
);
3448 if (icon_window
== 0)
3451 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3452 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3454 f
->display
.x
->icon_desc
= icon_window
;
3455 f
->display
.x
->icon_bitmap_flag
= 1;
3457 if (icon_bitmap
== 0)
3459 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3460 #endif /* ! defined (HAVE_X11) */
3466 /* Make the x-window of frame F use a rectangle with text. */
3469 x_text_icon (f
, icon_name
)
3477 char *X_DefaultValue
;
3481 #define WhitePixel 1
3482 #endif /* WhitePixel */
3485 #define BlackPixel 0
3486 #endif /* BlackPixel */
3487 #endif /* HAVE_X11 */
3489 if (FRAME_X_WINDOW (f
) == 0)
3494 f
->display
.x
->icon_label
= icon_name
;
3496 if (! f
->display
.x
->icon_label
)
3497 f
->display
.x
->icon_label
= " *emacs* ";
3499 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3500 (char *) f
->display
.x
->icon_label
);
3502 f
->display
.x
->icon_bitmap_flag
= 0;
3503 x_wm_set_icon_pixmap (f
, 0);
3504 #else /* ! defined (HAVE_X11) */
3505 if (icon_font_info
== 0)
3507 = XGetFont (XGetDefault (XDISPLAY
3508 (char *) XSTRING (invocation_name
)->data
,
3511 if (f
->display
.x
->icon_desc
)
3513 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3514 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3518 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3520 if (! f
->display
.x
->icon_label
)
3521 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3523 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3524 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3525 f
->display
.x
->left_pos
,
3526 f
->display
.x
->top_pos
,
3527 width
+ 10, icon_font_info
->height
+ 10,
3528 2, BlackPixmap
, WhitePixmap
);
3530 if (icon_window
== 0)
3533 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3534 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3536 f
->display
.x
->icon_desc
= icon_window
;
3537 f
->display
.x
->icon_bitmap_flag
= 0;
3538 f
->display
.x
->icon_label
= 0;
3539 #endif /* ! defined (HAVE_X11) */
3544 /* Handling X errors. */
3546 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3547 X server's connection, or an error reported via the X protocol. */
3550 x_connection_closed ()
3555 shut_down_emacs (0);
3560 /* An X error handler which prints an error message and then kills Emacs.
3561 This is what's normally installed as Xlib's handler for protocol and
3564 x_error_quitter (display
, error
)
3570 /* Note that there is no real way portable across R3/R4 to get the
3571 original error handler. */
3573 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3574 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3575 buf
, error
->request_code
);
3577 /* While we're testing Emacs 19, we'll just dump core whenever we
3578 get an X error, so we can figure out why it happened. */
3581 x_connection_closed ();
3584 /* A buffer for storing X error messages. */
3585 static char (*x_caught_error_message
)[200];
3587 /* An X error handler which stores the error message in
3588 x_caught_error_message. This is what's installed when
3589 x_catch_errors is in effect. */
3591 x_error_catcher (display
, error
)
3595 XGetErrorText (display
, error
->error_code
,
3596 *x_caught_error_message
, sizeof (*x_caught_error_message
));
3600 /* Begin trapping X errors.
3602 After calling this function, X protocol errors no longer cause
3603 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3605 Calling x_check_errors signals an Emacs error if an X error has
3606 occurred since the last call to x_catch_errors or x_check_errors.
3608 Calling x_uncatch_errors resumes the normal error handling. */
3610 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3615 /* Make sure any errors from previous requests have been dealt with. */
3616 XSync (x_current_display
, False
);
3618 /* Set up the error buffer. */
3619 x_caught_error_message
=
3620 (char (*)[]) xmalloc (sizeof (*x_caught_error_message
));
3621 (*x_caught_error_message
)[0] = '\0';
3623 /* Install our little error handler. */
3624 XHandleError (x_error_catcher
);
3627 /* If any X protocol errors have arrived since the last call to
3628 x_catch_errors or x_check_errors, signal an Emacs error using
3629 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3631 x_check_errors (format
)
3634 /* Make sure to catch any errors incurred so far. */
3635 XSync (x_current_display
, False
);
3637 if ((*x_caught_error_message
)[0])
3641 sprintf (buf
, format
, *x_caught_error_message
);
3642 free (x_caught_error_message
);
3644 x_uncatch_errors ();
3652 free (x_caught_error_message
);
3653 XHandleError (x_error_quitter
);
3657 static unsigned int x_wire_count
;
3660 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3665 /* Changing the font of the frame. */
3667 /* Set the font of the x-window specified by frame F
3668 to the font named NEWNAME. This is safe to use
3669 even before F has an actual x-window. */
3673 /* A table of all the fonts we have already loaded. */
3674 static XFontStruct
**x_font_table
;
3676 /* The current capacity of x_font_table. */
3677 static int x_font_table_size
;
3679 /* The number of fonts actually stored in x_font_table.
3680 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3681 0 <= n_fonts <= x_font_table_size. */
3684 x_new_font (f
, fontname
)
3686 register char *fontname
;
3690 int n_matching_fonts
;
3691 XFontStruct
*font_info
;
3694 /* Get a list of all the fonts that match this name. Once we
3695 have a list of matching fonts, we compare them against the fonts
3696 we already have by comparing font ids. */
3697 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3698 1024, &n_matching_fonts
,
3700 /* If the server couldn't find any fonts whose named matched fontname,
3701 return an error code. */
3702 if (n_matching_fonts
== 0)
3705 /* See if we've already loaded a matching font. */
3710 for (i
= 0; i
< n_fonts
; i
++)
3711 for (j
= 0; j
< n_matching_fonts
; j
++)
3712 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3720 /* If we have, just return it from the table. */
3722 f
->display
.x
->font
= x_font_table
[already_loaded
];
3724 /* Otherwise, load the font and add it to the table. */
3729 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
3733 /* Do we need to create the table? */
3734 if (x_font_table_size
== 0)
3736 x_font_table_size
= 16;
3738 = (XFontStruct
**) xmalloc (x_font_table_size
3739 * sizeof (x_font_table
[0]));
3741 /* Do we need to grow the table? */
3742 else if (n_fonts
>= x_font_table_size
)
3744 x_font_table_size
*= 2;
3746 = (XFontStruct
**) xrealloc (x_font_table
,
3748 * sizeof (x_font_table
[0])));
3751 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
3754 /* Free the information from XListFontsWithInfo. The data
3755 we actually retain comes from XLoadQueryFont. */
3756 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
3758 /* Now make the frame display the given font. */
3759 if (FRAME_X_WINDOW (f
) != 0)
3761 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
3762 f
->display
.x
->font
->fid
);
3763 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
3764 f
->display
.x
->font
->fid
);
3765 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
3766 f
->display
.x
->font
->fid
);
3768 x_set_window_size (f
, f
->width
, f
->height
);
3773 #else /* ! defined (HAVE_X11) */
3774 x_new_font (f
, newname
)
3776 register char *newname
;
3781 temp
= XGetFont (newname
);
3782 if (temp
== (FONT_TYPE
*) 0)
3785 if (f
->display
.x
->font
)
3786 XLoseFont (f
->display
.x
->font
);
3788 f
->display
.x
->font
= temp
;
3790 if (FRAME_X_WINDOW (f
) != 0)
3791 x_set_window_size (f
, f
->width
, f
->height
);
3795 #endif /* ! defined (HAVE_X11) */
3797 /* X Window sizes and positions. */
3799 x_calc_absolute_position (f
)
3803 if (f
->display
.x
->left_pos
< 0)
3804 f
->display
.x
->left_pos
3805 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
3807 if (f
->display
.x
->top_pos
< 0)
3808 f
->display
.x
->top_pos
3809 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
3810 #else /* ! defined (HAVE_X11) */
3811 WINDOWINFO_TYPE parentinfo
;
3813 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
3815 if (f
->display
.x
->left_pos
< 0)
3816 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
3817 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
3819 if (f
->display
.x
->top_pos
< 0)
3820 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
3821 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
3822 #endif /* ! defined (HAVE_X11) */
3825 x_set_offset (f
, xoff
, yoff
)
3827 register int xoff
, yoff
;
3829 f
->display
.x
->top_pos
= yoff
;
3830 f
->display
.x
->left_pos
= xoff
;
3831 x_calc_absolute_position (f
);
3834 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
3835 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
3837 x_wm_set_size_hint (f
, 0);
3838 #endif /* ! defined (HAVE_X11) */
3842 /* Call this to change the size of frame F's x-window. */
3844 x_set_window_size (f
, cols
, rows
)
3848 int pixelwidth
, pixelheight
;
3853 check_frame_size (f
, &rows
, &cols
);
3854 f
->display
.x
->vertical_scrollbar_extra
=
3855 (FRAME_HAS_VERTICAL_SCROLLBARS (f
)
3856 ? VERTICAL_SCROLLBAR_PIXEL_WIDTH (f
)
3858 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3859 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3862 x_wm_set_size_hint (f
, 0);
3863 #endif /* ! defined (HAVE_X11) */
3864 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
3866 /* Now, strictly speaking, we can't be sure that this is accurate,
3867 but the window manager will get around to dealing with the size
3868 change request eventually, and we'll hear how it went when the
3869 ConfigureNotify event gets here.
3871 We could just not bother storing any of this information here,
3872 and let the ConfigureNotify event set everything up, but that
3873 might be kind of confusing to the lisp code, since size changes
3874 wouldn't be reported in the frame parameters until some random
3875 point in the future when the ConfigureNotify event arrives. */
3876 FRAME_WIDTH (f
) = cols
;
3877 FRAME_HEIGHT (f
) = rows
;
3878 PIXEL_WIDTH (f
) = pixelwidth
;
3879 PIXEL_HEIGHT (f
) = pixelheight
;
3881 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3882 receive in the ConfigureNotify event; if we get what we asked
3883 for, then the event won't cause the screen to become garbaged, so
3884 we have to make sure to do it here. */
3885 SET_FRAME_GARBAGED (f
);
3892 x_set_resize_hint (f
)
3895 XSetResizeHint (FRAME_X_WINDOW (f
),
3896 2 * f
->display
.x
->internal_border_width
,
3897 2 * f
->display
.x
->internal_border_width
,
3898 FONT_WIDTH (f
->display
.x
->font
),
3899 FONT_HEIGHT (f
->display
.x
->font
));
3901 #endif /* HAVE_X11 */
3903 /* Mouse warping, focus shifting, raising and lowering. */
3905 x_set_mouse_position (f
, x
, y
)
3913 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
3914 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
3916 if (pix_x
< 0) pix_x
= 0;
3917 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3919 if (pix_y
< 0) pix_y
= 0;
3920 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3924 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
3929 x_focus_on_frame (f
)
3934 /* I don't think that the ICCCM allows programs to do things like this
3935 without the interaction of the window manager. Whatever you end up
3936 doing with this code, do it to x_unfocus_frame too. */
3937 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
3938 RevertToPointerRoot
, CurrentTime
);
3946 /* Look at the remarks in x_focus_on_frame. */
3947 if (x_focus_frame
== f
)
3948 XSetInputFocus (x_current_display
, PointerRoot
,
3949 RevertToPointerRoot
, CurrentTime
);
3953 #endif /* ! defined (HAVE_X11) */
3955 /* Raise frame F. */
3960 if (f
->async_visible
)
3963 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3969 /* Lower frame F. */
3974 if (f
->async_visible
)
3977 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3984 XTframe_raise_lower (f
, raise
)
3995 /* Change from withdrawn state to mapped state. */
3997 x_make_frame_visible (f
)
4004 if (! FRAME_VISIBLE_P (f
))
4007 if (! EQ (Vx_no_window_manager
, Qt
))
4008 x_wm_set_window_state (f
, NormalState
);
4010 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4011 if (FRAME_HAS_VERTICAL_SCROLLBARS (f
))
4012 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4013 #else /* ! defined (HAVE_X11) */
4014 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4015 if (f
->display
.x
->icon_desc
!= 0)
4016 XUnmapWindow (f
->display
.x
->icon_desc
);
4018 /* Handled by the MapNotify event for X11 */
4019 f
->async_visible
= 1;
4020 f
->async_iconified
= 0;
4022 /* NOTE: this may cause problems for the first frame. */
4024 #endif /* ! defined (HAVE_X11) */
4032 /* Change from mapped state to withdrawn state. */
4034 x_make_frame_invisible (f
)
4039 if (! f
->async_visible
)
4046 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4047 DefaultScreen (x_current_display
)))
4049 UNBLOCK_INPUT_RESIGNAL
;
4050 error ("can't notify window manager of window withdrawl");
4053 #else /* ! defined (HAVE_X11R4) */
4056 /* Tell the window manager what we're going to do. */
4057 if (! EQ (Vx_no_window_manager
, Qt
))
4061 unmap
.xunmap
.type
= UnmapNotify
;
4062 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4063 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4064 unmap
.xunmap
.from_configure
= False
;
4065 if (! XSendEvent (x_current_display
,
4066 DefaultRootWindow (x_current_display
),
4068 SubstructureRedirectMask
|SubstructureNotifyMask
,
4071 UNBLOCK_INPUT_RESIGNAL
;
4072 error ("can't notify window manager of withdrawal");
4076 /* Unmap the window ourselves. Cheeky! */
4077 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4079 #else /* ! defined (HAVE_X11) */
4081 XUnmapWindow (FRAME_X_WINDOW (f
));
4082 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4083 if (f
->display
.x
->icon_desc
!= 0)
4084 XUnmapWindow (f
->display
.x
->icon_desc
);
4086 #endif /* ! defined (HAVE_X11) */
4087 #endif /* ! defined (HAVE_X11R4) */
4093 /* Window manager communication. Created in Fx_open_connection. */
4094 extern Atom Xatom_wm_change_state
;
4096 /* Change window state from mapped to iconified. */
4103 if (f
->async_iconified
)
4109 /* Since we don't know which revision of X we're running, we'll use both
4110 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4112 /* X11R4: send a ClientMessage to the window manager using the
4113 WM_CHANGE_STATE type. */
4117 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4118 message
.xclient
.type
= ClientMessage
;
4119 message
.xclient
.message_type
= Xatom_wm_change_state
;
4120 message
.xclient
.format
= 32;
4121 message
.xclient
.data
.l
[0] = IconicState
;
4123 if (! XSendEvent (x_current_display
,
4124 DefaultRootWindow (x_current_display
),
4126 SubstructureRedirectMask
| SubstructureNotifyMask
,
4129 UNBLOCK_INPUT_RESIGNAL
;
4130 error ("Can't notify window manager of iconification.");
4134 /* X11R3: set the initial_state field of the window manager hints to
4136 x_wm_set_window_state (f
, IconicState
);
4138 f
->async_iconified
= 1;
4139 #else /* ! defined (HAVE_X11) */
4140 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4142 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4143 if (f
->display
.x
->icon_desc
!= 0)
4145 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4148 #endif /* ! defined (HAVE_X11) */
4154 /* Destroy the X window of frame F. */
4156 x_destroy_window (f
)
4161 if (f
->display
.x
->icon_desc
!= 0)
4162 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4163 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4166 free (f
->display
.x
);
4168 if (f
== x_focus_frame
)
4170 if (f
== x_highlight_frame
)
4171 x_highlight_frame
= 0;
4176 /* Manage event queues for X10. */
4180 /* Manage event queues.
4182 This code is only used by the X10 support.
4184 We cannot leave events in the X queue and get them when we are ready
4185 because X does not provide a subroutine to get only a certain kind
4186 of event but not block if there are no queued events of that kind.
4188 Therefore, we must examine events as they come in and copy events
4189 of certain kinds into our private queues.
4191 All ExposeRegion events are put in x_expose_queue.
4192 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4195 /* Write the event *P_XREP into the event queue *QUEUE.
4196 If the queue is full, do nothing, but return nonzero. */
4199 enqueue_event (p_xrep
, queue
)
4200 register XEvent
*p_xrep
;
4201 register struct event_queue
*queue
;
4203 int newindex
= queue
->windex
+ 1;
4204 if (newindex
== EVENT_BUFFER_SIZE
)
4206 if (newindex
== queue
->rindex
)
4208 queue
->xrep
[queue
->windex
] = *p_xrep
;
4209 queue
->windex
= newindex
;
4213 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4214 If *QUEUE is empty, do nothing and return 0. */
4217 dequeue_event (p_xrep
, queue
)
4218 register XEvent
*p_xrep
;
4219 register struct event_queue
*queue
;
4221 if (queue
->windex
== queue
->rindex
)
4223 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4224 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4229 /* Return the number of events buffered in *QUEUE. */
4232 queue_event_count (queue
)
4233 register struct event_queue
*queue
;
4235 int tem
= queue
->windex
- queue
->rindex
;
4238 return EVENT_BUFFER_SIZE
+ tem
;
4241 /* Return nonzero if mouse input is pending. */
4244 mouse_event_pending_p ()
4246 return queue_event_count (&x_mouse_queue
);
4248 #endif /* HAVE_X11 */
4250 /* Setting window manager hints. */
4254 x_wm_set_size_hint (f
, prompting
)
4258 XSizeHints size_hints
;
4259 Window window
= FRAME_X_WINDOW (f
);
4261 size_hints
.flags
= PResizeInc
| PMinSize
| PMaxSize
;
4263 flexlines
= f
->height
;
4265 size_hints
.x
= f
->display
.x
->left_pos
;
4266 size_hints
.y
= f
->display
.x
->top_pos
;
4267 size_hints
.height
= PIXEL_HEIGHT (f
);
4268 size_hints
.width
= PIXEL_WIDTH (f
);
4269 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4270 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4271 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4272 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4275 int base_width
, base_height
;
4277 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4278 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4281 int min_rows
= 0, min_cols
= 0;
4282 check_frame_size (f
, &min_rows
, &min_cols
);
4284 /* The window manager uses the base width hints to calculate the
4285 current number of rows and columns in the frame while
4286 resizing; min_width and min_height aren't useful for this
4287 purpose, since they might not give the dimensions for a
4288 zero-row, zero-column frame.
4290 We use the base_width and base_height members if we have
4291 them; otherwise, we set the min_width and min_height members
4292 to the size for a zero x zero frame. */
4295 size_hints
.flags
|= PBaseSize
;
4296 size_hints
.base_width
= base_width
;
4297 size_hints
.base_height
= base_height
;
4298 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4299 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4301 size_hints
.min_width
= base_width
;
4302 size_hints
.min_height
= base_height
;
4309 size_hints
.flags
|= prompting
;
4312 XSizeHints hints
; /* Sometimes I hate X Windows... */
4314 XGetNormalHints (x_current_display
, window
, &hints
);
4315 if (hints
.flags
& PSize
)
4316 size_hints
.flags
|= PSize
;
4317 if (hints
.flags
& PPosition
)
4318 size_hints
.flags
|= PPosition
;
4319 if (hints
.flags
& USPosition
)
4320 size_hints
.flags
|= USPosition
;
4321 if (hints
.flags
& USSize
)
4322 size_hints
.flags
|= USSize
;
4326 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4328 XSetNormalHints (x_current_display
, window
, &size_hints
);
4332 /* Used for IconicState or NormalState */
4333 x_wm_set_window_state (f
, state
)
4337 Window window
= FRAME_X_WINDOW (f
);
4339 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4340 f
->display
.x
->wm_hints
.initial_state
= state
;
4342 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4345 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4349 Window window
= FRAME_X_WINDOW (f
);
4353 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4354 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4357 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4359 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4362 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4366 Window window
= FRAME_X_WINDOW (f
);
4368 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4369 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4370 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4372 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4376 /* Initialization. */
4379 x_term_init (display_name
)
4385 extern int old_fcntl_owner
;
4386 #endif /* ! defined (F_SETOWN) */
4388 x_focus_frame
= x_highlight_frame
= 0;
4390 x_current_display
= XOpenDisplay (display_name
);
4391 if (x_current_display
== 0)
4392 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4397 int hostname_size
= 256;
4399 hostname
= (char *) xmalloc (hostname_size
);
4402 XSetAfterFunction (x_current_display
, x_trace_wire
);
4405 invocation_name
= Ffile_name_nondirectory (Fcar (Vcommand_line_args
));
4407 /* Try to get the host name; if the buffer is too short, try
4408 again. Apparently, the only indication gethostname gives of
4409 whether the buffer was large enough is the presence or absence
4410 of a '\0' in the string. Eech. */
4413 gethostname (hostname
, hostname_size
- 1);
4414 hostname
[hostname_size
- 1] = '\0';
4416 /* Was the buffer large enough for gethostname to store the '\0'? */
4417 if (strlen (hostname
) < hostname_size
- 1)
4420 hostname_size
<<= 1;
4421 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4423 x_id_name
= (char *) xmalloc (XSTRING (invocation_name
)->size
4426 sprintf (x_id_name
, "%s@%s", XSTRING (invocation_name
)->data
, hostname
);
4429 /* Figure out which modifier bits mean what. */
4430 x_find_modifier_meanings ();
4432 /* Get the scrollbar cursor. */
4433 x_vertical_scrollbar_cursor
=
4434 XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4436 /* Watch for PropertyNotify events on the root window; we use them
4437 to figure out when to invalidate our cache of the cut buffers. */
4438 x_watch_cut_buffer_cache ();
4440 dup2 (ConnectionNumber (x_current_display
), 0);
4442 #ifndef SYSV_STREAMS
4443 /* Streams somehow keeps track of which descriptor number
4444 is being used to talk to X. So it is not safe to substitute
4445 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4446 close (ConnectionNumber (x_current_display
));
4447 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4448 * check the def of the macro;
4449 * it is a genuine lvalue */
4450 #endif /* SYSV_STREAMS */
4452 #endif /* ! defined (HAVE_X11) */
4455 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4456 #ifdef F_SETOWN_SOCK_NEG
4457 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4458 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4459 fcntl (0, F_SETOWN
, getpid ());
4460 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4461 #endif /* ! defined (F_SETOWN) */
4465 #endif /* ! defined (SIGIO) */
4467 /* Must use interrupt input because we cannot otherwise
4468 arrange for C-g to be noticed immediately.
4469 We cannot connect it to SIGINT. */
4470 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4472 expose_all_windows
= 0;
4474 clear_frame_hook
= XTclear_frame
;
4475 clear_end_of_line_hook
= XTclear_end_of_line
;
4476 ins_del_lines_hook
= XTins_del_lines
;
4477 change_line_highlight_hook
= XTchange_line_highlight
;
4478 insert_glyphs_hook
= XTinsert_glyphs
;
4479 write_glyphs_hook
= XTwrite_glyphs
;
4480 delete_glyphs_hook
= XTdelete_glyphs
;
4481 ring_bell_hook
= XTring_bell
;
4482 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4483 set_terminal_modes_hook
= XTset_terminal_modes
;
4484 update_begin_hook
= XTupdate_begin
;
4485 update_end_hook
= XTupdate_end
;
4486 set_terminal_window_hook
= XTset_terminal_window
;
4487 read_socket_hook
= XTread_socket
;
4488 cursor_to_hook
= XTcursor_to
;
4489 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4490 mouse_position_hook
= XTmouse_position
;
4491 frame_rehighlight_hook
= XTframe_rehighlight
;
4492 frame_raise_lower_hook
= XTframe_raise_lower
;
4493 set_vertical_scrollbar_hook
= XTset_vertical_scrollbar
;
4494 condemn_scrollbars_hook
= XTcondemn_scrollbars
;
4495 redeem_scrollbar_hook
= XTredeem_scrollbar
;
4496 judge_scrollbars_hook
= XTjudge_scrollbars
;
4498 scroll_region_ok
= 1; /* we'll scroll partial frames */
4499 char_ins_del_ok
= 0; /* just as fast to write the line */
4500 line_ins_del_ok
= 1; /* we'll just blt 'em */
4501 fast_clear_end_of_line
= 1; /* X does this well */
4502 memory_below_frame
= 0; /* we don't remember what scrolls
4506 /* Note that there is no real way portable across R3/R4 to get the
4507 original error handler. */
4508 XHandleError (x_error_quitter
);
4509 XHandleIOError (x_error_quitter
);
4511 /* Disable Window Change signals; they are handled by X events. */
4513 signal (SIGWINCH
, SIG_DFL
);
4514 #endif /* ! defined (SIGWINCH) */
4516 signal (SIGPIPE
, x_connection_closed
);
4522 staticpro (&invocation_name
);
4523 invocation_name
= Qnil
;
4525 staticpro (&last_mouse_scrollbar
);
4527 #endif /* ! defined (HAVE_X11) */
4528 #endif /* ! defined (HAVE_X_WINDOWS) */