1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
60 #ifndef INCLUDED_FCNTL
67 #include <sys/param.h>
69 #include "dispextern.h"
70 #include "termhooks.h"
84 extern XtAppContext Xt_app_con
;
85 extern Widget Xt_app_shell
;
86 extern void free_frame_menubar ();
87 extern void _XEditResCheckMessages ();
88 #endif /* USE_X_TOOLKIT */
91 #define x_any_window_to_frame x_window_to_frame
92 #define x_top_window_to_frame x_window_to_frame
96 #ifndef XtNinitialState
97 #define XtNinitialState "initialState"
102 #define XMapWindow XMapRaised /* Raise them when mapping. */
103 #else /* ! defined (HAVE_X11) */
104 #include <X/Xkeyboard.h>
105 /*#include <X/Xproto.h> */
106 #endif /* ! defined (HAVE_X11) */
109 /* We could get this from param.h, but better not to depend on finding that.
110 And better not to risk that it might define other symbols used in this
113 #define MAXDESC FD_SETSIZE
117 #define SELECT_TYPE fd_set
118 #else /* no FD_SET */
120 #define SELECT_TYPE int
122 /* Define the macros to access a single-int bitmap of descriptors. */
123 #define FD_SET(n, p) (*(p) |= (1 << (n)))
124 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
125 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
126 #define FD_ZERO(p) (*(p) = 0)
127 #endif /* no FD_SET */
129 /* For sending Meta-characters. Do we need this? */
132 #define min(a,b) ((a)<(b) ? (a) : (b))
133 #define max(a,b) ((a)>(b) ? (a) : (b))
135 /* Nonzero means we must reprint all windows
136 because 1) we received an ExposeWindow event
137 or 2) we received too many ExposeRegion events to record.
139 This is never needed under X11. */
140 static int expose_all_windows
;
142 /* Nonzero means we must reprint all icon windows. */
144 static int expose_all_icons
;
147 /* ExposeRegion events, when received, are copied into this queue
148 for later processing. */
150 static struct event_queue x_expose_queue
;
152 /* ButtonPress and ButtonReleased events, when received,
153 are copied into this queue for later processing. */
155 struct event_queue x_mouse_queue
;
156 #endif /* HAVE_X11 */
158 #if defined (SIGIO) && defined (FIONREAD)
159 int BLOCK_INPUT_mask
;
160 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
162 /* The id of a bitmap used for icon windows.
163 One such map is shared by all Emacs icon windows.
164 This is zero if we have not yet had a need to create the bitmap. */
166 static Bitmap icon_bitmap
;
168 /* Font used for text icons. */
170 static FONT_TYPE
*icon_font_info
;
172 /* Stuff for dealing with the main icon title. */
174 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
177 /* Initial values of argv and argc. */
178 extern char **initial_argv
;
179 extern int initial_argc
;
181 /* This is the X connection that we are using. */
183 Display
*x_current_display
;
185 /* The cursor to use for vertical scroll bars on x_current_display. */
186 static Cursor x_vertical_scroll_bar_cursor
;
188 /* Frame being updated by update_frame. This is declared in term.c.
189 This is set by update_begin and looked at by all the
190 XT functions. It is zero while not inside an update.
191 In that case, the XT functions assume that `selected_frame'
192 is the frame to apply to. */
193 extern struct frame
*updating_frame
;
195 /* The frame (if any) which has the X window that has keyboard focus.
196 Zero if none. This is examined by Ffocus_frame in frame.c. Note
197 that a mere EnterNotify event can set this; if you need to know the
198 last frame specified in a FocusIn or FocusOut event, use
199 x_focus_event_frame. */
200 struct frame
*x_focus_frame
;
202 /* This is a frame waiting to be autoraised, within XTread_socket. */
203 struct frame
*pending_autoraise_frame
;
205 /* The last frame mentioned in a FocusIn or FocusOut event. This is
206 separate from x_focus_frame, because whether or not LeaveNotify
207 events cause us to lose focus depends on whether or not we have
208 received a FocusIn event for it. */
209 struct frame
*x_focus_event_frame
;
211 /* The frame which currently has the visual highlight, and should get
212 keyboard input (other sorts of input have the frame encoded in the
213 event). It points to the X focus frame's selected window's
214 frame. It differs from x_focus_frame when we're using a global
216 static struct frame
*x_highlight_frame
;
218 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
219 mouse is moved to inside of frame when frame is de-iconified. */
221 static int warp_mouse_on_deiconify
;
223 /* During an update, maximum vpos for ins/del line operations to affect. */
225 static int flexlines
;
227 /* During an update, nonzero if chars output now should be highlighted. */
229 static int highlight
;
231 /* Nominal cursor position -- where to draw output.
232 During an update, these are different from the cursor-box position. */
237 /* Reusable Graphics Context for drawing a cursor in a non-default face. */
238 static GC scratch_cursor_gc
;
242 In order to avoid asking for motion events and then throwing most
243 of them away or busy-polling the server for mouse positions, we ask
244 the server for pointer motion hints. This means that we get only
245 one event per group of mouse movements. "Groups" are delimited by
246 other kinds of events (focus changes and button clicks, for
247 example), or by XQueryPointer calls; when one of these happens, we
248 get another MotionNotify event the next time the mouse moves. This
249 is at least as efficient as getting motion events when mouse
250 tracking is on, and I suspect only negligibly worse when tracking
253 The silly O'Reilly & Associates Nutshell guides barely document
254 pointer motion hints at all (I think you have to infer how they
255 work from an example), and the description of XQueryPointer doesn't
256 mention that calling it causes you to get another motion hint from
257 the server, which is very important. */
259 /* Where the mouse was last time we reported a mouse event. */
260 static FRAME_PTR last_mouse_frame
;
261 static XRectangle last_mouse_glyph
;
263 /* The scroll bar in which the last X motion event occurred.
265 If the last X motion event occurred in a scroll bar, we set this
266 so XTmouse_position can know whether to report a scroll bar motion or
269 If the last X motion event didn't occur in a scroll bar, we set this
270 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
271 static Lisp_Object last_mouse_scroll_bar
;
273 /* Record which buttons are currently pressed. */
274 unsigned int x_mouse_grabbed
;
276 /* This is a hack. We would really prefer that XTmouse_position would
277 return the time associated with the position it returns, but there
278 doesn't seem to be any way to wrest the timestamp from the server
279 along with the position query. So, we just keep track of the time
280 of the last movement we received, and return that in hopes that
281 it's somewhat accurate. */
282 static Time last_mouse_movement_time
;
284 /* These variables describe the range of text currently shown
285 in its mouse-face, together with the window they apply to.
286 As long as the mouse stays within this range, we need not
287 redraw anything on its account. */
288 static int mouse_face_beg_row
, mouse_face_beg_col
;
289 static int mouse_face_end_row
, mouse_face_end_col
;
290 static int mouse_face_past_end
;
291 static Lisp_Object mouse_face_window
;
292 static int mouse_face_face_id
;
294 /* 1 if a mouse motion event came and we didn't handle it right away because
295 gc was in progress. */
296 static int mouse_face_deferred_gc
;
298 /* FRAME and X, Y position of mouse when last checked for
299 highlighting. X and Y can be negative or out of range for the frame. */
300 static FRAME_PTR mouse_face_mouse_frame
;
301 static int mouse_face_mouse_x
, mouse_face_mouse_y
;
303 /* Nonzero means defer mouse-motion highlighting. */
304 static int mouse_face_defer
;
307 /* `t' if a mouse button is depressed. */
309 extern Lisp_Object Vmouse_depressed
;
311 /* Tells if a window manager is present or not. */
313 extern Lisp_Object Vx_no_window_manager
;
315 /* Timestamp that we requested selection data was made. */
316 extern Time requestor_time
;
318 /* ID of the window requesting selection data. */
319 extern Window requestor_window
;
321 /* Nonzero enables some debugging for the X interface code. */
324 extern Lisp_Object Qface
, Qmouse_face
;
326 #else /* ! defined (HAVE_X11) */
328 /* Bit patterns for the mouse cursor. */
330 short MouseCursor
[] = {
331 0x0000, 0x0008, 0x0018, 0x0038,
332 0x0078, 0x00f8, 0x01f8, 0x03f8,
333 0x07f8, 0x00f8, 0x00d8, 0x0188,
334 0x0180, 0x0300, 0x0300, 0x0000};
336 short MouseMask
[] = {
337 0x000c, 0x001c, 0x003c, 0x007c,
338 0x00fc, 0x01fc, 0x03fc, 0x07fc,
339 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
340 0x03cc, 0x0780, 0x0780, 0x0300};
342 static short grey_bits
[] = {
343 0x0005, 0x000a, 0x0005, 0x000a};
345 static Pixmap GreyPixmap
= 0;
346 #endif /* ! defined (HAVE_X11) */
349 static int x_noop_count
;
353 /* From time to time we get info on an Emacs window, here. */
355 static WINDOWINFO_TYPE windowinfo
;
359 /* A mask of extra modifier bits to put into every keyboard char. */
360 extern int extra_keyboard_modifiers
;
362 extern Display
*XOpenDisplay ();
363 extern Window
XCreateWindow ();
365 extern Cursor
XCreateCursor ();
366 extern FONT_TYPE
*XOpenFont ();
368 static void flashback ();
369 static void redraw_previous_char ();
370 static void redraw_following_char ();
371 static unsigned int x_x_to_emacs_modifiers ();
373 static int fast_find_position ();
374 static void note_mouse_highlight ();
375 static void clear_mouse_face ();
376 static void show_mouse_face ();
379 static void dumpqueue ();
380 #endif /* HAVE_X11 */
383 static int XTcursor_to ();
384 static int XTclear_end_of_line ();
387 /* Starting and ending updates.
389 These hooks are called by update_frame at the beginning and end
390 of a frame update. We record in `updating_frame' the identity
391 of the frame being updated, so that the XT... functions do not
392 need to take a frame as argument. Most of the XT... functions
393 should never be called except during an update, the only exceptions
394 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
396 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
407 flexlines
= f
->height
;
412 if (f
== mouse_face_mouse_frame
)
414 /* Don't do highlighting for mouse motion during the update. */
415 mouse_face_defer
= 1;
416 if (!NILP (mouse_face_window
))
418 int firstline
, lastline
, i
;
419 struct window
*w
= XWINDOW (mouse_face_window
);
421 /* Find the first, and the last+1, lines affected by redisplay. */
422 for (firstline
= 0; firstline
< f
->height
; firstline
++)
423 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
426 lastline
= f
->height
;
427 for (i
= f
->height
- 1; i
>= 0; i
--)
429 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
435 /* Can we tell that this update does not affect the window
436 where the mouse highlight is? If so, no need to turn off. */
437 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
438 || lastline
< XFASTINT (w
->top
)))
439 /* Otherwise turn off the mouse highlight now. */
445 #endif /* HAVE_X11 */
450 static void x_do_pending_expose ();
462 x_do_pending_expose ();
463 #endif /* HAVE_X11 */
465 x_display_cursor (f
, 1);
467 if (f
== mouse_face_mouse_frame
)
468 mouse_face_defer
= 0;
470 /* This fails in the case of having updated only the echo area
471 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
472 has no relation to the current contents, and its charstarts
473 have no relation to the contents of the window-buffer.
474 I don't know a clean way to check
475 for that case. window_end_valid isn't set up yet. */
476 if (f
== mouse_face_mouse_frame
)
477 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
484 /* This is called after a redisplay on frame F. */
487 XTframe_up_to_date (f
)
490 if (mouse_face_deferred_gc
|| f
== mouse_face_mouse_frame
)
492 note_mouse_highlight (mouse_face_mouse_frame
,
493 mouse_face_mouse_x
, mouse_face_mouse_y
);
494 mouse_face_deferred_gc
= 0;
498 /* External interface to control of standout mode.
499 Call this when about to modify line at position VPOS
500 and not change whether it is highlighted. */
502 XTreassert_line_highlight (new, vpos
)
508 /* Call this when about to modify line at position VPOS
509 and change whether it is highlighted. */
512 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
513 int new_highlight
, vpos
, first_unused_hpos
;
515 highlight
= new_highlight
;
516 XTcursor_to (vpos
, 0);
517 XTclear_end_of_line (updating_frame
->width
);
520 /* This is used when starting Emacs and when restarting after suspend.
521 When starting Emacs, no X window is mapped. And nothing must be done
522 to Emacs's own window if it is suspended (though that rarely happens). */
525 XTset_terminal_modes ()
529 /* This is called when exiting or suspending Emacs.
530 Exiting will make the X-windows go away, and suspending
531 requires no action. */
534 XTreset_terminal_modes ()
536 /* XTclear_frame (); */
539 /* Set the nominal cursor position of the frame.
540 This is where display update commands will take effect.
541 This does not affect the place where the cursor-box is displayed. */
544 XTcursor_to (row
, col
)
545 register int row
, col
;
553 if (updating_frame
== 0)
556 x_display_cursor (selected_frame
, 1);
562 /* Display a sequence of N glyphs found at GP.
563 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
564 HL is 1 if this text is highlighted, 2 if the cursor is on it,
565 3 if should appear in its mouse-face.
566 JUST_FOREGROUND if 1 means draw only the foreground;
567 don't alter the background.
569 FONT is the default font to use (for glyphs whose font-code is 0).
571 Since the display generation code is responsible for calling
572 compute_char_face and compute_glyph_face on everything it puts in
573 the display structure, we can assume that the face code on each
574 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
575 to which we can actually apply intern_face.
576 Call this function with input blocked. */
579 /* This is the multi-face code. */
582 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
585 register GLYPH
*gp
; /* Points to first GLYPH. */
586 register int n
; /* Number of glyphs to display. */
590 /* Holds characters to be displayed. */
591 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
592 register char *cp
; /* Steps through buf[]. */
593 register int tlen
= GLYPH_TABLE_LENGTH
;
594 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
595 Window window
= FRAME_X_WINDOW (f
);
596 int orig_left
= left
;
600 /* Get the face-code of the next GLYPH. */
604 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
605 cf
= FAST_GLYPH_FACE (g
);
607 /* Find the run of consecutive glyphs with the same face-code.
608 Extract their character codes into BUF. */
613 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
614 if (FAST_GLYPH_FACE (g
) != cf
)
617 *cp
++ = FAST_GLYPH_CHAR (g
);
622 /* LEN gets the length of the run. */
625 /* Now output this run of chars, with the font and pixel values
626 determined by the face code CF. */
628 struct face
*face
= FRAME_DEFAULT_FACE (f
);
629 FONT_TYPE
*font
= FACE_FONT (face
);
630 GC gc
= FACE_GC (face
);
632 /* HL = 3 means use a mouse face previously chosen. */
634 cf
= mouse_face_face_id
;
636 /* First look at the face of the text itself. */
639 /* It's possible for the display table to specify
640 a face code that is out of range. Use 0 in that case. */
641 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
642 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
646 face
= FRAME_MODE_LINE_FACE (f
);
648 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
649 font
= FACE_FONT (face
);
653 /* Then comes the distinction between modeline and normal text. */
658 face
= FRAME_MODE_LINE_FACE (f
);
659 font
= FACE_FONT (face
);
663 #define FACE_DEFAULT (~0)
665 /* Now override that if the cursor's on this character. */
669 || (int) face
->font
== FACE_DEFAULT
670 || face
->font
== f
->display
.x
->font
)
671 && face
->background
== f
->display
.x
->background_pixel
672 && face
->foreground
== f
->display
.x
->foreground_pixel
)
674 gc
= f
->display
.x
->cursor_gc
;
676 /* Cursor on non-default face: must merge. */
682 xgcv
.background
= f
->display
.x
->cursor_pixel
;
683 xgcv
.foreground
= face
->background
;
684 /* If the glyph would be invisible,
685 try a different foreground. */
686 if (xgcv
.foreground
== xgcv
.background
)
687 xgcv
.foreground
= face
->foreground
;
688 if (xgcv
.foreground
== xgcv
.background
)
689 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
690 if (xgcv
.foreground
== xgcv
.background
)
691 xgcv
.foreground
= face
->foreground
;
692 /* Make sure the cursor is distinct from text in this face. */
693 if (xgcv
.background
== face
->background
694 && xgcv
.foreground
== face
->foreground
)
696 xgcv
.background
= face
->foreground
;
697 xgcv
.foreground
= face
->background
;
699 xgcv
.font
= face
->font
->fid
;
700 xgcv
.graphics_exposures
= 0;
701 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
702 if (scratch_cursor_gc
)
703 XChangeGC (x_current_display
, scratch_cursor_gc
, mask
, &xgcv
);
706 XCreateGC (x_current_display
, window
, mask
, &xgcv
);
707 gc
= scratch_cursor_gc
;
709 /* If this code is restored, it must also reset to the default stipple
711 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
712 XSetStipple (x_current_display
, gc
, face
->stipple
);
717 if ((int) font
== FACE_DEFAULT
)
718 font
= f
->display
.x
->font
;
721 XDrawString (x_current_display
, window
, gc
,
722 left
, top
+ FONT_BASE (font
), buf
, len
);
725 XDrawImageString (x_current_display
, window
, gc
,
726 left
, top
+ FONT_BASE (font
), buf
, len
);
727 /* Clear the rest of the line's height. */
728 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
729 XClearArea (x_current_display
, window
, left
,
730 top
+ FONT_HEIGHT (font
),
731 FONT_WIDTH (font
) * len
,
732 /* This is how many pixels of height
734 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
738 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
739 which often is not up to date yet. */
740 if (!just_foreground
)
742 if (left
== orig_left
)
743 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
744 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
746 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
747 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
751 /* We should probably check for XA_UNDERLINE_POSITION and
752 XA_UNDERLINE_THICKNESS properties on the font, but let's
753 just get the thing working, and come back to that. */
755 int underline_position
= 1;
757 if (font
->descent
<= underline_position
)
758 underline_position
= font
->descent
- 1;
761 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
765 + underline_position
),
766 len
* FONT_WIDTH (font
), 1);
769 left
+= len
* FONT_WIDTH (font
);
776 /* This is the old single-face code. */
779 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
782 register GLYPH
*gp
; /* Points to first GLYPH. */
783 register int n
; /* Number of glyphs to display. */
788 Window window
= FRAME_X_WINDOW (f
);
789 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
790 : (hl
? f
->display
.x
->reverse_gc
791 : f
->display
.x
->normal_gc
));
793 if (sizeof (GLYPH
) == sizeof (XChar2b
))
794 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
795 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
796 else if (sizeof (GLYPH
) == sizeof (unsigned char))
797 XDrawImageString (x_current_display
, window
, drawing_gc
,
798 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
800 /* What size of glyph ARE you using? And does X have a function to
806 /* Output some text at the nominal frame cursor position.
807 Advance the cursor over the text.
808 Output LEN glyphs at START.
810 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
811 controls the pixel values used for foreground and background. */
814 XTwrite_glyphs (start
, len
)
815 register GLYPH
*start
;
818 register int temp_length
;
828 /* If not within an update,
829 output at the frame's visible cursor. */
830 curs_x
= f
->cursor_x
;
831 curs_y
= f
->cursor_y
;
835 CHAR_TO_PIXEL_COL (f
, curs_x
),
836 CHAR_TO_PIXEL_ROW (f
, curs_y
),
837 start
, len
, highlight
, 0);
839 /* If we drew on top of the cursor, note that it is turned off. */
840 if (curs_y
== f
->phys_cursor_y
841 && curs_x
<= f
->phys_cursor_x
842 && curs_x
+ len
> f
->phys_cursor_x
)
843 f
->phys_cursor_x
= -1;
845 if (updating_frame
== 0)
848 x_display_cursor (f
, 1);
857 /* Clear to the end of the line.
858 Erase the current text line from the nominal cursor position (inclusive)
859 to column FIRST_UNUSED (exclusive). The idea is that everything
860 from FIRST_UNUSED onward is already erased. */
863 XTclear_end_of_line (first_unused
)
864 register int first_unused
;
866 struct frame
*f
= updating_frame
;
872 if (curs_y
< 0 || curs_y
>= f
->height
)
874 if (first_unused
<= 0)
877 if (first_unused
>= f
->width
)
878 first_unused
= f
->width
;
882 /* Notice if the cursor will be cleared by this operation. */
883 if (curs_y
== f
->phys_cursor_y
884 && curs_x
<= f
->phys_cursor_x
885 && f
->phys_cursor_x
< first_unused
)
886 f
->phys_cursor_x
= -1;
889 XClearArea (x_current_display
, 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
, False
);
895 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
897 #else /* ! defined (HAVE_X11) */
898 XPixSet (FRAME_X_WINDOW (f
),
899 CHAR_TO_PIXEL_COL (f
, curs_x
),
900 CHAR_TO_PIXEL_ROW (f
, curs_y
),
901 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
902 f
->display
.x
->line_height
,
903 f
->display
.x
->background_pixel
);
904 #endif /* ! defined (HAVE_X11) */
913 struct frame
*f
= updating_frame
;
918 f
->phys_cursor_x
= -1; /* Cursor not visible. */
919 curs_x
= 0; /* Nominal cursor position is top left. */
924 XClear (FRAME_X_WINDOW (f
));
926 /* We have to clear the scroll bars, too. If we have changed
927 colors or something like that, then they should be notified. */
928 x_scroll_bar_clear (f
);
932 #endif /* HAVE_X11 */
939 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
940 always contain the right glyphs to use.
942 It also needs to be changed to look at the details of the font and
943 see whether there is really overlap, and do nothing when there is
944 not. This can use font_char_overlap_left and font_char_overlap_right,
945 but just how to use them is not clear. */
947 /* Erase the character (if any) at the position just before X, Y in frame F,
948 then redraw it and the character before it.
949 This is necessary when we erase starting at X,
950 in case the character after X overlaps into the one before X.
951 Call this function with input blocked. */
954 redraw_previous_char (f
, x
, y
, highlight_flag
)
959 /* Erase the character before the new ones, in case
960 what was here before overlaps it.
961 Reoutput that character, and the previous character
962 (in case the previous character overlaps it). */
968 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
969 CHAR_TO_PIXEL_COL (f
, x
- 1),
970 CHAR_TO_PIXEL_ROW (f
, y
),
971 FONT_WIDTH (f
->display
.x
->font
),
972 f
->display
.x
->line_height
, False
);
974 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
975 CHAR_TO_PIXEL_ROW (f
, y
),
976 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
977 x
- start_x
, highlight_flag
, 1);
981 /* Erase the character (if any) at the position X, Y in frame F,
982 then redraw it and the character after it.
983 This is necessary when we erase endng at X,
984 in case the character after X overlaps into the one before X.
985 Call this function with input blocked. */
988 redraw_following_char (f
, x
, y
, highlight_flag
)
993 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
994 /* Erase the character after the new ones, in case
995 what was here before overlaps it.
996 Reoutput that character, and the following character
997 (in case the following character overlaps it). */
999 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1004 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1005 CHAR_TO_PIXEL_COL (f
, x
),
1006 CHAR_TO_PIXEL_ROW (f
, y
),
1007 FONT_WIDTH (f
->display
.x
->font
),
1008 f
->display
.x
->line_height
, False
);
1010 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1011 CHAR_TO_PIXEL_ROW (f
, y
),
1012 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1013 end_x
- x
, highlight_flag
, 1);
1018 #if 0 /* Not in use yet */
1020 /* Return 1 if character C in font F extends past its left edge. */
1023 font_char_overlap_left (font
, c
)
1029 /* Find the bounding-box info for C. */
1030 if (font
->per_char
== 0)
1031 s
= &font
->max_bounds
;
1034 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1037 /* Decode char into row number (byte 1) and code within row (byte 2). */
1040 if (!(within
>= font
->min_char_or_byte2
1041 && within
<= font
->max_char_or_byte2
1042 && row
>= font
->min_byte1
1043 && row
<= font
->max_byte1
))
1045 /* If char is out of range, try the font's default char instead. */
1046 c
= font
->default_char
;
1047 row
= c
>> (INTBITS
- 8);
1050 if (!(within
>= font
->min_char_or_byte2
1051 && within
<= font
->max_char_or_byte2
1052 && row
>= font
->min_byte1
1053 && row
<= font
->max_byte1
))
1054 /* Still out of range means this char does not overlap. */
1057 /* We found the info for this char. */
1058 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1062 return (s
&& s
->lbearing
< 0);
1065 /* Return 1 if character C in font F extends past its right edge. */
1068 font_char_overlap_right (font
, c
)
1074 /* Find the bounding-box info for C. */
1075 if (font
->per_char
== 0)
1076 s
= &font
->max_bounds
;
1079 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1082 /* Decode char into row number (byte 1) and code within row (byte 2). */
1085 if (!(within
>= font
->min_char_or_byte2
1086 && within
<= font
->max_char_or_byte2
1087 && row
>= font
->min_byte1
1088 && row
<= font
->max_byte1
))
1090 /* If char is out of range, try the font's default char instead. */
1091 c
= font
->default_char
;
1092 row
= c
>> (INTBITS
- 8);
1095 if (!(within
>= font
->min_char_or_byte2
1096 && within
<= font
->max_char_or_byte2
1097 && row
>= font
->min_byte1
1098 && row
<= font
->max_byte1
))
1099 /* Still out of range means this char does not overlap. */
1102 /* We found the info for this char. */
1103 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1107 return (s
&& s
->rbearing
>= s
->width
);
1111 /* Invert the middle quarter of the frame for .15 sec. */
1113 /* We use the select system call to do the waiting, so we have to make sure
1114 it's available. If it isn't, we just won't do visual bells. */
1115 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1117 /* Subtract the `struct timeval' values X and Y,
1118 storing the result in RESULT.
1119 Return 1 if the difference is negative, otherwise 0. */
1122 timeval_subtract (result
, x
, y
)
1123 struct timeval
*result
, x
, y
;
1125 /* Perform the carry for the later subtraction by updating y.
1126 This is safer because on some systems
1127 the tv_sec member is unsigned. */
1128 if (x
.tv_usec
< y
.tv_usec
)
1130 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1131 y
.tv_usec
-= 1000000 * nsec
;
1134 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1136 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1137 y
.tv_usec
+= 1000000 * nsec
;
1141 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1142 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1143 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1145 /* Return indication of whether the result should be considered negative. */
1146 return x
.tv_sec
< y
.tv_sec
;
1157 /* Create a GC that will use the GXxor function to flip foreground pixels
1158 into background pixels. */
1162 values
.function
= GXxor
;
1163 values
.foreground
= (f
->display
.x
->foreground_pixel
1164 ^ f
->display
.x
->background_pixel
);
1166 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
1167 GCFunction
| GCForeground
, &values
);
1171 int width
= PIXEL_WIDTH (f
);
1172 int height
= PIXEL_HEIGHT (f
);
1174 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1175 width
/4, height
/4, width
/2, height
/2);
1176 XFlush (x_current_display
);
1179 struct timeval wakeup
, now
;
1181 EMACS_GET_TIME (wakeup
);
1183 /* Compute time to wait until, propagating carry from usecs. */
1184 wakeup
.tv_usec
+= 150000;
1185 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1186 wakeup
.tv_usec
%= 1000000;
1188 /* Keep waiting until past the time wakeup. */
1191 struct timeval timeout
;
1193 EMACS_GET_TIME (timeout
);
1195 /* In effect, timeout = wakeup - timeout.
1196 Break if result would be negative. */
1197 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1200 /* Try to wait that long--but we might wake up sooner. */
1201 select (0, 0, 0, 0, &timeout
);
1205 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1206 width
/4, height
/4, width
/2, height
/2);
1207 XFreeGC (x_current_display
, gc
);
1208 XFlush (x_current_display
);
1218 /* Make audible bell. */
1221 #define XRINGBELL XBell (x_current_display, 0)
1222 #else /* ! defined (HAVE_X11) */
1223 #define XRINGBELL XFeep (0);
1224 #endif /* ! defined (HAVE_X11) */
1228 if (x_current_display
== 0)
1231 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1233 XTflash (selected_frame
);
1244 /* Insert and delete character.
1245 These are not supposed to be used because we are supposed to turn
1246 off the feature of using them. */
1249 XTinsert_glyphs (start
, len
)
1250 register char *start
;
1263 /* Specify how many text lines, from the top of the window,
1264 should be affected by insert-lines and delete-lines operations.
1265 This, and those operations, are used only within an update
1266 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1269 XTset_terminal_window (n
)
1272 if (updating_frame
== 0)
1275 if ((n
<= 0) || (n
> updating_frame
->height
))
1276 flexlines
= updating_frame
->height
;
1281 /* Perform an insert-lines operation.
1282 Insert N lines at a vertical position curs_y. */
1288 register int topregion
, bottomregion
;
1289 register int length
, newtop
, mask
;
1290 register struct frame
*f
= updating_frame
;
1291 int intborder
= f
->display
.x
->internal_border_width
;
1293 if (curs_y
>= flexlines
)
1297 bottomregion
= flexlines
- (n
+ 1);
1298 newtop
= topregion
+ n
;
1299 length
= (bottomregion
- topregion
) + 1;
1303 #endif /* HAVE_X11 */
1305 if ((length
> 0) && (newtop
<= flexlines
))
1308 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1309 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1310 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1311 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1312 length
* f
->display
.x
->line_height
, intborder
,
1313 CHAR_TO_PIXEL_ROW (f
, newtop
));
1314 #else /* ! defined (HAVE_X11) */
1315 XMoveArea (FRAME_X_WINDOW (f
),
1316 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1317 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1318 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1319 length
* f
->display
.x
->line_height
);
1320 /* Now we must process any ExposeRegion events that occur
1321 if the area being copied from is obscured.
1322 We can't let it wait because further i/d operations
1323 may want to copy this area to another area. */
1325 #endif /* ! defined (HAVE_X11) */
1328 newtop
= min (newtop
, (flexlines
- 1));
1329 length
= newtop
- topregion
;
1333 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1334 CHAR_TO_PIXEL_ROW (f
, topregion
),
1335 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1336 n
* f
->display
.x
->line_height
, False
);
1337 #else /* ! defined (HAVE_X11) */
1338 XPixSet (FRAME_X_WINDOW (f
),
1340 CHAR_TO_PIXEL_ROW (f
, topregion
),
1341 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1342 n
* f
->display
.x
->line_height
,
1343 f
->display
.x
->background_pixel
);
1344 #endif /* ! defined (HAVE_X11) */
1348 /* Perform a delete-lines operation, deleting N lines
1349 at a vertical position curs_y. */
1356 register struct frame
*f
= updating_frame
;
1357 int intborder
= f
->display
.x
->internal_border_width
;
1359 if (curs_y
>= flexlines
)
1364 #endif /* HAVE_X11 */
1366 if ((curs_y
+ n
) >= flexlines
)
1368 if (flexlines
>= (curs_y
+ 1))
1371 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1372 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1373 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1374 (flexlines
- curs_y
) * f
->display
.x
->line_height
, False
);
1375 #else /* ! defined (HAVE_X11) */
1376 XPixSet (FRAME_X_WINDOW (f
),
1377 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1378 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1379 (flexlines
- curs_y
) * f
->display
.x
->line_height
,
1380 f
->display
.x
->background_pixel
);
1381 #endif /* ! defined (HAVE_X11) */
1387 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1388 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1390 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1391 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1392 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
,
1393 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1394 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1396 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1397 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1398 n
* f
->display
.x
->line_height
, False
);
1399 #else /* ! defined (HAVE_X11) */
1400 XMoveArea (FRAME_X_WINDOW (f
),
1402 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1403 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1404 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1405 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
);
1406 /* Now we must process any ExposeRegion events that occur
1407 if the area being copied from is obscured.
1408 We can't let it wait because further i/d operations
1409 may want to copy this area to another area. */
1411 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1412 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1413 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1414 n
* f
->display
.x
->line_height
, f
->display
.x
->background_pixel
);
1415 #endif /* ! defined (HAVE_X11) */
1419 /* Perform an insert-lines or delete-lines operation,
1420 inserting N lines or deleting -N lines at vertical position VPOS. */
1422 XTins_del_lines (vpos
, n
)
1425 if (updating_frame
== 0)
1428 /* Hide the cursor. */
1429 x_display_cursor (updating_frame
, 0);
1431 XTcursor_to (vpos
, 0);
1442 /* Support routines for exposure events. */
1443 static void clear_cursor ();
1445 /* Output into a rectangle of an X-window (for frame F)
1446 the characters in f->phys_lines that overlap that rectangle.
1447 TOP and LEFT are the position of the upper left corner of the rectangle.
1448 ROWS and COLS are the size of the rectangle.
1449 Call this function with input blocked. */
1452 dumprectangle (f
, left
, top
, cols
, rows
)
1454 register int left
, top
, cols
, rows
;
1456 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1457 int cursor_cleared
= 0;
1461 if (FRAME_GARBAGED_P (f
))
1464 /* Express rectangle as four edges, instead of position-and-size. */
1465 bottom
= top
+ rows
;
1466 right
= left
+ cols
;
1468 #ifndef HAVE_X11 /* Window manger does this for X11. */
1470 int intborder
= f
->display
.x
->internal_border_width
;
1472 /* If the rectangle includes any of the internal border area,
1473 redisplay the border emphasis. */
1474 if (top
< intborder
|| left
< intborder
1475 || bottom
> intborder
+ f
->height
* f
->display
.x
->line_height
1476 || right
> intborder
+ f
->width
* f
->display
.x
->line_height
)
1479 #endif /* not HAVE_X11 Window manger does this for X11. */
1481 /* Convert rectangle edges in pixels to edges in chars.
1482 Round down for left and top, up for right and bottom. */
1483 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1484 left
= PIXEL_TO_CHAR_COL (f
, left
);
1485 bottom
+= (f
->display
.x
->line_height
- 1);
1486 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1487 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1488 right
= PIXEL_TO_CHAR_COL (f
, right
);
1490 /* Clip the rectangle to what can be visible. */
1495 if (right
> f
->width
)
1497 if (bottom
> f
->height
)
1500 /* Get size in chars of the rectangle. */
1501 cols
= right
- left
;
1502 rows
= bottom
- top
;
1504 /* If rectangle has zero area, return. */
1505 if (rows
<= 0) return;
1506 if (cols
<= 0) return;
1508 /* Turn off the cursor if it is in the rectangle.
1509 We will turn it back on afterward. */
1510 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1511 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1517 /* Display the text in the rectangle, one text line at a time. */
1519 for (y
= top
; y
< bottom
; y
++)
1521 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1523 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1527 CHAR_TO_PIXEL_COL (f
, left
),
1528 CHAR_TO_PIXEL_ROW (f
, y
),
1529 line
, min (cols
, active_frame
->used
[y
] - left
),
1530 active_frame
->highlight
[y
], 0);
1533 /* Turn the cursor on if we turned it off. */
1536 x_display_cursor (f
, 1);
1540 /* Process all queued ExposeRegion events. */
1546 XExposeRegionEvent r
;
1548 while (dequeue_event (&r
, &x_expose_queue
))
1550 struct frame
*f
= x_window_to_frame (r
.window
);
1551 if (f
->display
.x
->icon_desc
== r
.window
)
1554 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1558 #endif /* HAVE_X11 */
1560 /* Process all expose events that are pending, for X10.
1561 Redraws the cursor if necessary on any frame that
1562 is not in the process of being updated with update_frame. */
1566 x_do_pending_expose ()
1570 Lisp_Object tail
, frame
;
1572 if (expose_all_windows
)
1574 expose_all_windows
= 0;
1575 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1577 register int temp_width
, temp_height
;
1580 frame
= XCONS (tail
)->car
;
1581 if (XGCTYPE (frame
) != Lisp_Frame
)
1584 if (! FRAME_X_P (f
))
1586 if (!f
->async_visible
)
1588 if (!f
->display
.x
->needs_exposure
)
1591 intborder
= f
->display
.x
->internal_border_width
;
1594 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1595 temp_width
= ((windowinfo
.width
- 2 * intborder
1596 - f
->display
.x
->v_scroll_bar_width
)
1597 / FONT_WIDTH (f
->display
.x
->font
));
1598 temp_height
= ((windowinfo
.height
- 2 * intborder
1599 - f
->display
.x
->h_scroll_bar_height
)
1600 / f
->display
.x
->line_height
);
1601 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1603 change_frame_size (f
, max (1, temp_height
),
1604 max (1, temp_width
), 0, 1);
1605 x_resize_scroll_bars (f
);
1607 f
->display
.x
->left_pos
= windowinfo
.x
;
1608 f
->display
.x
->top_pos
= windowinfo
.y
;
1609 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1613 f
->display
.x
->needs_exposure
= 0;
1614 if (updating_frame
!= f
)
1615 x_display_cursor (f
, 1);
1620 /* Handle any individual-rectangle expose events queued
1621 for various windows. */
1624 #else /* ! defined (HAVE_X11) */
1626 #endif /* ! defined (HAVE_X11) */
1632 frame_highlight (frame
)
1633 struct frame
*frame
;
1635 /* We used to only do this if Vx_no_window_manager was non-nil, but
1636 the ICCCM (section 4.1.6) says that the window's border pixmap
1637 and border pixel are window attributes which are "private to the
1638 client", so we can always change it to whatever we want. */
1640 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1641 frame
->display
.x
->border_pixel
);
1643 x_display_cursor (frame
, 1);
1647 frame_unhighlight (frame
)
1648 struct frame
*frame
;
1650 /* We used to only do this if Vx_no_window_manager was non-nil, but
1651 the ICCCM (section 4.1.6) says that the window's border pixmap
1652 and border pixel are window attributes which are "private to the
1653 client", so we can always change it to whatever we want. */
1655 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1656 frame
->display
.x
->border_tile
);
1658 x_display_cursor (frame
, 1);
1660 #else /* ! defined (HAVE_X11) */
1661 /* Dump the border-emphasis of frame F.
1662 If F is selected, this is a lining of the same color as the border,
1663 just within the border, occupying a portion of the internal border.
1664 If F is not selected, it is background in the same place.
1665 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1667 ALWAYS = 1 is used when a frame becomes selected or deselected.
1668 In that case, we also turn the cursor off and on again
1669 so it will appear in the proper shape (solid if selected; else hollow.) */
1672 dumpborder (f
, always
)
1676 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1677 int width
= PIXEL_WIDTH (f
);
1678 int height
= PIXEL_HEIGHT (f
);
1681 if (f
!= selected_frame
)
1686 pixel
= f
->display
.x
->background_pixel
;
1690 pixel
= f
->display
.x
->border_pixel
;
1693 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1694 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1695 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1697 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1701 x_display_cursor (f
, 1);
1703 #endif /* ! defined (HAVE_X11) */
1705 static void XTframe_rehighlight ();
1707 /* The focus has changed. Update the frames as necessary to reflect
1708 the new situation. Note that we can't change the selected frame
1709 here, because the lisp code we are interrupting might become confused.
1710 Each event gets marked with the frame in which it occurred, so the
1711 lisp code can tell when the switch took place by examining the events. */
1714 x_new_focus_frame (frame
)
1715 struct frame
*frame
;
1717 struct frame
*old_focus
= x_focus_frame
;
1718 int events_enqueued
= 0;
1720 if (frame
!= x_focus_frame
)
1722 /* Set this before calling other routines, so that they see
1723 the correct value of x_focus_frame. */
1724 x_focus_frame
= frame
;
1726 if (old_focus
&& old_focus
->auto_lower
)
1727 x_lower_frame (old_focus
);
1730 selected_frame
= frame
;
1731 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1732 Lisp_Frame
, selected_frame
);
1733 Fselect_window (selected_frame
->selected_window
);
1734 choose_minibuf_frame ();
1737 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1738 pending_autoraise_frame
= x_focus_frame
;
1740 pending_autoraise_frame
= 0;
1743 XTframe_rehighlight ();
1747 /* The focus has changed, or we have redirected a frame's focus to
1748 another frame (this happens when a frame uses a surrogate
1749 minibuffer frame). Shift the highlight as appropriate. */
1751 XTframe_rehighlight ()
1753 struct frame
*old_highlight
= x_highlight_frame
;
1758 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1759 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1761 if (! FRAME_LIVE_P (x_highlight_frame
))
1763 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1764 x_highlight_frame
= x_focus_frame
;
1768 x_highlight_frame
= 0;
1770 if (x_highlight_frame
!= old_highlight
)
1773 frame_unhighlight (old_highlight
);
1774 if (x_highlight_frame
)
1775 frame_highlight (x_highlight_frame
);
1779 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1781 /* Which modifier keys are on which modifier bits?
1783 With each keystroke, X returns eight bits indicating which modifier
1784 keys were held down when the key was pressed. The interpretation
1785 of the top five modifier bits depends on what keys are attached
1786 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1789 x_meta_mod_mask is a mask containing the bits used for the meta key.
1790 It may have more than one bit set, if more than one modifier bit
1791 has meta keys on it. Basically, if EVENT is a KeyPress event,
1792 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1794 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1795 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1796 only be affected by the lock modifier bit if XK_Shift_Lock is in
1797 use; XK_Caps_Lock should only affect alphabetic keys. With this
1798 arrangement, the lock modifier should shift the character if
1799 (EVENT.state & x_shift_lock_mask) != 0. */
1800 static int x_meta_mod_mask
, x_shift_lock_mask
;
1802 /* These are like x_meta_mod_mask, but for different modifiers. */
1803 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1805 /* Initialize mode_switch_bit and modifier_meaning. */
1807 x_find_modifier_meanings ()
1809 int min_code
, max_code
;
1812 XModifierKeymap
*mods
;
1814 x_meta_mod_mask
= 0;
1815 x_shift_lock_mask
= 0;
1817 x_super_mod_mask
= 0;
1818 x_hyper_mod_mask
= 0;
1821 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1823 min_code
= x_current_display
->min_keycode
;
1824 max_code
= x_current_display
->max_keycode
;
1827 syms
= XGetKeyboardMapping (x_current_display
,
1828 min_code
, max_code
- min_code
+ 1,
1830 mods
= XGetModifierMapping (x_current_display
);
1832 /* Scan the modifier table to see which modifier bits the Meta and
1833 Alt keysyms are on. */
1835 int row
, col
; /* The row and column in the modifier table. */
1837 for (row
= 3; row
< 8; row
++)
1838 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1841 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1843 /* Zeroes are used for filler. Skip them. */
1847 /* Are any of this keycode's keysyms a meta key? */
1851 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1853 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1859 x_meta_mod_mask
|= (1 << row
);
1864 x_alt_mod_mask
|= (1 << row
);
1869 x_hyper_mod_mask
|= (1 << row
);
1874 x_super_mod_mask
|= (1 << row
);
1878 /* Ignore this if it's not on the lock modifier. */
1879 if ((1 << row
) == LockMask
)
1880 x_shift_lock_mask
= LockMask
;
1888 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1889 if (! x_meta_mod_mask
)
1891 x_meta_mod_mask
= x_alt_mod_mask
;
1895 /* If some keys are both alt and meta,
1896 make them just meta, not alt. */
1897 if (x_alt_mod_mask
& x_meta_mod_mask
)
1899 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1902 XFree ((char *) syms
);
1903 XFreeModifiermap (mods
);
1906 /* Convert between the modifier bits X uses and the modifier bits
1909 x_x_to_emacs_modifiers (state
)
1912 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1913 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1914 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1915 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1916 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1917 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1921 x_emacs_to_x_modifiers (state
)
1924 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1925 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1926 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1927 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1928 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1929 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1932 /* Mouse clicks and mouse movement. Rah. */
1935 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1936 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1937 that the glyph at X, Y occupies, if BOUNDS != 0.
1938 If NOCLIP is nonzero, do not force the value into range. */
1941 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1943 register int pix_x
, pix_y
;
1944 register int *x
, *y
;
1948 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1949 even for negative values. */
1951 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1953 pix_y
-= (f
)->display
.x
->line_height
- 1;
1955 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1956 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1960 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1961 bounds
->height
= f
->display
.x
->line_height
;
1962 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1963 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1970 else if (pix_x
> f
->width
)
1975 else if (pix_y
> f
->height
)
1984 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1987 register int *pix_x
, *pix_y
;
1989 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1990 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1993 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1995 If the event is a button press, then note that we have grabbed
1999 construct_mouse_click (result
, event
, f
)
2000 struct input_event
*result
;
2001 XButtonEvent
*event
;
2004 /* Make the event type no_event; we'll change that when we decide
2006 result
->kind
= mouse_click
;
2007 result
->code
= event
->button
- Button1
;
2008 result
->timestamp
= event
->time
;
2009 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2010 | (event
->type
== ButtonRelease
2018 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2019 XFASTINT (result
->x
) = column
;
2020 XFASTINT (result
->y
) = row
;
2022 XSET (result
->x
, Lisp_Int
, event
->x
);
2023 XSET (result
->y
, Lisp_Int
, event
->y
);
2024 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2028 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2031 construct_menu_click (result
, event
, f
)
2032 struct input_event
*result
;
2033 XButtonEvent
*event
;
2036 /* Make the event type no_event; we'll change that when we decide
2038 result
->kind
= mouse_click
;
2039 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
2040 result
->timestamp
= event
->time
;
2041 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2042 | (event
->type
== ButtonRelease
2046 XSET (result
->x
, Lisp_Int
, event
->x
);
2047 XSET (result
->y
, Lisp_Int
, -1);
2048 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2051 /* Function to report a mouse movement to the mainstream Emacs code.
2052 The input handler calls this.
2054 We have received a mouse movement event, which is given in *event.
2055 If the mouse is over a different glyph than it was last time, tell
2056 the mainstream emacs code by setting mouse_moved. If not, ask for
2057 another motion event, so we can check again the next time it moves. */
2060 note_mouse_movement (frame
, event
)
2062 XMotionEvent
*event
;
2065 last_mouse_movement_time
= event
->time
;
2067 if (event
->window
!= FRAME_X_WINDOW (frame
))
2070 last_mouse_scroll_bar
= Qnil
;
2072 note_mouse_highlight (frame
, -1, -1);
2074 /* Ask for another mouse motion event. */
2077 Window dummy_window
;
2079 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2080 &dummy_window
, &dummy_window
,
2081 &dummy
, &dummy
, &dummy
, &dummy
,
2082 (unsigned int *) &dummy
);
2086 /* Has the mouse moved off the glyph it was on at the last sighting? */
2087 else if (event
->x
< last_mouse_glyph
.x
2088 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2089 || event
->y
< last_mouse_glyph
.y
2090 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2093 last_mouse_scroll_bar
= Qnil
;
2095 note_mouse_highlight (frame
, event
->x
, event
->y
);
2097 /* Ask for another mouse motion event. */
2100 Window dummy_window
;
2102 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2103 &dummy_window
, &dummy_window
,
2104 &dummy
, &dummy
, &dummy
, &dummy
,
2105 (unsigned int *) &dummy
);
2110 /* It's on the same glyph. Call XQueryPointer so we'll get an
2111 event the next time the mouse moves and we can see if it's
2112 *still* on the same glyph. */
2114 Window dummy_window
;
2116 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
2117 &dummy_window
, &dummy_window
,
2118 &dummy
, &dummy
, &dummy
, &dummy
,
2119 (unsigned int *) &dummy
);
2123 /* This is used for debugging, to turn off note_mouse_highlight. */
2124 static int disable_mouse_highlight
;
2126 /* Take proper action when the mouse has moved to position X, Y on frame F
2127 as regards highlighting characters that have mouse-face properties.
2128 Also dehighlighting chars where the mouse was before.
2129 X and Y can be negative or out of range. */
2132 note_mouse_highlight (f
, x
, y
)
2135 int row
, column
, portion
;
2136 XRectangle new_glyph
;
2140 if (disable_mouse_highlight
)
2143 mouse_face_mouse_x
= x
;
2144 mouse_face_mouse_y
= y
;
2145 mouse_face_mouse_frame
= f
;
2147 if (mouse_face_defer
)
2152 mouse_face_deferred_gc
= 1;
2156 /* Find out which glyph the mouse is on. */
2157 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2158 &new_glyph
, x_mouse_grabbed
);
2160 /* Which window is that in? */
2161 window
= window_from_coordinates (f
, column
, row
, &portion
);
2162 w
= XWINDOW (window
);
2164 /* If we were displaying active text in another window, clear that. */
2165 if (! EQ (window
, mouse_face_window
))
2166 clear_mouse_face ();
2168 /* Are we in a window whose display is up to date?
2169 And verify the buffer's text has not changed. */
2170 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2171 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2172 && EQ (w
->window_end_valid
, w
->buffer
)
2173 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
2175 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2178 /* Find which buffer position the mouse corresponds to. */
2179 for (i
= column
; i
>= 0; i
--)
2183 /* Is it outside the displayed active region (if any)? */
2185 clear_mouse_face ();
2186 else if (! (EQ (window
, mouse_face_window
)
2187 && row
>= mouse_face_beg_row
2188 && row
<= mouse_face_end_row
2189 && (row
> mouse_face_beg_row
|| column
>= mouse_face_beg_col
)
2190 && (row
< mouse_face_end_row
|| column
< mouse_face_end_col
2191 || mouse_face_past_end
)))
2193 Lisp_Object mouse_face
, overlay
, position
;
2194 Lisp_Object
*overlay_vec
;
2195 int len
, noverlays
, ignor1
;
2196 struct buffer
*obuf
;
2199 /* If we get an out-of-range value, return now; avoid an error. */
2200 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2203 /* Make the window's buffer temporarily current for
2204 overlays_at and compute_char_face. */
2205 obuf
= current_buffer
;
2206 current_buffer
= XBUFFER (w
->buffer
);
2212 /* Yes. Clear the display of the old active region, if any. */
2213 clear_mouse_face ();
2215 /* Is this char mouse-active? */
2216 XSET (position
, Lisp_Int
, pos
);
2219 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2221 /* Put all the overlays we want in a vector in overlay_vec.
2222 Store the length in len. */
2223 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
, &ignor1
);
2224 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2226 /* Find the highest priority overlay that has a mouse-face prop. */
2228 for (i
= 0; i
< noverlays
; i
++)
2230 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2231 if (!NILP (mouse_face
))
2233 overlay
= overlay_vec
[i
];
2238 /* If no overlay applies, get a text property. */
2240 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2242 /* Handle the overlay case. */
2243 if (! NILP (overlay
))
2245 /* Find the range of text around this char that
2246 should be active. */
2247 Lisp_Object before
, after
;
2250 before
= Foverlay_start (overlay
);
2251 after
= Foverlay_end (overlay
);
2252 /* Record this as the current active region. */
2253 fast_find_position (window
, before
, &mouse_face_beg_col
,
2254 &mouse_face_beg_row
);
2256 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2257 &mouse_face_end_row
);
2258 mouse_face_window
= window
;
2259 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
2260 &ignore
, pos
+ 1, 1);
2262 /* Display it as active. */
2263 show_mouse_face (1);
2265 /* Handle the text property case. */
2266 else if (! NILP (mouse_face
))
2268 /* Find the range of text around this char that
2269 should be active. */
2270 Lisp_Object before
, after
, beginning
, end
;
2273 beginning
= Fmarker_position (w
->start
);
2274 XSET (end
, Lisp_Int
,
2275 (BUF_Z (XBUFFER (w
->buffer
))
2276 - XFASTINT (w
->window_end_pos
)));
2278 = Fprevious_single_property_change (make_number (pos
+ 1),
2280 w
->buffer
, beginning
);
2282 = Fnext_single_property_change (position
, Qmouse_face
,
2284 /* Record this as the current active region. */
2285 fast_find_position (window
, before
, &mouse_face_beg_col
,
2286 &mouse_face_beg_row
);
2288 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2289 &mouse_face_end_row
);
2290 mouse_face_window
= window
;
2292 = compute_char_face (f
, w
, pos
, 0, 0,
2293 &ignore
, pos
+ 1, 1);
2295 /* Display it as active. */
2296 show_mouse_face (1);
2300 current_buffer
= obuf
;
2305 /* Find the row and column of position POS in window WINDOW.
2306 Store them in *COLUMNP and *ROWP.
2307 This assumes display in WINDOW is up to date.
2308 If POS is above start of WINDOW, return coords
2309 of start of first screen line.
2310 If POS is after end of WINDOW, return coords of end of last screen line.
2312 Value is 1 if POS is in range, 0 if it was off screen. */
2315 fast_find_position (window
, pos
, columnp
, rowp
)
2318 int *columnp
, *rowp
;
2320 struct window
*w
= XWINDOW (window
);
2321 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2326 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2327 int width
= window_internal_width (w
);
2331 /* Find the right row. */
2336 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2337 if (linestart
> pos
)
2343 /* Find the right column with in it. */
2344 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2346 for (i
= 0; i
< width
; i
++)
2348 if (charstarts
[left
+ i
] == pos
)
2351 *columnp
= i
+ left
;
2354 else if (charstarts
[left
+ i
] > pos
)
2356 else if (charstarts
[left
+ i
] > 0)
2365 /* Display the active region described by mouse_face_*
2366 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2369 show_mouse_face (hl
)
2372 struct window
*w
= XWINDOW (mouse_face_window
);
2373 int width
= window_internal_width (w
);
2374 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2377 int old_curs_x
= curs_x
;
2378 int old_curs_y
= curs_y
;
2380 /* Set these variables temporarily
2381 so that if we have to turn the cursor off and on again
2382 we will put it back at the same place. */
2383 curs_x
= f
->phys_cursor_x
;
2384 curs_y
= f
->phys_cursor_y
;
2386 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2388 int column
= (i
== mouse_face_beg_row
? mouse_face_beg_col
: w
->left
);
2389 int endcolumn
= (i
== mouse_face_end_row
? mouse_face_end_col
: w
->left
+ width
);
2390 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2392 /* If the cursor's in the text we are about to rewrite,
2393 turn the cursor off. */
2395 && curs_x
>= mouse_face_beg_col
- 1 && curs_x
<= mouse_face_end_col
)
2397 x_display_cursor (f
, 0);
2402 CHAR_TO_PIXEL_COL (f
, column
),
2403 CHAR_TO_PIXEL_ROW (f
, i
),
2404 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2406 /* Highlight with mouse face if hl > 0. */
2410 /* If we turned the cursor off, turn it back on. */
2412 x_display_cursor (f
, 1);
2414 curs_x
= old_curs_x
;
2415 curs_y
= old_curs_y
;
2417 /* Change the mouse cursor according to the value of HL. */
2419 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->cross_cursor
);
2421 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->text_cursor
);
2424 /* Clear out the mouse-highlighted active region.
2425 Redraw it unhighlighted first. */
2430 if (! NILP (mouse_face_window
))
2431 show_mouse_face (0);
2433 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2434 mouse_face_end_row
= mouse_face_end_col
= -1;
2435 mouse_face_window
= Qnil
;
2438 static struct scroll_bar
*x_window_to_scroll_bar ();
2439 static void x_scroll_bar_report_motion ();
2441 /* Return the current position of the mouse.
2443 If the mouse movement started in a scroll bar, set *f, *bar_window,
2444 and *part to the frame, window, and scroll bar part that the mouse
2445 is over. Set *x and *y to the portion and whole of the mouse's
2446 position on the scroll bar.
2448 If the mouse movement started elsewhere, set *f to the frame the
2449 mouse is on, *bar_window to nil, and *x and *y to the character cell
2452 Set *time to the server timestamp for the time at which the mouse
2453 was at this position.
2455 Don't store anything if we don't have a valid set of values to report.
2457 This clears the mouse_moved flag, so we can wait for the next mouse
2458 movement. This also calls XQueryPointer, which will cause the
2459 server to give us another MotionNotify when the mouse moves
2463 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
2465 Lisp_Object
*bar_window
;
2466 enum scroll_bar_part
*part
;
2468 unsigned long *time
;
2474 if (! NILP (last_mouse_scroll_bar
))
2475 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
2481 Window dummy_window
;
2485 last_mouse_scroll_bar
= Qnil
;
2487 /* Figure out which root window we're on. */
2488 XQueryPointer (x_current_display
,
2489 DefaultRootWindow (x_current_display
),
2491 /* The root window which contains the pointer. */
2494 /* Trash which we can't trust if the pointer is on
2495 a different screen. */
2498 /* The position on that root window. */
2501 /* More trash we can't trust. */
2504 /* Modifier keys and pointer buttons, about which
2506 (unsigned int *) &dummy
);
2508 /* Now we have a position on the root; find the innermost window
2509 containing the pointer. */
2513 int parent_x
, parent_y
;
2517 if (x_mouse_grabbed
&& last_mouse_frame
2518 && FRAME_LIVE_P (last_mouse_frame
))
2520 /* If mouse was grabbed on a frame, give coords for that frame
2521 even if the mouse is now outside it. */
2522 XTranslateCoordinates (x_current_display
,
2524 /* From-window, to-window. */
2525 root
, FRAME_X_WINDOW (last_mouse_frame
),
2527 /* From-position, to-position. */
2528 root_x
, root_y
, &win_x
, &win_y
,
2532 f1
= last_mouse_frame
;
2538 XTranslateCoordinates (x_current_display
,
2540 /* From-window, to-window. */
2543 /* From-position, to-position. */
2544 root_x
, root_y
, &win_x
, &win_y
,
2557 /* Now we know that:
2558 win is the innermost window containing the pointer
2559 (XTC says it has no child containing the pointer),
2560 win_x and win_y are the pointer's position in it
2561 (XTC did this the last time through), and
2562 parent_x and parent_y are the pointer's position in win's parent.
2563 (They are what win_x and win_y were when win was child.
2564 If win is the root window, it has no parent, and
2565 parent_{x,y} are invalid, but that's okay, because we'll
2566 never use them in that case.) */
2568 /* Is win one of our frames? */
2569 f1
= x_any_window_to_frame (win
);
2572 /* If not, is it one of our scroll bars? */
2575 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2579 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2587 int ignore1
, ignore2
;
2589 /* Ok, we found a frame. Store all the values. */
2591 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2592 &last_mouse_glyph
, x_mouse_grabbed
);
2597 XSET (*x
, Lisp_Int
, win_x
);
2598 XSET (*y
, Lisp_Int
, win_y
);
2599 *time
= last_mouse_movement_time
;
2607 #else /* ! defined (HAVE_X11) */
2608 #define XEvent XKeyPressedEvent
2609 #endif /* ! defined (HAVE_X11) */
2611 /* Scroll bar support. */
2613 /* Given an X window ID, find the struct scroll_bar which manages it.
2614 This can be called in GC, so we have to make sure to strip off mark
2616 static struct scroll_bar
*
2617 x_window_to_scroll_bar (window_id
)
2620 Lisp_Object tail
, frame
;
2622 for (tail
= Vframe_list
;
2623 XGCTYPE (tail
) == Lisp_Cons
;
2624 tail
= XCONS (tail
)->cdr
)
2626 Lisp_Object frame
, bar
, condemned
;
2628 frame
= XCONS (tail
)->car
;
2629 /* All elements of Vframe_list should be frames. */
2630 if (XGCTYPE (frame
) != Lisp_Frame
)
2633 /* Scan this frame's scroll bar list for a scroll bar with the
2635 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2636 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2637 /* This trick allows us to search both the ordinary and
2638 condemned scroll bar lists with one loop. */
2639 ! GC_NILP (bar
) || (bar
= condemned
,
2642 bar
= XSCROLL_BAR (bar
)->next
)
2643 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2644 return XSCROLL_BAR (bar
);
2650 /* Open a new X window to serve as a scroll bar, and return the
2651 scroll bar vector for it. */
2652 static struct scroll_bar
*
2653 x_scroll_bar_create (window
, top
, left
, width
, height
)
2654 struct window
*window
;
2655 int top
, left
, width
, height
;
2657 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2658 struct scroll_bar
*bar
=
2659 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2664 XSetWindowAttributes a
;
2666 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2667 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2668 | ButtonMotionMask
| PointerMotionHintMask
2670 a
.cursor
= x_vertical_scroll_bar_cursor
;
2672 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2677 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2678 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2679 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2680 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2681 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2682 sb_widget
= XtCreateManagedWidget ("box",
2684 frame
->display
.x
->edit_widget
, al
, ac
);
2685 SET_SCROLL_BAR_X_WINDOW
2686 (bar
, sb_widget
->core
.window
);
2688 SET_SCROLL_BAR_X_WINDOW
2690 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2692 /* Position and size of scroll bar. */
2693 left
, top
, width
, height
,
2695 /* Border width, depth, class, and visual. */
2696 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2702 XSET (bar
->window
, Lisp_Window
, window
);
2703 XSET (bar
->top
, Lisp_Int
, top
);
2704 XSET (bar
->left
, Lisp_Int
, left
);
2705 XSET (bar
->width
, Lisp_Int
, width
);
2706 XSET (bar
->height
, Lisp_Int
, height
);
2707 XSET (bar
->start
, Lisp_Int
, 0);
2708 XSET (bar
->end
, Lisp_Int
, 0);
2709 bar
->dragging
= Qnil
;
2711 /* Add bar to its frame's list of scroll bars. */
2712 bar
->next
= FRAME_SCROLL_BARS (frame
);
2714 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2715 if (! NILP (bar
->next
))
2716 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2718 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2725 /* Draw BAR's handle in the proper position.
2726 If the handle is already drawn from START to END, don't bother
2727 redrawing it, unless REBUILD is non-zero; in that case, always
2728 redraw it. (REBUILD is handy for drawing the handle after expose
2731 Normally, we want to constrain the start and end of the handle to
2732 fit inside its rectangle, but if the user is dragging the scroll bar
2733 handle, we want to let them drag it down all the way, so that the
2734 bar's top is as far down as it goes; otherwise, there's no way to
2735 move to the very end of the buffer. */
2737 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2738 struct scroll_bar
*bar
;
2742 int dragging
= ! NILP (bar
->dragging
);
2743 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2744 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2746 /* If the display is already accurate, do nothing. */
2748 && start
== XINT (bar
->start
)
2749 && end
== XINT (bar
->end
))
2755 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2756 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2757 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2759 /* Make sure the values are reasonable, and try to preserve
2760 the distance between start and end. */
2762 int length
= end
- start
;
2766 else if (start
> top_range
)
2768 end
= start
+ length
;
2772 else if (end
> top_range
&& ! dragging
)
2776 /* Store the adjusted setting in the scroll bar. */
2777 XSET (bar
->start
, Lisp_Int
, start
);
2778 XSET (bar
->end
, Lisp_Int
, end
);
2780 /* Clip the end position, just for display. */
2781 if (end
> top_range
)
2784 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2785 below top positions, to make sure the handle is always at least
2786 that many pixels tall. */
2787 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2789 /* Draw the empty space above the handle. Note that we can't clear
2790 zero-height areas; that means "clear to end of window." */
2792 XClearArea (x_current_display
, w
,
2794 /* x, y, width, height, and exposures. */
2795 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2796 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2797 inside_width
, start
,
2800 /* Draw the handle itself. */
2801 XFillRectangle (x_current_display
, w
, gc
,
2803 /* x, y, width, height */
2804 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2805 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2806 inside_width
, end
- start
);
2809 /* Draw the empty space below the handle. Note that we can't
2810 clear zero-height areas; that means "clear to end of window." */
2811 if (end
< inside_height
)
2812 XClearArea (x_current_display
, w
,
2814 /* x, y, width, height, and exposures. */
2815 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2816 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2817 inside_width
, inside_height
- end
,
2825 /* Move a scroll bar around on the screen, to accommodate changing
2826 window configurations. */
2828 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2829 struct scroll_bar
*bar
;
2830 int top
, left
, width
, height
;
2836 unsigned int mask
= 0;
2843 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2844 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2845 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2846 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2849 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2853 XSET (bar
->left
, Lisp_Int
, left
);
2854 XSET (bar
->top
, Lisp_Int
, top
);
2855 XSET (bar
->width
, Lisp_Int
, width
);
2856 XSET (bar
->height
, Lisp_Int
, height
);
2861 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2864 x_scroll_bar_remove (bar
)
2865 struct scroll_bar
*bar
;
2867 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2871 /* Destroy the window. */
2872 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2874 /* Disassociate this scroll bar from its window. */
2875 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2880 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2881 that we are displaying PORTION characters out of a total of WHOLE
2882 characters, starting at POSITION. If WINDOW has no scroll bar,
2885 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2886 struct window
*window
;
2887 int portion
, whole
, position
;
2889 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2890 int top
= XINT (window
->top
);
2891 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2892 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2894 /* Where should this scroll bar be, pixelwise? */
2895 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2896 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2897 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2898 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2900 struct scroll_bar
*bar
;
2902 /* Does the scroll bar exist yet? */
2903 if (NILP (window
->vertical_scroll_bar
))
2904 bar
= x_scroll_bar_create (window
,
2905 pixel_top
, pixel_left
,
2906 pixel_width
, pixel_height
);
2909 /* It may just need to be moved and resized. */
2910 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2911 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2914 /* Set the scroll bar's current state, unless we're currently being
2916 if (NILP (bar
->dragging
))
2919 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2922 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2925 int start
= ((double) position
* top_range
) / whole
;
2926 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2928 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2932 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2936 /* The following three hooks are used when we're doing a thorough
2937 redisplay of the frame. We don't explicitly know which scroll bars
2938 are going to be deleted, because keeping track of when windows go
2939 away is a real pain - "Can you say set-window-configuration, boys
2940 and girls?" Instead, we just assert at the beginning of redisplay
2941 that *all* scroll bars are to be removed, and then save a scroll bar
2942 from the fiery pit when we actually redisplay its window. */
2944 /* Arrange for all scroll bars on FRAME to be removed at the next call
2945 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2946 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2948 XTcondemn_scroll_bars (frame
)
2951 /* The condemned list should be empty at this point; if it's not,
2952 then the rest of Emacs isn't using the condemn/redeem/judge
2953 protocol correctly. */
2954 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2957 /* Move them all to the "condemned" list. */
2958 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2959 FRAME_SCROLL_BARS (frame
) = Qnil
;
2962 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2963 Note that WINDOW isn't necessarily condemned at all. */
2965 XTredeem_scroll_bar (window
)
2966 struct window
*window
;
2968 struct scroll_bar
*bar
;
2970 /* We can't redeem this window's scroll bar if it doesn't have one. */
2971 if (NILP (window
->vertical_scroll_bar
))
2974 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2976 /* Unlink it from the condemned list. */
2978 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2980 if (NILP (bar
->prev
))
2982 /* If the prev pointer is nil, it must be the first in one of
2984 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2985 /* It's not condemned. Everything's fine. */
2987 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2988 window
->vertical_scroll_bar
))
2989 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2991 /* If its prev pointer is nil, it must be at the front of
2992 one or the other! */
2996 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2998 if (! NILP (bar
->next
))
2999 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3001 bar
->next
= FRAME_SCROLL_BARS (f
);
3003 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
3004 if (! NILP (bar
->next
))
3005 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
3009 /* Remove all scroll bars on FRAME that haven't been saved since the
3010 last call to `*condemn_scroll_bars_hook'. */
3012 XTjudge_scroll_bars (f
)
3015 Lisp_Object bar
, next
;
3017 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3019 /* Clear out the condemned list now so we won't try to process any
3020 more events on the hapless scroll bars. */
3021 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3023 for (; ! NILP (bar
); bar
= next
)
3025 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3027 x_scroll_bar_remove (b
);
3030 b
->next
= b
->prev
= Qnil
;
3033 /* Now there should be no references to the condemned scroll bars,
3034 and they should get garbage-collected. */
3038 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3040 This may be called from a signal handler, so we have to ignore GC
3043 x_scroll_bar_expose (bar
, event
)
3044 struct scroll_bar
*bar
;
3047 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3048 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
3052 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3054 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3055 XDrawRectangle (x_current_display
, w
, gc
,
3057 /* x, y, width, height */
3058 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
3063 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3064 is set to something other than no_event, it is enqueued.
3066 This may be called from a signal handler, so we have to ignore GC
3069 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3070 struct scroll_bar
*bar
;
3072 struct input_event
*emacs_event
;
3074 if (XGCTYPE (bar
->window
) != Lisp_Window
)
3077 emacs_event
->kind
= scroll_bar_click
;
3078 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3079 emacs_event
->modifiers
=
3080 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
3081 | (event
->type
== ButtonRelease
3084 emacs_event
->frame_or_window
= bar
->window
;
3085 emacs_event
->timestamp
= event
->xbutton
.time
;
3087 int internal_height
=
3088 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3090 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3091 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3094 if (y
> top_range
) y
= top_range
;
3096 if (y
< XINT (bar
->start
))
3097 emacs_event
->part
= scroll_bar_above_handle
;
3098 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3099 emacs_event
->part
= scroll_bar_handle
;
3101 emacs_event
->part
= scroll_bar_below_handle
;
3103 /* Just because the user has clicked on the handle doesn't mean
3104 they want to drag it. Lisp code needs to be able to decide
3105 whether or not we're dragging. */
3107 /* If the user has just clicked on the handle, record where they're
3109 if (event
->type
== ButtonPress
3110 && emacs_event
->part
== scroll_bar_handle
)
3111 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
3114 /* If the user has released the handle, set it to its final position. */
3115 if (event
->type
== ButtonRelease
3116 && ! NILP (bar
->dragging
))
3118 int new_start
= y
- XINT (bar
->dragging
);
3119 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3121 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3122 bar
->dragging
= Qnil
;
3125 /* Same deal here as the other #if 0. */
3127 /* Clicks on the handle are always reported as occurring at the top of
3129 if (emacs_event
->part
== scroll_bar_handle
)
3130 emacs_event
->x
= bar
->start
;
3132 XSET (emacs_event
->x
, Lisp_Int
, y
);
3134 XSET (emacs_event
->x
, Lisp_Int
, y
);
3137 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
3141 /* Handle some mouse motion while someone is dragging the scroll bar.
3143 This may be called from a signal handler, so we have to ignore GC
3146 x_scroll_bar_note_movement (bar
, event
)
3147 struct scroll_bar
*bar
;
3150 last_mouse_movement_time
= event
->xmotion
.time
;
3153 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
3155 /* If we're dragging the bar, display it. */
3156 if (! GC_NILP (bar
->dragging
))
3158 /* Where should the handle be now? */
3159 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3161 if (new_start
!= XINT (bar
->start
))
3163 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3165 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3169 /* Call XQueryPointer so we'll get an event the next time the mouse
3170 moves and we can see *still* on the same position. */
3173 Window dummy_window
;
3175 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3176 &dummy_window
, &dummy_window
,
3177 &dummy
, &dummy
, &dummy
, &dummy
,
3178 (unsigned int *) &dummy
);
3182 /* Return information to the user about the current position of the mouse
3183 on the scroll bar. */
3185 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
3187 Lisp_Object
*bar_window
;
3188 enum scroll_bar_part
*part
;
3190 unsigned long *time
;
3192 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3194 Window dummy_window
;
3196 unsigned int dummy_mask
;
3200 /* Get the mouse's position relative to the scroll bar window, and
3202 if (! XQueryPointer (x_current_display
,
3203 SCROLL_BAR_X_WINDOW (bar
),
3205 /* Root, child, root x and root y. */
3206 &dummy_window
, &dummy_window
,
3207 &dummy_coord
, &dummy_coord
,
3209 /* Position relative to scroll bar. */
3212 /* Mouse buttons and modifier keys. */
3218 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3220 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3222 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3224 if (! NILP (bar
->dragging
))
3225 win_y
-= XINT (bar
->dragging
);
3229 if (win_y
> top_range
)
3232 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3233 *bar_window
= bar
->window
;
3235 if (! NILP (bar
->dragging
))
3236 *part
= scroll_bar_handle
;
3237 else if (win_y
< XINT (bar
->start
))
3238 *part
= scroll_bar_above_handle
;
3239 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3240 *part
= scroll_bar_handle
;
3242 *part
= scroll_bar_below_handle
;
3244 XSET (*x
, Lisp_Int
, win_y
);
3245 XSET (*y
, Lisp_Int
, top_range
);
3248 last_mouse_scroll_bar
= Qnil
;
3251 *time
= last_mouse_movement_time
;
3257 /* The screen has been cleared so we may have changed foreground or
3258 background colors, and the scroll bars may need to be redrawn.
3259 Clear out the scroll bars, and ask for expose events, so we can
3262 x_scroll_bar_clear (f
)
3267 for (bar
= FRAME_SCROLL_BARS (f
);
3268 XTYPE (bar
) == Lisp_Vector
;
3269 bar
= XSCROLL_BAR (bar
)->next
)
3270 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3274 /* This processes Expose events from the menubar specific X event
3275 loop in menubar.c. This allows to redisplay the frame if necessary
3276 when handling menubar or popup items. */
3279 process_expose_from_menu (event
)
3286 f
= x_window_to_frame (event
.xexpose
.window
);
3289 if (f
->async_visible
== 0)
3291 f
->async_visible
= 1;
3292 f
->async_iconified
= 0;
3293 SET_FRAME_GARBAGED (f
);
3297 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3298 event
.xexpose
.x
, event
.xexpose
.y
,
3299 event
.xexpose
.width
, event
.xexpose
.height
);
3304 struct scroll_bar
*bar
3305 = x_window_to_scroll_bar (event
.xexpose
.window
);
3308 x_scroll_bar_expose (bar
, &event
);
3314 /* Define a queue to save up SelectionRequest events for later handling. */
3316 struct selection_event_queue
3319 struct selection_event_queue
*next
;
3322 static struct selection_event_queue
*queue
;
3324 /* Nonzero means queue up certain events--don't process them yet. */
3325 static int x_queue_selection_requests
;
3327 /* Queue up an X event *EVENT, to be processed later. */
3330 x_queue_event (event
)
3333 struct selection_event_queue
*queue_tmp
3334 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3336 if (queue_tmp
!= NULL
)
3338 queue_tmp
->event
= *event
;
3339 queue_tmp
->next
= queue
;
3344 /* Take all the queued events and put them back
3345 so that they get processed afresh. */
3350 while (queue
!= NULL
)
3352 struct selection_event_queue
*queue_tmp
= queue
;
3353 XPutBackEvent (XDISPLAY
&queue_tmp
->event
);
3354 queue
= queue_tmp
->next
;
3355 free ((char *)queue_tmp
);
3359 /* Start queuing SelectionRequest events. */
3362 x_start_queuing_selection_requests ()
3364 x_queue_selection_requests
++;
3367 /* Stop queuing SelectionRequest events. */
3370 x_stop_queuing_selection_requests ()
3372 x_queue_selection_requests
--;
3373 x_unqueue_events ();
3376 /* The main X event-reading loop - XTread_socket. */
3378 /* Timestamp of enter window event. This is only used by XTread_socket,
3379 but we have to put it out here, since static variables within functions
3380 sometimes don't work. */
3381 static Time enter_timestamp
;
3383 /* This holds the state XLookupString needs to implement dead keys
3384 and other tricks known as "compose processing". _X Window System_
3385 says that a portable program can't use this, but Stephen Gildea assures
3386 me that letting the compiler initialize it to zeros will work okay.
3388 This must be defined outside of XTread_socket, for the same reasons
3389 given for enter_timestamp, above. */
3390 static XComposeStatus compose_status
;
3392 /* Communication with window managers. */
3393 Atom Xatom_wm_protocols
;
3395 /* Kinds of protocol things we may receive. */
3396 Atom Xatom_wm_take_focus
;
3397 Atom Xatom_wm_save_yourself
;
3398 Atom Xatom_wm_delete_window
;
3400 /* Other WM communication */
3401 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3402 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3404 /* Window manager communication. */
3405 Atom Xatom_wm_change_state
;
3407 /* EditRes protocol */
3408 Atom Xatom_editres_name
;
3410 /* Record the last 100 characters stored
3411 to help debug the loss-of-chars-during-GC problem. */
3413 short temp_buffer
[100];
3415 /* Read events coming from the X server.
3416 This routine is called by the SIGIO handler.
3417 We return as soon as there are no more events to be read.
3419 Events representing keys are stored in buffer BUFP,
3420 which can hold up to NUMCHARS characters.
3421 We return the number of characters stored into the buffer,
3422 thus pretending to be `read'.
3424 WAITP is nonzero if we should block until input arrives.
3425 EXPECTED is nonzero if the caller knows input is available. */
3428 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3430 register struct input_event
*bufp
;
3431 register int numchars
;
3438 int items_pending
; /* How many items are in the X queue. */
3441 int event_found
= 0;
3445 if (interrupt_input_blocked
)
3447 interrupt_input_pending
= 1;
3451 interrupt_input_pending
= 0;
3455 abort (); /* Don't think this happens. */
3458 /* If available, Xlib uses FIOSNBIO to make the socket
3459 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3460 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3461 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3462 fcntl (fileno (stdin
), F_SETFL
, 0);
3463 #endif /* ! defined (FIOSNBIO) */
3467 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3469 extern int read_alarm_should_throw
;
3470 read_alarm_should_throw
= 1;
3471 XPeekEvent (XDISPLAY
&event
);
3472 read_alarm_should_throw
= 0;
3474 #endif /* HAVE_SELECT */
3477 while (XStuffPending () != 0)
3479 XNextEvent (XDISPLAY
&event
);
3487 if (event
.xclient
.message_type
== Xatom_wm_protocols
3488 && event
.xclient
.format
== 32)
3490 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3492 f
= x_window_to_frame (event
.xclient
.window
);
3493 /* Since we set WM_TAKE_FOCUS, we must call
3494 XSetInputFocus explicitly. But not if f is null,
3495 since that might be an event for a deleted frame. */
3497 XSetInputFocus (event
.xclient
.display
,
3498 event
.xclient
.window
,
3499 RevertToPointerRoot
,
3500 event
.xclient
.data
.l
[1]);
3501 /* Not certain about handling scroll bars here */
3503 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3505 /* Save state modify the WM_COMMAND property to
3506 something which can reinstate us. This notifies
3507 the session manager, who's looking for such a
3508 PropertyNotify. Can restart processing when
3509 a keyboard or mouse event arrives. */
3512 /* This is just so we only give real data once
3513 for a single Emacs process. */
3514 if (x_top_window_to_frame (event
.xclient
.window
)
3516 XSetCommand (x_current_display
,
3517 event
.xclient
.window
,
3518 initial_argv
, initial_argc
);
3520 XSetCommand (x_current_display
,
3521 event
.xclient
.window
,
3525 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3527 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3534 bufp
->kind
= delete_window_event
;
3535 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3543 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3546 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3549 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3551 new_x
= event
.xclient
.data
.s
[0];
3552 new_y
= event
.xclient
.data
.s
[1];
3556 f
->display
.x
->left_pos
= new_x
;
3557 f
->display
.x
->top_pos
= new_y
;
3560 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3561 else if (event
.xclient
.message_type
== Xatom_editres_name
)
3563 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3564 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3566 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3570 case SelectionNotify
:
3571 #ifdef USE_X_TOOLKIT
3572 if (! x_window_to_frame (event
.xselection
.requestor
))
3574 #endif /* not USE_X_TOOLKIT */
3575 x_handle_selection_notify (&event
);
3578 case SelectionClear
: /* Someone has grabbed ownership. */
3579 #ifdef USE_X_TOOLKIT
3580 if (! x_window_to_frame (event
.xselectionclear
.window
))
3582 #endif /* USE_X_TOOLKIT */
3584 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3589 bufp
->kind
= selection_clear_event
;
3590 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3591 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3592 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3600 case SelectionRequest
: /* Someone wants our selection. */
3601 #ifdef USE_X_TOOLKIT
3602 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3604 #endif /* USE_X_TOOLKIT */
3605 if (x_queue_selection_requests
)
3606 x_queue_event (&event
);
3609 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3614 bufp
->kind
= selection_request_event
;
3615 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3616 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3617 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3618 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3619 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3620 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3628 case PropertyNotify
:
3629 #ifdef USE_X_TOOLKIT
3630 if (!x_any_window_to_frame (event
.xproperty
.window
))
3632 #endif /* not USE_X_TOOLKIT */
3633 x_handle_property_notify (&event
);
3636 case ReparentNotify
:
3637 f
= x_top_window_to_frame (event
.xreparent
.window
);
3641 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3642 x_real_positions (f
, &x
, &y
);
3643 f
->display
.x
->left_pos
= x
;
3644 f
->display
.x
->top_pos
= y
;
3649 f
= x_window_to_frame (event
.xexpose
.window
);
3652 if (f
->async_visible
== 0)
3654 f
->async_visible
= 1;
3655 f
->async_iconified
= 0;
3656 SET_FRAME_GARBAGED (f
);
3659 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3660 event
.xexpose
.x
, event
.xexpose
.y
,
3661 event
.xexpose
.width
, event
.xexpose
.height
);
3665 struct scroll_bar
*bar
3666 = x_window_to_scroll_bar (event
.xexpose
.window
);
3669 x_scroll_bar_expose (bar
, &event
);
3670 #ifdef USE_X_TOOLKIT
3673 #endif /* USE_X_TOOLKIT */
3677 case GraphicsExpose
: /* This occurs when an XCopyArea's
3678 source area was obscured or not
3680 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3684 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3685 event
.xgraphicsexpose
.width
,
3686 event
.xgraphicsexpose
.height
);
3688 #ifdef USE_X_TOOLKIT
3691 #endif /* USE_X_TOOLKIT */
3694 case NoExpose
: /* This occurs when an XCopyArea's
3695 source area was completely
3698 #else /* ! defined (HAVE_X11) */
3700 if (event
.subwindow
!= 0)
3701 break; /* duplicate event */
3702 f
= x_window_to_frame (event
.window
);
3703 if (event
.window
== f
->display
.x
->icon_desc
)
3706 f
->async_iconified
= 1;
3708 if (event
.window
== FRAME_X_WINDOW (f
))
3710 /* Say must check all windows' needs_exposure flags. */
3711 expose_all_windows
= 1;
3712 f
->display
.x
->needs_exposure
= 1;
3713 f
->async_visible
= 1;
3718 if (event
.subwindow
!= 0)
3719 break; /* duplicate event */
3720 f
= x_window_to_frame (event
.window
);
3721 if (event
.window
== f
->display
.x
->icon_desc
)
3726 /* If window already needs full redraw, ignore this rectangle. */
3727 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3729 /* Put the event on the queue of rectangles to redraw. */
3730 if (enqueue_event (&event
, &x_expose_queue
))
3731 /* If it is full, we can't record the rectangle,
3732 so redraw this entire window. */
3734 /* Say must check all windows' needs_exposure flags. */
3735 expose_all_windows
= 1;
3736 f
->display
.x
->needs_exposure
= 1;
3741 /* This should happen only when we are expecting it,
3742 in x_read_exposes. */
3744 #endif /* ! defined (HAVE_X11) */
3748 f
= x_any_window_to_frame (event
.xunmap
.window
);
3749 if (f
) /* F may no longer exist if
3750 the frame was deleted. */
3752 /* While a frame is unmapped, display generation is
3753 disabled; you don't want to spend time updating a
3754 display that won't ever be seen. */
3755 f
->async_visible
= 0;
3756 /* We can't distinguish, from the event, whether the window
3757 has become iconified or invisible. So assume, if it
3758 was previously visible, than now it is iconified.
3759 We depend on x_make_frame_invisible to mark it iconified. */
3760 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3761 f
->async_iconified
= 1;
3763 #ifdef USE_X_TOOLKIT
3765 #endif /* USE_X_TOOLKIT */
3769 /* We use x_top_window_to_frame because map events can come
3770 for subwindows and they don't mean that the frame is visible. */
3771 f
= x_top_window_to_frame (event
.xmap
.window
);
3774 f
->async_visible
= 1;
3775 f
->async_iconified
= 0;
3777 /* wait_reading_process_input will notice this and update
3778 the frame's display structures. */
3779 SET_FRAME_GARBAGED (f
);
3781 #ifdef USE_X_TOOLKIT
3783 #endif /* USE_X_TOOLKIT */
3786 /* Turn off processing if we become fully obscured. */
3787 case VisibilityNotify
:
3790 #else /* ! defined (HAVE_X11) */
3792 f
= x_window_to_frame (event
.window
);
3793 if (event
.window
== f
->display
.x
->icon_desc
)
3794 f
->async_iconified
= 0;
3795 if (event
.window
== FRAME_X_WINDOW (f
))
3796 f
->async_visible
= 0;
3798 #endif /* ! defined (HAVE_X11) */
3802 f
= x_any_window_to_frame (event
.xkey
.window
);
3806 KeySym keysym
, orig_keysym
;
3807 /* al%imercury@uunet.uu.net says that making this 81 instead of
3808 80 fixed a bug whereby meta chars made his Emacs hang. */
3809 unsigned char copy_buffer
[81];
3813 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3814 modifiers
= event
.xkey
.state
;
3816 /* This will have to go some day... */
3818 /* make_lispy_event turns chars into control chars.
3819 Don't do it here because XLookupString is too eager. */
3820 event
.xkey
.state
&= ~ControlMask
;
3822 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3825 orig_keysym
= keysym
;
3829 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3830 || keysym
== XK_Delete
3831 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3832 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3834 /* This recognizes the "extended function keys".
3835 It seems there's no cleaner way.
3836 Test IsModifierKey to avoid handling mode_switch
3838 || ((unsigned) (keysym
) >= XK_Select
3839 && (unsigned)(keysym
) < XK_KP_Space
)
3841 #ifdef XK_dead_circumflex
3842 || orig_keysym
== XK_dead_circumflex
3844 #ifdef XK_dead_grave
3845 || orig_keysym
== XK_dead_grave
3847 #ifdef XK_dead_tilde
3848 || orig_keysym
== XK_dead_tilde
3850 #ifdef XK_dead_diaeresis
3851 || orig_keysym
== XK_dead_diaeresis
3853 #ifdef XK_dead_macron
3854 || orig_keysym
== XK_dead_macron
3856 #ifdef XK_dead_degree
3857 || orig_keysym
== XK_dead_degree
3859 #ifdef XK_dead_acute
3860 || orig_keysym
== XK_dead_acute
3862 #ifdef XK_dead_cedilla
3863 || orig_keysym
== XK_dead_cedilla
3865 #ifdef XK_dead_breve
3866 || orig_keysym
== XK_dead_breve
3868 #ifdef XK_dead_ogonek
3869 || orig_keysym
== XK_dead_ogonek
3871 #ifdef XK_dead_caron
3872 || orig_keysym
== XK_dead_caron
3874 #ifdef XK_dead_doubleacute
3875 || orig_keysym
== XK_dead_doubleacute
3877 #ifdef XK_dead_abovedot
3878 || orig_keysym
== XK_dead_abovedot
3880 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3881 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3882 /* Any "vendor-specific" key is ok. */
3883 || (orig_keysym
& (1 << 28)))
3884 && ! (IsModifierKey (orig_keysym
)
3886 #ifdef XK_Mode_switch
3887 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3890 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3892 #endif /* not HAVE_X11R5 */
3895 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3897 temp_buffer
[temp_index
++] = keysym
;
3898 bufp
->kind
= non_ascii_keystroke
;
3899 bufp
->code
= keysym
;
3900 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3901 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3902 bufp
->timestamp
= event
.xkey
.time
;
3907 else if (numchars
> nbytes
)
3911 for (i
= 0; i
< nbytes
; i
++)
3913 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3915 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3916 bufp
->kind
= ascii_keystroke
;
3917 bufp
->code
= copy_buffer
[i
];
3918 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3919 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3920 bufp
->timestamp
= event
.xkey
.time
;
3934 #else /* ! defined (HAVE_X11) */
3937 register char *where_mapping
;
3939 f
= x_window_to_frame (event
.window
);
3940 /* Ignore keys typed on icon windows. */
3941 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3943 where_mapping
= XLookupMapping (&event
, &nbytes
);
3944 /* Nasty fix for arrow keys */
3945 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3947 switch (event
.detail
& 0xff)
3949 case KC_CURSOR_LEFT
:
3950 where_mapping
= "\002";
3952 case KC_CURSOR_RIGHT
:
3953 where_mapping
= "\006";
3956 where_mapping
= "\020";
3958 case KC_CURSOR_DOWN
:
3959 where_mapping
= "\016";
3964 if (numchars
- nbytes
> 0)
3968 for (i
= 0; i
< nbytes
; i
++)
3970 bufp
->kind
= ascii_keystroke
;
3971 bufp
->code
= where_mapping
[i
];
3972 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3973 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3981 #endif /* ! defined (HAVE_X11) */
3985 /* Here's a possible interpretation of the whole
3986 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3987 FocusIn event, you have to get a FocusOut event before you
3988 relinquish the focus. If you haven't received a FocusIn event,
3989 then a mere LeaveNotify is enough to free you. */
3992 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3994 if (event
.xcrossing
.focus
) /* Entered Window */
3996 /* Avoid nasty pop/raise loops. */
3997 if (f
&& (!(f
->auto_raise
)
3999 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
4001 x_new_focus_frame (f
);
4002 enter_timestamp
= event
.xcrossing
.time
;
4005 else if (f
== x_focus_frame
)
4006 x_new_focus_frame (0);
4007 /* EnterNotify counts as mouse movement,
4008 so update things that depend on mouse position. */
4010 note_mouse_movement (f
, &event
.xmotion
);
4011 #ifdef USE_X_TOOLKIT
4013 #endif /* USE_X_TOOLKIT */
4017 f
= x_any_window_to_frame (event
.xfocus
.window
);
4018 if (event
.xfocus
.detail
!= NotifyPointer
)
4019 x_focus_event_frame
= f
;
4021 x_new_focus_frame (f
);
4022 #ifdef USE_X_TOOLKIT
4024 #endif /* USE_X_TOOLKIT */
4029 f
= x_top_window_to_frame (event
.xcrossing
.window
);
4032 if (f
== mouse_face_mouse_frame
)
4033 /* If we move outside the frame,
4034 then we're certainly no longer on any text in the frame. */
4035 clear_mouse_face ();
4037 if (event
.xcrossing
.focus
)
4039 if (! x_focus_event_frame
)
4040 x_new_focus_frame (0);
4042 x_new_focus_frame (f
);
4046 if (f
== x_focus_event_frame
)
4047 x_focus_event_frame
= 0;
4048 if (f
== x_focus_frame
)
4049 x_new_focus_frame (0);
4052 #ifdef USE_X_TOOLKIT
4054 #endif /* USE_X_TOOLKIT */
4058 f
= x_any_window_to_frame (event
.xfocus
.window
);
4059 if (event
.xfocus
.detail
!= NotifyPointer
4060 && f
== x_focus_event_frame
)
4061 x_focus_event_frame
= 0;
4062 if (f
&& f
== x_focus_frame
)
4063 x_new_focus_frame (0);
4064 #ifdef USE_X_TOOLKIT
4066 #endif /* USE_X_TOOLKIT */
4069 #else /* ! defined (HAVE_X11) */
4072 if ((event
.detail
& 0xFF) == 1)
4073 break; /* Coming from our own subwindow */
4074 if (event
.subwindow
!= 0)
4075 break; /* Entering our own subwindow. */
4078 f
= x_window_to_frame (event
.window
);
4081 x_new_focus_frame (f
);
4086 if ((event
.detail
& 0xFF) == 1)
4087 break; /* Entering our own subwindow */
4088 if (event
.subwindow
!= 0)
4089 break; /* Leaving our own subwindow. */
4092 if (x_focus_frame
== 0
4093 && x_input_frame
!= 0
4094 && x_input_frame
== x_window_to_frame (event
.window
)
4095 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
4100 frame_unhighlight (f
);
4103 #endif /* ! defined (HAVE_X11) */
4108 if (x_mouse_grabbed
&& last_mouse_frame
4109 && FRAME_LIVE_P (last_mouse_frame
))
4110 f
= last_mouse_frame
;
4112 f
= x_window_to_frame (event
.xmotion
.window
);
4114 note_mouse_movement (f
, &event
.xmotion
);
4117 struct scroll_bar
*bar
4118 = x_window_to_scroll_bar (event
.xmotion
.window
);
4121 x_scroll_bar_note_movement (bar
, &event
);
4123 /* If we move outside the frame,
4124 then we're certainly no longer on any text in the frame. */
4125 clear_mouse_face ();
4128 #if 0 /* This should be unnecessary, since the toolkit has no use
4129 for motion events that happen outside of the menu event loop,
4130 and it seems to cause the bug that mouse events stop coming
4132 #ifdef USE_X_TOOLKIT
4134 #endif /* USE_X_TOOLKIT */
4138 case ConfigureNotify
:
4139 f
= x_any_window_to_frame (event
.xconfigure
.window
);
4140 #ifdef USE_X_TOOLKIT
4143 && ! event
.xconfigure
.send_event
4145 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
4150 /* Find the position of the outside upper-left corner of
4151 the window, in the root coordinate system. Don't
4152 refer to the parent window here; we may be processing
4153 this event after the window manager has changed our
4154 parent, but before we have reached the ReparentNotify. */
4155 XTranslateCoordinates (x_current_display
,
4157 /* From-window, to-window. */
4158 XtWindow (f
->display
.x
->widget
),
4161 /* From-position, to-position. */
4162 -event
.xconfigure
.border_width
,
4163 -event
.xconfigure
.border_width
,
4168 event
.xconfigure
.x
= win_x
;
4169 event
.xconfigure
.y
= win_y
;
4171 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4172 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4173 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4174 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4176 /* What we have now is the position of Emacs's own window.
4177 Convert that to the position of the window manager window. */
4180 x_real_positions (f
, &x
, &y
);
4181 f
->display
.x
->left_pos
= x
;
4182 f
->display
.x
->top_pos
= y
;
4186 #else /* not USE_X_TOOLKIT */
4189 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4190 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4192 /* Even if the number of character rows and columns has
4193 not changed, the font size may have changed, so we need
4194 to check the pixel dimensions as well. */
4195 if (columns
!= f
->width
4196 || rows
!= f
->height
4197 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
4198 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
4200 change_frame_size (f
, rows
, columns
, 0, 1);
4201 SET_FRAME_GARBAGED (f
);
4204 if (! event
.xconfigure
.send_event
)
4209 /* Find the position of the outside upper-left corner of
4210 the window, in the root coordinate system. Don't
4211 refer to the parent window here; we may be processing
4212 this event after the window manager has changed our
4213 parent, but before we have reached the ReparentNotify. */
4214 XTranslateCoordinates (x_current_display
,
4216 /* From-window, to-window. */
4217 f
->display
.x
->window_desc
,
4220 /* From-position, to-position. */
4221 -event
.xconfigure
.border_width
,
4222 -event
.xconfigure
.border_width
,
4227 event
.xconfigure
.x
= win_x
;
4228 event
.xconfigure
.y
= win_y
;
4231 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4232 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4233 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4234 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4236 /* What we have now is the position of Emacs's own window.
4237 Convert that to the position of the window manager window. */
4240 x_real_positions (f
, &x
, &y
);
4241 f
->display
.x
->left_pos
= x
;
4242 f
->display
.x
->top_pos
= y
;
4243 if (y
!= event
.xconfigure
.y
)
4245 /* Since the WM decorations come below top_pos now,
4246 we must put them below top_pos in the future. */
4247 f
->display
.x
->win_gravity
= NorthWestGravity
;
4248 x_wm_set_size_hint (f
, 0, 0);
4252 #endif /* not USE_X_TOOLKIT */
4258 /* If we decide we want to generate an event to be seen
4259 by the rest of Emacs, we put it here. */
4260 struct input_event emacs_event
;
4261 emacs_event
.kind
= no_event
;
4263 bzero (&compose_status
, sizeof (compose_status
));
4265 f
= x_window_to_frame (event
.xbutton
.window
);
4268 if (!x_focus_frame
|| (f
== x_focus_frame
))
4269 construct_mouse_click (&emacs_event
, &event
, f
);
4273 struct scroll_bar
*bar
4274 = x_window_to_scroll_bar (event
.xbutton
.window
);
4277 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4278 #ifdef USE_X_TOOLKIT
4281 f
= x_any_window_to_frame (event
.xbutton
.window
);
4282 if (f
&& event
.type
== ButtonPress
)
4283 construct_menu_click (&emacs_event
,
4286 #endif /* USE_X_TOOLKIT */
4289 if (event
.type
== ButtonPress
)
4291 x_mouse_grabbed
|= (1 << event
.xbutton
.button
);
4292 Vmouse_depressed
= Qt
;
4293 last_mouse_frame
= f
;
4297 x_mouse_grabbed
&= ~(1 << event
.xbutton
.button
);
4298 if (!x_mouse_grabbed
)
4299 Vmouse_depressed
= Qnil
;
4302 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4304 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4310 #ifdef USE_X_TOOLKIT
4312 #endif /* USE_X_TOOLKIT */
4316 #else /* ! defined (HAVE_X11) */
4318 case ButtonReleased
:
4319 f
= x_window_to_frame (event
.window
);
4322 if (event
.window
== f
->display
.x
->icon_desc
)
4324 x_make_frame_visible (f
);
4326 if (warp_mouse_on_deiconify
)
4327 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
4330 if (event
.window
== FRAME_X_WINDOW (f
))
4336 enqueue_event (&event
, &x_mouse_queue
);
4339 bufp
->kind
= ascii_keystroke
;
4340 bufp
->code
= 'X' & 037; /* C-x */
4341 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4342 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4345 bufp
->kind
= ascii_keystroke
;
4346 bufp
->code
= 0; /* C-@ */
4347 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4348 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4355 #endif /* ! defined (HAVE_X11) */
4359 case CirculateNotify
:
4361 case CirculateRequest
:
4364 #endif /* ! defined (HAVE_X11) */
4367 /* Someone has changed the keyboard mapping - update the
4369 switch (event
.xmapping
.request
)
4371 case MappingModifier
:
4372 x_find_modifier_meanings ();
4373 /* This is meant to fall through. */
4374 case MappingKeyboard
:
4375 XRefreshKeyboardMapping (&event
.xmapping
);
4377 #ifdef USE_X_TOOLKIT
4379 #endif /* USE_X_TOOLKIT */
4383 #ifdef USE_X_TOOLKIT
4386 XtDispatchEvent (&event
);
4388 #endif /* USE_X_TOOLKIT */
4396 /* On some systems, an X bug causes Emacs to get no more events
4397 when the window is destroyed. Detect that. (1994.) */
4398 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4399 One XNOOP in 100 loops will make Emacs terminate.
4400 B. Bretthauer, 1994 */
4402 if (x_noop_count
>= 100)
4405 XNoOp (x_current_display
);
4408 #endif /* X_IO_BUG */
4410 #if 0 /* This fails for serial-line connections to the X server,
4411 because the characters arrive one by one, and a partial
4412 command makes select return but gives nothing to read.
4413 We'll have to hope that the bug that this tried to fix
4414 in 1988 has been fixed in Xlib or the X server. */
4416 if (expected
&& ! event_found
)
4418 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4419 there is an EOF condition; in other words, that X has died.
4420 Act as if there had been a hangup. */
4421 int fd
= ConnectionNumber (x_current_display
);
4422 SELECT_TYPE mask
, junk1
, junk2
;
4427 EMACS_SET_SECS_USECS (timeout
, 0, 0);
4430 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
4431 && !XStuffPending ())
4432 kill (getpid (), SIGHUP
);
4434 #endif /* HAVE_SELECT */
4438 if (updating_frame
== 0)
4439 x_do_pending_expose ();
4442 /* If the focus was just given to an autoraising frame,
4445 if (pending_autoraise_frame
)
4447 x_raise_frame (pending_autoraise_frame
);
4448 pending_autoraise_frame
= 0;
4457 /* Read and process only Expose events
4458 until we get an ExposeCopy event; then return.
4459 This is used in insert/delete line.
4460 We assume input is already blocked. */
4466 XKeyPressedEvent event
;
4470 /* while there are more events*/
4471 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
4475 if (event
.subwindow
!= 0)
4476 break; /* duplicate event */
4477 f
= x_window_to_frame (event
.window
);
4478 if (event
.window
== f
->display
.x
->icon_desc
)
4483 if (event
.window
== FRAME_X_WINDOW (f
))
4485 expose_all_windows
= 1;
4486 f
->display
.x
->needs_exposure
= 1;
4492 if (event
.subwindow
!= 0)
4493 break; /* duplicate event */
4494 f
= x_window_to_frame (event
.window
);
4495 if (event
.window
== f
->display
.x
->icon_desc
)
4500 /* If window already needs full redraw, ignore this rectangle. */
4501 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
4503 /* Put the event on the queue of rectangles to redraw. */
4504 if (enqueue_event (&event
, &x_expose_queue
))
4505 /* If it is full, we can't record the rectangle,
4506 so redraw this entire window. */
4508 /* Say must check all windows' needs_exposure flags. */
4509 expose_all_windows
= 1;
4510 f
->display
.x
->needs_exposure
= 1;
4519 #endif /* HAVE_X11 */
4522 /* Drawing the cursor. */
4525 /* Draw a hollow box cursor. Don't change the inside of the box. */
4531 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
4532 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
4533 int width
= FONT_WIDTH (f
->display
.x
->font
);
4534 int height
= f
->display
.x
->line_height
;
4537 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4538 f
->display
.x
->cursor_gc
,
4539 left
, top
, width
- 1, height
- 1);
4540 #else /* ! defined (HAVE_X11) */
4541 XPixSet (FRAME_X_WINDOW (f
),
4542 left
, top
, width
, 1,
4543 f
->display
.x
->cursor_pixel
);
4545 XPixSet (FRAME_X_WINDOW (f
),
4546 left
, top
, 1, height
,
4547 f
->display
.x
->cursor_pixel
);
4549 XPixSet (FRAME_X_WINDOW (f
),
4550 left
+width
-1, top
, 1, height
,
4551 f
->display
.x
->cursor_pixel
);
4553 XPixSet (FRAME_X_WINDOW (f
),
4554 left
, top
+height
-1, width
, 1,
4555 f
->display
.x
->cursor_pixel
);
4556 #endif /* ! defined (HAVE_X11) */
4559 /* Clear the cursor of frame F to background color,
4560 and mark the cursor as not shown.
4561 This is used when the text where the cursor is
4562 is about to be rewritten. */
4570 if (! FRAME_VISIBLE_P (f
)
4571 || f
->phys_cursor_x
< 0)
4575 x_display_cursor (f
, 0);
4576 #else /* ! defined (HAVE_X11) */
4577 XPixSet (FRAME_X_WINDOW (f
),
4578 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4579 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4580 FONT_WIDTH (f
->display
.x
->font
), f
->display
.x
->line_height
,
4581 f
->display
.x
->background_pixel
);
4582 #endif /* ! defined (HAVE_X11) */
4583 f
->phys_cursor_x
= -1;
4586 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4587 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4591 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4598 CHAR_TO_PIXEL_COL (f
, column
),
4599 CHAR_TO_PIXEL_ROW (f
, row
),
4600 &glyph
, 1, highlight
, 0);
4604 x_display_bar_cursor (f
, on
)
4608 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4610 /* This is pointless on invisible frames, and dangerous on garbaged
4611 frames; in the latter case, the frame may be in the midst of
4612 changing its size, and curs_x and curs_y may be off the frame. */
4613 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4616 if (! on
&& f
->phys_cursor_x
< 0)
4619 /* If we're not updating, then we want to use the current frame's
4620 cursor position, not our local idea of where the cursor ought to be. */
4621 if (f
!= updating_frame
)
4623 curs_x
= FRAME_CURSOR_X (f
);
4624 curs_y
= FRAME_CURSOR_Y (f
);
4627 /* If there is anything wrong with the current cursor state, remove it. */
4628 if (f
->phys_cursor_x
>= 0
4630 || f
->phys_cursor_x
!= curs_x
4631 || f
->phys_cursor_y
!= curs_y
4632 || f
->display
.x
->current_cursor
!= bar_cursor
))
4634 /* Erase the cursor by redrawing the character underneath it. */
4635 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4636 f
->phys_cursor_glyph
,
4637 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4638 f
->phys_cursor_x
= -1;
4641 /* If we now need a cursor in the new place or in the new form, do it so. */
4643 && (f
->phys_cursor_x
< 0
4644 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4646 f
->phys_cursor_glyph
4647 = ((current_glyphs
->enable
[curs_y
]
4648 && curs_x
< current_glyphs
->used
[curs_y
])
4649 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4651 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4652 f
->display
.x
->cursor_gc
,
4653 CHAR_TO_PIXEL_COL (f
, curs_x
),
4654 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4655 1, f
->display
.x
->line_height
);
4657 f
->phys_cursor_x
= curs_x
;
4658 f
->phys_cursor_y
= curs_y
;
4660 f
->display
.x
->current_cursor
= bar_cursor
;
4663 if (updating_frame
!= f
)
4668 /* Turn the displayed cursor of frame F on or off according to ON.
4669 If ON is nonzero, where to put the cursor is specified
4670 by F->cursor_x and F->cursor_y. */
4673 x_display_box_cursor (f
, on
)
4677 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4679 /* This is pointless on invisible frames, and dangerous on garbaged
4680 frames; in the latter case, the frame may be in the midst of
4681 changing its size, and curs_x and curs_y may be off the frame. */
4682 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4685 /* If cursor is off and we want it off, return quickly. */
4686 if (!on
&& f
->phys_cursor_x
< 0)
4689 /* If we're not updating, then we want to use the current frame's
4690 cursor position, not our local idea of where the cursor ought to be. */
4691 if (f
!= updating_frame
)
4693 curs_x
= FRAME_CURSOR_X (f
);
4694 curs_y
= FRAME_CURSOR_Y (f
);
4697 /* If cursor is currently being shown and we don't want it to be
4698 or it is in the wrong place,
4699 or we want a hollow box and it's not so, (pout!)
4701 if (f
->phys_cursor_x
>= 0
4703 || f
->phys_cursor_x
!= curs_x
4704 || f
->phys_cursor_y
!= curs_y
4705 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4706 && (f
!= x_highlight_frame
))))
4708 int mouse_face_here
= 0;
4710 /* If the cursor is in the mouse face area, redisplay that when
4711 we clear the cursor. */
4712 if (f
== mouse_face_mouse_frame
4714 (f
->phys_cursor_y
> mouse_face_beg_row
4715 || (f
->phys_cursor_y
== mouse_face_beg_row
4716 && f
->phys_cursor_x
>= mouse_face_beg_col
))
4718 (f
->phys_cursor_y
< mouse_face_end_row
4719 || (f
->phys_cursor_y
== mouse_face_end_row
4720 && f
->phys_cursor_x
< mouse_face_end_col
)))
4721 mouse_face_here
= 1;
4723 /* If the font is not as tall as a whole line,
4724 we must explicitly clear the line's whole height. */
4725 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4726 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
4727 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4728 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4729 FONT_WIDTH (f
->display
.x
->font
),
4730 f
->display
.x
->line_height
, False
);
4731 /* Erase the cursor by redrawing the character underneath it. */
4732 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4733 f
->phys_cursor_glyph
,
4736 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4737 f
->phys_cursor_x
= -1;
4740 /* If we want to show a cursor,
4741 or we want a box cursor and it's not so,
4742 write it in the right place. */
4744 && (f
->phys_cursor_x
< 0
4745 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4746 && f
== x_highlight_frame
)))
4748 f
->phys_cursor_glyph
4749 = ((current_glyphs
->enable
[curs_y
]
4750 && curs_x
< current_glyphs
->used
[curs_y
])
4751 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4753 if (f
!= x_highlight_frame
)
4756 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4760 x_draw_single_glyph (f
, curs_y
, curs_x
,
4761 f
->phys_cursor_glyph
, 2);
4762 f
->display
.x
->current_cursor
= filled_box_cursor
;
4765 f
->phys_cursor_x
= curs_x
;
4766 f
->phys_cursor_y
= curs_y
;
4769 if (updating_frame
!= f
)
4773 x_display_cursor (f
, on
)
4779 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4780 x_display_box_cursor (f
, on
);
4781 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4782 x_display_bar_cursor (f
, on
);
4784 /* Those are the only two we have implemented! */
4792 /* Refresh bitmap kitchen sink icon for frame F
4793 when we get an expose event for it. */
4799 /* Normally, the window manager handles this function. */
4800 #else /* ! defined (HAVE_X11) */
4803 if (f
->display
.x
->icon_bitmap_flag
)
4804 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
4805 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
4806 icon_bitmap
, GXcopy
, AllPlanes
);
4809 extern struct frame
*selected_frame
;
4810 struct Lisp_String
*str
;
4811 unsigned char *string
;
4814 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
4816 if (f
->display
.x
->icon_label
!= string
)
4818 f
->display
.x
->icon_label
= string
;
4819 XChangeWindow (f
->display
.x
->icon_desc
,
4820 XQueryWidth (string
, icon_font_info
->id
) + 10,
4821 icon_font_info
->height
+ 10);
4824 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4825 str
->size
, icon_font_info
->id
,
4826 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4829 #endif /* ! defined (HAVE_X11) */
4832 /* Make the x-window of frame F use the gnu icon bitmap. */
4841 if (FRAME_X_WINDOW (f
) == 0)
4847 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4848 gnu_bits
, gnu_width
, gnu_height
);
4849 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4850 f
->display
.x
->icon_bitmap_flag
= 1;
4851 #else /* ! defined (HAVE_X11) */
4852 if (f
->display
.x
->icon_desc
)
4854 XClearIconWindow (FRAME_X_WINDOW (f
));
4855 XDestroyWindow (f
->display
.x
->icon_desc
);
4858 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4859 0, 0, sink_width
, sink_height
,
4860 2, WhitePixmap
, (Pixmap
) NULL
);
4862 if (icon_window
== 0)
4865 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4866 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4868 f
->display
.x
->icon_desc
= icon_window
;
4869 f
->display
.x
->icon_bitmap_flag
= 1;
4871 if (icon_bitmap
== 0)
4873 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4874 #endif /* ! defined (HAVE_X11) */
4880 /* Make the x-window of frame F use a rectangle with text. */
4883 x_text_icon (f
, icon_name
)
4891 char *X_DefaultValue
;
4895 #define WhitePixel 1
4896 #endif /* WhitePixel */
4899 #define BlackPixel 0
4900 #endif /* BlackPixel */
4901 #endif /* HAVE_X11 */
4903 if (FRAME_X_WINDOW (f
) == 0)
4908 f
->display
.x
->icon_label
= icon_name
;
4910 if (! f
->display
.x
->icon_label
)
4911 f
->display
.x
->icon_label
= " *emacs* ";
4914 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4915 (char *) f
->display
.x
->icon_label
);
4918 f
->display
.x
->icon_bitmap_flag
= 0;
4919 x_wm_set_icon_pixmap (f
, 0);
4920 #else /* ! defined (HAVE_X11) */
4921 if (icon_font_info
== 0)
4923 = XGetFont (XGetDefault (XDISPLAY
4924 (char *) XSTRING (Vinvocation_name
)->data
,
4927 if (f
->display
.x
->icon_desc
)
4929 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4930 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4934 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4936 if (! f
->display
.x
->icon_label
)
4937 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4939 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4940 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4941 f
->display
.x
->left_pos
,
4942 f
->display
.x
->top_pos
,
4943 width
+ 10, icon_font_info
->height
+ 10,
4944 2, BlackPixmap
, WhitePixmap
);
4946 if (icon_window
== 0)
4949 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4950 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4952 f
->display
.x
->icon_desc
= icon_window
;
4953 f
->display
.x
->icon_bitmap_flag
= 0;
4954 f
->display
.x
->icon_label
= 0;
4955 #endif /* ! defined (HAVE_X11) */
4960 /* Handling X errors. */
4962 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4963 X server's connection, or an error reported via the X protocol. */
4966 x_connection_closed ()
4971 shut_down_emacs (0, 1, Qnil
);
4976 /* An X error handler which prints an error message and then kills
4977 Emacs. This is what's normally installed as Xlib's handler for
4980 x_error_quitter (display
, error
)
4986 /* Note that there is no real way portable across R3/R4 to get the
4987 original error handler. */
4989 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4990 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4991 buf
, error
->request_code
);
4994 /* While we're testing Emacs 19, we'll just dump core whenever we
4995 get an X error, so we can figure out why it happened. */
4999 x_connection_closed ();
5002 /* A handler for X IO errors which prints an error message and then
5003 kills Emacs. This is what is always installed as Xlib's handler
5006 x_io_error_quitter (display
)
5009 fprintf (stderr
, "Connection to X server %s lost.\n",
5010 XDisplayName (DisplayString (display
)));
5013 /* While we're testing Emacs 19, we'll just dump core whenever we
5014 get an X error, so we can figure out why it happened. */
5018 x_connection_closed ();
5021 /* A buffer for storing X error messages. */
5022 static char *x_caught_error_message
;
5023 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
5025 /* An X error handler which stores the error message in
5026 x_caught_error_message. This is what's installed when
5027 x_catch_errors is in effect. */
5029 x_error_catcher (display
, error
)
5033 XGetErrorText (display
, error
->error_code
,
5034 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
5038 /* Begin trapping X errors.
5040 After calling this function, X protocol errors no longer cause
5041 Emacs to exit; instead, they are recorded in x_cfc_error_message.
5043 Calling x_check_errors signals an Emacs error if an X error has
5044 occurred since the last call to x_catch_errors or x_check_errors.
5046 Calling x_uncatch_errors resumes the normal error handling. */
5048 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
5053 /* Make sure any errors from previous requests have been dealt with. */
5054 XSync (x_current_display
, False
);
5056 /* Set up the error buffer. */
5057 x_caught_error_message
5058 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
5059 x_caught_error_message
[0] = '\0';
5061 /* Install our little error handler. */
5062 XHandleError (x_error_catcher
);
5065 /* If any X protocol errors have arrived since the last call to
5066 x_catch_errors or x_check_errors, signal an Emacs error using
5067 sprintf (a buffer, FORMAT, the x error message text) as the text. */
5070 x_check_errors (format
)
5073 /* Make sure to catch any errors incurred so far. */
5074 XSync (x_current_display
, False
);
5076 if (x_caught_error_message
[0])
5078 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
5080 sprintf (buf
, format
, x_caught_error_message
);
5081 x_uncatch_errors ();
5086 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
5091 /* Make sure to catch any errors incurred so far. */
5092 XSync (x_current_display
, False
);
5094 return x_caught_error_message
[0] != 0;
5097 /* Stop catching X protocol errors and let them make Emacs die. */
5102 xfree (x_caught_error_message
);
5103 x_caught_error_message
= 0;
5104 XHandleError (x_error_quitter
);
5108 static unsigned int x_wire_count
;
5111 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5116 /* Changing the font of the frame. */
5118 /* Set the font of the x-window specified by frame F
5119 to the font named NEWNAME. This is safe to use
5120 even before F has an actual x-window. */
5131 /* A table of all the fonts we have already loaded. */
5132 static struct font_info
*x_font_table
;
5134 /* The current capacity of x_font_table. */
5135 static int x_font_table_size
;
5137 /* The number of fonts actually stored in x_font_table.
5138 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
5139 0 <= n_fonts <= x_font_table_size. */
5142 /* Give frame F the font named FONTNAME as its default font, and
5143 return the full name of that font. FONTNAME may be a wildcard
5144 pattern; in that case, we choose some font that fits the pattern.
5145 The return value shows which font we chose. */
5148 x_new_font (f
, fontname
)
5150 register char *fontname
;
5153 int n_matching_fonts
;
5154 XFontStruct
*font_info
;
5157 /* Get a list of all the fonts that match this name. Once we
5158 have a list of matching fonts, we compare them against the fonts
5159 we already have by comparing font ids. */
5160 font_names
= (char **) XListFonts (x_current_display
, fontname
,
5161 1024, &n_matching_fonts
);
5162 /* Apparently it doesn't set n_matching_fonts to zero when it can't
5163 find any matches; font_names == 0 is the only clue. */
5165 n_matching_fonts
= 0;
5167 /* Don't just give up if n_matching_fonts is 0.
5168 Apparently there's a bug on Suns: XListFontsWithInfo can
5169 fail to find a font, but XLoadQueryFont may still find it. */
5171 /* See if we've already loaded a matching font. */
5172 already_loaded
= -1;
5173 if (n_matching_fonts
!= 0)
5177 for (i
= 0; i
< n_fonts
; i
++)
5178 for (j
= 0; j
< n_matching_fonts
; j
++)
5179 if (!strcmp (x_font_table
[i
].name
, font_names
[j
])
5180 || !strcmp (x_font_table
[i
].full_name
, font_names
[j
]))
5183 fontname
= x_font_table
[i
].full_name
;
5189 /* If we have, just return it from the table. */
5190 if (already_loaded
>= 0)
5191 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
5193 /* Otherwise, load the font and add it to the table. */
5200 /* Try to find a character-cell font in the list. */
5202 /* A laudable goal, but this isn't how to do it. */
5203 for (i
= 0; i
< n_matching_fonts
; i
++)
5204 if (! font_info
[i
].per_char
)
5210 /* See comment above. */
5211 if (n_matching_fonts
!= 0)
5212 fontname
= font_names
[i
];
5214 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
5217 /* Free the information from XListFonts. */
5218 if (n_matching_fonts
)
5219 XFreeFontNames (font_names
);
5223 /* Do we need to create the table? */
5224 if (x_font_table_size
== 0)
5226 x_font_table_size
= 16;
5228 = (struct font_info
*) xmalloc (x_font_table_size
5229 * sizeof (x_font_table
[0]));
5231 /* Do we need to grow the table? */
5232 else if (n_fonts
>= x_font_table_size
)
5234 x_font_table_size
*= 2;
5236 = (struct font_info
*) xrealloc (x_font_table
,
5238 * sizeof (x_font_table
[0])));
5241 /* Try to get the full name of FONT. Put it in full_name. */
5243 for (i
= 0; i
< font
->n_properties
; i
++)
5246 = XGetAtomName (x_current_display
, font
->properties
[i
].name
);
5247 if (!strcmp (atom
, "FONT"))
5248 full_name
= XGetAtomName (x_current_display
,
5249 (Atom
) (font
->properties
[i
].card32
));
5253 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
5254 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
5256 x_font_table
[n_fonts
].full_name
= full_name
;
5258 x_font_table
[n_fonts
].full_name
= x_font_table
[n_fonts
].name
;
5259 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
5261 fontname
= full_name
;
5264 /* Now make the frame display the given font. */
5265 if (FRAME_X_WINDOW (f
) != 0)
5267 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
5268 f
->display
.x
->font
->fid
);
5269 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
5270 f
->display
.x
->font
->fid
);
5271 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
5272 f
->display
.x
->font
->fid
);
5274 frame_update_line_height (f
);
5275 x_set_window_size (f
, 0, f
->width
, f
->height
);
5278 /* If we are setting a new frame's font for the first time,
5279 there are no faces yet, so this font's height is the line height. */
5280 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
5283 Lisp_Object lispy_name
;
5285 lispy_name
= build_string (fontname
);
5287 /* Free the information from XListFonts. The data
5288 we actually retain comes from XLoadQueryFont. */
5289 XFreeFontNames (font_names
);
5294 #else /* ! defined (HAVE_X11) */
5295 x_new_font (f
, newname
)
5297 register char *newname
;
5302 temp
= XGetFont (newname
);
5303 if (temp
== (FONT_TYPE
*) 0)
5306 if (f
->display
.x
->font
)
5307 XLoseFont (f
->display
.x
->font
);
5309 f
->display
.x
->font
= temp
;
5311 if (FRAME_X_WINDOW (f
) != 0)
5312 x_set_window_size (f
, 0, f
->width
, f
->height
);
5316 #endif /* ! defined (HAVE_X11) */
5318 x_calc_absolute_position (f
)
5323 int win_x
= 0, win_y
= 0;
5324 int flags
= f
->display
.x
->size_hint_flags
;
5326 /* Find the position of the outside upper-left corner of
5327 the inner window, with respect to the outer window. */
5328 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
5331 XTranslateCoordinates (x_current_display
,
5333 /* From-window, to-window. */
5334 f
->display
.x
->window_desc
,
5335 f
->display
.x
->parent_desc
,
5337 /* From-position, to-position. */
5338 0, 0, &win_x
, &win_y
,
5345 /* Treat negative positions as relative to the leftmost bottommost
5346 position that fits on the screen. */
5347 if (flags
& XNegative
)
5348 f
->display
.x
->left_pos
= (x_screen_width
5349 - 2 * f
->display
.x
->border_width
- win_x
5351 + f
->display
.x
->left_pos
);
5353 if (flags
& YNegative
)
5354 f
->display
.x
->top_pos
= (x_screen_height
5355 - 2 * f
->display
.x
->border_width
- win_y
5357 + f
->display
.x
->top_pos
);
5358 /* The left_pos and top_pos
5359 are now relative to the top and left screen edges,
5360 so the flags should correspond. */
5361 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5362 #else /* ! defined (HAVE_X11) */
5363 WINDOWINFO_TYPE parentinfo
;
5365 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
5367 if (f
->display
.x
->left_pos
< 0)
5368 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
5369 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
5371 if (f
->display
.x
->top_pos
< 0)
5372 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
5373 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
5374 #endif /* ! defined (HAVE_X11) */
5377 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5378 to really change the position, and 0 when calling from
5379 x_make_frame_visible (in that case, XOFF and YOFF are the current
5380 position values). */
5382 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5384 register int xoff
, yoff
;
5389 f
->display
.x
->top_pos
= yoff
;
5390 f
->display
.x
->left_pos
= xoff
;
5391 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5393 f
->display
.x
->size_hint_flags
|= XNegative
;
5395 f
->display
.x
->size_hint_flags
|= YNegative
;
5396 f
->display
.x
->win_gravity
= NorthWestGravity
;
5398 x_calc_absolute_position (f
);
5401 x_wm_set_size_hint (f
, 0, 0);
5403 #ifdef USE_X_TOOLKIT
5404 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
5405 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5406 #else /* not USE_X_TOOLKIT */
5407 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
5408 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5409 #endif /* not USE_X_TOOLKIT */
5413 /* Call this to change the size of frame F's x-window.
5414 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5415 for this size change and subsequent size changes.
5416 Otherwise we leave the window gravity unchanged. */
5418 x_set_window_size (f
, change_gravity
, cols
, rows
)
5423 int pixelwidth
, pixelheight
;
5426 #ifdef USE_X_TOOLKIT
5429 /* The x and y position of the widget is clobbered by the
5430 call to XtSetValues within EmacsFrameSetCharSize.
5431 This is a real kludge, but I don't understand Xt so I can't
5432 figure out a correct fix. Can anyone else tell me? -- rms. */
5433 int xpos
= f
->display
.x
->widget
->core
.x
;
5434 int ypos
= f
->display
.x
->widget
->core
.y
;
5435 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
5436 f
->display
.x
->widget
->core
.x
= xpos
;
5437 f
->display
.x
->widget
->core
.y
= ypos
;
5441 #else /* not USE_X_TOOLKIT */
5445 check_frame_size (f
, &rows
, &cols
);
5446 f
->display
.x
->vertical_scroll_bar_extra
5447 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5448 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
5450 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5451 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5454 f
->display
.x
->win_gravity
= NorthWestGravity
;
5455 x_wm_set_size_hint (f
, 0, 0);
5456 #endif /* ! defined (HAVE_X11) */
5457 XSync (x_current_display
, False
);
5458 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
5460 /* Now, strictly speaking, we can't be sure that this is accurate,
5461 but the window manager will get around to dealing with the size
5462 change request eventually, and we'll hear how it went when the
5463 ConfigureNotify event gets here.
5465 We could just not bother storing any of this information here,
5466 and let the ConfigureNotify event set everything up, but that
5467 might be kind of confusing to the lisp code, since size changes
5468 wouldn't be reported in the frame parameters until some random
5469 point in the future when the ConfigureNotify event arrives. */
5470 change_frame_size (f
, rows
, cols
, 0, 0);
5471 PIXEL_WIDTH (f
) = pixelwidth
;
5472 PIXEL_HEIGHT (f
) = pixelheight
;
5474 /* If cursor was outside the new size, mark it as off. */
5475 if (f
->phys_cursor_y
>= rows
5476 || f
->phys_cursor_x
>= cols
)
5478 f
->phys_cursor_x
= -1;
5479 f
->phys_cursor_y
= -1;
5482 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5483 receive in the ConfigureNotify event; if we get what we asked
5484 for, then the event won't cause the screen to become garbaged, so
5485 we have to make sure to do it here. */
5486 SET_FRAME_GARBAGED (f
);
5490 #endif /* not USE_X_TOOLKIT */
5494 x_set_resize_hint (f
)
5497 XSetResizeHint (FRAME_X_WINDOW (f
),
5498 2 * f
->display
.x
->internal_border_width
,
5499 2 * f
->display
.x
->internal_border_width
,
5500 FONT_WIDTH (f
->display
.x
->font
),
5501 f
->display
.x
->line_height
);
5503 #endif /* HAVE_X11 */
5505 /* Mouse warping, focus shifting, raising and lowering. */
5508 x_set_mouse_position (f
, x
, y
)
5514 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
5515 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
5517 if (pix_x
< 0) pix_x
= 0;
5518 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5520 if (pix_y
< 0) pix_y
= 0;
5521 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5525 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5529 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5532 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5538 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5543 x_focus_on_frame (f
)
5546 #if 0 /* This proves to be unpleasant. */
5550 /* I don't think that the ICCCM allows programs to do things like this
5551 without the interaction of the window manager. Whatever you end up
5552 doing with this code, do it to x_unfocus_frame too. */
5553 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
5554 RevertToPointerRoot
, CurrentTime
);
5562 /* Look at the remarks in x_focus_on_frame. */
5563 if (x_focus_frame
== f
)
5564 XSetInputFocus (x_current_display
, PointerRoot
,
5565 RevertToPointerRoot
, CurrentTime
);
5569 #endif /* ! defined (HAVE_X11) */
5571 /* Raise frame F. */
5576 if (f
->async_visible
)
5579 #ifdef USE_X_TOOLKIT
5580 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5581 #else /* not USE_X_TOOLKIT */
5582 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5583 #endif /* not USE_X_TOOLKIT */
5589 /* Lower frame F. */
5594 if (f
->async_visible
)
5597 #ifdef USE_X_TOOLKIT
5598 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5599 #else /* not USE_X_TOOLKIT */
5600 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5601 #endif /* not USE_X_TOOLKIT */
5608 XTframe_raise_lower (f
, raise
)
5619 /* Change from withdrawn state to mapped state,
5622 x_make_frame_visible (f
)
5629 if (! FRAME_VISIBLE_P (f
))
5632 #ifndef USE_X_TOOLKIT
5633 if (! FRAME_ICONIFIED_P (f
))
5634 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5637 if (! EQ (Vx_no_window_manager
, Qt
))
5638 x_wm_set_window_state (f
, NormalState
);
5639 #ifdef USE_X_TOOLKIT
5640 /* This was XtPopup, but that did nothing for an iconified frame. */
5641 XtMapWidget (f
->display
.x
->widget
);
5642 #else /* not USE_X_TOOLKIT */
5643 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5644 #endif /* not USE_X_TOOLKIT */
5645 #if 0 /* This seems to bring back scroll bars in the wrong places
5646 if the window configuration has changed. They seem
5647 to come back ok without this. */
5648 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5649 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5651 #else /* ! defined (HAVE_X11) */
5652 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5653 if (f
->display
.x
->icon_desc
!= 0)
5654 XUnmapWindow (f
->display
.x
->icon_desc
);
5656 /* Handled by the MapNotify event for X11 */
5657 f
->async_visible
= 1;
5658 f
->async_iconified
= 0;
5660 /* NOTE: this may cause problems for the first frame. */
5662 #endif /* ! defined (HAVE_X11) */
5669 /* Synchronize to ensure Emacs knows the frame is visible
5670 before we do anything else. We do this loop with input not blocked
5671 so that incoming events are handled. */
5674 int one_in_four
= 0;
5675 XSET (frame
, Lisp_Frame
, f
);
5676 while (! f
->async_visible
)
5679 /* On HPUX on the HP800, the sleep is needed sometimes. */
5680 if ((one_in_four
& 3) == 0)
5682 #ifdef EMACS_HAS_USECS
5683 Fsleep_for (make_number (1), make_number (0));
5685 Fsleep_for (make_number (0), make_number (250));
5690 FRAME_SAMPLE_VISIBILITY (f
);
5694 /* Change from mapped state to withdrawn state. */
5696 x_make_frame_invisible (f
)
5702 #ifdef USE_X_TOOLKIT
5703 /* Use the frame's outermost window, not the one we normally draw on. */
5704 window
= XtWindow (f
->display
.x
->widget
);
5705 #else /* not USE_X_TOOLKIT */
5706 window
= FRAME_X_WINDOW (f
);
5707 #endif /* not USE_X_TOOLKIT */
5709 /* Don't keep the highlight on an invisible frame. */
5710 if (x_highlight_frame
== f
)
5711 x_highlight_frame
= 0;
5713 #if 0/* This might add unreliability; I don't trust it -- rms. */
5714 if (! f
->async_visible
&& ! f
->async_iconified
)
5720 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5721 that the current position of the window is user-specified, rather than
5722 program-specified, so that when the window is mapped again, it will be
5723 placed at the same location, without forcing the user to position it
5724 by hand again (they have already done that once for this window.) */
5725 x_wm_set_size_hint (f
, 0, 1);
5729 if (! XWithdrawWindow (x_current_display
, window
,
5730 DefaultScreen (x_current_display
)))
5732 UNBLOCK_INPUT_RESIGNAL
;
5733 error ("Can't notify window manager of window withdrawal");
5735 #else /* ! defined (HAVE_X11R4) */
5738 /* Tell the window manager what we're going to do. */
5739 if (! EQ (Vx_no_window_manager
, Qt
))
5743 unmap
.xunmap
.type
= UnmapNotify
;
5744 unmap
.xunmap
.window
= window
;
5745 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5746 unmap
.xunmap
.from_configure
= False
;
5747 if (! XSendEvent (x_current_display
,
5748 DefaultRootWindow (x_current_display
),
5750 SubstructureRedirectMask
|SubstructureNotifyMask
,
5753 UNBLOCK_INPUT_RESIGNAL
;
5754 error ("Can't notify window manager of withdrawal");
5758 /* Unmap the window ourselves. Cheeky! */
5759 XUnmapWindow (x_current_display
, window
);
5760 #else /* ! defined (HAVE_X11) */
5762 XUnmapWindow (FRAME_X_WINDOW (f
));
5763 if (f
->display
.x
->icon_desc
!= 0)
5764 XUnmapWindow (f
->display
.x
->icon_desc
);
5766 #endif /* ! defined (HAVE_X11) */
5767 #endif /* ! defined (HAVE_X11R4) */
5769 /* We can't distinguish this from iconification
5770 just by the event that we get from the server.
5771 So we can't win using the usual strategy of letting
5772 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5773 and synchronize with the server to make sure we agree. */
5775 FRAME_ICONIFIED_P (f
) = 0;
5776 f
->async_visible
= 0;
5777 f
->async_iconified
= 0;
5784 /* Change window state from mapped to iconified. */
5792 /* Don't keep the highlight on an invisible frame. */
5793 if (x_highlight_frame
== f
)
5794 x_highlight_frame
= 0;
5796 if (f
->async_iconified
)
5799 #ifdef USE_X_TOOLKIT
5802 if (! FRAME_VISIBLE_P (f
))
5804 if (! EQ (Vx_no_window_manager
, Qt
))
5805 x_wm_set_window_state (f
, IconicState
);
5806 /* This was XtPopup, but that did nothing for an iconified frame. */
5807 XtMapWidget (f
->display
.x
->widget
);
5812 result
= XIconifyWindow (x_current_display
,
5813 XtWindow (f
->display
.x
->widget
),
5814 DefaultScreen (x_current_display
));
5818 error ("Can't notify window manager of iconification");
5820 f
->async_iconified
= 1;
5825 #else /* not USE_X_TOOLKIT */
5830 /* Make sure the X server knows where the window should be positioned,
5831 in case the user deiconifies with the window manager. */
5832 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5833 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5835 /* Since we don't know which revision of X we're running, we'll use both
5836 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5838 /* X11R4: send a ClientMessage to the window manager using the
5839 WM_CHANGE_STATE type. */
5843 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5844 message
.xclient
.type
= ClientMessage
;
5845 message
.xclient
.message_type
= Xatom_wm_change_state
;
5846 message
.xclient
.format
= 32;
5847 message
.xclient
.data
.l
[0] = IconicState
;
5849 if (! XSendEvent (x_current_display
,
5850 DefaultRootWindow (x_current_display
),
5852 SubstructureRedirectMask
| SubstructureNotifyMask
,
5855 UNBLOCK_INPUT_RESIGNAL
;
5856 error ("Can't notify window manager of iconification");
5860 /* X11R3: set the initial_state field of the window manager hints to
5862 x_wm_set_window_state (f
, IconicState
);
5864 if (!FRAME_VISIBLE_P (f
))
5866 /* If the frame was withdrawn, before, we must map it. */
5867 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5868 #if 0 /* We don't have subwindows in the icon. */
5869 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5870 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5874 f
->async_iconified
= 1;
5875 #else /* ! defined (HAVE_X11) */
5876 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5878 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
5879 if (f
->display
.x
->icon_desc
!= 0)
5881 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
5884 #endif /* ! defined (HAVE_X11) */
5888 #endif /* not USE_X_TOOLKIT */
5891 /* Destroy the X window of frame F. */
5893 x_destroy_window (f
)
5898 if (f
->display
.x
->icon_desc
!= 0)
5899 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5900 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5901 #ifdef USE_X_TOOLKIT
5902 XtDestroyWidget (f
->display
.x
->widget
);
5903 free_frame_menubar (f
);
5904 #endif /* USE_X_TOOLKIT */
5906 free_frame_faces (f
);
5909 xfree (f
->display
.x
);
5911 if (f
== x_focus_frame
)
5913 if (f
== x_highlight_frame
)
5914 x_highlight_frame
= 0;
5916 if (f
== mouse_face_mouse_frame
)
5918 mouse_face_beg_row
= mouse_face_beg_col
= -1;
5919 mouse_face_end_row
= mouse_face_end_col
= -1;
5920 mouse_face_window
= Qnil
;
5926 /* Manage event queues for X10. */
5930 /* Manage event queues.
5932 This code is only used by the X10 support.
5934 We cannot leave events in the X queue and get them when we are ready
5935 because X does not provide a subroutine to get only a certain kind
5936 of event but not block if there are no queued events of that kind.
5938 Therefore, we must examine events as they come in and copy events
5939 of certain kinds into our private queues.
5941 All ExposeRegion events are put in x_expose_queue.
5942 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5945 /* Write the event *P_XREP into the event queue *QUEUE.
5946 If the queue is full, do nothing, but return nonzero. */
5949 enqueue_event (p_xrep
, queue
)
5950 register XEvent
*p_xrep
;
5951 register struct event_queue
*queue
;
5953 int newindex
= queue
->windex
+ 1;
5954 if (newindex
== EVENT_BUFFER_SIZE
)
5956 if (newindex
== queue
->rindex
)
5958 queue
->xrep
[queue
->windex
] = *p_xrep
;
5959 queue
->windex
= newindex
;
5963 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5964 If *QUEUE is empty, do nothing and return 0. */
5967 dequeue_event (p_xrep
, queue
)
5968 register XEvent
*p_xrep
;
5969 register struct event_queue
*queue
;
5971 if (queue
->windex
== queue
->rindex
)
5973 *p_xrep
= queue
->xrep
[queue
->rindex
++];
5974 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
5979 /* Return the number of events buffered in *QUEUE. */
5982 queue_event_count (queue
)
5983 register struct event_queue
*queue
;
5985 int tem
= queue
->windex
- queue
->rindex
;
5988 return EVENT_BUFFER_SIZE
+ tem
;
5991 /* Return nonzero if mouse input is pending. */
5994 mouse_event_pending_p ()
5996 return queue_event_count (&x_mouse_queue
);
5998 #endif /* HAVE_X11 */
6000 /* Setting window manager hints. */
6004 /* Set the normal size hints for the window manager, for frame F.
6005 FLAGS is the flags word to use--or 0 meaning preserve the flags
6006 that the window now has.
6007 If USER_POSITION is nonzero, we set the USPosition
6008 flag (this is useful when FLAGS is 0). */
6010 x_wm_set_size_hint (f
, flags
, user_position
)
6015 XSizeHints size_hints
;
6017 #ifdef USE_X_TOOLKIT
6020 Dimension widget_width
, widget_height
;
6021 Window window
= XtWindow (f
->display
.x
->widget
);
6022 #else /* not USE_X_TOOLKIT */
6023 Window window
= FRAME_X_WINDOW (f
);
6024 #endif /* not USE_X_TOOLKIT */
6026 /* Setting PMaxSize caused various problems. */
6027 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
6029 flexlines
= f
->height
;
6031 size_hints
.x
= f
->display
.x
->left_pos
;
6032 size_hints
.y
= f
->display
.x
->top_pos
;
6034 #ifdef USE_X_TOOLKIT
6035 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
6036 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
6037 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
6038 size_hints
.height
= widget_height
;
6039 size_hints
.width
= widget_width
;
6040 #else /* not USE_X_TOOLKIT */
6041 size_hints
.height
= PIXEL_HEIGHT (f
);
6042 size_hints
.width
= PIXEL_WIDTH (f
);
6043 #endif /* not USE_X_TOOLKIT */
6045 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
6046 size_hints
.height_inc
= f
->display
.x
->line_height
;
6047 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
6048 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
6051 int base_width
, base_height
;
6052 int min_rows
= 0, min_cols
= 0;
6054 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
6055 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
6057 check_frame_size (f
, &min_rows
, &min_cols
);
6059 /* The window manager uses the base width hints to calculate the
6060 current number of rows and columns in the frame while
6061 resizing; min_width and min_height aren't useful for this
6062 purpose, since they might not give the dimensions for a
6063 zero-row, zero-column frame.
6065 We use the base_width and base_height members if we have
6066 them; otherwise, we set the min_width and min_height members
6067 to the size for a zero x zero frame. */
6070 size_hints
.flags
|= PBaseSize
;
6071 size_hints
.base_width
= base_width
;
6072 size_hints
.base_height
= base_height
;
6073 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
6074 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
6076 size_hints
.min_width
= base_width
;
6077 size_hints
.min_height
= base_height
;
6082 size_hints
.flags
|= flags
;
6085 XSizeHints hints
; /* Sometimes I hate X Windows... */
6086 long supplied_return
;
6090 value
= XGetWMNormalHints (x_current_display
, window
, &hints
,
6093 value
= XGetNormalHints (x_current_display
, window
, &hints
);
6098 if (hints
.flags
& PSize
)
6099 size_hints
.flags
|= PSize
;
6100 if (hints
.flags
& PPosition
)
6101 size_hints
.flags
|= PPosition
;
6102 if (hints
.flags
& USPosition
)
6103 size_hints
.flags
|= USPosition
;
6104 if (hints
.flags
& USSize
)
6105 size_hints
.flags
|= USSize
;
6109 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
6110 size_hints
.flags
|= PWinGravity
;
6114 size_hints
.flags
&= ~ PPosition
;
6115 size_hints
.flags
|= USPosition
;
6117 #endif /* PWinGravity */
6120 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
6122 XSetNormalHints (x_current_display
, window
, &size_hints
);
6126 /* Used for IconicState or NormalState */
6127 x_wm_set_window_state (f
, state
)
6131 #ifdef USE_X_TOOLKIT
6134 XtSetArg (al
[0], XtNinitialState
, state
);
6135 XtSetValues (f
->display
.x
->widget
, al
, 1);
6136 #else /* not USE_X_TOOLKIT */
6137 Window window
= FRAME_X_WINDOW (f
);
6139 f
->display
.x
->wm_hints
.flags
|= StateHint
;
6140 f
->display
.x
->wm_hints
.initial_state
= state
;
6142 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6143 #endif /* not USE_X_TOOLKIT */
6146 x_wm_set_icon_pixmap (f
, icon_pixmap
)
6150 #ifdef USE_X_TOOLKIT
6151 Window window
= XtWindow (f
->display
.x
->widget
);
6153 Window window
= FRAME_X_WINDOW (f
);
6158 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6159 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
6162 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
6164 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6167 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6171 #ifdef USE_X_TOOLKIT
6172 Window window
= XtWindow (f
->display
.x
->widget
);
6174 Window window
= FRAME_X_WINDOW (f
);
6177 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
6178 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
6179 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
6181 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
6185 /* Initialization. */
6187 #ifdef USE_X_TOOLKIT
6188 static XrmOptionDescRec emacs_options
[] = {
6189 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6190 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6192 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6193 XrmoptionSepArg
, NULL
},
6194 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6196 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6197 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6198 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6199 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6200 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6201 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6202 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6204 #endif /* USE_X_TOOLKIT */
6207 x_term_init (display_name
, xrm_option
, resource_name
)
6210 char *resource_name
;
6216 #ifndef F_SETOWN_BUG
6218 extern int old_fcntl_owner
;
6219 #endif /* ! defined (F_SETOWN) */
6220 #endif /* F_SETOWN_BUG */
6226 x_focus_frame
= x_highlight_frame
= 0;
6228 #ifdef USE_X_TOOLKIT
6229 argv
= (char **) XtMalloc (7 * sizeof (char *));
6231 argv
[1] = "-display";
6232 argv
[2] = display_name
;
6234 /* Usually `emacs', but not always. */
6235 argv
[4] = resource_name
;
6239 argv
[argc
++] = "-xrm";
6240 argv
[argc
++] = xrm_option
;
6242 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
6243 emacs_options
, XtNumber (emacs_options
),
6246 XtFree ((char *)argv
);
6247 x_current_display
= XtDisplay (Xt_app_shell
);
6249 #else /* not USE_X_TOOLKIT */
6250 x_current_display
= XOpenDisplay (display_name
);
6251 #endif /* not USE_X_TOOLKIT */
6252 if (x_current_display
== 0)
6253 fatal ("X server %s not responding.\n\
6254 Check the DISPLAY environment variable or use \"-d\"\n",
6260 XSetAfterFunction (x_current_display
, x_trace_wire
);
6262 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
6263 + XSTRING (Vsystem_name
)->size
6265 sprintf (x_id_name
, "%s@%s",
6266 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
6269 /* Figure out which modifier bits mean what. */
6270 x_find_modifier_meanings ();
6272 /* Get the scroll bar cursor. */
6273 x_vertical_scroll_bar_cursor
6274 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
6277 /* Watch for PropertyNotify events on the root window; we use them
6278 to figure out when to invalidate our cache of the cut buffers. */
6279 x_watch_cut_buffer_cache ();
6282 if (ConnectionNumber (x_current_display
) != 0)
6283 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
6284 change_input_fd (ConnectionNumber (x_current_display
));
6286 #endif /* ! defined (HAVE_X11) */
6288 #ifndef F_SETOWN_BUG
6290 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
6291 #ifdef F_SETOWN_SOCK_NEG
6292 /* stdin is a socket here */
6293 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
6294 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6295 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
6296 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6297 #endif /* ! defined (F_SETOWN) */
6298 #endif /* F_SETOWN_BUG */
6302 #endif /* ! defined (SIGIO) */
6304 expose_all_windows
= 0;
6306 clear_frame_hook
= XTclear_frame
;
6307 clear_end_of_line_hook
= XTclear_end_of_line
;
6308 ins_del_lines_hook
= XTins_del_lines
;
6309 change_line_highlight_hook
= XTchange_line_highlight
;
6310 insert_glyphs_hook
= XTinsert_glyphs
;
6311 write_glyphs_hook
= XTwrite_glyphs
;
6312 delete_glyphs_hook
= XTdelete_glyphs
;
6313 ring_bell_hook
= XTring_bell
;
6314 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6315 set_terminal_modes_hook
= XTset_terminal_modes
;
6316 update_begin_hook
= XTupdate_begin
;
6317 update_end_hook
= XTupdate_end
;
6318 set_terminal_window_hook
= XTset_terminal_window
;
6319 read_socket_hook
= XTread_socket
;
6320 frame_up_to_date_hook
= XTframe_up_to_date
;
6321 cursor_to_hook
= XTcursor_to
;
6322 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6323 mouse_position_hook
= XTmouse_position
;
6324 frame_rehighlight_hook
= XTframe_rehighlight
;
6325 frame_raise_lower_hook
= XTframe_raise_lower
;
6326 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6327 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6328 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6329 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6331 scroll_region_ok
= 1; /* we'll scroll partial frames */
6332 char_ins_del_ok
= 0; /* just as fast to write the line */
6333 line_ins_del_ok
= 1; /* we'll just blt 'em */
6334 fast_clear_end_of_line
= 1; /* X does this well */
6335 memory_below_frame
= 0; /* we don't remember what scrolls
6339 /* Try to use interrupt input; if we can't, then start polling. */
6340 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6342 /* Note that there is no real way portable across R3/R4 to get the
6343 original error handler. */
6344 XHandleError (x_error_quitter
);
6345 XHandleIOError (x_io_error_quitter
);
6347 /* Disable Window Change signals; they are handled by X events. */
6349 signal (SIGWINCH
, SIG_DFL
);
6350 #endif /* ! defined (SIGWINCH) */
6352 signal (SIGPIPE
, x_connection_closed
);
6358 staticpro (&last_mouse_scroll_bar
);
6359 last_mouse_scroll_bar
= Qnil
;
6360 staticpro (&mouse_face_window
);
6361 mouse_face_window
= Qnil
;
6363 #endif /* ! defined (HAVE_X11) */
6364 #endif /* ! defined (HAVE_X_WINDOWS) */