1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 #define NEW_SELECTIONS
35 #include "blockinput.h"
37 /* On 4.3 these lose if they come after xterm.h. */
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
44 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
55 #include <sys/ioctl.h>
57 #else /* ! defined (BSD) */
59 #include <sys/termio.h>
62 #endif /* ! defined (BSD) */
64 /* Allow m- file to inhibit use of FIONREAD. */
65 #ifdef BROKEN_FIONREAD
67 #endif /* ! defined (BROKEN_FIONREAD) */
69 /* We are unable to use interrupts if FIONREAD is not available,
70 so flush SIGIO so we won't try. */
74 #endif /* ! defined (SIGIO) */
84 #include <sys/param.h>
86 #include "dispextern.h"
87 #include "termhooks.h"
101 #define XMapWindow XMapRaised /* Raise them when mapping. */
102 #else /* ! defined (HAVE_X11) */
103 #include <X/Xkeyboard.h>
104 /*#include <X/Xproto.h> */
105 #endif /* ! defined (HAVE_X11) */
107 /* For sending Meta-characters. Do we need this? */
110 #define min(a,b) ((a)<(b) ? (a) : (b))
111 #define max(a,b) ((a)>(b) ? (a) : (b))
113 /* Nonzero means we must reprint all windows
114 because 1) we received an ExposeWindow event
115 or 2) we received too many ExposeRegion events to record.
117 This is never needed under X11. */
118 static int expose_all_windows
;
120 /* Nonzero means we must reprint all icon windows. */
122 static int expose_all_icons
;
125 /* ExposeRegion events, when received, are copied into this queue
126 for later processing. */
128 static struct event_queue x_expose_queue
;
130 /* ButtonPressed and ButtonReleased events, when received,
131 are copied into this queue for later processing. */
133 struct event_queue x_mouse_queue
;
134 #endif /* HAVE_X11 */
136 #if defined (SIGIO) && defined (FIONREAD)
137 int BLOCK_INPUT_mask
;
138 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
140 /* The id of a bitmap used for icon windows.
141 One such map is shared by all Emacs icon windows.
142 This is zero if we have not yet had a need to create the bitmap. */
144 static Bitmap icon_bitmap
;
146 /* Font used for text icons. */
148 static FONT_TYPE
*icon_font_info
;
150 /* Stuff for dealing with the main icon title. */
152 extern Lisp_Object Vcommand_line_args
;
153 char *hostname
, *x_id_name
;
155 /* This is the X connection that we are using. */
157 Display
*x_current_display
;
159 /* The cursor to use for vertical scroll bars on x_current_display. */
160 static Cursor x_vertical_scroll_bar_cursor
;
162 /* Frame being updated by update_frame. */
163 /* This is set by XTupdate_begin and looked at by all the
164 XT functions. It is zero while not inside an update.
165 In that case, the XT functions assume that `selected_frame'
166 is the frame to apply to. */
168 static struct frame
*updating_frame
;
170 /* The frame (if any) which has the X window that has keyboard focus.
171 Zero if none. This is examined by Ffocus_frame in frame.c. Note
172 that a mere EnterNotify event can set this; if you need to know the
173 last frame specified in a FocusIn or FocusOut event, use
174 x_focus_event_frame. */
175 struct frame
*x_focus_frame
;
177 /* The last frame mentioned in a FocusIn or FocusOut event. This is
178 separate from x_focus_frame, because whether or not LeaveNotify
179 events cause us to lose focus depends on whether or not we have
180 received a FocusIn event for it. */
181 struct frame
*x_focus_event_frame
;
183 /* The frame which currently has the visual highlight, and should get
184 keyboard input (other sorts of input have the frame encoded in the
185 event). It points to the X focus frame's selected window's
186 frame. It differs from x_focus_frame when we're using a global
188 static struct frame
*x_highlight_frame
;
190 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
191 mouse is moved to inside of frame when frame is de-iconified. */
193 static int warp_mouse_on_deiconify
;
195 /* During an update, maximum vpos for ins/del line operations to affect. */
197 static int flexlines
;
199 /* During an update, nonzero if chars output now should be highlighted. */
201 static int highlight
;
203 /* Nominal cursor position -- where to draw output.
204 During an update, these are different from the cursor-box position. */
210 /* `t' if a mouse button is depressed. */
212 extern Lisp_Object Vmouse_depressed
;
214 /* Tells if a window manager is present or not. */
216 extern Lisp_Object Vx_no_window_manager
;
218 /* Timestamp that we requested selection data was made. */
219 extern Time requestor_time
;
221 /* ID of the window requesting selection data. */
222 extern Window requestor_window
;
224 /* Nonzero enables some debugging for the X interface code. */
227 #else /* ! defined (HAVE_X11) */
229 /* Bit patterns for the mouse cursor. */
231 short MouseCursor
[] = {
232 0x0000, 0x0008, 0x0018, 0x0038,
233 0x0078, 0x00f8, 0x01f8, 0x03f8,
234 0x07f8, 0x00f8, 0x00d8, 0x0188,
235 0x0180, 0x0300, 0x0300, 0x0000};
237 short MouseMask
[] = {
238 0x000c, 0x001c, 0x003c, 0x007c,
239 0x00fc, 0x01fc, 0x03fc, 0x07fc,
240 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
241 0x03cc, 0x0780, 0x0780, 0x0300};
243 static short grey_bits
[] = {
244 0x0005, 0x000a, 0x0005, 0x000a};
246 static Pixmap GreyPixmap
= 0;
247 #endif /* ! defined (HAVE_X11) */
249 /* From time to time we get info on an Emacs window, here. */
251 static WINDOWINFO_TYPE windowinfo
;
255 /* See keyboard.c. */
256 extern int extra_keyboard_modifiers
;
258 extern Display
*XOpenDisplay ();
259 extern Window
XCreateWindow ();
261 extern Cursor
XCreateCursor ();
262 extern FONT_TYPE
*XOpenFont ();
264 static void flashback ();
267 static void dumpqueue ();
268 #endif /* HAVE_X11 */
271 static int XTcursor_to ();
272 static int XTclear_end_of_line ();
275 /* Starting and ending updates.
277 These hooks are called by update_frame at the beginning and end
278 of a frame update. We record in `updating_frame' the identity
279 of the frame being updated, so that the XT... functions do not
280 need to take a frame as argument. Most of the XT... functions
281 should never be called except during an update, the only exceptions
282 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
284 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
296 flexlines
= f
->height
;
302 #endif /* HAVE_X11 */
307 static void x_do_pending_expose ();
316 if (updating_frame
== 0
317 || updating_frame
!= f
)
323 x_do_pending_expose ();
324 #endif /* HAVE_X11 */
326 x_display_cursor (f
, 1);
333 /* External interface to control of standout mode.
334 Call this when about to modify line at position VPOS
335 and not change whether it is highlighted. */
337 XTreassert_line_highlight (new, vpos
)
343 /* Call this when about to modify line at position VPOS
344 and change whether it is highlighted. */
347 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
348 int new_highlight
, vpos
, first_unused_hpos
;
350 highlight
= new_highlight
;
351 XTcursor_to (vpos
, 0);
352 XTclear_end_of_line (updating_frame
->width
);
355 /* This is used when starting Emacs and when restarting after suspend.
356 When starting Emacs, no X window is mapped. And nothing must be done
357 to Emacs's own window if it is suspended (though that rarely happens). */
360 XTset_terminal_modes ()
364 /* This is called when exiting or suspending Emacs.
365 Exiting will make the X-windows go away, and suspending
366 requires no action. */
369 XTreset_terminal_modes ()
371 /* XTclear_frame (); */
374 /* Set the nominal cursor position of the frame.
375 This is where display update commands will take effect.
376 This does not affect the place where the cursor-box is displayed. */
379 XTcursor_to (row
, col
)
380 register int row
, col
;
388 if (updating_frame
== 0)
391 x_display_cursor (selected_frame
, 1);
397 /* Display a sequence of N glyphs found at GP.
398 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
399 HL is 1 if this text is highlighted, 2 if the cursor is on it.
401 FONT is the default font to use (for glyphs whose font-code is 0). */
404 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
407 register GLYPH
*gp
; /* Points to first GLYPH. */
408 register int n
; /* Number of glyphs to display. */
413 Window window
= FRAME_X_WINDOW (f
);
414 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
415 : (hl
? f
->display
.x
->reverse_gc
416 : f
->display
.x
->normal_gc
));
418 if (sizeof (GLYPH
) == sizeof (XChar2b
))
419 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
420 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
421 else if (sizeof (GLYPH
) == sizeof (unsigned char))
422 XDrawImageString (x_current_display
, window
, drawing_gc
,
423 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
425 /* What size of glyph ARE you using? And does X have a function to
432 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
435 register GLYPH
*gp
; /* Points to first GLYPH. */
436 register int n
; /* Number of glyphs to display. */
440 char buf
[f
->width
]; /* Holds characters to be displayed. */
441 register char *cp
; /* Steps through buf[]. */
442 register int tlen
= GLYPH_TABLE_LENGTH
;
443 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
444 Window window
= FRAME_X_WINDOW (f
);
445 int cursor_pixel
= f
->display
.x
->cursor_pixel
;
446 int fg_pixel
= f
->display
.x
->foreground_pixel
;
447 int bg_pixel
= f
->display
.x
->background_pixel
;
448 int intborder
= f
->display
.x
->internal_border_width
;
452 /* Get the face-code of the next GLYPH. */
456 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
457 g
= GLYPH_ALIAS (tbase
, g
);
461 /* Find the run of consecutive glyphs with the same face-code.
462 Extract their character codes into BUF. */
467 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
468 g
= GLYPH_ALIAS (tbase
, g
);
477 /* LEN gets the length of the run. */
480 /* Now output this run of chars, with the font and pixel values
481 determined by the face code CF. */
485 GC GC_cursor
= f
->display
.x
->cursor_gc
;
486 GC GC_reverse
= f
->display
.x
->reverse_gc
;
487 GC GC_normal
= f
->display
.x
->normal_gc
;
489 XDrawImageString (x_current_display
, window
,
492 : (hl
? GC_reverse
: GC_normal
)),
493 left
, top
+ FONT_BASE (font
), buf
, len
);
494 #else /* ! defined (HAVE_X11) */
495 XText (window
, left
, top
,
500 ? (cursor_pixel
== fg_pixel
? bg_pixel
: fg_pixel
)
501 : hl
? bg_pixel
: fg_pixel
),
502 (hl
== 2 ? cursor_pixel
503 : hl
? fg_pixel
: bg_pixel
));
504 #endif /* ! defined (HAVE_X11) */
509 if (FACE_IS_FONT (cf
))
510 XDrawImageString (x_current_display
, FRAME_X_WINDOW (f
),
512 left
, top
+ FONT_BASE (FACE_FONT (cf
)),
514 else if (FACE_IS_IMAGE (cf
))
515 XCopyPlane (x_current_display
, FACE_IMAGE (cf
),
517 f
->display
.x
->normal_gc
,
519 FACE_IMAGE_WIDTH (cf
),
520 FACE_IMAGE_HEIGHT (cf
), left
, top
);
523 #else /* ! defined (HAVE_X11) */
524 register struct face
*fp
= x_face_table
[cf
];
526 XText (window
, left
, top
,
531 ? (cursor_pixel
== fp
->fg
? fp
->bg
: fp
->fg
)
532 : hl
? fp
->bg
: fp
->fg
),
533 (hl
== 2 ? cursor_pixel
534 : hl
? fp
->fg
: fp
->bg
));
535 #endif /* ! defined (HAVE_X11) */
537 left
+= len
* FONT_WIDTH (font
);
542 /* Output some text at the nominal frame cursor position.
543 Advance the cursor over the text.
544 Output LEN glyphs at START.
546 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
547 controls the pixel values used for foreground and background. */
550 XTwrite_glyphs (start
, len
)
551 register GLYPH
*start
;
554 register int temp_length
;
564 /* If not within an update,
565 output at the frame's visible cursor. */
566 curs_x
= f
->cursor_x
;
567 curs_y
= f
->cursor_y
;
571 CHAR_TO_PIXEL_COL (f
, curs_x
),
572 CHAR_TO_PIXEL_ROW (f
, curs_y
),
573 start
, len
, highlight
, f
->display
.x
->font
);
575 /* If we drew on top of the cursor, note that it is turned off. */
576 if (curs_y
== f
->phys_cursor_y
577 && curs_x
<= f
->phys_cursor_x
578 && curs_x
+ len
> f
->phys_cursor_x
)
579 f
->phys_cursor_x
= -1;
581 if (updating_frame
== 0)
584 x_display_cursor (f
, 1);
593 /* Clear to the end of the line.
594 Erase the current text line from the nominal cursor position (inclusive)
595 to column FIRST_UNUSED (exclusive). The idea is that everything
596 from FIRST_UNUSED onward is already erased. */
599 XTclear_end_of_line (first_unused
)
600 register int first_unused
;
602 struct frame
*f
= updating_frame
;
608 if (curs_y
< 0 || curs_y
>= f
->height
)
610 if (first_unused
<= 0)
613 if (first_unused
>= f
->width
)
614 first_unused
= f
->width
;
618 /* Notice if the cursor will be cleared by this operation. */
619 if (curs_y
== f
->phys_cursor_y
620 && curs_x
<= f
->phys_cursor_x
621 && f
->phys_cursor_x
< first_unused
)
622 f
->phys_cursor_x
= -1;
625 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
626 CHAR_TO_PIXEL_COL (f
, curs_x
),
627 CHAR_TO_PIXEL_ROW (f
, curs_y
),
628 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
629 FONT_HEIGHT (f
->display
.x
->font
), False
);
631 #else /* ! defined (HAVE_X11) */
632 XPixSet (FRAME_X_WINDOW (f
),
633 CHAR_TO_PIXEL_COL (f
, curs_x
),
634 CHAR_TO_PIXEL_ROW (f
, curs_y
),
635 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
636 FONT_HEIGHT (f
->display
.x
->font
),
637 f
->display
.x
->background_pixel
);
638 #endif /* ! defined (HAVE_X11) */
647 struct frame
*f
= updating_frame
;
652 f
->phys_cursor_x
= -1; /* Cursor not visible. */
653 curs_x
= 0; /* Nominal cursor position is top left. */
658 XClear (FRAME_X_WINDOW (f
));
660 /* We have to clear the scroll bars, too. If we have changed
661 colors or something like that, then they should be notified. */
662 x_scroll_bar_clear (f
);
666 #endif /* HAVE_X11 */
672 /* Invert the middle quarter of the frame for .15 sec. */
674 /* We use the select system call to do the waiting, so we have to make sure
675 it's avaliable. If it isn't, we just won't do visual bells. */
676 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
678 /* Subtract the `struct timeval' values X and Y,
679 storing the result in RESULT.
680 Return 1 if the difference is negative, otherwise 0. */
683 timeval_subtract (result
, x
, y
)
684 struct timeval
*result
, x
, y
;
686 /* Perform the carry for the later subtraction by updating y.
687 This is safer because on some systems
688 the tv_sec member is unsigned. */
689 if (x
.tv_usec
< y
.tv_usec
)
691 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
692 y
.tv_usec
-= 1000000 * nsec
;
695 if (x
.tv_usec
- y
.tv_usec
> 1000000)
697 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
698 y
.tv_usec
+= 1000000 * nsec
;
702 /* Compute the time remaining to wait. tv_usec is certainly positive. */
703 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
704 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
706 /* Return indication of whether the result should be considered negative. */
707 return x
.tv_sec
< y
.tv_sec
;
718 /* Create a GC that will use the GXxor function to flip foreground pixels
719 into background pixels. */
723 values
.function
= GXxor
;
724 values
.foreground
= (f
->display
.x
->foreground_pixel
725 ^ f
->display
.x
->background_pixel
);
727 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
728 GCFunction
| GCForeground
, &values
);
732 int width
= PIXEL_WIDTH (f
);
733 int height
= PIXEL_HEIGHT (f
);
735 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
736 width
/4, height
/4, width
/2, height
/2);
737 XFlush (x_current_display
);
740 struct timeval wakeup
, now
;
742 gettimeofday (&wakeup
, (struct timezone
*) 0);
744 /* Compute time to wait until, propagating carry from usecs. */
745 wakeup
.tv_usec
+= 150000;
746 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
747 wakeup
.tv_usec
%= 1000000;
749 /* Keep waiting until past the time wakeup. */
752 struct timeval timeout
;
754 gettimeofday (&timeout
, (struct timezone
*)0);
756 /* In effect, timeout = wakeup - timeout.
757 Break if result would be negative. */
758 if (timeval_subtract (&timeout
, wakeup
, timeout
))
761 /* Try to wait that long--but we might wake up sooner. */
762 select (0, 0, 0, 0, &timeout
);
766 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
767 width
/4, height
/4, width
/2, height
/2);
768 XFreeGC (x_current_display
, gc
);
769 XFlush (x_current_display
);
779 /* Make audible bell. */
782 #define XRINGBELL XBell(x_current_display, 0)
783 #else /* ! defined (HAVE_X11) */
784 #define XRINGBELL XFeep(0);
785 #endif /* ! defined (HAVE_X11) */
789 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
791 XTflash (selected_frame
);
802 /* Insert and delete character.
803 These are not supposed to be used because we are supposed to turn
804 off the feature of using them. */
807 XTinsert_glyphs (start
, len
)
808 register char *start
;
821 /* Specify how many text lines, from the top of the window,
822 should be affected by insert-lines and delete-lines operations.
823 This, and those operations, are used only within an update
824 that is bounded by calls to XTupdate_begin and XTupdate_end. */
827 XTset_terminal_window (n
)
830 if (updating_frame
== 0)
833 if ((n
<= 0) || (n
> updating_frame
->height
))
834 flexlines
= updating_frame
->height
;
839 /* Perform an insert-lines operation.
840 Insert N lines at a vertical position curs_y. */
846 register int topregion
, bottomregion
;
847 register int length
, newtop
, mask
;
848 register struct frame
*f
= updating_frame
;
849 int intborder
= f
->display
.x
->internal_border_width
;
851 if (curs_y
>= flexlines
)
855 bottomregion
= flexlines
- (n
+ 1);
856 newtop
= topregion
+ n
;
857 length
= (bottomregion
- topregion
) + 1;
861 #endif /* HAVE_X11 */
863 if ((length
> 0) && (newtop
<= flexlines
))
866 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
867 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
868 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
869 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
870 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
871 CHAR_TO_PIXEL_ROW (f
, newtop
));
872 #else /* ! defined (HAVE_X11) */
873 XMoveArea (FRAME_X_WINDOW (f
),
874 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
875 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
876 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
877 length
* FONT_HEIGHT (f
->display
.x
->font
));
878 /* Now we must process any ExposeRegion events that occur
879 if the area being copied from is obscured.
880 We can't let it wait because further i/d operations
881 may want to copy this area to another area. */
883 #endif /* ! defined (HAVE_X11) */
886 newtop
= min (newtop
, (flexlines
- 1));
887 length
= newtop
- topregion
;
891 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
892 CHAR_TO_PIXEL_ROW (f
, topregion
),
893 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
894 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
895 #else /* ! defined (HAVE_X11) */
896 XPixSet (FRAME_X_WINDOW (f
),
898 CHAR_TO_PIXEL_ROW (f
, topregion
),
899 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
900 n
* FONT_HEIGHT (f
->display
.x
->font
),
901 f
->display
.x
->background_pixel
);
902 #endif /* ! defined (HAVE_X11) */
906 /* Perform a delete-lines operation, deleting N lines
907 at a vertical position curs_y. */
914 register struct frame
*f
= updating_frame
;
915 int intborder
= f
->display
.x
->internal_border_width
;
917 if (curs_y
>= flexlines
)
922 #endif /* HAVE_X11 */
924 if ((curs_y
+ n
) >= flexlines
)
926 if (flexlines
>= (curs_y
+ 1))
929 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
930 CHAR_TO_PIXEL_ROW (f
, curs_y
),
931 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
932 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
933 #else /* ! defined (HAVE_X11) */
934 XPixSet (FRAME_X_WINDOW (f
),
935 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
936 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
937 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
938 f
->display
.x
->background_pixel
);
939 #endif /* ! defined (HAVE_X11) */
945 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
946 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
948 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
949 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
950 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
951 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
952 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
954 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
955 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
956 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
957 #else /* ! defined (HAVE_X11) */
958 XMoveArea (FRAME_X_WINDOW (f
),
960 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
961 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
962 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
963 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
964 /* Now we must process any ExposeRegion events that occur
965 if the area being copied from is obscured.
966 We can't let it wait because further i/d operations
967 may want to copy this area to another area. */
969 XPixSet (FRAME_X_WINDOW (f
), intborder
,
970 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
971 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
972 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
973 #endif /* ! defined (HAVE_X11) */
977 /* Perform an insert-lines or delete-lines operation,
978 inserting N lines or deleting -N lines at vertical position VPOS. */
980 XTins_del_lines (vpos
, n
)
983 if (updating_frame
== 0)
986 /* Hide the cursor. */
987 x_display_cursor (updating_frame
, 0);
989 XTcursor_to (vpos
, 0);
1000 /* Support routines for exposure events. */
1001 static void clear_cursor ();
1003 /* Output into a rectangle of an X-window (for frame F)
1004 the characters in f->phys_lines that overlap that rectangle.
1005 TOP and LEFT are the position of the upper left corner of the rectangle.
1006 ROWS and COLS are the size of the rectangle. */
1009 dumprectangle (f
, left
, top
, cols
, rows
)
1011 register int left
, top
, cols
, rows
;
1013 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1014 int cursor_cleared
= 0;
1018 if (FRAME_GARBAGED_P (f
))
1021 /* Express rectangle as four edges, instead of position-and-size. */
1022 bottom
= top
+ rows
;
1023 right
= left
+ cols
;
1025 #ifndef HAVE_X11 /* Window manger does this for X11. */
1027 int intborder
= f
->display
.x
->internal_border_width
;
1029 /* If the rectangle includes any of the internal border area,
1030 redisplay the border emphasis. */
1031 if (top
< intborder
|| left
< intborder
1032 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1033 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1036 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1038 /* Convert rectangle edges in pixels to edges in chars.
1039 Round down for left and top, up for right and bottom. */
1040 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1041 left
= PIXEL_TO_CHAR_COL (f
, left
);
1042 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1043 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1044 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1045 right
= PIXEL_TO_CHAR_COL (f
, right
);
1047 /* Clip the rectangle to what can be visible. */
1052 if (right
> f
->width
)
1054 if (bottom
> f
->height
)
1057 /* Get size in chars of the rectangle. */
1058 cols
= right
- left
;
1059 rows
= bottom
- top
;
1061 /* If rectangle has zero area, return. */
1062 if (rows
<= 0) return;
1063 if (cols
<= 0) return;
1065 /* Turn off the cursor if it is in the rectangle.
1066 We will turn it back on afterward. */
1067 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1068 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1074 /* Display the text in the rectangle, one text line at a time. */
1076 for (y
= top
; y
< bottom
; y
++)
1078 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1080 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1084 CHAR_TO_PIXEL_COL (f
, left
),
1085 CHAR_TO_PIXEL_ROW (f
, y
),
1086 line
, min (cols
, active_frame
->used
[y
] - left
),
1087 active_frame
->highlight
[y
], f
->display
.x
->font
);
1090 /* Turn the cursor on if we turned it off. */
1093 x_display_cursor (f
, 1);
1097 /* Process all queued ExposeRegion events. */
1103 XExposeRegionEvent r
;
1105 while (dequeue_event (&r
, &x_expose_queue
))
1107 struct frame
*f
= x_window_to_frame (r
.window
);
1108 if (f
->display
.x
->icon_desc
== r
.window
)
1111 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1115 #endif /* HAVE_X11 */
1117 /* Process all expose events that are pending, for X10.
1118 Redraws the cursor if necessary on any frame that
1119 is not in the process of being updated with update_frame. */
1123 x_do_pending_expose ()
1127 Lisp_Object tail
, frame
;
1129 if (expose_all_windows
)
1131 expose_all_windows
= 0;
1132 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1134 register int temp_width
, temp_height
;
1137 frame
= XCONS (tail
)->car
;
1138 if (XGCTYPE (frame
) != Lisp_Frame
)
1141 if (! FRAME_X_P (f
))
1143 if (!f
->async_visible
)
1145 if (!f
->display
.x
->needs_exposure
)
1148 intborder
= f
->display
.x
->internal_border_width
;
1151 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1152 temp_width
= ((windowinfo
.width
- 2 * intborder
1153 - f
->display
.x
->v_scroll_bar_width
)
1154 / FONT_WIDTH (f
->display
.x
->font
));
1155 temp_height
= ((windowinfo
.height
- 2 * intborder
1156 - f
->display
.x
->h_scroll_bar_height
)
1157 / FONT_HEIGHT (f
->display
.x
->font
));
1158 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1160 change_frame_size (f
, max (1, temp_height
),
1161 max (1, temp_width
), 0, 1);
1162 x_resize_scroll_bars (f
);
1164 f
->display
.x
->left_pos
= windowinfo
.x
;
1165 f
->display
.x
->top_pos
= windowinfo
.y
;
1166 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1170 f
->display
.x
->needs_exposure
= 0;
1171 if (updating_frame
!= f
)
1172 x_display_cursor (f
, 1);
1177 /* Handle any individual-rectangle expose events queued
1178 for various windows. */
1181 #else /* ! defined (HAVE_X11) */
1183 #endif /* ! defined (HAVE_X11) */
1189 frame_highlight (frame
)
1190 struct frame
*frame
;
1192 if (! EQ (Vx_no_window_manager
, Qnil
))
1193 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1194 frame
->display
.x
->border_pixel
);
1195 x_display_cursor (frame
, 1);
1199 frame_unhighlight (frame
)
1200 struct frame
*frame
;
1202 if (! EQ (Vx_no_window_manager
, Qnil
))
1203 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1204 frame
->display
.x
->border_tile
);
1205 x_display_cursor (frame
, 1);
1207 #else /* ! defined (HAVE_X11) */
1208 /* Dump the border-emphasis of frame F.
1209 If F is selected, this is a lining of the same color as the border,
1210 just within the border, occupying a portion of the internal border.
1211 If F is not selected, it is background in the same place.
1212 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1214 ALWAYS = 1 is used when a frame becomes selected or deselected.
1215 In that case, we also turn the cursor off and on again
1216 so it will appear in the proper shape (solid if selected; else hollow.) */
1219 dumpborder (f
, always
)
1223 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1224 int width
= PIXEL_WIDTH (f
);
1225 int height
= PIXEL_HEIGHT (f
);
1228 if (f
!= selected_frame
)
1233 pixel
= f
->display
.x
->background_pixel
;
1237 pixel
= f
->display
.x
->border_pixel
;
1240 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1241 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1242 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1244 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1248 x_display_cursor (f
, 1);
1250 #endif /* ! defined (HAVE_X11) */
1252 static void XTframe_rehighlight ();
1254 /* The focus has changed. Update the frames as necessary to reflect
1255 the new situation. Note that we can't change the selected frame
1256 here, because the lisp code we are interrupting might become confused.
1257 Each event gets marked with the frame in which it occured, so the
1258 lisp code can tell when the switch took place by examining the events. */
1261 x_new_focus_frame (frame
)
1262 struct frame
*frame
;
1264 struct frame
*old_focus
= x_focus_frame
;
1265 int events_enqueued
= 0;
1267 if (frame
!= x_focus_frame
)
1269 /* Set this before calling other routines, so that they see
1270 the correct value of x_focus_frame. */
1271 x_focus_frame
= frame
;
1273 if (old_focus
&& old_focus
->auto_lower
)
1274 x_lower_frame (old_focus
);
1277 selected_frame
= frame
;
1278 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1279 Lisp_Frame
, selected_frame
);
1280 Fselect_window (selected_frame
->selected_window
);
1281 choose_minibuf_frame ();
1284 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1285 x_raise_frame (x_focus_frame
);
1288 XTframe_rehighlight ();
1292 /* The focus has changed, or we have redirected a frame's focus to
1293 another frame (this happens when a frame uses a surrogate
1294 minibuffer frame). Shift the highlight as appropriate. */
1296 XTframe_rehighlight ()
1298 struct frame
*old_highlight
= x_highlight_frame
;
1303 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1304 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1306 if (! FRAME_LIVE_P (x_highlight_frame
))
1308 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1309 x_highlight_frame
= x_focus_frame
;
1313 x_highlight_frame
= 0;
1315 if (x_highlight_frame
!= old_highlight
)
1318 frame_unhighlight (old_highlight
);
1319 if (x_highlight_frame
)
1320 frame_highlight (x_highlight_frame
);
1324 /* Mouse clicks and mouse movement. Rah. */
1327 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1328 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1329 that the glyph at X, Y occupies, if BOUNDS != 0. */
1331 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
)
1333 register unsigned int pix_x
, pix_y
;
1334 register int *x
, *y
;
1337 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1338 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1342 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1343 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1344 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1345 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1348 if (pix_x
< 0) pix_x
= 0;
1349 else if (pix_x
> f
->width
) pix_x
= f
->width
;
1351 if (pix_y
< 0) pix_y
= 0;
1352 else if (pix_y
> f
->height
) pix_y
= f
->height
;
1358 /* Any buttons grabbed. */
1359 unsigned int x_mouse_grabbed
;
1361 /* Which modifier keys are on which modifier bits?
1363 With each keystroke, X returns eight bits indicating which modifier
1364 keys were held down when the key was pressed. The interpretation
1365 of the top five modifier bits depends on what keys are attached
1366 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1369 x_meta_mod_mask is a mask containing the bits used for the meta key.
1370 It may have more than one bit set, if more than one modifier bit
1371 has meta keys on it. Basically, if EVENT is a KeyPress event,
1372 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1374 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1375 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1376 only be affected by the lock modifier bit if XK_Shift_Lock is in
1377 use; XK_Caps_Lock should only affect alphabetic keys. With this
1378 arrangement, the lock modifier should shift the character if
1379 (EVENT.state & x_shift_lock_mask) != 0. */
1380 static int x_meta_mod_mask
, x_shift_lock_mask
;
1382 /* These are like x_meta_mod_mask, but for different modifiers. */
1383 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1385 /* Initialize mode_switch_bit and modifier_meaning. */
1387 x_find_modifier_meanings ()
1389 int min_code
, max_code
;
1392 XModifierKeymap
*mods
;
1394 x_meta_mod_mask
= 0;
1395 x_shift_lock_mask
= 0;
1397 x_super_mod_mask
= 0;
1398 x_hyper_mod_mask
= 0;
1401 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1403 min_code
= x_current_display
->min_keycode
;
1404 max_code
= x_current_display
->max_keycode
;
1407 syms
= XGetKeyboardMapping (x_current_display
,
1408 min_code
, max_code
- min_code
+ 1,
1410 mods
= XGetModifierMapping (x_current_display
);
1412 /* Scan the modifier table to see which modifier bits the Meta and
1413 Alt keysyms are on. */
1415 int row
, col
; /* The row and column in the modifier table. */
1417 for (row
= 3; row
< 8; row
++)
1418 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1421 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1423 /* Are any of this keycode's keysyms a meta key? */
1427 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1429 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1435 x_meta_mod_mask
|= (1 << row
);
1440 x_alt_mod_mask
|= (1 << row
);
1445 x_hyper_mod_mask
|= (1 << row
);
1450 x_super_mod_mask
|= (1 << row
);
1454 /* Ignore this if it's not on the lock modifier. */
1455 if ((1 << row
) == LockMask
)
1456 x_shift_lock_mask
= LockMask
;
1464 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1465 if (! x_meta_mod_mask
)
1467 x_meta_mod_mask
= x_alt_mod_mask
;
1471 XFree ((char *) syms
);
1472 XFreeModifiermap (mods
);
1476 /* Convert a set of X modifier bits to the proper form for a
1477 struct input_event modifiers value. */
1480 x_convert_modifiers (state
)
1483 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1484 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1485 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1486 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1487 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1488 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1491 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1493 If the event is a button press, then note that we have grabbed
1497 construct_mouse_click (result
, event
, f
)
1498 struct input_event
*result
;
1499 XButtonEvent
*event
;
1502 /* Make the event type no_event; we'll change that when we decide
1504 result
->kind
= mouse_click
;
1505 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1506 result
->timestamp
= event
->time
;
1507 result
->modifiers
= (x_convert_modifiers (event
->state
)
1508 | (event
->type
== ButtonRelease
1512 /* Notice if the mouse is still grabbed. */
1513 if (event
->type
== ButtonPress
)
1515 if (! x_mouse_grabbed
)
1516 Vmouse_depressed
= Qt
;
1517 x_mouse_grabbed
|= (1 << event
->button
);
1519 else if (event
->type
== ButtonRelease
)
1521 x_mouse_grabbed
&= ~(1 << event
->button
);
1522 if (!x_mouse_grabbed
)
1523 Vmouse_depressed
= Qnil
;
1529 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
);
1530 XFASTINT (result
->x
) = column
;
1531 XFASTINT (result
->y
) = row
;
1532 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1537 /* Mouse movement. Rah.
1539 In order to avoid asking for motion events and then throwing most
1540 of them away or busy-polling the server for mouse positions, we ask
1541 the server for pointer motion hints. This means that we get only
1542 one event per group of mouse movements. "Groups" are delimited by
1543 other kinds of events (focus changes and button clicks, for
1544 example), or by XQueryPointer calls; when one of these happens, we
1545 get another MotionNotify event the next time the mouse moves. This
1546 is at least as efficient as getting motion events when mouse
1547 tracking is on, and I suspect only negligibly worse when tracking
1550 The silly O'Reilly & Associates Nutshell guides barely document
1551 pointer motion hints at all (I think you have to infer how they
1552 work from an example), and the description of XQueryPointer doesn't
1553 mention that calling it causes you to get another motion hint from
1554 the server, which is very important. */
1556 /* Where the mouse was last time we reported a mouse event. */
1557 static FRAME_PTR last_mouse_frame
;
1558 static XRectangle last_mouse_glyph
;
1560 /* The scroll bar in which the last X motion event occurred.
1562 If the last X motion event occured in a scroll bar, we set this
1563 so XTmouse_position can know whether to report a scroll bar motion or
1566 If the last X motion event didn't occur in a scroll bar, we set this
1567 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1568 static Lisp_Object last_mouse_scroll_bar
;
1570 /* This is a hack. We would really prefer that XTmouse_position would
1571 return the time associated with the position it returns, but there
1572 doesn't seem to be any way to wrest the timestamp from the server
1573 along with the position query. So, we just keep track of the time
1574 of the last movement we received, and return that in hopes that
1575 it's somewhat accurate. */
1576 static Time last_mouse_movement_time
;
1578 /* Function to report a mouse movement to the mainstream Emacs code.
1579 The input handler calls this.
1581 We have received a mouse movement event, which is given in *event.
1582 If the mouse is over a different glyph than it was last time, tell
1583 the mainstream emacs code by setting mouse_moved. If not, ask for
1584 another motion event, so we can check again the next time it moves. */
1586 note_mouse_movement (frame
, event
)
1588 XMotionEvent
*event
;
1591 last_mouse_movement_time
= event
->time
;
1593 /* Has the mouse moved off the glyph it was on at the last sighting? */
1594 if (event
->x
< last_mouse_glyph
.x
1595 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1596 || event
->y
< last_mouse_glyph
.y
1597 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1600 last_mouse_scroll_bar
= Qnil
;
1604 /* It's on the same glyph. Call XQueryPointer so we'll get an
1605 event the next time the mouse moves and we can see if it's
1606 *still* on the same glyph. */
1609 XQueryPointer (event
->display
, event
->window
,
1610 (Window
*) &dummy
, (Window
*) &dummy
,
1611 &dummy
, &dummy
, &dummy
, &dummy
,
1612 (unsigned int *) &dummy
);
1616 static struct scroll_bar
*x_window_to_scroll_bar ();
1617 static void x_scroll_bar_report_motion ();
1619 /* Return the current position of the mouse.
1621 If the mouse movement started in a scroll bar, set *f, *bar_window,
1622 and *part to the frame, window, and scroll bar part that the mouse
1623 is over. Set *x and *y to the portion and whole of the mouse's
1624 position on the scroll bar.
1626 If the mouse movement started elsewhere, set *f to the frame the
1627 mouse is on, *bar_window to nil, and *x and *y to the character cell
1630 Set *time to the server timestamp for the time at which the mouse
1631 was at this position.
1633 This clears the mouse_moved flag, so we can wait for the next mouse
1634 movement. This also calls XQueryPointer, which will cause the
1635 server to give us another MotionNotify when the mouse moves
1639 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1641 Lisp_Object
*bar_window
;
1642 enum scroll_bar_part
*part
;
1644 unsigned long *time
;
1648 if (! NILP (last_mouse_scroll_bar
))
1649 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1655 Window dummy_window
;
1659 last_mouse_scroll_bar
= Qnil
;
1661 /* Figure out which root window we're on. */
1662 XQueryPointer (x_current_display
,
1663 DefaultRootWindow (x_current_display
),
1665 /* The root window which contains the pointer. */
1668 /* Trash which we can't trust if the pointer is on
1669 a different screen. */
1672 /* The position on that root window. */
1675 /* More trash we can't trust. */
1678 /* Modifier keys and pointer buttons, about which
1680 (unsigned int *) &dummy
);
1682 /* Now we have a position on the root; find the innermost window
1683 containing the pointer. */
1687 int parent_x
, parent_y
;
1692 XTranslateCoordinates (x_current_display
,
1694 /* From-window, to-window. */
1697 /* From-position, to-position. */
1698 root_x
, root_y
, &win_x
, &win_y
,
1711 /* Now we know that:
1712 win is the innermost window containing the pointer
1713 (XTC says it has no child containing the pointer),
1714 win_x and win_y are the pointer's position in it
1715 (XTC did this the last time through), and
1716 parent_x and parent_y are the pointer's position in win's parent.
1717 (They are what win_x and win_y were when win was child.
1718 If win is the root window, it has no parent, and
1719 parent_{x,y} are invalid, but that's okay, because we'll
1720 never use them in that case.) */
1722 /* Is win one of our frames? */
1723 *f
= x_window_to_frame (win
);
1725 /* If not, is it one of our scroll bars? */
1728 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1732 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1740 pixel_to_glyph_coords (*f
, win_x
, win_y
, &win_x
, &win_y
,
1745 XSET (*x
, Lisp_Int
, win_x
);
1746 XSET (*y
, Lisp_Int
, win_y
);
1747 *time
= last_mouse_movement_time
;
1755 #else /* ! defined (HAVE_X11) */
1756 #define XEvent XKeyPressedEvent
1757 #endif /* ! defined (HAVE_X11) */
1759 /* Scroll bar support. */
1761 /* Given an X window ID, find the struct scroll_bar which manages it.
1762 This can be called in GC, so we have to make sure to strip off mark
1764 static struct scroll_bar
*
1765 x_window_to_scroll_bar (window_id
)
1768 Lisp_Object tail
, frame
;
1770 for (tail
= Vframe_list
;
1771 XGCTYPE (tail
) == Lisp_Cons
;
1772 tail
= XCONS (tail
)->cdr
)
1774 Lisp_Object frame
= XCONS (tail
)->car
;
1775 Lisp_Object bar
, condemned
;
1777 /* All elements of Vframe_list should be frames. */
1778 if (XGCTYPE (frame
) != Lisp_Frame
)
1781 /* Scan this frame's scroll bar list for a scroll bar with the
1783 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1784 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1785 /* This trick allows us to search both the ordinary and
1786 condemned scroll bar lists with one loop. */
1787 ! GC_NILP (bar
) || (bar
= condemned
,
1790 bar
= XSCROLL_BAR(bar
)->next
)
1791 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1792 return XSCROLL_BAR (bar
);
1798 /* Open a new X window to serve as a scroll bar, and return the
1799 scroll bar vector for it. */
1800 static struct scroll_bar
*
1801 x_scroll_bar_create (window
, top
, left
, width
, height
)
1802 struct window
*window
;
1803 int top
, left
, width
, height
;
1805 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
1806 struct scroll_bar
*bar
=
1807 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1812 XSetWindowAttributes a
;
1815 a
.background_pixel
= frame
->display
.x
->background_pixel
;
1816 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
1817 | ButtonMotionMask
| PointerMotionHintMask
1819 a
.cursor
= x_vertical_scroll_bar_cursor
;
1821 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
1823 SET_SCROLL_BAR_X_WINDOW
1825 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
1827 /* Position and size of scroll bar. */
1828 left
, top
, width
, height
,
1830 /* Border width, depth, class, and visual. */
1831 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
1837 XSET (bar
->window
, Lisp_Window
, window
);
1838 XSET (bar
->top
, Lisp_Int
, top
);
1839 XSET (bar
->left
, Lisp_Int
, left
);
1840 XSET (bar
->width
, Lisp_Int
, width
);
1841 XSET (bar
->height
, Lisp_Int
, height
);
1842 XSET (bar
->start
, Lisp_Int
, 0);
1843 XSET (bar
->end
, Lisp_Int
, 0);
1844 bar
->dragging
= Qnil
;
1846 /* Add bar to its frame's list of scroll bars. */
1847 bar
->next
= FRAME_SCROLL_BARS (frame
);
1849 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
1850 if (! NILP (bar
->next
))
1851 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
1853 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
1860 /* Draw BAR's handle in the proper position.
1861 If the handle is already drawn from START to END, don't bother
1862 redrawing it, unless REBUILD is non-zero; in that case, always
1863 redraw it. (REBUILD is handy for drawing the handle after expose
1866 Normally, we want to constrain the start and end of the handle to
1867 fit inside its rectangle, but if the user is dragging the scroll bar
1868 handle, we want to let them drag it down all the way, so that the
1869 bar's top is as far down as it goes; otherwise, there's no way to
1870 move to the very end of the buffer. */
1872 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1873 struct scroll_bar
*bar
;
1877 int dragging
= ! NILP (bar
->dragging
);
1878 Window w
= SCROLL_BAR_X_WINDOW (bar
);
1879 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
1881 /* If the display is already accurate, do nothing. */
1883 && start
== XINT (bar
->start
)
1884 && end
== XINT (bar
->end
))
1890 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
1891 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
1892 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
1894 /* Make sure the values are reasonable, and try to preserve
1895 the distance between start and end. */
1897 int length
= end
- start
;
1901 else if (start
> top_range
)
1903 end
= start
+ length
;
1907 else if (end
> top_range
&& ! dragging
)
1911 /* Store the adjusted setting in the scroll bar. */
1912 XSET (bar
->start
, Lisp_Int
, start
);
1913 XSET (bar
->end
, Lisp_Int
, end
);
1915 /* Clip the end position, just for display. */
1916 if (end
> top_range
)
1919 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1920 below top positions, to make sure the handle is always at least
1921 that many pixels tall. */
1922 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
1924 /* Draw the empty space above the handle. Note that we can't clear
1925 zero-height areas; that means "clear to end of window." */
1927 XClearArea (x_current_display
, w
,
1929 /* x, y, width, height, and exposures. */
1930 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1931 VERTICAL_SCROLL_BAR_TOP_BORDER
,
1932 inside_width
, start
,
1935 /* Draw the handle itself. */
1936 XFillRectangle (x_current_display
, w
, gc
,
1938 /* x, y, width, height */
1939 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1940 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
1941 inside_width
, end
- start
);
1944 /* Draw the empty space below the handle. Note that we can't
1945 clear zero-height areas; that means "clear to end of window." */
1946 if (end
< inside_height
)
1947 XClearArea (x_current_display
, w
,
1949 /* x, y, width, height, and exposures. */
1950 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
1951 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
1952 inside_width
, inside_height
- end
,
1960 /* Move a scroll bar around on the screen, to accomodate changing
1961 window configurations. */
1963 x_scroll_bar_move (bar
, top
, left
, width
, height
)
1964 struct scroll_bar
*bar
;
1965 int top
, left
, width
, height
;
1971 unsigned int mask
= 0;
1978 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
1979 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
1980 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
1981 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
1984 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
1988 XSET (bar
->left
, Lisp_Int
, left
);
1989 XSET (bar
->top
, Lisp_Int
, top
);
1990 XSET (bar
->width
, Lisp_Int
, width
);
1991 XSET (bar
->height
, Lisp_Int
, height
);
1996 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
1999 x_scroll_bar_remove (bar
)
2000 struct scroll_bar
*bar
;
2002 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2006 /* Destroy the window. */
2007 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2009 /* Disassociate this scroll bar from its window. */
2010 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2015 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2016 that we are displaying PORTION characters out of a total of WHOLE
2017 characters, starting at POSITION. If WINDOW has no scroll bar,
2020 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2021 struct window
*window
;
2022 int portion
, whole
, position
;
2024 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2025 int top
= XINT (window
->top
);
2026 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2027 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2029 /* Where should this scroll bar be, pixelwise? */
2030 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2031 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2032 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2033 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2035 struct scroll_bar
*bar
;
2037 /* Does the scroll bar exist yet? */
2038 if (NILP (window
->vertical_scroll_bar
))
2039 bar
= x_scroll_bar_create (window
,
2040 pixel_top
, pixel_left
,
2041 pixel_width
, pixel_height
);
2044 /* It may just need to be moved and resized. */
2045 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2046 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2049 /* Set the scroll bar's current state, unless we're currently being
2051 if (NILP (bar
->dragging
))
2054 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2057 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2060 int start
= (position
* top_range
) / whole
;
2061 int end
= ((position
+ portion
) * top_range
) / whole
;
2063 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2067 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2071 /* The following three hooks are used when we're doing a thorough
2072 redisplay of the frame. We don't explicitly know which scroll bars
2073 are going to be deleted, because keeping track of when windows go
2074 away is a real pain - "Can you say set-window-configuration, boys
2075 and girls?" Instead, we just assert at the beginning of redisplay
2076 that *all* scroll bars are to be removed, and then save a scroll bar
2077 from the fiery pit when we actually redisplay its window. */
2079 /* Arrange for all scroll bars on FRAME to be removed at the next call
2080 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2081 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2083 XTcondemn_scroll_bars (frame
)
2086 /* The condemned list should be empty at this point; if it's not,
2087 then the rest of Emacs isn't using the condemn/redeem/judge
2088 protocol correctly. */
2089 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2092 /* Move them all to the "condemned" list. */
2093 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2094 FRAME_SCROLL_BARS (frame
) = Qnil
;
2097 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2098 Note that WINDOW isn't necessarily condemned at all. */
2100 XTredeem_scroll_bar (window
)
2101 struct window
*window
;
2103 struct scroll_bar
*bar
;
2105 /* We can't redeem this window's scroll bar if it doesn't have one. */
2106 if (NILP (window
->vertical_scroll_bar
))
2109 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2111 /* Unlink it from the condemned list. */
2113 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2115 if (NILP (bar
->prev
))
2117 /* If the prev pointer is nil, it must be the first in one of
2119 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2120 /* It's not condemned. Everything's fine. */
2122 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2123 window
->vertical_scroll_bar
))
2124 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2126 /* If its prev pointer is nil, it must be at the front of
2127 one or the other! */
2131 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2133 if (! NILP (bar
->next
))
2134 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2136 bar
->next
= FRAME_SCROLL_BARS (f
);
2138 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2139 if (! NILP (bar
->next
))
2140 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2144 /* Remove all scroll bars on FRAME that haven't been saved since the
2145 last call to `*condemn_scroll_bars_hook'. */
2147 XTjudge_scroll_bars (f
)
2150 Lisp_Object bar
, next
;
2152 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2154 /* Clear out the condemned list now so we won't try to process any
2155 more events on the hapless scroll bars. */
2156 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2158 for (; ! NILP (bar
); bar
= next
)
2160 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2162 x_scroll_bar_remove (b
);
2165 b
->next
= b
->prev
= Qnil
;
2168 /* Now there should be no references to the condemned scroll bars,
2169 and they should get garbage-collected. */
2173 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2175 This may be called from a signal handler, so we have to ignore GC
2178 x_scroll_bar_expose (bar
, event
)
2179 struct scroll_bar
*bar
;
2182 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2183 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2187 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2189 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2190 XDrawRectangle (x_current_display
, w
, gc
,
2192 /* x, y, width, height */
2193 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2195 /* Draw another line to make the extra-thick border on the right. */
2196 XFillRectangle (x_current_display
, w
, gc
,
2198 /* x, y, width, height */
2199 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2204 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2205 is set to something other than no_event, it is enqueued.
2207 This may be called from a signal handler, so we have to ignore GC
2210 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2211 struct scroll_bar
*bar
;
2213 struct input_event
*emacs_event
;
2215 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2218 emacs_event
->kind
= scroll_bar_click
;
2219 XSET (emacs_event
->code
, Lisp_Int
, event
->xbutton
.button
- Button1
);
2220 emacs_event
->modifiers
=
2221 (x_convert_modifiers (event
->xbutton
.state
)
2222 | (event
->type
== ButtonRelease
2225 emacs_event
->frame_or_window
= bar
->window
;
2226 emacs_event
->timestamp
= event
->xbutton
.time
;
2228 int internal_height
=
2229 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2231 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2232 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2235 if (y
> top_range
) y
= top_range
;
2237 if (y
< XINT (bar
->start
))
2238 emacs_event
->part
= scroll_bar_above_handle
;
2239 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2240 emacs_event
->part
= scroll_bar_handle
;
2242 emacs_event
->part
= scroll_bar_below_handle
;
2244 /* If the user has just clicked on the handle, record where they're
2246 if (event
->type
== ButtonPress
2247 && emacs_event
->part
== scroll_bar_handle
)
2248 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2250 /* If the user has released the handle, set it to its final position. */
2251 if (event
->type
== ButtonRelease
2252 && ! NILP (bar
->dragging
))
2254 int new_start
= y
- XINT (bar
->dragging
);
2255 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2257 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2258 bar
->dragging
= Qnil
;
2261 /* Clicks on the handle are always reported as occuring at the top of
2263 if (emacs_event
->part
== scroll_bar_handle
)
2264 emacs_event
->x
= bar
->start
;
2266 XSET (emacs_event
->x
, Lisp_Int
, y
);
2268 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2272 /* Handle some mouse motion while someone is dragging the scroll bar.
2274 This may be called from a signal handler, so we have to ignore GC
2277 x_scroll_bar_note_movement (bar
, event
)
2278 struct scroll_bar
*bar
;
2281 last_mouse_movement_time
= event
->xmotion
.time
;
2284 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2286 /* If we're dragging the bar, display it. */
2287 if (! GC_NILP (bar
->dragging
))
2289 /* Where should the handle be now? */
2290 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2292 if (new_start
!= XINT (bar
->start
))
2294 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2296 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2300 /* Call XQueryPointer so we'll get an event the next time the mouse
2301 moves and we can see *still* on the same position. */
2305 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2306 (Window
*) &dummy
, (Window
*) &dummy
,
2307 &dummy
, &dummy
, &dummy
, &dummy
,
2308 (unsigned int *) &dummy
);
2312 /* Return information to the user about the current position of the mouse
2313 on the scroll bar. */
2315 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2317 Lisp_Object
*bar_window
;
2318 enum scroll_bar_part
*part
;
2320 unsigned long *time
;
2322 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2327 /* Get the mouse's position relative to the scroll bar window, and
2330 Window dummy_window
;
2332 unsigned int dummy_mask
;
2334 if (! XQueryPointer (x_current_display
,
2335 SCROLL_BAR_X_WINDOW (bar
),
2337 /* Root, child, root x and root y. */
2338 &dummy_window
, &dummy_window
,
2339 &dummy_coord
, &dummy_coord
,
2341 /* Position relative to scroll bar. */
2344 /* Mouse buttons and modifier keys. */
2353 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2354 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2356 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2358 if (! NILP (bar
->dragging
))
2359 win_y
-= XINT (bar
->dragging
);
2363 if (win_y
> top_range
)
2366 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2367 *bar_window
= bar
->window
;
2369 if (! NILP (bar
->dragging
))
2370 *part
= scroll_bar_handle
;
2371 else if (win_y
< XINT (bar
->start
))
2372 *part
= scroll_bar_above_handle
;
2373 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2374 *part
= scroll_bar_handle
;
2376 *part
= scroll_bar_below_handle
;
2378 XSET (*x
, Lisp_Int
, win_y
);
2379 XSET (*y
, Lisp_Int
, top_range
);
2380 *time
= last_mouse_movement_time
;
2384 last_mouse_scroll_bar
= Qnil
;
2391 /* The screen has been cleared so we may have changed foreground or
2392 background colors, and the scroll bars may need to be redrawn.
2393 Clear out the scroll bars, and ask for expose events, so we can
2396 x_scroll_bar_clear (f
)
2401 for (bar
= FRAME_SCROLL_BARS (f
);
2402 XTYPE (bar
) == Lisp_Vector
;
2403 bar
= XSCROLL_BAR (bar
)->next
)
2404 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2410 /* The main X event-reading loop - XTread_socket. */
2412 /* Timestamp of enter window event. This is only used by XTread_socket,
2413 but we have to put it out here, since static variables within functions
2414 sometimes don't work. */
2415 static Time enter_timestamp
;
2417 /* This holds the state XLookupString needs to implement dead keys
2418 and other tricks known as "compose processing". _X Window System_
2419 says that a portable program can't use this, but Stephen Gildea assures
2420 me that letting the compiler initialize it to zeros will work okay.
2422 This must be defined outside of XTread_socket, for the same reasons
2423 given for enter_timestamp, above. */
2424 static XComposeStatus compose_status
;
2426 /* Communication with window managers. */
2427 Atom Xatom_wm_protocols
;
2429 /* Kinds of protocol things we may receive. */
2430 Atom Xatom_wm_take_focus
;
2431 Atom Xatom_wm_save_yourself
;
2432 Atom Xatom_wm_delete_window
;
2434 /* Other WM communication */
2435 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2436 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2438 /* Window manager communication. */
2439 Atom Xatom_wm_change_state
;
2441 /* Record the last 100 characters stored
2442 to help debug the loss-of-chars-during-GC problem. */
2444 short temp_buffer
[100];
2446 /* Read events coming from the X server.
2447 This routine is called by the SIGIO handler.
2448 We return as soon as there are no more events to be read.
2450 Events representing keys are stored in buffer BUFP,
2451 which can hold up to NUMCHARS characters.
2452 We return the number of characters stored into the buffer,
2453 thus pretending to be `read'.
2455 WAITP is nonzero if we should block until input arrives.
2456 EXPECTED is nonzero if the caller knows input is available. */
2459 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2461 register struct input_event
*bufp
;
2462 register int numchars
;
2469 int items_pending
; /* How many items are in the X queue. */
2476 if (interrupt_input_blocked
)
2478 interrupt_input_pending
= 1;
2482 interrupt_input_pending
= 0;
2486 abort (); /* Don't think this happens. */
2489 /* If available, Xlib uses FIOSNBIO to make the socket
2490 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2491 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2492 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2493 fcntl (fileno (stdin
), F_SETFL
, 0);
2494 #endif /* ! defined (FIOSNBIO) */
2498 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2500 extern int read_alarm_should_throw
;
2501 read_alarm_should_throw
= 1;
2502 XPeekEvent (XDISPLAY
&event
);
2503 read_alarm_should_throw
= 0;
2505 #endif /* HAVE_SELECT */
2508 while (XStuffPending () != 0)
2510 XNextEvent (XDISPLAY
&event
);
2518 if (event
.xclient
.message_type
== Xatom_wm_protocols
2519 && event
.xclient
.format
== 32)
2521 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2523 f
= x_window_to_frame (event
.xclient
.window
);
2525 x_focus_on_frame (f
);
2526 /* Not certain about handling scroll bars here */
2528 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2530 /* Save state modify the WM_COMMAND property to
2531 something which can reinstate us. This notifies
2532 the session manager, who's looking for such a
2533 PropertyNotify. Can restart processing when
2534 a keyboard or mouse event arrives. */
2539 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2541 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2549 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2552 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2556 new_x
= event
.xclient
.data
.s
[0];
2557 new_y
= event
.xclient
.data
.s
[1];
2562 #ifdef NEW_SELECTIONS
2563 case SelectionNotify
:
2564 x_handle_selection_notify (&event
);
2568 case SelectionClear
: /* Someone has grabbed ownership. */
2569 #ifdef NEW_SELECTIONS
2571 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2576 bufp
->kind
= selection_clear_event
;
2577 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2578 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2579 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2586 x_disown_selection (event
.xselectionclear
.window
,
2587 event
.xselectionclear
.selection
,
2588 event
.xselectionclear
.time
);
2592 case SelectionRequest
: /* Someone wants our selection. */
2593 #ifdef NEW_SELECTIONS
2595 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2600 bufp
->kind
= selection_request_event
;
2601 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2602 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2603 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2604 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2605 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2606 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2613 x_answer_selection_request (event
);
2617 case PropertyNotify
:
2618 #ifdef NEW_SELECTIONS
2619 x_handle_property_notify (&event
);
2621 /* If we're being told about a root window property, then it's
2622 a cut buffer change. */
2623 if (event
.xproperty
.window
== ROOT_WINDOW
)
2624 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2626 /* Otherwise, we're probably handling an incremental
2627 selection transmission. */
2630 /* If we were to do this synchronously, there'd be no worry
2631 about re-selecting. */
2632 x_send_incremental (event
);
2638 f
= x_window_to_frame (event
.xexpose
.window
);
2641 if (f
->async_visible
== 0)
2643 f
->async_visible
= 1;
2644 f
->async_iconified
= 0;
2645 SET_FRAME_GARBAGED (f
);
2649 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2650 event
.xexpose
.x
, event
.xexpose
.y
,
2651 event
.xexpose
.width
, event
.xexpose
.height
);
2656 struct scroll_bar
*bar
2657 = x_window_to_scroll_bar (event
.xexpose
.window
);
2660 x_scroll_bar_expose (bar
, &event
);
2664 case GraphicsExpose
: /* This occurs when an XCopyArea's
2665 source area was obscured or not
2667 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
2671 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
2672 event
.xgraphicsexpose
.width
,
2673 event
.xgraphicsexpose
.height
);
2677 case NoExpose
: /* This occurs when an XCopyArea's
2678 source area was completely
2681 #else /* ! defined (HAVE_X11) */
2683 if (event
.subwindow
!= 0)
2684 break; /* duplicate event */
2685 f
= x_window_to_frame (event
.window
);
2686 if (event
.window
== f
->display
.x
->icon_desc
)
2689 f
->async_iconified
= 1;
2691 if (event
.window
== FRAME_X_WINDOW (f
))
2693 /* Say must check all windows' needs_exposure flags. */
2694 expose_all_windows
= 1;
2695 f
->display
.x
->needs_exposure
= 1;
2696 f
->async_visible
= 1;
2701 if (event
.subwindow
!= 0)
2702 break; /* duplicate event */
2703 f
= x_window_to_frame (event
.window
);
2704 if (event
.window
== f
->display
.x
->icon_desc
)
2709 /* If window already needs full redraw, ignore this rectangle. */
2710 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
2712 /* Put the event on the queue of rectangles to redraw. */
2713 if (enqueue_event (&event
, &x_expose_queue
))
2714 /* If it is full, we can't record the rectangle,
2715 so redraw this entire window. */
2717 /* Say must check all windows' needs_exposure flags. */
2718 expose_all_windows
= 1;
2719 f
->display
.x
->needs_exposure
= 1;
2724 /* This should happen only when we are expecting it,
2725 in x_read_exposes. */
2727 #endif /* ! defined (HAVE_X11) */
2731 f
= x_window_to_frame (event
.xunmap
.window
);
2732 if (f
) /* F may no longer exist if
2733 the frame was deleted. */
2735 /* While a frame is unmapped, display generation is
2736 disabled; you don't want to spend time updating a
2737 display that won't ever be seen. */
2738 f
->async_visible
= 0;
2743 f
= x_window_to_frame (event
.xmap
.window
);
2746 f
->async_visible
= 1;
2747 f
->async_iconified
= 0;
2749 /* wait_reading_process_input will notice this and update
2750 the frame's display structures. */
2751 SET_FRAME_GARBAGED (f
);
2755 /* Turn off processing if we become fully obscured. */
2756 case VisibilityNotify
:
2759 #else /* ! defined (HAVE_X11) */
2761 f
= x_window_to_frame (event
.window
);
2762 if (event
.window
== f
->display
.x
->icon_desc
)
2763 f
->async_iconified
= 0;
2764 if (event
.window
== FRAME_X_WINDOW (f
))
2765 f
->async_visible
= 0;
2767 #endif /* ! defined (HAVE_X11) */
2771 f
= x_window_to_frame (event
.xkey
.window
);
2776 char copy_buffer
[80];
2779 event
.xkey
.state
|= extra_keyboard_modifiers
;
2780 modifiers
= event
.xkey
.state
;
2782 /* Some keyboards generate different characters
2783 depending on the state of the meta key, in an attempt
2784 to support non-English typists. It would be nice to
2785 keep this functionality somehow, but for now, we will
2786 just clear the meta-key flag to get the 'pure' character. */
2787 event
.xkey
.state
&= ~Mod1Mask
;
2789 /* This will have to go some day... */
2791 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
2794 /* Strip off the vendor-specific keysym bit, and take a shot
2795 at recognizing the codes. HP servers have extra keysyms
2796 that fit into the MiscFunctionKey category. */
2801 if ((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
2802 || keysym
== XK_Delete
2803 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
2804 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < 0xff80 */
2805 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
2806 || IsFunctionKey (keysym
)) /* 0xffbe <= x < 0xffe1 */
2808 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2810 temp_buffer
[temp_index
++] = keysym
;
2811 bufp
->kind
= non_ascii_keystroke
;
2812 XSET (bufp
->code
, Lisp_Int
, (unsigned) keysym
- 0xff00);
2813 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2814 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2815 bufp
->timestamp
= event
.xkey
.time
;
2820 else if (numchars
> nbytes
)
2824 for (i
= 0; i
< nbytes
; i
++)
2826 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2828 temp_buffer
[temp_index
++] = copy_buffer
[i
];
2829 bufp
->kind
= ascii_keystroke
;
2830 XSET (bufp
->code
, Lisp_Int
, copy_buffer
[i
]);
2831 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2832 bufp
->modifiers
= x_convert_modifiers (modifiers
);
2833 bufp
->timestamp
= event
.xkey
.time
;
2847 #else /* ! defined (HAVE_X11) */
2850 register char *where_mapping
;
2852 f
= x_window_to_frame (event
.window
);
2853 /* Ignore keys typed on icon windows. */
2854 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
2856 where_mapping
= XLookupMapping (&event
, &nbytes
);
2857 /* Nasty fix for arrow keys */
2858 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
2860 switch (event
.detail
& 0xff)
2862 case KC_CURSOR_LEFT
:
2863 where_mapping
= "\002";
2865 case KC_CURSOR_RIGHT
:
2866 where_mapping
= "\006";
2869 where_mapping
= "\020";
2871 case KC_CURSOR_DOWN
:
2872 where_mapping
= "\016";
2877 if (numchars
- nbytes
> 0)
2881 for (i
= 0; i
< nbytes
; i
++)
2883 bufp
->kind
= ascii_keystroke
;
2884 XSET (bufp
->code
, Lisp_Int
, where_mapping
[i
]);
2885 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
2886 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2894 #endif /* ! defined (HAVE_X11) */
2898 /* Here's a possible interpretation of the whole
2899 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2900 FocusIn event, you have to get a FocusOut event before you
2901 relinquish the focus. If you haven't received a FocusIn event,
2902 then a mere LeaveNotify is enough to free you. */
2905 f
= x_window_to_frame (event
.xcrossing
.window
);
2907 if (event
.xcrossing
.focus
) /* Entered Window */
2909 /* Avoid nasty pop/raise loops. */
2910 if (f
&& (!(f
->auto_raise
)
2912 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
2914 x_new_focus_frame (f
);
2915 enter_timestamp
= event
.xcrossing
.time
;
2918 else if (f
== x_focus_frame
)
2919 x_new_focus_frame (0);
2924 f
= x_window_to_frame (event
.xfocus
.window
);
2925 if (event
.xfocus
.detail
!= NotifyPointer
)
2926 x_focus_event_frame
= f
;
2928 x_new_focus_frame (f
);
2933 f
= x_window_to_frame (event
.xcrossing
.window
);
2935 if (event
.xcrossing
.focus
)
2937 if (! x_focus_event_frame
)
2938 x_new_focus_frame (0);
2940 x_new_focus_frame (f
);
2944 if (f
== x_focus_event_frame
)
2945 x_focus_event_frame
= 0;
2946 if (f
== x_focus_frame
)
2947 x_new_focus_frame (0);
2952 f
= x_window_to_frame (event
.xfocus
.window
);
2953 if (event
.xfocus
.detail
!= NotifyPointer
2954 && f
== x_focus_event_frame
)
2955 x_focus_event_frame
= 0;
2956 if (f
&& f
== x_focus_frame
)
2957 x_new_focus_frame (0);
2960 #else /* ! defined (HAVE_X11) */
2963 if ((event
.detail
& 0xFF) == 1)
2964 break; /* Coming from our own subwindow */
2965 if (event
.subwindow
!= 0)
2966 break; /* Entering our own subwindow. */
2969 f
= x_window_to_frame (event
.window
);
2972 x_new_focus_frame (f
);
2977 if ((event
.detail
& 0xFF) == 1)
2978 break; /* Entering our own subwindow */
2979 if (event
.subwindow
!= 0)
2980 break; /* Leaving our own subwindow. */
2983 if (x_focus_frame
== 0
2984 && x_input_frame
!= 0
2985 && x_input_frame
== x_window_to_frame (event
.window
)
2986 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
2991 frame_unhighlight (f
);
2994 #endif /* ! defined (HAVE_X11) */
2999 f
= x_window_to_frame (event
.xmotion
.window
);
3001 note_mouse_movement (f
, &event
.xmotion
);
3004 struct scroll_bar
*bar
=
3005 x_window_to_scroll_bar (event
.xmotion
.window
);
3008 x_scroll_bar_note_movement (bar
, &event
);
3013 case ConfigureNotify
:
3014 f
= x_window_to_frame (event
.xconfigure
.window
);
3017 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3018 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3020 /* Even if the number of character rows and columns has
3021 not changed, the font size may have changed, so we need
3022 to check the pixel dimensions as well. */
3023 if (columns
!= f
->width
3024 || rows
!= f
->height
3025 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3026 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3028 change_frame_size (f
, rows
, columns
, 0, 1);
3029 SET_FRAME_GARBAGED (f
);
3032 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3033 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3034 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3035 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3042 /* If we decide we want to generate an event to be seen
3043 by the rest of Emacs, we put it here. */
3044 struct input_event emacs_event
;
3045 emacs_event
.kind
= no_event
;
3047 f
= x_window_to_frame (event
.xbutton
.window
);
3050 if (!x_focus_frame
|| (f
== x_focus_frame
))
3051 construct_mouse_click (&emacs_event
,
3056 struct scroll_bar
*bar
=
3057 x_window_to_scroll_bar (event
.xbutton
.window
);
3060 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3063 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3065 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3073 #else /* ! defined (HAVE_X11) */
3075 case ButtonReleased
:
3076 f
= x_window_to_frame (event
.window
);
3079 if (event
.window
== f
->display
.x
->icon_desc
)
3081 x_make_frame_visible (f
);
3083 if (warp_mouse_on_deiconify
)
3084 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3087 if (event
.window
== FRAME_X_WINDOW (f
))
3093 enqueue_event (&event
, &x_mouse_queue
);
3096 bufp
->kind
= ascii_keystroke
;
3097 bufp
->code
= (char) 'X' & 037; /* C-x */
3098 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3099 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3102 bufp
->kind
= ascii_keystroke
;
3103 bufp
->code
= (char) 0; /* C-@ */
3104 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3105 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3112 #endif /* ! defined (HAVE_X11) */
3116 case CirculateNotify
:
3118 case CirculateRequest
:
3121 #endif /* ! defined (HAVE_X11) */
3124 /* Someone has changed the keyboard mapping - update the
3126 switch (event
.xmapping
.request
)
3128 case MappingModifier
:
3129 x_find_modifier_meanings ();
3130 /* This is meant to fall through. */
3131 case MappingKeyboard
:
3132 XRefreshKeyboardMapping (&event
.xmapping
);
3143 if (expected
&& ! event_found
)
3145 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3146 there is an EOF condition; in other words, that X has died.
3147 Act as if there had been a hangup. */
3149 int fd
= ConnectionNumber (x_current_display
);
3152 if (0 != select (fd
+ 1, &mask
, (long *) 0, (long *) 0,
3154 && !XStuffPending ())
3155 kill (getpid (), SIGHUP
);
3157 #endif /* ! defined (HAVE_SELECT) */
3161 if (updating_frame
== 0)
3162 x_do_pending_expose ();
3170 /* Read and process only Expose events
3171 until we get an ExposeCopy event; then return.
3172 This is used in insert/delete line.
3173 We assume input is already blocked. */
3179 XKeyPressedEvent event
;
3183 /* while there are more events*/
3184 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3188 if (event
.subwindow
!= 0)
3189 break; /* duplicate event */
3190 f
= x_window_to_frame (event
.window
);
3191 if (event
.window
== f
->display
.x
->icon_desc
)
3196 if (event
.window
== FRAME_X_WINDOW (f
))
3198 expose_all_windows
= 1;
3199 f
->display
.x
->needs_exposure
= 1;
3205 if (event
.subwindow
!= 0)
3206 break; /* duplicate event */
3207 f
= x_window_to_frame (event
.window
);
3208 if (event
.window
== f
->display
.x
->icon_desc
)
3213 /* If window already needs full redraw, ignore this rectangle. */
3214 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3216 /* Put the event on the queue of rectangles to redraw. */
3217 if (enqueue_event (&event
, &x_expose_queue
))
3218 /* If it is full, we can't record the rectangle,
3219 so redraw this entire window. */
3221 /* Say must check all windows' needs_exposure flags. */
3222 expose_all_windows
= 1;
3223 f
->display
.x
->needs_exposure
= 1;
3232 #endif /* HAVE_X11 */
3235 /* Drawing the cursor. */
3238 /* Draw a hollow box cursor. Don't change the inside of the box. */
3244 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3245 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3246 int width
= FONT_WIDTH (f
->display
.x
->font
);
3247 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3250 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3251 f
->display
.x
->cursor_gc
,
3252 left
, top
, width
- 1, height
- 1);
3253 #else /* ! defined (HAVE_X11) */
3254 XPixSet (FRAME_X_WINDOW (f
),
3255 left
, top
, width
, 1,
3256 f
->display
.x
->cursor_pixel
);
3258 XPixSet (FRAME_X_WINDOW (f
),
3259 left
, top
, 1, height
,
3260 f
->display
.x
->cursor_pixel
);
3262 XPixSet (FRAME_X_WINDOW (f
),
3263 left
+width
-1, top
, 1, height
,
3264 f
->display
.x
->cursor_pixel
);
3266 XPixSet (FRAME_X_WINDOW (f
),
3267 left
, top
+height
-1, width
, 1,
3268 f
->display
.x
->cursor_pixel
);
3269 #endif /* ! defined (HAVE_X11) */
3272 /* Clear the cursor of frame F to background color,
3273 and mark the cursor as not shown.
3274 This is used when the text where the cursor is
3275 is about to be rewritten. */
3283 if (! FRAME_VISIBLE_P (f
)
3284 || f
->phys_cursor_x
< 0)
3288 x_display_cursor (f
, 0);
3289 #else /* ! defined (HAVE_X11) */
3290 XPixSet (FRAME_X_WINDOW (f
),
3291 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3292 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3293 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3294 f
->display
.x
->background_pixel
);
3295 #endif /* ! defined (HAVE_X11) */
3296 f
->phys_cursor_x
= -1;
3299 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3300 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3304 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3311 CHAR_TO_PIXEL_COL (f
, column
),
3312 CHAR_TO_PIXEL_ROW (f
, row
),
3313 &glyph
, 1, highlight
, f
->display
.x
->font
);
3317 x_display_bar_cursor (f
, on
)
3321 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3323 /* This is pointless on invisible frames, and dangerous on garbaged
3324 frames; in the latter case, the frame may be in the midst of
3325 changing its size, and curs_x and curs_y may be off the frame. */
3326 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3329 if (! on
&& f
->phys_cursor_x
< 0)
3332 /* If we're not updating, then we want to use the current frame's
3333 cursor position, not our local idea of where the cursor ought to be. */
3334 if (f
!= updating_frame
)
3336 curs_x
= FRAME_CURSOR_X (f
);
3337 curs_y
= FRAME_CURSOR_Y (f
);
3340 /* If there is anything wrong with the current cursor state, remove it. */
3341 if (f
->phys_cursor_x
>= 0
3343 || f
->phys_cursor_x
!= curs_x
3344 || f
->phys_cursor_y
!= curs_y
3345 || f
->display
.x
->current_cursor
!= bar_cursor
))
3347 /* Erase the cursor by redrawing the character underneath it. */
3348 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3349 f
->phys_cursor_glyph
,
3350 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3351 f
->phys_cursor_x
= -1;
3354 /* If we now need a cursor in the new place or in the new form, do it so. */
3356 && (f
->phys_cursor_x
< 0
3357 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3359 f
->phys_cursor_glyph
3360 = ((current_glyphs
->enable
[curs_y
]
3361 && curs_x
< current_glyphs
->used
[curs_y
])
3362 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3364 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3365 f
->display
.x
->cursor_gc
,
3366 CHAR_TO_PIXEL_COL (f
, curs_x
),
3367 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3368 1, FONT_HEIGHT (f
->display
.x
->font
));
3370 f
->phys_cursor_x
= curs_x
;
3371 f
->phys_cursor_y
= curs_y
;
3373 f
->display
.x
->current_cursor
= bar_cursor
;
3376 if (updating_frame
!= f
)
3381 /* Turn the displayed cursor of frame F on or off according to ON.
3382 If ON is nonzero, where to put the cursor is specified
3383 by F->cursor_x and F->cursor_y. */
3386 x_display_box_cursor (f
, on
)
3390 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3392 /* This is pointless on invisible frames, and dangerous on garbaged
3393 frames; in the latter case, the frame may be in the midst of
3394 changing its size, and curs_x and curs_y may be off the frame. */
3395 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3398 /* If cursor is off and we want it off, return quickly. */
3399 if (!on
&& f
->phys_cursor_x
< 0)
3402 /* If we're not updating, then we want to use the current frame's
3403 cursor position, not our local idea of where the cursor ought to be. */
3404 if (f
!= updating_frame
)
3406 curs_x
= FRAME_CURSOR_X (f
);
3407 curs_y
= FRAME_CURSOR_Y (f
);
3410 /* If cursor is currently being shown and we don't want it to be
3411 or it is in the wrong place,
3412 or we want a hollow box and it's not so, (pout!)
3414 if (f
->phys_cursor_x
>= 0
3416 || f
->phys_cursor_x
!= curs_x
3417 || f
->phys_cursor_y
!= curs_y
3418 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3419 && (f
!= x_highlight_frame
))))
3421 /* Erase the cursor by redrawing the character underneath it. */
3422 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3423 f
->phys_cursor_glyph
,
3424 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3425 f
->phys_cursor_x
= -1;
3428 /* If we want to show a cursor,
3429 or we want a box cursor and it's not so,
3430 write it in the right place. */
3432 && (f
->phys_cursor_x
< 0
3433 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3434 && f
== x_highlight_frame
)))
3436 f
->phys_cursor_glyph
3437 = ((current_glyphs
->enable
[curs_y
]
3438 && curs_x
< current_glyphs
->used
[curs_y
])
3439 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3441 if (f
!= x_highlight_frame
)
3444 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3448 x_draw_single_glyph (f
, curs_y
, curs_x
,
3449 f
->phys_cursor_glyph
, 2);
3450 f
->display
.x
->current_cursor
= filled_box_cursor
;
3453 f
->phys_cursor_x
= curs_x
;
3454 f
->phys_cursor_y
= curs_y
;
3457 if (updating_frame
!= f
)
3461 x_display_cursor (f
, on
)
3465 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3466 x_display_box_cursor (f
, on
);
3467 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3468 x_display_bar_cursor (f
, on
);
3470 /* Those are the only two we have implemented! */
3476 /* Refresh bitmap kitchen sink icon for frame F
3477 when we get an expose event for it. */
3483 /* Normally, the window manager handles this function. */
3484 #else /* ! defined (HAVE_X11) */
3487 if (f
->display
.x
->icon_bitmap_flag
)
3488 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3489 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3490 icon_bitmap
, GXcopy
, AllPlanes
);
3493 extern struct frame
*selected_frame
;
3494 struct Lisp_String
*str
;
3495 unsigned char *string
;
3498 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3500 if (f
->display
.x
->icon_label
!= string
)
3502 f
->display
.x
->icon_label
= string
;
3503 XChangeWindow (f
->display
.x
->icon_desc
,
3504 XQueryWidth (string
, icon_font_info
->id
) + 10,
3505 icon_font_info
->height
+ 10);
3508 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3509 str
->size
, icon_font_info
->id
,
3510 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
3513 #endif /* ! defined (HAVE_X11) */
3516 /* Make the x-window of frame F use the gnu icon bitmap. */
3525 if (FRAME_X_WINDOW (f
) == 0)
3530 XFreePixmap (x_current_display
, icon_bitmap
);
3533 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
3534 gnu_bits
, gnu_width
, gnu_height
);
3535 x_wm_set_icon_pixmap (f
, icon_bitmap
);
3536 f
->display
.x
->icon_bitmap_flag
= 1;
3537 #else /* ! defined (HAVE_X11) */
3538 if (f
->display
.x
->icon_desc
)
3540 XClearIconWindow (FRAME_X_WINDOW (f
));
3541 XDestroyWindow (f
->display
.x
->icon_desc
);
3544 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3545 0, 0, sink_width
, sink_height
,
3546 2, WhitePixmap
, (Pixmap
) NULL
);
3548 if (icon_window
== 0)
3551 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3552 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
3554 f
->display
.x
->icon_desc
= icon_window
;
3555 f
->display
.x
->icon_bitmap_flag
= 1;
3557 if (icon_bitmap
== 0)
3559 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
3560 #endif /* ! defined (HAVE_X11) */
3566 /* Make the x-window of frame F use a rectangle with text. */
3569 x_text_icon (f
, icon_name
)
3577 char *X_DefaultValue
;
3581 #define WhitePixel 1
3582 #endif /* WhitePixel */
3585 #define BlackPixel 0
3586 #endif /* BlackPixel */
3587 #endif /* HAVE_X11 */
3589 if (FRAME_X_WINDOW (f
) == 0)
3594 f
->display
.x
->icon_label
= icon_name
;
3596 if (! f
->display
.x
->icon_label
)
3597 f
->display
.x
->icon_label
= " *emacs* ";
3599 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
3600 (char *) f
->display
.x
->icon_label
);
3602 f
->display
.x
->icon_bitmap_flag
= 0;
3603 x_wm_set_icon_pixmap (f
, 0);
3604 #else /* ! defined (HAVE_X11) */
3605 if (icon_font_info
== 0)
3607 = XGetFont (XGetDefault (XDISPLAY
3608 (char *) XSTRING (Vinvocation_name
)->data
,
3611 if (f
->display
.x
->icon_desc
)
3613 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
3614 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
3618 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
3620 if (! f
->display
.x
->icon_label
)
3621 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
3623 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
3624 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
3625 f
->display
.x
->left_pos
,
3626 f
->display
.x
->top_pos
,
3627 width
+ 10, icon_font_info
->height
+ 10,
3628 2, BlackPixmap
, WhitePixmap
);
3630 if (icon_window
== 0)
3633 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
3634 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
3636 f
->display
.x
->icon_desc
= icon_window
;
3637 f
->display
.x
->icon_bitmap_flag
= 0;
3638 f
->display
.x
->icon_label
= 0;
3639 #endif /* ! defined (HAVE_X11) */
3644 /* Handling X errors. */
3646 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3647 X server's connection, or an error reported via the X protocol. */
3650 x_connection_closed ()
3655 shut_down_emacs (0);
3660 /* An X error handler which prints an error message and then kills
3661 Emacs. This is what's normally installed as Xlib's handler for
3664 x_error_quitter (display
, error
)
3670 /* Note that there is no real way portable across R3/R4 to get the
3671 original error handler. */
3673 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
3674 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
3675 buf
, error
->request_code
);
3677 /* While we're testing Emacs 19, we'll just dump core whenever we
3678 get an X error, so we can figure out why it happened. */
3681 x_connection_closed ();
3684 /* A handler for X IO errors which prints an error message and then
3685 kills Emacs. This is what is always installed as Xlib's handler
3688 x_io_error_quitter (display
)
3691 fprintf (stderr
, "Connection to X server %s lost.\n",
3692 XDisplayName (DisplayString (display
)));
3694 /* While we're testing Emacs 19, we'll just dump core whenever we
3695 get an X error, so we can figure out why it happened. */
3698 x_connection_closed ();
3701 /* A buffer for storing X error messages. */
3702 static char (*x_caught_error_message
)[200];
3704 /* An X error handler which stores the error message in
3705 x_caught_error_message. This is what's installed when
3706 x_catch_errors is in effect. */
3708 x_error_catcher (display
, error
)
3712 XGetErrorText (display
, error
->error_code
,
3713 *x_caught_error_message
, sizeof (*x_caught_error_message
));
3717 /* Begin trapping X errors.
3719 After calling this function, X protocol errors no longer cause
3720 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3722 Calling x_check_errors signals an Emacs error if an X error has
3723 occurred since the last call to x_catch_errors or x_check_errors.
3725 Calling x_uncatch_errors resumes the normal error handling. */
3727 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3732 /* Make sure any errors from previous requests have been dealt with. */
3733 XSync (x_current_display
, False
);
3735 /* Set up the error buffer. */
3736 x_caught_error_message
=
3737 (char (*)[]) xmalloc (sizeof (*x_caught_error_message
));
3738 (*x_caught_error_message
)[0] = '\0';
3740 /* Install our little error handler. */
3741 XHandleError (x_error_catcher
);
3744 /* If any X protocol errors have arrived since the last call to
3745 x_catch_errors or x_check_errors, signal an Emacs error using
3746 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3748 x_check_errors (format
)
3751 /* Make sure to catch any errors incurred so far. */
3752 XSync (x_current_display
, False
);
3754 if ((*x_caught_error_message
)[0])
3758 sprintf (buf
, format
, *x_caught_error_message
);
3759 xfree (x_caught_error_message
);
3761 x_uncatch_errors ();
3769 xfree (x_caught_error_message
);
3770 XHandleError (x_error_quitter
);
3774 static unsigned int x_wire_count
;
3777 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
3782 /* Changing the font of the frame. */
3784 /* Set the font of the x-window specified by frame F
3785 to the font named NEWNAME. This is safe to use
3786 even before F has an actual x-window. */
3790 /* A table of all the fonts we have already loaded. */
3791 static XFontStruct
**x_font_table
;
3793 /* The current capacity of x_font_table. */
3794 static int x_font_table_size
;
3796 /* The number of fonts actually stored in x_font_table.
3797 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3798 0 <= n_fonts <= x_font_table_size. */
3801 x_new_font (f
, fontname
)
3803 register char *fontname
;
3807 int n_matching_fonts
;
3808 XFontStruct
*font_info
;
3811 /* Get a list of all the fonts that match this name. Once we
3812 have a list of matching fonts, we compare them against the fonts
3813 we already have by comparing font ids. */
3814 font_names
= (char **) XListFontsWithInfo (x_current_display
, fontname
,
3815 1024, &n_matching_fonts
,
3817 /* If the server couldn't find any fonts whose named matched fontname,
3818 return an error code. */
3819 if (n_matching_fonts
== 0)
3822 /* See if we've already loaded a matching font. */
3827 for (i
= 0; i
< n_fonts
; i
++)
3828 for (j
= 0; j
< n_matching_fonts
; j
++)
3829 if (x_font_table
[i
]->fid
== font_info
[j
].fid
)
3837 /* If we have, just return it from the table. */
3839 f
->display
.x
->font
= x_font_table
[already_loaded
];
3841 /* Otherwise, load the font and add it to the table. */
3846 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
3850 /* Do we need to create the table? */
3851 if (x_font_table_size
== 0)
3853 x_font_table_size
= 16;
3855 = (XFontStruct
**) xmalloc (x_font_table_size
3856 * sizeof (x_font_table
[0]));
3858 /* Do we need to grow the table? */
3859 else if (n_fonts
>= x_font_table_size
)
3861 x_font_table_size
*= 2;
3863 = (XFontStruct
**) xrealloc (x_font_table
,
3865 * sizeof (x_font_table
[0])));
3868 f
->display
.x
->font
= x_font_table
[n_fonts
++] = font
;
3871 /* Free the information from XListFontsWithInfo. The data
3872 we actually retain comes from XLoadQueryFont. */
3873 XFreeFontInfo (font_names
, font_info
, n_matching_fonts
);
3875 /* Now make the frame display the given font. */
3876 if (FRAME_X_WINDOW (f
) != 0)
3878 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
3879 f
->display
.x
->font
->fid
);
3880 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
3881 f
->display
.x
->font
->fid
);
3882 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
3883 f
->display
.x
->font
->fid
);
3885 x_set_window_size (f
, f
->width
, f
->height
);
3890 #else /* ! defined (HAVE_X11) */
3891 x_new_font (f
, newname
)
3893 register char *newname
;
3898 temp
= XGetFont (newname
);
3899 if (temp
== (FONT_TYPE
*) 0)
3902 if (f
->display
.x
->font
)
3903 XLoseFont (f
->display
.x
->font
);
3905 f
->display
.x
->font
= temp
;
3907 if (FRAME_X_WINDOW (f
) != 0)
3908 x_set_window_size (f
, f
->width
, f
->height
);
3912 #endif /* ! defined (HAVE_X11) */
3914 /* X Window sizes and positions. */
3916 x_calc_absolute_position (f
)
3920 if (f
->display
.x
->left_pos
< 0)
3921 f
->display
.x
->left_pos
3922 = x_screen_width
- PIXEL_WIDTH (f
) + f
->display
.x
->left_pos
;
3924 if (f
->display
.x
->top_pos
< 0)
3925 f
->display
.x
->top_pos
3926 = x_screen_height
- PIXEL_HEIGHT (f
) + f
->display
.x
->top_pos
;
3927 #else /* ! defined (HAVE_X11) */
3928 WINDOWINFO_TYPE parentinfo
;
3930 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
3932 if (f
->display
.x
->left_pos
< 0)
3933 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
3934 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
3936 if (f
->display
.x
->top_pos
< 0)
3937 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
3938 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
3939 #endif /* ! defined (HAVE_X11) */
3942 x_set_offset (f
, xoff
, yoff
)
3944 register int xoff
, yoff
;
3946 f
->display
.x
->top_pos
= yoff
;
3947 f
->display
.x
->left_pos
= xoff
;
3948 x_calc_absolute_position (f
);
3951 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
3952 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
3954 x_wm_set_size_hint (f
, 0);
3955 #endif /* ! defined (HAVE_X11) */
3959 /* Call this to change the size of frame F's x-window. */
3961 x_set_window_size (f
, cols
, rows
)
3965 int pixelwidth
, pixelheight
;
3970 check_frame_size (f
, &rows
, &cols
);
3971 f
->display
.x
->vertical_scroll_bar_extra
=
3972 (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3973 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
3975 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3976 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3979 x_wm_set_size_hint (f
, 0);
3980 #endif /* ! defined (HAVE_X11) */
3981 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
3983 /* Now, strictly speaking, we can't be sure that this is accurate,
3984 but the window manager will get around to dealing with the size
3985 change request eventually, and we'll hear how it went when the
3986 ConfigureNotify event gets here.
3988 We could just not bother storing any of this information here,
3989 and let the ConfigureNotify event set everything up, but that
3990 might be kind of confusing to the lisp code, since size changes
3991 wouldn't be reported in the frame parameters until some random
3992 point in the future when the ConfigureNotify event arrives. */
3993 change_frame_size (f
, rows
, cols
, 0, 0);
3994 PIXEL_WIDTH (f
) = pixelwidth
;
3995 PIXEL_HEIGHT (f
) = pixelheight
;
3997 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3998 receive in the ConfigureNotify event; if we get what we asked
3999 for, then the event won't cause the screen to become garbaged, so
4000 we have to make sure to do it here. */
4001 SET_FRAME_GARBAGED (f
);
4008 x_set_resize_hint (f
)
4011 XSetResizeHint (FRAME_X_WINDOW (f
),
4012 2 * f
->display
.x
->internal_border_width
,
4013 2 * f
->display
.x
->internal_border_width
,
4014 FONT_WIDTH (f
->display
.x
->font
),
4015 FONT_HEIGHT (f
->display
.x
->font
));
4017 #endif /* HAVE_X11 */
4019 /* Mouse warping, focus shifting, raising and lowering. */
4021 x_set_mouse_position (f
, x
, y
)
4029 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4030 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4032 if (pix_x
< 0) pix_x
= 0;
4033 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4035 if (pix_y
< 0) pix_y
= 0;
4036 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4040 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4045 x_focus_on_frame (f
)
4050 /* I don't think that the ICCCM allows programs to do things like this
4051 without the interaction of the window manager. Whatever you end up
4052 doing with this code, do it to x_unfocus_frame too. */
4053 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4054 RevertToPointerRoot
, CurrentTime
);
4062 /* Look at the remarks in x_focus_on_frame. */
4063 if (x_focus_frame
== f
)
4064 XSetInputFocus (x_current_display
, PointerRoot
,
4065 RevertToPointerRoot
, CurrentTime
);
4069 #endif /* ! defined (HAVE_X11) */
4071 /* Raise frame F. */
4076 if (f
->async_visible
)
4079 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4085 /* Lower frame F. */
4090 if (f
->async_visible
)
4093 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4100 XTframe_raise_lower (f
, raise
)
4111 /* Change from withdrawn state to mapped state. */
4113 x_make_frame_visible (f
)
4120 if (! FRAME_VISIBLE_P (f
))
4123 if (! EQ (Vx_no_window_manager
, Qt
))
4124 x_wm_set_window_state (f
, NormalState
);
4126 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4127 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4128 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4129 #else /* ! defined (HAVE_X11) */
4130 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4131 if (f
->display
.x
->icon_desc
!= 0)
4132 XUnmapWindow (f
->display
.x
->icon_desc
);
4134 /* Handled by the MapNotify event for X11 */
4135 f
->async_visible
= 1;
4136 f
->async_iconified
= 0;
4138 /* NOTE: this may cause problems for the first frame. */
4140 #endif /* ! defined (HAVE_X11) */
4148 /* Change from mapped state to withdrawn state. */
4150 x_make_frame_invisible (f
)
4155 if (! f
->async_visible
)
4162 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4163 DefaultScreen (x_current_display
)))
4165 UNBLOCK_INPUT_RESIGNAL
;
4166 error ("can't notify window manager of window withdrawl");
4169 #else /* ! defined (HAVE_X11R4) */
4172 /* Tell the window manager what we're going to do. */
4173 if (! EQ (Vx_no_window_manager
, Qt
))
4177 unmap
.xunmap
.type
= UnmapNotify
;
4178 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4179 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4180 unmap
.xunmap
.from_configure
= False
;
4181 if (! XSendEvent (x_current_display
,
4182 DefaultRootWindow (x_current_display
),
4184 SubstructureRedirectMask
|SubstructureNotifyMask
,
4187 UNBLOCK_INPUT_RESIGNAL
;
4188 error ("can't notify window manager of withdrawal");
4192 /* Unmap the window ourselves. Cheeky! */
4193 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4195 #else /* ! defined (HAVE_X11) */
4197 XUnmapWindow (FRAME_X_WINDOW (f
));
4198 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4199 if (f
->display
.x
->icon_desc
!= 0)
4200 XUnmapWindow (f
->display
.x
->icon_desc
);
4202 #endif /* ! defined (HAVE_X11) */
4203 #endif /* ! defined (HAVE_X11R4) */
4209 /* Change window state from mapped to iconified. */
4216 if (f
->async_iconified
)
4222 /* Since we don't know which revision of X we're running, we'll use both
4223 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4225 /* X11R4: send a ClientMessage to the window manager using the
4226 WM_CHANGE_STATE type. */
4230 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4231 message
.xclient
.type
= ClientMessage
;
4232 message
.xclient
.message_type
= Xatom_wm_change_state
;
4233 message
.xclient
.format
= 32;
4234 message
.xclient
.data
.l
[0] = IconicState
;
4236 if (! XSendEvent (x_current_display
,
4237 DefaultRootWindow (x_current_display
),
4239 SubstructureRedirectMask
| SubstructureNotifyMask
,
4242 UNBLOCK_INPUT_RESIGNAL
;
4243 error ("Can't notify window manager of iconification.");
4247 /* X11R3: set the initial_state field of the window manager hints to
4249 x_wm_set_window_state (f
, IconicState
);
4251 f
->async_iconified
= 1;
4252 #else /* ! defined (HAVE_X11) */
4253 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4255 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4256 if (f
->display
.x
->icon_desc
!= 0)
4258 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4261 #endif /* ! defined (HAVE_X11) */
4267 /* Destroy the X window of frame F. */
4269 x_destroy_window (f
)
4274 if (f
->display
.x
->icon_desc
!= 0)
4275 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4276 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4279 xfree (f
->display
.x
);
4281 if (f
== x_focus_frame
)
4283 if (f
== x_highlight_frame
)
4284 x_highlight_frame
= 0;
4289 /* Manage event queues for X10. */
4293 /* Manage event queues.
4295 This code is only used by the X10 support.
4297 We cannot leave events in the X queue and get them when we are ready
4298 because X does not provide a subroutine to get only a certain kind
4299 of event but not block if there are no queued events of that kind.
4301 Therefore, we must examine events as they come in and copy events
4302 of certain kinds into our private queues.
4304 All ExposeRegion events are put in x_expose_queue.
4305 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4308 /* Write the event *P_XREP into the event queue *QUEUE.
4309 If the queue is full, do nothing, but return nonzero. */
4312 enqueue_event (p_xrep
, queue
)
4313 register XEvent
*p_xrep
;
4314 register struct event_queue
*queue
;
4316 int newindex
= queue
->windex
+ 1;
4317 if (newindex
== EVENT_BUFFER_SIZE
)
4319 if (newindex
== queue
->rindex
)
4321 queue
->xrep
[queue
->windex
] = *p_xrep
;
4322 queue
->windex
= newindex
;
4326 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4327 If *QUEUE is empty, do nothing and return 0. */
4330 dequeue_event (p_xrep
, queue
)
4331 register XEvent
*p_xrep
;
4332 register struct event_queue
*queue
;
4334 if (queue
->windex
== queue
->rindex
)
4336 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4337 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4342 /* Return the number of events buffered in *QUEUE. */
4345 queue_event_count (queue
)
4346 register struct event_queue
*queue
;
4348 int tem
= queue
->windex
- queue
->rindex
;
4351 return EVENT_BUFFER_SIZE
+ tem
;
4354 /* Return nonzero if mouse input is pending. */
4357 mouse_event_pending_p ()
4359 return queue_event_count (&x_mouse_queue
);
4361 #endif /* HAVE_X11 */
4363 /* Setting window manager hints. */
4367 x_wm_set_size_hint (f
, prompting
)
4371 XSizeHints size_hints
;
4372 Window window
= FRAME_X_WINDOW (f
);
4374 size_hints
.flags
= PResizeInc
| PMinSize
| PMaxSize
;
4376 flexlines
= f
->height
;
4378 size_hints
.x
= f
->display
.x
->left_pos
;
4379 size_hints
.y
= f
->display
.x
->top_pos
;
4380 size_hints
.height
= PIXEL_HEIGHT (f
);
4381 size_hints
.width
= PIXEL_WIDTH (f
);
4382 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
4383 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
4384 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
4385 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
4388 int base_width
, base_height
;
4390 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
4391 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
4394 int min_rows
= 0, min_cols
= 0;
4395 check_frame_size (f
, &min_rows
, &min_cols
);
4397 /* The window manager uses the base width hints to calculate the
4398 current number of rows and columns in the frame while
4399 resizing; min_width and min_height aren't useful for this
4400 purpose, since they might not give the dimensions for a
4401 zero-row, zero-column frame.
4403 We use the base_width and base_height members if we have
4404 them; otherwise, we set the min_width and min_height members
4405 to the size for a zero x zero frame. */
4408 size_hints
.flags
|= PBaseSize
;
4409 size_hints
.base_width
= base_width
;
4410 size_hints
.base_height
= base_height
;
4411 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
4412 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
4414 size_hints
.min_width
= base_width
;
4415 size_hints
.min_height
= base_height
;
4422 size_hints
.flags
|= prompting
;
4425 XSizeHints hints
; /* Sometimes I hate X Windows... */
4427 XGetNormalHints (x_current_display
, window
, &hints
);
4428 if (hints
.flags
& PSize
)
4429 size_hints
.flags
|= PSize
;
4430 if (hints
.flags
& PPosition
)
4431 size_hints
.flags
|= PPosition
;
4432 if (hints
.flags
& USPosition
)
4433 size_hints
.flags
|= USPosition
;
4434 if (hints
.flags
& USSize
)
4435 size_hints
.flags
|= USSize
;
4439 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
4441 XSetNormalHints (x_current_display
, window
, &size_hints
);
4445 /* Used for IconicState or NormalState */
4446 x_wm_set_window_state (f
, state
)
4450 Window window
= FRAME_X_WINDOW (f
);
4452 f
->display
.x
->wm_hints
.flags
|= StateHint
;
4453 f
->display
.x
->wm_hints
.initial_state
= state
;
4455 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4458 x_wm_set_icon_pixmap (f
, icon_pixmap
)
4462 Window window
= FRAME_X_WINDOW (f
);
4466 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
4467 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
4470 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
4472 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4475 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4479 Window window
= FRAME_X_WINDOW (f
);
4481 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4482 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4483 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4485 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
4489 /* Initialization. */
4492 x_term_init (display_name
)
4498 extern int old_fcntl_owner
;
4499 #endif /* ! defined (F_SETOWN) */
4501 x_focus_frame
= x_highlight_frame
= 0;
4503 x_current_display
= XOpenDisplay (display_name
);
4504 if (x_current_display
== 0)
4505 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4510 int hostname_size
= 256;
4512 hostname
= (char *) xmalloc (hostname_size
);
4515 XSetAfterFunction (x_current_display
, x_trace_wire
);
4518 /* Try to get the host name; if the buffer is too short, try
4519 again. Apparently, the only indication gethostname gives of
4520 whether the buffer was large enough is the presence or absence
4521 of a '\0' in the string. Eech. */
4524 gethostname (hostname
, hostname_size
- 1);
4525 hostname
[hostname_size
- 1] = '\0';
4527 /* Was the buffer large enough for gethostname to store the '\0'? */
4528 if (strlen (hostname
) < hostname_size
- 1)
4531 hostname_size
<<= 1;
4532 hostname
= (char *) xrealloc (hostname
, hostname_size
);
4534 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4537 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
4540 /* Figure out which modifier bits mean what. */
4541 x_find_modifier_meanings ();
4543 /* Get the scroll bar cursor. */
4544 x_vertical_scroll_bar_cursor
4545 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
4548 /* Watch for PropertyNotify events on the root window; we use them
4549 to figure out when to invalidate our cache of the cut buffers. */
4550 x_watch_cut_buffer_cache ();
4553 if (ConnectionNumber (x_current_display
) != 0)
4555 dup2 (ConnectionNumber (x_current_display
), 0);
4557 #ifndef SYSV_STREAMS
4558 /* Streams somehow keeps track of which descriptor number
4559 is being used to talk to X. So it is not safe to substitute
4560 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4561 close (ConnectionNumber (x_current_display
));
4562 ConnectionNumber (x_current_display
) = 0; /* Looks a little strange?
4563 * check the def of the macro;
4564 * it is a genuine lvalue */
4565 #endif /* SYSV_STREAMS */
4568 #endif /* ! defined (HAVE_X11) */
4571 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
4572 #ifdef F_SETOWN_SOCK_NEG
4573 fcntl (0, F_SETOWN
, -getpid ()); /* stdin is a socket here */
4574 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4575 fcntl (0, F_SETOWN
, getpid ());
4576 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4577 #endif /* ! defined (F_SETOWN) */
4581 #endif /* ! defined (SIGIO) */
4583 /* Must use interrupt input because we cannot otherwise
4584 arrange for C-g to be noticed immediately.
4585 We cannot connect it to SIGINT. */
4586 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
4588 expose_all_windows
= 0;
4590 clear_frame_hook
= XTclear_frame
;
4591 clear_end_of_line_hook
= XTclear_end_of_line
;
4592 ins_del_lines_hook
= XTins_del_lines
;
4593 change_line_highlight_hook
= XTchange_line_highlight
;
4594 insert_glyphs_hook
= XTinsert_glyphs
;
4595 write_glyphs_hook
= XTwrite_glyphs
;
4596 delete_glyphs_hook
= XTdelete_glyphs
;
4597 ring_bell_hook
= XTring_bell
;
4598 reset_terminal_modes_hook
= XTreset_terminal_modes
;
4599 set_terminal_modes_hook
= XTset_terminal_modes
;
4600 update_begin_hook
= XTupdate_begin
;
4601 update_end_hook
= XTupdate_end
;
4602 set_terminal_window_hook
= XTset_terminal_window
;
4603 read_socket_hook
= XTread_socket
;
4604 cursor_to_hook
= XTcursor_to
;
4605 reassert_line_highlight_hook
= XTreassert_line_highlight
;
4606 mouse_position_hook
= XTmouse_position
;
4607 frame_rehighlight_hook
= XTframe_rehighlight
;
4608 frame_raise_lower_hook
= XTframe_raise_lower
;
4609 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
4610 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
4611 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
4612 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
4614 scroll_region_ok
= 1; /* we'll scroll partial frames */
4615 char_ins_del_ok
= 0; /* just as fast to write the line */
4616 line_ins_del_ok
= 1; /* we'll just blt 'em */
4617 fast_clear_end_of_line
= 1; /* X does this well */
4618 memory_below_frame
= 0; /* we don't remember what scrolls
4622 /* Note that there is no real way portable across R3/R4 to get the
4623 original error handler. */
4624 XHandleError (x_error_quitter
);
4625 XHandleIOError (x_io_error_quitter
);
4627 /* Disable Window Change signals; they are handled by X events. */
4629 signal (SIGWINCH
, SIG_DFL
);
4630 #endif /* ! defined (SIGWINCH) */
4632 signal (SIGPIPE
, x_connection_closed
);
4638 staticpro (&last_mouse_scroll_bar
);
4640 #endif /* ! defined (HAVE_X11) */
4641 #endif /* ! defined (HAVE_X_WINDOWS) */