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 #include <sys/param.h>
69 #include "dispextern.h"
70 #include "termhooks.h"
84 extern XtAppContext Xt_app_con
;
85 extern Widget Xt_app_shell
;
86 extern void free_frame_menubar ();
87 extern void _XEditResCheckMessages ();
88 #endif /* USE_X_TOOLKIT */
91 #define x_any_window_to_frame x_window_to_frame
92 #define x_top_window_to_frame x_window_to_frame
96 #ifndef XtNinitialState
97 #define XtNinitialState "initialState"
102 #define XMapWindow XMapRaised /* Raise them when mapping. */
103 #else /* ! defined (HAVE_X11) */
104 #include <X/Xkeyboard.h>
105 /*#include <X/Xproto.h> */
106 #endif /* ! defined (HAVE_X11) */
109 /* We could get this from param.h, but better not to depend on finding that.
110 And better not to risk that it might define other symbols used in this
113 #define MAXDESC FD_SETSIZE
117 #define SELECT_TYPE fd_set
118 #else /* no FD_SET */
120 #define SELECT_TYPE int
122 /* Define the macros to access a single-int bitmap of descriptors. */
123 #define FD_SET(n, p) (*(p) |= (1 << (n)))
124 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
125 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
126 #define FD_ZERO(p) (*(p) = 0)
127 #endif /* no FD_SET */
129 /* For sending Meta-characters. Do we need this? */
132 #define min(a,b) ((a)<(b) ? (a) : (b))
133 #define max(a,b) ((a)>(b) ? (a) : (b))
135 /* Nonzero means we must reprint all windows
136 because 1) we received an ExposeWindow event
137 or 2) we received too many ExposeRegion events to record.
139 This is never needed under X11. */
140 static int expose_all_windows
;
142 /* Nonzero means we must reprint all icon windows. */
144 static int expose_all_icons
;
147 /* ExposeRegion events, when received, are copied into this queue
148 for later processing. */
150 static struct event_queue x_expose_queue
;
152 /* ButtonPress and ButtonReleased events, when received,
153 are copied into this queue for later processing. */
155 struct event_queue x_mouse_queue
;
156 #endif /* HAVE_X11 */
158 #if defined (SIGIO) && defined (FIONREAD)
159 int BLOCK_INPUT_mask
;
160 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
162 /* The id of a bitmap used for icon windows.
163 One such map is shared by all Emacs icon windows.
164 This is zero if we have not yet had a need to create the bitmap. */
166 static Bitmap icon_bitmap
;
168 /* Font used for text icons. */
170 static FONT_TYPE
*icon_font_info
;
172 /* Stuff for dealing with the main icon title. */
174 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
177 /* Initial values of argv and argc. */
178 extern char **initial_argv
;
179 extern int initial_argc
;
181 /* This is the X connection that we are using. */
183 Display
*x_current_display
;
185 /* The cursor to use for vertical scroll bars on x_current_display. */
186 static Cursor x_vertical_scroll_bar_cursor
;
188 /* Frame being updated by update_frame. This is declared in term.c.
189 This is set by update_begin and looked at by all the
190 XT functions. It is zero while not inside an update.
191 In that case, the XT functions assume that `selected_frame'
192 is the frame to apply to. */
193 extern struct frame
*updating_frame
;
195 /* The frame (if any) which has the X window that has keyboard focus.
196 Zero if none. This is examined by Ffocus_frame in frame.c. Note
197 that a mere EnterNotify event can set this; if you need to know the
198 last frame specified in a FocusIn or FocusOut event, use
199 x_focus_event_frame. */
200 struct frame
*x_focus_frame
;
202 /* This is a frame waiting to be autoraised, within XTread_socket. */
203 struct frame
*pending_autoraise_frame
;
205 /* The last frame mentioned in a FocusIn or FocusOut event. This is
206 separate from x_focus_frame, because whether or not LeaveNotify
207 events cause us to lose focus depends on whether or not we have
208 received a FocusIn event for it. */
209 struct frame
*x_focus_event_frame
;
211 /* The frame which currently has the visual highlight, and should get
212 keyboard input (other sorts of input have the frame encoded in the
213 event). It points to the X focus frame's selected window's
214 frame. It differs from x_focus_frame when we're using a global
216 static struct frame
*x_highlight_frame
;
218 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
219 mouse is moved to inside of frame when frame is de-iconified. */
221 static int warp_mouse_on_deiconify
;
223 /* During an update, maximum vpos for ins/del line operations to affect. */
225 static int flexlines
;
227 /* During an update, nonzero if chars output now should be highlighted. */
229 static int highlight
;
231 /* Nominal cursor position -- where to draw output.
232 During an update, these are different from the cursor-box position. */
237 /* Reusable Graphics Context for drawing a cursor in a non-default face. */
238 static GC scratch_cursor_gc
;
242 In order to avoid asking for motion events and then throwing most
243 of them away or busy-polling the server for mouse positions, we ask
244 the server for pointer motion hints. This means that we get only
245 one event per group of mouse movements. "Groups" are delimited by
246 other kinds of events (focus changes and button clicks, for
247 example), or by XQueryPointer calls; when one of these happens, we
248 get another MotionNotify event the next time the mouse moves. This
249 is at least as efficient as getting motion events when mouse
250 tracking is on, and I suspect only negligibly worse when tracking
253 The silly O'Reilly & Associates Nutshell guides barely document
254 pointer motion hints at all (I think you have to infer how they
255 work from an example), and the description of XQueryPointer doesn't
256 mention that calling it causes you to get another motion hint from
257 the server, which is very important. */
259 /* Where the mouse was last time we reported a mouse event. */
260 static FRAME_PTR last_mouse_frame
;
261 static XRectangle last_mouse_glyph
;
263 /* The scroll bar in which the last X motion event occurred.
265 If the last X motion event occurred in a scroll bar, we set this
266 so XTmouse_position can know whether to report a scroll bar motion or
269 If the last X motion event didn't occur in a scroll bar, we set this
270 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
271 static Lisp_Object last_mouse_scroll_bar
;
273 /* Record which buttons are currently pressed. */
274 unsigned int x_mouse_grabbed
;
276 /* This is a hack. We would really prefer that XTmouse_position would
277 return the time associated with the position it returns, but there
278 doesn't seem to be any way to wrest the timestamp from the server
279 along with the position query. So, we just keep track of the time
280 of the last movement we received, and return that in hopes that
281 it's somewhat accurate. */
282 static Time last_mouse_movement_time
;
284 /* These variables describe the range of text currently shown
285 in its mouse-face, together with the window they apply to.
286 As long as the mouse stays within this range, we need not
287 redraw anything on its account. */
288 static int mouse_face_beg_row
, mouse_face_beg_col
;
289 static int mouse_face_end_row
, mouse_face_end_col
;
290 static int mouse_face_past_end
;
291 static Lisp_Object mouse_face_window
;
292 static int mouse_face_face_id
;
294 /* 1 if a mouse motion event came and we didn't handle it right away because
295 gc was in progress. */
296 static int mouse_face_deferred_gc
;
298 /* FRAME and X, Y position of mouse when last checked for
299 highlighting. X and Y can be negative or out of range for the frame. */
300 static FRAME_PTR mouse_face_mouse_frame
;
301 static int mouse_face_mouse_x
, mouse_face_mouse_y
;
303 /* Nonzero means defer mouse-motion highlighting. */
304 static int mouse_face_defer
;
307 /* `t' if a mouse button is depressed. */
309 extern Lisp_Object Vmouse_depressed
;
311 /* Tells if a window manager is present or not. */
313 extern Lisp_Object Vx_no_window_manager
;
315 /* Timestamp that we requested selection data was made. */
316 extern Time requestor_time
;
318 /* ID of the window requesting selection data. */
319 extern Window requestor_window
;
321 /* Nonzero enables some debugging for the X interface code. */
324 extern Lisp_Object Qface
, Qmouse_face
;
326 #else /* ! defined (HAVE_X11) */
328 /* Bit patterns for the mouse cursor. */
330 short MouseCursor
[] = {
331 0x0000, 0x0008, 0x0018, 0x0038,
332 0x0078, 0x00f8, 0x01f8, 0x03f8,
333 0x07f8, 0x00f8, 0x00d8, 0x0188,
334 0x0180, 0x0300, 0x0300, 0x0000};
336 short MouseMask
[] = {
337 0x000c, 0x001c, 0x003c, 0x007c,
338 0x00fc, 0x01fc, 0x03fc, 0x07fc,
339 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
340 0x03cc, 0x0780, 0x0780, 0x0300};
342 static short grey_bits
[] = {
343 0x0005, 0x000a, 0x0005, 0x000a};
345 static Pixmap GreyPixmap
= 0;
346 #endif /* ! defined (HAVE_X11) */
348 static int x_noop_count
;
351 /* From time to time we get info on an Emacs window, here. */
353 static WINDOWINFO_TYPE windowinfo
;
357 /* A mask of extra modifier bits to put into every keyboard char. */
358 extern int extra_keyboard_modifiers
;
360 extern Display
*XOpenDisplay ();
361 extern Window
XCreateWindow ();
363 extern Cursor
XCreateCursor ();
364 extern FONT_TYPE
*XOpenFont ();
366 static void flashback ();
367 static void redraw_previous_char ();
368 static void redraw_following_char ();
369 static unsigned int x_x_to_emacs_modifiers ();
371 static int fast_find_position ();
372 static void note_mouse_highlight ();
373 static void clear_mouse_face ();
374 static void show_mouse_face ();
377 static void dumpqueue ();
378 #endif /* HAVE_X11 */
381 static int XTcursor_to ();
382 static int XTclear_end_of_line ();
385 /* Starting and ending updates.
387 These hooks are called by update_frame at the beginning and end
388 of a frame update. We record in `updating_frame' the identity
389 of the frame being updated, so that the XT... functions do not
390 need to take a frame as argument. Most of the XT... functions
391 should never be called except during an update, the only exceptions
392 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
394 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
405 flexlines
= f
->height
;
410 if (f
== mouse_face_mouse_frame
)
412 /* Don't do highlighting for mouse motion during the update. */
413 mouse_face_defer
= 1;
414 if (!NILP (mouse_face_window
))
416 int firstline
, lastline
, i
;
417 struct window
*w
= XWINDOW (mouse_face_window
);
419 /* Find the first, and the last+1, lines affected by redisplay. */
420 for (firstline
= 0; firstline
< f
->height
; firstline
++)
421 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
424 lastline
= f
->height
;
425 for (i
= f
->height
- 1; i
>= 0; i
--)
427 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
433 /* Can we tell that this update does not affect the window
434 where the mouse highlight is? If so, no need to turn off. */
435 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
436 || lastline
< XFASTINT (w
->top
)))
437 /* Otherwise turn off the mouse highlight now. */
443 #endif /* HAVE_X11 */
448 static void x_do_pending_expose ();
460 x_do_pending_expose ();
461 #endif /* HAVE_X11 */
463 x_display_cursor (f
, 1);
465 if (f
== mouse_face_mouse_frame
)
466 mouse_face_defer
= 0;
468 /* This fails in the case of having updated only the echo area
469 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
470 has no relation to the current contents, and its charstarts
471 have no relation to the contents of the window-buffer.
472 I don't know a clean way to check
473 for that case. window_end_valid isn't set up yet. */
474 if (f
== mouse_face_mouse_frame
)
475 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
482 /* This is called after a redisplay on frame F. */
485 XTframe_up_to_date (f
)
488 if (mouse_face_deferred_gc
|| f
== mouse_face_mouse_frame
)
490 note_mouse_highlight (mouse_face_mouse_frame
,
491 mouse_face_mouse_x
, mouse_face_mouse_y
);
492 mouse_face_deferred_gc
= 0;
496 /* External interface to control of standout mode.
497 Call this when about to modify line at position VPOS
498 and not change whether it is highlighted. */
500 XTreassert_line_highlight (new, vpos
)
506 /* Call this when about to modify line at position VPOS
507 and change whether it is highlighted. */
510 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
511 int new_highlight
, vpos
, first_unused_hpos
;
513 highlight
= new_highlight
;
514 XTcursor_to (vpos
, 0);
515 XTclear_end_of_line (updating_frame
->width
);
518 /* This is used when starting Emacs and when restarting after suspend.
519 When starting Emacs, no X window is mapped. And nothing must be done
520 to Emacs's own window if it is suspended (though that rarely happens). */
523 XTset_terminal_modes ()
527 /* This is called when exiting or suspending Emacs.
528 Exiting will make the X-windows go away, and suspending
529 requires no action. */
532 XTreset_terminal_modes ()
534 /* XTclear_frame (); */
537 /* Set the nominal cursor position of the frame.
538 This is where display update commands will take effect.
539 This does not affect the place where the cursor-box is displayed. */
542 XTcursor_to (row
, col
)
543 register int row
, col
;
551 if (updating_frame
== 0)
554 x_display_cursor (selected_frame
, 1);
560 /* Display a sequence of N glyphs found at GP.
561 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
562 HL is 1 if this text is highlighted, 2 if the cursor is on it,
563 3 if should appear in its mouse-face.
564 JUST_FOREGROUND if 1 means draw only the foreground;
565 don't alter the background.
567 FONT is the default font to use (for glyphs whose font-code is 0).
569 Since the display generation code is responsible for calling
570 compute_char_face and compute_glyph_face on everything it puts in
571 the display structure, we can assume that the face code on each
572 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
573 to which we can actually apply intern_face.
574 Call this function with input blocked. */
577 /* This is the multi-face code. */
580 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
583 register GLYPH
*gp
; /* Points to first GLYPH. */
584 register int n
; /* Number of glyphs to display. */
588 /* Holds characters to be displayed. */
589 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
590 register char *cp
; /* Steps through buf[]. */
591 register int tlen
= GLYPH_TABLE_LENGTH
;
592 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
593 Window window
= FRAME_X_WINDOW (f
);
594 int orig_left
= left
;
598 /* Get the face-code of the next GLYPH. */
602 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
603 cf
= FAST_GLYPH_FACE (g
);
605 /* Find the run of consecutive glyphs with the same face-code.
606 Extract their character codes into BUF. */
611 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
612 if (FAST_GLYPH_FACE (g
) != cf
)
615 *cp
++ = FAST_GLYPH_CHAR (g
);
620 /* LEN gets the length of the run. */
623 /* Now output this run of chars, with the font and pixel values
624 determined by the face code CF. */
626 struct face
*face
= FRAME_DEFAULT_FACE (f
);
627 FONT_TYPE
*font
= FACE_FONT (face
);
628 GC gc
= FACE_GC (face
);
630 /* HL = 3 means use a mouse face previously chosen. */
632 cf
= mouse_face_face_id
;
634 /* First look at the face of the text itself. */
637 /* It's possible for the display table to specify
638 a face code that is out of range. Use 0 in that case. */
639 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
640 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
644 face
= FRAME_MODE_LINE_FACE (f
);
646 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
647 font
= FACE_FONT (face
);
651 /* Then comes the distinction between modeline and normal text. */
656 face
= FRAME_MODE_LINE_FACE (f
);
657 font
= FACE_FONT (face
);
661 #define FACE_DEFAULT (~0)
663 /* Now override that if the cursor's on this character. */
667 || (int) face
->font
== FACE_DEFAULT
668 || face
->font
== f
->display
.x
->font
)
669 && face
->background
== f
->display
.x
->background_pixel
670 && face
->foreground
== f
->display
.x
->foreground_pixel
)
672 gc
= f
->display
.x
->cursor_gc
;
674 /* Cursor on non-default face: must merge. */
680 xgcv
.background
= f
->display
.x
->cursor_pixel
;
681 xgcv
.foreground
= face
->background
;
682 /* If the glyph would be invisible,
683 try a different foreground. */
684 if (xgcv
.foreground
== xgcv
.background
)
685 xgcv
.foreground
= face
->foreground
;
686 if (xgcv
.foreground
== xgcv
.background
)
687 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
688 if (xgcv
.foreground
== xgcv
.background
)
689 xgcv
.foreground
= face
->foreground
;
690 /* Make sure the cursor is distinct from text in this face. */
691 if (xgcv
.background
== face
->background
692 && xgcv
.foreground
== face
->foreground
)
694 xgcv
.background
= face
->foreground
;
695 xgcv
.foreground
= face
->background
;
697 xgcv
.font
= face
->font
->fid
;
698 xgcv
.graphics_exposures
= 0;
699 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
700 if (scratch_cursor_gc
)
701 XChangeGC (x_current_display
, scratch_cursor_gc
, mask
, &xgcv
);
704 XCreateGC (x_current_display
, window
, mask
, &xgcv
);
705 gc
= scratch_cursor_gc
;
707 /* If this code is restored, it must also reset to the default stipple
709 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
710 XSetStipple (x_current_display
, gc
, face
->stipple
);
715 if ((int) font
== FACE_DEFAULT
)
716 font
= f
->display
.x
->font
;
719 XDrawString (x_current_display
, window
, gc
,
720 left
, top
+ FONT_BASE (font
), buf
, len
);
723 XDrawImageString (x_current_display
, window
, gc
,
724 left
, top
+ FONT_BASE (font
), buf
, len
);
725 /* Clear the rest of the line's height. */
726 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
727 XClearArea (x_current_display
, window
, left
,
728 top
+ FONT_HEIGHT (font
),
729 FONT_WIDTH (font
) * len
,
730 /* This is how many pixels of height
732 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
736 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
737 which often is not up to date yet. */
738 if (!just_foreground
)
740 if (left
== orig_left
)
741 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
742 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
744 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
745 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
749 /* We should probably check for XA_UNDERLINE_POSITION and
750 XA_UNDERLINE_THICKNESS properties on the font, but let's
751 just get the thing working, and come back to that. */
753 int underline_position
= 1;
755 if (font
->descent
<= underline_position
)
756 underline_position
= font
->descent
- 1;
759 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
763 + underline_position
),
764 len
* FONT_WIDTH (font
), 1);
767 left
+= len
* FONT_WIDTH (font
);
774 /* This is the old single-face code. */
777 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
780 register GLYPH
*gp
; /* Points to first GLYPH. */
781 register int n
; /* Number of glyphs to display. */
786 Window window
= FRAME_X_WINDOW (f
);
787 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
788 : (hl
? f
->display
.x
->reverse_gc
789 : f
->display
.x
->normal_gc
));
791 if (sizeof (GLYPH
) == sizeof (XChar2b
))
792 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
793 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
794 else if (sizeof (GLYPH
) == sizeof (unsigned char))
795 XDrawImageString (x_current_display
, window
, drawing_gc
,
796 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
798 /* What size of glyph ARE you using? And does X have a function to
804 /* Output some text at the nominal frame cursor position.
805 Advance the cursor over the text.
806 Output LEN glyphs at START.
808 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
809 controls the pixel values used for foreground and background. */
812 XTwrite_glyphs (start
, len
)
813 register GLYPH
*start
;
816 register int temp_length
;
826 /* If not within an update,
827 output at the frame's visible cursor. */
828 curs_x
= f
->cursor_x
;
829 curs_y
= f
->cursor_y
;
833 CHAR_TO_PIXEL_COL (f
, curs_x
),
834 CHAR_TO_PIXEL_ROW (f
, curs_y
),
835 start
, len
, highlight
, 0);
837 /* If we drew on top of the cursor, note that it is turned off. */
838 if (curs_y
== f
->phys_cursor_y
839 && curs_x
<= f
->phys_cursor_x
840 && curs_x
+ len
> f
->phys_cursor_x
)
841 f
->phys_cursor_x
= -1;
843 if (updating_frame
== 0)
846 x_display_cursor (f
, 1);
855 /* Clear to the end of the line.
856 Erase the current text line from the nominal cursor position (inclusive)
857 to column FIRST_UNUSED (exclusive). The idea is that everything
858 from FIRST_UNUSED onward is already erased. */
861 XTclear_end_of_line (first_unused
)
862 register int first_unused
;
864 struct frame
*f
= updating_frame
;
870 if (curs_y
< 0 || curs_y
>= f
->height
)
872 if (first_unused
<= 0)
875 if (first_unused
>= f
->width
)
876 first_unused
= f
->width
;
880 /* Notice if the cursor will be cleared by this operation. */
881 if (curs_y
== f
->phys_cursor_y
882 && curs_x
<= f
->phys_cursor_x
883 && f
->phys_cursor_x
< first_unused
)
884 f
->phys_cursor_x
= -1;
887 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
888 CHAR_TO_PIXEL_COL (f
, curs_x
),
889 CHAR_TO_PIXEL_ROW (f
, curs_y
),
890 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
891 f
->display
.x
->line_height
, False
);
893 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
895 #else /* ! defined (HAVE_X11) */
896 XPixSet (FRAME_X_WINDOW (f
),
897 CHAR_TO_PIXEL_COL (f
, curs_x
),
898 CHAR_TO_PIXEL_ROW (f
, curs_y
),
899 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
900 f
->display
.x
->line_height
,
901 f
->display
.x
->background_pixel
);
902 #endif /* ! defined (HAVE_X11) */
911 struct frame
*f
= updating_frame
;
916 f
->phys_cursor_x
= -1; /* Cursor not visible. */
917 curs_x
= 0; /* Nominal cursor position is top left. */
922 XClear (FRAME_X_WINDOW (f
));
924 /* We have to clear the scroll bars, too. If we have changed
925 colors or something like that, then they should be notified. */
926 x_scroll_bar_clear (f
);
930 #endif /* HAVE_X11 */
937 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
938 always contain the right glyphs to use.
940 It also needs to be changed to look at the details of the font and
941 see whether there is really overlap, and do nothing when there is
942 not. This can use font_char_overlap_left and font_char_overlap_right,
943 but just how to use them is not clear. */
945 /* Erase the character (if any) at the position just before X, Y in frame F,
946 then redraw it and the character before it.
947 This is necessary when we erase starting at X,
948 in case the character after X overlaps into the one before X.
949 Call this function with input blocked. */
952 redraw_previous_char (f
, x
, y
, highlight_flag
)
957 /* Erase the character before the new ones, in case
958 what was here before overlaps it.
959 Reoutput that character, and the previous character
960 (in case the previous character overlaps it). */
966 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
967 CHAR_TO_PIXEL_COL (f
, x
- 1),
968 CHAR_TO_PIXEL_ROW (f
, y
),
969 FONT_WIDTH (f
->display
.x
->font
),
970 f
->display
.x
->line_height
, False
);
972 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
973 CHAR_TO_PIXEL_ROW (f
, y
),
974 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
975 x
- start_x
, highlight_flag
, 1);
979 /* Erase the character (if any) at the position X, Y in frame F,
980 then redraw it and the character after it.
981 This is necessary when we erase endng at X,
982 in case the character after X overlaps into the one before X.
983 Call this function with input blocked. */
986 redraw_following_char (f
, x
, y
, highlight_flag
)
991 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
992 /* Erase the character after the new ones, in case
993 what was here before overlaps it.
994 Reoutput that character, and the following character
995 (in case the following character overlaps it). */
997 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1002 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1003 CHAR_TO_PIXEL_COL (f
, x
),
1004 CHAR_TO_PIXEL_ROW (f
, y
),
1005 FONT_WIDTH (f
->display
.x
->font
),
1006 f
->display
.x
->line_height
, False
);
1008 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1009 CHAR_TO_PIXEL_ROW (f
, y
),
1010 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1011 end_x
- x
, highlight_flag
, 1);
1016 #if 0 /* Not in use yet */
1018 /* Return 1 if character C in font F extends past its left edge. */
1021 font_char_overlap_left (font
, c
)
1027 /* Find the bounding-box info for C. */
1028 if (font
->per_char
== 0)
1029 s
= &font
->max_bounds
;
1032 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1035 /* Decode char into row number (byte 1) and code within row (byte 2). */
1038 if (!(within
>= font
->min_char_or_byte2
1039 && within
<= font
->max_char_or_byte2
1040 && row
>= font
->min_byte1
1041 && row
<= font
->max_byte1
))
1043 /* If char is out of range, try the font's default char instead. */
1044 c
= font
->default_char
;
1045 row
= c
>> (INTBITS
- 8);
1048 if (!(within
>= font
->min_char_or_byte2
1049 && within
<= font
->max_char_or_byte2
1050 && row
>= font
->min_byte1
1051 && row
<= font
->max_byte1
))
1052 /* Still out of range means this char does not overlap. */
1055 /* We found the info for this char. */
1056 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1060 return (s
&& s
->lbearing
< 0);
1063 /* Return 1 if character C in font F extends past its right edge. */
1066 font_char_overlap_right (font
, c
)
1072 /* Find the bounding-box info for C. */
1073 if (font
->per_char
== 0)
1074 s
= &font
->max_bounds
;
1077 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1080 /* Decode char into row number (byte 1) and code within row (byte 2). */
1083 if (!(within
>= font
->min_char_or_byte2
1084 && within
<= font
->max_char_or_byte2
1085 && row
>= font
->min_byte1
1086 && row
<= font
->max_byte1
))
1088 /* If char is out of range, try the font's default char instead. */
1089 c
= font
->default_char
;
1090 row
= c
>> (INTBITS
- 8);
1093 if (!(within
>= font
->min_char_or_byte2
1094 && within
<= font
->max_char_or_byte2
1095 && row
>= font
->min_byte1
1096 && row
<= font
->max_byte1
))
1097 /* Still out of range means this char does not overlap. */
1100 /* We found the info for this char. */
1101 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1105 return (s
&& s
->rbearing
>= s
->width
);
1109 /* Invert the middle quarter of the frame for .15 sec. */
1111 /* We use the select system call to do the waiting, so we have to make sure
1112 it's available. If it isn't, we just won't do visual bells. */
1113 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1115 /* Subtract the `struct timeval' values X and Y,
1116 storing the result in RESULT.
1117 Return 1 if the difference is negative, otherwise 0. */
1120 timeval_subtract (result
, x
, y
)
1121 struct timeval
*result
, x
, y
;
1123 /* Perform the carry for the later subtraction by updating y.
1124 This is safer because on some systems
1125 the tv_sec member is unsigned. */
1126 if (x
.tv_usec
< y
.tv_usec
)
1128 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1129 y
.tv_usec
-= 1000000 * nsec
;
1132 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1134 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1135 y
.tv_usec
+= 1000000 * nsec
;
1139 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1140 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1141 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1143 /* Return indication of whether the result should be considered negative. */
1144 return x
.tv_sec
< y
.tv_sec
;
1155 /* Create a GC that will use the GXxor function to flip foreground pixels
1156 into background pixels. */
1160 values
.function
= GXxor
;
1161 values
.foreground
= (f
->display
.x
->foreground_pixel
1162 ^ f
->display
.x
->background_pixel
);
1164 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
1165 GCFunction
| GCForeground
, &values
);
1169 int width
= PIXEL_WIDTH (f
);
1170 int height
= PIXEL_HEIGHT (f
);
1172 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1173 width
/4, height
/4, width
/2, height
/2);
1174 XFlush (x_current_display
);
1177 struct timeval wakeup
, now
;
1179 EMACS_GET_TIME (wakeup
);
1181 /* Compute time to wait until, propagating carry from usecs. */
1182 wakeup
.tv_usec
+= 150000;
1183 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1184 wakeup
.tv_usec
%= 1000000;
1186 /* Keep waiting until past the time wakeup. */
1189 struct timeval timeout
;
1191 EMACS_GET_TIME (timeout
);
1193 /* In effect, timeout = wakeup - timeout.
1194 Break if result would be negative. */
1195 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1198 /* Try to wait that long--but we might wake up sooner. */
1199 select (0, 0, 0, 0, &timeout
);
1203 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1204 width
/4, height
/4, width
/2, height
/2);
1205 XFreeGC (x_current_display
, gc
);
1206 XFlush (x_current_display
);
1216 /* Make audible bell. */
1219 #define XRINGBELL XBell (x_current_display, 0)
1220 #else /* ! defined (HAVE_X11) */
1221 #define XRINGBELL XFeep (0);
1222 #endif /* ! defined (HAVE_X11) */
1226 if (x_current_display
== 0)
1229 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1231 XTflash (selected_frame
);
1242 /* Insert and delete character.
1243 These are not supposed to be used because we are supposed to turn
1244 off the feature of using them. */
1247 XTinsert_glyphs (start
, len
)
1248 register char *start
;
1261 /* Specify how many text lines, from the top of the window,
1262 should be affected by insert-lines and delete-lines operations.
1263 This, and those operations, are used only within an update
1264 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1267 XTset_terminal_window (n
)
1270 if (updating_frame
== 0)
1273 if ((n
<= 0) || (n
> updating_frame
->height
))
1274 flexlines
= updating_frame
->height
;
1279 /* Perform an insert-lines operation.
1280 Insert N lines at a vertical position curs_y. */
1286 register int topregion
, bottomregion
;
1287 register int length
, newtop
, mask
;
1288 register struct frame
*f
= updating_frame
;
1289 int intborder
= f
->display
.x
->internal_border_width
;
1291 if (curs_y
>= flexlines
)
1295 bottomregion
= flexlines
- (n
+ 1);
1296 newtop
= topregion
+ n
;
1297 length
= (bottomregion
- topregion
) + 1;
1301 #endif /* HAVE_X11 */
1303 if ((length
> 0) && (newtop
<= flexlines
))
1306 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1307 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1308 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1309 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1310 length
* f
->display
.x
->line_height
, intborder
,
1311 CHAR_TO_PIXEL_ROW (f
, newtop
));
1312 #else /* ! defined (HAVE_X11) */
1313 XMoveArea (FRAME_X_WINDOW (f
),
1314 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1315 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1316 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1317 length
* f
->display
.x
->line_height
);
1318 /* Now we must process any ExposeRegion events that occur
1319 if the area being copied from is obscured.
1320 We can't let it wait because further i/d operations
1321 may want to copy this area to another area. */
1323 #endif /* ! defined (HAVE_X11) */
1326 newtop
= min (newtop
, (flexlines
- 1));
1327 length
= newtop
- topregion
;
1331 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1332 CHAR_TO_PIXEL_ROW (f
, topregion
),
1333 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1334 n
* f
->display
.x
->line_height
, False
);
1335 #else /* ! defined (HAVE_X11) */
1336 XPixSet (FRAME_X_WINDOW (f
),
1338 CHAR_TO_PIXEL_ROW (f
, topregion
),
1339 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1340 n
* f
->display
.x
->line_height
,
1341 f
->display
.x
->background_pixel
);
1342 #endif /* ! defined (HAVE_X11) */
1346 /* Perform a delete-lines operation, deleting N lines
1347 at a vertical position curs_y. */
1354 register struct frame
*f
= updating_frame
;
1355 int intborder
= f
->display
.x
->internal_border_width
;
1357 if (curs_y
>= flexlines
)
1362 #endif /* HAVE_X11 */
1364 if ((curs_y
+ n
) >= flexlines
)
1366 if (flexlines
>= (curs_y
+ 1))
1369 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1370 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1371 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1372 (flexlines
- curs_y
) * f
->display
.x
->line_height
, False
);
1373 #else /* ! defined (HAVE_X11) */
1374 XPixSet (FRAME_X_WINDOW (f
),
1375 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1376 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1377 (flexlines
- curs_y
) * f
->display
.x
->line_height
,
1378 f
->display
.x
->background_pixel
);
1379 #endif /* ! defined (HAVE_X11) */
1385 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1386 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1388 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1389 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1390 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
,
1391 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1392 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1394 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1395 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1396 n
* f
->display
.x
->line_height
, False
);
1397 #else /* ! defined (HAVE_X11) */
1398 XMoveArea (FRAME_X_WINDOW (f
),
1400 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1401 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1402 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1403 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
);
1404 /* Now we must process any ExposeRegion events that occur
1405 if the area being copied from is obscured.
1406 We can't let it wait because further i/d operations
1407 may want to copy this area to another area. */
1409 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1410 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1411 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1412 n
* f
->display
.x
->line_height
, f
->display
.x
->background_pixel
);
1413 #endif /* ! defined (HAVE_X11) */
1417 /* Perform an insert-lines or delete-lines operation,
1418 inserting N lines or deleting -N lines at vertical position VPOS. */
1420 XTins_del_lines (vpos
, n
)
1423 if (updating_frame
== 0)
1426 /* Hide the cursor. */
1427 x_display_cursor (updating_frame
, 0);
1429 XTcursor_to (vpos
, 0);
1440 /* Support routines for exposure events. */
1441 static void clear_cursor ();
1443 /* Output into a rectangle of an X-window (for frame F)
1444 the characters in f->phys_lines that overlap that rectangle.
1445 TOP and LEFT are the position of the upper left corner of the rectangle.
1446 ROWS and COLS are the size of the rectangle.
1447 Call this function with input blocked. */
1450 dumprectangle (f
, left
, top
, cols
, rows
)
1452 register int left
, top
, cols
, rows
;
1454 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1455 int cursor_cleared
= 0;
1459 if (FRAME_GARBAGED_P (f
))
1462 /* Express rectangle as four edges, instead of position-and-size. */
1463 bottom
= top
+ rows
;
1464 right
= left
+ cols
;
1466 #ifndef HAVE_X11 /* Window manger does this for X11. */
1468 int intborder
= f
->display
.x
->internal_border_width
;
1470 /* If the rectangle includes any of the internal border area,
1471 redisplay the border emphasis. */
1472 if (top
< intborder
|| left
< intborder
1473 || bottom
> intborder
+ f
->height
* f
->display
.x
->line_height
1474 || right
> intborder
+ f
->width
* f
->display
.x
->line_height
)
1477 #endif /* not HAVE_X11 Window manger does this for X11. */
1479 /* Convert rectangle edges in pixels to edges in chars.
1480 Round down for left and top, up for right and bottom. */
1481 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1482 left
= PIXEL_TO_CHAR_COL (f
, left
);
1483 bottom
+= (f
->display
.x
->line_height
- 1);
1484 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1485 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1486 right
= PIXEL_TO_CHAR_COL (f
, right
);
1488 /* Clip the rectangle to what can be visible. */
1493 if (right
> f
->width
)
1495 if (bottom
> f
->height
)
1498 /* Get size in chars of the rectangle. */
1499 cols
= right
- left
;
1500 rows
= bottom
- top
;
1502 /* If rectangle has zero area, return. */
1503 if (rows
<= 0) return;
1504 if (cols
<= 0) return;
1506 /* Turn off the cursor if it is in the rectangle.
1507 We will turn it back on afterward. */
1508 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1509 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1515 /* Display the text in the rectangle, one text line at a time. */
1517 for (y
= top
; y
< bottom
; y
++)
1519 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1521 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1525 CHAR_TO_PIXEL_COL (f
, left
),
1526 CHAR_TO_PIXEL_ROW (f
, y
),
1527 line
, min (cols
, active_frame
->used
[y
] - left
),
1528 active_frame
->highlight
[y
], 0);
1531 /* Turn the cursor on if we turned it off. */
1534 x_display_cursor (f
, 1);
1538 /* Process all queued ExposeRegion events. */
1544 XExposeRegionEvent r
;
1546 while (dequeue_event (&r
, &x_expose_queue
))
1548 struct frame
*f
= x_window_to_frame (r
.window
);
1549 if (f
->display
.x
->icon_desc
== r
.window
)
1552 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1556 #endif /* HAVE_X11 */
1558 /* Process all expose events that are pending, for X10.
1559 Redraws the cursor if necessary on any frame that
1560 is not in the process of being updated with update_frame. */
1564 x_do_pending_expose ()
1568 Lisp_Object tail
, frame
;
1570 if (expose_all_windows
)
1572 expose_all_windows
= 0;
1573 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1575 register int temp_width
, temp_height
;
1578 frame
= XCONS (tail
)->car
;
1579 if (XGCTYPE (frame
) != Lisp_Frame
)
1582 if (! FRAME_X_P (f
))
1584 if (!f
->async_visible
)
1586 if (!f
->display
.x
->needs_exposure
)
1589 intborder
= f
->display
.x
->internal_border_width
;
1592 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1593 temp_width
= ((windowinfo
.width
- 2 * intborder
1594 - f
->display
.x
->v_scroll_bar_width
)
1595 / FONT_WIDTH (f
->display
.x
->font
));
1596 temp_height
= ((windowinfo
.height
- 2 * intborder
1597 - f
->display
.x
->h_scroll_bar_height
)
1598 / f
->display
.x
->line_height
);
1599 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1601 change_frame_size (f
, max (1, temp_height
),
1602 max (1, temp_width
), 0, 1);
1603 x_resize_scroll_bars (f
);
1605 f
->display
.x
->left_pos
= windowinfo
.x
;
1606 f
->display
.x
->top_pos
= windowinfo
.y
;
1607 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1611 f
->display
.x
->needs_exposure
= 0;
1612 if (updating_frame
!= f
)
1613 x_display_cursor (f
, 1);
1618 /* Handle any individual-rectangle expose events queued
1619 for various windows. */
1622 #else /* ! defined (HAVE_X11) */
1624 #endif /* ! defined (HAVE_X11) */
1630 frame_highlight (frame
)
1631 struct frame
*frame
;
1633 /* We used to only do this if Vx_no_window_manager was non-nil, but
1634 the ICCCM (section 4.1.6) says that the window's border pixmap
1635 and border pixel are window attributes which are "private to the
1636 client", so we can always change it to whatever we want. */
1638 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1639 frame
->display
.x
->border_pixel
);
1641 x_display_cursor (frame
, 1);
1645 frame_unhighlight (frame
)
1646 struct frame
*frame
;
1648 /* We used to only do this if Vx_no_window_manager was non-nil, but
1649 the ICCCM (section 4.1.6) says that the window's border pixmap
1650 and border pixel are window attributes which are "private to the
1651 client", so we can always change it to whatever we want. */
1653 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1654 frame
->display
.x
->border_tile
);
1656 x_display_cursor (frame
, 1);
1658 #else /* ! defined (HAVE_X11) */
1659 /* Dump the border-emphasis of frame F.
1660 If F is selected, this is a lining of the same color as the border,
1661 just within the border, occupying a portion of the internal border.
1662 If F is not selected, it is background in the same place.
1663 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1665 ALWAYS = 1 is used when a frame becomes selected or deselected.
1666 In that case, we also turn the cursor off and on again
1667 so it will appear in the proper shape (solid if selected; else hollow.) */
1670 dumpborder (f
, always
)
1674 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1675 int width
= PIXEL_WIDTH (f
);
1676 int height
= PIXEL_HEIGHT (f
);
1679 if (f
!= selected_frame
)
1684 pixel
= f
->display
.x
->background_pixel
;
1688 pixel
= f
->display
.x
->border_pixel
;
1691 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1692 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1693 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1695 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1699 x_display_cursor (f
, 1);
1701 #endif /* ! defined (HAVE_X11) */
1703 static void XTframe_rehighlight ();
1705 /* The focus has changed. Update the frames as necessary to reflect
1706 the new situation. Note that we can't change the selected frame
1707 here, because the lisp code we are interrupting might become confused.
1708 Each event gets marked with the frame in which it occurred, so the
1709 lisp code can tell when the switch took place by examining the events. */
1712 x_new_focus_frame (frame
)
1713 struct frame
*frame
;
1715 struct frame
*old_focus
= x_focus_frame
;
1716 int events_enqueued
= 0;
1718 if (frame
!= x_focus_frame
)
1720 /* Set this before calling other routines, so that they see
1721 the correct value of x_focus_frame. */
1722 x_focus_frame
= frame
;
1724 if (old_focus
&& old_focus
->auto_lower
)
1725 x_lower_frame (old_focus
);
1728 selected_frame
= frame
;
1729 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1730 Lisp_Frame
, selected_frame
);
1731 Fselect_window (selected_frame
->selected_window
);
1732 choose_minibuf_frame ();
1735 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1736 pending_autoraise_frame
= x_focus_frame
;
1738 pending_autoraise_frame
= 0;
1741 XTframe_rehighlight ();
1745 /* The focus has changed, or we have redirected a frame's focus to
1746 another frame (this happens when a frame uses a surrogate
1747 minibuffer frame). Shift the highlight as appropriate. */
1749 XTframe_rehighlight ()
1751 struct frame
*old_highlight
= x_highlight_frame
;
1756 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1757 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1759 if (! FRAME_LIVE_P (x_highlight_frame
))
1761 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1762 x_highlight_frame
= x_focus_frame
;
1766 x_highlight_frame
= 0;
1768 if (x_highlight_frame
!= old_highlight
)
1771 frame_unhighlight (old_highlight
);
1772 if (x_highlight_frame
)
1773 frame_highlight (x_highlight_frame
);
1777 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1779 /* Which modifier keys are on which modifier bits?
1781 With each keystroke, X returns eight bits indicating which modifier
1782 keys were held down when the key was pressed. The interpretation
1783 of the top five modifier bits depends on what keys are attached
1784 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1787 x_meta_mod_mask is a mask containing the bits used for the meta key.
1788 It may have more than one bit set, if more than one modifier bit
1789 has meta keys on it. Basically, if EVENT is a KeyPress event,
1790 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1792 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1793 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1794 only be affected by the lock modifier bit if XK_Shift_Lock is in
1795 use; XK_Caps_Lock should only affect alphabetic keys. With this
1796 arrangement, the lock modifier should shift the character if
1797 (EVENT.state & x_shift_lock_mask) != 0. */
1798 static int x_meta_mod_mask
, x_shift_lock_mask
;
1800 /* These are like x_meta_mod_mask, but for different modifiers. */
1801 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1803 /* Initialize mode_switch_bit and modifier_meaning. */
1805 x_find_modifier_meanings ()
1807 int min_code
, max_code
;
1810 XModifierKeymap
*mods
;
1812 x_meta_mod_mask
= 0;
1813 x_shift_lock_mask
= 0;
1815 x_super_mod_mask
= 0;
1816 x_hyper_mod_mask
= 0;
1819 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1821 min_code
= x_current_display
->min_keycode
;
1822 max_code
= x_current_display
->max_keycode
;
1825 syms
= XGetKeyboardMapping (x_current_display
,
1826 min_code
, max_code
- min_code
+ 1,
1828 mods
= XGetModifierMapping (x_current_display
);
1830 /* Scan the modifier table to see which modifier bits the Meta and
1831 Alt keysyms are on. */
1833 int row
, col
; /* The row and column in the modifier table. */
1835 for (row
= 3; row
< 8; row
++)
1836 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1839 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1841 /* Zeroes are used for filler. Skip them. */
1845 /* Are any of this keycode's keysyms a meta key? */
1849 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1851 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1857 x_meta_mod_mask
|= (1 << row
);
1862 x_alt_mod_mask
|= (1 << row
);
1867 x_hyper_mod_mask
|= (1 << row
);
1872 x_super_mod_mask
|= (1 << row
);
1876 /* Ignore this if it's not on the lock modifier. */
1877 if ((1 << row
) == LockMask
)
1878 x_shift_lock_mask
= LockMask
;
1886 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1887 if (! x_meta_mod_mask
)
1889 x_meta_mod_mask
= x_alt_mod_mask
;
1893 /* If some keys are both alt and meta,
1894 make them just meta, not alt. */
1895 if (x_alt_mod_mask
& x_meta_mod_mask
)
1897 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1900 XFree ((char *) syms
);
1901 XFreeModifiermap (mods
);
1904 /* Convert between the modifier bits X uses and the modifier bits
1907 x_x_to_emacs_modifiers (state
)
1910 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1911 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1912 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1913 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1914 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1915 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1919 x_emacs_to_x_modifiers (state
)
1922 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1923 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1924 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1925 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1926 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1927 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1930 /* Mouse clicks and mouse movement. Rah. */
1933 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1934 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1935 that the glyph at X, Y occupies, if BOUNDS != 0.
1936 If NOCLIP is nonzero, do not force the value into range. */
1939 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1941 register int pix_x
, pix_y
;
1942 register int *x
, *y
;
1946 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1947 even for negative values. */
1949 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1951 pix_y
-= (f
)->display
.x
->line_height
- 1;
1953 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1954 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1958 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1959 bounds
->height
= f
->display
.x
->line_height
;
1960 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1961 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1968 else if (pix_x
> f
->width
)
1973 else if (pix_y
> f
->height
)
1982 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1985 register int *pix_x
, *pix_y
;
1987 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1988 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1991 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1993 If the event is a button press, then note that we have grabbed
1997 construct_mouse_click (result
, event
, f
)
1998 struct input_event
*result
;
1999 XButtonEvent
*event
;
2002 /* Make the event type no_event; we'll change that when we decide
2004 result
->kind
= mouse_click
;
2005 result
->code
= event
->button
- Button1
;
2006 result
->timestamp
= event
->time
;
2007 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2008 | (event
->type
== ButtonRelease
2016 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2017 XFASTINT (result
->x
) = column
;
2018 XFASTINT (result
->y
) = row
;
2020 XSET (result
->x
, Lisp_Int
, event
->x
);
2021 XSET (result
->y
, Lisp_Int
, event
->y
);
2022 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2026 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2029 construct_menu_click (result
, event
, f
)
2030 struct input_event
*result
;
2031 XButtonEvent
*event
;
2034 /* Make the event type no_event; we'll change that when we decide
2036 result
->kind
= mouse_click
;
2037 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
2038 result
->timestamp
= event
->time
;
2039 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2040 | (event
->type
== ButtonRelease
2044 XSET (result
->x
, Lisp_Int
, event
->x
);
2045 XSET (result
->y
, Lisp_Int
, -1);
2046 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2049 /* Function to report a mouse movement to the mainstream Emacs code.
2050 The input handler calls this.
2052 We have received a mouse movement event, which is given in *event.
2053 If the mouse is over a different glyph than it was last time, tell
2054 the mainstream emacs code by setting mouse_moved. If not, ask for
2055 another motion event, so we can check again the next time it moves. */
2058 note_mouse_movement (frame
, event
)
2060 XMotionEvent
*event
;
2063 last_mouse_movement_time
= event
->time
;
2065 if (event
->window
!= FRAME_X_WINDOW (frame
))
2068 last_mouse_scroll_bar
= Qnil
;
2070 note_mouse_highlight (frame
, -1, -1);
2072 /* Ask for another mouse motion event. */
2075 Window dummy_window
;
2077 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2078 &dummy_window
, &dummy_window
,
2079 &dummy
, &dummy
, &dummy
, &dummy
,
2080 (unsigned int *) &dummy
);
2084 /* Has the mouse moved off the glyph it was on at the last sighting? */
2085 else if (event
->x
< last_mouse_glyph
.x
2086 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2087 || event
->y
< last_mouse_glyph
.y
2088 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2091 last_mouse_scroll_bar
= Qnil
;
2093 note_mouse_highlight (frame
, event
->x
, event
->y
);
2095 /* Ask for another mouse motion event. */
2098 Window dummy_window
;
2100 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2101 &dummy_window
, &dummy_window
,
2102 &dummy
, &dummy
, &dummy
, &dummy
,
2103 (unsigned int *) &dummy
);
2108 /* It's on the same glyph. Call XQueryPointer so we'll get an
2109 event the next time the mouse moves and we can see if it's
2110 *still* on the same glyph. */
2112 Window dummy_window
;
2114 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2115 &dummy_window
, &dummy_window
,
2116 &dummy
, &dummy
, &dummy
, &dummy
,
2117 (unsigned int *) &dummy
);
2121 /* This is used for debugging, to turn off note_mouse_highlight. */
2122 static int disable_mouse_highlight
;
2124 /* Take proper action when the mouse has moved to position X, Y on frame F
2125 as regards highlighting characters that have mouse-face properties.
2126 Also dehighlighting chars where the mouse was before.
2127 X and Y can be negative or out of range. */
2130 note_mouse_highlight (f
, x
, y
)
2133 int row
, column
, portion
;
2134 XRectangle new_glyph
;
2138 if (disable_mouse_highlight
)
2141 mouse_face_mouse_x
= x
;
2142 mouse_face_mouse_y
= y
;
2143 mouse_face_mouse_frame
= f
;
2145 if (mouse_face_defer
)
2150 mouse_face_deferred_gc
= 1;
2154 /* Find out which glyph the mouse is on. */
2155 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2156 &new_glyph
, x_mouse_grabbed
);
2158 /* Which window is that in? */
2159 window
= window_from_coordinates (f
, column
, row
, &portion
);
2160 w
= XWINDOW (window
);
2162 /* If we were displaying active text in another window, clear that. */
2163 if (! EQ (window
, mouse_face_window
))
2164 clear_mouse_face ();
2166 /* Are we in a window whose display is up to date?
2167 And verify the buffer's text has not changed. */
2168 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2169 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2170 && EQ (w
->window_end_valid
, w
->buffer
)
2171 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
2173 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2176 /* Find which buffer position the mouse corresponds to. */
2177 for (i
= column
; i
>= 0; i
--)
2181 /* Is it outside the displayed active region (if any)? */
2183 clear_mouse_face ();
2184 else if (! (EQ (window
, mouse_face_window
)
2185 && row
>= mouse_face_beg_row
2186 && row
<= mouse_face_end_row
2187 && (row
> mouse_face_beg_row
|| column
>= mouse_face_beg_col
)
2188 && (row
< mouse_face_end_row
|| column
< mouse_face_end_col
2189 || mouse_face_past_end
)))
2191 Lisp_Object mouse_face
, overlay
, position
;
2192 Lisp_Object
*overlay_vec
;
2193 int len
, noverlays
, ignor1
;
2194 struct buffer
*obuf
;
2197 /* If we get an out-of-range value, return now; avoid an error. */
2198 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2201 /* Make the window's buffer temporarily current for
2202 overlays_at and compute_char_face. */
2203 obuf
= current_buffer
;
2204 current_buffer
= XBUFFER (w
->buffer
);
2210 /* Yes. Clear the display of the old active region, if any. */
2211 clear_mouse_face ();
2213 /* Is this char mouse-active? */
2214 XSET (position
, Lisp_Int
, pos
);
2217 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2219 /* Put all the overlays we want in a vector in overlay_vec.
2220 Store the length in len. */
2221 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
, &ignor1
);
2222 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2224 /* Find the highest priority overlay that has a mouse-face prop. */
2226 for (i
= 0; i
< noverlays
; i
++)
2228 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2229 if (!NILP (mouse_face
))
2231 overlay
= overlay_vec
[i
];
2236 /* If no overlay applies, get a text property. */
2238 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2240 /* Handle the overlay case. */
2241 if (! NILP (overlay
))
2243 /* Find the range of text around this char that
2244 should be active. */
2245 Lisp_Object before
, after
;
2248 before
= Foverlay_start (overlay
);
2249 after
= Foverlay_end (overlay
);
2250 /* Record this as the current active region. */
2251 fast_find_position (window
, before
, &mouse_face_beg_col
,
2252 &mouse_face_beg_row
);
2254 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2255 &mouse_face_end_row
);
2256 mouse_face_window
= window
;
2257 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
2258 &ignore
, pos
+ 1, 1);
2260 /* Display it as active. */
2261 show_mouse_face (1);
2263 /* Handle the text property case. */
2264 else if (! NILP (mouse_face
))
2266 /* Find the range of text around this char that
2267 should be active. */
2268 Lisp_Object before
, after
, beginning
, end
;
2271 beginning
= Fmarker_position (w
->start
);
2272 XSET (end
, Lisp_Int
,
2273 (BUF_Z (XBUFFER (w
->buffer
))
2274 - XFASTINT (w
->window_end_pos
)));
2276 = Fprevious_single_property_change (make_number (pos
+ 1),
2278 w
->buffer
, beginning
);
2280 = Fnext_single_property_change (position
, Qmouse_face
,
2282 /* Record this as the current active region. */
2283 fast_find_position (window
, before
, &mouse_face_beg_col
,
2284 &mouse_face_beg_row
);
2286 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2287 &mouse_face_end_row
);
2288 mouse_face_window
= window
;
2290 = compute_char_face (f
, w
, pos
, 0, 0,
2291 &ignore
, pos
+ 1, 1);
2293 /* Display it as active. */
2294 show_mouse_face (1);
2298 current_buffer
= obuf
;
2303 /* Find the row and column of position POS in window WINDOW.
2304 Store them in *COLUMNP and *ROWP.
2305 This assumes display in WINDOW is up to date.
2306 If POS is above start of WINDOW, return coords
2307 of start of first screen line.
2308 If POS is after end of WINDOW, return coords of end of last screen line.
2310 Value is 1 if POS is in range, 0 if it was off screen. */
2313 fast_find_position (window
, pos
, columnp
, rowp
)
2316 int *columnp
, *rowp
;
2318 struct window
*w
= XWINDOW (window
);
2319 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2324 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2325 int width
= window_internal_width (w
);
2329 /* Find the right row. */
2334 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2335 if (linestart
> pos
)
2341 /* Find the right column with in it. */
2342 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2344 for (i
= 0; i
< width
; i
++)
2346 if (charstarts
[left
+ i
] == pos
)
2349 *columnp
= i
+ left
;
2352 else if (charstarts
[left
+ i
] > pos
)
2354 else if (charstarts
[left
+ i
] > 0)
2363 /* Display the active region described by mouse_face_*
2364 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2367 show_mouse_face (hl
)
2370 struct window
*w
= XWINDOW (mouse_face_window
);
2371 int width
= window_internal_width (w
);
2372 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2375 int old_curs_x
= curs_x
;
2376 int old_curs_y
= curs_y
;
2378 /* Set these variables temporarily
2379 so that if we have to turn the cursor off and on again
2380 we will put it back at the same place. */
2381 curs_x
= f
->phys_cursor_x
;
2382 curs_y
= f
->phys_cursor_y
;
2384 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2386 int column
= (i
== mouse_face_beg_row
? mouse_face_beg_col
: w
->left
);
2387 int endcolumn
= (i
== mouse_face_end_row
? mouse_face_end_col
: w
->left
+ width
);
2388 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2390 /* If the cursor's in the text we are about to rewrite,
2391 turn the cursor off. */
2393 && curs_x
>= mouse_face_beg_col
- 1 && curs_x
<= mouse_face_end_col
)
2395 x_display_cursor (f
, 0);
2400 CHAR_TO_PIXEL_COL (f
, column
),
2401 CHAR_TO_PIXEL_ROW (f
, i
),
2402 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2404 /* Highlight with mouse face if hl > 0. */
2408 /* If we turned the cursor off, turn it back on. */
2410 x_display_cursor (f
, 1);
2412 curs_x
= old_curs_x
;
2413 curs_y
= old_curs_y
;
2415 /* Change the mouse cursor according to the value of HL. */
2417 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->cross_cursor
);
2419 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->text_cursor
);
2422 /* Clear out the mouse-highlighted active region.
2423 Redraw it unhighlighted first. */
2428 if (! NILP (mouse_face_window
))
2429 show_mouse_face (0);
2431 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2432 mouse_face_end_row
= mouse_face_end_col
= -1;
2433 mouse_face_window
= Qnil
;
2436 static struct scroll_bar
*x_window_to_scroll_bar ();
2437 static void x_scroll_bar_report_motion ();
2439 /* Return the current position of the mouse.
2441 If the mouse movement started in a scroll bar, set *f, *bar_window,
2442 and *part to the frame, window, and scroll bar part that the mouse
2443 is over. Set *x and *y to the portion and whole of the mouse's
2444 position on the scroll bar.
2446 If the mouse movement started elsewhere, set *f to the frame the
2447 mouse is on, *bar_window to nil, and *x and *y to the character cell
2450 Set *time to the server timestamp for the time at which the mouse
2451 was at this position.
2453 Don't store anything if we don't have a valid set of values to report.
2455 This clears the mouse_moved flag, so we can wait for the next mouse
2456 movement. This also calls XQueryPointer, which will cause the
2457 server to give us another MotionNotify when the mouse moves
2461 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
2463 Lisp_Object
*bar_window
;
2464 enum scroll_bar_part
*part
;
2466 unsigned long *time
;
2472 if (! NILP (last_mouse_scroll_bar
))
2473 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
2479 Window dummy_window
;
2483 last_mouse_scroll_bar
= Qnil
;
2485 /* Figure out which root window we're on. */
2486 XQueryPointer (x_current_display
,
2487 DefaultRootWindow (x_current_display
),
2489 /* The root window which contains the pointer. */
2492 /* Trash which we can't trust if the pointer is on
2493 a different screen. */
2496 /* The position on that root window. */
2499 /* More trash we can't trust. */
2502 /* Modifier keys and pointer buttons, about which
2504 (unsigned int *) &dummy
);
2506 /* Now we have a position on the root; find the innermost window
2507 containing the pointer. */
2511 int parent_x
, parent_y
;
2515 if (x_mouse_grabbed
&& last_mouse_frame
2516 && FRAME_LIVE_P (last_mouse_frame
))
2518 /* If mouse was grabbed on a frame, give coords for that frame
2519 even if the mouse is now outside it. */
2520 XTranslateCoordinates (x_current_display
,
2522 /* From-window, to-window. */
2523 root
, FRAME_X_WINDOW (last_mouse_frame
),
2525 /* From-position, to-position. */
2526 root_x
, root_y
, &win_x
, &win_y
,
2530 f1
= last_mouse_frame
;
2536 XTranslateCoordinates (x_current_display
,
2538 /* From-window, to-window. */
2541 /* From-position, to-position. */
2542 root_x
, root_y
, &win_x
, &win_y
,
2555 /* Now we know that:
2556 win is the innermost window containing the pointer
2557 (XTC says it has no child containing the pointer),
2558 win_x and win_y are the pointer's position in it
2559 (XTC did this the last time through), and
2560 parent_x and parent_y are the pointer's position in win's parent.
2561 (They are what win_x and win_y were when win was child.
2562 If win is the root window, it has no parent, and
2563 parent_{x,y} are invalid, but that's okay, because we'll
2564 never use them in that case.) */
2566 /* Is win one of our frames? */
2567 f1
= x_any_window_to_frame (win
);
2570 /* If not, is it one of our scroll bars? */
2573 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2577 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2585 int ignore1
, ignore2
;
2587 /* Ok, we found a frame. Store all the values. */
2589 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2590 &last_mouse_glyph
, x_mouse_grabbed
);
2595 XSET (*x
, Lisp_Int
, win_x
);
2596 XSET (*y
, Lisp_Int
, win_y
);
2597 *time
= last_mouse_movement_time
;
2605 #else /* ! defined (HAVE_X11) */
2606 #define XEvent XKeyPressedEvent
2607 #endif /* ! defined (HAVE_X11) */
2609 /* Scroll bar support. */
2611 /* Given an X window ID, find the struct scroll_bar which manages it.
2612 This can be called in GC, so we have to make sure to strip off mark
2614 static struct scroll_bar
*
2615 x_window_to_scroll_bar (window_id
)
2618 Lisp_Object tail
, frame
;
2620 for (tail
= Vframe_list
;
2621 XGCTYPE (tail
) == Lisp_Cons
;
2622 tail
= XCONS (tail
)->cdr
)
2624 Lisp_Object frame
, bar
, condemned
;
2626 frame
= XCONS (tail
)->car
;
2627 /* All elements of Vframe_list should be frames. */
2628 if (XGCTYPE (frame
) != Lisp_Frame
)
2631 /* Scan this frame's scroll bar list for a scroll bar with the
2633 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2634 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2635 /* This trick allows us to search both the ordinary and
2636 condemned scroll bar lists with one loop. */
2637 ! GC_NILP (bar
) || (bar
= condemned
,
2640 bar
= XSCROLL_BAR (bar
)->next
)
2641 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2642 return XSCROLL_BAR (bar
);
2648 /* Open a new X window to serve as a scroll bar, and return the
2649 scroll bar vector for it. */
2650 static struct scroll_bar
*
2651 x_scroll_bar_create (window
, top
, left
, width
, height
)
2652 struct window
*window
;
2653 int top
, left
, width
, height
;
2655 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2656 struct scroll_bar
*bar
=
2657 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2662 XSetWindowAttributes a
;
2664 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2665 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2666 | ButtonMotionMask
| PointerMotionHintMask
2668 a
.cursor
= x_vertical_scroll_bar_cursor
;
2670 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2675 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2676 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2677 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2678 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2679 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2680 sb_widget
= XtCreateManagedWidget ("box",
2682 frame
->display
.x
->edit_widget
, al
, ac
);
2683 SET_SCROLL_BAR_X_WINDOW
2684 (bar
, sb_widget
->core
.window
);
2686 SET_SCROLL_BAR_X_WINDOW
2688 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2690 /* Position and size of scroll bar. */
2691 left
, top
, width
, height
,
2693 /* Border width, depth, class, and visual. */
2694 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2700 XSET (bar
->window
, Lisp_Window
, window
);
2701 XSET (bar
->top
, Lisp_Int
, top
);
2702 XSET (bar
->left
, Lisp_Int
, left
);
2703 XSET (bar
->width
, Lisp_Int
, width
);
2704 XSET (bar
->height
, Lisp_Int
, height
);
2705 XSET (bar
->start
, Lisp_Int
, 0);
2706 XSET (bar
->end
, Lisp_Int
, 0);
2707 bar
->dragging
= Qnil
;
2709 /* Add bar to its frame's list of scroll bars. */
2710 bar
->next
= FRAME_SCROLL_BARS (frame
);
2712 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2713 if (! NILP (bar
->next
))
2714 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2716 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2723 /* Draw BAR's handle in the proper position.
2724 If the handle is already drawn from START to END, don't bother
2725 redrawing it, unless REBUILD is non-zero; in that case, always
2726 redraw it. (REBUILD is handy for drawing the handle after expose
2729 Normally, we want to constrain the start and end of the handle to
2730 fit inside its rectangle, but if the user is dragging the scroll bar
2731 handle, we want to let them drag it down all the way, so that the
2732 bar's top is as far down as it goes; otherwise, there's no way to
2733 move to the very end of the buffer. */
2735 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2736 struct scroll_bar
*bar
;
2740 int dragging
= ! NILP (bar
->dragging
);
2741 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2742 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2744 /* If the display is already accurate, do nothing. */
2746 && start
== XINT (bar
->start
)
2747 && end
== XINT (bar
->end
))
2753 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2754 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2755 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2757 /* Make sure the values are reasonable, and try to preserve
2758 the distance between start and end. */
2760 int length
= end
- start
;
2764 else if (start
> top_range
)
2766 end
= start
+ length
;
2770 else if (end
> top_range
&& ! dragging
)
2774 /* Store the adjusted setting in the scroll bar. */
2775 XSET (bar
->start
, Lisp_Int
, start
);
2776 XSET (bar
->end
, Lisp_Int
, end
);
2778 /* Clip the end position, just for display. */
2779 if (end
> top_range
)
2782 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2783 below top positions, to make sure the handle is always at least
2784 that many pixels tall. */
2785 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2787 /* Draw the empty space above the handle. Note that we can't clear
2788 zero-height areas; that means "clear to end of window." */
2790 XClearArea (x_current_display
, w
,
2792 /* x, y, width, height, and exposures. */
2793 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2794 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2795 inside_width
, start
,
2798 /* Draw the handle itself. */
2799 XFillRectangle (x_current_display
, w
, gc
,
2801 /* x, y, width, height */
2802 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2803 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2804 inside_width
, end
- start
);
2807 /* Draw the empty space below the handle. Note that we can't
2808 clear zero-height areas; that means "clear to end of window." */
2809 if (end
< inside_height
)
2810 XClearArea (x_current_display
, w
,
2812 /* x, y, width, height, and exposures. */
2813 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2814 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2815 inside_width
, inside_height
- end
,
2823 /* Move a scroll bar around on the screen, to accommodate changing
2824 window configurations. */
2826 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2827 struct scroll_bar
*bar
;
2828 int top
, left
, width
, height
;
2834 unsigned int mask
= 0;
2841 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2842 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2843 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2844 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2847 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2851 XSET (bar
->left
, Lisp_Int
, left
);
2852 XSET (bar
->top
, Lisp_Int
, top
);
2853 XSET (bar
->width
, Lisp_Int
, width
);
2854 XSET (bar
->height
, Lisp_Int
, height
);
2859 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2862 x_scroll_bar_remove (bar
)
2863 struct scroll_bar
*bar
;
2865 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2869 /* Destroy the window. */
2870 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2872 /* Disassociate this scroll bar from its window. */
2873 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2878 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2879 that we are displaying PORTION characters out of a total of WHOLE
2880 characters, starting at POSITION. If WINDOW has no scroll bar,
2883 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2884 struct window
*window
;
2885 int portion
, whole
, position
;
2887 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2888 int top
= XINT (window
->top
);
2889 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2890 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2892 /* Where should this scroll bar be, pixelwise? */
2893 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2894 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2895 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2896 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2898 struct scroll_bar
*bar
;
2900 /* Does the scroll bar exist yet? */
2901 if (NILP (window
->vertical_scroll_bar
))
2902 bar
= x_scroll_bar_create (window
,
2903 pixel_top
, pixel_left
,
2904 pixel_width
, pixel_height
);
2907 /* It may just need to be moved and resized. */
2908 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2909 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2912 /* Set the scroll bar's current state, unless we're currently being
2914 if (NILP (bar
->dragging
))
2917 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2920 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2923 int start
= ((double) position
* top_range
) / whole
;
2924 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2926 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2930 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2934 /* The following three hooks are used when we're doing a thorough
2935 redisplay of the frame. We don't explicitly know which scroll bars
2936 are going to be deleted, because keeping track of when windows go
2937 away is a real pain - "Can you say set-window-configuration, boys
2938 and girls?" Instead, we just assert at the beginning of redisplay
2939 that *all* scroll bars are to be removed, and then save a scroll bar
2940 from the fiery pit when we actually redisplay its window. */
2942 /* Arrange for all scroll bars on FRAME to be removed at the next call
2943 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2944 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2946 XTcondemn_scroll_bars (frame
)
2949 /* The condemned list should be empty at this point; if it's not,
2950 then the rest of Emacs isn't using the condemn/redeem/judge
2951 protocol correctly. */
2952 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2955 /* Move them all to the "condemned" list. */
2956 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2957 FRAME_SCROLL_BARS (frame
) = Qnil
;
2960 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2961 Note that WINDOW isn't necessarily condemned at all. */
2963 XTredeem_scroll_bar (window
)
2964 struct window
*window
;
2966 struct scroll_bar
*bar
;
2968 /* We can't redeem this window's scroll bar if it doesn't have one. */
2969 if (NILP (window
->vertical_scroll_bar
))
2972 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2974 /* Unlink it from the condemned list. */
2976 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2978 if (NILP (bar
->prev
))
2980 /* If the prev pointer is nil, it must be the first in one of
2982 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2983 /* It's not condemned. Everything's fine. */
2985 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2986 window
->vertical_scroll_bar
))
2987 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2989 /* If its prev pointer is nil, it must be at the front of
2990 one or the other! */
2994 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2996 if (! NILP (bar
->next
))
2997 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2999 bar
->next
= FRAME_SCROLL_BARS (f
);
3001 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
3002 if (! NILP (bar
->next
))
3003 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
3007 /* Remove all scroll bars on FRAME that haven't been saved since the
3008 last call to `*condemn_scroll_bars_hook'. */
3010 XTjudge_scroll_bars (f
)
3013 Lisp_Object bar
, next
;
3015 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3017 /* Clear out the condemned list now so we won't try to process any
3018 more events on the hapless scroll bars. */
3019 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3021 for (; ! NILP (bar
); bar
= next
)
3023 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3025 x_scroll_bar_remove (b
);
3028 b
->next
= b
->prev
= Qnil
;
3031 /* Now there should be no references to the condemned scroll bars,
3032 and they should get garbage-collected. */
3036 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3038 This may be called from a signal handler, so we have to ignore GC
3041 x_scroll_bar_expose (bar
, event
)
3042 struct scroll_bar
*bar
;
3045 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3046 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
3050 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3052 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3053 XDrawRectangle (x_current_display
, w
, gc
,
3055 /* x, y, width, height */
3056 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
3061 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3062 is set to something other than no_event, it is enqueued.
3064 This may be called from a signal handler, so we have to ignore GC
3067 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3068 struct scroll_bar
*bar
;
3070 struct input_event
*emacs_event
;
3072 if (XGCTYPE (bar
->window
) != Lisp_Window
)
3075 emacs_event
->kind
= scroll_bar_click
;
3076 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3077 emacs_event
->modifiers
=
3078 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
3079 | (event
->type
== ButtonRelease
3082 emacs_event
->frame_or_window
= bar
->window
;
3083 emacs_event
->timestamp
= event
->xbutton
.time
;
3085 int internal_height
=
3086 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3088 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3089 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3092 if (y
> top_range
) y
= top_range
;
3094 if (y
< XINT (bar
->start
))
3095 emacs_event
->part
= scroll_bar_above_handle
;
3096 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3097 emacs_event
->part
= scroll_bar_handle
;
3099 emacs_event
->part
= scroll_bar_below_handle
;
3101 /* Just because the user has clicked on the handle doesn't mean
3102 they want to drag it. Lisp code needs to be able to decide
3103 whether or not we're dragging. */
3105 /* If the user has just clicked on the handle, record where they're
3107 if (event
->type
== ButtonPress
3108 && emacs_event
->part
== scroll_bar_handle
)
3109 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
3112 /* If the user has released the handle, set it to its final position. */
3113 if (event
->type
== ButtonRelease
3114 && ! NILP (bar
->dragging
))
3116 int new_start
= y
- XINT (bar
->dragging
);
3117 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3119 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3120 bar
->dragging
= Qnil
;
3123 /* Same deal here as the other #if 0. */
3125 /* Clicks on the handle are always reported as occurring at the top of
3127 if (emacs_event
->part
== scroll_bar_handle
)
3128 emacs_event
->x
= bar
->start
;
3130 XSET (emacs_event
->x
, Lisp_Int
, y
);
3132 XSET (emacs_event
->x
, Lisp_Int
, y
);
3135 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
3139 /* Handle some mouse motion while someone is dragging the scroll bar.
3141 This may be called from a signal handler, so we have to ignore GC
3144 x_scroll_bar_note_movement (bar
, event
)
3145 struct scroll_bar
*bar
;
3148 last_mouse_movement_time
= event
->xmotion
.time
;
3151 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
3153 /* If we're dragging the bar, display it. */
3154 if (! GC_NILP (bar
->dragging
))
3156 /* Where should the handle be now? */
3157 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3159 if (new_start
!= XINT (bar
->start
))
3161 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3163 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3167 /* Call XQueryPointer so we'll get an event the next time the mouse
3168 moves and we can see *still* on the same position. */
3171 Window dummy_window
;
3173 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3174 &dummy_window
, &dummy_window
,
3175 &dummy
, &dummy
, &dummy
, &dummy
,
3176 (unsigned int *) &dummy
);
3180 /* Return information to the user about the current position of the mouse
3181 on the scroll bar. */
3183 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
3185 Lisp_Object
*bar_window
;
3186 enum scroll_bar_part
*part
;
3188 unsigned long *time
;
3190 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3192 Window dummy_window
;
3194 unsigned int dummy_mask
;
3198 /* Get the mouse's position relative to the scroll bar window, and
3200 if (! XQueryPointer (x_current_display
,
3201 SCROLL_BAR_X_WINDOW (bar
),
3203 /* Root, child, root x and root y. */
3204 &dummy_window
, &dummy_window
,
3205 &dummy_coord
, &dummy_coord
,
3207 /* Position relative to scroll bar. */
3210 /* Mouse buttons and modifier keys. */
3216 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3218 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3220 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3222 if (! NILP (bar
->dragging
))
3223 win_y
-= XINT (bar
->dragging
);
3227 if (win_y
> top_range
)
3230 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3231 *bar_window
= bar
->window
;
3233 if (! NILP (bar
->dragging
))
3234 *part
= scroll_bar_handle
;
3235 else if (win_y
< XINT (bar
->start
))
3236 *part
= scroll_bar_above_handle
;
3237 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3238 *part
= scroll_bar_handle
;
3240 *part
= scroll_bar_below_handle
;
3242 XSET (*x
, Lisp_Int
, win_y
);
3243 XSET (*y
, Lisp_Int
, top_range
);
3246 last_mouse_scroll_bar
= Qnil
;
3249 *time
= last_mouse_movement_time
;
3255 /* The screen has been cleared so we may have changed foreground or
3256 background colors, and the scroll bars may need to be redrawn.
3257 Clear out the scroll bars, and ask for expose events, so we can
3260 x_scroll_bar_clear (f
)
3265 for (bar
= FRAME_SCROLL_BARS (f
);
3266 XTYPE (bar
) == Lisp_Vector
;
3267 bar
= XSCROLL_BAR (bar
)->next
)
3268 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3272 /* This processes Expose events from the menubar specific X event
3273 loop in menubar.c. This allows to redisplay the frame if necessary
3274 when handling menubar or popup items. */
3277 process_expose_from_menu (event
)
3284 f
= x_window_to_frame (event
.xexpose
.window
);
3287 if (f
->async_visible
== 0)
3289 f
->async_visible
= 1;
3290 f
->async_iconified
= 0;
3291 SET_FRAME_GARBAGED (f
);
3295 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3296 event
.xexpose
.x
, event
.xexpose
.y
,
3297 event
.xexpose
.width
, event
.xexpose
.height
);
3302 struct scroll_bar
*bar
3303 = x_window_to_scroll_bar (event
.xexpose
.window
);
3306 x_scroll_bar_expose (bar
, &event
);
3312 /* Define a queue to save up SelectionRequest events for later handling. */
3314 struct selection_event_queue
3317 struct selection_event_queue
*next
;
3320 static struct selection_event_queue
*queue
;
3322 /* Nonzero means queue up certain events--don't process them yet. */
3323 static int x_queue_selection_requests
;
3325 /* Queue up an X event *EVENT, to be processed later. */
3328 x_queue_event (event
)
3331 struct selection_event_queue
*queue_tmp
3332 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3334 if (queue_tmp
!= NULL
)
3336 queue_tmp
->event
= *event
;
3337 queue_tmp
->next
= queue
;
3342 /* Take all the queued events and put them back
3343 so that they get processed afresh. */
3348 while (queue
!= NULL
)
3350 struct selection_event_queue
*queue_tmp
= queue
;
3351 XPutBackEvent (XDISPLAY
&queue_tmp
->event
);
3352 queue
= queue_tmp
->next
;
3353 free ((char *)queue_tmp
);
3357 /* Start queuing SelectionRequest events. */
3360 x_start_queuing_selection_requests ()
3362 x_queue_selection_requests
++;
3365 /* Stop queuing SelectionRequest events. */
3368 x_stop_queuing_selection_requests ()
3370 x_queue_selection_requests
--;
3371 x_unqueue_events ();
3374 /* The main X event-reading loop - XTread_socket. */
3376 /* Timestamp of enter window event. This is only used by XTread_socket,
3377 but we have to put it out here, since static variables within functions
3378 sometimes don't work. */
3379 static Time enter_timestamp
;
3381 /* This holds the state XLookupString needs to implement dead keys
3382 and other tricks known as "compose processing". _X Window System_
3383 says that a portable program can't use this, but Stephen Gildea assures
3384 me that letting the compiler initialize it to zeros will work okay.
3386 This must be defined outside of XTread_socket, for the same reasons
3387 given for enter_timestamp, above. */
3388 static XComposeStatus compose_status
;
3390 /* Communication with window managers. */
3391 Atom Xatom_wm_protocols
;
3393 /* Kinds of protocol things we may receive. */
3394 Atom Xatom_wm_take_focus
;
3395 Atom Xatom_wm_save_yourself
;
3396 Atom Xatom_wm_delete_window
;
3398 /* Other WM communication */
3399 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3400 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3402 /* Window manager communication. */
3403 Atom Xatom_wm_change_state
;
3405 /* EditRes protocol */
3406 Atom Xatom_editres_name
;
3408 /* Record the last 100 characters stored
3409 to help debug the loss-of-chars-during-GC problem. */
3411 short temp_buffer
[100];
3413 /* Read events coming from the X server.
3414 This routine is called by the SIGIO handler.
3415 We return as soon as there are no more events to be read.
3417 Events representing keys are stored in buffer BUFP,
3418 which can hold up to NUMCHARS characters.
3419 We return the number of characters stored into the buffer,
3420 thus pretending to be `read'.
3422 WAITP is nonzero if we should block until input arrives.
3423 EXPECTED is nonzero if the caller knows input is available. */
3426 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3428 register struct input_event
*bufp
;
3429 register int numchars
;
3436 int items_pending
; /* How many items are in the X queue. */
3439 int event_found
= 0;
3443 if (interrupt_input_blocked
)
3445 interrupt_input_pending
= 1;
3449 interrupt_input_pending
= 0;
3453 abort (); /* Don't think this happens. */
3456 /* If available, Xlib uses FIOSNBIO to make the socket
3457 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3458 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3459 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3460 fcntl (fileno (stdin
), F_SETFL
, 0);
3461 #endif /* ! defined (FIOSNBIO) */
3465 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3467 extern int read_alarm_should_throw
;
3468 read_alarm_should_throw
= 1;
3469 XPeekEvent (XDISPLAY
&event
);
3470 read_alarm_should_throw
= 0;
3472 #endif /* HAVE_SELECT */
3475 while (XStuffPending () != 0)
3477 XNextEvent (XDISPLAY
&event
);
3485 if (event
.xclient
.message_type
== Xatom_wm_protocols
3486 && event
.xclient
.format
== 32)
3488 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3490 f
= x_window_to_frame (event
.xclient
.window
);
3491 /* Since we set WM_TAKE_FOCUS, we must call
3492 XSetInputFocus explicitly. But not if f is null,
3493 since that might be an event for a deleted frame. */
3495 XSetInputFocus (event
.xclient
.display
,
3496 event
.xclient
.window
,
3497 RevertToPointerRoot
,
3498 event
.xclient
.data
.l
[1]);
3499 /* Not certain about handling scroll bars here */
3501 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3503 /* Save state modify the WM_COMMAND property to
3504 something which can reinstate us. This notifies
3505 the session manager, who's looking for such a
3506 PropertyNotify. Can restart processing when
3507 a keyboard or mouse event arrives. */
3510 /* This is just so we only give real data once
3511 for a single Emacs process. */
3512 if (x_top_window_to_frame (event
.xclient
.window
)
3514 XSetCommand (x_current_display
,
3515 event
.xclient
.window
,
3516 initial_argv
, initial_argc
);
3518 XSetCommand (x_current_display
,
3519 event
.xclient
.window
,
3523 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3525 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3532 bufp
->kind
= delete_window_event
;
3533 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3541 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3544 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3547 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3549 new_x
= event
.xclient
.data
.s
[0];
3550 new_y
= event
.xclient
.data
.s
[1];
3554 f
->display
.x
->left_pos
= new_x
;
3555 f
->display
.x
->top_pos
= new_y
;
3558 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3559 else if (event
.xclient
.message_type
== Xatom_editres_name
)
3561 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3562 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3564 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3568 case SelectionNotify
:
3569 #ifdef USE_X_TOOLKIT
3570 if (! x_window_to_frame (event
.xselection
.requestor
))
3572 #endif /* not USE_X_TOOLKIT */
3573 x_handle_selection_notify (&event
);
3576 case SelectionClear
: /* Someone has grabbed ownership. */
3577 #ifdef USE_X_TOOLKIT
3578 if (! x_window_to_frame (event
.xselectionclear
.window
))
3580 #endif /* USE_X_TOOLKIT */
3582 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3587 bufp
->kind
= selection_clear_event
;
3588 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3589 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3590 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3598 case SelectionRequest
: /* Someone wants our selection. */
3599 #ifdef USE_X_TOOLKIT
3600 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3602 #endif /* USE_X_TOOLKIT */
3603 if (x_queue_selection_requests
)
3604 x_queue_event (&event
);
3607 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3612 bufp
->kind
= selection_request_event
;
3613 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3614 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3615 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3616 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3617 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3618 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3626 case PropertyNotify
:
3627 #ifdef USE_X_TOOLKIT
3628 if (!x_any_window_to_frame (event
.xproperty
.window
))
3630 #endif /* not USE_X_TOOLKIT */
3631 x_handle_property_notify (&event
);
3634 case ReparentNotify
:
3635 f
= x_top_window_to_frame (event
.xreparent
.window
);
3639 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3640 x_real_positions (f
, &x
, &y
);
3641 f
->display
.x
->left_pos
= x
;
3642 f
->display
.x
->top_pos
= y
;
3647 f
= x_window_to_frame (event
.xexpose
.window
);
3650 if (f
->async_visible
== 0)
3652 f
->async_visible
= 1;
3653 f
->async_iconified
= 0;
3654 SET_FRAME_GARBAGED (f
);
3657 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3658 event
.xexpose
.x
, event
.xexpose
.y
,
3659 event
.xexpose
.width
, event
.xexpose
.height
);
3663 struct scroll_bar
*bar
3664 = x_window_to_scroll_bar (event
.xexpose
.window
);
3667 x_scroll_bar_expose (bar
, &event
);
3668 #ifdef USE_X_TOOLKIT
3671 #endif /* USE_X_TOOLKIT */
3675 case GraphicsExpose
: /* This occurs when an XCopyArea's
3676 source area was obscured or not
3678 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3682 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3683 event
.xgraphicsexpose
.width
,
3684 event
.xgraphicsexpose
.height
);
3686 #ifdef USE_X_TOOLKIT
3689 #endif /* USE_X_TOOLKIT */
3692 case NoExpose
: /* This occurs when an XCopyArea's
3693 source area was completely
3696 #else /* ! defined (HAVE_X11) */
3698 if (event
.subwindow
!= 0)
3699 break; /* duplicate event */
3700 f
= x_window_to_frame (event
.window
);
3701 if (event
.window
== f
->display
.x
->icon_desc
)
3704 f
->async_iconified
= 1;
3706 if (event
.window
== FRAME_X_WINDOW (f
))
3708 /* Say must check all windows' needs_exposure flags. */
3709 expose_all_windows
= 1;
3710 f
->display
.x
->needs_exposure
= 1;
3711 f
->async_visible
= 1;
3716 if (event
.subwindow
!= 0)
3717 break; /* duplicate event */
3718 f
= x_window_to_frame (event
.window
);
3719 if (event
.window
== f
->display
.x
->icon_desc
)
3724 /* If window already needs full redraw, ignore this rectangle. */
3725 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3727 /* Put the event on the queue of rectangles to redraw. */
3728 if (enqueue_event (&event
, &x_expose_queue
))
3729 /* If it is full, we can't record the rectangle,
3730 so redraw this entire window. */
3732 /* Say must check all windows' needs_exposure flags. */
3733 expose_all_windows
= 1;
3734 f
->display
.x
->needs_exposure
= 1;
3739 /* This should happen only when we are expecting it,
3740 in x_read_exposes. */
3742 #endif /* ! defined (HAVE_X11) */
3746 f
= x_any_window_to_frame (event
.xunmap
.window
);
3747 if (f
) /* F may no longer exist if
3748 the frame was deleted. */
3750 /* While a frame is unmapped, display generation is
3751 disabled; you don't want to spend time updating a
3752 display that won't ever be seen. */
3753 f
->async_visible
= 0;
3754 /* We can't distinguish, from the event, whether the window
3755 has become iconified or invisible. So assume, if it
3756 was previously visible, than now it is iconified.
3757 We depend on x_make_frame_invisible to mark it iconified. */
3758 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3759 f
->async_iconified
= 1;
3761 #ifdef USE_X_TOOLKIT
3763 #endif /* USE_X_TOOLKIT */
3767 /* We use x_top_window_to_frame because map events can come
3768 for subwindows and they don't mean that the frame is visible. */
3769 f
= x_top_window_to_frame (event
.xmap
.window
);
3772 f
->async_visible
= 1;
3773 f
->async_iconified
= 0;
3775 /* wait_reading_process_input will notice this and update
3776 the frame's display structures. */
3777 SET_FRAME_GARBAGED (f
);
3779 #ifdef USE_X_TOOLKIT
3781 #endif /* USE_X_TOOLKIT */
3784 /* Turn off processing if we become fully obscured. */
3785 case VisibilityNotify
:
3788 #else /* ! defined (HAVE_X11) */
3790 f
= x_window_to_frame (event
.window
);
3791 if (event
.window
== f
->display
.x
->icon_desc
)
3792 f
->async_iconified
= 0;
3793 if (event
.window
== FRAME_X_WINDOW (f
))
3794 f
->async_visible
= 0;
3796 #endif /* ! defined (HAVE_X11) */
3800 f
= x_any_window_to_frame (event
.xkey
.window
);
3804 KeySym keysym
, orig_keysym
;
3805 /* al%imercury@uunet.uu.net says that making this 81 instead of
3806 80 fixed a bug whereby meta chars made his Emacs hang. */
3807 unsigned char copy_buffer
[81];
3811 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3812 modifiers
= event
.xkey
.state
;
3814 /* This will have to go some day... */
3816 /* make_lispy_event turns chars into control chars.
3817 Don't do it here because XLookupString is too eager. */
3818 event
.xkey
.state
&= ~ControlMask
;
3820 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3823 orig_keysym
= keysym
;
3827 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3828 || keysym
== XK_Delete
3829 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3830 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3832 /* This recognizes the "extended function keys".
3833 It seems there's no cleaner way.
3834 Test IsModifierKey to avoid handling mode_switch
3836 || ((unsigned) (keysym
) >= XK_Select
3837 && (unsigned)(keysym
) < XK_KP_Space
)
3839 #ifdef XK_dead_circumflex
3840 || orig_keysym
== XK_dead_circumflex
3842 #ifdef XK_dead_grave
3843 || orig_keysym
== XK_dead_grave
3845 #ifdef XK_dead_tilde
3846 || orig_keysym
== XK_dead_tilde
3848 #ifdef XK_dead_diaeresis
3849 || orig_keysym
== XK_dead_diaeresis
3851 #ifdef XK_dead_macron
3852 || orig_keysym
== XK_dead_macron
3854 #ifdef XK_dead_degree
3855 || orig_keysym
== XK_dead_degree
3857 #ifdef XK_dead_acute
3858 || orig_keysym
== XK_dead_acute
3860 #ifdef XK_dead_cedilla
3861 || orig_keysym
== XK_dead_cedilla
3863 #ifdef XK_dead_breve
3864 || orig_keysym
== XK_dead_breve
3866 #ifdef XK_dead_ogonek
3867 || orig_keysym
== XK_dead_ogonek
3869 #ifdef XK_dead_caron
3870 || orig_keysym
== XK_dead_caron
3872 #ifdef XK_dead_doubleacute
3873 || orig_keysym
== XK_dead_doubleacute
3875 #ifdef XK_dead_abovedot
3876 || orig_keysym
== XK_dead_abovedot
3878 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3879 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3880 /* Any "vendor-specific" key is ok. */
3881 || (orig_keysym
& (1 << 28)))
3882 && ! (IsModifierKey (orig_keysym
)
3884 #ifdef XK_Mode_switch
3885 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3888 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3890 #endif /* not HAVE_X11R5 */
3893 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3895 temp_buffer
[temp_index
++] = keysym
;
3896 bufp
->kind
= non_ascii_keystroke
;
3897 bufp
->code
= keysym
;
3898 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3899 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3900 bufp
->timestamp
= event
.xkey
.time
;
3905 else if (numchars
> nbytes
)
3909 for (i
= 0; i
< nbytes
; i
++)
3911 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3913 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3914 bufp
->kind
= ascii_keystroke
;
3915 bufp
->code
= copy_buffer
[i
];
3916 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3917 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3918 bufp
->timestamp
= event
.xkey
.time
;
3932 #else /* ! defined (HAVE_X11) */
3935 register char *where_mapping
;
3937 f
= x_window_to_frame (event
.window
);
3938 /* Ignore keys typed on icon windows. */
3939 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3941 where_mapping
= XLookupMapping (&event
, &nbytes
);
3942 /* Nasty fix for arrow keys */
3943 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3945 switch (event
.detail
& 0xff)
3947 case KC_CURSOR_LEFT
:
3948 where_mapping
= "\002";
3950 case KC_CURSOR_RIGHT
:
3951 where_mapping
= "\006";
3954 where_mapping
= "\020";
3956 case KC_CURSOR_DOWN
:
3957 where_mapping
= "\016";
3962 if (numchars
- nbytes
> 0)
3966 for (i
= 0; i
< nbytes
; i
++)
3968 bufp
->kind
= ascii_keystroke
;
3969 bufp
->code
= where_mapping
[i
];
3970 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3971 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3979 #endif /* ! defined (HAVE_X11) */
3983 /* Here's a possible interpretation of the whole
3984 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3985 FocusIn event, you have to get a FocusOut event before you
3986 relinquish the focus. If you haven't received a FocusIn event,
3987 then a mere LeaveNotify is enough to free you. */
3990 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3992 if (event
.xcrossing
.focus
) /* Entered Window */
3994 /* Avoid nasty pop/raise loops. */
3995 if (f
&& (!(f
->auto_raise
)
3997 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3999 x_new_focus_frame (f
);
4000 enter_timestamp
= event
.xcrossing
.time
;
4003 else if (f
== x_focus_frame
)
4004 x_new_focus_frame (0);
4005 /* EnterNotify counts as mouse movement,
4006 so update things that depend on mouse position. */
4008 note_mouse_movement (f
, &event
.xmotion
);
4009 #ifdef USE_X_TOOLKIT
4011 #endif /* USE_X_TOOLKIT */
4015 f
= x_any_window_to_frame (event
.xfocus
.window
);
4016 if (event
.xfocus
.detail
!= NotifyPointer
)
4017 x_focus_event_frame
= f
;
4019 x_new_focus_frame (f
);
4020 #ifdef USE_X_TOOLKIT
4022 #endif /* USE_X_TOOLKIT */
4027 f
= x_top_window_to_frame (event
.xcrossing
.window
);
4030 if (f
== mouse_face_mouse_frame
)
4031 /* If we move outside the frame,
4032 then we're certainly no longer on any text in the frame. */
4033 clear_mouse_face ();
4035 if (event
.xcrossing
.focus
)
4037 if (! x_focus_event_frame
)
4038 x_new_focus_frame (0);
4040 x_new_focus_frame (f
);
4044 if (f
== x_focus_event_frame
)
4045 x_focus_event_frame
= 0;
4046 if (f
== x_focus_frame
)
4047 x_new_focus_frame (0);
4050 #ifdef USE_X_TOOLKIT
4052 #endif /* USE_X_TOOLKIT */
4056 f
= x_any_window_to_frame (event
.xfocus
.window
);
4057 if (event
.xfocus
.detail
!= NotifyPointer
4058 && f
== x_focus_event_frame
)
4059 x_focus_event_frame
= 0;
4060 if (f
&& f
== x_focus_frame
)
4061 x_new_focus_frame (0);
4062 #ifdef USE_X_TOOLKIT
4064 #endif /* USE_X_TOOLKIT */
4067 #else /* ! defined (HAVE_X11) */
4070 if ((event
.detail
& 0xFF) == 1)
4071 break; /* Coming from our own subwindow */
4072 if (event
.subwindow
!= 0)
4073 break; /* Entering our own subwindow. */
4076 f
= x_window_to_frame (event
.window
);
4079 x_new_focus_frame (f
);
4084 if ((event
.detail
& 0xFF) == 1)
4085 break; /* Entering our own subwindow */
4086 if (event
.subwindow
!= 0)
4087 break; /* Leaving our own subwindow. */
4090 if (x_focus_frame
== 0
4091 && x_input_frame
!= 0
4092 && x_input_frame
== x_window_to_frame (event
.window
)
4093 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
4098 frame_unhighlight (f
);
4101 #endif /* ! defined (HAVE_X11) */
4106 if (x_mouse_grabbed
&& last_mouse_frame
4107 && FRAME_LIVE_P (last_mouse_frame
))
4108 f
= last_mouse_frame
;
4110 f
= x_window_to_frame (event
.xmotion
.window
);
4112 note_mouse_movement (f
, &event
.xmotion
);
4115 struct scroll_bar
*bar
4116 = x_window_to_scroll_bar (event
.xmotion
.window
);
4119 x_scroll_bar_note_movement (bar
, &event
);
4121 /* If we move outside the frame,
4122 then we're certainly no longer on any text in the frame. */
4123 clear_mouse_face ();
4126 #if 0 /* This should be unnecessary, since the toolkit has no use
4127 for motion events that happen outside of the menu event loop,
4128 and it seems to cause the bug that mouse events stop coming
4130 #ifdef USE_X_TOOLKIT
4132 #endif /* USE_X_TOOLKIT */
4136 case ConfigureNotify
:
4137 f
= x_any_window_to_frame (event
.xconfigure
.window
);
4138 #ifdef USE_X_TOOLKIT
4141 && ! event
.xconfigure
.send_event
4143 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
4148 /* Find the position of the outside upper-left corner of
4149 the window, in the root coordinate system. Don't
4150 refer to the parent window here; we may be processing
4151 this event after the window manager has changed our
4152 parent, but before we have reached the ReparentNotify. */
4153 XTranslateCoordinates (x_current_display
,
4155 /* From-window, to-window. */
4156 XtWindow (f
->display
.x
->widget
),
4159 /* From-position, to-position. */
4160 -event
.xconfigure
.border_width
,
4161 -event
.xconfigure
.border_width
,
4166 event
.xconfigure
.x
= win_x
;
4167 event
.xconfigure
.y
= win_y
;
4169 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4170 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4171 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4172 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4174 /* What we have now is the position of Emacs's own window.
4175 Convert that to the position of the window manager window. */
4178 x_real_positions (f
, &x
, &y
);
4179 f
->display
.x
->left_pos
= x
;
4180 f
->display
.x
->top_pos
= y
;
4184 #else /* not USE_X_TOOLKIT */
4187 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4188 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4190 /* Even if the number of character rows and columns has
4191 not changed, the font size may have changed, so we need
4192 to check the pixel dimensions as well. */
4193 if (columns
!= f
->width
4194 || rows
!= f
->height
4195 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
4196 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
4198 change_frame_size (f
, rows
, columns
, 0, 1);
4199 SET_FRAME_GARBAGED (f
);
4202 if (! event
.xconfigure
.send_event
)
4207 /* Find the position of the outside upper-left corner of
4208 the window, in the root coordinate system. Don't
4209 refer to the parent window here; we may be processing
4210 this event after the window manager has changed our
4211 parent, but before we have reached the ReparentNotify. */
4212 XTranslateCoordinates (x_current_display
,
4214 /* From-window, to-window. */
4215 f
->display
.x
->window_desc
,
4218 /* From-position, to-position. */
4219 -event
.xconfigure
.border_width
,
4220 -event
.xconfigure
.border_width
,
4225 event
.xconfigure
.x
= win_x
;
4226 event
.xconfigure
.y
= win_y
;
4229 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4230 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4231 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4232 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4234 /* What we have now is the position of Emacs's own window.
4235 Convert that to the position of the window manager window. */
4238 x_real_positions (f
, &x
, &y
);
4239 f
->display
.x
->left_pos
= x
;
4240 f
->display
.x
->top_pos
= y
;
4241 if (y
!= event
.xconfigure
.y
)
4243 /* Since the WM decorations come below top_pos now,
4244 we must put them below top_pos in the future. */
4245 f
->display
.x
->win_gravity
= NorthWestGravity
;
4246 x_wm_set_size_hint (f
, 0, 0);
4250 #endif /* not USE_X_TOOLKIT */
4256 /* If we decide we want to generate an event to be seen
4257 by the rest of Emacs, we put it here. */
4258 struct input_event emacs_event
;
4259 emacs_event
.kind
= no_event
;
4261 bzero (&compose_status
, sizeof (compose_status
));
4263 f
= x_window_to_frame (event
.xbutton
.window
);
4266 if (!x_focus_frame
|| (f
== x_focus_frame
))
4267 construct_mouse_click (&emacs_event
, &event
, f
);
4271 struct scroll_bar
*bar
4272 = x_window_to_scroll_bar (event
.xbutton
.window
);
4275 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4276 #ifdef USE_X_TOOLKIT
4279 f
= x_any_window_to_frame (event
.xbutton
.window
);
4280 if (f
&& event
.type
== ButtonPress
)
4281 construct_menu_click (&emacs_event
,
4284 #endif /* USE_X_TOOLKIT */
4287 if (event
.type
== ButtonPress
)
4289 x_mouse_grabbed
|= (1 << event
.xbutton
.button
);
4290 Vmouse_depressed
= Qt
;
4291 last_mouse_frame
= f
;
4295 x_mouse_grabbed
&= ~(1 << event
.xbutton
.button
);
4296 if (!x_mouse_grabbed
)
4297 Vmouse_depressed
= Qnil
;
4300 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4302 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4308 #ifdef USE_X_TOOLKIT
4310 #endif /* USE_X_TOOLKIT */
4314 #else /* ! defined (HAVE_X11) */
4316 case ButtonReleased
:
4317 f
= x_window_to_frame (event
.window
);
4320 if (event
.window
== f
->display
.x
->icon_desc
)
4322 x_make_frame_visible (f
);
4324 if (warp_mouse_on_deiconify
)
4325 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
4328 if (event
.window
== FRAME_X_WINDOW (f
))
4334 enqueue_event (&event
, &x_mouse_queue
);
4337 bufp
->kind
= ascii_keystroke
;
4338 bufp
->code
= 'X' & 037; /* C-x */
4339 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4340 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4343 bufp
->kind
= ascii_keystroke
;
4344 bufp
->code
= 0; /* C-@ */
4345 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4346 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4353 #endif /* ! defined (HAVE_X11) */
4357 case CirculateNotify
:
4359 case CirculateRequest
:
4362 #endif /* ! defined (HAVE_X11) */
4365 /* Someone has changed the keyboard mapping - update the
4367 switch (event
.xmapping
.request
)
4369 case MappingModifier
:
4370 x_find_modifier_meanings ();
4371 /* This is meant to fall through. */
4372 case MappingKeyboard
:
4373 XRefreshKeyboardMapping (&event
.xmapping
);
4375 #ifdef USE_X_TOOLKIT
4377 #endif /* USE_X_TOOLKIT */
4381 #ifdef USE_X_TOOLKIT
4384 XtDispatchEvent (&event
);
4386 #endif /* USE_X_TOOLKIT */
4391 /* On some systems, an X bug causes Emacs to get no more events
4392 when the window is destroyed. Detect that. (1994.) */
4395 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4396 One XNOOP in 100 loops will make Emacs terminate.
4397 B. Bretthauer, 1994 */
4399 if (x_noop_count
>= 100)
4402 XNoOp (x_current_display
);
4406 #if 0 /* This fails for serial-line connections to the X server,
4407 because the characters arrive one by one, and a partial
4408 command makes select return but gives nothing to read.
4409 We'll have to hope that the bug that this tried to fix
4410 in 1988 has been fixed in Xlib or the X server. */
4412 if (expected
&& ! event_found
)
4414 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4415 there is an EOF condition; in other words, that X has died.
4416 Act as if there had been a hangup. */
4417 int fd
= ConnectionNumber (x_current_display
);
4418 SELECT_TYPE mask
, junk1
, junk2
;
4423 EMACS_SET_SECS_USECS (timeout
, 0, 0);
4426 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
4427 && !XStuffPending ())
4428 kill (getpid (), SIGHUP
);
4430 #endif /* HAVE_SELECT */
4434 if (updating_frame
== 0)
4435 x_do_pending_expose ();
4438 /* If the focus was just given to an autoraising frame,
4441 if (pending_autoraise_frame
)
4443 x_raise_frame (pending_autoraise_frame
);
4444 pending_autoraise_frame
= 0;
4453 /* Read and process only Expose events
4454 until we get an ExposeCopy event; then return.
4455 This is used in insert/delete line.
4456 We assume input is already blocked. */
4462 XKeyPressedEvent event
;
4466 /* while there are more events*/
4467 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
4471 if (event
.subwindow
!= 0)
4472 break; /* duplicate event */
4473 f
= x_window_to_frame (event
.window
);
4474 if (event
.window
== f
->display
.x
->icon_desc
)
4479 if (event
.window
== FRAME_X_WINDOW (f
))
4481 expose_all_windows
= 1;
4482 f
->display
.x
->needs_exposure
= 1;
4488 if (event
.subwindow
!= 0)
4489 break; /* duplicate event */
4490 f
= x_window_to_frame (event
.window
);
4491 if (event
.window
== f
->display
.x
->icon_desc
)
4496 /* If window already needs full redraw, ignore this rectangle. */
4497 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
4499 /* Put the event on the queue of rectangles to redraw. */
4500 if (enqueue_event (&event
, &x_expose_queue
))
4501 /* If it is full, we can't record the rectangle,
4502 so redraw this entire window. */
4504 /* Say must check all windows' needs_exposure flags. */
4505 expose_all_windows
= 1;
4506 f
->display
.x
->needs_exposure
= 1;
4515 #endif /* HAVE_X11 */
4518 /* Drawing the cursor. */
4521 /* Draw a hollow box cursor. Don't change the inside of the box. */
4527 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
4528 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
4529 int width
= FONT_WIDTH (f
->display
.x
->font
);
4530 int height
= f
->display
.x
->line_height
;
4533 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4534 f
->display
.x
->cursor_gc
,
4535 left
, top
, width
- 1, height
- 1);
4536 #else /* ! defined (HAVE_X11) */
4537 XPixSet (FRAME_X_WINDOW (f
),
4538 left
, top
, width
, 1,
4539 f
->display
.x
->cursor_pixel
);
4541 XPixSet (FRAME_X_WINDOW (f
),
4542 left
, top
, 1, height
,
4543 f
->display
.x
->cursor_pixel
);
4545 XPixSet (FRAME_X_WINDOW (f
),
4546 left
+width
-1, top
, 1, height
,
4547 f
->display
.x
->cursor_pixel
);
4549 XPixSet (FRAME_X_WINDOW (f
),
4550 left
, top
+height
-1, width
, 1,
4551 f
->display
.x
->cursor_pixel
);
4552 #endif /* ! defined (HAVE_X11) */
4555 /* Clear the cursor of frame F to background color,
4556 and mark the cursor as not shown.
4557 This is used when the text where the cursor is
4558 is about to be rewritten. */
4566 if (! FRAME_VISIBLE_P (f
)
4567 || f
->phys_cursor_x
< 0)
4571 x_display_cursor (f
, 0);
4572 #else /* ! defined (HAVE_X11) */
4573 XPixSet (FRAME_X_WINDOW (f
),
4574 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4575 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4576 FONT_WIDTH (f
->display
.x
->font
), f
->display
.x
->line_height
,
4577 f
->display
.x
->background_pixel
);
4578 #endif /* ! defined (HAVE_X11) */
4579 f
->phys_cursor_x
= -1;
4582 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4583 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4587 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4594 CHAR_TO_PIXEL_COL (f
, column
),
4595 CHAR_TO_PIXEL_ROW (f
, row
),
4596 &glyph
, 1, highlight
, 0);
4600 x_display_bar_cursor (f
, on
)
4604 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4606 /* This is pointless on invisible frames, and dangerous on garbaged
4607 frames; in the latter case, the frame may be in the midst of
4608 changing its size, and curs_x and curs_y may be off the frame. */
4609 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4612 if (! on
&& f
->phys_cursor_x
< 0)
4615 /* If we're not updating, then we want to use the current frame's
4616 cursor position, not our local idea of where the cursor ought to be. */
4617 if (f
!= updating_frame
)
4619 curs_x
= FRAME_CURSOR_X (f
);
4620 curs_y
= FRAME_CURSOR_Y (f
);
4623 /* If there is anything wrong with the current cursor state, remove it. */
4624 if (f
->phys_cursor_x
>= 0
4626 || f
->phys_cursor_x
!= curs_x
4627 || f
->phys_cursor_y
!= curs_y
4628 || f
->display
.x
->current_cursor
!= bar_cursor
))
4630 /* Erase the cursor by redrawing the character underneath it. */
4631 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4632 f
->phys_cursor_glyph
,
4633 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4634 f
->phys_cursor_x
= -1;
4637 /* If we now need a cursor in the new place or in the new form, do it so. */
4639 && (f
->phys_cursor_x
< 0
4640 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4642 f
->phys_cursor_glyph
4643 = ((current_glyphs
->enable
[curs_y
]
4644 && curs_x
< current_glyphs
->used
[curs_y
])
4645 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4647 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4648 f
->display
.x
->cursor_gc
,
4649 CHAR_TO_PIXEL_COL (f
, curs_x
),
4650 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4651 1, f
->display
.x
->line_height
);
4653 f
->phys_cursor_x
= curs_x
;
4654 f
->phys_cursor_y
= curs_y
;
4656 f
->display
.x
->current_cursor
= bar_cursor
;
4659 if (updating_frame
!= f
)
4664 /* Turn the displayed cursor of frame F on or off according to ON.
4665 If ON is nonzero, where to put the cursor is specified
4666 by F->cursor_x and F->cursor_y. */
4669 x_display_box_cursor (f
, on
)
4673 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4675 /* This is pointless on invisible frames, and dangerous on garbaged
4676 frames; in the latter case, the frame may be in the midst of
4677 changing its size, and curs_x and curs_y may be off the frame. */
4678 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4681 /* If cursor is off and we want it off, return quickly. */
4682 if (!on
&& f
->phys_cursor_x
< 0)
4685 /* If we're not updating, then we want to use the current frame's
4686 cursor position, not our local idea of where the cursor ought to be. */
4687 if (f
!= updating_frame
)
4689 curs_x
= FRAME_CURSOR_X (f
);
4690 curs_y
= FRAME_CURSOR_Y (f
);
4693 /* If cursor is currently being shown and we don't want it to be
4694 or it is in the wrong place,
4695 or we want a hollow box and it's not so, (pout!)
4697 if (f
->phys_cursor_x
>= 0
4699 || f
->phys_cursor_x
!= curs_x
4700 || f
->phys_cursor_y
!= curs_y
4701 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4702 && (f
!= x_highlight_frame
))))
4704 int mouse_face_here
= 0;
4706 /* If the cursor is in the mouse face area, redisplay that when
4707 we clear the cursor. */
4708 if (f
== mouse_face_mouse_frame
4710 (f
->phys_cursor_y
> mouse_face_beg_row
4711 || (f
->phys_cursor_y
== mouse_face_beg_row
4712 && f
->phys_cursor_x
>= mouse_face_beg_col
))
4714 (f
->phys_cursor_y
< mouse_face_end_row
4715 || (f
->phys_cursor_y
== mouse_face_end_row
4716 && f
->phys_cursor_x
< mouse_face_end_col
)))
4717 mouse_face_here
= 1;
4719 /* If the font is not as tall as a whole line,
4720 we must explicitly clear the line's whole height. */
4721 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4722 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
4723 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4724 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4725 FONT_WIDTH (f
->display
.x
->font
),
4726 f
->display
.x
->line_height
, False
);
4727 /* Erase the cursor by redrawing the character underneath it. */
4728 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4729 f
->phys_cursor_glyph
,
4732 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4733 f
->phys_cursor_x
= -1;
4736 /* If we want to show a cursor,
4737 or we want a box cursor and it's not so,
4738 write it in the right place. */
4740 && (f
->phys_cursor_x
< 0
4741 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4742 && f
== x_highlight_frame
)))
4744 f
->phys_cursor_glyph
4745 = ((current_glyphs
->enable
[curs_y
]
4746 && curs_x
< current_glyphs
->used
[curs_y
])
4747 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4749 if (f
!= x_highlight_frame
)
4752 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4756 x_draw_single_glyph (f
, curs_y
, curs_x
,
4757 f
->phys_cursor_glyph
, 2);
4758 f
->display
.x
->current_cursor
= filled_box_cursor
;
4761 f
->phys_cursor_x
= curs_x
;
4762 f
->phys_cursor_y
= curs_y
;
4765 if (updating_frame
!= f
)
4769 x_display_cursor (f
, on
)
4775 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4776 x_display_box_cursor (f
, on
);
4777 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4778 x_display_bar_cursor (f
, on
);
4780 /* Those are the only two we have implemented! */
4788 /* Refresh bitmap kitchen sink icon for frame F
4789 when we get an expose event for it. */
4795 /* Normally, the window manager handles this function. */
4796 #else /* ! defined (HAVE_X11) */
4799 if (f
->display
.x
->icon_bitmap_flag
)
4800 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
4801 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
4802 icon_bitmap
, GXcopy
, AllPlanes
);
4805 extern struct frame
*selected_frame
;
4806 struct Lisp_String
*str
;
4807 unsigned char *string
;
4810 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
4812 if (f
->display
.x
->icon_label
!= string
)
4814 f
->display
.x
->icon_label
= string
;
4815 XChangeWindow (f
->display
.x
->icon_desc
,
4816 XQueryWidth (string
, icon_font_info
->id
) + 10,
4817 icon_font_info
->height
+ 10);
4820 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4821 str
->size
, icon_font_info
->id
,
4822 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4825 #endif /* ! defined (HAVE_X11) */
4828 /* Make the x-window of frame F use the gnu icon bitmap. */
4837 if (FRAME_X_WINDOW (f
) == 0)
4843 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4844 gnu_bits
, gnu_width
, gnu_height
);
4845 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4846 f
->display
.x
->icon_bitmap_flag
= 1;
4847 #else /* ! defined (HAVE_X11) */
4848 if (f
->display
.x
->icon_desc
)
4850 XClearIconWindow (FRAME_X_WINDOW (f
));
4851 XDestroyWindow (f
->display
.x
->icon_desc
);
4854 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4855 0, 0, sink_width
, sink_height
,
4856 2, WhitePixmap
, (Pixmap
) NULL
);
4858 if (icon_window
== 0)
4861 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4862 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4864 f
->display
.x
->icon_desc
= icon_window
;
4865 f
->display
.x
->icon_bitmap_flag
= 1;
4867 if (icon_bitmap
== 0)
4869 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4870 #endif /* ! defined (HAVE_X11) */
4876 /* Make the x-window of frame F use a rectangle with text. */
4879 x_text_icon (f
, icon_name
)
4887 char *X_DefaultValue
;
4891 #define WhitePixel 1
4892 #endif /* WhitePixel */
4895 #define BlackPixel 0
4896 #endif /* BlackPixel */
4897 #endif /* HAVE_X11 */
4899 if (FRAME_X_WINDOW (f
) == 0)
4904 f
->display
.x
->icon_label
= icon_name
;
4906 if (! f
->display
.x
->icon_label
)
4907 f
->display
.x
->icon_label
= " *emacs* ";
4910 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4911 (char *) f
->display
.x
->icon_label
);
4914 f
->display
.x
->icon_bitmap_flag
= 0;
4915 x_wm_set_icon_pixmap (f
, 0);
4916 #else /* ! defined (HAVE_X11) */
4917 if (icon_font_info
== 0)
4919 = XGetFont (XGetDefault (XDISPLAY
4920 (char *) XSTRING (Vinvocation_name
)->data
,
4923 if (f
->display
.x
->icon_desc
)
4925 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4926 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4930 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4932 if (! f
->display
.x
->icon_label
)
4933 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4935 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4936 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4937 f
->display
.x
->left_pos
,
4938 f
->display
.x
->top_pos
,
4939 width
+ 10, icon_font_info
->height
+ 10,
4940 2, BlackPixmap
, WhitePixmap
);
4942 if (icon_window
== 0)
4945 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4946 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4948 f
->display
.x
->icon_desc
= icon_window
;
4949 f
->display
.x
->icon_bitmap_flag
= 0;
4950 f
->display
.x
->icon_label
= 0;
4951 #endif /* ! defined (HAVE_X11) */
4956 /* Handling X errors. */
4958 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4959 X server's connection, or an error reported via the X protocol. */
4962 x_connection_closed ()
4967 shut_down_emacs (0, 1, Qnil
);
4972 /* An X error handler which prints an error message and then kills
4973 Emacs. This is what's normally installed as Xlib's handler for
4976 x_error_quitter (display
, error
)
4982 /* Note that there is no real way portable across R3/R4 to get the
4983 original error handler. */
4985 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4986 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4987 buf
, error
->request_code
);
4990 /* While we're testing Emacs 19, we'll just dump core whenever we
4991 get an X error, so we can figure out why it happened. */
4995 x_connection_closed ();
4998 /* A handler for X IO errors which prints an error message and then
4999 kills Emacs. This is what is always installed as Xlib's handler
5002 x_io_error_quitter (display
)
5005 fprintf (stderr
, "Connection to X server %s lost.\n",
5006 XDisplayName (DisplayString (display
)));
5009 /* While we're testing Emacs 19, we'll just dump core whenever we
5010 get an X error, so we can figure out why it happened. */
5014 x_connection_closed ();
5017 /* A buffer for storing X error messages. */
5018 static char *x_caught_error_message
;
5019 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
5021 /* An X error handler which stores the error message in
5022 x_caught_error_message. This is what's installed when
5023 x_catch_errors is in effect. */
5025 x_error_catcher (display
, error
)
5029 XGetErrorText (display
, error
->error_code
,
5030 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
5034 /* Begin trapping X errors.
5036 After calling this function, X protocol errors no longer cause
5037 Emacs to exit; instead, they are recorded in x_cfc_error_message.
5039 Calling x_check_errors signals an Emacs error if an X error has
5040 occurred since the last call to x_catch_errors or x_check_errors.
5042 Calling x_uncatch_errors resumes the normal error handling. */
5044 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
5049 /* Make sure any errors from previous requests have been dealt with. */
5050 XSync (x_current_display
, False
);
5052 /* Set up the error buffer. */
5053 x_caught_error_message
5054 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
5055 x_caught_error_message
[0] = '\0';
5057 /* Install our little error handler. */
5058 XHandleError (x_error_catcher
);
5061 /* If any X protocol errors have arrived since the last call to
5062 x_catch_errors or x_check_errors, signal an Emacs error using
5063 sprintf (a buffer, FORMAT, the x error message text) as the text. */
5066 x_check_errors (format
)
5069 /* Make sure to catch any errors incurred so far. */
5070 XSync (x_current_display
, False
);
5072 if (x_caught_error_message
[0])
5074 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
5076 sprintf (buf
, format
, x_caught_error_message
);
5077 x_uncatch_errors ();
5082 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
5087 /* Make sure to catch any errors incurred so far. */
5088 XSync (x_current_display
, False
);
5090 return x_caught_error_message
[0] != 0;
5093 /* Stop catching X protocol errors and let them make Emacs die. */
5098 xfree (x_caught_error_message
);
5099 x_caught_error_message
= 0;
5100 XHandleError (x_error_quitter
);
5104 static unsigned int x_wire_count
;
5107 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5112 /* Changing the font of the frame. */
5114 /* Set the font of the x-window specified by frame F
5115 to the font named NEWNAME. This is safe to use
5116 even before F has an actual x-window. */
5127 /* A table of all the fonts we have already loaded. */
5128 static struct font_info
*x_font_table
;
5130 /* The current capacity of x_font_table. */
5131 static int x_font_table_size
;
5133 /* The number of fonts actually stored in x_font_table.
5134 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
5135 0 <= n_fonts <= x_font_table_size. */
5138 /* Give frame F the font named FONTNAME as its default font, and
5139 return the full name of that font. FONTNAME may be a wildcard
5140 pattern; in that case, we choose some font that fits the pattern.
5141 The return value shows which font we chose. */
5144 x_new_font (f
, fontname
)
5146 register char *fontname
;
5149 int n_matching_fonts
;
5150 XFontStruct
*font_info
;
5153 /* Get a list of all the fonts that match this name. Once we
5154 have a list of matching fonts, we compare them against the fonts
5155 we already have by comparing font ids. */
5156 font_names
= (char **) XListFonts (x_current_display
, fontname
,
5157 1024, &n_matching_fonts
);
5158 /* Apparently it doesn't set n_matching_fonts to zero when it can't
5159 find any matches; font_names == 0 is the only clue. */
5161 n_matching_fonts
= 0;
5163 /* Don't just give up if n_matching_fonts is 0.
5164 Apparently there's a bug on Suns: XListFontsWithInfo can
5165 fail to find a font, but XLoadQueryFont may still find it. */
5167 /* See if we've already loaded a matching font. */
5168 already_loaded
= -1;
5169 if (n_matching_fonts
!= 0)
5173 for (i
= 0; i
< n_fonts
; i
++)
5174 for (j
= 0; j
< n_matching_fonts
; j
++)
5175 if (!strcmp (x_font_table
[i
].name
, font_names
[j
])
5176 || !strcmp (x_font_table
[i
].full_name
, font_names
[j
]))
5179 fontname
= x_font_table
[i
].full_name
;
5185 /* If we have, just return it from the table. */
5186 if (already_loaded
>= 0)
5187 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
5189 /* Otherwise, load the font and add it to the table. */
5196 /* Try to find a character-cell font in the list. */
5198 /* A laudable goal, but this isn't how to do it. */
5199 for (i
= 0; i
< n_matching_fonts
; i
++)
5200 if (! font_info
[i
].per_char
)
5206 /* See comment above. */
5207 if (n_matching_fonts
!= 0)
5208 fontname
= font_names
[i
];
5210 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
5213 /* Free the information from XListFonts. */
5214 if (n_matching_fonts
)
5215 XFreeFontNames (font_names
);
5219 /* Do we need to create the table? */
5220 if (x_font_table_size
== 0)
5222 x_font_table_size
= 16;
5224 = (struct font_info
*) xmalloc (x_font_table_size
5225 * sizeof (x_font_table
[0]));
5227 /* Do we need to grow the table? */
5228 else if (n_fonts
>= x_font_table_size
)
5230 x_font_table_size
*= 2;
5232 = (struct font_info
*) xrealloc (x_font_table
,
5234 * sizeof (x_font_table
[0])));
5237 /* Try to get the full name of FONT. Put it in full_name. */
5239 for (i
= 0; i
< font
->n_properties
; i
++)
5242 = XGetAtomName (x_current_display
, font
->properties
[i
].name
);
5243 if (!strcmp (atom
, "FONT"))
5244 full_name
= XGetAtomName (x_current_display
,
5245 (Atom
) (font
->properties
[i
].card32
));
5249 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
5250 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
5252 x_font_table
[n_fonts
].full_name
= full_name
;
5254 x_font_table
[n_fonts
].full_name
= x_font_table
[n_fonts
].name
;
5255 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
5257 fontname
= full_name
;
5260 /* Now make the frame display the given font. */
5261 if (FRAME_X_WINDOW (f
) != 0)
5263 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
5264 f
->display
.x
->font
->fid
);
5265 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
5266 f
->display
.x
->font
->fid
);
5267 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
5268 f
->display
.x
->font
->fid
);
5270 frame_update_line_height (f
);
5271 x_set_window_size (f
, 0, f
->width
, f
->height
);
5274 /* If we are setting a new frame's font for the first time,
5275 there are no faces yet, so this font's height is the line height. */
5276 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
5279 Lisp_Object lispy_name
;
5281 lispy_name
= build_string (fontname
);
5283 /* Free the information from XListFonts. The data
5284 we actually retain comes from XLoadQueryFont. */
5285 XFreeFontNames (font_names
);
5290 #else /* ! defined (HAVE_X11) */
5291 x_new_font (f
, newname
)
5293 register char *newname
;
5298 temp
= XGetFont (newname
);
5299 if (temp
== (FONT_TYPE
*) 0)
5302 if (f
->display
.x
->font
)
5303 XLoseFont (f
->display
.x
->font
);
5305 f
->display
.x
->font
= temp
;
5307 if (FRAME_X_WINDOW (f
) != 0)
5308 x_set_window_size (f
, 0, f
->width
, f
->height
);
5312 #endif /* ! defined (HAVE_X11) */
5314 x_calc_absolute_position (f
)
5319 int win_x
= 0, win_y
= 0;
5320 int flags
= f
->display
.x
->size_hint_flags
;
5322 /* Find the position of the outside upper-left corner of
5323 the inner window, with respect to the outer window. */
5324 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
5327 XTranslateCoordinates (x_current_display
,
5329 /* From-window, to-window. */
5330 f
->display
.x
->window_desc
,
5331 f
->display
.x
->parent_desc
,
5333 /* From-position, to-position. */
5334 0, 0, &win_x
, &win_y
,
5341 /* Treat negative positions as relative to the leftmost bottommost
5342 position that fits on the screen. */
5343 if (flags
& XNegative
)
5344 f
->display
.x
->left_pos
= (x_screen_width
5345 - 2 * f
->display
.x
->border_width
- win_x
5347 + f
->display
.x
->left_pos
);
5349 if (flags
& YNegative
)
5350 f
->display
.x
->top_pos
= (x_screen_height
5351 - 2 * f
->display
.x
->border_width
- win_y
5353 + f
->display
.x
->top_pos
);
5354 /* The left_pos and top_pos
5355 are now relative to the top and left screen edges,
5356 so the flags should correspond. */
5357 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5358 #else /* ! defined (HAVE_X11) */
5359 WINDOWINFO_TYPE parentinfo
;
5361 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
5363 if (f
->display
.x
->left_pos
< 0)
5364 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
5365 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
5367 if (f
->display
.x
->top_pos
< 0)
5368 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
5369 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
5370 #endif /* ! defined (HAVE_X11) */
5373 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5374 to really change the position, and 0 when calling from
5375 x_make_frame_visible (in that case, XOFF and YOFF are the current
5376 position values). */
5378 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5380 register int xoff
, yoff
;
5385 f
->display
.x
->top_pos
= yoff
;
5386 f
->display
.x
->left_pos
= xoff
;
5387 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5389 f
->display
.x
->size_hint_flags
|= XNegative
;
5391 f
->display
.x
->size_hint_flags
|= YNegative
;
5392 f
->display
.x
->win_gravity
= NorthWestGravity
;
5394 x_calc_absolute_position (f
);
5397 x_wm_set_size_hint (f
, 0, 0);
5399 #ifdef USE_X_TOOLKIT
5400 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
5401 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5402 #else /* not USE_X_TOOLKIT */
5403 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
5404 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5405 #endif /* not USE_X_TOOLKIT */
5409 /* Call this to change the size of frame F's x-window.
5410 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5411 for this size change and subsequent size changes.
5412 Otherwise we leave the window gravity unchanged. */
5414 x_set_window_size (f
, change_gravity
, cols
, rows
)
5419 int pixelwidth
, pixelheight
;
5422 #ifdef USE_X_TOOLKIT
5425 /* The x and y position of the widget is clobbered by the
5426 call to XtSetValues within EmacsFrameSetCharSize.
5427 This is a real kludge, but I don't understand Xt so I can't
5428 figure out a correct fix. Can anyone else tell me? -- rms. */
5429 int xpos
= f
->display
.x
->widget
->core
.x
;
5430 int ypos
= f
->display
.x
->widget
->core
.y
;
5431 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
5432 f
->display
.x
->widget
->core
.x
= xpos
;
5433 f
->display
.x
->widget
->core
.y
= ypos
;
5437 #else /* not USE_X_TOOLKIT */
5441 check_frame_size (f
, &rows
, &cols
);
5442 f
->display
.x
->vertical_scroll_bar_extra
5443 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5444 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
5446 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5447 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5450 f
->display
.x
->win_gravity
= NorthWestGravity
;
5451 x_wm_set_size_hint (f
, 0, 0);
5452 #endif /* ! defined (HAVE_X11) */
5453 XSync (x_current_display
, False
);
5454 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
5456 /* Now, strictly speaking, we can't be sure that this is accurate,
5457 but the window manager will get around to dealing with the size
5458 change request eventually, and we'll hear how it went when the
5459 ConfigureNotify event gets here.
5461 We could just not bother storing any of this information here,
5462 and let the ConfigureNotify event set everything up, but that
5463 might be kind of confusing to the lisp code, since size changes
5464 wouldn't be reported in the frame parameters until some random
5465 point in the future when the ConfigureNotify event arrives. */
5466 change_frame_size (f
, rows
, cols
, 0, 0);
5467 PIXEL_WIDTH (f
) = pixelwidth
;
5468 PIXEL_HEIGHT (f
) = pixelheight
;
5470 /* If cursor was outside the new size, mark it as off. */
5471 if (f
->phys_cursor_y
>= rows
5472 || f
->phys_cursor_x
>= cols
)
5474 f
->phys_cursor_x
= -1;
5475 f
->phys_cursor_y
= -1;
5478 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5479 receive in the ConfigureNotify event; if we get what we asked
5480 for, then the event won't cause the screen to become garbaged, so
5481 we have to make sure to do it here. */
5482 SET_FRAME_GARBAGED (f
);
5486 #endif /* not USE_X_TOOLKIT */
5490 x_set_resize_hint (f
)
5493 XSetResizeHint (FRAME_X_WINDOW (f
),
5494 2 * f
->display
.x
->internal_border_width
,
5495 2 * f
->display
.x
->internal_border_width
,
5496 FONT_WIDTH (f
->display
.x
->font
),
5497 f
->display
.x
->line_height
);
5499 #endif /* HAVE_X11 */
5501 /* Mouse warping, focus shifting, raising and lowering. */
5504 x_set_mouse_position (f
, x
, y
)
5510 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
5511 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
5513 if (pix_x
< 0) pix_x
= 0;
5514 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5516 if (pix_y
< 0) pix_y
= 0;
5517 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5521 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5525 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5528 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5534 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5539 x_focus_on_frame (f
)
5542 #if 0 /* This proves to be unpleasant. */
5546 /* I don't think that the ICCCM allows programs to do things like this
5547 without the interaction of the window manager. Whatever you end up
5548 doing with this code, do it to x_unfocus_frame too. */
5549 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
5550 RevertToPointerRoot
, CurrentTime
);
5558 /* Look at the remarks in x_focus_on_frame. */
5559 if (x_focus_frame
== f
)
5560 XSetInputFocus (x_current_display
, PointerRoot
,
5561 RevertToPointerRoot
, CurrentTime
);
5565 #endif /* ! defined (HAVE_X11) */
5567 /* Raise frame F. */
5572 if (f
->async_visible
)
5575 #ifdef USE_X_TOOLKIT
5576 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5577 #else /* not USE_X_TOOLKIT */
5578 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5579 #endif /* not USE_X_TOOLKIT */
5585 /* Lower frame F. */
5590 if (f
->async_visible
)
5593 #ifdef USE_X_TOOLKIT
5594 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5595 #else /* not USE_X_TOOLKIT */
5596 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5597 #endif /* not USE_X_TOOLKIT */
5604 XTframe_raise_lower (f
, raise
)
5615 /* Change from withdrawn state to mapped state,
5618 x_make_frame_visible (f
)
5625 if (! FRAME_VISIBLE_P (f
))
5628 #ifndef USE_X_TOOLKIT
5629 if (! FRAME_ICONIFIED_P (f
))
5630 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5633 if (! EQ (Vx_no_window_manager
, Qt
))
5634 x_wm_set_window_state (f
, NormalState
);
5635 #ifdef USE_X_TOOLKIT
5636 /* This was XtPopup, but that did nothing for an iconified frame. */
5637 XtMapWidget (f
->display
.x
->widget
);
5638 #else /* not USE_X_TOOLKIT */
5639 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5640 #endif /* not USE_X_TOOLKIT */
5641 #if 0 /* This seems to bring back scroll bars in the wrong places
5642 if the window configuration has changed. They seem
5643 to come back ok without this. */
5644 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5645 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5647 #else /* ! defined (HAVE_X11) */
5648 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5649 if (f
->display
.x
->icon_desc
!= 0)
5650 XUnmapWindow (f
->display
.x
->icon_desc
);
5652 /* Handled by the MapNotify event for X11 */
5653 f
->async_visible
= 1;
5654 f
->async_iconified
= 0;
5656 /* NOTE: this may cause problems for the first frame. */
5658 #endif /* ! defined (HAVE_X11) */
5665 /* Synchronize to ensure Emacs knows the frame is visible
5666 before we do anything else. We do this loop with input not blocked
5667 so that incoming events are handled. */
5670 int one_in_four
= 1;
5671 XSET (frame
, Lisp_Frame
, f
);
5672 while (! f
->async_visible
)
5675 /* On HPUX on the HP800, the sleep is needed sometimes. */
5676 if ((one_in_four
& 3) == 0)
5678 #ifdef EMACS_HAS_USECS
5679 Fsleep_for (make_number (1), make_number (0));
5681 Fsleep_for (make_number (0), make_number (250));
5686 FRAME_SAMPLE_VISIBILITY (f
);
5690 /* Change from mapped state to withdrawn state. */
5692 x_make_frame_invisible (f
)
5698 #ifdef USE_X_TOOLKIT
5699 /* Use the frame's outermost window, not the one we normally draw on. */
5700 window
= XtWindow (f
->display
.x
->widget
);
5701 #else /* not USE_X_TOOLKIT */
5702 window
= FRAME_X_WINDOW (f
);
5703 #endif /* not USE_X_TOOLKIT */
5705 /* Don't keep the highlight on an invisible frame. */
5706 if (x_highlight_frame
== f
)
5707 x_highlight_frame
= 0;
5709 #if 0/* This might add unreliability; I don't trust it -- rms. */
5710 if (! f
->async_visible
&& ! f
->async_iconified
)
5716 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5717 that the current position of the window is user-specified, rather than
5718 program-specified, so that when the window is mapped again, it will be
5719 placed at the same location, without forcing the user to position it
5720 by hand again (they have already done that once for this window.) */
5721 x_wm_set_size_hint (f
, 0, 1);
5725 if (! XWithdrawWindow (x_current_display
, window
,
5726 DefaultScreen (x_current_display
)))
5728 UNBLOCK_INPUT_RESIGNAL
;
5729 error ("Can't notify window manager of window withdrawal");
5731 #else /* ! defined (HAVE_X11R4) */
5734 /* Tell the window manager what we're going to do. */
5735 if (! EQ (Vx_no_window_manager
, Qt
))
5739 unmap
.xunmap
.type
= UnmapNotify
;
5740 unmap
.xunmap
.window
= window
;
5741 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5742 unmap
.xunmap
.from_configure
= False
;
5743 if (! XSendEvent (x_current_display
,
5744 DefaultRootWindow (x_current_display
),
5746 SubstructureRedirectMask
|SubstructureNotifyMask
,
5749 UNBLOCK_INPUT_RESIGNAL
;
5750 error ("Can't notify window manager of withdrawal");
5754 /* Unmap the window ourselves. Cheeky! */
5755 XUnmapWindow (x_current_display
, window
);
5756 #else /* ! defined (HAVE_X11) */
5758 XUnmapWindow (FRAME_X_WINDOW (f
));
5759 if (f
->display
.x
->icon_desc
!= 0)
5760 XUnmapWindow (f
->display
.x
->icon_desc
);
5762 #endif /* ! defined (HAVE_X11) */
5763 #endif /* ! defined (HAVE_X11R4) */
5765 /* We can't distinguish this from iconification
5766 just by the event that we get from the server.
5767 So we can't win using the usual strategy of letting
5768 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5769 and synchronize with the server to make sure we agree. */
5771 FRAME_ICONIFIED_P (f
) = 0;
5772 f
->async_visible
= 0;
5773 f
->async_iconified
= 0;
5780 /* Change window state from mapped to iconified. */
5788 /* Don't keep the highlight on an invisible frame. */
5789 if (x_highlight_frame
== f
)
5790 x_highlight_frame
= 0;
5792 if (f
->async_iconified
)
5795 #ifdef USE_X_TOOLKIT
5798 if (! FRAME_VISIBLE_P (f
))
5800 if (! EQ (Vx_no_window_manager
, Qt
))
5801 x_wm_set_window_state (f
, IconicState
);
5802 /* This was XtPopup, but that did nothing for an iconified frame. */
5803 XtMapWidget (f
->display
.x
->widget
);
5808 result
= XIconifyWindow (x_current_display
,
5809 XtWindow (f
->display
.x
->widget
),
5810 DefaultScreen (x_current_display
));
5814 error ("Can't notify window manager of iconification");
5816 f
->async_iconified
= 1;
5821 #else /* not USE_X_TOOLKIT */
5826 /* Make sure the X server knows where the window should be positioned,
5827 in case the user deiconifies with the window manager. */
5828 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5829 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5831 /* Since we don't know which revision of X we're running, we'll use both
5832 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5834 /* X11R4: send a ClientMessage to the window manager using the
5835 WM_CHANGE_STATE type. */
5839 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5840 message
.xclient
.type
= ClientMessage
;
5841 message
.xclient
.message_type
= Xatom_wm_change_state
;
5842 message
.xclient
.format
= 32;
5843 message
.xclient
.data
.l
[0] = IconicState
;
5845 if (! XSendEvent (x_current_display
,
5846 DefaultRootWindow (x_current_display
),
5848 SubstructureRedirectMask
| SubstructureNotifyMask
,
5851 UNBLOCK_INPUT_RESIGNAL
;
5852 error ("Can't notify window manager of iconification");
5856 /* X11R3: set the initial_state field of the window manager hints to
5858 x_wm_set_window_state (f
, IconicState
);
5860 if (!FRAME_VISIBLE_P (f
))
5862 /* If the frame was withdrawn, before, we must map it. */
5863 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5864 #if 0 /* We don't have subwindows in the icon. */
5865 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5866 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5870 f
->async_iconified
= 1;
5871 #else /* ! defined (HAVE_X11) */
5872 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5874 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
5875 if (f
->display
.x
->icon_desc
!= 0)
5877 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
5880 #endif /* ! defined (HAVE_X11) */
5884 #endif /* not USE_X_TOOLKIT */
5887 /* Destroy the X window of frame F. */
5889 x_destroy_window (f
)
5894 if (f
->display
.x
->icon_desc
!= 0)
5895 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5896 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5897 #ifdef USE_X_TOOLKIT
5898 XtDestroyWidget (f
->display
.x
->widget
);
5899 free_frame_menubar (f
);
5900 #endif /* USE_X_TOOLKIT */
5902 free_frame_faces (f
);
5905 xfree (f
->display
.x
);
5907 if (f
== x_focus_frame
)
5909 if (f
== x_highlight_frame
)
5910 x_highlight_frame
= 0;
5912 if (f
== mouse_face_mouse_frame
)
5914 mouse_face_beg_row
= mouse_face_beg_col
= -1;
5915 mouse_face_end_row
= mouse_face_end_col
= -1;
5916 mouse_face_window
= Qnil
;
5922 /* Manage event queues for X10. */
5926 /* Manage event queues.
5928 This code is only used by the X10 support.
5930 We cannot leave events in the X queue and get them when we are ready
5931 because X does not provide a subroutine to get only a certain kind
5932 of event but not block if there are no queued events of that kind.
5934 Therefore, we must examine events as they come in and copy events
5935 of certain kinds into our private queues.
5937 All ExposeRegion events are put in x_expose_queue.
5938 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5941 /* Write the event *P_XREP into the event queue *QUEUE.
5942 If the queue is full, do nothing, but return nonzero. */
5945 enqueue_event (p_xrep
, queue
)
5946 register XEvent
*p_xrep
;
5947 register struct event_queue
*queue
;
5949 int newindex
= queue
->windex
+ 1;
5950 if (newindex
== EVENT_BUFFER_SIZE
)
5952 if (newindex
== queue
->rindex
)
5954 queue
->xrep
[queue
->windex
] = *p_xrep
;
5955 queue
->windex
= newindex
;
5959 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5960 If *QUEUE is empty, do nothing and return 0. */
5963 dequeue_event (p_xrep
, queue
)
5964 register XEvent
*p_xrep
;
5965 register struct event_queue
*queue
;
5967 if (queue
->windex
== queue
->rindex
)
5969 *p_xrep
= queue
->xrep
[queue
->rindex
++];
5970 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
5975 /* Return the number of events buffered in *QUEUE. */
5978 queue_event_count (queue
)
5979 register struct event_queue
*queue
;
5981 int tem
= queue
->windex
- queue
->rindex
;
5984 return EVENT_BUFFER_SIZE
+ tem
;
5987 /* Return nonzero if mouse input is pending. */
5990 mouse_event_pending_p ()
5992 return queue_event_count (&x_mouse_queue
);
5994 #endif /* HAVE_X11 */
5996 /* Setting window manager hints. */
6000 /* Set the normal size hints for the window manager, for frame F.
6001 FLAGS is the flags word to use--or 0 meaning preserve the flags
6002 that the window now has.
6003 If USER_POSITION is nonzero, we set the USPosition
6004 flag (this is useful when FLAGS is 0). */
6006 x_wm_set_size_hint (f
, flags
, user_position
)
6011 XSizeHints size_hints
;
6013 #ifdef USE_X_TOOLKIT
6016 Dimension widget_width
, widget_height
;
6017 Window window
= XtWindow (f
->display
.x
->widget
);
6018 #else /* not USE_X_TOOLKIT */
6019 Window window
= FRAME_X_WINDOW (f
);
6020 #endif /* not USE_X_TOOLKIT */
6022 /* Setting PMaxSize caused various problems. */
6023 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
6025 flexlines
= f
->height
;
6027 size_hints
.x
= f
->display
.x
->left_pos
;
6028 size_hints
.y
= f
->display
.x
->top_pos
;
6030 #ifdef USE_X_TOOLKIT
6031 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
6032 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
6033 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
6034 size_hints
.height
= widget_height
;
6035 size_hints
.width
= widget_width
;
6036 #else /* not USE_X_TOOLKIT */
6037 size_hints
.height
= PIXEL_HEIGHT (f
);
6038 size_hints
.width
= PIXEL_WIDTH (f
);
6039 #endif /* not USE_X_TOOLKIT */
6041 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
6042 size_hints
.height_inc
= f
->display
.x
->line_height
;
6043 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
6044 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
6047 int base_width
, base_height
;
6048 int min_rows
= 0, min_cols
= 0;
6050 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
6051 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
6053 check_frame_size (f
, &min_rows
, &min_cols
);
6055 /* The window manager uses the base width hints to calculate the
6056 current number of rows and columns in the frame while
6057 resizing; min_width and min_height aren't useful for this
6058 purpose, since they might not give the dimensions for a
6059 zero-row, zero-column frame.
6061 We use the base_width and base_height members if we have
6062 them; otherwise, we set the min_width and min_height members
6063 to the size for a zero x zero frame. */
6066 size_hints
.flags
|= PBaseSize
;
6067 size_hints
.base_width
= base_width
;
6068 size_hints
.base_height
= base_height
;
6069 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
6070 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
6072 size_hints
.min_width
= base_width
;
6073 size_hints
.min_height
= base_height
;
6078 size_hints
.flags
|= flags
;
6081 XSizeHints hints
; /* Sometimes I hate X Windows... */
6082 long supplied_return
;
6086 value
= XGetWMNormalHints (x_current_display
, window
, &hints
,
6089 value
= XGetNormalHints (x_current_display
, window
, &hints
);
6094 if (hints
.flags
& PSize
)
6095 size_hints
.flags
|= PSize
;
6096 if (hints
.flags
& PPosition
)
6097 size_hints
.flags
|= PPosition
;
6098 if (hints
.flags
& USPosition
)
6099 size_hints
.flags
|= USPosition
;
6100 if (hints
.flags
& USSize
)
6101 size_hints
.flags
|= USSize
;
6105 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
6106 size_hints
.flags
|= PWinGravity
;
6110 size_hints
.flags
&= ~ PPosition
;
6111 size_hints
.flags
|= USPosition
;
6113 #endif /* PWinGravity */
6116 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
6118 XSetNormalHints (x_current_display
, window
, &size_hints
);
6122 /* Used for IconicState or NormalState */
6123 x_wm_set_window_state (f
, state
)
6127 #ifdef USE_X_TOOLKIT
6130 XtSetArg (al
[0], XtNinitialState
, state
);
6131 XtSetValues (f
->display
.x
->widget
, al
, 1);
6132 #else /* not USE_X_TOOLKIT */
6133 Window window
= FRAME_X_WINDOW (f
);
6135 f
->display
.x
->wm_hints
.flags
|= StateHint
;
6136 f
->display
.x
->wm_hints
.initial_state
= state
;
6138 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6139 #endif /* not USE_X_TOOLKIT */
6142 x_wm_set_icon_pixmap (f
, icon_pixmap
)
6146 #ifdef USE_X_TOOLKIT
6147 Window window
= XtWindow (f
->display
.x
->widget
);
6149 Window window
= FRAME_X_WINDOW (f
);
6154 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6155 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
6158 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
6160 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6163 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6167 #ifdef USE_X_TOOLKIT
6168 Window window
= XtWindow (f
->display
.x
->widget
);
6170 Window window
= FRAME_X_WINDOW (f
);
6173 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
6174 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
6175 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
6177 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6181 /* Initialization. */
6183 #ifdef USE_X_TOOLKIT
6184 static XrmOptionDescRec emacs_options
[] = {
6185 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6186 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6188 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6189 XrmoptionSepArg
, NULL
},
6190 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6192 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6193 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6194 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6195 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6196 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6197 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6198 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6200 #endif /* USE_X_TOOLKIT */
6203 x_term_init (display_name
, xrm_option
, resource_name
)
6206 char *resource_name
;
6212 #ifndef F_SETOWN_BUG
6214 extern int old_fcntl_owner
;
6215 #endif /* ! defined (F_SETOWN) */
6216 #endif /* F_SETOWN_BUG */
6220 x_focus_frame
= x_highlight_frame
= 0;
6222 #ifdef USE_X_TOOLKIT
6223 argv
= (char **) XtMalloc (7 * sizeof (char *));
6225 argv
[1] = "-display";
6226 argv
[2] = display_name
;
6228 /* Usually `emacs', but not always. */
6229 argv
[4] = resource_name
;
6233 argv
[argc
++] = "-xrm";
6234 argv
[argc
++] = xrm_option
;
6236 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
6237 emacs_options
, XtNumber (emacs_options
),
6240 XtFree ((char *)argv
);
6241 x_current_display
= XtDisplay (Xt_app_shell
);
6243 #else /* not USE_X_TOOLKIT */
6244 x_current_display
= XOpenDisplay (display_name
);
6245 #endif /* not USE_X_TOOLKIT */
6246 if (x_current_display
== 0)
6247 fatal ("X server %s not responding.\n\
6248 Check the DISPLAY environment variable or use \"-d\"\n",
6254 XSetAfterFunction (x_current_display
, x_trace_wire
);
6256 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
6257 + XSTRING (Vsystem_name
)->size
6259 sprintf (x_id_name
, "%s@%s",
6260 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
6263 /* Figure out which modifier bits mean what. */
6264 x_find_modifier_meanings ();
6266 /* Get the scroll bar cursor. */
6267 x_vertical_scroll_bar_cursor
6268 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
6271 /* Watch for PropertyNotify events on the root window; we use them
6272 to figure out when to invalidate our cache of the cut buffers. */
6273 x_watch_cut_buffer_cache ();
6276 if (ConnectionNumber (x_current_display
) != 0)
6277 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
6278 change_input_fd (ConnectionNumber (x_current_display
));
6280 #endif /* ! defined (HAVE_X11) */
6282 #ifndef F_SETOWN_BUG
6284 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
6285 #ifdef F_SETOWN_SOCK_NEG
6286 /* stdin is a socket here */
6287 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
6288 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6289 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
6290 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6291 #endif /* ! defined (F_SETOWN) */
6292 #endif /* F_SETOWN_BUG */
6296 #endif /* ! defined (SIGIO) */
6298 expose_all_windows
= 0;
6300 clear_frame_hook
= XTclear_frame
;
6301 clear_end_of_line_hook
= XTclear_end_of_line
;
6302 ins_del_lines_hook
= XTins_del_lines
;
6303 change_line_highlight_hook
= XTchange_line_highlight
;
6304 insert_glyphs_hook
= XTinsert_glyphs
;
6305 write_glyphs_hook
= XTwrite_glyphs
;
6306 delete_glyphs_hook
= XTdelete_glyphs
;
6307 ring_bell_hook
= XTring_bell
;
6308 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6309 set_terminal_modes_hook
= XTset_terminal_modes
;
6310 update_begin_hook
= XTupdate_begin
;
6311 update_end_hook
= XTupdate_end
;
6312 set_terminal_window_hook
= XTset_terminal_window
;
6313 read_socket_hook
= XTread_socket
;
6314 frame_up_to_date_hook
= XTframe_up_to_date
;
6315 cursor_to_hook
= XTcursor_to
;
6316 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6317 mouse_position_hook
= XTmouse_position
;
6318 frame_rehighlight_hook
= XTframe_rehighlight
;
6319 frame_raise_lower_hook
= XTframe_raise_lower
;
6320 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6321 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6322 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6323 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6325 scroll_region_ok
= 1; /* we'll scroll partial frames */
6326 char_ins_del_ok
= 0; /* just as fast to write the line */
6327 line_ins_del_ok
= 1; /* we'll just blt 'em */
6328 fast_clear_end_of_line
= 1; /* X does this well */
6329 memory_below_frame
= 0; /* we don't remember what scrolls
6333 /* Try to use interrupt input; if we can't, then start polling. */
6334 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6336 /* Note that there is no real way portable across R3/R4 to get the
6337 original error handler. */
6338 XHandleError (x_error_quitter
);
6339 XHandleIOError (x_io_error_quitter
);
6341 /* Disable Window Change signals; they are handled by X events. */
6343 signal (SIGWINCH
, SIG_DFL
);
6344 #endif /* ! defined (SIGWINCH) */
6346 signal (SIGPIPE
, x_connection_closed
);
6352 staticpro (&last_mouse_scroll_bar
);
6353 last_mouse_scroll_bar
= Qnil
;
6354 staticpro (&mouse_face_window
);
6355 mouse_face_window
= Qnil
;
6357 #endif /* ! defined (HAVE_X11) */
6358 #endif /* ! defined (HAVE_X_WINDOWS) */