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. */
30 /* Need syssignal.h for various externs and definitions that may be required
31 by some configurations for calls to signal later in this source file. */
32 #include "syssignal.h"
37 #include "blockinput.h"
39 /* This may include sys/types.h, and that somehow loses
40 if this is not done before the other system files. */
42 #include <X11/cursorfont.h>
45 /* Load sys/types.h if not already loaded.
46 In some systems loading it twice is suicidal. */
48 #include <sys/types.h>
53 #include <sys/ioctl.h>
55 #else /* ! defined (BSD) */
59 #endif /* ! defined (BSD) */
64 #ifndef INCLUDED_FCNTL
71 #include <sys/param.h>
73 #include "dispextern.h"
74 #include "termhooks.h"
88 extern XtAppContext Xt_app_con
;
89 extern Widget Xt_app_shell
;
90 extern void free_frame_menubar ();
91 extern void _XEditResCheckMessages ();
92 #endif /* USE_X_TOOLKIT */
95 #define x_any_window_to_frame x_window_to_frame
96 #define x_top_window_to_frame x_window_to_frame
100 #ifndef XtNinitialState
101 #define XtNinitialState "initialState"
106 #define XMapWindow XMapRaised /* Raise them when mapping. */
107 #else /* ! defined (HAVE_X11) */
108 #include <X/Xkeyboard.h>
109 /*#include <X/Xproto.h> */
110 #endif /* ! defined (HAVE_X11) */
113 /* We could get this from param.h, but better not to depend on finding that.
114 And better not to risk that it might define other symbols used in this
117 #define MAXDESC FD_SETSIZE
121 #define SELECT_TYPE fd_set
122 #else /* no FD_SET */
124 #define SELECT_TYPE int
126 /* Define the macros to access a single-int bitmap of descriptors. */
127 #define FD_SET(n, p) (*(p) |= (1 << (n)))
128 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
129 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
130 #define FD_ZERO(p) (*(p) = 0)
131 #endif /* no FD_SET */
133 /* For sending Meta-characters. Do we need this? */
136 #define min(a,b) ((a)<(b) ? (a) : (b))
137 #define max(a,b) ((a)>(b) ? (a) : (b))
139 /* Nonzero means we must reprint all windows
140 because 1) we received an ExposeWindow event
141 or 2) we received too many ExposeRegion events to record.
143 This is never needed under X11. */
144 static int expose_all_windows
;
146 /* Nonzero means we must reprint all icon windows. */
148 static int expose_all_icons
;
151 /* ExposeRegion events, when received, are copied into this queue
152 for later processing. */
154 static struct event_queue x_expose_queue
;
156 /* ButtonPress and ButtonReleased events, when received,
157 are copied into this queue for later processing. */
159 struct event_queue x_mouse_queue
;
160 #endif /* HAVE_X11 */
162 #if defined (SIGIO) && defined (FIONREAD)
163 int BLOCK_INPUT_mask
;
164 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
166 /* The id of a bitmap used for icon windows.
167 One such map is shared by all Emacs icon windows.
168 This is zero if we have not yet had a need to create the bitmap. */
170 static Bitmap icon_bitmap
;
172 /* Font used for text icons. */
174 static FONT_TYPE
*icon_font_info
;
176 /* Stuff for dealing with the main icon title. */
178 extern Lisp_Object Vcommand_line_args
;
179 char *hostname
, *x_id_name
;
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. */
239 In order to avoid asking for motion events and then throwing most
240 of them away or busy-polling the server for mouse positions, we ask
241 the server for pointer motion hints. This means that we get only
242 one event per group of mouse movements. "Groups" are delimited by
243 other kinds of events (focus changes and button clicks, for
244 example), or by XQueryPointer calls; when one of these happens, we
245 get another MotionNotify event the next time the mouse moves. This
246 is at least as efficient as getting motion events when mouse
247 tracking is on, and I suspect only negligibly worse when tracking
250 The silly O'Reilly & Associates Nutshell guides barely document
251 pointer motion hints at all (I think you have to infer how they
252 work from an example), and the description of XQueryPointer doesn't
253 mention that calling it causes you to get another motion hint from
254 the server, which is very important. */
256 /* Where the mouse was last time we reported a mouse event. */
257 static FRAME_PTR last_mouse_frame
;
258 static XRectangle last_mouse_glyph
;
260 /* The scroll bar in which the last X motion event occurred.
262 If the last X motion event occurred in a scroll bar, we set this
263 so XTmouse_position can know whether to report a scroll bar motion or
266 If the last X motion event didn't occur in a scroll bar, we set this
267 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
268 static Lisp_Object last_mouse_scroll_bar
;
270 /* Record which buttons are currently pressed. */
271 unsigned int x_mouse_grabbed
;
273 /* This is a hack. We would really prefer that XTmouse_position would
274 return the time associated with the position it returns, but there
275 doesn't seem to be any way to wrest the timestamp from the server
276 along with the position query. So, we just keep track of the time
277 of the last movement we received, and return that in hopes that
278 it's somewhat accurate. */
279 static Time last_mouse_movement_time
;
281 /* These variables describe the range of text currently shown
282 in its mouse-face, together with the window they apply to.
283 As long as the mouse stays within this range, we need not
284 redraw anything on its account. */
285 static int mouse_face_beg_row
, mouse_face_beg_col
;
286 static int mouse_face_end_row
, mouse_face_end_col
;
287 static int mouse_face_past_end
;
288 static Lisp_Object mouse_face_window
;
289 static int mouse_face_face_id
;
291 /* 1 if a mouse motion event came and we didn't handle it right away because
292 gc was in progress. */
293 static int mouse_face_deferred_gc
;
295 /* FRAME and X, Y position of mouse when last checked for
296 highlighting. X and Y can be negative or out of range for the frame. */
297 static FRAME_PTR mouse_face_mouse_frame
;
298 static int mouse_face_mouse_x
, mouse_face_mouse_y
;
300 /* Nonzero means defer mouse-motion highlighting. */
301 static int mouse_face_defer
;
304 /* `t' if a mouse button is depressed. */
306 extern Lisp_Object Vmouse_depressed
;
308 /* Tells if a window manager is present or not. */
310 extern Lisp_Object Vx_no_window_manager
;
312 /* Timestamp that we requested selection data was made. */
313 extern Time requestor_time
;
315 /* ID of the window requesting selection data. */
316 extern Window requestor_window
;
318 /* Nonzero enables some debugging for the X interface code. */
321 extern Lisp_Object Qface
, Qmouse_face
;
323 #else /* ! defined (HAVE_X11) */
325 /* Bit patterns for the mouse cursor. */
327 short MouseCursor
[] = {
328 0x0000, 0x0008, 0x0018, 0x0038,
329 0x0078, 0x00f8, 0x01f8, 0x03f8,
330 0x07f8, 0x00f8, 0x00d8, 0x0188,
331 0x0180, 0x0300, 0x0300, 0x0000};
333 short MouseMask
[] = {
334 0x000c, 0x001c, 0x003c, 0x007c,
335 0x00fc, 0x01fc, 0x03fc, 0x07fc,
336 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
337 0x03cc, 0x0780, 0x0780, 0x0300};
339 static short grey_bits
[] = {
340 0x0005, 0x000a, 0x0005, 0x000a};
342 static Pixmap GreyPixmap
= 0;
343 #endif /* ! defined (HAVE_X11) */
345 /* From time to time we get info on an Emacs window, here. */
347 static WINDOWINFO_TYPE windowinfo
;
351 /* A mask of extra modifier bits to put into every keyboard char. */
352 extern int extra_keyboard_modifiers
;
354 extern Display
*XOpenDisplay ();
355 extern Window
XCreateWindow ();
357 extern Cursor
XCreateCursor ();
358 extern FONT_TYPE
*XOpenFont ();
360 static void flashback ();
361 static void redraw_previous_char ();
362 static void redraw_following_char ();
363 static unsigned int x_x_to_emacs_modifiers ();
365 static int fast_find_position ();
366 static void note_mouse_highlight ();
367 static void clear_mouse_face ();
368 static void show_mouse_face ();
371 static void dumpqueue ();
372 #endif /* HAVE_X11 */
375 static int XTcursor_to ();
376 static int XTclear_end_of_line ();
379 /* Starting and ending updates.
381 These hooks are called by update_frame at the beginning and end
382 of a frame update. We record in `updating_frame' the identity
383 of the frame being updated, so that the XT... functions do not
384 need to take a frame as argument. Most of the XT... functions
385 should never be called except during an update, the only exceptions
386 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
388 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
399 flexlines
= f
->height
;
404 if (f
== mouse_face_mouse_frame
)
406 /* Don't do highlighting for mouse motion during the update. */
407 mouse_face_defer
= 1;
408 if (!NILP (mouse_face_window
))
410 int firstline
, lastline
, i
;
411 struct window
*w
= XWINDOW (mouse_face_window
);
413 /* Find the first, and the last+1, lines affected by redisplay. */
414 for (firstline
= 0; firstline
< f
->height
; firstline
++)
415 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
418 lastline
= f
->height
;
419 for (i
= f
->height
- 1; i
>= 0; i
--)
421 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
427 /* Can we tell that this update does not affect the window
428 where the mouse highlight is? If so, no need to turn off. */
429 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
430 || lastline
< XFASTINT (w
->top
)))
431 /* Otherwise turn off the mouse highlight now. */
437 #endif /* HAVE_X11 */
442 static void x_do_pending_expose ();
454 x_do_pending_expose ();
455 #endif /* HAVE_X11 */
457 x_display_cursor (f
, 1);
459 if (f
== mouse_face_mouse_frame
)
460 mouse_face_defer
= 0;
462 /* This fails in the case of having updated only the echo area
463 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
464 has no relation to the current contents, and its charstarts
465 have no relation to the contents of the window-buffer.
466 I don't know a clean way to check
467 for that case. window_end_valid isn't set up yet. */
468 if (f
== mouse_face_mouse_frame
)
469 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
476 /* This is called after a redisplay on frame F. */
479 XTframe_up_to_date (f
)
482 if (mouse_face_deferred_gc
|| f
== mouse_face_mouse_frame
)
484 note_mouse_highlight (mouse_face_mouse_frame
,
485 mouse_face_mouse_x
, mouse_face_mouse_y
);
486 mouse_face_deferred_gc
= 0;
490 /* External interface to control of standout mode.
491 Call this when about to modify line at position VPOS
492 and not change whether it is highlighted. */
494 XTreassert_line_highlight (new, vpos
)
500 /* Call this when about to modify line at position VPOS
501 and change whether it is highlighted. */
504 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
505 int new_highlight
, vpos
, first_unused_hpos
;
507 highlight
= new_highlight
;
508 XTcursor_to (vpos
, 0);
509 XTclear_end_of_line (updating_frame
->width
);
512 /* This is used when starting Emacs and when restarting after suspend.
513 When starting Emacs, no X window is mapped. And nothing must be done
514 to Emacs's own window if it is suspended (though that rarely happens). */
517 XTset_terminal_modes ()
521 /* This is called when exiting or suspending Emacs.
522 Exiting will make the X-windows go away, and suspending
523 requires no action. */
526 XTreset_terminal_modes ()
528 /* XTclear_frame (); */
531 /* Set the nominal cursor position of the frame.
532 This is where display update commands will take effect.
533 This does not affect the place where the cursor-box is displayed. */
536 XTcursor_to (row
, col
)
537 register int row
, col
;
545 if (updating_frame
== 0)
548 x_display_cursor (selected_frame
, 1);
554 /* Display a sequence of N glyphs found at GP.
555 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
556 HL is 1 if this text is highlighted, 2 if the cursor is on it,
557 3 if should appear in its mouse-face.
558 JUST_FOREGROUND if 1 means draw only the foreground;
559 don't alter the background.
561 FONT is the default font to use (for glyphs whose font-code is 0).
563 Since the display generation code is responsible for calling
564 compute_char_face and compute_glyph_face on everything it puts in
565 the display structure, we can assume that the face code on each
566 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
567 to which we can actually apply intern_face.
568 Call this function with input blocked. */
571 /* This is the multi-face code. */
574 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
577 register GLYPH
*gp
; /* Points to first GLYPH. */
578 register int n
; /* Number of glyphs to display. */
582 /* Holds characters to be displayed. */
583 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
584 register char *cp
; /* Steps through buf[]. */
585 register int tlen
= GLYPH_TABLE_LENGTH
;
586 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
587 Window window
= FRAME_X_WINDOW (f
);
588 int orig_left
= left
;
592 /* Get the face-code of the next GLYPH. */
596 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
597 cf
= FAST_GLYPH_FACE (g
);
599 /* Find the run of consecutive glyphs with the same face-code.
600 Extract their character codes into BUF. */
605 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
606 if (FAST_GLYPH_FACE (g
) != cf
)
609 *cp
++ = FAST_GLYPH_CHAR (g
);
614 /* LEN gets the length of the run. */
617 /* Now output this run of chars, with the font and pixel values
618 determined by the face code CF. */
620 struct face
*face
= FRAME_DEFAULT_FACE (f
);
621 FONT_TYPE
*font
= FACE_FONT (face
);
622 GC gc
= FACE_GC (face
);
623 int gc_temporary
= 0;
625 /* HL = 3 means use a mouse face previously chosen. */
627 cf
= mouse_face_face_id
;
629 /* First look at the face of the text itself. */
632 /* It's possible for the display table to specify
633 a face code that is out of range. Use 0 in that case. */
634 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
635 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
639 face
= FRAME_MODE_LINE_FACE (f
);
641 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
642 font
= FACE_FONT (face
);
646 /* Then comes the distinction between modeline and normal text. */
651 face
= FRAME_MODE_LINE_FACE (f
);
652 font
= FACE_FONT (face
);
656 #define FACE_DEFAULT (~0)
658 /* Now override that if the cursor's on this character. */
662 || (int) face
->font
== FACE_DEFAULT
)
664 gc
= f
->display
.x
->cursor_gc
;
666 /* Cursor on non-default face: must merge. */
672 xgcv
.background
= f
->display
.x
->cursor_pixel
;
673 if (face
== FRAME_DEFAULT_FACE (f
))
674 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
676 xgcv
.foreground
= face
->background
;
677 /* If the glyph would be invisible,
678 try a different foreground. */
679 if (xgcv
.foreground
== xgcv
.background
)
680 xgcv
.foreground
= face
->foreground
;
681 if (xgcv
.foreground
== xgcv
.background
)
682 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
683 if (xgcv
.foreground
== xgcv
.background
)
684 xgcv
.foreground
= face
->foreground
;
685 /* Make sure the cursor is distinct from text in this face. */
686 if (xgcv
.background
== face
->background
687 && xgcv
.foreground
== face
->foreground
)
689 xgcv
.background
= face
->foreground
;
690 xgcv
.foreground
= face
->background
;
692 xgcv
.font
= face
->font
->fid
;
693 xgcv
.graphics_exposures
= 0;
694 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
695 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
698 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
699 XSetStipple (x_current_display
, gc
, face
->stipple
);
705 if ((int) font
== FACE_DEFAULT
)
706 font
= f
->display
.x
->font
;
709 XDrawString (x_current_display
, window
, gc
,
710 left
, top
+ FONT_BASE (font
), buf
, len
);
713 XDrawImageString (x_current_display
, window
, gc
,
714 left
, top
+ FONT_BASE (font
), buf
, len
);
715 /* Clear the rest of the line's height. */
716 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
717 XClearArea (x_current_display
, window
, left
,
718 top
+ FONT_HEIGHT (font
),
719 FONT_WIDTH (font
) * len
,
720 /* This is how many pixels of height
722 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
726 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
727 which often is not up to date yet. */
728 if (!just_foreground
)
730 if (left
== orig_left
)
731 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
732 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
734 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
735 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
740 XFreeGC (x_current_display
, gc
);
742 /* We should probably check for XA_UNDERLINE_POSITION and
743 XA_UNDERLINE_THICKNESS properties on the font, but let's
744 just get the thing working, and come back to that. */
746 int underline_position
= 1;
748 if (font
->descent
<= underline_position
)
749 underline_position
= font
->descent
- 1;
752 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
756 + underline_position
),
757 len
* FONT_WIDTH (font
), 1);
760 left
+= len
* FONT_WIDTH (font
);
767 /* This is the old single-face code. */
770 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
773 register GLYPH
*gp
; /* Points to first GLYPH. */
774 register int n
; /* Number of glyphs to display. */
779 Window window
= FRAME_X_WINDOW (f
);
780 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
781 : (hl
? f
->display
.x
->reverse_gc
782 : f
->display
.x
->normal_gc
));
784 if (sizeof (GLYPH
) == sizeof (XChar2b
))
785 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
786 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
787 else if (sizeof (GLYPH
) == sizeof (unsigned char))
788 XDrawImageString (x_current_display
, window
, drawing_gc
,
789 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
791 /* What size of glyph ARE you using? And does X have a function to
797 /* Output some text at the nominal frame cursor position.
798 Advance the cursor over the text.
799 Output LEN glyphs at START.
801 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
802 controls the pixel values used for foreground and background. */
805 XTwrite_glyphs (start
, len
)
806 register GLYPH
*start
;
809 register int temp_length
;
819 /* If not within an update,
820 output at the frame's visible cursor. */
821 curs_x
= f
->cursor_x
;
822 curs_y
= f
->cursor_y
;
826 CHAR_TO_PIXEL_COL (f
, curs_x
),
827 CHAR_TO_PIXEL_ROW (f
, curs_y
),
828 start
, len
, highlight
, 0);
830 /* If we drew on top of the cursor, note that it is turned off. */
831 if (curs_y
== f
->phys_cursor_y
832 && curs_x
<= f
->phys_cursor_x
833 && curs_x
+ len
> f
->phys_cursor_x
)
834 f
->phys_cursor_x
= -1;
836 if (updating_frame
== 0)
839 x_display_cursor (f
, 1);
848 /* Clear to the end of the line.
849 Erase the current text line from the nominal cursor position (inclusive)
850 to column FIRST_UNUSED (exclusive). The idea is that everything
851 from FIRST_UNUSED onward is already erased. */
854 XTclear_end_of_line (first_unused
)
855 register int first_unused
;
857 struct frame
*f
= updating_frame
;
863 if (curs_y
< 0 || curs_y
>= f
->height
)
865 if (first_unused
<= 0)
868 if (first_unused
>= f
->width
)
869 first_unused
= f
->width
;
873 /* Notice if the cursor will be cleared by this operation. */
874 if (curs_y
== f
->phys_cursor_y
875 && curs_x
<= f
->phys_cursor_x
876 && f
->phys_cursor_x
< first_unused
)
877 f
->phys_cursor_x
= -1;
880 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
881 CHAR_TO_PIXEL_COL (f
, curs_x
),
882 CHAR_TO_PIXEL_ROW (f
, curs_y
),
883 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
884 f
->display
.x
->line_height
, False
);
886 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
888 #else /* ! defined (HAVE_X11) */
889 XPixSet (FRAME_X_WINDOW (f
),
890 CHAR_TO_PIXEL_COL (f
, curs_x
),
891 CHAR_TO_PIXEL_ROW (f
, curs_y
),
892 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
893 f
->display
.x
->line_height
,
894 f
->display
.x
->background_pixel
);
895 #endif /* ! defined (HAVE_X11) */
904 struct frame
*f
= updating_frame
;
909 f
->phys_cursor_x
= -1; /* Cursor not visible. */
910 curs_x
= 0; /* Nominal cursor position is top left. */
915 XClear (FRAME_X_WINDOW (f
));
917 /* We have to clear the scroll bars, too. If we have changed
918 colors or something like that, then they should be notified. */
919 x_scroll_bar_clear (f
);
923 #endif /* HAVE_X11 */
930 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
931 always contain the right glyphs to use.
933 It also needs to be changed to look at the details of the font and
934 see whether there is really overlap, and do nothing when there is
935 not. This can use font_char_overlap_left and font_char_overlap_right,
936 but just how to use them is not clear. */
938 /* Erase the character (if any) at the position just before X, Y in frame F,
939 then redraw it and the character before it.
940 This is necessary when we erase starting at X,
941 in case the character after X overlaps into the one before X.
942 Call this function with input blocked. */
945 redraw_previous_char (f
, x
, y
, highlight_flag
)
950 /* Erase the character before the new ones, in case
951 what was here before overlaps it.
952 Reoutput that character, and the previous character
953 (in case the previous character overlaps it). */
959 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
960 CHAR_TO_PIXEL_COL (f
, x
- 1),
961 CHAR_TO_PIXEL_ROW (f
, y
),
962 FONT_WIDTH (f
->display
.x
->font
),
963 f
->display
.x
->line_height
, False
);
965 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
966 CHAR_TO_PIXEL_ROW (f
, y
),
967 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
968 x
- start_x
, highlight_flag
, 1);
972 /* Erase the character (if any) at the position X, Y in frame F,
973 then redraw it and the character after it.
974 This is necessary when we erase endng at X,
975 in case the character after X overlaps into the one before X.
976 Call this function with input blocked. */
979 redraw_following_char (f
, x
, y
, highlight_flag
)
984 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
985 /* Erase the character after the new ones, in case
986 what was here before overlaps it.
987 Reoutput that character, and the following character
988 (in case the following character overlaps it). */
990 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
995 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
996 CHAR_TO_PIXEL_COL (f
, x
),
997 CHAR_TO_PIXEL_ROW (f
, y
),
998 FONT_WIDTH (f
->display
.x
->font
),
999 f
->display
.x
->line_height
, False
);
1001 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1002 CHAR_TO_PIXEL_ROW (f
, y
),
1003 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1004 end_x
- x
, highlight_flag
, 1);
1009 #if 0 /* Not in use yet */
1011 /* Return 1 if character C in font F extends past its left edge. */
1014 font_char_overlap_left (font
, c
)
1020 /* Find the bounding-box info for C. */
1021 if (font
->per_char
== 0)
1022 s
= &font
->max_bounds
;
1025 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1028 /* Decode char into row number (byte 1) and code within row (byte 2). */
1031 if (!(within
>= font
->min_char_or_byte2
1032 && within
<= font
->max_char_or_byte2
1033 && row
>= font
->min_byte1
1034 && row
<= font
->max_byte1
))
1036 /* If char is out of range, try the font's default char instead. */
1037 c
= font
->default_char
;
1038 row
= c
>> (INTBITS
- 8);
1041 if (!(within
>= font
->min_char_or_byte2
1042 && within
<= font
->max_char_or_byte2
1043 && row
>= font
->min_byte1
1044 && row
<= font
->max_byte1
))
1045 /* Still out of range means this char does not overlap. */
1048 /* We found the info for this char. */
1049 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1053 return (s
&& s
->lbearing
< 0);
1056 /* Return 1 if character C in font F extends past its right edge. */
1059 font_char_overlap_right (font
, c
)
1065 /* Find the bounding-box info for C. */
1066 if (font
->per_char
== 0)
1067 s
= &font
->max_bounds
;
1070 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1073 /* Decode char into row number (byte 1) and code within row (byte 2). */
1076 if (!(within
>= font
->min_char_or_byte2
1077 && within
<= font
->max_char_or_byte2
1078 && row
>= font
->min_byte1
1079 && row
<= font
->max_byte1
))
1081 /* If char is out of range, try the font's default char instead. */
1082 c
= font
->default_char
;
1083 row
= c
>> (INTBITS
- 8);
1086 if (!(within
>= font
->min_char_or_byte2
1087 && within
<= font
->max_char_or_byte2
1088 && row
>= font
->min_byte1
1089 && row
<= font
->max_byte1
))
1090 /* Still out of range means this char does not overlap. */
1093 /* We found the info for this char. */
1094 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1098 return (s
&& s
->rbearing
>= s
->width
);
1102 /* Invert the middle quarter of the frame for .15 sec. */
1104 /* We use the select system call to do the waiting, so we have to make sure
1105 it's available. If it isn't, we just won't do visual bells. */
1106 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1108 /* Subtract the `struct timeval' values X and Y,
1109 storing the result in RESULT.
1110 Return 1 if the difference is negative, otherwise 0. */
1113 timeval_subtract (result
, x
, y
)
1114 struct timeval
*result
, x
, y
;
1116 /* Perform the carry for the later subtraction by updating y.
1117 This is safer because on some systems
1118 the tv_sec member is unsigned. */
1119 if (x
.tv_usec
< y
.tv_usec
)
1121 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1122 y
.tv_usec
-= 1000000 * nsec
;
1125 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1127 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1128 y
.tv_usec
+= 1000000 * nsec
;
1132 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1133 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1134 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1136 /* Return indication of whether the result should be considered negative. */
1137 return x
.tv_sec
< y
.tv_sec
;
1148 /* Create a GC that will use the GXxor function to flip foreground pixels
1149 into background pixels. */
1153 values
.function
= GXxor
;
1154 values
.foreground
= (f
->display
.x
->foreground_pixel
1155 ^ f
->display
.x
->background_pixel
);
1157 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
1158 GCFunction
| GCForeground
, &values
);
1162 int width
= PIXEL_WIDTH (f
);
1163 int height
= PIXEL_HEIGHT (f
);
1165 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1166 width
/4, height
/4, width
/2, height
/2);
1167 XFlush (x_current_display
);
1170 struct timeval wakeup
, now
;
1172 EMACS_GET_TIME (wakeup
);
1174 /* Compute time to wait until, propagating carry from usecs. */
1175 wakeup
.tv_usec
+= 150000;
1176 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1177 wakeup
.tv_usec
%= 1000000;
1179 /* Keep waiting until past the time wakeup. */
1182 struct timeval timeout
;
1184 EMACS_GET_TIME (timeout
);
1186 /* In effect, timeout = wakeup - timeout.
1187 Break if result would be negative. */
1188 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1191 /* Try to wait that long--but we might wake up sooner. */
1192 select (0, 0, 0, 0, &timeout
);
1196 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1197 width
/4, height
/4, width
/2, height
/2);
1198 XFreeGC (x_current_display
, gc
);
1199 XFlush (x_current_display
);
1209 /* Make audible bell. */
1212 #define XRINGBELL XBell (x_current_display, 0)
1213 #else /* ! defined (HAVE_X11) */
1214 #define XRINGBELL XFeep (0);
1215 #endif /* ! defined (HAVE_X11) */
1219 if (x_current_display
== 0)
1222 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1224 XTflash (selected_frame
);
1235 /* Insert and delete character.
1236 These are not supposed to be used because we are supposed to turn
1237 off the feature of using them. */
1240 XTinsert_glyphs (start
, len
)
1241 register char *start
;
1254 /* Specify how many text lines, from the top of the window,
1255 should be affected by insert-lines and delete-lines operations.
1256 This, and those operations, are used only within an update
1257 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1260 XTset_terminal_window (n
)
1263 if (updating_frame
== 0)
1266 if ((n
<= 0) || (n
> updating_frame
->height
))
1267 flexlines
= updating_frame
->height
;
1272 /* Perform an insert-lines operation.
1273 Insert N lines at a vertical position curs_y. */
1279 register int topregion
, bottomregion
;
1280 register int length
, newtop
, mask
;
1281 register struct frame
*f
= updating_frame
;
1282 int intborder
= f
->display
.x
->internal_border_width
;
1284 if (curs_y
>= flexlines
)
1288 bottomregion
= flexlines
- (n
+ 1);
1289 newtop
= topregion
+ n
;
1290 length
= (bottomregion
- topregion
) + 1;
1294 #endif /* HAVE_X11 */
1296 if ((length
> 0) && (newtop
<= flexlines
))
1299 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1300 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1301 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1302 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1303 length
* f
->display
.x
->line_height
, intborder
,
1304 CHAR_TO_PIXEL_ROW (f
, newtop
));
1305 #else /* ! defined (HAVE_X11) */
1306 XMoveArea (FRAME_X_WINDOW (f
),
1307 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1308 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1309 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1310 length
* f
->display
.x
->line_height
);
1311 /* Now we must process any ExposeRegion events that occur
1312 if the area being copied from is obscured.
1313 We can't let it wait because further i/d operations
1314 may want to copy this area to another area. */
1316 #endif /* ! defined (HAVE_X11) */
1319 newtop
= min (newtop
, (flexlines
- 1));
1320 length
= newtop
- topregion
;
1324 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1325 CHAR_TO_PIXEL_ROW (f
, topregion
),
1326 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1327 n
* f
->display
.x
->line_height
, False
);
1328 #else /* ! defined (HAVE_X11) */
1329 XPixSet (FRAME_X_WINDOW (f
),
1331 CHAR_TO_PIXEL_ROW (f
, topregion
),
1332 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1333 n
* f
->display
.x
->line_height
,
1334 f
->display
.x
->background_pixel
);
1335 #endif /* ! defined (HAVE_X11) */
1339 /* Perform a delete-lines operation, deleting N lines
1340 at a vertical position curs_y. */
1347 register struct frame
*f
= updating_frame
;
1348 int intborder
= f
->display
.x
->internal_border_width
;
1350 if (curs_y
>= flexlines
)
1355 #endif /* HAVE_X11 */
1357 if ((curs_y
+ n
) >= flexlines
)
1359 if (flexlines
>= (curs_y
+ 1))
1362 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1363 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1364 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1365 (flexlines
- curs_y
) * f
->display
.x
->line_height
, False
);
1366 #else /* ! defined (HAVE_X11) */
1367 XPixSet (FRAME_X_WINDOW (f
),
1368 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1369 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1370 (flexlines
- curs_y
) * f
->display
.x
->line_height
,
1371 f
->display
.x
->background_pixel
);
1372 #endif /* ! defined (HAVE_X11) */
1378 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1379 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1381 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1382 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1383 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
,
1384 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1385 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1387 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1388 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1389 n
* f
->display
.x
->line_height
, False
);
1390 #else /* ! defined (HAVE_X11) */
1391 XMoveArea (FRAME_X_WINDOW (f
),
1393 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1394 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1395 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1396 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
);
1397 /* Now we must process any ExposeRegion events that occur
1398 if the area being copied from is obscured.
1399 We can't let it wait because further i/d operations
1400 may want to copy this area to another area. */
1402 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1403 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1404 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1405 n
* f
->display
.x
->line_height
, f
->display
.x
->background_pixel
);
1406 #endif /* ! defined (HAVE_X11) */
1410 /* Perform an insert-lines or delete-lines operation,
1411 inserting N lines or deleting -N lines at vertical position VPOS. */
1413 XTins_del_lines (vpos
, n
)
1416 if (updating_frame
== 0)
1419 /* Hide the cursor. */
1420 x_display_cursor (updating_frame
, 0);
1422 XTcursor_to (vpos
, 0);
1433 /* Support routines for exposure events. */
1434 static void clear_cursor ();
1436 /* Output into a rectangle of an X-window (for frame F)
1437 the characters in f->phys_lines that overlap that rectangle.
1438 TOP and LEFT are the position of the upper left corner of the rectangle.
1439 ROWS and COLS are the size of the rectangle.
1440 Call this function with input blocked. */
1443 dumprectangle (f
, left
, top
, cols
, rows
)
1445 register int left
, top
, cols
, rows
;
1447 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1448 int cursor_cleared
= 0;
1452 if (FRAME_GARBAGED_P (f
))
1455 /* Express rectangle as four edges, instead of position-and-size. */
1456 bottom
= top
+ rows
;
1457 right
= left
+ cols
;
1459 #ifndef HAVE_X11 /* Window manger does this for X11. */
1461 int intborder
= f
->display
.x
->internal_border_width
;
1463 /* If the rectangle includes any of the internal border area,
1464 redisplay the border emphasis. */
1465 if (top
< intborder
|| left
< intborder
1466 || bottom
> intborder
+ f
->height
* f
->display
.x
->line_height
1467 || right
> intborder
+ f
->width
* f
->display
.x
->line_height
)
1470 #endif /* not HAVE_X11 Window manger does this for X11. */
1472 /* Convert rectangle edges in pixels to edges in chars.
1473 Round down for left and top, up for right and bottom. */
1474 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1475 left
= PIXEL_TO_CHAR_COL (f
, left
);
1476 bottom
+= (f
->display
.x
->line_height
- 1);
1477 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1478 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1479 right
= PIXEL_TO_CHAR_COL (f
, right
);
1481 /* Clip the rectangle to what can be visible. */
1486 if (right
> f
->width
)
1488 if (bottom
> f
->height
)
1491 /* Get size in chars of the rectangle. */
1492 cols
= right
- left
;
1493 rows
= bottom
- top
;
1495 /* If rectangle has zero area, return. */
1496 if (rows
<= 0) return;
1497 if (cols
<= 0) return;
1499 /* Turn off the cursor if it is in the rectangle.
1500 We will turn it back on afterward. */
1501 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1502 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1508 /* Display the text in the rectangle, one text line at a time. */
1510 for (y
= top
; y
< bottom
; y
++)
1512 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1514 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1518 CHAR_TO_PIXEL_COL (f
, left
),
1519 CHAR_TO_PIXEL_ROW (f
, y
),
1520 line
, min (cols
, active_frame
->used
[y
] - left
),
1521 active_frame
->highlight
[y
], 0);
1524 /* Turn the cursor on if we turned it off. */
1527 x_display_cursor (f
, 1);
1531 /* Process all queued ExposeRegion events. */
1537 XExposeRegionEvent r
;
1539 while (dequeue_event (&r
, &x_expose_queue
))
1541 struct frame
*f
= x_window_to_frame (r
.window
);
1542 if (f
->display
.x
->icon_desc
== r
.window
)
1545 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1549 #endif /* HAVE_X11 */
1551 /* Process all expose events that are pending, for X10.
1552 Redraws the cursor if necessary on any frame that
1553 is not in the process of being updated with update_frame. */
1557 x_do_pending_expose ()
1561 Lisp_Object tail
, frame
;
1563 if (expose_all_windows
)
1565 expose_all_windows
= 0;
1566 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1568 register int temp_width
, temp_height
;
1571 frame
= XCONS (tail
)->car
;
1572 if (XGCTYPE (frame
) != Lisp_Frame
)
1575 if (! FRAME_X_P (f
))
1577 if (!f
->async_visible
)
1579 if (!f
->display
.x
->needs_exposure
)
1582 intborder
= f
->display
.x
->internal_border_width
;
1585 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1586 temp_width
= ((windowinfo
.width
- 2 * intborder
1587 - f
->display
.x
->v_scroll_bar_width
)
1588 / FONT_WIDTH (f
->display
.x
->font
));
1589 temp_height
= ((windowinfo
.height
- 2 * intborder
1590 - f
->display
.x
->h_scroll_bar_height
)
1591 / f
->display
.x
->line_height
);
1592 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1594 change_frame_size (f
, max (1, temp_height
),
1595 max (1, temp_width
), 0, 1);
1596 x_resize_scroll_bars (f
);
1598 f
->display
.x
->left_pos
= windowinfo
.x
;
1599 f
->display
.x
->top_pos
= windowinfo
.y
;
1600 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1604 f
->display
.x
->needs_exposure
= 0;
1605 if (updating_frame
!= f
)
1606 x_display_cursor (f
, 1);
1611 /* Handle any individual-rectangle expose events queued
1612 for various windows. */
1615 #else /* ! defined (HAVE_X11) */
1617 #endif /* ! defined (HAVE_X11) */
1623 frame_highlight (frame
)
1624 struct frame
*frame
;
1626 /* We used to only do this if Vx_no_window_manager was non-nil, but
1627 the ICCCM (section 4.1.6) says that the window's border pixmap
1628 and border pixel are window attributes which are "private to the
1629 client", so we can always change it to whatever we want. */
1631 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1632 frame
->display
.x
->border_pixel
);
1634 x_display_cursor (frame
, 1);
1638 frame_unhighlight (frame
)
1639 struct frame
*frame
;
1641 /* We used to only do this if Vx_no_window_manager was non-nil, but
1642 the ICCCM (section 4.1.6) says that the window's border pixmap
1643 and border pixel are window attributes which are "private to the
1644 client", so we can always change it to whatever we want. */
1646 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1647 frame
->display
.x
->border_tile
);
1649 x_display_cursor (frame
, 1);
1651 #else /* ! defined (HAVE_X11) */
1652 /* Dump the border-emphasis of frame F.
1653 If F is selected, this is a lining of the same color as the border,
1654 just within the border, occupying a portion of the internal border.
1655 If F is not selected, it is background in the same place.
1656 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1658 ALWAYS = 1 is used when a frame becomes selected or deselected.
1659 In that case, we also turn the cursor off and on again
1660 so it will appear in the proper shape (solid if selected; else hollow.) */
1663 dumpborder (f
, always
)
1667 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1668 int width
= PIXEL_WIDTH (f
);
1669 int height
= PIXEL_HEIGHT (f
);
1672 if (f
!= selected_frame
)
1677 pixel
= f
->display
.x
->background_pixel
;
1681 pixel
= f
->display
.x
->border_pixel
;
1684 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1685 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1686 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1688 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1692 x_display_cursor (f
, 1);
1694 #endif /* ! defined (HAVE_X11) */
1696 static void XTframe_rehighlight ();
1698 /* The focus has changed. Update the frames as necessary to reflect
1699 the new situation. Note that we can't change the selected frame
1700 here, because the lisp code we are interrupting might become confused.
1701 Each event gets marked with the frame in which it occurred, so the
1702 lisp code can tell when the switch took place by examining the events. */
1705 x_new_focus_frame (frame
)
1706 struct frame
*frame
;
1708 struct frame
*old_focus
= x_focus_frame
;
1709 int events_enqueued
= 0;
1711 if (frame
!= x_focus_frame
)
1713 /* Set this before calling other routines, so that they see
1714 the correct value of x_focus_frame. */
1715 x_focus_frame
= frame
;
1717 if (old_focus
&& old_focus
->auto_lower
)
1718 x_lower_frame (old_focus
);
1721 selected_frame
= frame
;
1722 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1723 Lisp_Frame
, selected_frame
);
1724 Fselect_window (selected_frame
->selected_window
);
1725 choose_minibuf_frame ();
1728 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1729 pending_autoraise_frame
= x_focus_frame
;
1731 pending_autoraise_frame
= 0;
1734 XTframe_rehighlight ();
1738 /* The focus has changed, or we have redirected a frame's focus to
1739 another frame (this happens when a frame uses a surrogate
1740 minibuffer frame). Shift the highlight as appropriate. */
1742 XTframe_rehighlight ()
1744 struct frame
*old_highlight
= x_highlight_frame
;
1749 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1750 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1752 if (! FRAME_LIVE_P (x_highlight_frame
))
1754 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1755 x_highlight_frame
= x_focus_frame
;
1759 x_highlight_frame
= 0;
1761 if (x_highlight_frame
!= old_highlight
)
1764 frame_unhighlight (old_highlight
);
1765 if (x_highlight_frame
)
1766 frame_highlight (x_highlight_frame
);
1770 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1772 /* Which modifier keys are on which modifier bits?
1774 With each keystroke, X returns eight bits indicating which modifier
1775 keys were held down when the key was pressed. The interpretation
1776 of the top five modifier bits depends on what keys are attached
1777 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1780 x_meta_mod_mask is a mask containing the bits used for the meta key.
1781 It may have more than one bit set, if more than one modifier bit
1782 has meta keys on it. Basically, if EVENT is a KeyPress event,
1783 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1785 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1786 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1787 only be affected by the lock modifier bit if XK_Shift_Lock is in
1788 use; XK_Caps_Lock should only affect alphabetic keys. With this
1789 arrangement, the lock modifier should shift the character if
1790 (EVENT.state & x_shift_lock_mask) != 0. */
1791 static int x_meta_mod_mask
, x_shift_lock_mask
;
1793 /* These are like x_meta_mod_mask, but for different modifiers. */
1794 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1796 /* Initialize mode_switch_bit and modifier_meaning. */
1798 x_find_modifier_meanings ()
1800 int min_code
, max_code
;
1803 XModifierKeymap
*mods
;
1805 x_meta_mod_mask
= 0;
1806 x_shift_lock_mask
= 0;
1808 x_super_mod_mask
= 0;
1809 x_hyper_mod_mask
= 0;
1812 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1814 min_code
= x_current_display
->min_keycode
;
1815 max_code
= x_current_display
->max_keycode
;
1818 syms
= XGetKeyboardMapping (x_current_display
,
1819 min_code
, max_code
- min_code
+ 1,
1821 mods
= XGetModifierMapping (x_current_display
);
1823 /* Scan the modifier table to see which modifier bits the Meta and
1824 Alt keysyms are on. */
1826 int row
, col
; /* The row and column in the modifier table. */
1828 for (row
= 3; row
< 8; row
++)
1829 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1832 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1834 /* Zeroes are used for filler. Skip them. */
1838 /* Are any of this keycode's keysyms a meta key? */
1842 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1844 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1850 x_meta_mod_mask
|= (1 << row
);
1855 x_alt_mod_mask
|= (1 << row
);
1860 x_hyper_mod_mask
|= (1 << row
);
1865 x_super_mod_mask
|= (1 << row
);
1869 /* Ignore this if it's not on the lock modifier. */
1870 if ((1 << row
) == LockMask
)
1871 x_shift_lock_mask
= LockMask
;
1879 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1880 if (! x_meta_mod_mask
)
1882 x_meta_mod_mask
= x_alt_mod_mask
;
1886 /* If some keys are both alt and meta,
1887 make them just meta, not alt. */
1888 if (x_alt_mod_mask
& x_meta_mod_mask
)
1890 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1893 XFree ((char *) syms
);
1894 XFreeModifiermap (mods
);
1897 /* Convert between the modifier bits X uses and the modifier bits
1900 x_x_to_emacs_modifiers (state
)
1903 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1904 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1905 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1906 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1907 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1908 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1912 x_emacs_to_x_modifiers (state
)
1915 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1916 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1917 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1918 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1919 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1920 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1923 /* Mouse clicks and mouse movement. Rah. */
1926 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1927 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1928 that the glyph at X, Y occupies, if BOUNDS != 0.
1929 If NOCLIP is nonzero, do not force the value into range. */
1932 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1934 register int pix_x
, pix_y
;
1935 register int *x
, *y
;
1939 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1940 even for negative values. */
1942 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1944 pix_y
-= (f
)->display
.x
->line_height
- 1;
1946 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1947 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1951 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1952 bounds
->height
= f
->display
.x
->line_height
;
1953 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1954 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1961 else if (pix_x
> f
->width
)
1966 else if (pix_y
> f
->height
)
1975 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1978 register int *pix_x
, *pix_y
;
1980 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1981 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1984 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1986 If the event is a button press, then note that we have grabbed
1990 construct_mouse_click (result
, event
, f
)
1991 struct input_event
*result
;
1992 XButtonEvent
*event
;
1995 /* Make the event type no_event; we'll change that when we decide
1997 result
->kind
= mouse_click
;
1998 result
->code
= event
->button
- Button1
;
1999 result
->timestamp
= event
->time
;
2000 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2001 | (event
->type
== ButtonRelease
2005 /* Notice if the mouse is still grabbed. */
2006 if (event
->type
== ButtonPress
)
2008 if (! x_mouse_grabbed
)
2009 Vmouse_depressed
= Qt
;
2010 x_mouse_grabbed
|= (1 << event
->button
);
2011 last_mouse_frame
= f
;
2013 else if (event
->type
== ButtonRelease
)
2015 x_mouse_grabbed
&= ~(1 << event
->button
);
2016 if (!x_mouse_grabbed
)
2017 Vmouse_depressed
= Qnil
;
2024 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2025 XFASTINT (result
->x
) = column
;
2026 XFASTINT (result
->y
) = row
;
2028 XSET (result
->x
, Lisp_Int
, event
->x
);
2029 XSET (result
->y
, Lisp_Int
, event
->y
);
2030 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2034 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2037 construct_menu_click (result
, event
, f
)
2038 struct input_event
*result
;
2039 XButtonEvent
*event
;
2042 /* Make the event type no_event; we'll change that when we decide
2044 result
->kind
= mouse_click
;
2045 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
2046 result
->timestamp
= event
->time
;
2047 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2048 | (event
->type
== ButtonRelease
2052 XSET (result
->x
, Lisp_Int
, event
->x
);
2053 XSET (result
->y
, Lisp_Int
, -1);
2054 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2057 /* Function to report a mouse movement to the mainstream Emacs code.
2058 The input handler calls this.
2060 We have received a mouse movement event, which is given in *event.
2061 If the mouse is over a different glyph than it was last time, tell
2062 the mainstream emacs code by setting mouse_moved. If not, ask for
2063 another motion event, so we can check again the next time it moves. */
2066 note_mouse_movement (frame
, event
)
2068 XMotionEvent
*event
;
2071 last_mouse_movement_time
= event
->time
;
2073 if (event
->window
!= FRAME_X_WINDOW (frame
))
2076 last_mouse_scroll_bar
= Qnil
;
2078 note_mouse_highlight (frame
, -1, -1);
2080 /* Ask for another mouse motion event. */
2084 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2085 (Window
*) &dummy
, (Window
*) &dummy
,
2086 &dummy
, &dummy
, &dummy
, &dummy
,
2087 (unsigned int *) &dummy
);
2091 /* Has the mouse moved off the glyph it was on at the last sighting? */
2092 else if (event
->x
< last_mouse_glyph
.x
2093 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2094 || event
->y
< last_mouse_glyph
.y
2095 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2098 last_mouse_scroll_bar
= Qnil
;
2100 note_mouse_highlight (frame
, event
->x
, event
->y
);
2102 /* Ask for another mouse motion event. */
2106 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2107 (Window
*) &dummy
, (Window
*) &dummy
,
2108 &dummy
, &dummy
, &dummy
, &dummy
,
2109 (unsigned int *) &dummy
);
2114 /* It's on the same glyph. Call XQueryPointer so we'll get an
2115 event the next time the mouse moves and we can see if it's
2116 *still* on the same glyph. */
2119 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2120 (Window
*) &dummy
, (Window
*) &dummy
,
2121 &dummy
, &dummy
, &dummy
, &dummy
,
2122 (unsigned int *) &dummy
);
2126 /* This is used for debugging, to turn off note_mouse_highlight. */
2127 static int disable_mouse_highlight
;
2129 /* Take proper action when the mouse has moved to position X, Y on frame F
2130 as regards highlighting characters that have mouse-face properties.
2131 Also dehighlighting chars where the mouse was before.
2132 X and Y can be negative or out of range. */
2135 note_mouse_highlight (f
, x
, y
)
2138 int row
, column
, portion
;
2139 XRectangle new_glyph
;
2143 if (disable_mouse_highlight
)
2146 mouse_face_mouse_x
= x
;
2147 mouse_face_mouse_y
= y
;
2148 mouse_face_mouse_frame
= f
;
2150 if (mouse_face_defer
)
2155 mouse_face_deferred_gc
= 1;
2159 /* Find out which glyph the mouse is on. */
2160 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2161 &new_glyph
, x_mouse_grabbed
);
2163 /* Which window is that in? */
2164 window
= window_from_coordinates (f
, column
, row
, &portion
);
2165 w
= XWINDOW (window
);
2167 /* If we were displaying active text in another window, clear that. */
2168 if (! EQ (window
, mouse_face_window
))
2169 clear_mouse_face ();
2171 /* Are we in a window whose display is up to date?
2172 And verify the buffer's text has not changed. */
2173 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2174 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2175 && EQ (w
->window_end_valid
, w
->buffer
)
2176 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
2178 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2181 /* Find which buffer position the mouse corresponds to. */
2182 for (i
= column
; i
>= 0; i
--)
2186 /* Is it outside the displayed active region (if any)? */
2188 clear_mouse_face ();
2189 else if (! (EQ (window
, mouse_face_window
)
2190 && row
>= mouse_face_beg_row
2191 && row
<= mouse_face_end_row
2192 && (row
> mouse_face_beg_row
|| column
>= mouse_face_beg_col
)
2193 && (row
< mouse_face_end_row
|| column
< mouse_face_end_col
2194 || mouse_face_past_end
)))
2196 Lisp_Object mouse_face
, overlay
, position
;
2197 Lisp_Object
*overlay_vec
;
2198 int len
, noverlays
, ignor1
;
2199 struct buffer
*obuf
;
2202 /* If we get an out-of-range value, return now; avoid an error. */
2203 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2206 /* Make the window's buffer temporarily current for
2207 overlays_at and compute_char_face. */
2208 obuf
= current_buffer
;
2209 current_buffer
= XBUFFER (w
->buffer
);
2215 /* Yes. Clear the display of the old active region, if any. */
2216 clear_mouse_face ();
2218 /* Is this char mouse-active? */
2219 XSET (position
, Lisp_Int
, pos
);
2222 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2224 /* Put all the overlays we want in a vector in overlay_vec.
2225 Store the length in len. */
2226 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
, &ignor1
);
2227 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2229 /* Find the highest priority overlay that has a mouse-face prop. */
2231 for (i
= 0; i
< noverlays
; i
++)
2233 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2234 if (!NILP (mouse_face
))
2236 overlay
= overlay_vec
[i
];
2241 /* If no overlay applies, get a text property. */
2243 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2245 /* Handle the overlay case. */
2246 if (! NILP (overlay
))
2248 /* Find the range of text around this char that
2249 should be active. */
2250 Lisp_Object before
, after
;
2253 before
= Foverlay_start (overlay
);
2254 after
= Foverlay_end (overlay
);
2255 /* Record this as the current active region. */
2256 fast_find_position (window
, before
, &mouse_face_beg_col
,
2257 &mouse_face_beg_row
);
2259 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2260 &mouse_face_end_row
);
2261 mouse_face_window
= window
;
2262 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
2263 &ignore
, pos
+ 1, 1);
2265 /* Display it as active. */
2266 show_mouse_face (1);
2268 /* Handle the text property case. */
2269 else if (! NILP (mouse_face
))
2271 /* Find the range of text around this char that
2272 should be active. */
2273 Lisp_Object before
, after
, beginning
, end
;
2276 beginning
= Fmarker_position (w
->start
);
2277 XSET (end
, Lisp_Int
,
2278 (BUF_Z (XBUFFER (w
->buffer
))
2279 - XFASTINT (w
->window_end_pos
)));
2281 = Fprevious_single_property_change (make_number (pos
+ 1),
2283 w
->buffer
, beginning
);
2285 = Fnext_single_property_change (position
, Qmouse_face
,
2287 /* Record this as the current active region. */
2288 fast_find_position (window
, before
, &mouse_face_beg_col
,
2289 &mouse_face_beg_row
);
2291 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2292 &mouse_face_end_row
);
2293 mouse_face_window
= window
;
2295 = compute_char_face (f
, w
, pos
, 0, 0,
2296 &ignore
, pos
+ 1, 1);
2298 /* Display it as active. */
2299 show_mouse_face (1);
2303 current_buffer
= obuf
;
2308 /* Find the row and column of position POS in window WINDOW.
2309 Store them in *COLUMNP and *ROWP.
2310 This assumes display in WINDOW is up to date.
2311 If POS is above start of WINDOW, return coords
2312 of start of first screen line.
2313 If POS is after end of WINDOW, return coords of end of last screen line.
2315 Value is 1 if POS is in range, 0 if it was off screen. */
2318 fast_find_position (window
, pos
, columnp
, rowp
)
2321 int *columnp
, *rowp
;
2323 struct window
*w
= XWINDOW (window
);
2324 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2329 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2330 int width
= window_internal_width (w
);
2334 /* Find the right row. */
2339 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2340 if (linestart
> pos
)
2346 /* Find the right column with in it. */
2347 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2349 for (i
= 0; i
< width
; i
++)
2351 if (charstarts
[left
+ i
] == pos
)
2354 *columnp
= i
+ left
;
2357 else if (charstarts
[left
+ i
] > pos
)
2359 else if (charstarts
[left
+ i
] > 0)
2368 /* Display the active region described by mouse_face_*
2369 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2372 show_mouse_face (hl
)
2375 struct window
*w
= XWINDOW (mouse_face_window
);
2376 int width
= window_internal_width (w
);
2377 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2379 int curs_x
= f
->phys_cursor_x
;
2380 int curs_y
= f
->phys_cursor_y
;
2383 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2385 int column
= (i
== mouse_face_beg_row
? mouse_face_beg_col
: w
->left
);
2386 int endcolumn
= (i
== mouse_face_end_row
? mouse_face_end_col
: w
->left
+ width
);
2387 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
] - w
->left
);
2389 /* If the cursor's in the text we are about to rewrite,
2390 turn the cursor off. */
2392 && curs_x
>= mouse_face_beg_col
- 1 && curs_x
<= mouse_face_end_col
)
2394 x_display_cursor (f
, 0);
2399 CHAR_TO_PIXEL_COL (f
, column
),
2400 CHAR_TO_PIXEL_ROW (f
, i
),
2401 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2403 /* Highlight with mouse face if hl > 0. */
2407 /* If we turned the cursor off, turn it back on. */
2409 x_display_cursor (f
, 1);
2411 /* Change the mouse cursor according to the value of HL. */
2413 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->cross_cursor
);
2415 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->text_cursor
);
2418 /* Clear out the mouse-highlighted active region.
2419 Redraw it unhighlighted first. */
2424 if (! NILP (mouse_face_window
))
2425 show_mouse_face (0);
2427 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2428 mouse_face_end_row
= mouse_face_end_col
= -1;
2429 mouse_face_window
= Qnil
;
2432 static struct scroll_bar
*x_window_to_scroll_bar ();
2433 static void x_scroll_bar_report_motion ();
2435 /* Return the current position of the mouse.
2437 If the mouse movement started in a scroll bar, set *f, *bar_window,
2438 and *part to the frame, window, and scroll bar part that the mouse
2439 is over. Set *x and *y to the portion and whole of the mouse's
2440 position on the scroll bar.
2442 If the mouse movement started elsewhere, set *f to the frame the
2443 mouse is on, *bar_window to nil, and *x and *y to the character cell
2446 Set *time to the server timestamp for the time at which the mouse
2447 was at this position.
2449 Don't store anything if we don't have a valid set of values to report.
2451 This clears the mouse_moved flag, so we can wait for the next mouse
2452 movement. This also calls XQueryPointer, which will cause the
2453 server to give us another MotionNotify when the mouse moves
2457 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
2459 Lisp_Object
*bar_window
;
2460 enum scroll_bar_part
*part
;
2462 unsigned long *time
;
2468 if (! NILP (last_mouse_scroll_bar
))
2469 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
2475 Window dummy_window
;
2479 last_mouse_scroll_bar
= Qnil
;
2481 /* Figure out which root window we're on. */
2482 XQueryPointer (x_current_display
,
2483 DefaultRootWindow (x_current_display
),
2485 /* The root window which contains the pointer. */
2488 /* Trash which we can't trust if the pointer is on
2489 a different screen. */
2492 /* The position on that root window. */
2495 /* More trash we can't trust. */
2498 /* Modifier keys and pointer buttons, about which
2500 (unsigned int *) &dummy
);
2502 /* Now we have a position on the root; find the innermost window
2503 containing the pointer. */
2507 int parent_x
, parent_y
;
2511 if (x_mouse_grabbed
&& FRAME_LIVE_P (last_mouse_frame
))
2513 /* If mouse was grabbed on a frame, give coords for that frame
2514 even if the mouse is now outside it. */
2515 XTranslateCoordinates (x_current_display
,
2517 /* From-window, to-window. */
2518 root
, FRAME_X_WINDOW (last_mouse_frame
),
2520 /* From-position, to-position. */
2521 root_x
, root_y
, &win_x
, &win_y
,
2525 f1
= last_mouse_frame
;
2531 XTranslateCoordinates (x_current_display
,
2533 /* From-window, to-window. */
2536 /* From-position, to-position. */
2537 root_x
, root_y
, &win_x
, &win_y
,
2550 /* Now we know that:
2551 win is the innermost window containing the pointer
2552 (XTC says it has no child containing the pointer),
2553 win_x and win_y are the pointer's position in it
2554 (XTC did this the last time through), and
2555 parent_x and parent_y are the pointer's position in win's parent.
2556 (They are what win_x and win_y were when win was child.
2557 If win is the root window, it has no parent, and
2558 parent_{x,y} are invalid, but that's okay, because we'll
2559 never use them in that case.) */
2561 /* Is win one of our frames? */
2562 f1
= x_any_window_to_frame (win
);
2565 /* If not, is it one of our scroll bars? */
2568 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2572 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2580 int ignore1
, ignore2
;
2582 /* Ok, we found a frame. Store all the values. */
2584 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2585 &last_mouse_glyph
, x_mouse_grabbed
);
2590 XSET (*x
, Lisp_Int
, win_x
);
2591 XSET (*y
, Lisp_Int
, win_y
);
2592 *time
= last_mouse_movement_time
;
2600 #else /* ! defined (HAVE_X11) */
2601 #define XEvent XKeyPressedEvent
2602 #endif /* ! defined (HAVE_X11) */
2604 /* Scroll bar support. */
2606 /* Given an X window ID, find the struct scroll_bar which manages it.
2607 This can be called in GC, so we have to make sure to strip off mark
2609 static struct scroll_bar
*
2610 x_window_to_scroll_bar (window_id
)
2613 Lisp_Object tail
, frame
;
2615 for (tail
= Vframe_list
;
2616 XGCTYPE (tail
) == Lisp_Cons
;
2617 tail
= XCONS (tail
)->cdr
)
2619 Lisp_Object frame
, bar
, condemned
;
2621 frame
= XCONS (tail
)->car
;
2622 /* All elements of Vframe_list should be frames. */
2623 if (XGCTYPE (frame
) != Lisp_Frame
)
2626 /* Scan this frame's scroll bar list for a scroll bar with the
2628 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2629 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2630 /* This trick allows us to search both the ordinary and
2631 condemned scroll bar lists with one loop. */
2632 ! GC_NILP (bar
) || (bar
= condemned
,
2635 bar
= XSCROLL_BAR (bar
)->next
)
2636 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2637 return XSCROLL_BAR (bar
);
2643 /* Open a new X window to serve as a scroll bar, and return the
2644 scroll bar vector for it. */
2645 static struct scroll_bar
*
2646 x_scroll_bar_create (window
, top
, left
, width
, height
)
2647 struct window
*window
;
2648 int top
, left
, width
, height
;
2650 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2651 struct scroll_bar
*bar
=
2652 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2657 XSetWindowAttributes a
;
2659 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2660 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2661 | ButtonMotionMask
| PointerMotionHintMask
2663 a
.cursor
= x_vertical_scroll_bar_cursor
;
2665 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2670 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2671 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2672 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2673 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2674 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2675 sb_widget
= XtCreateManagedWidget ("box",
2677 frame
->display
.x
->edit_widget
, al
, ac
);
2678 SET_SCROLL_BAR_X_WINDOW
2679 (bar
, sb_widget
->core
.window
);
2681 SET_SCROLL_BAR_X_WINDOW
2683 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2685 /* Position and size of scroll bar. */
2686 left
, top
, width
, height
,
2688 /* Border width, depth, class, and visual. */
2689 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2695 XSET (bar
->window
, Lisp_Window
, window
);
2696 XSET (bar
->top
, Lisp_Int
, top
);
2697 XSET (bar
->left
, Lisp_Int
, left
);
2698 XSET (bar
->width
, Lisp_Int
, width
);
2699 XSET (bar
->height
, Lisp_Int
, height
);
2700 XSET (bar
->start
, Lisp_Int
, 0);
2701 XSET (bar
->end
, Lisp_Int
, 0);
2702 bar
->dragging
= Qnil
;
2704 /* Add bar to its frame's list of scroll bars. */
2705 bar
->next
= FRAME_SCROLL_BARS (frame
);
2707 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2708 if (! NILP (bar
->next
))
2709 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2711 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2718 /* Draw BAR's handle in the proper position.
2719 If the handle is already drawn from START to END, don't bother
2720 redrawing it, unless REBUILD is non-zero; in that case, always
2721 redraw it. (REBUILD is handy for drawing the handle after expose
2724 Normally, we want to constrain the start and end of the handle to
2725 fit inside its rectangle, but if the user is dragging the scroll bar
2726 handle, we want to let them drag it down all the way, so that the
2727 bar's top is as far down as it goes; otherwise, there's no way to
2728 move to the very end of the buffer. */
2730 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2731 struct scroll_bar
*bar
;
2735 int dragging
= ! NILP (bar
->dragging
);
2736 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2737 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2739 /* If the display is already accurate, do nothing. */
2741 && start
== XINT (bar
->start
)
2742 && end
== XINT (bar
->end
))
2748 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2749 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2750 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2752 /* Make sure the values are reasonable, and try to preserve
2753 the distance between start and end. */
2755 int length
= end
- start
;
2759 else if (start
> top_range
)
2761 end
= start
+ length
;
2765 else if (end
> top_range
&& ! dragging
)
2769 /* Store the adjusted setting in the scroll bar. */
2770 XSET (bar
->start
, Lisp_Int
, start
);
2771 XSET (bar
->end
, Lisp_Int
, end
);
2773 /* Clip the end position, just for display. */
2774 if (end
> top_range
)
2777 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2778 below top positions, to make sure the handle is always at least
2779 that many pixels tall. */
2780 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2782 /* Draw the empty space above the handle. Note that we can't clear
2783 zero-height areas; that means "clear to end of window." */
2785 XClearArea (x_current_display
, w
,
2787 /* x, y, width, height, and exposures. */
2788 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2789 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2790 inside_width
, start
,
2793 /* Draw the handle itself. */
2794 XFillRectangle (x_current_display
, w
, gc
,
2796 /* x, y, width, height */
2797 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2798 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2799 inside_width
, end
- start
);
2802 /* Draw the empty space below the handle. Note that we can't
2803 clear zero-height areas; that means "clear to end of window." */
2804 if (end
< inside_height
)
2805 XClearArea (x_current_display
, w
,
2807 /* x, y, width, height, and exposures. */
2808 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2809 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2810 inside_width
, inside_height
- end
,
2818 /* Move a scroll bar around on the screen, to accommodate changing
2819 window configurations. */
2821 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2822 struct scroll_bar
*bar
;
2823 int top
, left
, width
, height
;
2829 unsigned int mask
= 0;
2836 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2837 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2838 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2839 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2842 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2846 XSET (bar
->left
, Lisp_Int
, left
);
2847 XSET (bar
->top
, Lisp_Int
, top
);
2848 XSET (bar
->width
, Lisp_Int
, width
);
2849 XSET (bar
->height
, Lisp_Int
, height
);
2854 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2857 x_scroll_bar_remove (bar
)
2858 struct scroll_bar
*bar
;
2860 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2864 /* Destroy the window. */
2865 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2867 /* Disassociate this scroll bar from its window. */
2868 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2873 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2874 that we are displaying PORTION characters out of a total of WHOLE
2875 characters, starting at POSITION. If WINDOW has no scroll bar,
2878 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2879 struct window
*window
;
2880 int portion
, whole
, position
;
2882 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2883 int top
= XINT (window
->top
);
2884 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2885 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2887 /* Where should this scroll bar be, pixelwise? */
2888 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2889 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2890 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2891 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2893 struct scroll_bar
*bar
;
2895 /* Does the scroll bar exist yet? */
2896 if (NILP (window
->vertical_scroll_bar
))
2897 bar
= x_scroll_bar_create (window
,
2898 pixel_top
, pixel_left
,
2899 pixel_width
, pixel_height
);
2902 /* It may just need to be moved and resized. */
2903 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2904 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2907 /* Set the scroll bar's current state, unless we're currently being
2909 if (NILP (bar
->dragging
))
2912 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2915 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2918 int start
= ((double) position
* top_range
) / whole
;
2919 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2921 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2925 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2929 /* The following three hooks are used when we're doing a thorough
2930 redisplay of the frame. We don't explicitly know which scroll bars
2931 are going to be deleted, because keeping track of when windows go
2932 away is a real pain - "Can you say set-window-configuration, boys
2933 and girls?" Instead, we just assert at the beginning of redisplay
2934 that *all* scroll bars are to be removed, and then save a scroll bar
2935 from the fiery pit when we actually redisplay its window. */
2937 /* Arrange for all scroll bars on FRAME to be removed at the next call
2938 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2939 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2941 XTcondemn_scroll_bars (frame
)
2944 /* The condemned list should be empty at this point; if it's not,
2945 then the rest of Emacs isn't using the condemn/redeem/judge
2946 protocol correctly. */
2947 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2950 /* Move them all to the "condemned" list. */
2951 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2952 FRAME_SCROLL_BARS (frame
) = Qnil
;
2955 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2956 Note that WINDOW isn't necessarily condemned at all. */
2958 XTredeem_scroll_bar (window
)
2959 struct window
*window
;
2961 struct scroll_bar
*bar
;
2963 /* We can't redeem this window's scroll bar if it doesn't have one. */
2964 if (NILP (window
->vertical_scroll_bar
))
2967 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2969 /* Unlink it from the condemned list. */
2971 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2973 if (NILP (bar
->prev
))
2975 /* If the prev pointer is nil, it must be the first in one of
2977 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2978 /* It's not condemned. Everything's fine. */
2980 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2981 window
->vertical_scroll_bar
))
2982 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2984 /* If its prev pointer is nil, it must be at the front of
2985 one or the other! */
2989 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2991 if (! NILP (bar
->next
))
2992 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2994 bar
->next
= FRAME_SCROLL_BARS (f
);
2996 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2997 if (! NILP (bar
->next
))
2998 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
3002 /* Remove all scroll bars on FRAME that haven't been saved since the
3003 last call to `*condemn_scroll_bars_hook'. */
3005 XTjudge_scroll_bars (f
)
3008 Lisp_Object bar
, next
;
3010 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3012 /* Clear out the condemned list now so we won't try to process any
3013 more events on the hapless scroll bars. */
3014 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3016 for (; ! NILP (bar
); bar
= next
)
3018 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3020 x_scroll_bar_remove (b
);
3023 b
->next
= b
->prev
= Qnil
;
3026 /* Now there should be no references to the condemned scroll bars,
3027 and they should get garbage-collected. */
3031 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3033 This may be called from a signal handler, so we have to ignore GC
3036 x_scroll_bar_expose (bar
, event
)
3037 struct scroll_bar
*bar
;
3040 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3041 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
3045 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3047 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3048 XDrawRectangle (x_current_display
, w
, gc
,
3050 /* x, y, width, height */
3051 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
3056 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3057 is set to something other than no_event, it is enqueued.
3059 This may be called from a signal handler, so we have to ignore GC
3062 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3063 struct scroll_bar
*bar
;
3065 struct input_event
*emacs_event
;
3067 if (XGCTYPE (bar
->window
) != Lisp_Window
)
3070 emacs_event
->kind
= scroll_bar_click
;
3071 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3072 emacs_event
->modifiers
=
3073 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
3074 | (event
->type
== ButtonRelease
3077 emacs_event
->frame_or_window
= bar
->window
;
3078 emacs_event
->timestamp
= event
->xbutton
.time
;
3080 int internal_height
=
3081 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3083 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3084 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3087 if (y
> top_range
) y
= top_range
;
3089 if (y
< XINT (bar
->start
))
3090 emacs_event
->part
= scroll_bar_above_handle
;
3091 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3092 emacs_event
->part
= scroll_bar_handle
;
3094 emacs_event
->part
= scroll_bar_below_handle
;
3096 /* Just because the user has clicked on the handle doesn't mean
3097 they want to drag it. Lisp code needs to be able to decide
3098 whether or not we're dragging. */
3100 /* If the user has just clicked on the handle, record where they're
3102 if (event
->type
== ButtonPress
3103 && emacs_event
->part
== scroll_bar_handle
)
3104 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
3107 /* If the user has released the handle, set it to its final position. */
3108 if (event
->type
== ButtonRelease
3109 && ! NILP (bar
->dragging
))
3111 int new_start
= y
- XINT (bar
->dragging
);
3112 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3114 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3115 bar
->dragging
= Qnil
;
3118 /* Same deal here as the other #if 0. */
3120 /* Clicks on the handle are always reported as occurring at the top of
3122 if (emacs_event
->part
== scroll_bar_handle
)
3123 emacs_event
->x
= bar
->start
;
3125 XSET (emacs_event
->x
, Lisp_Int
, y
);
3127 XSET (emacs_event
->x
, Lisp_Int
, y
);
3130 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
3134 /* Handle some mouse motion while someone is dragging the scroll bar.
3136 This may be called from a signal handler, so we have to ignore GC
3139 x_scroll_bar_note_movement (bar
, event
)
3140 struct scroll_bar
*bar
;
3143 last_mouse_movement_time
= event
->xmotion
.time
;
3146 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
3148 /* If we're dragging the bar, display it. */
3149 if (! GC_NILP (bar
->dragging
))
3151 /* Where should the handle be now? */
3152 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3154 if (new_start
!= XINT (bar
->start
))
3156 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3158 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3162 /* Call XQueryPointer so we'll get an event the next time the mouse
3163 moves and we can see *still* on the same position. */
3167 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3168 (Window
*) &dummy
, (Window
*) &dummy
,
3169 &dummy
, &dummy
, &dummy
, &dummy
,
3170 (unsigned int *) &dummy
);
3174 /* Return information to the user about the current position of the mouse
3175 on the scroll bar. */
3177 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
3179 Lisp_Object
*bar_window
;
3180 enum scroll_bar_part
*part
;
3182 unsigned long *time
;
3184 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3186 Window dummy_window
;
3188 unsigned int dummy_mask
;
3192 /* Get the mouse's position relative to the scroll bar window, and
3194 if (! XQueryPointer (x_current_display
,
3195 SCROLL_BAR_X_WINDOW (bar
),
3197 /* Root, child, root x and root y. */
3198 &dummy_window
, &dummy_window
,
3199 &dummy_coord
, &dummy_coord
,
3201 /* Position relative to scroll bar. */
3204 /* Mouse buttons and modifier keys. */
3210 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3212 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3214 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3216 if (! NILP (bar
->dragging
))
3217 win_y
-= XINT (bar
->dragging
);
3221 if (win_y
> top_range
)
3224 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3225 *bar_window
= bar
->window
;
3227 if (! NILP (bar
->dragging
))
3228 *part
= scroll_bar_handle
;
3229 else if (win_y
< XINT (bar
->start
))
3230 *part
= scroll_bar_above_handle
;
3231 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3232 *part
= scroll_bar_handle
;
3234 *part
= scroll_bar_below_handle
;
3236 XSET (*x
, Lisp_Int
, win_y
);
3237 XSET (*y
, Lisp_Int
, top_range
);
3240 last_mouse_scroll_bar
= Qnil
;
3243 *time
= last_mouse_movement_time
;
3249 /* The screen has been cleared so we may have changed foreground or
3250 background colors, and the scroll bars may need to be redrawn.
3251 Clear out the scroll bars, and ask for expose events, so we can
3254 x_scroll_bar_clear (f
)
3259 for (bar
= FRAME_SCROLL_BARS (f
);
3260 XTYPE (bar
) == Lisp_Vector
;
3261 bar
= XSCROLL_BAR (bar
)->next
)
3262 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3266 /* This processes Expose events from the menubar specific X event
3267 loop in menubar.c. This allows to redisplay the frame if necessary
3268 when handling menubar or popup items. */
3271 process_expose_from_menu (event
)
3278 f
= x_window_to_frame (event
.xexpose
.window
);
3281 if (f
->async_visible
== 0)
3283 f
->async_visible
= 1;
3284 f
->async_iconified
= 0;
3285 SET_FRAME_GARBAGED (f
);
3289 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3290 event
.xexpose
.x
, event
.xexpose
.y
,
3291 event
.xexpose
.width
, event
.xexpose
.height
);
3296 struct scroll_bar
*bar
3297 = x_window_to_scroll_bar (event
.xexpose
.window
);
3300 x_scroll_bar_expose (bar
, &event
);
3307 /* The main X event-reading loop - XTread_socket. */
3309 /* Timestamp of enter window event. This is only used by XTread_socket,
3310 but we have to put it out here, since static variables within functions
3311 sometimes don't work. */
3312 static Time enter_timestamp
;
3314 /* This holds the state XLookupString needs to implement dead keys
3315 and other tricks known as "compose processing". _X Window System_
3316 says that a portable program can't use this, but Stephen Gildea assures
3317 me that letting the compiler initialize it to zeros will work okay.
3319 This must be defined outside of XTread_socket, for the same reasons
3320 given for enter_timestamp, above. */
3321 static XComposeStatus compose_status
;
3323 /* Communication with window managers. */
3324 Atom Xatom_wm_protocols
;
3326 /* Kinds of protocol things we may receive. */
3327 Atom Xatom_wm_take_focus
;
3328 Atom Xatom_wm_save_yourself
;
3329 Atom Xatom_wm_delete_window
;
3331 /* Other WM communication */
3332 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3333 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3335 /* Window manager communication. */
3336 Atom Xatom_wm_change_state
;
3338 /* EditRes protocol */
3339 Atom Xatom_editres_name
;
3341 /* Record the last 100 characters stored
3342 to help debug the loss-of-chars-during-GC problem. */
3344 short temp_buffer
[100];
3346 /* Read events coming from the X server.
3347 This routine is called by the SIGIO handler.
3348 We return as soon as there are no more events to be read.
3350 Events representing keys are stored in buffer BUFP,
3351 which can hold up to NUMCHARS characters.
3352 We return the number of characters stored into the buffer,
3353 thus pretending to be `read'.
3355 WAITP is nonzero if we should block until input arrives.
3356 EXPECTED is nonzero if the caller knows input is available. */
3359 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3361 register struct input_event
*bufp
;
3362 register int numchars
;
3369 int items_pending
; /* How many items are in the X queue. */
3372 int event_found
= 0;
3376 if (interrupt_input_blocked
)
3378 interrupt_input_pending
= 1;
3382 interrupt_input_pending
= 0;
3386 abort (); /* Don't think this happens. */
3389 /* If available, Xlib uses FIOSNBIO to make the socket
3390 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3391 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3392 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3393 fcntl (fileno (stdin
), F_SETFL
, 0);
3394 #endif /* ! defined (FIOSNBIO) */
3398 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3400 extern int read_alarm_should_throw
;
3401 read_alarm_should_throw
= 1;
3402 XPeekEvent (XDISPLAY
&event
);
3403 read_alarm_should_throw
= 0;
3405 #endif /* HAVE_SELECT */
3408 while (XStuffPending () != 0)
3410 XNextEvent (XDISPLAY
&event
);
3418 if (event
.xclient
.message_type
== Xatom_wm_protocols
3419 && event
.xclient
.format
== 32)
3421 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3423 f
= x_window_to_frame (event
.xclient
.window
);
3424 /* Since we set WM_TAKE_FOCUS, we must call
3425 XSetInputFocus explicitly. But not if f is null,
3426 since that might be an event for a deleted frame. */
3428 XSetInputFocus (event
.xclient
.display
,
3429 event
.xclient
.window
,
3430 RevertToPointerRoot
,
3431 event
.xclient
.data
.l
[1]);
3432 /* Not certain about handling scroll bars here */
3434 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3436 /* Save state modify the WM_COMMAND property to
3437 something which can reinstate us. This notifies
3438 the session manager, who's looking for such a
3439 PropertyNotify. Can restart processing when
3440 a keyboard or mouse event arrives. */
3445 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3447 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3454 bufp
->kind
= delete_window_event
;
3455 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3463 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3466 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3469 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3471 new_x
= event
.xclient
.data
.s
[0];
3472 new_y
= event
.xclient
.data
.s
[1];
3476 f
->display
.x
->left_pos
= new_x
;
3477 f
->display
.x
->top_pos
= new_y
;
3480 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3481 else if (event
.xclient
.message_type
== Xatom_editres_name
)
3483 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3484 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3486 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3490 case SelectionNotify
:
3491 #ifdef USE_X_TOOLKIT
3492 if (! x_window_to_frame (event
.xselection
.requestor
))
3494 #endif /* not USE_X_TOOLKIT */
3495 x_handle_selection_notify (&event
);
3498 case SelectionClear
: /* Someone has grabbed ownership. */
3499 #ifdef USE_X_TOOLKIT
3500 if (! x_window_to_frame (event
.xselectionclear
.window
))
3502 #endif /* USE_X_TOOLKIT */
3504 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3509 bufp
->kind
= selection_clear_event
;
3510 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3511 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3512 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3520 case SelectionRequest
: /* Someone wants our selection. */
3521 #ifdef USE_X_TOOLKIT
3522 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3524 #endif /* USE_X_TOOLKIT */
3526 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3531 bufp
->kind
= selection_request_event
;
3532 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3533 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3534 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3535 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3536 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3537 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3545 case PropertyNotify
:
3546 #ifdef USE_X_TOOLKIT
3547 if (!x_any_window_to_frame (event
.xproperty
.window
))
3549 #endif /* not USE_X_TOOLKIT */
3550 x_handle_property_notify (&event
);
3553 case ReparentNotify
:
3554 f
= x_top_window_to_frame (event
.xreparent
.window
);
3558 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3559 x_real_positions (f
, &x
, &y
);
3560 f
->display
.x
->left_pos
= x
;
3561 f
->display
.x
->top_pos
= y
;
3566 f
= x_window_to_frame (event
.xexpose
.window
);
3569 if (f
->async_visible
== 0)
3571 f
->async_visible
= 1;
3572 f
->async_iconified
= 0;
3573 SET_FRAME_GARBAGED (f
);
3576 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3577 event
.xexpose
.x
, event
.xexpose
.y
,
3578 event
.xexpose
.width
, event
.xexpose
.height
);
3582 struct scroll_bar
*bar
3583 = x_window_to_scroll_bar (event
.xexpose
.window
);
3586 x_scroll_bar_expose (bar
, &event
);
3587 #ifdef USE_X_TOOLKIT
3590 #endif /* USE_X_TOOLKIT */
3594 case GraphicsExpose
: /* This occurs when an XCopyArea's
3595 source area was obscured or not
3597 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3601 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3602 event
.xgraphicsexpose
.width
,
3603 event
.xgraphicsexpose
.height
);
3605 #ifdef USE_X_TOOLKIT
3608 #endif /* USE_X_TOOLKIT */
3611 case NoExpose
: /* This occurs when an XCopyArea's
3612 source area was completely
3615 #else /* ! defined (HAVE_X11) */
3617 if (event
.subwindow
!= 0)
3618 break; /* duplicate event */
3619 f
= x_window_to_frame (event
.window
);
3620 if (event
.window
== f
->display
.x
->icon_desc
)
3623 f
->async_iconified
= 1;
3625 if (event
.window
== FRAME_X_WINDOW (f
))
3627 /* Say must check all windows' needs_exposure flags. */
3628 expose_all_windows
= 1;
3629 f
->display
.x
->needs_exposure
= 1;
3630 f
->async_visible
= 1;
3635 if (event
.subwindow
!= 0)
3636 break; /* duplicate event */
3637 f
= x_window_to_frame (event
.window
);
3638 if (event
.window
== f
->display
.x
->icon_desc
)
3643 /* If window already needs full redraw, ignore this rectangle. */
3644 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3646 /* Put the event on the queue of rectangles to redraw. */
3647 if (enqueue_event (&event
, &x_expose_queue
))
3648 /* If it is full, we can't record the rectangle,
3649 so redraw this entire window. */
3651 /* Say must check all windows' needs_exposure flags. */
3652 expose_all_windows
= 1;
3653 f
->display
.x
->needs_exposure
= 1;
3658 /* This should happen only when we are expecting it,
3659 in x_read_exposes. */
3661 #endif /* ! defined (HAVE_X11) */
3665 f
= x_any_window_to_frame (event
.xunmap
.window
);
3666 if (f
) /* F may no longer exist if
3667 the frame was deleted. */
3669 /* While a frame is unmapped, display generation is
3670 disabled; you don't want to spend time updating a
3671 display that won't ever be seen. */
3672 f
->async_visible
= 0;
3673 /* We can't distinguish, from the event, whether the window
3674 has become iconified or invisible. So assume, if it
3675 was previously visible, than now it is iconified.
3676 We depend on x_make_frame_invisible to mark it iconified. */
3677 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3678 f
->async_iconified
= 1;
3680 #ifdef USE_X_TOOLKIT
3682 #endif /* USE_X_TOOLKIT */
3686 /* We use x_top_window_to_frame because map events can come
3687 for subwindows and they don't mean that the frame is visible. */
3688 f
= x_top_window_to_frame (event
.xmap
.window
);
3691 f
->async_visible
= 1;
3692 f
->async_iconified
= 0;
3694 /* wait_reading_process_input will notice this and update
3695 the frame's display structures. */
3696 SET_FRAME_GARBAGED (f
);
3698 #ifdef USE_X_TOOLKIT
3700 #endif /* USE_X_TOOLKIT */
3703 /* Turn off processing if we become fully obscured. */
3704 case VisibilityNotify
:
3707 #else /* ! defined (HAVE_X11) */
3709 f
= x_window_to_frame (event
.window
);
3710 if (event
.window
== f
->display
.x
->icon_desc
)
3711 f
->async_iconified
= 0;
3712 if (event
.window
== FRAME_X_WINDOW (f
))
3713 f
->async_visible
= 0;
3715 #endif /* ! defined (HAVE_X11) */
3719 f
= x_any_window_to_frame (event
.xkey
.window
);
3723 KeySym keysym
, orig_keysym
;
3724 /* al%imercury@uunet.uu.net says that making this 81 instead of
3725 80 fixed a bug whereby meta chars made his Emacs hang. */
3726 unsigned char copy_buffer
[81];
3730 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3731 modifiers
= event
.xkey
.state
;
3733 /* This will have to go some day... */
3735 /* make_lispy_event turns chars into control chars.
3736 Don't do it here because XLookupString is too eager. */
3737 event
.xkey
.state
&= ~ControlMask
;
3739 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3742 orig_keysym
= keysym
;
3746 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3747 || keysym
== XK_Delete
3748 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3749 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3751 /* This recognizes the "extended function keys".
3752 It seems there's no cleaner way.
3753 Test IsModifierKey to avoid handling mode_switch
3755 || ((unsigned) (keysym
) >= XK_Select
3756 && (unsigned)(keysym
) < XK_KP_Space
)
3758 #ifdef XK_dead_circumflex
3759 || orig_keysym
== XK_dead_circumflex
3761 #ifdef XK_dead_grave
3762 || orig_keysym
== XK_dead_grave
3764 #ifdef XK_dead_tilde
3765 || orig_keysym
== XK_dead_tilde
3767 #ifdef XK_dead_diaeresis
3768 || orig_keysym
== XK_dead_diaeresis
3770 #ifdef XK_dead_macron
3771 || orig_keysym
== XK_dead_macron
3773 #ifdef XK_dead_degree
3774 || orig_keysym
== XK_dead_degree
3776 #ifdef XK_dead_acute
3777 || orig_keysym
== XK_dead_acute
3779 #ifdef XK_dead_cedilla
3780 || orig_keysym
== XK_dead_cedilla
3782 #ifdef XK_dead_breve
3783 || orig_keysym
== XK_dead_breve
3785 #ifdef XK_dead_ogonek
3786 || orig_keysym
== XK_dead_ogonek
3788 #ifdef XK_dead_caron
3789 || orig_keysym
== XK_dead_caron
3791 #ifdef XK_dead_doubleacute
3792 || orig_keysym
== XK_dead_doubleacute
3794 #ifdef XK_dead_abovedot
3795 || orig_keysym
== XK_dead_abovedot
3797 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3798 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3799 /* Any "vendor-specific" key is ok. */
3800 || (orig_keysym
& (1 << 28)))
3801 && ! (IsModifierKey (orig_keysym
)
3803 #ifdef XK_Mode_switch
3804 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3807 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3809 #endif /* not HAVE_X11R5 */
3812 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3814 temp_buffer
[temp_index
++] = keysym
;
3815 bufp
->kind
= non_ascii_keystroke
;
3816 bufp
->code
= keysym
;
3817 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3818 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3819 bufp
->timestamp
= event
.xkey
.time
;
3824 else if (numchars
> nbytes
)
3828 for (i
= 0; i
< nbytes
; i
++)
3830 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3832 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3833 bufp
->kind
= ascii_keystroke
;
3834 bufp
->code
= copy_buffer
[i
];
3835 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3836 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3837 bufp
->timestamp
= event
.xkey
.time
;
3851 #else /* ! defined (HAVE_X11) */
3854 register char *where_mapping
;
3856 f
= x_window_to_frame (event
.window
);
3857 /* Ignore keys typed on icon windows. */
3858 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3860 where_mapping
= XLookupMapping (&event
, &nbytes
);
3861 /* Nasty fix for arrow keys */
3862 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3864 switch (event
.detail
& 0xff)
3866 case KC_CURSOR_LEFT
:
3867 where_mapping
= "\002";
3869 case KC_CURSOR_RIGHT
:
3870 where_mapping
= "\006";
3873 where_mapping
= "\020";
3875 case KC_CURSOR_DOWN
:
3876 where_mapping
= "\016";
3881 if (numchars
- nbytes
> 0)
3885 for (i
= 0; i
< nbytes
; i
++)
3887 bufp
->kind
= ascii_keystroke
;
3888 bufp
->code
= where_mapping
[i
];
3889 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3890 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3898 #endif /* ! defined (HAVE_X11) */
3902 /* Here's a possible interpretation of the whole
3903 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3904 FocusIn event, you have to get a FocusOut event before you
3905 relinquish the focus. If you haven't received a FocusIn event,
3906 then a mere LeaveNotify is enough to free you. */
3909 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3911 if (event
.xcrossing
.focus
) /* Entered Window */
3913 /* Avoid nasty pop/raise loops. */
3914 if (f
&& (!(f
->auto_raise
)
3916 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3918 x_new_focus_frame (f
);
3919 enter_timestamp
= event
.xcrossing
.time
;
3922 else if (f
== x_focus_frame
)
3923 x_new_focus_frame (0);
3924 /* EnterNotify counts as mouse movement,
3925 so update things that depend on mouse position. */
3927 note_mouse_movement (f
, &event
.xmotion
);
3928 #ifdef USE_X_TOOLKIT
3930 #endif /* USE_X_TOOLKIT */
3934 f
= x_any_window_to_frame (event
.xfocus
.window
);
3935 if (event
.xfocus
.detail
!= NotifyPointer
)
3936 x_focus_event_frame
= f
;
3938 x_new_focus_frame (f
);
3939 #ifdef USE_X_TOOLKIT
3941 #endif /* USE_X_TOOLKIT */
3946 f
= x_top_window_to_frame (event
.xcrossing
.window
);
3949 if (f
== mouse_face_mouse_frame
)
3950 /* If we move outside the frame,
3951 then we're certainly no longer on any text in the frame. */
3952 clear_mouse_face ();
3954 if (event
.xcrossing
.focus
)
3956 if (! x_focus_event_frame
)
3957 x_new_focus_frame (0);
3959 x_new_focus_frame (f
);
3963 if (f
== x_focus_event_frame
)
3964 x_focus_event_frame
= 0;
3965 if (f
== x_focus_frame
)
3966 x_new_focus_frame (0);
3969 #ifdef USE_X_TOOLKIT
3971 #endif /* USE_X_TOOLKIT */
3975 f
= x_any_window_to_frame (event
.xfocus
.window
);
3976 if (event
.xfocus
.detail
!= NotifyPointer
3977 && f
== x_focus_event_frame
)
3978 x_focus_event_frame
= 0;
3979 if (f
&& f
== x_focus_frame
)
3980 x_new_focus_frame (0);
3981 #ifdef USE_X_TOOLKIT
3983 #endif /* USE_X_TOOLKIT */
3986 #else /* ! defined (HAVE_X11) */
3989 if ((event
.detail
& 0xFF) == 1)
3990 break; /* Coming from our own subwindow */
3991 if (event
.subwindow
!= 0)
3992 break; /* Entering our own subwindow. */
3995 f
= x_window_to_frame (event
.window
);
3998 x_new_focus_frame (f
);
4003 if ((event
.detail
& 0xFF) == 1)
4004 break; /* Entering our own subwindow */
4005 if (event
.subwindow
!= 0)
4006 break; /* Leaving our own subwindow. */
4009 if (x_focus_frame
== 0
4010 && x_input_frame
!= 0
4011 && x_input_frame
== x_window_to_frame (event
.window
)
4012 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
4017 frame_unhighlight (f
);
4020 #endif /* ! defined (HAVE_X11) */
4025 if (x_mouse_grabbed
&& FRAME_LIVE_P (last_mouse_frame
))
4026 f
= last_mouse_frame
;
4028 f
= x_window_to_frame (event
.xmotion
.window
);
4030 note_mouse_movement (f
, &event
.xmotion
);
4033 struct scroll_bar
*bar
4034 = x_window_to_scroll_bar (event
.xmotion
.window
);
4037 x_scroll_bar_note_movement (bar
, &event
);
4039 /* If we move outside the frame,
4040 then we're certainly no longer on any text in the frame. */
4041 clear_mouse_face ();
4044 #if 0 /* This should be unnecessary, since the toolkit has no use
4045 for motion events that happen outside of the menu event loop,
4046 and it seems to cause the bug that mouse events stop coming
4048 #ifdef USE_X_TOOLKIT
4050 #endif /* USE_X_TOOLKIT */
4054 case ConfigureNotify
:
4055 f
= x_any_window_to_frame (event
.xconfigure
.window
);
4056 #ifdef USE_X_TOOLKIT
4059 && ! event
.xconfigure
.send_event
4061 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
4066 /* Find the position of the outside upper-left corner of
4067 the window, in the root coordinate system. Don't
4068 refer to the parent window here; we may be processing
4069 this event after the window manager has changed our
4070 parent, but before we have reached the ReparentNotify. */
4071 XTranslateCoordinates (x_current_display
,
4073 /* From-window, to-window. */
4074 XtWindow (f
->display
.x
->widget
),
4077 /* From-position, to-position. */
4078 -event
.xconfigure
.border_width
,
4079 -event
.xconfigure
.border_width
,
4084 event
.xconfigure
.x
= win_x
;
4085 event
.xconfigure
.y
= win_y
;
4087 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4088 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4089 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4090 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4092 /* What we have now is the position of Emacs's own window.
4093 Convert that to the position of the window manager window. */
4096 x_real_positions (f
, &x
, &y
);
4097 f
->display
.x
->left_pos
= x
;
4098 f
->display
.x
->top_pos
= y
;
4102 #else /* not USE_X_TOOLKIT */
4105 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4106 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4108 /* Even if the number of character rows and columns has
4109 not changed, the font size may have changed, so we need
4110 to check the pixel dimensions as well. */
4111 if (columns
!= f
->width
4112 || rows
!= f
->height
4113 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
4114 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
4116 change_frame_size (f
, rows
, columns
, 0, 1);
4117 SET_FRAME_GARBAGED (f
);
4120 if (! event
.xconfigure
.send_event
)
4125 /* Find the position of the outside upper-left corner of
4126 the window, in the root coordinate system. Don't
4127 refer to the parent window here; we may be processing
4128 this event after the window manager has changed our
4129 parent, but before we have reached the ReparentNotify. */
4130 XTranslateCoordinates (x_current_display
,
4132 /* From-window, to-window. */
4133 f
->display
.x
->window_desc
,
4136 /* From-position, to-position. */
4137 -event
.xconfigure
.border_width
,
4138 -event
.xconfigure
.border_width
,
4143 event
.xconfigure
.x
= win_x
;
4144 event
.xconfigure
.y
= win_y
;
4147 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4148 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4149 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4150 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4152 /* What we have now is the position of Emacs's own window.
4153 Convert that to the position of the window manager window. */
4156 x_real_positions (f
, &x
, &y
);
4157 f
->display
.x
->left_pos
= x
;
4158 f
->display
.x
->top_pos
= y
;
4159 if (y
!= event
.xconfigure
.y
)
4161 /* Since the WM decorations come below top_pos now,
4162 we must put them below top_pos in the future. */
4163 f
->display
.x
->win_gravity
= NorthWestGravity
;
4164 x_wm_set_size_hint (f
, 0, 0);
4168 #endif /* not USE_X_TOOLKIT */
4174 /* If we decide we want to generate an event to be seen
4175 by the rest of Emacs, we put it here. */
4176 struct input_event emacs_event
;
4177 emacs_event
.kind
= no_event
;
4179 bzero (&compose_status
, sizeof (compose_status
));
4181 f
= x_window_to_frame (event
.xbutton
.window
);
4184 if (!x_focus_frame
|| (f
== x_focus_frame
))
4185 construct_mouse_click (&emacs_event
, &event
, f
);
4189 struct scroll_bar
*bar
=
4190 x_window_to_scroll_bar (event
.xbutton
.window
);
4193 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4194 #ifdef USE_X_TOOLKIT
4197 f
= x_any_window_to_frame (event
.xbutton
.window
);
4198 if (f
&& event
.type
== ButtonPress
)
4199 construct_menu_click (&emacs_event
,
4202 #endif /* USE_X_TOOLKIT */
4205 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4207 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4213 #ifdef USE_X_TOOLKIT
4215 #endif /* USE_X_TOOLKIT */
4219 #else /* ! defined (HAVE_X11) */
4221 case ButtonReleased
:
4222 f
= x_window_to_frame (event
.window
);
4225 if (event
.window
== f
->display
.x
->icon_desc
)
4227 x_make_frame_visible (f
);
4229 if (warp_mouse_on_deiconify
)
4230 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
4233 if (event
.window
== FRAME_X_WINDOW (f
))
4239 enqueue_event (&event
, &x_mouse_queue
);
4242 bufp
->kind
= ascii_keystroke
;
4243 bufp
->code
= 'X' & 037; /* C-x */
4244 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4245 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4248 bufp
->kind
= ascii_keystroke
;
4249 bufp
->code
= 0; /* C-@ */
4250 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4251 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4258 #endif /* ! defined (HAVE_X11) */
4262 case CirculateNotify
:
4264 case CirculateRequest
:
4267 #endif /* ! defined (HAVE_X11) */
4270 /* Someone has changed the keyboard mapping - update the
4272 switch (event
.xmapping
.request
)
4274 case MappingModifier
:
4275 x_find_modifier_meanings ();
4276 /* This is meant to fall through. */
4277 case MappingKeyboard
:
4278 XRefreshKeyboardMapping (&event
.xmapping
);
4280 #ifdef USE_X_TOOLKIT
4282 #endif /* USE_X_TOOLKIT */
4286 #ifdef USE_X_TOOLKIT
4289 XtDispatchEvent (&event
);
4291 #endif /* USE_X_TOOLKIT */
4298 /* On some systems, an X bug causes Emacs to get no more events
4299 when the window is destroyed. Detect that. (1994.) */
4300 XNoOp (x_current_display
);
4301 #endif /* X_IO_BUG */
4303 #if 0 /* This fails for serial-line connections to the X server,
4304 because the characters arrive one by one, and a partial
4305 command makes select return but gives nothing to read.
4306 We'll have to hope that the bug that this tried to fix
4307 in 1988 has been fixed in Xlib or the X server. */
4309 if (expected
&& ! event_found
)
4311 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4312 there is an EOF condition; in other words, that X has died.
4313 Act as if there had been a hangup. */
4314 int fd
= ConnectionNumber (x_current_display
);
4315 SELECT_TYPE mask
, junk1
, junk2
;
4320 EMACS_SET_SECS_USECS (timeout
, 0, 0);
4323 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
4324 && !XStuffPending ())
4325 kill (getpid (), SIGHUP
);
4327 #endif /* HAVE_SELECT */
4331 if (updating_frame
== 0)
4332 x_do_pending_expose ();
4335 /* If the focus was just given to an autoraising frame,
4338 if (pending_autoraise_frame
)
4340 x_raise_frame (pending_autoraise_frame
);
4341 pending_autoraise_frame
= 0;
4350 /* Read and process only Expose events
4351 until we get an ExposeCopy event; then return.
4352 This is used in insert/delete line.
4353 We assume input is already blocked. */
4359 XKeyPressedEvent event
;
4363 /* while there are more events*/
4364 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
4368 if (event
.subwindow
!= 0)
4369 break; /* duplicate event */
4370 f
= x_window_to_frame (event
.window
);
4371 if (event
.window
== f
->display
.x
->icon_desc
)
4376 if (event
.window
== FRAME_X_WINDOW (f
))
4378 expose_all_windows
= 1;
4379 f
->display
.x
->needs_exposure
= 1;
4385 if (event
.subwindow
!= 0)
4386 break; /* duplicate event */
4387 f
= x_window_to_frame (event
.window
);
4388 if (event
.window
== f
->display
.x
->icon_desc
)
4393 /* If window already needs full redraw, ignore this rectangle. */
4394 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
4396 /* Put the event on the queue of rectangles to redraw. */
4397 if (enqueue_event (&event
, &x_expose_queue
))
4398 /* If it is full, we can't record the rectangle,
4399 so redraw this entire window. */
4401 /* Say must check all windows' needs_exposure flags. */
4402 expose_all_windows
= 1;
4403 f
->display
.x
->needs_exposure
= 1;
4412 #endif /* HAVE_X11 */
4415 /* Drawing the cursor. */
4418 /* Draw a hollow box cursor. Don't change the inside of the box. */
4424 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
4425 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
4426 int width
= FONT_WIDTH (f
->display
.x
->font
);
4427 int height
= f
->display
.x
->line_height
;
4430 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4431 f
->display
.x
->cursor_gc
,
4432 left
, top
, width
- 1, height
- 1);
4433 #else /* ! defined (HAVE_X11) */
4434 XPixSet (FRAME_X_WINDOW (f
),
4435 left
, top
, width
, 1,
4436 f
->display
.x
->cursor_pixel
);
4438 XPixSet (FRAME_X_WINDOW (f
),
4439 left
, top
, 1, height
,
4440 f
->display
.x
->cursor_pixel
);
4442 XPixSet (FRAME_X_WINDOW (f
),
4443 left
+width
-1, top
, 1, height
,
4444 f
->display
.x
->cursor_pixel
);
4446 XPixSet (FRAME_X_WINDOW (f
),
4447 left
, top
+height
-1, width
, 1,
4448 f
->display
.x
->cursor_pixel
);
4449 #endif /* ! defined (HAVE_X11) */
4452 /* Clear the cursor of frame F to background color,
4453 and mark the cursor as not shown.
4454 This is used when the text where the cursor is
4455 is about to be rewritten. */
4463 if (! FRAME_VISIBLE_P (f
)
4464 || f
->phys_cursor_x
< 0)
4468 x_display_cursor (f
, 0);
4469 #else /* ! defined (HAVE_X11) */
4470 XPixSet (FRAME_X_WINDOW (f
),
4471 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4472 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4473 FONT_WIDTH (f
->display
.x
->font
), f
->display
.x
->line_height
,
4474 f
->display
.x
->background_pixel
);
4475 #endif /* ! defined (HAVE_X11) */
4476 f
->phys_cursor_x
= -1;
4479 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4480 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4484 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4491 CHAR_TO_PIXEL_COL (f
, column
),
4492 CHAR_TO_PIXEL_ROW (f
, row
),
4493 &glyph
, 1, highlight
, 0);
4497 x_display_bar_cursor (f
, on
)
4501 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4503 /* This is pointless on invisible frames, and dangerous on garbaged
4504 frames; in the latter case, the frame may be in the midst of
4505 changing its size, and curs_x and curs_y may be off the frame. */
4506 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4509 if (! on
&& f
->phys_cursor_x
< 0)
4512 /* If we're not updating, then we want to use the current frame's
4513 cursor position, not our local idea of where the cursor ought to be. */
4514 if (f
!= updating_frame
)
4516 curs_x
= FRAME_CURSOR_X (f
);
4517 curs_y
= FRAME_CURSOR_Y (f
);
4520 /* If there is anything wrong with the current cursor state, remove it. */
4521 if (f
->phys_cursor_x
>= 0
4523 || f
->phys_cursor_x
!= curs_x
4524 || f
->phys_cursor_y
!= curs_y
4525 || f
->display
.x
->current_cursor
!= bar_cursor
))
4527 /* Erase the cursor by redrawing the character underneath it. */
4528 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4529 f
->phys_cursor_glyph
,
4530 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4531 f
->phys_cursor_x
= -1;
4534 /* If we now need a cursor in the new place or in the new form, do it so. */
4536 && (f
->phys_cursor_x
< 0
4537 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4539 f
->phys_cursor_glyph
4540 = ((current_glyphs
->enable
[curs_y
]
4541 && curs_x
< current_glyphs
->used
[curs_y
])
4542 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4544 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4545 f
->display
.x
->cursor_gc
,
4546 CHAR_TO_PIXEL_COL (f
, curs_x
),
4547 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4548 1, f
->display
.x
->line_height
);
4550 f
->phys_cursor_x
= curs_x
;
4551 f
->phys_cursor_y
= curs_y
;
4553 f
->display
.x
->current_cursor
= bar_cursor
;
4556 if (updating_frame
!= f
)
4561 /* Turn the displayed cursor of frame F on or off according to ON.
4562 If ON is nonzero, where to put the cursor is specified
4563 by F->cursor_x and F->cursor_y. */
4566 x_display_box_cursor (f
, on
)
4570 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4572 /* This is pointless on invisible frames, and dangerous on garbaged
4573 frames; in the latter case, the frame may be in the midst of
4574 changing its size, and curs_x and curs_y may be off the frame. */
4575 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4578 /* If cursor is off and we want it off, return quickly. */
4579 if (!on
&& f
->phys_cursor_x
< 0)
4582 /* If we're not updating, then we want to use the current frame's
4583 cursor position, not our local idea of where the cursor ought to be. */
4584 if (f
!= updating_frame
)
4586 curs_x
= FRAME_CURSOR_X (f
);
4587 curs_y
= FRAME_CURSOR_Y (f
);
4590 /* If cursor is currently being shown and we don't want it to be
4591 or it is in the wrong place,
4592 or we want a hollow box and it's not so, (pout!)
4594 if (f
->phys_cursor_x
>= 0
4596 || f
->phys_cursor_x
!= curs_x
4597 || f
->phys_cursor_y
!= curs_y
4598 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4599 && (f
!= x_highlight_frame
))))
4601 int mouse_face_here
= 0;
4603 /* If the cursor is in the mouse face area, redisplay that when
4604 we clear the cursor. */
4605 if (f
== mouse_face_mouse_frame
4607 (f
->phys_cursor_y
> mouse_face_beg_row
4608 || (f
->phys_cursor_y
== mouse_face_beg_row
4609 && f
->phys_cursor_x
>= mouse_face_beg_col
))
4611 (f
->phys_cursor_y
< mouse_face_end_row
4612 || (f
->phys_cursor_y
== mouse_face_end_row
4613 && f
->phys_cursor_x
< mouse_face_end_col
)))
4614 mouse_face_here
= 1;
4616 /* If the font is not as tall as a whole line,
4617 we must explicitly clear the line's whole height. */
4618 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4619 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
4620 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4621 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4622 FONT_WIDTH (f
->display
.x
->font
),
4623 f
->display
.x
->line_height
, False
);
4624 /* Erase the cursor by redrawing the character underneath it. */
4625 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4626 f
->phys_cursor_glyph
,
4629 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4630 f
->phys_cursor_x
= -1;
4633 /* If we want to show a cursor,
4634 or we want a box cursor and it's not so,
4635 write it in the right place. */
4637 && (f
->phys_cursor_x
< 0
4638 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4639 && f
== x_highlight_frame
)))
4641 f
->phys_cursor_glyph
4642 = ((current_glyphs
->enable
[curs_y
]
4643 && curs_x
< current_glyphs
->used
[curs_y
])
4644 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4646 if (f
!= x_highlight_frame
)
4649 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4653 x_draw_single_glyph (f
, curs_y
, curs_x
,
4654 f
->phys_cursor_glyph
, 2);
4655 f
->display
.x
->current_cursor
= filled_box_cursor
;
4658 f
->phys_cursor_x
= curs_x
;
4659 f
->phys_cursor_y
= curs_y
;
4662 if (updating_frame
!= f
)
4666 x_display_cursor (f
, on
)
4672 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4673 x_display_box_cursor (f
, on
);
4674 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4675 x_display_bar_cursor (f
, on
);
4677 /* Those are the only two we have implemented! */
4685 /* Refresh bitmap kitchen sink icon for frame F
4686 when we get an expose event for it. */
4692 /* Normally, the window manager handles this function. */
4693 #else /* ! defined (HAVE_X11) */
4696 if (f
->display
.x
->icon_bitmap_flag
)
4697 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
4698 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
4699 icon_bitmap
, GXcopy
, AllPlanes
);
4702 extern struct frame
*selected_frame
;
4703 struct Lisp_String
*str
;
4704 unsigned char *string
;
4707 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
4709 if (f
->display
.x
->icon_label
!= string
)
4711 f
->display
.x
->icon_label
= string
;
4712 XChangeWindow (f
->display
.x
->icon_desc
,
4713 XQueryWidth (string
, icon_font_info
->id
) + 10,
4714 icon_font_info
->height
+ 10);
4717 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4718 str
->size
, icon_font_info
->id
,
4719 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4722 #endif /* ! defined (HAVE_X11) */
4725 /* Make the x-window of frame F use the gnu icon bitmap. */
4734 if (FRAME_X_WINDOW (f
) == 0)
4740 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4741 gnu_bits
, gnu_width
, gnu_height
);
4742 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4743 f
->display
.x
->icon_bitmap_flag
= 1;
4744 #else /* ! defined (HAVE_X11) */
4745 if (f
->display
.x
->icon_desc
)
4747 XClearIconWindow (FRAME_X_WINDOW (f
));
4748 XDestroyWindow (f
->display
.x
->icon_desc
);
4751 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4752 0, 0, sink_width
, sink_height
,
4753 2, WhitePixmap
, (Pixmap
) NULL
);
4755 if (icon_window
== 0)
4758 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4759 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4761 f
->display
.x
->icon_desc
= icon_window
;
4762 f
->display
.x
->icon_bitmap_flag
= 1;
4764 if (icon_bitmap
== 0)
4766 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4767 #endif /* ! defined (HAVE_X11) */
4773 /* Make the x-window of frame F use a rectangle with text. */
4776 x_text_icon (f
, icon_name
)
4784 char *X_DefaultValue
;
4788 #define WhitePixel 1
4789 #endif /* WhitePixel */
4792 #define BlackPixel 0
4793 #endif /* BlackPixel */
4794 #endif /* HAVE_X11 */
4796 if (FRAME_X_WINDOW (f
) == 0)
4801 f
->display
.x
->icon_label
= icon_name
;
4803 if (! f
->display
.x
->icon_label
)
4804 f
->display
.x
->icon_label
= " *emacs* ";
4807 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4808 (char *) f
->display
.x
->icon_label
);
4811 f
->display
.x
->icon_bitmap_flag
= 0;
4812 x_wm_set_icon_pixmap (f
, 0);
4813 #else /* ! defined (HAVE_X11) */
4814 if (icon_font_info
== 0)
4816 = XGetFont (XGetDefault (XDISPLAY
4817 (char *) XSTRING (Vinvocation_name
)->data
,
4820 if (f
->display
.x
->icon_desc
)
4822 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4823 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4827 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4829 if (! f
->display
.x
->icon_label
)
4830 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4832 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4833 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4834 f
->display
.x
->left_pos
,
4835 f
->display
.x
->top_pos
,
4836 width
+ 10, icon_font_info
->height
+ 10,
4837 2, BlackPixmap
, WhitePixmap
);
4839 if (icon_window
== 0)
4842 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4843 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4845 f
->display
.x
->icon_desc
= icon_window
;
4846 f
->display
.x
->icon_bitmap_flag
= 0;
4847 f
->display
.x
->icon_label
= 0;
4848 #endif /* ! defined (HAVE_X11) */
4853 /* Handling X errors. */
4855 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4856 X server's connection, or an error reported via the X protocol. */
4859 x_connection_closed ()
4864 shut_down_emacs (0, 1, Qnil
);
4869 /* An X error handler which prints an error message and then kills
4870 Emacs. This is what's normally installed as Xlib's handler for
4873 x_error_quitter (display
, error
)
4879 /* Note that there is no real way portable across R3/R4 to get the
4880 original error handler. */
4882 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4883 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4884 buf
, error
->request_code
);
4887 /* While we're testing Emacs 19, we'll just dump core whenever we
4888 get an X error, so we can figure out why it happened. */
4892 x_connection_closed ();
4895 /* A handler for X IO errors which prints an error message and then
4896 kills Emacs. This is what is always installed as Xlib's handler
4899 x_io_error_quitter (display
)
4902 fprintf (stderr
, "Connection to X server %s lost.\n",
4903 XDisplayName (DisplayString (display
)));
4906 /* While we're testing Emacs 19, we'll just dump core whenever we
4907 get an X error, so we can figure out why it happened. */
4911 x_connection_closed ();
4914 /* A buffer for storing X error messages. */
4915 static char *x_caught_error_message
;
4916 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4918 /* An X error handler which stores the error message in
4919 x_caught_error_message. This is what's installed when
4920 x_catch_errors is in effect. */
4922 x_error_catcher (display
, error
)
4926 XGetErrorText (display
, error
->error_code
,
4927 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4931 /* Begin trapping X errors.
4933 After calling this function, X protocol errors no longer cause
4934 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4936 Calling x_check_errors signals an Emacs error if an X error has
4937 occurred since the last call to x_catch_errors or x_check_errors.
4939 Calling x_uncatch_errors resumes the normal error handling. */
4941 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4946 /* Make sure any errors from previous requests have been dealt with. */
4947 XSync (x_current_display
, False
);
4949 /* Set up the error buffer. */
4950 x_caught_error_message
4951 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4952 x_caught_error_message
[0] = '\0';
4954 /* Install our little error handler. */
4955 XHandleError (x_error_catcher
);
4958 /* If any X protocol errors have arrived since the last call to
4959 x_catch_errors or x_check_errors, signal an Emacs error using
4960 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4963 x_check_errors (format
)
4966 /* Make sure to catch any errors incurred so far. */
4967 XSync (x_current_display
, False
);
4969 if (x_caught_error_message
[0])
4971 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4973 sprintf (buf
, format
, x_caught_error_message
);
4974 x_uncatch_errors ();
4979 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4984 /* Make sure to catch any errors incurred so far. */
4985 XSync (x_current_display
, False
);
4987 return x_caught_error_message
[0] != 0;
4990 /* Stop catching X protocol errors and let them make Emacs die. */
4995 xfree (x_caught_error_message
);
4996 x_caught_error_message
= 0;
4997 XHandleError (x_error_quitter
);
5001 static unsigned int x_wire_count
;
5004 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5009 /* Changing the font of the frame. */
5011 /* Set the font of the x-window specified by frame F
5012 to the font named NEWNAME. This is safe to use
5013 even before F has an actual x-window. */
5023 /* A table of all the fonts we have already loaded. */
5024 static struct font_info
*x_font_table
;
5026 /* The current capacity of x_font_table. */
5027 static int x_font_table_size
;
5029 /* The number of fonts actually stored in x_font_table.
5030 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
5031 0 <= n_fonts <= x_font_table_size. */
5035 x_new_font (f
, fontname
)
5037 register char *fontname
;
5040 int n_matching_fonts
;
5041 XFontStruct
*font_info
;
5044 /* Get a list of all the fonts that match this name. Once we
5045 have a list of matching fonts, we compare them against the fonts
5046 we already have by comparing font ids. */
5047 font_names
= (char **) XListFonts (x_current_display
, fontname
,
5048 1024, &n_matching_fonts
);
5049 /* Apparently it doesn't set n_matching_fonts to zero when it can't
5050 find any matches; font_names == 0 is the only clue. */
5052 n_matching_fonts
= 0;
5054 /* Don't just give up if n_matching_fonts is 0.
5055 Apparently there's a bug on Suns: XListFontsWithInfo can
5056 fail to find a font, but XLoadQueryFont may still find it. */
5058 /* See if we've already loaded a matching font. */
5059 already_loaded
= -1;
5060 if (n_matching_fonts
!= 0)
5064 for (i
= 0; i
< n_fonts
; i
++)
5065 for (j
= 0; j
< n_matching_fonts
; j
++)
5066 if (!strcmp (x_font_table
[i
].name
, font_names
[j
]))
5069 fontname
= font_names
[j
];
5075 /* If we have, just return it from the table. */
5076 if (already_loaded
>= 0)
5077 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
5079 /* Otherwise, load the font and add it to the table. */
5085 /* Try to find a character-cell font in the list. */
5087 /* A laudable goal, but this isn't how to do it. */
5088 for (i
= 0; i
< n_matching_fonts
; i
++)
5089 if (! font_info
[i
].per_char
)
5095 /* See comment above. */
5096 if (n_matching_fonts
!= 0)
5097 fontname
= font_names
[i
];
5099 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
5102 /* Free the information from XListFonts. */
5103 if (n_matching_fonts
)
5104 XFreeFontNames (font_names
);
5108 /* Do we need to create the table? */
5109 if (x_font_table_size
== 0)
5111 x_font_table_size
= 16;
5113 = (struct font_info
*) xmalloc (x_font_table_size
5114 * sizeof (x_font_table
[0]));
5116 /* Do we need to grow the table? */
5117 else if (n_fonts
>= x_font_table_size
)
5119 x_font_table_size
*= 2;
5121 = (struct font_info
*) xrealloc (x_font_table
,
5123 * sizeof (x_font_table
[0])));
5126 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
5127 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
5128 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
5131 /* Now make the frame display the given font. */
5132 if (FRAME_X_WINDOW (f
) != 0)
5134 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
5135 f
->display
.x
->font
->fid
);
5136 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
5137 f
->display
.x
->font
->fid
);
5138 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
5139 f
->display
.x
->font
->fid
);
5141 frame_update_line_height (f
);
5142 x_set_window_size (f
, 0, f
->width
, f
->height
);
5145 /* If we are setting a new frame's font for the first time,
5146 there are no faces yet, so this font's height is the line height. */
5147 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
5150 Lisp_Object lispy_name
;
5152 lispy_name
= build_string (fontname
);
5154 /* Free the information from XListFonts. The data
5155 we actually retain comes from XLoadQueryFont. */
5156 XFreeFontNames (font_names
);
5161 #else /* ! defined (HAVE_X11) */
5162 x_new_font (f
, newname
)
5164 register char *newname
;
5169 temp
= XGetFont (newname
);
5170 if (temp
== (FONT_TYPE
*) 0)
5173 if (f
->display
.x
->font
)
5174 XLoseFont (f
->display
.x
->font
);
5176 f
->display
.x
->font
= temp
;
5178 if (FRAME_X_WINDOW (f
) != 0)
5179 x_set_window_size (f
, 0, f
->width
, f
->height
);
5183 #endif /* ! defined (HAVE_X11) */
5185 x_calc_absolute_position (f
)
5190 int win_x
= 0, win_y
= 0;
5191 int flags
= f
->display
.x
->size_hint_flags
;
5193 /* Find the position of the outside upper-left corner of
5194 the inner window, with respect to the outer window. */
5195 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
5198 XTranslateCoordinates (x_current_display
,
5200 /* From-window, to-window. */
5201 f
->display
.x
->window_desc
,
5202 f
->display
.x
->parent_desc
,
5204 /* From-position, to-position. */
5205 0, 0, &win_x
, &win_y
,
5212 /* Treat negative positions as relative to the leftmost bottommost
5213 position that fits on the screen. */
5214 if (flags
& XNegative
)
5215 f
->display
.x
->left_pos
= (x_screen_width
5216 - 2 * f
->display
.x
->border_width
- win_x
5218 + f
->display
.x
->left_pos
);
5220 if (flags
& YNegative
)
5221 f
->display
.x
->top_pos
= (x_screen_height
5222 - 2 * f
->display
.x
->border_width
- win_y
5224 + f
->display
.x
->top_pos
);
5225 /* The left_pos and top_pos
5226 are now relative to the top and left screen edges,
5227 so the flags should correspond. */
5228 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5229 #else /* ! defined (HAVE_X11) */
5230 WINDOWINFO_TYPE parentinfo
;
5232 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
5234 if (f
->display
.x
->left_pos
< 0)
5235 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
5236 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
5238 if (f
->display
.x
->top_pos
< 0)
5239 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
5240 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
5241 #endif /* ! defined (HAVE_X11) */
5244 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5245 to really change the position, and 0 when calling from
5246 x_make_frame_visible (in that case, XOFF and YOFF are the current
5247 position values). */
5249 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5251 register int xoff
, yoff
;
5256 f
->display
.x
->top_pos
= yoff
;
5257 f
->display
.x
->left_pos
= xoff
;
5258 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5260 f
->display
.x
->size_hint_flags
|= XNegative
;
5262 f
->display
.x
->size_hint_flags
|= YNegative
;
5263 f
->display
.x
->win_gravity
= NorthWestGravity
;
5265 x_calc_absolute_position (f
);
5268 x_wm_set_size_hint (f
, 0, 0);
5270 #ifdef USE_X_TOOLKIT
5271 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
5272 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5273 #else /* not USE_X_TOOLKIT */
5274 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
5275 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5276 #endif /* not USE_X_TOOLKIT */
5280 /* Call this to change the size of frame F's x-window.
5281 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5282 for this size change and subsequent size changes.
5283 Otherwise we leave the window gravity unchanged. */
5285 x_set_window_size (f
, change_gravity
, cols
, rows
)
5290 int pixelwidth
, pixelheight
;
5293 #ifdef USE_X_TOOLKIT
5296 /* The x and y position of the widget is clobbered by the
5297 call to XtSetValues within EmacsFrameSetCharSize.
5298 This is a real kludge, but I don't understand Xt so I can't
5299 figure out a correct fix. Can anyone else tell me? -- rms. */
5300 int xpos
= f
->display
.x
->widget
->core
.x
;
5301 int ypos
= f
->display
.x
->widget
->core
.y
;
5302 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
5303 f
->display
.x
->widget
->core
.x
= xpos
;
5304 f
->display
.x
->widget
->core
.y
= ypos
;
5308 #else /* not USE_X_TOOLKIT */
5312 check_frame_size (f
, &rows
, &cols
);
5313 f
->display
.x
->vertical_scroll_bar_extra
5314 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5315 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
5317 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5318 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5321 f
->display
.x
->win_gravity
= NorthWestGravity
;
5322 x_wm_set_size_hint (f
, 0, 0);
5323 #endif /* ! defined (HAVE_X11) */
5324 XSync (x_current_display
, False
);
5325 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
5327 /* Now, strictly speaking, we can't be sure that this is accurate,
5328 but the window manager will get around to dealing with the size
5329 change request eventually, and we'll hear how it went when the
5330 ConfigureNotify event gets here.
5332 We could just not bother storing any of this information here,
5333 and let the ConfigureNotify event set everything up, but that
5334 might be kind of confusing to the lisp code, since size changes
5335 wouldn't be reported in the frame parameters until some random
5336 point in the future when the ConfigureNotify event arrives. */
5337 change_frame_size (f
, rows
, cols
, 0, 0);
5338 PIXEL_WIDTH (f
) = pixelwidth
;
5339 PIXEL_HEIGHT (f
) = pixelheight
;
5341 /* If cursor was outside the new size, mark it as off. */
5342 if (f
->phys_cursor_y
>= rows
5343 || f
->phys_cursor_x
>= cols
)
5345 f
->phys_cursor_x
= -1;
5346 f
->phys_cursor_y
= -1;
5349 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5350 receive in the ConfigureNotify event; if we get what we asked
5351 for, then the event won't cause the screen to become garbaged, so
5352 we have to make sure to do it here. */
5353 SET_FRAME_GARBAGED (f
);
5357 #endif /* not USE_X_TOOLKIT */
5361 x_set_resize_hint (f
)
5364 XSetResizeHint (FRAME_X_WINDOW (f
),
5365 2 * f
->display
.x
->internal_border_width
,
5366 2 * f
->display
.x
->internal_border_width
,
5367 FONT_WIDTH (f
->display
.x
->font
),
5368 f
->display
.x
->line_height
);
5370 #endif /* HAVE_X11 */
5372 /* Mouse warping, focus shifting, raising and lowering. */
5375 x_set_mouse_position (f
, x
, y
)
5381 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
5382 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
5384 if (pix_x
< 0) pix_x
= 0;
5385 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5387 if (pix_y
< 0) pix_y
= 0;
5388 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5392 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5396 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5399 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5405 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5410 x_focus_on_frame (f
)
5413 #if 0 /* This proves to be unpleasant. */
5417 /* I don't think that the ICCCM allows programs to do things like this
5418 without the interaction of the window manager. Whatever you end up
5419 doing with this code, do it to x_unfocus_frame too. */
5420 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
5421 RevertToPointerRoot
, CurrentTime
);
5429 /* Look at the remarks in x_focus_on_frame. */
5430 if (x_focus_frame
== f
)
5431 XSetInputFocus (x_current_display
, PointerRoot
,
5432 RevertToPointerRoot
, CurrentTime
);
5436 #endif /* ! defined (HAVE_X11) */
5438 /* Raise frame F. */
5443 if (f
->async_visible
)
5446 #ifdef USE_X_TOOLKIT
5447 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5448 #else /* not USE_X_TOOLKIT */
5449 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5450 #endif /* not USE_X_TOOLKIT */
5456 /* Lower frame F. */
5461 if (f
->async_visible
)
5464 #ifdef USE_X_TOOLKIT
5465 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5466 #else /* not USE_X_TOOLKIT */
5467 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5468 #endif /* not USE_X_TOOLKIT */
5475 XTframe_raise_lower (f
, raise
)
5486 /* Change from withdrawn state to mapped state,
5489 x_make_frame_visible (f
)
5496 if (! FRAME_VISIBLE_P (f
))
5499 #ifndef USE_X_TOOLKIT
5500 if (! FRAME_ICONIFIED_P (f
))
5501 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5504 if (! EQ (Vx_no_window_manager
, Qt
))
5505 x_wm_set_window_state (f
, NormalState
);
5506 #ifdef USE_X_TOOLKIT
5507 /* This was XtPopup, but that did nothing for an iconified frame. */
5508 XtMapWidget (f
->display
.x
->widget
);
5509 #else /* not USE_X_TOOLKIT */
5510 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5511 #endif /* not USE_X_TOOLKIT */
5512 #if 0 /* This seems to bring back scroll bars in the wrong places
5513 if the window configuration has changed. They seem
5514 to come back ok without this. */
5515 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5516 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5518 #else /* ! defined (HAVE_X11) */
5519 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5520 if (f
->display
.x
->icon_desc
!= 0)
5521 XUnmapWindow (f
->display
.x
->icon_desc
);
5523 /* Handled by the MapNotify event for X11 */
5524 f
->async_visible
= 1;
5525 f
->async_iconified
= 0;
5527 /* NOTE: this may cause problems for the first frame. */
5529 #endif /* ! defined (HAVE_X11) */
5537 /* Change from mapped state to withdrawn state. */
5539 x_make_frame_invisible (f
)
5545 #ifdef USE_X_TOOLKIT
5546 /* Use the frame's outermost window, not the one we normally draw on. */
5547 window
= XtWindow (f
->display
.x
->widget
);
5548 #else /* not USE_X_TOOLKIT */
5549 window
= FRAME_X_WINDOW (f
);
5550 #endif /* not USE_X_TOOLKIT */
5552 /* Don't keep the highlight on an invisible frame. */
5553 if (x_highlight_frame
== f
)
5554 x_highlight_frame
= 0;
5556 #if 0/* This might add unreliability; I don't trust it -- rms. */
5557 if (! f
->async_visible
&& ! f
->async_iconified
)
5563 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5564 that the current position of the window is user-specified, rather than
5565 program-specified, so that when the window is mapped again, it will be
5566 placed at the same location, without forcing the user to position it
5567 by hand again (they have already done that once for this window.) */
5568 x_wm_set_size_hint (f
, 0, 1);
5572 if (! XWithdrawWindow (x_current_display
, window
,
5573 DefaultScreen (x_current_display
)))
5575 UNBLOCK_INPUT_RESIGNAL
;
5576 error ("Can't notify window manager of window withdrawal");
5578 #else /* ! defined (HAVE_X11R4) */
5581 /* Tell the window manager what we're going to do. */
5582 if (! EQ (Vx_no_window_manager
, Qt
))
5586 unmap
.xunmap
.type
= UnmapNotify
;
5587 unmap
.xunmap
.window
= window
;
5588 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5589 unmap
.xunmap
.from_configure
= False
;
5590 if (! XSendEvent (x_current_display
,
5591 DefaultRootWindow (x_current_display
),
5593 SubstructureRedirectMask
|SubstructureNotifyMask
,
5596 UNBLOCK_INPUT_RESIGNAL
;
5597 error ("Can't notify window manager of withdrawal");
5601 /* Unmap the window ourselves. Cheeky! */
5602 XUnmapWindow (x_current_display
, window
);
5603 #else /* ! defined (HAVE_X11) */
5605 XUnmapWindow (FRAME_X_WINDOW (f
));
5606 if (f
->display
.x
->icon_desc
!= 0)
5607 XUnmapWindow (f
->display
.x
->icon_desc
);
5609 #endif /* ! defined (HAVE_X11) */
5610 #endif /* ! defined (HAVE_X11R4) */
5612 /* We can't distinguish this from iconification
5613 just by the event that we get from the server.
5614 So we can't win using the usual strategy of letting
5615 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5616 and synchronize with the server to make sure we agree. */
5618 FRAME_ICONIFIED_P (f
) = 0;
5619 f
->async_visible
= 0;
5620 f
->async_iconified
= 0;
5627 /* Change window state from mapped to iconified. */
5635 /* Don't keep the highlight on an invisible frame. */
5636 if (x_highlight_frame
== f
)
5637 x_highlight_frame
= 0;
5639 if (f
->async_iconified
)
5642 #ifdef USE_X_TOOLKIT
5645 if (! FRAME_VISIBLE_P (f
))
5647 if (! EQ (Vx_no_window_manager
, Qt
))
5648 x_wm_set_window_state (f
, IconicState
);
5649 /* This was XtPopup, but that did nothing for an iconified frame. */
5650 XtMapWidget (f
->display
.x
->widget
);
5655 result
= XIconifyWindow (x_current_display
,
5656 XtWindow (f
->display
.x
->widget
),
5657 DefaultScreen (x_current_display
));
5661 error ("Can't notify window manager of iconification");
5663 f
->async_iconified
= 1;
5668 #else /* not USE_X_TOOLKIT */
5673 /* Make sure the X server knows where the window should be positioned,
5674 in case the user deiconifies with the window manager. */
5675 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5676 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5678 /* Since we don't know which revision of X we're running, we'll use both
5679 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5681 /* X11R4: send a ClientMessage to the window manager using the
5682 WM_CHANGE_STATE type. */
5686 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5687 message
.xclient
.type
= ClientMessage
;
5688 message
.xclient
.message_type
= Xatom_wm_change_state
;
5689 message
.xclient
.format
= 32;
5690 message
.xclient
.data
.l
[0] = IconicState
;
5692 if (! XSendEvent (x_current_display
,
5693 DefaultRootWindow (x_current_display
),
5695 SubstructureRedirectMask
| SubstructureNotifyMask
,
5698 UNBLOCK_INPUT_RESIGNAL
;
5699 error ("Can't notify window manager of iconification");
5703 /* X11R3: set the initial_state field of the window manager hints to
5705 x_wm_set_window_state (f
, IconicState
);
5707 if (!FRAME_VISIBLE_P (f
))
5709 /* If the frame was withdrawn, before, we must map it. */
5710 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5711 #if 0 /* We don't have subwindows in the icon. */
5712 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5713 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5717 f
->async_iconified
= 1;
5718 #else /* ! defined (HAVE_X11) */
5719 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5721 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
5722 if (f
->display
.x
->icon_desc
!= 0)
5724 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
5727 #endif /* ! defined (HAVE_X11) */
5731 #endif /* not USE_X_TOOLKIT */
5734 /* Destroy the X window of frame F. */
5736 x_destroy_window (f
)
5741 if (f
->display
.x
->icon_desc
!= 0)
5742 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5743 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5744 #ifdef USE_X_TOOLKIT
5745 XtDestroyWidget (f
->display
.x
->widget
);
5746 free_frame_menubar (f
);
5747 #endif /* USE_X_TOOLKIT */
5749 free_frame_faces (f
);
5752 xfree (f
->display
.x
);
5754 if (f
== x_focus_frame
)
5756 if (f
== x_highlight_frame
)
5757 x_highlight_frame
= 0;
5759 if (f
== mouse_face_mouse_frame
)
5761 mouse_face_beg_row
= mouse_face_beg_col
= -1;
5762 mouse_face_end_row
= mouse_face_end_col
= -1;
5763 mouse_face_window
= Qnil
;
5769 /* Manage event queues for X10. */
5773 /* Manage event queues.
5775 This code is only used by the X10 support.
5777 We cannot leave events in the X queue and get them when we are ready
5778 because X does not provide a subroutine to get only a certain kind
5779 of event but not block if there are no queued events of that kind.
5781 Therefore, we must examine events as they come in and copy events
5782 of certain kinds into our private queues.
5784 All ExposeRegion events are put in x_expose_queue.
5785 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5788 /* Write the event *P_XREP into the event queue *QUEUE.
5789 If the queue is full, do nothing, but return nonzero. */
5792 enqueue_event (p_xrep
, queue
)
5793 register XEvent
*p_xrep
;
5794 register struct event_queue
*queue
;
5796 int newindex
= queue
->windex
+ 1;
5797 if (newindex
== EVENT_BUFFER_SIZE
)
5799 if (newindex
== queue
->rindex
)
5801 queue
->xrep
[queue
->windex
] = *p_xrep
;
5802 queue
->windex
= newindex
;
5806 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5807 If *QUEUE is empty, do nothing and return 0. */
5810 dequeue_event (p_xrep
, queue
)
5811 register XEvent
*p_xrep
;
5812 register struct event_queue
*queue
;
5814 if (queue
->windex
== queue
->rindex
)
5816 *p_xrep
= queue
->xrep
[queue
->rindex
++];
5817 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
5822 /* Return the number of events buffered in *QUEUE. */
5825 queue_event_count (queue
)
5826 register struct event_queue
*queue
;
5828 int tem
= queue
->windex
- queue
->rindex
;
5831 return EVENT_BUFFER_SIZE
+ tem
;
5834 /* Return nonzero if mouse input is pending. */
5837 mouse_event_pending_p ()
5839 return queue_event_count (&x_mouse_queue
);
5841 #endif /* HAVE_X11 */
5843 /* Setting window manager hints. */
5847 /* Set the normal size hints for the window manager, for frame F.
5848 FLAGS is the flags word to use--or 0 meaning preserve the flags
5849 that the window now has.
5850 If USER_POSITION is nonzero, we set the USPosition
5851 flag (this is useful when FLAGS is 0). */
5853 x_wm_set_size_hint (f
, flags
, user_position
)
5858 XSizeHints size_hints
;
5860 #ifdef USE_X_TOOLKIT
5863 Dimension widget_width
, widget_height
;
5864 Window window
= XtWindow (f
->display
.x
->widget
);
5865 #else /* not USE_X_TOOLKIT */
5866 Window window
= FRAME_X_WINDOW (f
);
5867 #endif /* not USE_X_TOOLKIT */
5869 /* Setting PMaxSize caused various problems. */
5870 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5872 flexlines
= f
->height
;
5874 size_hints
.x
= f
->display
.x
->left_pos
;
5875 size_hints
.y
= f
->display
.x
->top_pos
;
5877 #ifdef USE_X_TOOLKIT
5878 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5879 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5880 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5881 size_hints
.height
= widget_height
;
5882 size_hints
.width
= widget_width
;
5883 #else /* not USE_X_TOOLKIT */
5884 size_hints
.height
= PIXEL_HEIGHT (f
);
5885 size_hints
.width
= PIXEL_WIDTH (f
);
5886 #endif /* not USE_X_TOOLKIT */
5888 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5889 size_hints
.height_inc
= f
->display
.x
->line_height
;
5890 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5891 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5894 int base_width
, base_height
;
5895 int min_rows
= 0, min_cols
= 0;
5897 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5898 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5900 check_frame_size (f
, &min_rows
, &min_cols
);
5902 /* The window manager uses the base width hints to calculate the
5903 current number of rows and columns in the frame while
5904 resizing; min_width and min_height aren't useful for this
5905 purpose, since they might not give the dimensions for a
5906 zero-row, zero-column frame.
5908 We use the base_width and base_height members if we have
5909 them; otherwise, we set the min_width and min_height members
5910 to the size for a zero x zero frame. */
5913 size_hints
.flags
|= PBaseSize
;
5914 size_hints
.base_width
= base_width
;
5915 size_hints
.base_height
= base_height
;
5916 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5917 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5919 size_hints
.min_width
= base_width
;
5920 size_hints
.min_height
= base_height
;
5925 size_hints
.flags
|= flags
;
5928 XSizeHints hints
; /* Sometimes I hate X Windows... */
5929 long supplied_return
;
5933 value
= XGetWMNormalHints (x_current_display
, window
, &hints
,
5936 value
= XGetNormalHints (x_current_display
, window
, &hints
);
5941 if (hints
.flags
& PSize
)
5942 size_hints
.flags
|= PSize
;
5943 if (hints
.flags
& PPosition
)
5944 size_hints
.flags
|= PPosition
;
5945 if (hints
.flags
& USPosition
)
5946 size_hints
.flags
|= USPosition
;
5947 if (hints
.flags
& USSize
)
5948 size_hints
.flags
|= USSize
;
5952 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5953 size_hints
.flags
|= PWinGravity
;
5957 size_hints
.flags
&= ~ PPosition
;
5958 size_hints
.flags
|= USPosition
;
5960 #endif /* PWinGravity */
5963 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
5965 XSetNormalHints (x_current_display
, window
, &size_hints
);
5969 /* Used for IconicState or NormalState */
5970 x_wm_set_window_state (f
, state
)
5974 #ifdef USE_X_TOOLKIT
5977 XtSetArg (al
[0], XtNinitialState
, state
);
5978 XtSetValues (f
->display
.x
->widget
, al
, 1);
5979 #else /* not USE_X_TOOLKIT */
5980 Window window
= FRAME_X_WINDOW (f
);
5982 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5983 f
->display
.x
->wm_hints
.initial_state
= state
;
5985 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5986 #endif /* not USE_X_TOOLKIT */
5989 x_wm_set_icon_pixmap (f
, icon_pixmap
)
5993 #ifdef USE_X_TOOLKIT
5994 Window window
= XtWindow (f
->display
.x
->widget
);
5996 Window window
= FRAME_X_WINDOW (f
);
6001 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6002 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
6005 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
6007 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6010 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6014 #ifdef USE_X_TOOLKIT
6015 Window window
= XtWindow (f
->display
.x
->widget
);
6017 Window window
= FRAME_X_WINDOW (f
);
6020 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
6021 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
6022 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
6024 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6028 /* Initialization. */
6030 #ifdef USE_X_TOOLKIT
6031 static XrmOptionDescRec emacs_options
[] = {
6032 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6033 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6035 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6036 XrmoptionSepArg
, NULL
},
6037 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6039 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6040 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6041 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6042 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6043 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6044 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6045 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6047 #endif /* USE_X_TOOLKIT */
6050 x_term_init (display_name
, xrm_option
, resource_name
)
6053 char *resource_name
;
6059 #ifndef F_SETOWN_BUG
6061 extern int old_fcntl_owner
;
6062 #endif /* ! defined (F_SETOWN) */
6063 #endif /* F_SETOWN_BUG */
6065 x_focus_frame
= x_highlight_frame
= 0;
6067 #ifdef USE_X_TOOLKIT
6068 argv
= (char **) XtMalloc (7 * sizeof (char *));
6070 argv
[1] = "-display";
6071 argv
[2] = display_name
;
6073 /* Usually `emacs', but not always. */
6074 argv
[4] = resource_name
;
6078 argv
[argc
++] = "-xrm";
6079 argv
[argc
++] = xrm_option
;
6081 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
6082 emacs_options
, XtNumber (emacs_options
),
6085 XtFree ((char *)argv
);
6086 x_current_display
= XtDisplay (Xt_app_shell
);
6088 #else /* not USE_X_TOOLKIT */
6089 x_current_display
= XOpenDisplay (display_name
);
6090 #endif /* not USE_X_TOOLKIT */
6091 if (x_current_display
== 0)
6092 fatal ("X server %s not responding.\n\
6093 Check the DISPLAY environment variable or use \"-d\"\n",
6099 XSetAfterFunction (x_current_display
, x_trace_wire
);
6101 hostname
= get_system_name ();
6102 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
6105 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
6108 /* Figure out which modifier bits mean what. */
6109 x_find_modifier_meanings ();
6111 /* Get the scroll bar cursor. */
6112 x_vertical_scroll_bar_cursor
6113 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
6116 /* Watch for PropertyNotify events on the root window; we use them
6117 to figure out when to invalidate our cache of the cut buffers. */
6118 x_watch_cut_buffer_cache ();
6121 if (ConnectionNumber (x_current_display
) != 0)
6122 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
6123 change_input_fd (ConnectionNumber (x_current_display
));
6125 #endif /* ! defined (HAVE_X11) */
6127 #ifndef F_SETOWN_BUG
6129 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
6130 #ifdef F_SETOWN_SOCK_NEG
6131 /* stdin is a socket here */
6132 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
6133 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6134 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
6135 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6136 #endif /* ! defined (F_SETOWN) */
6137 #endif /* F_SETOWN_BUG */
6141 #endif /* ! defined (SIGIO) */
6143 expose_all_windows
= 0;
6145 clear_frame_hook
= XTclear_frame
;
6146 clear_end_of_line_hook
= XTclear_end_of_line
;
6147 ins_del_lines_hook
= XTins_del_lines
;
6148 change_line_highlight_hook
= XTchange_line_highlight
;
6149 insert_glyphs_hook
= XTinsert_glyphs
;
6150 write_glyphs_hook
= XTwrite_glyphs
;
6151 delete_glyphs_hook
= XTdelete_glyphs
;
6152 ring_bell_hook
= XTring_bell
;
6153 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6154 set_terminal_modes_hook
= XTset_terminal_modes
;
6155 update_begin_hook
= XTupdate_begin
;
6156 update_end_hook
= XTupdate_end
;
6157 set_terminal_window_hook
= XTset_terminal_window
;
6158 read_socket_hook
= XTread_socket
;
6159 frame_up_to_date_hook
= XTframe_up_to_date
;
6160 cursor_to_hook
= XTcursor_to
;
6161 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6162 mouse_position_hook
= XTmouse_position
;
6163 frame_rehighlight_hook
= XTframe_rehighlight
;
6164 frame_raise_lower_hook
= XTframe_raise_lower
;
6165 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6166 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6167 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6168 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6170 scroll_region_ok
= 1; /* we'll scroll partial frames */
6171 char_ins_del_ok
= 0; /* just as fast to write the line */
6172 line_ins_del_ok
= 1; /* we'll just blt 'em */
6173 fast_clear_end_of_line
= 1; /* X does this well */
6174 memory_below_frame
= 0; /* we don't remember what scrolls
6178 /* Try to use interrupt input; if we can't, then start polling. */
6179 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6181 /* Note that there is no real way portable across R3/R4 to get the
6182 original error handler. */
6183 XHandleError (x_error_quitter
);
6184 XHandleIOError (x_io_error_quitter
);
6186 /* Disable Window Change signals; they are handled by X events. */
6188 signal (SIGWINCH
, SIG_DFL
);
6189 #endif /* ! defined (SIGWINCH) */
6191 signal (SIGPIPE
, x_connection_closed
);
6197 staticpro (&last_mouse_scroll_bar
);
6198 last_mouse_scroll_bar
= Qnil
;
6199 staticpro (&mouse_face_window
);
6200 mouse_face_window
= Qnil
;
6202 #endif /* ! defined (HAVE_X11) */
6203 #endif /* ! defined (HAVE_X_WINDOWS) */