1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 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. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
60 #ifndef INCLUDED_FCNTL
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
71 #include "dispextern.h"
72 #include "termhooks.h"
84 #include "intervals.h"
87 extern void free_frame_menubar ();
88 extern void _XEditResCheckMessages ();
89 #endif /* USE_X_TOOLKIT */
92 #define x_any_window_to_frame x_window_to_frame
93 #define x_top_window_to_frame x_window_to_frame
97 #ifndef XtNinitialState
98 #define XtNinitialState "initialState"
102 #define min(a,b) ((a)<(b) ? (a) : (b))
103 #define max(a,b) ((a)>(b) ? (a) : (b))
105 /* This is a chain of structures for all the X displays currently in use. */
106 struct x_display_info
*x_display_list
;
108 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
109 one for each element of x_display_list and in the same order.
110 NAME is the name of the frame.
111 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
112 Lisp_Object x_display_name_list
;
114 /* Frame being updated by update_frame. This is declared in term.c.
115 This is set by update_begin and looked at by all the
116 XT functions. It is zero while not inside an update.
117 In that case, the XT functions assume that `selected_frame'
118 is the frame to apply to. */
119 extern struct frame
*updating_frame
;
121 /* The frame (if any) which has the X window that has keyboard focus.
122 Zero if none. This is examined by Ffocus_frame in frame.c. Note
123 that a mere EnterNotify event can set this; if you need to know the
124 last frame specified in a FocusIn or FocusOut event, use
125 x_focus_event_frame. */
126 struct frame
*x_focus_frame
;
128 /* This is a frame waiting to be autoraised, within XTread_socket. */
129 struct frame
*pending_autoraise_frame
;
131 /* The last frame mentioned in a FocusIn or FocusOut event. This is
132 separate from x_focus_frame, because whether or not LeaveNotify
133 events cause us to lose focus depends on whether or not we have
134 received a FocusIn event for it. */
135 struct frame
*x_focus_event_frame
;
137 /* The frame which currently has the visual highlight, and should get
138 keyboard input (other sorts of input have the frame encoded in the
139 event). It points to the X focus frame's selected window's
140 frame. It differs from x_focus_frame when we're using a global
142 static struct frame
*x_highlight_frame
;
145 /* The application context for Xt use. */
146 XtAppContext Xt_app_con
;
149 /* During an update, maximum vpos for ins/del line operations to affect. */
151 static int flexlines
;
153 /* During an update, nonzero if chars output now should be highlighted. */
155 static int highlight
;
157 /* Nominal cursor position -- where to draw output.
158 During an update, these are different from the cursor-box position. */
165 In order to avoid asking for motion events and then throwing most
166 of them away or busy-polling the server for mouse positions, we ask
167 the server for pointer motion hints. This means that we get only
168 one event per group of mouse movements. "Groups" are delimited by
169 other kinds of events (focus changes and button clicks, for
170 example), or by XQueryPointer calls; when one of these happens, we
171 get another MotionNotify event the next time the mouse moves. This
172 is at least as efficient as getting motion events when mouse
173 tracking is on, and I suspect only negligibly worse when tracking
176 The silly O'Reilly & Associates Nutshell guides barely document
177 pointer motion hints at all (I think you have to infer how they
178 work from an example), and the description of XQueryPointer doesn't
179 mention that calling it causes you to get another motion hint from
180 the server, which is very important. */
182 /* Where the mouse was last time we reported a mouse event. */
183 static FRAME_PTR last_mouse_frame
;
184 static XRectangle last_mouse_glyph
;
186 /* The scroll bar in which the last X motion event occurred.
188 If the last X motion event occurred in a scroll bar, we set this
189 so XTmouse_position can know whether to report a scroll bar motion or
192 If the last X motion event didn't occur in a scroll bar, we set this
193 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
194 static Lisp_Object last_mouse_scroll_bar
;
196 /* This is a hack. We would really prefer that XTmouse_position would
197 return the time associated with the position it returns, but there
198 doesn't seem to be any way to wrest the timestamp from the server
199 along with the position query. So, we just keep track of the time
200 of the last movement we received, and return that in hopes that
201 it's somewhat accurate. */
202 static Time last_mouse_movement_time
;
204 /* Incremented by XTread_socket whenever it really tries to read events. */
206 static int volatile input_signal_count
;
208 static int input_signal_count
;
211 /* Used locally within XTread_socket. */
212 static int x_noop_count
;
214 /* Initial values of argv and argc. */
215 extern char **initial_argv
;
216 extern int initial_argc
;
218 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
220 /* Tells if a window manager is present or not. */
222 extern Lisp_Object Vx_no_window_manager
;
224 /* Nonzero enables some debugging for the X interface code. */
227 extern Lisp_Object Qface
, Qmouse_face
;
231 /* A mask of extra modifier bits to put into every keyboard char. */
232 extern int extra_keyboard_modifiers
;
234 extern XrmDatabase
x_load_resources ();
236 void x_delete_display ();
238 static void flashback ();
239 static void redraw_previous_char ();
240 static void redraw_following_char ();
241 static unsigned int x_x_to_emacs_modifiers ();
243 static int fast_find_position ();
244 static void note_mouse_highlight ();
245 static void clear_mouse_face ();
246 static void show_mouse_face ();
247 static void do_line_dance ();
249 static int XTcursor_to ();
250 static int XTclear_end_of_line ();
251 static int x_io_error_quitter ();
253 /* Return the struct x_display_info corresponding to DPY. */
255 struct x_display_info
*
256 x_display_info_for_display (dpy
)
259 struct x_display_info
*dpyinfo
;
261 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
262 if (dpyinfo
->display
== dpy
)
268 /* Starting and ending updates.
270 These hooks are called by update_frame at the beginning and end
271 of a frame update. We record in `updating_frame' the identity
272 of the frame being updated, so that the XT... functions do not
273 need to take a frame as argument. Most of the XT... functions
274 should never be called except during an update, the only exceptions
275 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
286 flexlines
= f
->height
;
291 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
293 /* Don't do highlighting for mouse motion during the update. */
294 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
296 /* If the frame needs to be redrawn,
297 simply forget about any prior mouse highlighting. */
298 if (FRAME_GARBAGED_P (f
))
299 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
301 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
303 int firstline
, lastline
, i
;
304 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
306 /* Find the first, and the last+1, lines affected by redisplay. */
307 for (firstline
= 0; firstline
< f
->height
; firstline
++)
308 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
311 lastline
= f
->height
;
312 for (i
= f
->height
- 1; i
>= 0; i
--)
314 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
320 /* Can we tell that this update does not affect the window
321 where the mouse highlight is? If so, no need to turn off.
322 Likewise, don't do anything if the frame is garbaged;
323 in that case, the FRAME_CURRENT_GLYPHS that we would use
324 are all wrong, and we will redisplay that line anyway. */
325 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
326 || lastline
< XFASTINT (w
->top
)))
327 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
343 x_display_cursor (f
, 1);
345 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
346 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
348 /* This fails in the case of having updated only the echo area
349 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
350 has no relation to the current contents, and its charstarts
351 have no relation to the contents of the window-buffer.
352 I don't know a clean way to check
353 for that case. window_end_valid isn't set up yet. */
354 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
355 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
356 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
359 XFlush (FRAME_X_DISPLAY (f
));
363 /* This is called after a redisplay on frame F. */
366 XTframe_up_to_date (f
)
369 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
370 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
372 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
373 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
374 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
375 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
379 /* External interface to control of standout mode.
380 Call this when about to modify line at position VPOS
381 and not change whether it is highlighted. */
383 XTreassert_line_highlight (new, vpos
)
389 /* Call this when about to modify line at position VPOS
390 and change whether it is highlighted. */
393 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
394 int new_highlight
, vpos
, first_unused_hpos
;
396 highlight
= new_highlight
;
397 XTcursor_to (vpos
, 0);
398 XTclear_end_of_line (updating_frame
->width
);
401 /* This is used when starting Emacs and when restarting after suspend.
402 When starting Emacs, no X window is mapped. And nothing must be done
403 to Emacs's own window if it is suspended (though that rarely happens). */
406 XTset_terminal_modes ()
410 /* This is called when exiting or suspending Emacs.
411 Exiting will make the X-windows go away, and suspending
412 requires no action. */
415 XTreset_terminal_modes ()
417 /* XTclear_frame (); */
420 /* Set the nominal cursor position of the frame.
421 This is where display update commands will take effect.
422 This does not affect the place where the cursor-box is displayed. */
425 XTcursor_to (row
, col
)
426 register int row
, col
;
434 if (updating_frame
== 0)
437 x_display_cursor (selected_frame
, 1);
438 XFlush (FRAME_X_DISPLAY (selected_frame
));
443 /* Display a sequence of N glyphs found at GP.
444 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
445 HL is 1 if this text is highlighted, 2 if the cursor is on it,
446 3 if should appear in its mouse-face.
447 JUST_FOREGROUND if 1 means draw only the foreground;
448 don't alter the background.
450 FONT is the default font to use (for glyphs whose font-code is 0).
452 Since the display generation code is responsible for calling
453 compute_char_face and compute_glyph_face on everything it puts in
454 the display structure, we can assume that the face code on each
455 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
456 to which we can actually apply intern_face.
457 Call this function with input blocked. */
460 /* This is the multi-face code. */
463 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
466 register GLYPH
*gp
; /* Points to first GLYPH. */
467 register int n
; /* Number of glyphs to display. */
471 /* Holds characters to be displayed. */
472 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
473 register char *cp
; /* Steps through buf[]. */
474 register int tlen
= GLYPH_TABLE_LENGTH
;
475 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
476 Window window
= FRAME_X_WINDOW (f
);
477 int orig_left
= left
;
481 /* Get the face-code of the next GLYPH. */
485 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
486 cf
= FAST_GLYPH_FACE (g
);
488 /* Find the run of consecutive glyphs with the same face-code.
489 Extract their character codes into BUF. */
494 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
495 if (FAST_GLYPH_FACE (g
) != cf
)
498 *cp
++ = FAST_GLYPH_CHAR (g
);
503 /* LEN gets the length of the run. */
506 /* Now output this run of chars, with the font and pixel values
507 determined by the face code CF. */
509 struct face
*face
= FRAME_DEFAULT_FACE (f
);
510 XFontStruct
*font
= FACE_FONT (face
);
511 GC gc
= FACE_GC (face
);
514 /* HL = 3 means use a mouse face previously chosen. */
516 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
518 /* First look at the face of the text itself. */
521 /* It's possible for the display table to specify
522 a face code that is out of range. Use 0 in that case. */
523 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
524 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
528 face
= FRAME_MODE_LINE_FACE (f
);
530 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
531 font
= FACE_FONT (face
);
533 if (FACE_STIPPLE (face
))
537 /* Then comes the distinction between modeline and normal text. */
542 face
= FRAME_MODE_LINE_FACE (f
);
543 font
= FACE_FONT (face
);
545 if (FACE_STIPPLE (face
))
549 #define FACE_DEFAULT (~0)
551 /* Now override that if the cursor's on this character. */
554 /* The cursor overrides stippling. */
558 || (int) face
->font
== FACE_DEFAULT
559 || face
->font
== f
->display
.x
->font
)
560 && face
->background
== f
->display
.x
->background_pixel
561 && face
->foreground
== f
->display
.x
->foreground_pixel
)
563 gc
= f
->display
.x
->cursor_gc
;
565 /* Cursor on non-default face: must merge. */
571 xgcv
.background
= f
->display
.x
->cursor_pixel
;
572 xgcv
.foreground
= face
->background
;
573 /* If the glyph would be invisible,
574 try a different foreground. */
575 if (xgcv
.foreground
== xgcv
.background
)
576 xgcv
.foreground
= face
->foreground
;
577 if (xgcv
.foreground
== xgcv
.background
)
578 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
579 if (xgcv
.foreground
== xgcv
.background
)
580 xgcv
.foreground
= face
->foreground
;
581 /* Make sure the cursor is distinct from text in this face. */
582 if (xgcv
.background
== face
->background
583 && xgcv
.foreground
== face
->foreground
)
585 xgcv
.background
= face
->foreground
;
586 xgcv
.foreground
= face
->background
;
588 xgcv
.font
= face
->font
->fid
;
589 xgcv
.graphics_exposures
= 0;
590 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
591 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
592 XChangeGC (FRAME_X_DISPLAY (f
),
593 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
596 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
597 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
598 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
600 /* If this code is restored, it must also reset to the default stipple
602 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
603 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
608 if ((int) font
== FACE_DEFAULT
)
609 font
= f
->display
.x
->font
;
612 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
613 left
, top
+ FONT_BASE (font
), buf
, len
);
618 /* Turn stipple on. */
619 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
621 /* Draw stipple on background. */
622 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
624 FONT_WIDTH (font
) * len
,
627 /* Turn stipple off. */
628 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
630 /* Draw the text, solidly, onto the stipple pattern. */
631 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
632 left
, top
+ FONT_BASE (font
), buf
, len
);
635 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
636 left
, top
+ FONT_BASE (font
), buf
, len
);
638 /* Clear the rest of the line's height. */
639 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
640 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
641 top
+ FONT_HEIGHT (font
),
642 FONT_WIDTH (font
) * len
,
643 /* This is how many pixels of height
645 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
649 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
650 which often is not up to date yet. */
651 if (!just_foreground
)
653 if (left
== orig_left
)
654 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
655 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
657 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
658 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
662 /* We should probably check for XA_UNDERLINE_POSITION and
663 XA_UNDERLINE_THICKNESS properties on the font, but let's
664 just get the thing working, and come back to that. */
666 int underline_position
= 1;
668 if (font
->descent
<= underline_position
)
669 underline_position
= font
->descent
- 1;
672 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
676 + underline_position
),
677 len
* FONT_WIDTH (font
), 1);
680 left
+= len
* FONT_WIDTH (font
);
687 /* This is the old single-face code. */
690 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
693 register GLYPH
*gp
; /* Points to first GLYPH. */
694 register int n
; /* Number of glyphs to display. */
699 Window window
= FRAME_X_WINDOW (f
);
700 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
701 : (hl
? f
->display
.x
->reverse_gc
702 : f
->display
.x
->normal_gc
));
704 if (sizeof (GLYPH
) == sizeof (XChar2b
))
705 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
706 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
707 else if (sizeof (GLYPH
) == sizeof (unsigned char))
708 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
709 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
711 /* What size of glyph ARE you using? And does X have a function to
717 /* Output some text at the nominal frame cursor position.
718 Advance the cursor over the text.
719 Output LEN glyphs at START.
721 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
722 controls the pixel values used for foreground and background. */
725 XTwrite_glyphs (start
, len
)
726 register GLYPH
*start
;
729 register int temp_length
;
740 /* If not within an update,
741 output at the frame's visible cursor. */
742 curs_x
= f
->cursor_x
;
743 curs_y
= f
->cursor_y
;
747 CHAR_TO_PIXEL_COL (f
, curs_x
),
748 CHAR_TO_PIXEL_ROW (f
, curs_y
),
749 start
, len
, highlight
, 0);
751 /* If we drew on top of the cursor, note that it is turned off. */
752 if (curs_y
== f
->phys_cursor_y
753 && curs_x
<= f
->phys_cursor_x
754 && curs_x
+ len
> f
->phys_cursor_x
)
755 f
->phys_cursor_x
= -1;
757 if (updating_frame
== 0)
760 x_display_cursor (f
, 1);
769 /* Clear to the end of the line.
770 Erase the current text line from the nominal cursor position (inclusive)
771 to column FIRST_UNUSED (exclusive). The idea is that everything
772 from FIRST_UNUSED onward is already erased. */
775 XTclear_end_of_line (first_unused
)
776 register int first_unused
;
778 struct frame
*f
= updating_frame
;
784 if (curs_y
< 0 || curs_y
>= f
->height
)
786 if (first_unused
<= 0)
789 if (first_unused
>= f
->width
)
790 first_unused
= f
->width
;
796 /* Notice if the cursor will be cleared by this operation. */
797 if (curs_y
== f
->phys_cursor_y
798 && curs_x
<= f
->phys_cursor_x
799 && f
->phys_cursor_x
< first_unused
)
800 f
->phys_cursor_x
= -1;
802 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
803 CHAR_TO_PIXEL_COL (f
, curs_x
),
804 CHAR_TO_PIXEL_ROW (f
, curs_y
),
805 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
806 f
->display
.x
->line_height
, False
);
808 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
818 struct frame
*f
= updating_frame
;
823 f
->phys_cursor_x
= -1; /* Cursor not visible. */
824 curs_x
= 0; /* Nominal cursor position is top left. */
829 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
831 /* We have to clear the scroll bars, too. If we have changed
832 colors or something like that, then they should be notified. */
833 x_scroll_bar_clear (f
);
835 XFlush (FRAME_X_DISPLAY (f
));
840 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
841 always contain the right glyphs to use.
843 It also needs to be changed to look at the details of the font and
844 see whether there is really overlap, and do nothing when there is
845 not. This can use font_char_overlap_left and font_char_overlap_right,
846 but just how to use them is not clear. */
848 /* Erase the character (if any) at the position just before X, Y in frame F,
849 then redraw it and the character before it.
850 This is necessary when we erase starting at X,
851 in case the character after X overlaps into the one before X.
852 Call this function with input blocked. */
855 redraw_previous_char (f
, x
, y
, highlight_flag
)
860 /* Erase the character before the new ones, in case
861 what was here before overlaps it.
862 Reoutput that character, and the previous character
863 (in case the previous character overlaps it). */
869 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
870 CHAR_TO_PIXEL_COL (f
, x
- 1),
871 CHAR_TO_PIXEL_ROW (f
, y
),
872 FONT_WIDTH (f
->display
.x
->font
),
873 f
->display
.x
->line_height
, False
);
875 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
876 CHAR_TO_PIXEL_ROW (f
, y
),
877 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
878 x
- start_x
, highlight_flag
, 1);
882 /* Erase the character (if any) at the position X, Y in frame F,
883 then redraw it and the character after it.
884 This is necessary when we erase endng at X,
885 in case the character after X overlaps into the one before X.
886 Call this function with input blocked. */
889 redraw_following_char (f
, x
, y
, highlight_flag
)
894 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
895 /* Erase the character after the new ones, in case
896 what was here before overlaps it.
897 Reoutput that character, and the following character
898 (in case the following character overlaps it). */
900 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
905 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
906 CHAR_TO_PIXEL_COL (f
, x
),
907 CHAR_TO_PIXEL_ROW (f
, y
),
908 FONT_WIDTH (f
->display
.x
->font
),
909 f
->display
.x
->line_height
, False
);
911 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
912 CHAR_TO_PIXEL_ROW (f
, y
),
913 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
914 end_x
- x
, highlight_flag
, 1);
919 #if 0 /* Not in use yet */
921 /* Return 1 if character C in font F extends past its left edge. */
924 font_char_overlap_left (font
, c
)
930 /* Find the bounding-box info for C. */
931 if (font
->per_char
== 0)
932 s
= &font
->max_bounds
;
935 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
938 /* Decode char into row number (byte 1) and code within row (byte 2). */
941 if (!(within
>= font
->min_char_or_byte2
942 && within
<= font
->max_char_or_byte2
943 && row
>= font
->min_byte1
944 && row
<= font
->max_byte1
))
946 /* If char is out of range, try the font's default char instead. */
947 c
= font
->default_char
;
948 row
= c
>> (INTBITS
- 8);
951 if (!(within
>= font
->min_char_or_byte2
952 && within
<= font
->max_char_or_byte2
953 && row
>= font
->min_byte1
954 && row
<= font
->max_byte1
))
955 /* Still out of range means this char does not overlap. */
958 /* We found the info for this char. */
959 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
963 return (s
&& s
->lbearing
< 0);
966 /* Return 1 if character C in font F extends past its right edge. */
969 font_char_overlap_right (font
, c
)
975 /* Find the bounding-box info for C. */
976 if (font
->per_char
== 0)
977 s
= &font
->max_bounds
;
980 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
983 /* Decode char into row number (byte 1) and code within row (byte 2). */
986 if (!(within
>= font
->min_char_or_byte2
987 && within
<= font
->max_char_or_byte2
988 && row
>= font
->min_byte1
989 && row
<= font
->max_byte1
))
991 /* If char is out of range, try the font's default char instead. */
992 c
= font
->default_char
;
993 row
= c
>> (INTBITS
- 8);
996 if (!(within
>= font
->min_char_or_byte2
997 && within
<= font
->max_char_or_byte2
998 && row
>= font
->min_byte1
999 && row
<= font
->max_byte1
))
1000 /* Still out of range means this char does not overlap. */
1003 /* We found the info for this char. */
1004 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1008 return (s
&& s
->rbearing
>= s
->width
);
1012 /* Invert the middle quarter of the frame for .15 sec. */
1014 /* We use the select system call to do the waiting, so we have to make sure
1015 it's available. If it isn't, we just won't do visual bells. */
1016 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1018 /* Subtract the `struct timeval' values X and Y,
1019 storing the result in RESULT.
1020 Return 1 if the difference is negative, otherwise 0. */
1023 timeval_subtract (result
, x
, y
)
1024 struct timeval
*result
, x
, y
;
1026 /* Perform the carry for the later subtraction by updating y.
1027 This is safer because on some systems
1028 the tv_sec member is unsigned. */
1029 if (x
.tv_usec
< y
.tv_usec
)
1031 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1032 y
.tv_usec
-= 1000000 * nsec
;
1035 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1037 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1038 y
.tv_usec
+= 1000000 * nsec
;
1042 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1043 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1044 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1046 /* Return indication of whether the result should be considered negative. */
1047 return x
.tv_sec
< y
.tv_sec
;
1058 /* Create a GC that will use the GXxor function to flip foreground pixels
1059 into background pixels. */
1063 values
.function
= GXxor
;
1064 values
.foreground
= (f
->display
.x
->foreground_pixel
1065 ^ f
->display
.x
->background_pixel
);
1067 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1068 GCFunction
| GCForeground
, &values
);
1072 int width
= PIXEL_WIDTH (f
);
1073 int height
= PIXEL_HEIGHT (f
);
1075 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1076 width
/4, height
/4, width
/2, height
/2);
1077 XFlush (FRAME_X_DISPLAY (f
));
1080 struct timeval wakeup
, now
;
1082 EMACS_GET_TIME (wakeup
);
1084 /* Compute time to wait until, propagating carry from usecs. */
1085 wakeup
.tv_usec
+= 150000;
1086 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1087 wakeup
.tv_usec
%= 1000000;
1089 /* Keep waiting until past the time wakeup. */
1092 struct timeval timeout
;
1094 EMACS_GET_TIME (timeout
);
1096 /* In effect, timeout = wakeup - timeout.
1097 Break if result would be negative. */
1098 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1101 /* Try to wait that long--but we might wake up sooner. */
1102 select (0, 0, 0, 0, &timeout
);
1106 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1107 width
/4, height
/4, width
/2, height
/2);
1108 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1109 XFlush (FRAME_X_DISPLAY (f
));
1119 /* Make audible bell. */
1121 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1125 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1128 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1130 XTflash (selected_frame
);
1136 XFlush (FRAME_X_DISPLAY (selected_frame
));
1141 /* Insert and delete character.
1142 These are not supposed to be used because we are supposed to turn
1143 off the feature of using them. */
1146 XTinsert_glyphs (start
, len
)
1147 register char *start
;
1160 /* Specify how many text lines, from the top of the window,
1161 should be affected by insert-lines and delete-lines operations.
1162 This, and those operations, are used only within an update
1163 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1166 XTset_terminal_window (n
)
1169 if (updating_frame
== 0)
1172 if ((n
<= 0) || (n
> updating_frame
->height
))
1173 flexlines
= updating_frame
->height
;
1178 /* These variables need not be per frame
1179 because redisplay is done on a frame-by-frame basis
1180 and the line dance for one frame is finished before
1181 anything is done for anoter frame. */
1183 /* Array of line numbers from cached insert/delete operations.
1184 line_dance[i] is the old position of the line that we want
1185 to move to line i, or -1 if we want a blank line there. */
1186 static int *line_dance
;
1188 /* Allocated length of that array. */
1189 static int line_dance_len
;
1191 /* Flag indicating whether we've done any work. */
1192 static int line_dance_in_progress
;
1194 /* Perform an insert-lines or delete-lines operation,
1195 inserting N lines or deleting -N lines at vertical position VPOS. */
1196 XTins_del_lines (vpos
, n
)
1199 register int fence
, i
;
1201 if (vpos
>= flexlines
)
1204 if (!line_dance_in_progress
)
1206 int ht
= updating_frame
->height
;
1207 if (ht
> line_dance_len
)
1209 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1210 line_dance_len
= ht
;
1212 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1213 line_dance_in_progress
= 1;
1217 if (n
> flexlines
- vpos
)
1218 n
= flexlines
- vpos
;
1220 for (i
= flexlines
; --i
>= fence
;)
1221 line_dance
[i
] = line_dance
[i
-n
];
1222 for (i
= fence
; --i
>= vpos
;)
1228 if (n
> flexlines
- vpos
)
1229 n
= flexlines
- vpos
;
1230 fence
= flexlines
- n
;
1231 for (i
= vpos
; i
< fence
; ++i
)
1232 line_dance
[i
] = line_dance
[i
+ n
];
1233 for (i
= fence
; i
< flexlines
; ++i
)
1238 /* Here's where we actually move the pixels around.
1239 Must be called with input blocked. */
1243 register int i
, j
, distance
;
1244 register struct frame
*f
;
1248 /* Must check this flag first. If it's not set, then not only is the
1249 array uninitialized, but we might not even have a frame. */
1250 if (!line_dance_in_progress
)
1258 intborder
= f
->display
.x
->internal_border_width
;
1260 x_display_cursor (updating_frame
, 0);
1262 for (i
= 0; i
< ht
; ++i
)
1263 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1265 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1266 && line_dance
[j
]-j
== distance
); ++j
);
1267 /* Copy [i,j) upward from [i+distance,j+distance) */
1268 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1269 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1270 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1271 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1272 (j
-i
) * f
->display
.x
->line_height
,
1273 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1277 for (i
= ht
; --i
>=0; )
1278 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1280 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1281 && line_dance
[j
]-j
== distance
););
1282 /* Copy (j,i] downward from (j+distance, i+distance] */
1283 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1284 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1285 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1286 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1287 (i
-j
) * f
->display
.x
->line_height
,
1288 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1292 for (i
= 0; i
< ht
; ++i
)
1293 if (line_dance
[i
] == -1)
1295 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1297 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1298 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1299 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1300 (j
-i
) * f
->display
.x
->line_height
, False
);
1303 line_dance_in_progress
= 0;
1306 /* Support routines for exposure events. */
1307 static void clear_cursor ();
1309 /* Output into a rectangle of an X-window (for frame F)
1310 the characters in f->phys_lines that overlap that rectangle.
1311 TOP and LEFT are the position of the upper left corner of the rectangle.
1312 ROWS and COLS are the size of the rectangle.
1313 Call this function with input blocked. */
1316 dumprectangle (f
, left
, top
, cols
, rows
)
1318 register int left
, top
, cols
, rows
;
1320 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1321 int cursor_cleared
= 0;
1325 if (FRAME_GARBAGED_P (f
))
1328 /* Express rectangle as four edges, instead of position-and-size. */
1329 bottom
= top
+ rows
;
1330 right
= left
+ cols
;
1332 /* Convert rectangle edges in pixels to edges in chars.
1333 Round down for left and top, up for right and bottom. */
1334 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1335 left
= PIXEL_TO_CHAR_COL (f
, left
);
1336 bottom
+= (f
->display
.x
->line_height
- 1);
1337 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1338 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1339 right
= PIXEL_TO_CHAR_COL (f
, right
);
1341 /* Clip the rectangle to what can be visible. */
1346 if (right
> f
->width
)
1348 if (bottom
> f
->height
)
1351 /* Get size in chars of the rectangle. */
1352 cols
= right
- left
;
1353 rows
= bottom
- top
;
1355 /* If rectangle has zero area, return. */
1356 if (rows
<= 0) return;
1357 if (cols
<= 0) return;
1359 /* Turn off the cursor if it is in the rectangle.
1360 We will turn it back on afterward. */
1361 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1362 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1368 /* Display the text in the rectangle, one text line at a time. */
1370 for (y
= top
; y
< bottom
; y
++)
1372 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1374 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1378 CHAR_TO_PIXEL_COL (f
, left
),
1379 CHAR_TO_PIXEL_ROW (f
, y
),
1380 line
, min (cols
, active_frame
->used
[y
] - left
),
1381 active_frame
->highlight
[y
], 0);
1384 /* Turn the cursor on if we turned it off. */
1387 x_display_cursor (f
, 1);
1394 /* We used to only do this if Vx_no_window_manager was non-nil, but
1395 the ICCCM (section 4.1.6) says that the window's border pixmap
1396 and border pixel are window attributes which are "private to the
1397 client", so we can always change it to whatever we want. */
1399 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1400 f
->display
.x
->border_pixel
);
1402 x_display_cursor (f
, 1);
1406 frame_unhighlight (f
)
1409 /* We used to only do this if Vx_no_window_manager was non-nil, but
1410 the ICCCM (section 4.1.6) says that the window's border pixmap
1411 and border pixel are window attributes which are "private to the
1412 client", so we can always change it to whatever we want. */
1414 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1415 f
->display
.x
->border_tile
);
1417 x_display_cursor (f
, 1);
1420 static void XTframe_rehighlight ();
1422 /* The focus has changed. Update the frames as necessary to reflect
1423 the new situation. Note that we can't change the selected frame
1424 here, because the lisp code we are interrupting might become confused.
1425 Each event gets marked with the frame in which it occurred, so the
1426 lisp code can tell when the switch took place by examining the events. */
1429 x_new_focus_frame (frame
)
1430 struct frame
*frame
;
1432 struct frame
*old_focus
= x_focus_frame
;
1433 int events_enqueued
= 0;
1435 if (frame
!= x_focus_frame
)
1437 /* Set this before calling other routines, so that they see
1438 the correct value of x_focus_frame. */
1439 x_focus_frame
= frame
;
1441 if (old_focus
&& old_focus
->auto_lower
)
1442 x_lower_frame (old_focus
);
1445 selected_frame
= frame
;
1446 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1448 Fselect_window (selected_frame
->selected_window
);
1449 choose_minibuf_frame ();
1452 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1453 pending_autoraise_frame
= x_focus_frame
;
1455 pending_autoraise_frame
= 0;
1458 XTframe_rehighlight ();
1461 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1466 if (! x_focus_event_frame
)
1467 x_new_focus_frame (NULL
);
1469 x_new_focus_frame (x_focus_event_frame
); /* Was f, but that seems wrong. */
1472 /* The focus has changed, or we have redirected a frame's focus to
1473 another frame (this happens when a frame uses a surrogate
1474 minibuffer frame). Shift the highlight as appropriate. */
1476 XTframe_rehighlight ()
1478 struct frame
*old_highlight
= x_highlight_frame
;
1483 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (x_focus_frame
)))
1484 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1486 if (! FRAME_LIVE_P (x_highlight_frame
))
1488 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1489 x_highlight_frame
= x_focus_frame
;
1493 x_highlight_frame
= 0;
1495 if (x_highlight_frame
!= old_highlight
)
1498 frame_unhighlight (old_highlight
);
1499 if (x_highlight_frame
)
1500 frame_highlight (x_highlight_frame
);
1504 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1506 /* Initialize mode_switch_bit and modifier_meaning. */
1508 x_find_modifier_meanings (dpyinfo
)
1509 struct x_display_info
*dpyinfo
;
1511 int min_code
, max_code
;
1514 XModifierKeymap
*mods
;
1516 dpyinfo
->meta_mod_mask
= 0;
1517 dpyinfo
->shift_lock_mask
= 0;
1518 dpyinfo
->alt_mod_mask
= 0;
1519 dpyinfo
->super_mod_mask
= 0;
1520 dpyinfo
->hyper_mod_mask
= 0;
1523 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1525 min_code
= display
->min_keycode
;
1526 max_code
= display
->max_keycode
;
1529 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1530 min_code
, max_code
- min_code
+ 1,
1532 mods
= XGetModifierMapping (dpyinfo
->display
);
1534 /* Scan the modifier table to see which modifier bits the Meta and
1535 Alt keysyms are on. */
1537 int row
, col
; /* The row and column in the modifier table. */
1539 for (row
= 3; row
< 8; row
++)
1540 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1543 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1545 /* Zeroes are used for filler. Skip them. */
1549 /* Are any of this keycode's keysyms a meta key? */
1553 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1555 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1561 dpyinfo
->meta_mod_mask
|= (1 << row
);
1566 dpyinfo
->alt_mod_mask
|= (1 << row
);
1571 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1576 dpyinfo
->super_mod_mask
|= (1 << row
);
1580 /* Ignore this if it's not on the lock modifier. */
1581 if ((1 << row
) == LockMask
)
1582 dpyinfo
->shift_lock_mask
= LockMask
;
1590 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1591 if (! dpyinfo
->meta_mod_mask
)
1593 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1594 dpyinfo
->alt_mod_mask
= 0;
1597 /* If some keys are both alt and meta,
1598 make them just meta, not alt. */
1599 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1601 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1604 XFree ((char *) syms
);
1605 XFreeModifiermap (mods
);
1608 /* Convert between the modifier bits X uses and the modifier bits
1611 x_x_to_emacs_modifiers (dpyinfo
, state
)
1612 struct x_display_info
*dpyinfo
;
1615 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1616 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1617 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1618 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1619 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1620 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1624 x_emacs_to_x_modifiers (dpyinfo
, state
)
1625 struct x_display_info
*dpyinfo
;
1628 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1629 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1630 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1631 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1632 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1633 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1636 /* Mouse clicks and mouse movement. Rah. */
1638 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1639 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1640 that the glyph at X, Y occupies, if BOUNDS != 0.
1641 If NOCLIP is nonzero, do not force the value into range. */
1644 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1646 register int pix_x
, pix_y
;
1647 register int *x
, *y
;
1651 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1652 even for negative values. */
1654 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1656 pix_y
-= (f
)->display
.x
->line_height
- 1;
1658 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1659 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1663 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1664 bounds
->height
= f
->display
.x
->line_height
;
1665 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1666 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1673 else if (pix_x
> f
->width
)
1678 else if (pix_y
> f
->height
)
1687 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1690 register int *pix_x
, *pix_y
;
1692 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1693 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1696 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1698 If the event is a button press, then note that we have grabbed
1702 construct_mouse_click (result
, event
, f
)
1703 struct input_event
*result
;
1704 XButtonEvent
*event
;
1707 /* Make the event type no_event; we'll change that when we decide
1709 result
->kind
= mouse_click
;
1710 result
->code
= event
->button
- Button1
;
1711 result
->timestamp
= event
->time
;
1712 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1714 | (event
->type
== ButtonRelease
1722 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1723 XSETFASTINT (result
->x
, column
);
1724 XSETFASTINT (result
->y
, row
);
1726 XSETINT (result
->x
, event
->x
);
1727 XSETINT (result
->y
, event
->y
);
1728 XSETFRAME (result
->frame_or_window
, f
);
1732 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1735 construct_menu_click (result
, event
, f
)
1736 struct input_event
*result
;
1737 XButtonEvent
*event
;
1740 /* Make the event type no_event; we'll change that when we decide
1742 result
->kind
= mouse_click
;
1743 XSETINT (result
->code
, event
->button
- Button1
);
1744 result
->timestamp
= event
->time
;
1745 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1747 | (event
->type
== ButtonRelease
1751 XSETINT (result
->x
, event
->x
);
1752 XSETINT (result
->y
, -1);
1753 XSETFRAME (result
->frame_or_window
, f
);
1756 /* Function to report a mouse movement to the mainstream Emacs code.
1757 The input handler calls this.
1759 We have received a mouse movement event, which is given in *event.
1760 If the mouse is over a different glyph than it was last time, tell
1761 the mainstream emacs code by setting mouse_moved. If not, ask for
1762 another motion event, so we can check again the next time it moves. */
1765 note_mouse_movement (frame
, event
)
1767 XMotionEvent
*event
;
1770 last_mouse_movement_time
= event
->time
;
1772 if (event
->window
!= FRAME_X_WINDOW (frame
))
1775 last_mouse_scroll_bar
= Qnil
;
1777 note_mouse_highlight (frame
, -1, -1);
1779 /* Ask for another mouse motion event. */
1782 Window dummy_window
;
1784 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1785 &dummy_window
, &dummy_window
,
1786 &dummy
, &dummy
, &dummy
, &dummy
,
1787 (unsigned int *) &dummy
);
1791 /* Has the mouse moved off the glyph it was on at the last sighting? */
1792 else if (event
->x
< last_mouse_glyph
.x
1793 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1794 || event
->y
< last_mouse_glyph
.y
1795 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1798 last_mouse_scroll_bar
= Qnil
;
1800 note_mouse_highlight (frame
, event
->x
, event
->y
);
1802 /* Ask for another mouse motion event. */
1805 Window dummy_window
;
1807 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1808 &dummy_window
, &dummy_window
,
1809 &dummy
, &dummy
, &dummy
, &dummy
,
1810 (unsigned int *) &dummy
);
1815 /* It's on the same glyph. Call XQueryPointer so we'll get an
1816 event the next time the mouse moves and we can see if it's
1817 *still* on the same glyph. */
1819 Window dummy_window
;
1821 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1822 &dummy_window
, &dummy_window
,
1823 &dummy
, &dummy
, &dummy
, &dummy
,
1824 (unsigned int *) &dummy
);
1828 /* This is used for debugging, to turn off note_mouse_highlight. */
1829 static int disable_mouse_highlight
;
1831 /* Take proper action when the mouse has moved to position X, Y on frame F
1832 as regards highlighting characters that have mouse-face properties.
1833 Also dehighlighting chars where the mouse was before.
1834 X and Y can be negative or out of range. */
1837 note_mouse_highlight (f
, x
, y
)
1840 int row
, column
, portion
;
1841 XRectangle new_glyph
;
1845 if (disable_mouse_highlight
)
1848 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1849 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1850 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1852 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1857 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1861 /* Find out which glyph the mouse is on. */
1862 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1863 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1865 /* Which window is that in? */
1866 window
= window_from_coordinates (f
, column
, row
, &portion
);
1867 w
= XWINDOW (window
);
1869 /* If we were displaying active text in another window, clear that. */
1870 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1871 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1873 /* Are we in a window whose display is up to date?
1874 And verify the buffer's text has not changed. */
1875 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1876 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1877 && EQ (w
->window_end_valid
, w
->buffer
)
1878 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1880 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1883 /* Find which buffer position the mouse corresponds to. */
1884 for (i
= column
; i
>= 0; i
--)
1888 /* Is it outside the displayed active region (if any)? */
1890 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1891 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1892 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1893 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1894 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1895 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1896 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1897 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1898 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1900 Lisp_Object mouse_face
, overlay
, position
;
1901 Lisp_Object
*overlay_vec
;
1902 int len
, noverlays
, ignor1
;
1903 struct buffer
*obuf
;
1906 /* If we get an out-of-range value, return now; avoid an error. */
1907 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1910 /* Make the window's buffer temporarily current for
1911 overlays_at and compute_char_face. */
1912 obuf
= current_buffer
;
1913 current_buffer
= XBUFFER (w
->buffer
);
1919 /* Yes. Clear the display of the old active region, if any. */
1920 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1922 /* Is this char mouse-active? */
1923 XSETINT (position
, pos
);
1926 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1928 /* Put all the overlays we want in a vector in overlay_vec.
1929 Store the length in len. */
1930 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1932 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1934 /* Find the highest priority overlay that has a mouse-face prop. */
1936 for (i
= 0; i
< noverlays
; i
++)
1938 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1939 if (!NILP (mouse_face
))
1941 overlay
= overlay_vec
[i
];
1946 /* If no overlay applies, get a text property. */
1948 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1950 /* Handle the overlay case. */
1951 if (! NILP (overlay
))
1953 /* Find the range of text around this char that
1954 should be active. */
1955 Lisp_Object before
, after
;
1958 before
= Foverlay_start (overlay
);
1959 after
= Foverlay_end (overlay
);
1960 /* Record this as the current active region. */
1961 fast_find_position (window
, before
,
1962 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1963 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1964 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
1965 = !fast_find_position (window
, after
,
1966 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
1967 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
1968 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1969 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
1970 = compute_char_face (f
, w
, pos
, 0, 0,
1971 &ignore
, pos
+ 1, 1);
1973 /* Display it as active. */
1974 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
1976 /* Handle the text property case. */
1977 else if (! NILP (mouse_face
))
1979 /* Find the range of text around this char that
1980 should be active. */
1981 Lisp_Object before
, after
, beginning
, end
;
1984 beginning
= Fmarker_position (w
->start
);
1985 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1986 - XFASTINT (w
->window_end_pos
)));
1988 = Fprevious_single_property_change (make_number (pos
+ 1),
1990 w
->buffer
, beginning
);
1992 = Fnext_single_property_change (position
, Qmouse_face
,
1994 /* Record this as the current active region. */
1995 fast_find_position (window
, before
,
1996 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1997 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1998 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
1999 = !fast_find_position (window
, after
,
2000 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2001 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2002 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2003 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2004 = compute_char_face (f
, w
, pos
, 0, 0,
2005 &ignore
, pos
+ 1, 1);
2007 /* Display it as active. */
2008 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2012 current_buffer
= obuf
;
2017 /* Find the row and column of position POS in window WINDOW.
2018 Store them in *COLUMNP and *ROWP.
2019 This assumes display in WINDOW is up to date.
2020 If POS is above start of WINDOW, return coords
2021 of start of first screen line.
2022 If POS is after end of WINDOW, return coords of end of last screen line.
2024 Value is 1 if POS is in range, 0 if it was off screen. */
2027 fast_find_position (window
, pos
, columnp
, rowp
)
2030 int *columnp
, *rowp
;
2032 struct window
*w
= XWINDOW (window
);
2033 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2038 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2039 int width
= window_internal_width (w
);
2042 int maybe_next_line
= 0;
2044 /* Find the right row. */
2049 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2050 if (linestart
> pos
)
2052 /* If the position sought is the end of the buffer,
2053 don't include the blank lines at the bottom of the window. */
2054 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2056 maybe_next_line
= 1;
2063 /* Find the right column with in it. */
2064 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2066 for (i
= 0; i
< width
; i
++)
2068 if (charstarts
[left
+ i
] == pos
)
2071 *columnp
= i
+ left
;
2074 else if (charstarts
[left
+ i
] > pos
)
2076 else if (charstarts
[left
+ i
] > 0)
2080 /* If we're looking for the end of the buffer,
2081 and we didn't find it in the line we scanned,
2082 use the start of the following line. */
2083 if (maybe_next_line
)
2094 /* Display the active region described by mouse_face_*
2095 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2098 show_mouse_face (dpyinfo
, hl
)
2099 struct x_display_info
*dpyinfo
;
2102 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2103 int width
= window_internal_width (w
);
2104 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2107 int old_curs_x
= curs_x
;
2108 int old_curs_y
= curs_y
;
2110 /* Set these variables temporarily
2111 so that if we have to turn the cursor off and on again
2112 we will put it back at the same place. */
2113 curs_x
= f
->phys_cursor_x
;
2114 curs_y
= f
->phys_cursor_y
;
2116 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2117 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2119 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2120 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2122 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2123 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2125 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2127 /* If the cursor's in the text we are about to rewrite,
2128 turn the cursor off. */
2130 && curs_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
2131 && curs_x
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
)
2133 x_display_cursor (f
, 0);
2138 CHAR_TO_PIXEL_COL (f
, column
),
2139 CHAR_TO_PIXEL_ROW (f
, i
),
2140 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2142 /* Highlight with mouse face if hl > 0. */
2146 /* If we turned the cursor off, turn it back on. */
2148 x_display_cursor (f
, 1);
2150 curs_x
= old_curs_x
;
2151 curs_y
= old_curs_y
;
2153 /* Change the mouse cursor according to the value of HL. */
2155 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2156 f
->display
.x
->cross_cursor
);
2158 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2159 f
->display
.x
->text_cursor
);
2162 /* Clear out the mouse-highlighted active region.
2163 Redraw it unhighlighted first. */
2166 clear_mouse_face (dpyinfo
)
2167 struct x_display_info
*dpyinfo
;
2169 if (! NILP (dpyinfo
->mouse_face_window
))
2170 show_mouse_face (dpyinfo
, 0);
2172 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2173 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2174 dpyinfo
->mouse_face_window
= Qnil
;
2177 static struct scroll_bar
*x_window_to_scroll_bar ();
2178 static void x_scroll_bar_report_motion ();
2180 /* Return the current position of the mouse.
2182 If the mouse movement started in a scroll bar, set *f, *bar_window,
2183 and *part to the frame, window, and scroll bar part that the mouse
2184 is over. Set *x and *y to the portion and whole of the mouse's
2185 position on the scroll bar.
2187 If the mouse movement started elsewhere, set *f to the frame the
2188 mouse is on, *bar_window to nil, and *x and *y to the character cell
2191 Set *time to the server timestamp for the time at which the mouse
2192 was at this position.
2194 Don't store anything if we don't have a valid set of values to report.
2196 This clears the mouse_moved flag, so we can wait for the next mouse
2197 movement. This also calls XQueryPointer, which will cause the
2198 server to give us another MotionNotify when the mouse moves
2202 XTmouse_position (fp
, bar_window
, part
, x
, y
, time
)
2204 Lisp_Object
*bar_window
;
2205 enum scroll_bar_part
*part
;
2207 unsigned long *time
;
2213 if (! NILP (last_mouse_scroll_bar
))
2214 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2220 Window dummy_window
;
2224 last_mouse_scroll_bar
= Qnil
;
2226 /* Figure out which root window we're on. */
2227 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2228 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2230 /* The root window which contains the pointer. */
2233 /* Trash which we can't trust if the pointer is on
2234 a different screen. */
2237 /* The position on that root window. */
2240 /* More trash we can't trust. */
2243 /* Modifier keys and pointer buttons, about which
2245 (unsigned int *) &dummy
);
2247 /* Now we have a position on the root; find the innermost window
2248 containing the pointer. */
2252 int parent_x
, parent_y
;
2256 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2257 && FRAME_LIVE_P (last_mouse_frame
))
2259 /* If mouse was grabbed on a frame, give coords for that frame
2260 even if the mouse is now outside it. */
2261 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2263 /* From-window, to-window. */
2264 root
, FRAME_X_WINDOW (last_mouse_frame
),
2266 /* From-position, to-position. */
2267 root_x
, root_y
, &win_x
, &win_y
,
2271 f1
= last_mouse_frame
;
2277 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2279 /* From-window, to-window. */
2282 /* From-position, to-position. */
2283 root_x
, root_y
, &win_x
, &win_y
,
2296 /* Now we know that:
2297 win is the innermost window containing the pointer
2298 (XTC says it has no child containing the pointer),
2299 win_x and win_y are the pointer's position in it
2300 (XTC did this the last time through), and
2301 parent_x and parent_y are the pointer's position in win's parent.
2302 (They are what win_x and win_y were when win was child.
2303 If win is the root window, it has no parent, and
2304 parent_{x,y} are invalid, but that's okay, because we'll
2305 never use them in that case.) */
2307 /* Is win one of our frames? */
2308 f1
= x_any_window_to_frame (win
);
2311 /* If not, is it one of our scroll bars? */
2314 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2318 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2326 int ignore1
, ignore2
;
2328 /* Ok, we found a frame. Store all the values. */
2330 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2332 FRAME_X_DISPLAY_INFO (f1
)->grabbed
);
2337 XSETINT (*x
, win_x
);
2338 XSETINT (*y
, win_y
);
2339 *time
= last_mouse_movement_time
;
2347 /* Scroll bar support. */
2349 /* Given an X window ID, find the struct scroll_bar which manages it.
2350 This can be called in GC, so we have to make sure to strip off mark
2352 static struct scroll_bar
*
2353 x_window_to_scroll_bar (window_id
)
2356 Lisp_Object tail
, frame
;
2358 for (tail
= Vframe_list
;
2359 XGCTYPE (tail
) == Lisp_Cons
;
2360 tail
= XCONS (tail
)->cdr
)
2362 Lisp_Object frame
, bar
, condemned
;
2364 frame
= XCONS (tail
)->car
;
2365 /* All elements of Vframe_list should be frames. */
2366 if (! GC_FRAMEP (frame
))
2369 /* Scan this frame's scroll bar list for a scroll bar with the
2371 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2372 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2373 /* This trick allows us to search both the ordinary and
2374 condemned scroll bar lists with one loop. */
2375 ! GC_NILP (bar
) || (bar
= condemned
,
2378 bar
= XSCROLL_BAR (bar
)->next
)
2379 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2380 return XSCROLL_BAR (bar
);
2386 /* Open a new X window to serve as a scroll bar, and return the
2387 scroll bar vector for it. */
2388 static struct scroll_bar
*
2389 x_scroll_bar_create (window
, top
, left
, width
, height
)
2390 struct window
*window
;
2391 int top
, left
, width
, height
;
2393 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2394 struct scroll_bar
*bar
2395 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2400 XSetWindowAttributes a
;
2402 a
.background_pixel
= f
->display
.x
->background_pixel
;
2403 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2404 | ButtonMotionMask
| PointerMotionHintMask
2406 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2408 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2413 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2414 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2415 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2416 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2417 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2418 sb_widget
= XtCreateManagedWidget ("box",
2420 f
->display
.x
->edit_widget
, al
, ac
);
2421 SET_SCROLL_BAR_X_WINDOW
2422 (bar
, sb_widget
->core
.window
);
2424 SET_SCROLL_BAR_X_WINDOW
2426 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2428 /* Position and size of scroll bar. */
2429 left
, top
, width
, height
,
2431 /* Border width, depth, class, and visual. */
2432 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2438 XSETWINDOW (bar
->window
, window
);
2439 XSETINT (bar
->top
, top
);
2440 XSETINT (bar
->left
, left
);
2441 XSETINT (bar
->width
, width
);
2442 XSETINT (bar
->height
, height
);
2443 XSETINT (bar
->start
, 0);
2444 XSETINT (bar
->end
, 0);
2445 bar
->dragging
= Qnil
;
2447 /* Add bar to its frame's list of scroll bars. */
2448 bar
->next
= FRAME_SCROLL_BARS (f
);
2450 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2451 if (! NILP (bar
->next
))
2452 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2454 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2461 /* Draw BAR's handle in the proper position.
2462 If the handle is already drawn from START to END, don't bother
2463 redrawing it, unless REBUILD is non-zero; in that case, always
2464 redraw it. (REBUILD is handy for drawing the handle after expose
2467 Normally, we want to constrain the start and end of the handle to
2468 fit inside its rectangle, but if the user is dragging the scroll bar
2469 handle, we want to let them drag it down all the way, so that the
2470 bar's top is as far down as it goes; otherwise, there's no way to
2471 move to the very end of the buffer. */
2473 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2474 struct scroll_bar
*bar
;
2478 int dragging
= ! NILP (bar
->dragging
);
2479 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2480 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2481 GC gc
= f
->display
.x
->normal_gc
;
2483 /* If the display is already accurate, do nothing. */
2485 && start
== XINT (bar
->start
)
2486 && end
== XINT (bar
->end
))
2492 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2493 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2494 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2496 /* Make sure the values are reasonable, and try to preserve
2497 the distance between start and end. */
2499 int length
= end
- start
;
2503 else if (start
> top_range
)
2505 end
= start
+ length
;
2509 else if (end
> top_range
&& ! dragging
)
2513 /* Store the adjusted setting in the scroll bar. */
2514 XSETINT (bar
->start
, start
);
2515 XSETINT (bar
->end
, end
);
2517 /* Clip the end position, just for display. */
2518 if (end
> top_range
)
2521 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2522 below top positions, to make sure the handle is always at least
2523 that many pixels tall. */
2524 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2526 /* Draw the empty space above the handle. Note that we can't clear
2527 zero-height areas; that means "clear to end of window." */
2529 XClearArea (FRAME_X_DISPLAY (f
), w
,
2531 /* x, y, width, height, and exposures. */
2532 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2533 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2534 inside_width
, start
,
2537 /* Draw the handle itself. */
2538 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2540 /* x, y, width, height */
2541 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2542 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2543 inside_width
, end
- start
);
2546 /* Draw the empty space below the handle. Note that we can't
2547 clear zero-height areas; that means "clear to end of window." */
2548 if (end
< inside_height
)
2549 XClearArea (FRAME_X_DISPLAY (f
), w
,
2551 /* x, y, width, height, and exposures. */
2552 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2553 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2554 inside_width
, inside_height
- end
,
2562 /* Move a scroll bar around on the screen, to accommodate changing
2563 window configurations. */
2565 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2566 struct scroll_bar
*bar
;
2567 int top
, left
, width
, height
;
2569 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2570 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2576 unsigned int mask
= 0;
2583 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2584 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2585 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2586 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2589 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2593 XSETINT (bar
->left
, left
);
2594 XSETINT (bar
->top
, top
);
2595 XSETINT (bar
->width
, width
);
2596 XSETINT (bar
->height
, height
);
2601 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2604 x_scroll_bar_remove (bar
)
2605 struct scroll_bar
*bar
;
2607 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2611 /* Destroy the window. */
2612 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2614 /* Disassociate this scroll bar from its window. */
2615 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2620 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2621 that we are displaying PORTION characters out of a total of WHOLE
2622 characters, starting at POSITION. If WINDOW has no scroll bar,
2625 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2626 struct window
*window
;
2627 int portion
, whole
, position
;
2629 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2630 int top
= XINT (window
->top
);
2631 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2632 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2634 /* Where should this scroll bar be, pixelwise? */
2635 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2636 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2638 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2639 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2640 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
2641 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2643 struct scroll_bar
*bar
;
2645 /* Does the scroll bar exist yet? */
2646 if (NILP (window
->vertical_scroll_bar
))
2647 bar
= x_scroll_bar_create (window
,
2648 pixel_top
, pixel_left
,
2649 pixel_width
, pixel_height
);
2652 /* It may just need to be moved and resized. */
2653 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2654 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2657 /* Set the scroll bar's current state, unless we're currently being
2659 if (NILP (bar
->dragging
))
2661 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2664 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2667 int start
= ((double) position
* top_range
) / whole
;
2668 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2670 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2674 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2678 /* The following three hooks are used when we're doing a thorough
2679 redisplay of the frame. We don't explicitly know which scroll bars
2680 are going to be deleted, because keeping track of when windows go
2681 away is a real pain - "Can you say set-window-configuration, boys
2682 and girls?" Instead, we just assert at the beginning of redisplay
2683 that *all* scroll bars are to be removed, and then save a scroll bar
2684 from the fiery pit when we actually redisplay its window. */
2686 /* Arrange for all scroll bars on FRAME to be removed at the next call
2687 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2688 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2690 XTcondemn_scroll_bars (frame
)
2693 /* The condemned list should be empty at this point; if it's not,
2694 then the rest of Emacs isn't using the condemn/redeem/judge
2695 protocol correctly. */
2696 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2699 /* Move them all to the "condemned" list. */
2700 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2701 FRAME_SCROLL_BARS (frame
) = Qnil
;
2704 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2705 Note that WINDOW isn't necessarily condemned at all. */
2707 XTredeem_scroll_bar (window
)
2708 struct window
*window
;
2710 struct scroll_bar
*bar
;
2712 /* We can't redeem this window's scroll bar if it doesn't have one. */
2713 if (NILP (window
->vertical_scroll_bar
))
2716 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2718 /* Unlink it from the condemned list. */
2720 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2722 if (NILP (bar
->prev
))
2724 /* If the prev pointer is nil, it must be the first in one of
2726 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2727 /* It's not condemned. Everything's fine. */
2729 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2730 window
->vertical_scroll_bar
))
2731 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2733 /* If its prev pointer is nil, it must be at the front of
2734 one or the other! */
2738 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2740 if (! NILP (bar
->next
))
2741 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2743 bar
->next
= FRAME_SCROLL_BARS (f
);
2745 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2746 if (! NILP (bar
->next
))
2747 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2751 /* Remove all scroll bars on FRAME that haven't been saved since the
2752 last call to `*condemn_scroll_bars_hook'. */
2754 XTjudge_scroll_bars (f
)
2757 Lisp_Object bar
, next
;
2759 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2761 /* Clear out the condemned list now so we won't try to process any
2762 more events on the hapless scroll bars. */
2763 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2765 for (; ! NILP (bar
); bar
= next
)
2767 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2769 x_scroll_bar_remove (b
);
2772 b
->next
= b
->prev
= Qnil
;
2775 /* Now there should be no references to the condemned scroll bars,
2776 and they should get garbage-collected. */
2780 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2782 This may be called from a signal handler, so we have to ignore GC
2785 x_scroll_bar_expose (bar
, event
)
2786 struct scroll_bar
*bar
;
2789 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2790 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2791 GC gc
= f
->display
.x
->normal_gc
;
2795 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2797 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2798 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2800 /* x, y, width, height */
2801 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2806 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2807 is set to something other than no_event, it is enqueued.
2809 This may be called from a signal handler, so we have to ignore GC
2812 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2813 struct scroll_bar
*bar
;
2815 struct input_event
*emacs_event
;
2817 if (! GC_WINDOWP (bar
->window
))
2820 emacs_event
->kind
= scroll_bar_click
;
2821 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2822 emacs_event
->modifiers
2823 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2824 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2825 event
->xbutton
.state
)
2826 | (event
->type
== ButtonRelease
2829 emacs_event
->frame_or_window
= bar
->window
;
2830 emacs_event
->timestamp
= event
->xbutton
.time
;
2833 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2835 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2836 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2839 if (y
> top_range
) y
= top_range
;
2841 if (y
< XINT (bar
->start
))
2842 emacs_event
->part
= scroll_bar_above_handle
;
2843 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2844 emacs_event
->part
= scroll_bar_handle
;
2846 emacs_event
->part
= scroll_bar_below_handle
;
2848 /* Just because the user has clicked on the handle doesn't mean
2849 they want to drag it. Lisp code needs to be able to decide
2850 whether or not we're dragging. */
2852 /* If the user has just clicked on the handle, record where they're
2854 if (event
->type
== ButtonPress
2855 && emacs_event
->part
== scroll_bar_handle
)
2856 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2859 /* If the user has released the handle, set it to its final position. */
2860 if (event
->type
== ButtonRelease
2861 && ! NILP (bar
->dragging
))
2863 int new_start
= y
- XINT (bar
->dragging
);
2864 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2866 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2867 bar
->dragging
= Qnil
;
2870 /* Same deal here as the other #if 0. */
2872 /* Clicks on the handle are always reported as occurring at the top of
2874 if (emacs_event
->part
== scroll_bar_handle
)
2875 emacs_event
->x
= bar
->start
;
2877 XSETINT (emacs_event
->x
, y
);
2879 XSETINT (emacs_event
->x
, y
);
2882 XSETINT (emacs_event
->y
, top_range
);
2886 /* Handle some mouse motion while someone is dragging the scroll bar.
2888 This may be called from a signal handler, so we have to ignore GC
2891 x_scroll_bar_note_movement (bar
, event
)
2892 struct scroll_bar
*bar
;
2895 last_mouse_movement_time
= event
->xmotion
.time
;
2898 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2900 /* If we're dragging the bar, display it. */
2901 if (! GC_NILP (bar
->dragging
))
2903 /* Where should the handle be now? */
2904 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2906 if (new_start
!= XINT (bar
->start
))
2908 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2910 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2914 /* Call XQueryPointer so we'll get an event the next time the mouse
2915 moves and we can see *still* on the same position. */
2918 Window dummy_window
;
2920 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2921 &dummy_window
, &dummy_window
,
2922 &dummy
, &dummy
, &dummy
, &dummy
,
2923 (unsigned int *) &dummy
);
2927 /* Return information to the user about the current position of the mouse
2928 on the scroll bar. */
2930 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2932 Lisp_Object
*bar_window
;
2933 enum scroll_bar_part
*part
;
2935 unsigned long *time
;
2937 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2938 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2939 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2941 Window dummy_window
;
2943 unsigned int dummy_mask
;
2947 /* Get the mouse's position relative to the scroll bar window, and
2949 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
2951 /* Root, child, root x and root y. */
2952 &dummy_window
, &dummy_window
,
2953 &dummy_coord
, &dummy_coord
,
2955 /* Position relative to scroll bar. */
2958 /* Mouse buttons and modifier keys. */
2964 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2966 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2968 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2970 if (! NILP (bar
->dragging
))
2971 win_y
-= XINT (bar
->dragging
);
2975 if (win_y
> top_range
)
2979 *bar_window
= bar
->window
;
2981 if (! NILP (bar
->dragging
))
2982 *part
= scroll_bar_handle
;
2983 else if (win_y
< XINT (bar
->start
))
2984 *part
= scroll_bar_above_handle
;
2985 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2986 *part
= scroll_bar_handle
;
2988 *part
= scroll_bar_below_handle
;
2990 XSETINT (*x
, win_y
);
2991 XSETINT (*y
, top_range
);
2994 last_mouse_scroll_bar
= Qnil
;
2997 *time
= last_mouse_movement_time
;
3003 /* The screen has been cleared so we may have changed foreground or
3004 background colors, and the scroll bars may need to be redrawn.
3005 Clear out the scroll bars, and ask for expose events, so we can
3008 x_scroll_bar_clear (f
)
3013 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3014 bar
= XSCROLL_BAR (bar
)->next
)
3015 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3019 /* This processes Expose events from the menubar specific X event
3020 loop in menubar.c. This allows to redisplay the frame if necessary
3021 when handling menubar or popup items. */
3024 process_expose_from_menu (event
)
3031 f
= x_window_to_frame (event
.xexpose
.window
);
3034 if (f
->async_visible
== 0)
3036 f
->async_visible
= 1;
3037 f
->async_iconified
= 0;
3038 SET_FRAME_GARBAGED (f
);
3042 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3043 event
.xexpose
.x
, event
.xexpose
.y
,
3044 event
.xexpose
.width
, event
.xexpose
.height
);
3049 struct scroll_bar
*bar
3050 = x_window_to_scroll_bar (event
.xexpose
.window
);
3053 x_scroll_bar_expose (bar
, &event
);
3059 /* Define a queue to save up SelectionRequest events for later handling. */
3061 struct selection_event_queue
3064 struct selection_event_queue
*next
;
3067 static struct selection_event_queue
*queue
;
3069 /* Nonzero means queue up certain events--don't process them yet. */
3070 static int x_queue_selection_requests
;
3072 /* Queue up an X event *EVENT, to be processed later. */
3075 x_queue_event (f
, event
)
3079 struct selection_event_queue
*queue_tmp
3080 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3082 if (queue_tmp
!= NULL
)
3084 queue_tmp
->event
= *event
;
3085 queue_tmp
->next
= queue
;
3090 /* Take all the queued events and put them back
3091 so that they get processed afresh. */
3094 x_unqueue_events (f
)
3097 while (queue
!= NULL
)
3099 struct selection_event_queue
*queue_tmp
= queue
;
3100 XPutBackEvent (FRAME_X_DISPLAY (f
), &queue_tmp
->event
);
3101 queue
= queue_tmp
->next
;
3102 free ((char *)queue_tmp
);
3106 /* Start queuing SelectionRequest events. */
3109 x_start_queuing_selection_requests (f
)
3112 x_queue_selection_requests
++;
3115 /* Stop queuing SelectionRequest events. */
3118 x_stop_queuing_selection_requests (f
)
3121 x_queue_selection_requests
--;
3122 x_unqueue_events (f
);
3125 /* The main X event-reading loop - XTread_socket. */
3127 /* Timestamp of enter window event. This is only used by XTread_socket,
3128 but we have to put it out here, since static variables within functions
3129 sometimes don't work. */
3130 static Time enter_timestamp
;
3132 /* This holds the state XLookupString needs to implement dead keys
3133 and other tricks known as "compose processing". _X Window System_
3134 says that a portable program can't use this, but Stephen Gildea assures
3135 me that letting the compiler initialize it to zeros will work okay.
3137 This must be defined outside of XTread_socket, for the same reasons
3138 given for enter_timestamp, above. */
3139 static XComposeStatus compose_status
;
3141 /* Record the last 100 characters stored
3142 to help debug the loss-of-chars-during-GC problem. */
3144 short temp_buffer
[100];
3146 /* Set this to nonzero to fake an "X I/O error"
3147 on a particular display. */
3148 struct x_display_info
*XTread_socket_fake_io_error
;
3150 /* Read events coming from the X server.
3151 This routine is called by the SIGIO handler.
3152 We return as soon as there are no more events to be read.
3154 Events representing keys are stored in buffer BUFP,
3155 which can hold up to NUMCHARS characters.
3156 We return the number of characters stored into the buffer,
3157 thus pretending to be `read'.
3159 WAITP is nonzero if we should block until input arrives.
3160 EXPECTED is nonzero if the caller knows input is available. */
3163 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3165 register struct input_event
*bufp
;
3166 register int numchars
;
3173 int items_pending
; /* How many items are in the X queue. */
3176 int event_found
= 0;
3179 struct x_display_info
*dpyinfo
;
3181 if (interrupt_input_blocked
)
3183 interrupt_input_pending
= 1;
3187 interrupt_input_pending
= 0;
3190 /* So people can tell when we have read the available input. */
3191 input_signal_count
++;
3194 abort (); /* Don't think this happens. */
3196 /* Find the display we are supposed to read input for.
3197 It's the one communicating on descriptor SD. */
3198 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3200 #if 0 /* This ought to be unnecessary; let's verify it. */
3202 /* If available, Xlib uses FIOSNBIO to make the socket
3203 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3204 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3205 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3206 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3207 #endif /* ! defined (FIOSNBIO) */
3210 #if 0 /* This code can't be made to work, with multiple displays,
3211 and appears not to be used on any system any more.
3212 Also keyboard.c doesn't turn O_NDELAY on and off
3213 for X connections. */
3216 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3218 extern int read_alarm_should_throw
;
3219 read_alarm_should_throw
= 1;
3220 XPeekEvent (dpyinfo
->display
, &event
);
3221 read_alarm_should_throw
= 0;
3223 #endif /* HAVE_SELECT */
3227 /* For debugging, this gives a way to fake an I/O error. */
3228 if (dpyinfo
== XTread_socket_fake_io_error
)
3230 XTread_socket_fake_io_error
= 0;
3231 x_io_error_quitter (dpyinfo
->display
);
3234 while (XPending (dpyinfo
->display
) != 0)
3236 XNextEvent (dpyinfo
->display
, &event
);
3243 if (event
.xclient
.message_type
3244 == dpyinfo
->Xatom_wm_protocols
3245 && event
.xclient
.format
== 32)
3247 if (event
.xclient
.data
.l
[0]
3248 == dpyinfo
->Xatom_wm_take_focus
)
3250 f
= x_window_to_frame (event
.xclient
.window
);
3251 /* Since we set WM_TAKE_FOCUS, we must call
3252 XSetInputFocus explicitly. But not if f is null,
3253 since that might be an event for a deleted frame. */
3255 XSetInputFocus (event
.xclient
.display
,
3256 event
.xclient
.window
,
3257 RevertToPointerRoot
,
3258 event
.xclient
.data
.l
[1]);
3259 /* Not certain about handling scroll bars here */
3261 else if (event
.xclient
.data
.l
[0]
3262 == dpyinfo
->Xatom_wm_save_yourself
)
3264 /* Save state modify the WM_COMMAND property to
3265 something which can reinstate us. This notifies
3266 the session manager, who's looking for such a
3267 PropertyNotify. Can restart processing when
3268 a keyboard or mouse event arrives. */
3271 f
= x_top_window_to_frame (event
.xclient
.window
);
3273 /* This is just so we only give real data once
3274 for a single Emacs process. */
3275 if (f
== selected_frame
)
3276 XSetCommand (FRAME_X_DISPLAY (f
),
3277 event
.xclient
.window
,
3278 initial_argv
, initial_argc
);
3280 XSetCommand (FRAME_X_DISPLAY (f
),
3281 event
.xclient
.window
,
3285 else if (event
.xclient
.data
.l
[0]
3286 == dpyinfo
->Xatom_wm_delete_window
)
3288 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3295 bufp
->kind
= delete_window_event
;
3296 XSETFRAME (bufp
->frame_or_window
, f
);
3304 else if (event
.xclient
.message_type
3305 == dpyinfo
->Xatom_wm_configure_denied
)
3308 else if (event
.xclient
.message_type
3309 == dpyinfo
->Xatom_wm_window_moved
)
3312 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3314 new_x
= event
.xclient
.data
.s
[0];
3315 new_y
= event
.xclient
.data
.s
[1];
3319 f
->display
.x
->left_pos
= new_x
;
3320 f
->display
.x
->top_pos
= new_y
;
3323 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3324 else if (event
.xclient
.message_type
3325 == dpyinfo
->Xatom_editres
)
3327 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3328 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3330 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3334 case SelectionNotify
:
3335 #ifdef USE_X_TOOLKIT
3336 if (! x_window_to_frame (event
.xselection
.requestor
))
3338 #endif /* not USE_X_TOOLKIT */
3339 x_handle_selection_notify (&event
);
3342 case SelectionClear
: /* Someone has grabbed ownership. */
3343 #ifdef USE_X_TOOLKIT
3344 if (! x_window_to_frame (event
.xselectionclear
.window
))
3346 #endif /* USE_X_TOOLKIT */
3348 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3353 bufp
->kind
= selection_clear_event
;
3354 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3355 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3356 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3364 case SelectionRequest
: /* Someone wants our selection. */
3365 #ifdef USE_X_TOOLKIT
3366 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3368 #endif /* USE_X_TOOLKIT */
3369 if (x_queue_selection_requests
)
3370 x_queue_event (x_window_to_frame (event
.xselectionrequest
.owner
),
3374 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3379 bufp
->kind
= selection_request_event
;
3380 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3381 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3382 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3383 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3384 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3385 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3393 case PropertyNotify
:
3394 #ifdef USE_X_TOOLKIT
3395 if (!x_any_window_to_frame (event
.xproperty
.window
))
3397 #endif /* not USE_X_TOOLKIT */
3398 x_handle_property_notify (&event
);
3401 case ReparentNotify
:
3402 f
= x_top_window_to_frame (event
.xreparent
.window
);
3406 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3407 x_real_positions (f
, &x
, &y
);
3408 f
->display
.x
->left_pos
= x
;
3409 f
->display
.x
->top_pos
= y
;
3414 f
= x_window_to_frame (event
.xexpose
.window
);
3417 if (f
->async_visible
== 0)
3419 f
->async_visible
= 1;
3420 f
->async_iconified
= 0;
3421 SET_FRAME_GARBAGED (f
);
3424 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3425 event
.xexpose
.x
, event
.xexpose
.y
,
3426 event
.xexpose
.width
, event
.xexpose
.height
);
3430 struct scroll_bar
*bar
3431 = x_window_to_scroll_bar (event
.xexpose
.window
);
3434 x_scroll_bar_expose (bar
, &event
);
3435 #ifdef USE_X_TOOLKIT
3438 #endif /* USE_X_TOOLKIT */
3442 case GraphicsExpose
: /* This occurs when an XCopyArea's
3443 source area was obscured or not
3445 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3449 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3450 event
.xgraphicsexpose
.width
,
3451 event
.xgraphicsexpose
.height
);
3453 #ifdef USE_X_TOOLKIT
3456 #endif /* USE_X_TOOLKIT */
3459 case NoExpose
: /* This occurs when an XCopyArea's
3460 source area was completely
3465 f
= x_any_window_to_frame (event
.xunmap
.window
);
3466 if (f
) /* F may no longer exist if
3467 the frame was deleted. */
3469 /* While a frame is unmapped, display generation is
3470 disabled; you don't want to spend time updating a
3471 display that won't ever be seen. */
3472 f
->async_visible
= 0;
3473 /* We can't distinguish, from the event, whether the window
3474 has become iconified or invisible. So assume, if it
3475 was previously visible, than now it is iconified.
3476 We depend on x_make_frame_invisible to mark it iconified. */
3477 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3478 f
->async_iconified
= 1;
3480 bufp
->kind
= iconify_event
;
3481 XSETFRAME (bufp
->frame_or_window
, f
);
3486 #ifdef USE_X_TOOLKIT
3488 #endif /* USE_X_TOOLKIT */
3492 /* We use x_top_window_to_frame because map events can come
3493 for subwindows and they don't mean that the frame is visible. */
3494 f
= x_top_window_to_frame (event
.xmap
.window
);
3497 f
->async_visible
= 1;
3498 f
->async_iconified
= 0;
3500 /* wait_reading_process_input will notice this and update
3501 the frame's display structures. */
3502 SET_FRAME_GARBAGED (f
);
3504 bufp
->kind
= deiconify_event
;
3505 XSETFRAME (bufp
->frame_or_window
, f
);
3510 #ifdef USE_X_TOOLKIT
3512 #endif /* USE_X_TOOLKIT */
3515 /* Turn off processing if we become fully obscured. */
3516 case VisibilityNotify
:
3520 f
= x_any_window_to_frame (event
.xkey
.window
);
3524 KeySym keysym
, orig_keysym
;
3525 /* al%imercury@uunet.uu.net says that making this 81 instead of
3526 80 fixed a bug whereby meta chars made his Emacs hang. */
3527 unsigned char copy_buffer
[81];
3531 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3532 extra_keyboard_modifiers
);
3533 modifiers
= event
.xkey
.state
;
3535 /* This will have to go some day... */
3537 /* make_lispy_event turns chars into control chars.
3538 Don't do it here because XLookupString is too eager. */
3539 event
.xkey
.state
&= ~ControlMask
;
3540 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3541 80, &keysym
, &compose_status
);
3543 orig_keysym
= keysym
;
3547 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3548 || keysym
== XK_Delete
3549 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3550 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3552 /* This recognizes the "extended function keys".
3553 It seems there's no cleaner way.
3554 Test IsModifierKey to avoid handling mode_switch
3556 || ((unsigned) (keysym
) >= XK_Select
3557 && (unsigned)(keysym
) < XK_KP_Space
)
3559 #ifdef XK_dead_circumflex
3560 || orig_keysym
== XK_dead_circumflex
3562 #ifdef XK_dead_grave
3563 || orig_keysym
== XK_dead_grave
3565 #ifdef XK_dead_tilde
3566 || orig_keysym
== XK_dead_tilde
3568 #ifdef XK_dead_diaeresis
3569 || orig_keysym
== XK_dead_diaeresis
3571 #ifdef XK_dead_macron
3572 || orig_keysym
== XK_dead_macron
3574 #ifdef XK_dead_degree
3575 || orig_keysym
== XK_dead_degree
3577 #ifdef XK_dead_acute
3578 || orig_keysym
== XK_dead_acute
3580 #ifdef XK_dead_cedilla
3581 || orig_keysym
== XK_dead_cedilla
3583 #ifdef XK_dead_breve
3584 || orig_keysym
== XK_dead_breve
3586 #ifdef XK_dead_ogonek
3587 || orig_keysym
== XK_dead_ogonek
3589 #ifdef XK_dead_caron
3590 || orig_keysym
== XK_dead_caron
3592 #ifdef XK_dead_doubleacute
3593 || orig_keysym
== XK_dead_doubleacute
3595 #ifdef XK_dead_abovedot
3596 || orig_keysym
== XK_dead_abovedot
3598 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3599 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3600 /* Any "vendor-specific" key is ok. */
3601 || (orig_keysym
& (1 << 28)))
3602 && ! (IsModifierKey (orig_keysym
)
3604 #ifdef XK_Mode_switch
3605 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3608 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3610 #endif /* not HAVE_X11R5 */
3613 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3615 temp_buffer
[temp_index
++] = keysym
;
3616 bufp
->kind
= non_ascii_keystroke
;
3617 bufp
->code
= keysym
;
3618 XSETFRAME (bufp
->frame_or_window
, f
);
3620 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3622 bufp
->timestamp
= event
.xkey
.time
;
3627 else if (numchars
> nbytes
)
3631 for (i
= 0; i
< nbytes
; i
++)
3633 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3635 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3636 bufp
->kind
= ascii_keystroke
;
3637 bufp
->code
= copy_buffer
[i
];
3638 XSETFRAME (bufp
->frame_or_window
, f
);
3640 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3642 bufp
->timestamp
= event
.xkey
.time
;
3657 /* Here's a possible interpretation of the whole
3658 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3659 FocusIn event, you have to get a FocusOut event before you
3660 relinquish the focus. If you haven't received a FocusIn event,
3661 then a mere LeaveNotify is enough to free you. */
3664 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3666 if (event
.xcrossing
.focus
) /* Entered Window */
3668 /* Avoid nasty pop/raise loops. */
3669 if (f
&& (!(f
->auto_raise
)
3671 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3673 x_new_focus_frame (f
);
3674 enter_timestamp
= event
.xcrossing
.time
;
3677 else if (f
== x_focus_frame
)
3678 x_new_focus_frame (0);
3679 /* EnterNotify counts as mouse movement,
3680 so update things that depend on mouse position. */
3682 note_mouse_movement (f
, &event
.xmotion
);
3683 #ifdef USE_X_TOOLKIT
3685 #endif /* USE_X_TOOLKIT */
3689 f
= x_any_window_to_frame (event
.xfocus
.window
);
3690 if (event
.xfocus
.detail
!= NotifyPointer
)
3691 x_focus_event_frame
= f
;
3693 x_new_focus_frame (f
);
3694 #ifdef USE_X_TOOLKIT
3696 #endif /* USE_X_TOOLKIT */
3701 f
= x_top_window_to_frame (event
.xcrossing
.window
);
3704 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3705 /* If we move outside the frame,
3706 then we're certainly no longer on any text in the frame. */
3707 clear_mouse_face (dpyinfo
);
3709 if (event
.xcrossing
.focus
)
3713 if (f
== x_focus_event_frame
)
3714 x_focus_event_frame
= 0;
3715 if (f
== x_focus_frame
)
3716 x_new_focus_frame (0);
3719 #ifdef USE_X_TOOLKIT
3721 #endif /* USE_X_TOOLKIT */
3725 f
= x_any_window_to_frame (event
.xfocus
.window
);
3726 if (event
.xfocus
.detail
!= NotifyPointer
3727 && f
== x_focus_event_frame
)
3728 x_focus_event_frame
= 0;
3729 if (f
&& f
== x_focus_frame
)
3730 x_new_focus_frame (0);
3731 #ifdef USE_X_TOOLKIT
3733 #endif /* USE_X_TOOLKIT */
3738 if (dpyinfo
->grabbed
&& last_mouse_frame
3739 && FRAME_LIVE_P (last_mouse_frame
))
3740 f
= last_mouse_frame
;
3742 f
= x_window_to_frame (event
.xmotion
.window
);
3744 note_mouse_movement (f
, &event
.xmotion
);
3747 struct scroll_bar
*bar
3748 = x_window_to_scroll_bar (event
.xmotion
.window
);
3751 x_scroll_bar_note_movement (bar
, &event
);
3753 /* If we move outside the frame,
3754 then we're certainly no longer on any text in the frame. */
3755 clear_mouse_face (dpyinfo
);
3758 #if 0 /* This should be unnecessary, since the toolkit has no use
3759 for motion events that happen outside of the menu event loop,
3760 and it seems to cause the bug that mouse events stop coming
3762 #ifdef USE_X_TOOLKIT
3764 #endif /* USE_X_TOOLKIT */
3768 case ConfigureNotify
:
3769 f
= x_any_window_to_frame (event
.xconfigure
.window
);
3770 #ifdef USE_X_TOOLKIT
3773 && ! event
.xconfigure
.send_event
3775 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
3780 /* Find the position of the outside upper-left corner of
3781 the window, in the root coordinate system. Don't
3782 refer to the parent window here; we may be processing
3783 this event after the window manager has changed our
3784 parent, but before we have reached the ReparentNotify. */
3785 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3787 /* From-window, to-window. */
3788 XtWindow (f
->display
.x
->widget
),
3789 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3791 /* From-position, to-position. */
3792 -event
.xconfigure
.border_width
,
3793 -event
.xconfigure
.border_width
,
3798 event
.xconfigure
.x
= win_x
;
3799 event
.xconfigure
.y
= win_y
;
3801 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3802 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3803 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3804 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3806 /* What we have now is the position of Emacs's own window.
3807 Convert that to the position of the window manager window. */
3810 x_real_positions (f
, &x
, &y
);
3811 f
->display
.x
->left_pos
= x
;
3812 f
->display
.x
->top_pos
= y
;
3816 #else /* not USE_X_TOOLKIT */
3819 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3820 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3822 /* Even if the number of character rows and columns has
3823 not changed, the font size may have changed, so we need
3824 to check the pixel dimensions as well. */
3825 if (columns
!= f
->width
3826 || rows
!= f
->height
3827 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3828 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3830 change_frame_size (f
, rows
, columns
, 0, 1);
3831 SET_FRAME_GARBAGED (f
);
3834 if (! event
.xconfigure
.send_event
)
3839 /* Find the position of the outside upper-left corner of
3840 the window, in the root coordinate system. Don't
3841 refer to the parent window here; we may be processing
3842 this event after the window manager has changed our
3843 parent, but before we have reached the ReparentNotify. */
3844 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3846 /* From-window, to-window. */
3847 f
->display
.x
->window_desc
,
3848 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3850 /* From-position, to-position. */
3851 -event
.xconfigure
.border_width
,
3852 -event
.xconfigure
.border_width
,
3857 event
.xconfigure
.x
= win_x
;
3858 event
.xconfigure
.y
= win_y
;
3861 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3862 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3863 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3864 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3866 /* What we have now is the position of Emacs's own window.
3867 Convert that to the position of the window manager window. */
3870 x_real_positions (f
, &x
, &y
);
3871 f
->display
.x
->left_pos
= x
;
3872 f
->display
.x
->top_pos
= y
;
3873 if (y
!= event
.xconfigure
.y
)
3875 /* Since the WM decorations come below top_pos now,
3876 we must put them below top_pos in the future. */
3877 f
->display
.x
->win_gravity
= NorthWestGravity
;
3878 x_wm_set_size_hint (f
, 0, 0);
3882 #endif /* not USE_X_TOOLKIT */
3888 /* If we decide we want to generate an event to be seen
3889 by the rest of Emacs, we put it here. */
3890 struct input_event emacs_event
;
3891 emacs_event
.kind
= no_event
;
3893 bzero (&compose_status
, sizeof (compose_status
));
3895 if (dpyinfo
->grabbed
&& last_mouse_frame
3896 && FRAME_LIVE_P (last_mouse_frame
))
3897 f
= last_mouse_frame
;
3899 f
= x_window_to_frame (event
.xmotion
.window
);
3903 if (!x_focus_frame
|| (f
== x_focus_frame
))
3904 construct_mouse_click (&emacs_event
, &event
, f
);
3908 struct scroll_bar
*bar
3909 = x_window_to_scroll_bar (event
.xbutton
.window
);
3912 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3913 #ifdef USE_X_TOOLKIT
3916 /* Assume we have a menubar button press. A bad
3917 assumption should behave benignly. */
3918 popup_get_selection (&event
);
3921 #endif /* USE_X_TOOLKIT */
3924 if (event
.type
== ButtonPress
)
3926 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
3927 last_mouse_frame
= f
;
3931 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
3934 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3936 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3942 #ifdef USE_X_TOOLKIT
3944 #endif /* USE_X_TOOLKIT */
3948 case CirculateNotify
:
3950 case CirculateRequest
:
3954 /* Someone has changed the keyboard mapping - update the
3956 switch (event
.xmapping
.request
)
3958 case MappingModifier
:
3959 x_find_modifier_meanings (dpyinfo
);
3960 /* This is meant to fall through. */
3961 case MappingKeyboard
:
3962 XRefreshKeyboardMapping (&event
.xmapping
);
3964 #ifdef USE_X_TOOLKIT
3966 #endif /* USE_X_TOOLKIT */
3970 #ifdef USE_X_TOOLKIT
3973 XtDispatchEvent (&event
);
3975 #endif /* USE_X_TOOLKIT */
3981 /* On some systems, an X bug causes Emacs to get no more events
3982 when the window is destroyed. Detect that. (1994.) */
3985 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
3986 One XNOOP in 100 loops will make Emacs terminate.
3987 B. Bretthauer, 1994 */
3989 if (x_noop_count
>= 100)
3992 /* Use the first display in the list. Why not? */
3993 XNoOp (x_display_list
->display
);
3997 /* If the focus was just given to an autoraising frame,
3999 /* ??? This ought to be able to handle more than one such frame. */
4000 if (pending_autoraise_frame
)
4002 x_raise_frame (pending_autoraise_frame
);
4003 pending_autoraise_frame
= 0;
4010 /* Drawing the cursor. */
4013 /* Draw a hollow box cursor. Don't change the inside of the box. */
4019 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
4020 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
4021 int width
= FONT_WIDTH (f
->display
.x
->font
);
4022 int height
= f
->display
.x
->line_height
;
4024 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4025 f
->display
.x
->cursor_gc
,
4026 left
, top
, width
- 1, height
- 1);
4029 /* Clear the cursor of frame F to background color,
4030 and mark the cursor as not shown.
4031 This is used when the text where the cursor is
4032 is about to be rewritten. */
4040 if (! FRAME_VISIBLE_P (f
)
4041 || f
->phys_cursor_x
< 0)
4044 x_display_cursor (f
, 0);
4045 f
->phys_cursor_x
= -1;
4048 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4049 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4053 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4060 CHAR_TO_PIXEL_COL (f
, column
),
4061 CHAR_TO_PIXEL_ROW (f
, row
),
4062 &glyph
, 1, highlight
, 0);
4066 x_display_bar_cursor (f
, on
)
4070 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4072 /* This is pointless on invisible frames, and dangerous on garbaged
4073 frames; in the latter case, the frame may be in the midst of
4074 changing its size, and curs_x and curs_y may be off the frame. */
4075 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4078 if (! on
&& f
->phys_cursor_x
< 0)
4081 /* If we're not updating, then we want to use the current frame's
4082 cursor position, not our local idea of where the cursor ought to be. */
4083 if (f
!= updating_frame
)
4085 curs_x
= FRAME_CURSOR_X (f
);
4086 curs_y
= FRAME_CURSOR_Y (f
);
4089 /* If there is anything wrong with the current cursor state, remove it. */
4090 if (f
->phys_cursor_x
>= 0
4092 || f
->phys_cursor_x
!= curs_x
4093 || f
->phys_cursor_y
!= curs_y
4094 || f
->display
.x
->current_cursor
!= bar_cursor
))
4096 /* Erase the cursor by redrawing the character underneath it. */
4097 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4098 f
->phys_cursor_glyph
,
4099 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4100 f
->phys_cursor_x
= -1;
4103 /* If we now need a cursor in the new place or in the new form, do it so. */
4105 && (f
->phys_cursor_x
< 0
4106 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4108 f
->phys_cursor_glyph
4109 = ((current_glyphs
->enable
[curs_y
]
4110 && curs_x
< current_glyphs
->used
[curs_y
])
4111 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4113 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4114 f
->display
.x
->cursor_gc
,
4115 CHAR_TO_PIXEL_COL (f
, curs_x
),
4116 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4117 1, f
->display
.x
->line_height
);
4119 f
->phys_cursor_x
= curs_x
;
4120 f
->phys_cursor_y
= curs_y
;
4122 f
->display
.x
->current_cursor
= bar_cursor
;
4125 if (updating_frame
!= f
)
4126 XFlush (FRAME_X_DISPLAY (f
));
4130 /* Turn the displayed cursor of frame F on or off according to ON.
4131 If ON is nonzero, where to put the cursor is specified
4132 by F->cursor_x and F->cursor_y. */
4135 x_display_box_cursor (f
, on
)
4139 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4141 /* This is pointless on invisible frames, and dangerous on garbaged
4142 frames; in the latter case, the frame may be in the midst of
4143 changing its size, and curs_x and curs_y may be off the frame. */
4144 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4147 /* If cursor is off and we want it off, return quickly. */
4148 if (!on
&& f
->phys_cursor_x
< 0)
4151 /* If we're not updating, then we want to use the current frame's
4152 cursor position, not our local idea of where the cursor ought to be. */
4153 if (f
!= updating_frame
)
4155 curs_x
= FRAME_CURSOR_X (f
);
4156 curs_y
= FRAME_CURSOR_Y (f
);
4159 /* If cursor is currently being shown and we don't want it to be
4160 or it is in the wrong place,
4161 or we want a hollow box and it's not so, (pout!)
4163 if (f
->phys_cursor_x
>= 0
4165 || f
->phys_cursor_x
!= curs_x
4166 || f
->phys_cursor_y
!= curs_y
4167 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4168 && (f
!= x_highlight_frame
))))
4170 int mouse_face_here
= 0;
4171 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4173 /* If the cursor is in the mouse face area, redisplay that when
4174 we clear the cursor. */
4175 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4177 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4178 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4179 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4181 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4182 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4183 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4184 /* Don't redraw the cursor's spot in mouse face
4185 if it is at the end of a line (on a newline).
4186 The cursor appears there, but mouse highlighting does not. */
4187 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4188 mouse_face_here
= 1;
4190 /* If the font is not as tall as a whole line,
4191 we must explicitly clear the line's whole height. */
4192 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4193 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4194 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4195 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4196 FONT_WIDTH (f
->display
.x
->font
),
4197 f
->display
.x
->line_height
, False
);
4198 /* Erase the cursor by redrawing the character underneath it. */
4199 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4200 f
->phys_cursor_glyph
,
4203 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4204 f
->phys_cursor_x
= -1;
4207 /* If we want to show a cursor,
4208 or we want a box cursor and it's not so,
4209 write it in the right place. */
4211 && (f
->phys_cursor_x
< 0
4212 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4213 && f
== x_highlight_frame
)))
4215 f
->phys_cursor_glyph
4216 = ((current_glyphs
->enable
[curs_y
]
4217 && curs_x
< current_glyphs
->used
[curs_y
])
4218 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4220 if (f
!= x_highlight_frame
)
4223 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4227 x_draw_single_glyph (f
, curs_y
, curs_x
,
4228 f
->phys_cursor_glyph
, 2);
4229 f
->display
.x
->current_cursor
= filled_box_cursor
;
4232 f
->phys_cursor_x
= curs_x
;
4233 f
->phys_cursor_y
= curs_y
;
4236 if (updating_frame
!= f
)
4237 XFlush (FRAME_X_DISPLAY (f
));
4240 x_display_cursor (f
, on
)
4246 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4247 x_display_box_cursor (f
, on
);
4248 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4249 x_display_bar_cursor (f
, on
);
4251 /* Those are the only two we have implemented! */
4259 /* Refresh bitmap kitchen sink icon for frame F
4260 when we get an expose event for it. */
4265 /* Normally, the window manager handles this function. */
4268 /* Make the x-window of frame F use the gnu icon bitmap. */
4271 x_bitmap_icon (f
, file
)
4275 int mask
, bitmap_id
;
4278 if (FRAME_X_WINDOW (f
) == 0)
4281 /* Free up our existing icon bitmap if any. */
4282 if (f
->display
.x
->icon_bitmap
> 0)
4283 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4284 f
->display
.x
->icon_bitmap
= 0;
4287 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4290 /* Create the GNU bitmap if necessary. */
4291 if (!FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4292 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4293 = x_create_bitmap_from_data (f
, gnu_bits
,
4294 gnu_width
, gnu_height
);
4296 /* The first time we create the GNU bitmap,
4297 this increments the refcount one extra time.
4298 As a result, the GNU bitmap is never freed.
4299 That way, we don't have to worry about allocating it again. */
4300 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4302 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4305 x_wm_set_icon_pixmap (f
, bitmap_id
);
4306 f
->display
.x
->icon_bitmap
= bitmap_id
;
4312 /* Make the x-window of frame F use a rectangle with text. */
4315 x_text_icon (f
, icon_name
)
4319 if (FRAME_X_WINDOW (f
) == 0)
4323 f
->display
.x
->icon_label
= icon_name
;
4325 if (! f
->display
.x
->icon_label
)
4326 f
->display
.x
->icon_label
= " *emacs* ";
4329 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4330 (char *) f
->display
.x
->icon_label
);
4333 if (f
->display
.x
->icon_bitmap
> 0)
4334 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4335 f
->display
.x
->icon_bitmap
= 0;
4336 x_wm_set_icon_pixmap (f
, 0);
4341 /* Handling X errors. */
4343 /* Handle the loss of connection to display DISPLAY. */
4346 x_connection_closed (display
, error_message
)
4348 char *error_message
;
4350 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4351 Lisp_Object frame
, tail
;
4356 /* First delete frames whose minibuffers are on frames
4357 that are on the dead display. */
4358 FOR_EACH_FRAME (tail
, frame
)
4360 Lisp_Object minibuf_frame
;
4362 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4363 if (! EQ (frame
, minibuf_frame
)
4364 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4365 Fdelete_frame (frame
, Qt
);
4368 /* Now delete all remaining frames on the dead display.
4369 We are now sure none of these is used as the minibuffer
4370 for another frame that we need to delete. */
4371 FOR_EACH_FRAME (tail
, frame
)
4372 if (FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4373 Fdelete_frame (frame
, Qt
);
4375 x_delete_display (dpyinfo
);
4377 if (x_display_list
== 0)
4379 fprintf (stderr
, "%s", error_message
);
4380 shut_down_emacs (0, 0, Qnil
);
4384 /* Ordinary stack unwind doesn't deal with these. */
4386 sigunblock (sigmask (SIGIO
));
4388 sigunblock (sigmask (SIGALRM
));
4389 TOTALLY_UNBLOCK_INPUT
;
4391 error ("%s", error_message
);
4394 /* This is the usual handler for X protocol errors.
4395 It kills all frames on the display that we got the error for.
4396 If that was the only one, it prints an error message and kills Emacs. */
4399 x_error_quitter (display
, error
)
4403 char buf
[256], buf1
[356];
4405 /* Note that there is no real way portable across R3/R4 to get the
4406 original error handler. */
4408 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4409 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4410 buf
, error
->request_code
);
4411 x_connection_closed (display
, buf1
);
4414 /* This is the handler for X IO errors, always.
4415 It kills all frames on the display that we lost touch with.
4416 If that was the only one, it prints an error message and kills Emacs. */
4419 x_io_error_quitter (display
)
4424 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4425 x_connection_closed (display
, buf
);
4428 /* A buffer for storing X error messages. */
4429 static char *x_caught_error_message
;
4430 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4432 /* An X error handler which stores the error message in
4433 x_caught_error_message. This is what's installed when
4434 x_catch_errors is in effect. */
4437 x_error_catcher (display
, error
)
4441 XGetErrorText (display
, error
->error_code
,
4442 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4446 /* Begin trapping X errors for display DPY. Actually we trap X errors
4447 for all displays, but DPY should be the display you are actually
4450 After calling this function, X protocol errors no longer cause
4451 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4453 Calling x_check_errors signals an Emacs error if an X error has
4454 occurred since the last call to x_catch_errors or x_check_errors.
4456 Calling x_uncatch_errors resumes the normal error handling. */
4458 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4461 x_catch_errors (dpy
)
4464 /* Make sure any errors from previous requests have been dealt with. */
4467 /* Set up the error buffer. */
4468 x_caught_error_message
4469 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4470 x_caught_error_message
[0] = '\0';
4472 /* Install our little error handler. */
4473 XSetErrorHandler (x_error_catcher
);
4476 /* If any X protocol errors have arrived since the last call to
4477 x_catch_errors or x_check_errors, signal an Emacs error using
4478 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4481 x_check_errors (dpy
, format
)
4485 /* Make sure to catch any errors incurred so far. */
4488 if (x_caught_error_message
[0])
4490 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4492 sprintf (buf
, format
, x_caught_error_message
);
4493 x_uncatch_errors (dpy
);
4498 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4501 x_had_errors_p (dpy
)
4504 /* Make sure to catch any errors incurred so far. */
4507 return x_caught_error_message
[0] != 0;
4510 /* Stop catching X protocol errors and let them make Emacs die. */
4513 x_uncatch_errors (dpy
)
4516 xfree (x_caught_error_message
);
4517 x_caught_error_message
= 0;
4518 XSetErrorHandler (x_error_quitter
);
4522 static unsigned int x_wire_count
;
4525 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4530 /* Changing the font of the frame. */
4532 /* Give frame F the font named FONTNAME as its default font, and
4533 return the full name of that font. FONTNAME may be a wildcard
4534 pattern; in that case, we choose some font that fits the pattern.
4535 The return value shows which font we chose. */
4538 x_new_font (f
, fontname
)
4540 register char *fontname
;
4543 int n_matching_fonts
;
4544 XFontStruct
*font_info
;
4547 /* Get a list of all the fonts that match this name. Once we
4548 have a list of matching fonts, we compare them against the fonts
4549 we already have by comparing font ids. */
4550 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4551 1024, &n_matching_fonts
);
4552 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4553 find any matches; font_names == 0 is the only clue. */
4555 n_matching_fonts
= 0;
4557 /* Don't just give up if n_matching_fonts is 0.
4558 Apparently there's a bug on Suns: XListFontsWithInfo can
4559 fail to find a font, but XLoadQueryFont may still find it. */
4561 /* See if we've already loaded a matching font. */
4562 already_loaded
= -1;
4563 if (n_matching_fonts
!= 0)
4567 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4568 for (j
= 0; j
< n_matching_fonts
; j
++)
4569 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4570 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4573 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4579 /* If we have, just return it from the table. */
4580 if (already_loaded
>= 0)
4581 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4582 /* Otherwise, load the font and add it to the table. */
4590 /* Try to find a character-cell font in the list. */
4592 /* A laudable goal, but this isn't how to do it. */
4593 for (i
= 0; i
< n_matching_fonts
; i
++)
4594 if (! font_info
[i
].per_char
)
4600 /* See comment above. */
4601 if (n_matching_fonts
!= 0)
4602 fontname
= font_names
[i
];
4604 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4607 /* Free the information from XListFonts. */
4608 if (n_matching_fonts
)
4609 XFreeFontNames (font_names
);
4613 /* Do we need to create the table? */
4614 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4616 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4617 FRAME_X_DISPLAY_INFO (f
)->font_table
4618 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4619 * sizeof (struct font_info
));
4621 /* Do we need to grow the table? */
4622 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4623 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4625 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4626 FRAME_X_DISPLAY_INFO (f
)->font_table
4627 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4628 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4629 * sizeof (struct font_info
)));
4632 /* Try to get the full name of FONT. Put it in full_name. */
4634 for (i
= 0; i
< font
->n_properties
; i
++)
4637 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4638 if (!strcmp (atom
, "FONT"))
4640 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4641 (Atom
) (font
->properties
[i
].card32
));
4645 /* Count the number of dashes in the "full name".
4646 If it is too few, this isn't really the font's full name,
4648 In X11R4, the fonts did not come with their canonical names
4666 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4667 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4668 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4670 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4672 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4673 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4674 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4677 fontname
= full_name
;
4680 /* Compute the scroll bar width in character columns. */
4681 if (f
->scroll_bar_pixel_width
> 0)
4683 int wid
= FONT_WIDTH (f
->display
.x
->font
);
4684 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4687 f
->scroll_bar_cols
= 2;
4689 /* Now make the frame display the given font. */
4690 if (FRAME_X_WINDOW (f
) != 0)
4692 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->normal_gc
,
4693 f
->display
.x
->font
->fid
);
4694 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->reverse_gc
,
4695 f
->display
.x
->font
->fid
);
4696 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->cursor_gc
,
4697 f
->display
.x
->font
->fid
);
4699 frame_update_line_height (f
);
4700 x_set_window_size (f
, 0, f
->width
, f
->height
);
4703 /* If we are setting a new frame's font for the first time,
4704 there are no faces yet, so this font's height is the line height. */
4705 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
4708 Lisp_Object lispy_name
;
4710 lispy_name
= build_string (fontname
);
4712 /* Free the information from XListFonts. The data
4713 we actually retain comes from XLoadQueryFont. */
4714 XFreeFontNames (font_names
);
4720 x_calc_absolute_position (f
)
4724 int win_x
= 0, win_y
= 0;
4725 int flags
= f
->display
.x
->size_hint_flags
;
4727 /* Find the position of the outside upper-left corner of
4728 the inner window, with respect to the outer window. */
4729 if (f
->display
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4732 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4734 /* From-window, to-window. */
4735 f
->display
.x
->window_desc
,
4736 f
->display
.x
->parent_desc
,
4738 /* From-position, to-position. */
4739 0, 0, &win_x
, &win_y
,
4746 /* Treat negative positions as relative to the leftmost bottommost
4747 position that fits on the screen. */
4748 if (flags
& XNegative
)
4749 f
->display
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4750 - 2 * f
->display
.x
->border_width
- win_x
4752 + f
->display
.x
->left_pos
);
4754 if (flags
& YNegative
)
4755 f
->display
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
4756 - 2 * f
->display
.x
->border_width
- win_y
4758 + f
->display
.x
->top_pos
);
4759 /* The left_pos and top_pos
4760 are now relative to the top and left screen edges,
4761 so the flags should correspond. */
4762 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4765 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4766 to really change the position, and 0 when calling from
4767 x_make_frame_visible (in that case, XOFF and YOFF are the current
4768 position values). */
4770 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4772 register int xoff
, yoff
;
4777 f
->display
.x
->top_pos
= yoff
;
4778 f
->display
.x
->left_pos
= xoff
;
4779 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4781 f
->display
.x
->size_hint_flags
|= XNegative
;
4783 f
->display
.x
->size_hint_flags
|= YNegative
;
4784 f
->display
.x
->win_gravity
= NorthWestGravity
;
4786 x_calc_absolute_position (f
);
4789 x_wm_set_size_hint (f
, 0, 0);
4791 #ifdef USE_X_TOOLKIT
4792 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
),
4793 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4794 #else /* not USE_X_TOOLKIT */
4795 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4796 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4797 #endif /* not USE_X_TOOLKIT */
4801 /* Call this to change the size of frame F's x-window.
4802 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4803 for this size change and subsequent size changes.
4804 Otherwise we leave the window gravity unchanged. */
4806 x_set_window_size (f
, change_gravity
, cols
, rows
)
4811 int pixelwidth
, pixelheight
;
4814 #ifdef USE_X_TOOLKIT
4817 /* The x and y position of the widget is clobbered by the
4818 call to XtSetValues within EmacsFrameSetCharSize.
4819 This is a real kludge, but I don't understand Xt so I can't
4820 figure out a correct fix. Can anyone else tell me? -- rms. */
4821 int xpos
= f
->display
.x
->widget
->core
.x
;
4822 int ypos
= f
->display
.x
->widget
->core
.y
;
4823 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4824 f
->display
.x
->widget
->core
.x
= xpos
;
4825 f
->display
.x
->widget
->core
.y
= ypos
;
4829 #else /* not USE_X_TOOLKIT */
4833 check_frame_size (f
, &rows
, &cols
);
4834 f
->display
.x
->vertical_scroll_bar_extra
4835 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4837 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4838 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4839 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
4840 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4841 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4843 f
->display
.x
->win_gravity
= NorthWestGravity
;
4844 x_wm_set_size_hint (f
, 0, 0);
4846 XSync (FRAME_X_DISPLAY (f
), False
);
4847 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4848 pixelwidth
, pixelheight
);
4850 /* Now, strictly speaking, we can't be sure that this is accurate,
4851 but the window manager will get around to dealing with the size
4852 change request eventually, and we'll hear how it went when the
4853 ConfigureNotify event gets here.
4855 We could just not bother storing any of this information here,
4856 and let the ConfigureNotify event set everything up, but that
4857 might be kind of confusing to the lisp code, since size changes
4858 wouldn't be reported in the frame parameters until some random
4859 point in the future when the ConfigureNotify event arrives. */
4860 change_frame_size (f
, rows
, cols
, 0, 0);
4861 PIXEL_WIDTH (f
) = pixelwidth
;
4862 PIXEL_HEIGHT (f
) = pixelheight
;
4864 /* If cursor was outside the new size, mark it as off. */
4865 if (f
->phys_cursor_y
>= rows
4866 || f
->phys_cursor_x
>= cols
)
4868 f
->phys_cursor_x
= -1;
4869 f
->phys_cursor_y
= -1;
4872 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4873 receive in the ConfigureNotify event; if we get what we asked
4874 for, then the event won't cause the screen to become garbaged, so
4875 we have to make sure to do it here. */
4876 SET_FRAME_GARBAGED (f
);
4878 XFlush (FRAME_X_DISPLAY (f
));
4880 #endif /* not USE_X_TOOLKIT */
4883 /* Mouse warping, focus shifting, raising and lowering. */
4886 x_set_mouse_position (f
, x
, y
)
4892 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4893 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
4895 if (pix_x
< 0) pix_x
= 0;
4896 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4898 if (pix_y
< 0) pix_y
= 0;
4899 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4903 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4904 0, 0, 0, 0, pix_x
, pix_y
);
4908 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
4911 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4917 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4918 0, 0, 0, 0, pix_x
, pix_y
);
4922 x_focus_on_frame (f
)
4925 #if 0 /* This proves to be unpleasant. */
4929 /* I don't think that the ICCCM allows programs to do things like this
4930 without the interaction of the window manager. Whatever you end up
4931 doing with this code, do it to x_unfocus_frame too. */
4932 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4933 RevertToPointerRoot
, CurrentTime
);
4941 /* Look at the remarks in x_focus_on_frame. */
4942 if (x_focus_frame
== f
)
4943 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
4944 RevertToPointerRoot
, CurrentTime
);
4948 /* Raise frame F. */
4953 if (f
->async_visible
)
4956 #ifdef USE_X_TOOLKIT
4957 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4958 #else /* not USE_X_TOOLKIT */
4959 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4960 #endif /* not USE_X_TOOLKIT */
4961 XFlush (FRAME_X_DISPLAY (f
));
4966 /* Lower frame F. */
4971 if (f
->async_visible
)
4974 #ifdef USE_X_TOOLKIT
4975 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4976 #else /* not USE_X_TOOLKIT */
4977 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4978 #endif /* not USE_X_TOOLKIT */
4979 XFlush (FRAME_X_DISPLAY (f
));
4985 XTframe_raise_lower (f
, raise
)
4995 /* Change from withdrawn state to mapped state,
4998 x_make_frame_visible (f
)
5006 type
= x_icon_type (f
);
5008 x_bitmap_icon (f
, type
);
5010 if (! FRAME_VISIBLE_P (f
))
5012 #ifndef USE_X_TOOLKIT
5013 if (! FRAME_ICONIFIED_P (f
))
5014 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5017 if (! EQ (Vx_no_window_manager
, Qt
))
5018 x_wm_set_window_state (f
, NormalState
);
5019 #ifdef USE_X_TOOLKIT
5020 /* This was XtPopup, but that did nothing for an iconified frame. */
5021 XtMapWidget (f
->display
.x
->widget
);
5022 #else /* not USE_X_TOOLKIT */
5023 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5024 #endif /* not USE_X_TOOLKIT */
5025 #if 0 /* This seems to bring back scroll bars in the wrong places
5026 if the window configuration has changed. They seem
5027 to come back ok without this. */
5028 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5029 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5033 XFlush (FRAME_X_DISPLAY (f
));
5035 /* Synchronize to ensure Emacs knows the frame is visible
5036 before we do anything else. We do this loop with input not blocked
5037 so that incoming events are handled. */
5040 int count
= input_signal_count
;
5042 /* This must come after we set COUNT. */
5045 XSETFRAME (frame
, f
);
5050 /* Once we have handled input events,
5051 we should have received the MapNotify if one is coming.
5052 So if we have not got it yet, stop looping.
5053 Some window managers make their own decisions
5054 about visibility. */
5055 if (input_signal_count
!= count
)
5057 /* Machines that do polling rather than SIGIO have been observed
5058 to go into a busy-wait here. So we'll fake an alarm signal
5059 to let the handler know that there's something to be read.
5060 We used to raise a real alarm, but it seems that the handler
5061 isn't always enabled here. This is probably a bug. */
5062 if (input_polling_used ())
5064 /* It could be confusing if a real alarm arrives while processing
5065 the fake one. Turn it off and let the handler reset it. */
5067 input_poll_signal ();
5069 /* Once we have handled input events,
5070 we should have received the MapNotify if one is coming.
5071 So if we have not got it yet, stop looping.
5072 Some window managers make their own decisions
5073 about visibility. */
5074 if (input_signal_count
!= count
)
5077 FRAME_SAMPLE_VISIBILITY (f
);
5081 /* Change from mapped state to withdrawn state. */
5083 x_make_frame_invisible (f
)
5089 #ifdef USE_X_TOOLKIT
5090 /* Use the frame's outermost window, not the one we normally draw on. */
5091 window
= XtWindow (f
->display
.x
->widget
);
5092 #else /* not USE_X_TOOLKIT */
5093 window
= FRAME_X_WINDOW (f
);
5094 #endif /* not USE_X_TOOLKIT */
5096 /* Don't keep the highlight on an invisible frame. */
5097 if (x_highlight_frame
== f
)
5098 x_highlight_frame
= 0;
5100 #if 0/* This might add unreliability; I don't trust it -- rms. */
5101 if (! f
->async_visible
&& ! f
->async_iconified
)
5107 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5108 that the current position of the window is user-specified, rather than
5109 program-specified, so that when the window is mapped again, it will be
5110 placed at the same location, without forcing the user to position it
5111 by hand again (they have already done that once for this window.) */
5112 x_wm_set_size_hint (f
, 0, 1);
5116 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5117 DefaultScreen (FRAME_X_DISPLAY (f
))))
5119 UNBLOCK_INPUT_RESIGNAL
;
5120 error ("Can't notify window manager of window withdrawal");
5122 #else /* ! defined (HAVE_X11R4) */
5124 /* Tell the window manager what we're going to do. */
5125 if (! EQ (Vx_no_window_manager
, Qt
))
5129 unmap
.xunmap
.type
= UnmapNotify
;
5130 unmap
.xunmap
.window
= window
;
5131 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5132 unmap
.xunmap
.from_configure
= False
;
5133 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5134 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5136 SubstructureRedirectMask
|SubstructureNotifyMask
,
5139 UNBLOCK_INPUT_RESIGNAL
;
5140 error ("Can't notify window manager of withdrawal");
5144 /* Unmap the window ourselves. Cheeky! */
5145 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5146 #endif /* ! defined (HAVE_X11R4) */
5148 /* We can't distinguish this from iconification
5149 just by the event that we get from the server.
5150 So we can't win using the usual strategy of letting
5151 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5152 and synchronize with the server to make sure we agree. */
5154 FRAME_ICONIFIED_P (f
) = 0;
5155 f
->async_visible
= 0;
5156 f
->async_iconified
= 0;
5163 /* Change window state from mapped to iconified. */
5172 /* Don't keep the highlight on an invisible frame. */
5173 if (x_highlight_frame
== f
)
5174 x_highlight_frame
= 0;
5176 if (f
->async_iconified
)
5181 type
= x_icon_type (f
);
5183 x_bitmap_icon (f
, type
);
5185 #ifdef USE_X_TOOLKIT
5187 if (! FRAME_VISIBLE_P (f
))
5189 if (! EQ (Vx_no_window_manager
, Qt
))
5190 x_wm_set_window_state (f
, IconicState
);
5191 /* This was XtPopup, but that did nothing for an iconified frame. */
5192 XtMapWidget (f
->display
.x
->widget
);
5197 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5198 XtWindow (f
->display
.x
->widget
),
5199 DefaultScreen (FRAME_X_DISPLAY (f
)));
5203 error ("Can't notify window manager of iconification");
5205 f
->async_iconified
= 1;
5208 XFlush (FRAME_X_DISPLAY (f
));
5210 #else /* not USE_X_TOOLKIT */
5212 /* Make sure the X server knows where the window should be positioned,
5213 in case the user deiconifies with the window manager. */
5214 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5215 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5217 /* Since we don't know which revision of X we're running, we'll use both
5218 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5220 /* X11R4: send a ClientMessage to the window manager using the
5221 WM_CHANGE_STATE type. */
5225 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5226 message
.xclient
.type
= ClientMessage
;
5227 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5228 message
.xclient
.format
= 32;
5229 message
.xclient
.data
.l
[0] = IconicState
;
5231 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5232 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5234 SubstructureRedirectMask
| SubstructureNotifyMask
,
5237 UNBLOCK_INPUT_RESIGNAL
;
5238 error ("Can't notify window manager of iconification");
5242 /* X11R3: set the initial_state field of the window manager hints to
5244 x_wm_set_window_state (f
, IconicState
);
5246 if (!FRAME_VISIBLE_P (f
))
5248 /* If the frame was withdrawn, before, we must map it. */
5249 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5252 f
->async_iconified
= 1;
5254 XFlush (FRAME_X_DISPLAY (f
));
5256 #endif /* not USE_X_TOOLKIT */
5259 /* Destroy the X window of frame F. */
5261 x_destroy_window (f
)
5264 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5268 if (f
->display
.x
->icon_desc
!= 0)
5269 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->icon_desc
);
5270 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->window_desc
);
5271 #ifdef USE_X_TOOLKIT
5272 XtDestroyWidget (f
->display
.x
->widget
);
5273 free_frame_menubar (f
);
5274 #endif /* USE_X_TOOLKIT */
5276 free_frame_faces (f
);
5277 XFlush (FRAME_X_DISPLAY (f
));
5279 xfree (f
->display
.x
);
5281 if (f
== x_focus_frame
)
5283 if (f
== x_highlight_frame
)
5284 x_highlight_frame
= 0;
5286 dpyinfo
->reference_count
--;
5288 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5290 dpyinfo
->mouse_face_beg_row
5291 = dpyinfo
->mouse_face_beg_col
= -1;
5292 dpyinfo
->mouse_face_end_row
5293 = dpyinfo
->mouse_face_end_col
= -1;
5294 dpyinfo
->mouse_face_window
= Qnil
;
5300 /* Setting window manager hints. */
5302 /* Set the normal size hints for the window manager, for frame F.
5303 FLAGS is the flags word to use--or 0 meaning preserve the flags
5304 that the window now has.
5305 If USER_POSITION is nonzero, we set the USPosition
5306 flag (this is useful when FLAGS is 0). */
5308 x_wm_set_size_hint (f
, flags
, user_position
)
5313 XSizeHints size_hints
;
5315 #ifdef USE_X_TOOLKIT
5318 Dimension widget_width
, widget_height
;
5319 Window window
= XtWindow (f
->display
.x
->widget
);
5320 #else /* not USE_X_TOOLKIT */
5321 Window window
= FRAME_X_WINDOW (f
);
5322 #endif /* not USE_X_TOOLKIT */
5324 /* Setting PMaxSize caused various problems. */
5325 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5327 flexlines
= f
->height
;
5329 size_hints
.x
= f
->display
.x
->left_pos
;
5330 size_hints
.y
= f
->display
.x
->top_pos
;
5332 #ifdef USE_X_TOOLKIT
5333 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5334 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5335 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5336 size_hints
.height
= widget_height
;
5337 size_hints
.width
= widget_width
;
5338 #else /* not USE_X_TOOLKIT */
5339 size_hints
.height
= PIXEL_HEIGHT (f
);
5340 size_hints
.width
= PIXEL_WIDTH (f
);
5341 #endif /* not USE_X_TOOLKIT */
5343 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5344 size_hints
.height_inc
= f
->display
.x
->line_height
;
5345 size_hints
.max_width
5346 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5347 size_hints
.max_height
5348 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5351 int base_width
, base_height
;
5352 int min_rows
= 0, min_cols
= 0;
5354 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5355 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5357 check_frame_size (f
, &min_rows
, &min_cols
);
5359 /* The window manager uses the base width hints to calculate the
5360 current number of rows and columns in the frame while
5361 resizing; min_width and min_height aren't useful for this
5362 purpose, since they might not give the dimensions for a
5363 zero-row, zero-column frame.
5365 We use the base_width and base_height members if we have
5366 them; otherwise, we set the min_width and min_height members
5367 to the size for a zero x zero frame. */
5370 size_hints
.flags
|= PBaseSize
;
5371 size_hints
.base_width
= base_width
;
5372 size_hints
.base_height
= base_height
;
5373 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5374 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5376 size_hints
.min_width
= base_width
;
5377 size_hints
.min_height
= base_height
;
5382 size_hints
.flags
|= flags
;
5385 XSizeHints hints
; /* Sometimes I hate X Windows... */
5386 long supplied_return
;
5390 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5393 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5398 if (hints
.flags
& PSize
)
5399 size_hints
.flags
|= PSize
;
5400 if (hints
.flags
& PPosition
)
5401 size_hints
.flags
|= PPosition
;
5402 if (hints
.flags
& USPosition
)
5403 size_hints
.flags
|= USPosition
;
5404 if (hints
.flags
& USSize
)
5405 size_hints
.flags
|= USSize
;
5409 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5410 size_hints
.flags
|= PWinGravity
;
5414 size_hints
.flags
&= ~ PPosition
;
5415 size_hints
.flags
|= USPosition
;
5417 #endif /* PWinGravity */
5420 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5422 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5426 /* Used for IconicState or NormalState */
5427 x_wm_set_window_state (f
, state
)
5431 #ifdef USE_X_TOOLKIT
5434 XtSetArg (al
[0], XtNinitialState
, state
);
5435 XtSetValues (f
->display
.x
->widget
, al
, 1);
5436 #else /* not USE_X_TOOLKIT */
5437 Window window
= FRAME_X_WINDOW (f
);
5439 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5440 f
->display
.x
->wm_hints
.initial_state
= state
;
5442 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5443 #endif /* not USE_X_TOOLKIT */
5446 x_wm_set_icon_pixmap (f
, pixmap_id
)
5450 #ifdef USE_X_TOOLKIT
5451 Window window
= XtWindow (f
->display
.x
->widget
);
5453 Window window
= FRAME_X_WINDOW (f
);
5458 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5459 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5460 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5464 f
->display
.x
->wm_hints
.icon_pixmap
= None
;
5465 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5468 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5471 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5475 #ifdef USE_X_TOOLKIT
5476 Window window
= XtWindow (f
->display
.x
->widget
);
5478 Window window
= FRAME_X_WINDOW (f
);
5481 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5482 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5483 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5485 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5489 /* Initialization. */
5491 #ifdef USE_X_TOOLKIT
5492 static XrmOptionDescRec emacs_options
[] = {
5493 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5494 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5496 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5497 XrmoptionSepArg
, NULL
},
5498 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5500 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5501 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5502 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5503 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5504 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5505 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5506 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5508 #endif /* USE_X_TOOLKIT */
5510 static int x_initialized
;
5512 struct x_display_info
*
5513 x_term_init (display_name
, xrm_option
, resource_name
)
5514 Lisp_Object display_name
;
5516 char *resource_name
;
5522 struct x_display_info
*dpyinfo
;
5531 #ifdef USE_X_TOOLKIT
5533 XtSetLanguageProc (NULL
, NULL
, NULL
);
5544 argv
[argc
++] = "-xrm";
5545 argv
[argc
++] = xrm_option
;
5547 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5548 resource_name
, EMACS_CLASS
,
5549 emacs_options
, XtNumber (emacs_options
),
5553 #else /* not USE_X_TOOLKIT */
5555 XSetLocaleModifiers ("");
5557 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5558 #endif /* not USE_X_TOOLKIT */
5560 /* Detect failure. */
5564 /* We have definitely succeeded. Record the new connection. */
5566 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5568 /* Put this display on the chain. */
5569 dpyinfo
->next
= x_display_list
;
5570 x_display_list
= dpyinfo
;
5572 /* Put it on x_display_name_list as well, to keep them parallel. */
5573 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5574 x_display_name_list
);
5575 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5577 dpyinfo
->display
= dpy
;
5580 XSetAfterFunction (x_current_display
, x_trace_wire
);
5584 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5585 + XSTRING (Vsystem_name
)->size
5587 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5588 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5590 /* Figure out which modifier bits mean what. */
5591 x_find_modifier_meanings (dpyinfo
);
5593 /* Get the scroll bar cursor. */
5594 dpyinfo
->vertical_scroll_bar_cursor
5595 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5597 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5598 resource_name
, EMACS_CLASS
);
5599 #ifdef HAVE_XRMSETDATABASE
5600 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5602 dpyinfo
->display
->db
= xrdb
;
5604 /* Put thr rdb where we can find it in a way that works on
5606 dpyinfo
->xrdb
= xrdb
;
5608 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5609 DefaultScreen (dpyinfo
->display
));
5610 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5611 &dpyinfo
->n_planes
);
5612 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
5613 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
5614 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
5615 dpyinfo
->grabbed
= 0;
5616 dpyinfo
->reference_count
= 0;
5617 dpyinfo
->icon_bitmap_id
= -1;
5618 dpyinfo
->n_fonts
= 0;
5619 dpyinfo
->font_table_size
= 0;
5620 dpyinfo
->bitmaps
= 0;
5621 dpyinfo
->bitmaps_size
= 0;
5622 dpyinfo
->bitmaps_last
= 0;
5623 dpyinfo
->scratch_cursor_gc
= 0;
5624 dpyinfo
->mouse_face_mouse_frame
= 0;
5625 dpyinfo
->mouse_face_deferred_gc
= 0;
5626 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5627 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5628 dpyinfo
->mouse_face_face_id
= 0;
5629 dpyinfo
->mouse_face_window
= Qnil
;
5630 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
5631 dpyinfo
->mouse_face_defer
= 0;
5633 dpyinfo
->Xatom_wm_protocols
5634 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
5635 dpyinfo
->Xatom_wm_take_focus
5636 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
5637 dpyinfo
->Xatom_wm_save_yourself
5638 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
5639 dpyinfo
->Xatom_wm_delete_window
5640 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
5641 dpyinfo
->Xatom_wm_change_state
5642 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
5643 dpyinfo
->Xatom_wm_configure_denied
5644 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
5645 dpyinfo
->Xatom_wm_window_moved
5646 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
5647 dpyinfo
->Xatom_editres
5648 = XInternAtom (dpyinfo
->display
, "Editres", False
);
5649 dpyinfo
->Xatom_CLIPBOARD
5650 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
5651 dpyinfo
->Xatom_TIMESTAMP
5652 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
5654 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
5655 dpyinfo
->Xatom_DELETE
5656 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
5657 dpyinfo
->Xatom_MULTIPLE
5658 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
5660 = XInternAtom (dpyinfo
->display
, "INCR", False
);
5661 dpyinfo
->Xatom_EMACS_TMP
5662 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
5663 dpyinfo
->Xatom_TARGETS
5664 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
5666 = XInternAtom (dpyinfo
->display
, "NULL", False
);
5667 dpyinfo
->Xatom_ATOM_PAIR
5668 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
5670 connection
= ConnectionNumber (dpyinfo
->display
);
5671 dpyinfo
->connection
= connection
;
5674 /* This is only needed for distinguishing keyboard and process input. */
5675 if (connection
!= 0)
5676 add_keyboard_wait_descriptor (connection
);
5679 #ifndef F_SETOWN_BUG
5681 #ifdef F_SETOWN_SOCK_NEG
5682 /* stdin is a socket here */
5683 fcntl (connection
, F_SETOWN
, -getpid ());
5684 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5685 fcntl (connection
, F_SETOWN
, getpid ());
5686 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5687 #endif /* ! defined (F_SETOWN) */
5688 #endif /* F_SETOWN_BUG */
5691 init_sigio (connection
);
5692 #endif /* ! defined (SIGIO) */
5697 /* Get rid of display DPYINFO, assuming all frames are already gone,
5698 and without sending any more commands to the X server. */
5701 x_delete_display (dpyinfo
)
5702 struct x_display_info
*dpyinfo
;
5704 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
5706 /* Discard this display from x_display_name_list and x_display_list.
5707 We can't use Fdelq because that can quit. */
5708 if (! NILP (x_display_name_list
)
5709 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
5710 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
5715 tail
= x_display_name_list
;
5716 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
5718 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
5719 dpyinfo
->name_list_element
))
5721 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
5724 tail
= XCONS (tail
)->cdr
;
5728 if (x_display_list
== dpyinfo
)
5729 x_display_list
= dpyinfo
->next
;
5732 struct x_display_info
*tail
;
5734 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
5735 if (tail
->next
== dpyinfo
)
5736 tail
->next
= tail
->next
->next
;
5739 #ifndef USE_X_TOOLKIT
5740 /* I'm told Xt does this itself. */
5741 XrmDestroyDatabase (dpyinfo
->xrdb
);
5743 free (dpyinfo
->font_table
);
5744 free (dpyinfo
->x_id_name
);
5748 /* Set up use of X before we make the first connection. */
5752 clear_frame_hook
= XTclear_frame
;
5753 clear_end_of_line_hook
= XTclear_end_of_line
;
5754 ins_del_lines_hook
= XTins_del_lines
;
5755 change_line_highlight_hook
= XTchange_line_highlight
;
5756 insert_glyphs_hook
= XTinsert_glyphs
;
5757 write_glyphs_hook
= XTwrite_glyphs
;
5758 delete_glyphs_hook
= XTdelete_glyphs
;
5759 ring_bell_hook
= XTring_bell
;
5760 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5761 set_terminal_modes_hook
= XTset_terminal_modes
;
5762 update_begin_hook
= XTupdate_begin
;
5763 update_end_hook
= XTupdate_end
;
5764 set_terminal_window_hook
= XTset_terminal_window
;
5765 read_socket_hook
= XTread_socket
;
5766 frame_up_to_date_hook
= XTframe_up_to_date
;
5767 cursor_to_hook
= XTcursor_to
;
5768 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5769 mouse_position_hook
= XTmouse_position
;
5770 frame_rehighlight_hook
= XTframe_rehighlight
;
5771 frame_raise_lower_hook
= XTframe_raise_lower
;
5772 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5773 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5774 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5775 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5777 scroll_region_ok
= 1; /* we'll scroll partial frames */
5778 char_ins_del_ok
= 0; /* just as fast to write the line */
5779 line_ins_del_ok
= 1; /* we'll just blt 'em */
5780 fast_clear_end_of_line
= 1; /* X does this well */
5781 memory_below_frame
= 0; /* we don't remember what scrolls
5787 x_focus_frame
= x_highlight_frame
= 0;
5789 /* Try to use interrupt input; if we can't, then start polling. */
5790 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5792 #ifdef USE_X_TOOLKIT
5793 XtToolkitInitialize ();
5794 Xt_app_con
= XtCreateApplicationContext ();
5797 /* Note that there is no real way portable across R3/R4 to get the
5798 original error handler. */
5799 XSetErrorHandler (x_error_quitter
);
5800 XSetIOErrorHandler (x_io_error_quitter
);
5802 /* Disable Window Change signals; they are handled by X events. */
5804 signal (SIGWINCH
, SIG_DFL
);
5805 #endif /* ! defined (SIGWINCH) */
5807 signal (SIGPIPE
, x_connection_closed
);
5813 staticpro (&x_display_name_list
);
5814 x_display_name_list
= Qnil
;
5816 staticpro (&last_mouse_scroll_bar
);
5817 last_mouse_scroll_bar
= Qnil
;
5819 #endif /* ! defined (HAVE_X_WINDOWS) */