1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
30 /* Need syssignal.h for various externs and definitions that may be required
31 by some configurations for calls to signal later in this source file. */
32 #include "syssignal.h"
37 #include "blockinput.h"
39 /* This may include sys/types.h, and that somehow loses
40 if this is not done before the other system files. */
42 #include <X11/cursorfont.h>
45 /* Load sys/types.h if not already loaded.
46 In some systems loading it twice is suicidal. */
48 #include <sys/types.h>
53 #include <sys/ioctl.h>
55 #else /* ! defined (BSD) */
59 #endif /* ! defined (BSD) */
64 #ifndef INCLUDED_FCNTL
71 #include <sys/param.h>
73 #include "dispextern.h"
74 #include "termhooks.h"
88 extern XtAppContext Xt_app_con
;
89 extern Widget Xt_app_shell
;
90 extern void free_frame_menubar ();
91 extern void _XEditResCheckMessages ();
92 #endif /* USE_X_TOOLKIT */
95 #define x_any_window_to_frame x_window_to_frame
96 #define x_top_window_to_frame x_window_to_frame
100 #define XMapWindow XMapRaised /* Raise them when mapping. */
101 #else /* ! defined (HAVE_X11) */
102 #include <X/Xkeyboard.h>
103 /*#include <X/Xproto.h> */
104 #endif /* ! defined (HAVE_X11) */
107 /* We could get this from param.h, but better not to depend on finding that.
108 And better not to risk that it might define other symbols used in this
111 #define MAXDESC FD_SETSIZE
115 #define SELECT_TYPE fd_set
116 #else /* no FD_SET */
118 #define SELECT_TYPE int
120 /* Define the macros to access a single-int bitmap of descriptors. */
121 #define FD_SET(n, p) (*(p) |= (1 << (n)))
122 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
123 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
124 #define FD_ZERO(p) (*(p) = 0)
125 #endif /* no FD_SET */
127 /* For sending Meta-characters. Do we need this? */
130 #define min(a,b) ((a)<(b) ? (a) : (b))
131 #define max(a,b) ((a)>(b) ? (a) : (b))
133 /* Nonzero means we must reprint all windows
134 because 1) we received an ExposeWindow event
135 or 2) we received too many ExposeRegion events to record.
137 This is never needed under X11. */
138 static int expose_all_windows
;
140 /* Nonzero means we must reprint all icon windows. */
142 static int expose_all_icons
;
145 /* ExposeRegion events, when received, are copied into this queue
146 for later processing. */
148 static struct event_queue x_expose_queue
;
150 /* ButtonPress and ButtonReleased events, when received,
151 are copied into this queue for later processing. */
153 struct event_queue x_mouse_queue
;
154 #endif /* HAVE_X11 */
156 #if defined (SIGIO) && defined (FIONREAD)
157 int BLOCK_INPUT_mask
;
158 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
160 /* The id of a bitmap used for icon windows.
161 One such map is shared by all Emacs icon windows.
162 This is zero if we have not yet had a need to create the bitmap. */
164 static Bitmap icon_bitmap
;
166 /* Font used for text icons. */
168 static FONT_TYPE
*icon_font_info
;
170 /* Stuff for dealing with the main icon title. */
172 extern Lisp_Object Vcommand_line_args
;
173 char *hostname
, *x_id_name
;
175 /* This is the X connection that we are using. */
177 Display
*x_current_display
;
179 /* The cursor to use for vertical scroll bars on x_current_display. */
180 static Cursor x_vertical_scroll_bar_cursor
;
182 /* Frame being updated by update_frame. This is declared in term.c.
183 This is set by update_begin and looked at by all the
184 XT functions. It is zero while not inside an update.
185 In that case, the XT functions assume that `selected_frame'
186 is the frame to apply to. */
187 extern struct frame
*updating_frame
;
189 /* The frame (if any) which has the X window that has keyboard focus.
190 Zero if none. This is examined by Ffocus_frame in frame.c. Note
191 that a mere EnterNotify event can set this; if you need to know the
192 last frame specified in a FocusIn or FocusOut event, use
193 x_focus_event_frame. */
194 struct frame
*x_focus_frame
;
196 /* This is a frame waiting to be autoraised, within XTread_socket. */
197 struct frame
*pending_autoraise_frame
;
199 /* The last frame mentioned in a FocusIn or FocusOut event. This is
200 separate from x_focus_frame, because whether or not LeaveNotify
201 events cause us to lose focus depends on whether or not we have
202 received a FocusIn event for it. */
203 struct frame
*x_focus_event_frame
;
205 /* The frame which currently has the visual highlight, and should get
206 keyboard input (other sorts of input have the frame encoded in the
207 event). It points to the X focus frame's selected window's
208 frame. It differs from x_focus_frame when we're using a global
210 static struct frame
*x_highlight_frame
;
212 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
213 mouse is moved to inside of frame when frame is de-iconified. */
215 static int warp_mouse_on_deiconify
;
217 /* During an update, maximum vpos for ins/del line operations to affect. */
219 static int flexlines
;
221 /* During an update, nonzero if chars output now should be highlighted. */
223 static int highlight
;
225 /* Nominal cursor position -- where to draw output.
226 During an update, these are different from the cursor-box position. */
233 In order to avoid asking for motion events and then throwing most
234 of them away or busy-polling the server for mouse positions, we ask
235 the server for pointer motion hints. This means that we get only
236 one event per group of mouse movements. "Groups" are delimited by
237 other kinds of events (focus changes and button clicks, for
238 example), or by XQueryPointer calls; when one of these happens, we
239 get another MotionNotify event the next time the mouse moves. This
240 is at least as efficient as getting motion events when mouse
241 tracking is on, and I suspect only negligibly worse when tracking
244 The silly O'Reilly & Associates Nutshell guides barely document
245 pointer motion hints at all (I think you have to infer how they
246 work from an example), and the description of XQueryPointer doesn't
247 mention that calling it causes you to get another motion hint from
248 the server, which is very important. */
250 /* Where the mouse was last time we reported a mouse event. */
251 static FRAME_PTR last_mouse_frame
;
252 static XRectangle last_mouse_glyph
;
254 /* The scroll bar in which the last X motion event occurred.
256 If the last X motion event occurred in a scroll bar, we set this
257 so XTmouse_position can know whether to report a scroll bar motion or
260 If the last X motion event didn't occur in a scroll bar, we set this
261 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
262 static Lisp_Object last_mouse_scroll_bar
;
264 /* Record which buttons are currently pressed. */
265 unsigned int x_mouse_grabbed
;
267 /* This is a hack. We would really prefer that XTmouse_position would
268 return the time associated with the position it returns, but there
269 doesn't seem to be any way to wrest the timestamp from the server
270 along with the position query. So, we just keep track of the time
271 of the last movement we received, and return that in hopes that
272 it's somewhat accurate. */
273 static Time last_mouse_movement_time
;
275 /* These variables describe the range of text currently shown
276 in its mouse-face, together with the window they apply to.
277 As long as the mouse stays within this range, we need not
278 redraw anything on its account. */
279 static int mouse_face_beg
, mouse_face_end
;
280 static Lisp_Object mouse_face_window
;
281 static int mouse_face_face_id
;
283 /* 1 if a mouse motion event came and we didn't handle it right away because
284 gc was in progress. */
285 static int mouse_face_deferred_gc
;
287 /* FRAME and X, Y position of mouse when last checked for highlighting. */
288 static FRAME_PTR mouse_face_mouse_frame
;
289 static int mouse_face_mouse_x
, mouse_face_mouse_y
;
291 /* Nonzero means defer mouse-motion highlighting. */
292 static int mouse_face_defer
;
295 /* `t' if a mouse button is depressed. */
297 extern Lisp_Object Vmouse_depressed
;
299 /* Tells if a window manager is present or not. */
301 extern Lisp_Object Vx_no_window_manager
;
303 /* Timestamp that we requested selection data was made. */
304 extern Time requestor_time
;
306 /* ID of the window requesting selection data. */
307 extern Window requestor_window
;
309 /* Nonzero enables some debugging for the X interface code. */
312 extern Lisp_Object Qface
, Qmouse_face
;
314 #else /* ! defined (HAVE_X11) */
316 /* Bit patterns for the mouse cursor. */
318 short MouseCursor
[] = {
319 0x0000, 0x0008, 0x0018, 0x0038,
320 0x0078, 0x00f8, 0x01f8, 0x03f8,
321 0x07f8, 0x00f8, 0x00d8, 0x0188,
322 0x0180, 0x0300, 0x0300, 0x0000};
324 short MouseMask
[] = {
325 0x000c, 0x001c, 0x003c, 0x007c,
326 0x00fc, 0x01fc, 0x03fc, 0x07fc,
327 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
328 0x03cc, 0x0780, 0x0780, 0x0300};
330 static short grey_bits
[] = {
331 0x0005, 0x000a, 0x0005, 0x000a};
333 static Pixmap GreyPixmap
= 0;
334 #endif /* ! defined (HAVE_X11) */
336 /* From time to time we get info on an Emacs window, here. */
338 static WINDOWINFO_TYPE windowinfo
;
342 /* A mask of extra modifier bits to put into every keyboard char. */
343 extern int extra_keyboard_modifiers
;
345 extern Display
*XOpenDisplay ();
346 extern Window
XCreateWindow ();
348 extern Cursor
XCreateCursor ();
349 extern FONT_TYPE
*XOpenFont ();
351 static void flashback ();
352 static void redraw_previous_char ();
353 static void redraw_following_char ();
354 static unsigned int x_x_to_emacs_modifiers ();
356 static void note_mouse_highlight ();
357 static void clear_mouse_face ();
358 static void show_mouse_face ();
361 static void dumpqueue ();
362 #endif /* HAVE_X11 */
365 static int XTcursor_to ();
366 static int XTclear_end_of_line ();
369 /* Starting and ending updates.
371 These hooks are called by update_frame at the beginning and end
372 of a frame update. We record in `updating_frame' the identity
373 of the frame being updated, so that the XT... functions do not
374 need to take a frame as argument. Most of the XT... functions
375 should never be called except during an update, the only exceptions
376 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
378 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
389 flexlines
= f
->height
;
394 if (f
== mouse_face_mouse_frame
)
396 /* Don't do highlighting for mouse motion during the update. */
397 mouse_face_defer
= 1;
398 if (!NILP (mouse_face_window
))
400 int firstline
, lastline
, i
;
401 struct window
*w
= XWINDOW (mouse_face_window
);
403 /* Find the first, and the last+1, lines affected by redisplay. */
404 for (firstline
= 0; firstline
< f
->height
; firstline
++)
405 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
408 lastline
= f
->height
;
409 for (i
= f
->height
- 1; i
>= 0; i
--)
411 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
417 /* Can we tell that this update does not affect the window
418 where the mouse highlight is? If so, no need to turn off. */
419 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
420 || lastline
< XFASTINT (w
->top
)))
421 /* Otherwise turn off the mouse highlight now. */
427 #endif /* HAVE_X11 */
432 static void x_do_pending_expose ();
444 x_do_pending_expose ();
445 #endif /* HAVE_X11 */
447 x_display_cursor (f
, 1);
449 if (f
== mouse_face_mouse_frame
)
450 mouse_face_defer
= 0;
452 /* This fails in the case of having updated only the echo area
453 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
454 has no relation to the current contents, and its charstarts
455 have no relation to the contents of the window-buffer.
456 I don't know a clean way to check
457 for that case. window_end_valid isn't set up yet. */
458 if (f
== mouse_face_mouse_frame
)
459 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
466 /* This is called after a redisplay on frame F. */
469 XTframe_up_to_date (f
)
472 if (mouse_face_deferred_gc
|| f
== mouse_face_mouse_frame
)
474 note_mouse_highlight (mouse_face_mouse_frame
,
475 mouse_face_mouse_x
, mouse_face_mouse_y
);
476 mouse_face_deferred_gc
= 0;
480 /* External interface to control of standout mode.
481 Call this when about to modify line at position VPOS
482 and not change whether it is highlighted. */
484 XTreassert_line_highlight (new, vpos
)
490 /* Call this when about to modify line at position VPOS
491 and change whether it is highlighted. */
494 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
495 int new_highlight
, vpos
, first_unused_hpos
;
497 highlight
= new_highlight
;
498 XTcursor_to (vpos
, 0);
499 XTclear_end_of_line (updating_frame
->width
);
502 /* This is used when starting Emacs and when restarting after suspend.
503 When starting Emacs, no X window is mapped. And nothing must be done
504 to Emacs's own window if it is suspended (though that rarely happens). */
507 XTset_terminal_modes ()
511 /* This is called when exiting or suspending Emacs.
512 Exiting will make the X-windows go away, and suspending
513 requires no action. */
516 XTreset_terminal_modes ()
518 /* XTclear_frame (); */
521 /* Set the nominal cursor position of the frame.
522 This is where display update commands will take effect.
523 This does not affect the place where the cursor-box is displayed. */
526 XTcursor_to (row
, col
)
527 register int row
, col
;
535 if (updating_frame
== 0)
538 x_display_cursor (selected_frame
, 1);
544 /* Display a sequence of N glyphs found at GP.
545 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
546 HL is 1 if this text is highlighted, 2 if the cursor is on it,
547 3 if should appear in its mouse-face.
548 JUST_FOREGROUND if 1 means draw only the foreground;
549 don't alter the background.
551 FONT is the default font to use (for glyphs whose font-code is 0).
553 Since the display generation code is responsible for calling
554 compute_char_face and compute_glyph_face on everything it puts in
555 the display structure, we can assume that the face code on each
556 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
557 to which we can actually apply intern_face.
558 Call this function with input blocked. */
561 /* This is the multi-face code. */
564 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
567 register GLYPH
*gp
; /* Points to first GLYPH. */
568 register int n
; /* Number of glyphs to display. */
572 /* Holds characters to be displayed. */
573 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
574 register char *cp
; /* Steps through buf[]. */
575 register int tlen
= GLYPH_TABLE_LENGTH
;
576 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
577 Window window
= FRAME_X_WINDOW (f
);
578 int orig_left
= left
;
582 /* Get the face-code of the next GLYPH. */
586 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
587 cf
= FAST_GLYPH_FACE (g
);
589 /* Find the run of consecutive glyphs with the same face-code.
590 Extract their character codes into BUF. */
595 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
596 if (FAST_GLYPH_FACE (g
) != cf
)
599 *cp
++ = FAST_GLYPH_CHAR (g
);
604 /* LEN gets the length of the run. */
607 /* Now output this run of chars, with the font and pixel values
608 determined by the face code CF. */
610 struct face
*face
= FRAME_DEFAULT_FACE (f
);
611 FONT_TYPE
*font
= FACE_FONT (face
);
612 GC gc
= FACE_GC (face
);
613 int gc_temporary
= 0;
615 /* HL = 3 means use a mouse face previously chosen. */
617 cf
= mouse_face_face_id
;
619 /* First look at the face of the text itself. */
622 /* It's possible for the display table to specify
623 a face code that is out of range. Use 0 in that case. */
624 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
625 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
629 face
= FRAME_MODE_LINE_FACE (f
);
631 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
632 font
= FACE_FONT (face
);
636 /* Then comes the distinction between modeline and normal text. */
641 face
= FRAME_MODE_LINE_FACE (f
);
642 font
= FACE_FONT (face
);
646 #define FACE_DEFAULT (~0)
648 /* Now override that if the cursor's on this character. */
652 || (int) face
->font
== FACE_DEFAULT
)
654 gc
= f
->display
.x
->cursor_gc
;
656 /* Cursor on non-default face: must merge. */
662 xgcv
.background
= f
->display
.x
->cursor_pixel
;
663 if (face
== FRAME_DEFAULT_FACE (f
))
664 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
666 xgcv
.foreground
= face
->foreground
;
667 /* If the glyph would be invisible,
668 try a different foreground. */
669 if (xgcv
.foreground
== xgcv
.background
)
670 xgcv
.foreground
= face
->background
;
671 if (xgcv
.foreground
== xgcv
.background
)
672 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
673 if (xgcv
.foreground
== xgcv
.background
)
674 xgcv
.foreground
= face
->foreground
;
675 /* Make sure the cursor is distinct from text in this face. */
676 if (xgcv
.background
== face
->background
677 && xgcv
.foreground
== face
->foreground
)
679 xgcv
.background
= face
->foreground
;
680 xgcv
.foreground
= face
->background
;
682 xgcv
.font
= face
->font
->fid
;
683 xgcv
.graphics_exposures
= 0;
684 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
685 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
688 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
689 XSetStipple (x_current_display
, gc
, face
->stipple
);
695 if ((int) font
== FACE_DEFAULT
)
696 font
= f
->display
.x
->font
;
699 XDrawString (x_current_display
, window
, gc
,
700 left
, top
+ FONT_BASE (font
), buf
, len
);
703 XDrawImageString (x_current_display
, window
, gc
,
704 left
, top
+ FONT_BASE (font
), buf
, len
);
705 /* Clear the rest of the line's height. */
706 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
707 XClearArea (x_current_display
, window
, left
,
708 top
+ FONT_HEIGHT (font
),
709 FONT_WIDTH (font
) * len
,
710 /* This is how many pixels of height
712 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
716 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
717 which often is not up to date yet. */
718 if (!just_foreground
)
720 if (left
== orig_left
)
721 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
722 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
724 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
725 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
730 XFreeGC (x_current_display
, gc
);
732 /* We should probably check for XA_UNDERLINE_POSITION and
733 XA_UNDERLINE_THICKNESS properties on the font, but let's
734 just get the thing working, and come back to that. */
736 int underline_position
= 1;
738 if (font
->descent
<= underline_position
)
739 underline_position
= font
->descent
- 1;
742 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
746 + underline_position
),
747 len
* FONT_WIDTH (font
), 1);
750 left
+= len
* FONT_WIDTH (font
);
757 /* This is the old single-face code. */
760 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
763 register GLYPH
*gp
; /* Points to first GLYPH. */
764 register int n
; /* Number of glyphs to display. */
769 Window window
= FRAME_X_WINDOW (f
);
770 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
771 : (hl
? f
->display
.x
->reverse_gc
772 : f
->display
.x
->normal_gc
));
774 if (sizeof (GLYPH
) == sizeof (XChar2b
))
775 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
776 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
777 else if (sizeof (GLYPH
) == sizeof (unsigned char))
778 XDrawImageString (x_current_display
, window
, drawing_gc
,
779 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
781 /* What size of glyph ARE you using? And does X have a function to
787 /* Output some text at the nominal frame cursor position.
788 Advance the cursor over the text.
789 Output LEN glyphs at START.
791 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
792 controls the pixel values used for foreground and background. */
795 XTwrite_glyphs (start
, len
)
796 register GLYPH
*start
;
799 register int temp_length
;
809 /* If not within an update,
810 output at the frame's visible cursor. */
811 curs_x
= f
->cursor_x
;
812 curs_y
= f
->cursor_y
;
816 CHAR_TO_PIXEL_COL (f
, curs_x
),
817 CHAR_TO_PIXEL_ROW (f
, curs_y
),
818 start
, len
, highlight
, 0);
820 /* If we drew on top of the cursor, note that it is turned off. */
821 if (curs_y
== f
->phys_cursor_y
822 && curs_x
<= f
->phys_cursor_x
823 && curs_x
+ len
> f
->phys_cursor_x
)
824 f
->phys_cursor_x
= -1;
826 if (updating_frame
== 0)
829 x_display_cursor (f
, 1);
838 /* Clear to the end of the line.
839 Erase the current text line from the nominal cursor position (inclusive)
840 to column FIRST_UNUSED (exclusive). The idea is that everything
841 from FIRST_UNUSED onward is already erased. */
844 XTclear_end_of_line (first_unused
)
845 register int first_unused
;
847 struct frame
*f
= updating_frame
;
853 if (curs_y
< 0 || curs_y
>= f
->height
)
855 if (first_unused
<= 0)
858 if (first_unused
>= f
->width
)
859 first_unused
= f
->width
;
863 /* Notice if the cursor will be cleared by this operation. */
864 if (curs_y
== f
->phys_cursor_y
865 && curs_x
<= f
->phys_cursor_x
866 && f
->phys_cursor_x
< first_unused
)
867 f
->phys_cursor_x
= -1;
870 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
871 CHAR_TO_PIXEL_COL (f
, curs_x
),
872 CHAR_TO_PIXEL_ROW (f
, curs_y
),
873 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
874 f
->display
.x
->line_height
, False
);
876 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
878 #else /* ! defined (HAVE_X11) */
879 XPixSet (FRAME_X_WINDOW (f
),
880 CHAR_TO_PIXEL_COL (f
, curs_x
),
881 CHAR_TO_PIXEL_ROW (f
, curs_y
),
882 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
883 f
->display
.x
->line_height
,
884 f
->display
.x
->background_pixel
);
885 #endif /* ! defined (HAVE_X11) */
894 struct frame
*f
= updating_frame
;
899 f
->phys_cursor_x
= -1; /* Cursor not visible. */
900 curs_x
= 0; /* Nominal cursor position is top left. */
905 XClear (FRAME_X_WINDOW (f
));
907 /* We have to clear the scroll bars, too. If we have changed
908 colors or something like that, then they should be notified. */
909 x_scroll_bar_clear (f
);
913 #endif /* HAVE_X11 */
920 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
921 always contain the right glyphs to use.
923 It also needs to be changed to look at the details of the font and
924 see whether there is really overlap, and do nothing when there is
925 not. This can use font_char_overlap_left and font_char_overlap_right,
926 but just how to use them is not clear. */
928 /* Erase the character (if any) at the position just before X, Y in frame F,
929 then redraw it and the character before it.
930 This is necessary when we erase starting at X,
931 in case the character after X overlaps into the one before X.
932 Call this function with input blocked. */
935 redraw_previous_char (f
, x
, y
, highlight_flag
)
940 /* Erase the character before the new ones, in case
941 what was here before overlaps it.
942 Reoutput that character, and the previous character
943 (in case the previous character overlaps it). */
949 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
950 CHAR_TO_PIXEL_COL (f
, x
- 1),
951 CHAR_TO_PIXEL_ROW (f
, y
),
952 FONT_WIDTH (f
->display
.x
->font
),
953 f
->display
.x
->line_height
, False
);
955 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
956 CHAR_TO_PIXEL_ROW (f
, y
),
957 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
958 x
- start_x
, highlight_flag
, 1);
962 /* Erase the character (if any) at the position X, Y in frame F,
963 then redraw it and the character after it.
964 This is necessary when we erase endng at X,
965 in case the character after X overlaps into the one before X.
966 Call this function with input blocked. */
969 redraw_following_char (f
, x
, y
, highlight_flag
)
974 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
975 /* Erase the character after the new ones, in case
976 what was here before overlaps it.
977 Reoutput that character, and the following character
978 (in case the following character overlaps it). */
980 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
985 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
986 CHAR_TO_PIXEL_COL (f
, x
),
987 CHAR_TO_PIXEL_ROW (f
, y
),
988 FONT_WIDTH (f
->display
.x
->font
),
989 f
->display
.x
->line_height
, False
);
991 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
992 CHAR_TO_PIXEL_ROW (f
, y
),
993 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
994 end_x
- x
, highlight_flag
, 1);
999 #if 0 /* Not in use yet */
1001 /* Return 1 if character C in font F extends past its left edge. */
1004 font_char_overlap_left (font
, c
)
1010 /* Find the bounding-box info for C. */
1011 if (font
->per_char
== 0)
1012 s
= &font
->max_bounds
;
1015 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1018 /* Decode char into row number (byte 1) and code within row (byte 2). */
1021 if (!(within
>= font
->min_char_or_byte2
1022 && within
<= font
->max_char_or_byte2
1023 && row
>= font
->min_byte1
1024 && row
<= font
->max_byte1
))
1026 /* If char is out of range, try the font's default char instead. */
1027 c
= font
->default_char
;
1028 row
= c
>> (INTBITS
- 8);
1031 if (!(within
>= font
->min_char_or_byte2
1032 && within
<= font
->max_char_or_byte2
1033 && row
>= font
->min_byte1
1034 && row
<= font
->max_byte1
))
1035 /* Still out of range means this char does not overlap. */
1038 /* We found the info for this char. */
1039 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1043 return (s
&& s
->lbearing
< 0);
1046 /* Return 1 if character C in font F extends past its right edge. */
1049 font_char_overlap_right (font
, c
)
1055 /* Find the bounding-box info for C. */
1056 if (font
->per_char
== 0)
1057 s
= &font
->max_bounds
;
1060 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1063 /* Decode char into row number (byte 1) and code within row (byte 2). */
1066 if (!(within
>= font
->min_char_or_byte2
1067 && within
<= font
->max_char_or_byte2
1068 && row
>= font
->min_byte1
1069 && row
<= font
->max_byte1
))
1071 /* If char is out of range, try the font's default char instead. */
1072 c
= font
->default_char
;
1073 row
= c
>> (INTBITS
- 8);
1076 if (!(within
>= font
->min_char_or_byte2
1077 && within
<= font
->max_char_or_byte2
1078 && row
>= font
->min_byte1
1079 && row
<= font
->max_byte1
))
1080 /* Still out of range means this char does not overlap. */
1083 /* We found the info for this char. */
1084 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1088 return (s
&& s
->rbearing
>= s
->width
);
1092 /* Invert the middle quarter of the frame for .15 sec. */
1094 /* We use the select system call to do the waiting, so we have to make sure
1095 it's available. If it isn't, we just won't do visual bells. */
1096 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1098 /* Subtract the `struct timeval' values X and Y,
1099 storing the result in RESULT.
1100 Return 1 if the difference is negative, otherwise 0. */
1103 timeval_subtract (result
, x
, y
)
1104 struct timeval
*result
, x
, y
;
1106 /* Perform the carry for the later subtraction by updating y.
1107 This is safer because on some systems
1108 the tv_sec member is unsigned. */
1109 if (x
.tv_usec
< y
.tv_usec
)
1111 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1112 y
.tv_usec
-= 1000000 * nsec
;
1115 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1117 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1118 y
.tv_usec
+= 1000000 * nsec
;
1122 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1123 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1124 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1126 /* Return indication of whether the result should be considered negative. */
1127 return x
.tv_sec
< y
.tv_sec
;
1138 /* Create a GC that will use the GXxor function to flip foreground pixels
1139 into background pixels. */
1143 values
.function
= GXxor
;
1144 values
.foreground
= (f
->display
.x
->foreground_pixel
1145 ^ f
->display
.x
->background_pixel
);
1147 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
1148 GCFunction
| GCForeground
, &values
);
1152 int width
= PIXEL_WIDTH (f
);
1153 int height
= PIXEL_HEIGHT (f
);
1155 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1156 width
/4, height
/4, width
/2, height
/2);
1157 XFlush (x_current_display
);
1160 struct timeval wakeup
, now
;
1162 EMACS_GET_TIME (wakeup
);
1164 /* Compute time to wait until, propagating carry from usecs. */
1165 wakeup
.tv_usec
+= 150000;
1166 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1167 wakeup
.tv_usec
%= 1000000;
1169 /* Keep waiting until past the time wakeup. */
1172 struct timeval timeout
;
1174 EMACS_GET_TIME (timeout
);
1176 /* In effect, timeout = wakeup - timeout.
1177 Break if result would be negative. */
1178 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1181 /* Try to wait that long--but we might wake up sooner. */
1182 select (0, 0, 0, 0, &timeout
);
1186 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1187 width
/4, height
/4, width
/2, height
/2);
1188 XFreeGC (x_current_display
, gc
);
1189 XFlush (x_current_display
);
1199 /* Make audible bell. */
1202 #define XRINGBELL XBell (x_current_display, 0)
1203 #else /* ! defined (HAVE_X11) */
1204 #define XRINGBELL XFeep (0);
1205 #endif /* ! defined (HAVE_X11) */
1209 if (x_current_display
== 0)
1212 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1214 XTflash (selected_frame
);
1225 /* Insert and delete character.
1226 These are not supposed to be used because we are supposed to turn
1227 off the feature of using them. */
1230 XTinsert_glyphs (start
, len
)
1231 register char *start
;
1244 /* Specify how many text lines, from the top of the window,
1245 should be affected by insert-lines and delete-lines operations.
1246 This, and those operations, are used only within an update
1247 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1250 XTset_terminal_window (n
)
1253 if (updating_frame
== 0)
1256 if ((n
<= 0) || (n
> updating_frame
->height
))
1257 flexlines
= updating_frame
->height
;
1262 /* Perform an insert-lines operation.
1263 Insert N lines at a vertical position curs_y. */
1269 register int topregion
, bottomregion
;
1270 register int length
, newtop
, mask
;
1271 register struct frame
*f
= updating_frame
;
1272 int intborder
= f
->display
.x
->internal_border_width
;
1274 if (curs_y
>= flexlines
)
1278 bottomregion
= flexlines
- (n
+ 1);
1279 newtop
= topregion
+ n
;
1280 length
= (bottomregion
- topregion
) + 1;
1284 #endif /* HAVE_X11 */
1286 if ((length
> 0) && (newtop
<= flexlines
))
1289 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1290 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1291 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1292 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1293 length
* f
->display
.x
->line_height
, intborder
,
1294 CHAR_TO_PIXEL_ROW (f
, newtop
));
1295 #else /* ! defined (HAVE_X11) */
1296 XMoveArea (FRAME_X_WINDOW (f
),
1297 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1298 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1299 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1300 length
* f
->display
.x
->line_height
);
1301 /* Now we must process any ExposeRegion events that occur
1302 if the area being copied from is obscured.
1303 We can't let it wait because further i/d operations
1304 may want to copy this area to another area. */
1306 #endif /* ! defined (HAVE_X11) */
1309 newtop
= min (newtop
, (flexlines
- 1));
1310 length
= newtop
- topregion
;
1314 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1315 CHAR_TO_PIXEL_ROW (f
, topregion
),
1316 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1317 n
* f
->display
.x
->line_height
, False
);
1318 #else /* ! defined (HAVE_X11) */
1319 XPixSet (FRAME_X_WINDOW (f
),
1321 CHAR_TO_PIXEL_ROW (f
, topregion
),
1322 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1323 n
* f
->display
.x
->line_height
,
1324 f
->display
.x
->background_pixel
);
1325 #endif /* ! defined (HAVE_X11) */
1329 /* Perform a delete-lines operation, deleting N lines
1330 at a vertical position curs_y. */
1337 register struct frame
*f
= updating_frame
;
1338 int intborder
= f
->display
.x
->internal_border_width
;
1340 if (curs_y
>= flexlines
)
1345 #endif /* HAVE_X11 */
1347 if ((curs_y
+ n
) >= flexlines
)
1349 if (flexlines
>= (curs_y
+ 1))
1352 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1353 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1354 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1355 (flexlines
- curs_y
) * f
->display
.x
->line_height
, False
);
1356 #else /* ! defined (HAVE_X11) */
1357 XPixSet (FRAME_X_WINDOW (f
),
1358 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1359 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1360 (flexlines
- curs_y
) * f
->display
.x
->line_height
,
1361 f
->display
.x
->background_pixel
);
1362 #endif /* ! defined (HAVE_X11) */
1368 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1369 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1371 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1372 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1373 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
,
1374 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1375 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1377 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1378 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1379 n
* f
->display
.x
->line_height
, False
);
1380 #else /* ! defined (HAVE_X11) */
1381 XMoveArea (FRAME_X_WINDOW (f
),
1383 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1384 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1385 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1386 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
);
1387 /* Now we must process any ExposeRegion events that occur
1388 if the area being copied from is obscured.
1389 We can't let it wait because further i/d operations
1390 may want to copy this area to another area. */
1392 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1393 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1394 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1395 n
* f
->display
.x
->line_height
, f
->display
.x
->background_pixel
);
1396 #endif /* ! defined (HAVE_X11) */
1400 /* Perform an insert-lines or delete-lines operation,
1401 inserting N lines or deleting -N lines at vertical position VPOS. */
1403 XTins_del_lines (vpos
, n
)
1406 if (updating_frame
== 0)
1409 /* Hide the cursor. */
1410 x_display_cursor (updating_frame
, 0);
1412 XTcursor_to (vpos
, 0);
1423 /* Support routines for exposure events. */
1424 static void clear_cursor ();
1426 /* Output into a rectangle of an X-window (for frame F)
1427 the characters in f->phys_lines that overlap that rectangle.
1428 TOP and LEFT are the position of the upper left corner of the rectangle.
1429 ROWS and COLS are the size of the rectangle.
1430 Call this function with input blocked. */
1433 dumprectangle (f
, left
, top
, cols
, rows
)
1435 register int left
, top
, cols
, rows
;
1437 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1438 int cursor_cleared
= 0;
1442 if (FRAME_GARBAGED_P (f
))
1445 /* Express rectangle as four edges, instead of position-and-size. */
1446 bottom
= top
+ rows
;
1447 right
= left
+ cols
;
1449 #ifndef HAVE_X11 /* Window manger does this for X11. */
1451 int intborder
= f
->display
.x
->internal_border_width
;
1453 /* If the rectangle includes any of the internal border area,
1454 redisplay the border emphasis. */
1455 if (top
< intborder
|| left
< intborder
1456 || bottom
> intborder
+ f
->height
* f
->display
.x
->line_height
1457 || right
> intborder
+ f
->width
* f
->display
.x
->line_height
)
1460 #endif /* not HAVE_X11 Window manger does this for X11. */
1462 /* Convert rectangle edges in pixels to edges in chars.
1463 Round down for left and top, up for right and bottom. */
1464 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1465 left
= PIXEL_TO_CHAR_COL (f
, left
);
1466 bottom
+= (f
->display
.x
->line_height
- 1);
1467 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1468 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1469 right
= PIXEL_TO_CHAR_COL (f
, right
);
1471 /* Clip the rectangle to what can be visible. */
1476 if (right
> f
->width
)
1478 if (bottom
> f
->height
)
1481 /* Get size in chars of the rectangle. */
1482 cols
= right
- left
;
1483 rows
= bottom
- top
;
1485 /* If rectangle has zero area, return. */
1486 if (rows
<= 0) return;
1487 if (cols
<= 0) return;
1489 /* Turn off the cursor if it is in the rectangle.
1490 We will turn it back on afterward. */
1491 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1492 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1498 /* Display the text in the rectangle, one text line at a time. */
1500 for (y
= top
; y
< bottom
; y
++)
1502 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1504 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1508 CHAR_TO_PIXEL_COL (f
, left
),
1509 CHAR_TO_PIXEL_ROW (f
, y
),
1510 line
, min (cols
, active_frame
->used
[y
] - left
),
1511 active_frame
->highlight
[y
], 0);
1514 /* Turn the cursor on if we turned it off. */
1517 x_display_cursor (f
, 1);
1521 /* Process all queued ExposeRegion events. */
1527 XExposeRegionEvent r
;
1529 while (dequeue_event (&r
, &x_expose_queue
))
1531 struct frame
*f
= x_window_to_frame (r
.window
);
1532 if (f
->display
.x
->icon_desc
== r
.window
)
1535 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1539 #endif /* HAVE_X11 */
1541 /* Process all expose events that are pending, for X10.
1542 Redraws the cursor if necessary on any frame that
1543 is not in the process of being updated with update_frame. */
1547 x_do_pending_expose ()
1551 Lisp_Object tail
, frame
;
1553 if (expose_all_windows
)
1555 expose_all_windows
= 0;
1556 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1558 register int temp_width
, temp_height
;
1561 frame
= XCONS (tail
)->car
;
1562 if (XGCTYPE (frame
) != Lisp_Frame
)
1565 if (! FRAME_X_P (f
))
1567 if (!f
->async_visible
)
1569 if (!f
->display
.x
->needs_exposure
)
1572 intborder
= f
->display
.x
->internal_border_width
;
1575 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1576 temp_width
= ((windowinfo
.width
- 2 * intborder
1577 - f
->display
.x
->v_scroll_bar_width
)
1578 / FONT_WIDTH (f
->display
.x
->font
));
1579 temp_height
= ((windowinfo
.height
- 2 * intborder
1580 - f
->display
.x
->h_scroll_bar_height
)
1581 / f
->display
.x
->line_height
);
1582 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1584 change_frame_size (f
, max (1, temp_height
),
1585 max (1, temp_width
), 0, 1);
1586 x_resize_scroll_bars (f
);
1588 f
->display
.x
->left_pos
= windowinfo
.x
;
1589 f
->display
.x
->top_pos
= windowinfo
.y
;
1590 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1594 f
->display
.x
->needs_exposure
= 0;
1595 if (updating_frame
!= f
)
1596 x_display_cursor (f
, 1);
1601 /* Handle any individual-rectangle expose events queued
1602 for various windows. */
1605 #else /* ! defined (HAVE_X11) */
1607 #endif /* ! defined (HAVE_X11) */
1613 frame_highlight (frame
)
1614 struct frame
*frame
;
1616 /* We used to only do this if Vx_no_window_manager was non-nil, but
1617 the ICCCM (section 4.1.6) says that the window's border pixmap
1618 and border pixel are window attributes which are "private to the
1619 client", so we can always change it to whatever we want. */
1621 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1622 frame
->display
.x
->border_pixel
);
1624 x_display_cursor (frame
, 1);
1628 frame_unhighlight (frame
)
1629 struct frame
*frame
;
1631 /* We used to only do this if Vx_no_window_manager was non-nil, but
1632 the ICCCM (section 4.1.6) says that the window's border pixmap
1633 and border pixel are window attributes which are "private to the
1634 client", so we can always change it to whatever we want. */
1636 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1637 frame
->display
.x
->border_tile
);
1639 x_display_cursor (frame
, 1);
1641 #else /* ! defined (HAVE_X11) */
1642 /* Dump the border-emphasis of frame F.
1643 If F is selected, this is a lining of the same color as the border,
1644 just within the border, occupying a portion of the internal border.
1645 If F is not selected, it is background in the same place.
1646 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1648 ALWAYS = 1 is used when a frame becomes selected or deselected.
1649 In that case, we also turn the cursor off and on again
1650 so it will appear in the proper shape (solid if selected; else hollow.) */
1653 dumpborder (f
, always
)
1657 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1658 int width
= PIXEL_WIDTH (f
);
1659 int height
= PIXEL_HEIGHT (f
);
1662 if (f
!= selected_frame
)
1667 pixel
= f
->display
.x
->background_pixel
;
1671 pixel
= f
->display
.x
->border_pixel
;
1674 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1675 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1676 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1678 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1682 x_display_cursor (f
, 1);
1684 #endif /* ! defined (HAVE_X11) */
1686 static void XTframe_rehighlight ();
1688 /* The focus has changed. Update the frames as necessary to reflect
1689 the new situation. Note that we can't change the selected frame
1690 here, because the lisp code we are interrupting might become confused.
1691 Each event gets marked with the frame in which it occurred, so the
1692 lisp code can tell when the switch took place by examining the events. */
1695 x_new_focus_frame (frame
)
1696 struct frame
*frame
;
1698 struct frame
*old_focus
= x_focus_frame
;
1699 int events_enqueued
= 0;
1701 if (frame
!= x_focus_frame
)
1703 /* Set this before calling other routines, so that they see
1704 the correct value of x_focus_frame. */
1705 x_focus_frame
= frame
;
1707 if (old_focus
&& old_focus
->auto_lower
)
1708 x_lower_frame (old_focus
);
1711 selected_frame
= frame
;
1712 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1713 Lisp_Frame
, selected_frame
);
1714 Fselect_window (selected_frame
->selected_window
);
1715 choose_minibuf_frame ();
1718 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1719 pending_autoraise_frame
= x_focus_frame
;
1721 pending_autoraise_frame
= 0;
1724 XTframe_rehighlight ();
1728 /* The focus has changed, or we have redirected a frame's focus to
1729 another frame (this happens when a frame uses a surrogate
1730 minibuffer frame). Shift the highlight as appropriate. */
1732 XTframe_rehighlight ()
1734 struct frame
*old_highlight
= x_highlight_frame
;
1739 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1740 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1742 if (! FRAME_LIVE_P (x_highlight_frame
))
1744 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1745 x_highlight_frame
= x_focus_frame
;
1749 x_highlight_frame
= 0;
1751 if (x_highlight_frame
!= old_highlight
)
1754 frame_unhighlight (old_highlight
);
1755 if (x_highlight_frame
)
1756 frame_highlight (x_highlight_frame
);
1760 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1762 /* Which modifier keys are on which modifier bits?
1764 With each keystroke, X returns eight bits indicating which modifier
1765 keys were held down when the key was pressed. The interpretation
1766 of the top five modifier bits depends on what keys are attached
1767 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1770 x_meta_mod_mask is a mask containing the bits used for the meta key.
1771 It may have more than one bit set, if more than one modifier bit
1772 has meta keys on it. Basically, if EVENT is a KeyPress event,
1773 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1775 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1776 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1777 only be affected by the lock modifier bit if XK_Shift_Lock is in
1778 use; XK_Caps_Lock should only affect alphabetic keys. With this
1779 arrangement, the lock modifier should shift the character if
1780 (EVENT.state & x_shift_lock_mask) != 0. */
1781 static int x_meta_mod_mask
, x_shift_lock_mask
;
1783 /* These are like x_meta_mod_mask, but for different modifiers. */
1784 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1786 /* Initialize mode_switch_bit and modifier_meaning. */
1788 x_find_modifier_meanings ()
1790 int min_code
, max_code
;
1793 XModifierKeymap
*mods
;
1795 x_meta_mod_mask
= 0;
1796 x_shift_lock_mask
= 0;
1798 x_super_mod_mask
= 0;
1799 x_hyper_mod_mask
= 0;
1802 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1804 min_code
= x_current_display
->min_keycode
;
1805 max_code
= x_current_display
->max_keycode
;
1808 syms
= XGetKeyboardMapping (x_current_display
,
1809 min_code
, max_code
- min_code
+ 1,
1811 mods
= XGetModifierMapping (x_current_display
);
1813 /* Scan the modifier table to see which modifier bits the Meta and
1814 Alt keysyms are on. */
1816 int row
, col
; /* The row and column in the modifier table. */
1818 for (row
= 3; row
< 8; row
++)
1819 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1822 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1824 /* Zeroes are used for filler. Skip them. */
1828 /* Are any of this keycode's keysyms a meta key? */
1832 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1834 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1840 x_meta_mod_mask
|= (1 << row
);
1845 x_alt_mod_mask
|= (1 << row
);
1850 x_hyper_mod_mask
|= (1 << row
);
1855 x_super_mod_mask
|= (1 << row
);
1859 /* Ignore this if it's not on the lock modifier. */
1860 if ((1 << row
) == LockMask
)
1861 x_shift_lock_mask
= LockMask
;
1869 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1870 if (! x_meta_mod_mask
)
1872 x_meta_mod_mask
= x_alt_mod_mask
;
1876 /* If some keys are both alt and meta,
1877 make them just meta, not alt. */
1878 if (x_alt_mod_mask
& x_meta_mod_mask
)
1880 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1883 XFree ((char *) syms
);
1884 XFreeModifiermap (mods
);
1887 /* Convert between the modifier bits X uses and the modifier bits
1890 x_x_to_emacs_modifiers (state
)
1893 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1894 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1895 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1896 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1897 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1898 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1902 x_emacs_to_x_modifiers (state
)
1905 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1906 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1907 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1908 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1909 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1910 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1913 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1914 return as a function key. If you add a keysym to this, you should
1915 make sure that the tables make_lispy_event uses contain a suitable
1918 x_is_vendor_fkey (sym
)
1923 || (sym
== DXK_Remove
)
1929 /* Mouse clicks and mouse movement. Rah. */
1932 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1933 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1934 that the glyph at X, Y occupies, if BOUNDS != 0.
1935 If NOCLIP is nonzero, do not force the value into range. */
1938 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1940 register int pix_x
, pix_y
;
1941 register int *x
, *y
;
1945 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1946 even for negative values. */
1948 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1950 pix_y
-= (f
)->display
.x
->line_height
- 1;
1952 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1953 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1957 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1958 bounds
->height
= f
->display
.x
->line_height
;
1959 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1960 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1967 else if (pix_x
> f
->width
)
1972 else if (pix_y
> f
->height
)
1981 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1984 register int *pix_x
, *pix_y
;
1986 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1987 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1990 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1992 If the event is a button press, then note that we have grabbed
1996 construct_mouse_click (result
, event
, f
)
1997 struct input_event
*result
;
1998 XButtonEvent
*event
;
2001 /* Make the event type no_event; we'll change that when we decide
2003 result
->kind
= mouse_click
;
2004 result
->code
= event
->button
- Button1
;
2005 result
->timestamp
= event
->time
;
2006 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2007 | (event
->type
== ButtonRelease
2011 /* Notice if the mouse is still grabbed. */
2012 if (event
->type
== ButtonPress
)
2014 if (! x_mouse_grabbed
)
2015 Vmouse_depressed
= Qt
;
2016 x_mouse_grabbed
|= (1 << event
->button
);
2017 last_mouse_frame
= f
;
2019 else if (event
->type
== ButtonRelease
)
2021 x_mouse_grabbed
&= ~(1 << event
->button
);
2022 if (!x_mouse_grabbed
)
2023 Vmouse_depressed
= Qnil
;
2030 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2031 XFASTINT (result
->x
) = column
;
2032 XFASTINT (result
->y
) = row
;
2034 XSET (result
->x
, Lisp_Int
, event
->x
);
2035 XSET (result
->y
, Lisp_Int
, event
->y
);
2036 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2040 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2043 construct_menu_click (result
, event
, f
)
2044 struct input_event
*result
;
2045 XButtonEvent
*event
;
2048 /* Make the event type no_event; we'll change that when we decide
2050 result
->kind
= mouse_click
;
2051 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
2052 result
->timestamp
= event
->time
;
2053 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
2054 | (event
->type
== ButtonRelease
2058 XSET (result
->x
, Lisp_Int
, event
->x
);
2059 XSET (result
->y
, Lisp_Int
, -1);
2060 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
2063 /* Function to report a mouse movement to the mainstream Emacs code.
2064 The input handler calls this.
2066 We have received a mouse movement event, which is given in *event.
2067 If the mouse is over a different glyph than it was last time, tell
2068 the mainstream emacs code by setting mouse_moved. If not, ask for
2069 another motion event, so we can check again the next time it moves. */
2072 note_mouse_movement (frame
, event
)
2074 XMotionEvent
*event
;
2077 last_mouse_movement_time
= event
->time
;
2079 /* Has the mouse moved off the glyph it was on at the last sighting? */
2080 if (event
->x
< last_mouse_glyph
.x
2081 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2082 || event
->y
< last_mouse_glyph
.y
2083 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2086 last_mouse_scroll_bar
= Qnil
;
2088 note_mouse_highlight (frame
, event
->x
, event
->y
);
2090 /* Ask for another mouse motion event. */
2094 XQueryPointer (event
->display
, event
->window
,
2095 (Window
*) &dummy
, (Window
*) &dummy
,
2096 &dummy
, &dummy
, &dummy
, &dummy
,
2097 (unsigned int *) &dummy
);
2102 /* It's on the same glyph. Call XQueryPointer so we'll get an
2103 event the next time the mouse moves and we can see if it's
2104 *still* on the same glyph. */
2107 XQueryPointer (event
->display
, event
->window
,
2108 (Window
*) &dummy
, (Window
*) &dummy
,
2109 &dummy
, &dummy
, &dummy
, &dummy
,
2110 (unsigned int *) &dummy
);
2114 /* This is used for debugging, to turn off note_mouse_highlight. */
2115 static int disable_mouse_highlight
;
2117 /* Take proper action when the mouse has moved to position X, Y on frame F
2118 as regards highlighting characters that have mouse-face properties.
2119 Also dehighlighting chars where the mouse was before. */
2122 note_mouse_highlight (f
, x
, y
)
2125 int row
, column
, portion
;
2126 XRectangle new_glyph
;
2130 if (disable_mouse_highlight
)
2133 mouse_face_mouse_x
= x
;
2134 mouse_face_mouse_y
= y
;
2135 mouse_face_mouse_frame
= f
;
2137 if (mouse_face_defer
)
2142 mouse_face_deferred_gc
= 1;
2146 /* Find out which glyph the mouse is on. */
2147 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2148 &new_glyph
, x_mouse_grabbed
);
2150 /* Which window is that in? */
2151 window
= window_from_coordinates (f
, column
, row
, &portion
);
2152 w
= XWINDOW (window
);
2154 /* If we were displaying active text in another window, clear that. */
2155 if (! EQ (window
, mouse_face_window
))
2156 clear_mouse_face ();
2158 /* Are we in a window whose display is up to date?
2159 And verify the buffer's text has not changed. */
2160 if (WINDOWP (window
) && portion
== 0
2161 && EQ (w
->window_end_valid
, w
->buffer
)
2162 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
2164 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2167 /* Find which buffer position the mouse corresponds to. */
2168 for (i
= column
; i
>= 0; i
--)
2172 /* Is it outside the displayed active region (if any)? */
2174 && ! (EQ (window
, mouse_face_window
)
2175 && pos
>= mouse_face_beg
&& pos
< mouse_face_end
))
2177 Lisp_Object mouse_face
, overlay
, position
;
2178 Lisp_Object
*overlay_vec
;
2179 int len
, noverlays
, ignor1
;
2180 struct buffer
*obuf
;
2183 /* If we get an out-of-range value, return now; avoid an error. */
2184 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2187 /* Make the window's buffer temporarily current for
2188 overlays_at and compute_char_face. */
2189 obuf
= current_buffer
;
2190 current_buffer
= XBUFFER (w
->buffer
);
2196 /* Yes. Clear the display of the old active region, if any. */
2197 clear_mouse_face ();
2199 /* Is this char mouse-active? */
2200 XSET (position
, Lisp_Int
, pos
);
2203 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2205 /* Put all the overlays we want in a vector in overlay_vec.
2206 Store the length in len. */
2207 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
, &ignor1
);
2208 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2210 /* Find the highest priority overlay that has a mouse-face prop. */
2212 for (i
= 0; i
< noverlays
; i
++)
2214 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2215 if (!NILP (mouse_face
))
2217 overlay
= overlay_vec
[i
];
2222 /* If no overlay applies, get a text property. */
2224 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2226 /* Handle the overlay case. */
2227 if (! NILP (overlay
))
2229 /* Find the range of text around this char that
2230 should be active. */
2231 Lisp_Object before
, after
;
2234 before
= Foverlay_start (overlay
);
2235 after
= Foverlay_end (overlay
);
2236 /* Record this as the current active region. */
2237 mouse_face_beg
= XFASTINT (before
);
2238 mouse_face_end
= XFASTINT (after
);
2239 mouse_face_window
= window
;
2240 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
2241 &ignore
, pos
+ 1, 1);
2243 /* Display it as active. */
2244 show_mouse_face (1);
2246 /* Handle the text property case. */
2247 else if (! NILP (mouse_face
))
2249 /* Find the range of text around this char that
2250 should be active. */
2251 Lisp_Object before
, after
, beginning
, end
;
2254 beginning
= Fmarker_position (w
->start
);
2255 XSET (end
, Lisp_Int
,
2256 (BUF_Z (XBUFFER (w
->buffer
))
2257 - XFASTINT (w
->window_end_pos
)));
2259 = Fprevious_single_property_change (make_number (pos
+ 1),
2261 w
->buffer
, beginning
);
2263 = Fnext_single_property_change (position
, Qmouse_face
,
2265 /* Record this as the current active region. */
2266 mouse_face_beg
= XFASTINT (before
);
2267 mouse_face_end
= XFASTINT (after
);
2268 mouse_face_window
= window
;
2270 = compute_char_face (f
, w
, pos
, 0, 0,
2271 &ignore
, pos
+ 1, 1);
2273 /* Display it as active. */
2274 show_mouse_face (1);
2278 current_buffer
= obuf
;
2281 clear_mouse_face ();
2285 /* Find the row and column of position POS in window WINDOW.
2286 Store them in *COLUMNP and *ROWP.
2287 This assumes display in WINDOW is up to date.
2288 If POS is above start of WINDOW, return coords
2289 of start of first screen line.
2290 If POS is after end of WINDOW, return coords of end of last screen line. */
2293 fast_find_position (window
, pos
, columnp
, rowp
)
2296 int *columnp
, *rowp
;
2298 struct window
*w
= XWINDOW (window
);
2299 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2304 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2305 int width
= window_internal_width (w
);
2313 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2314 if (linestart
> pos
)
2320 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2322 for (i
= 0; i
< width
; i
++)
2324 if (charstarts
[left
+ i
] == pos
)
2327 *columnp
= i
+ left
;
2330 else if (charstarts
[left
+ i
] > pos
)
2339 /* Display the active region described by mouse_face_*
2340 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2343 show_mouse_face (hl
)
2346 int begcol
, begrow
, endcol
, endrow
;
2347 struct window
*w
= XWINDOW (mouse_face_window
);
2348 int width
= window_internal_width (w
);
2349 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2351 int curs_x
= f
->phys_cursor_x
;
2352 int curs_y
= f
->phys_cursor_y
;
2355 fast_find_position (mouse_face_window
, mouse_face_beg
,
2357 fast_find_position (mouse_face_window
, mouse_face_end
,
2360 for (i
= begrow
; i
<= endrow
; i
++)
2362 int column
= (i
== begrow
? begcol
: w
->left
);
2363 int endcolumn
= (i
== endrow
? endcol
: w
->left
+ width
);
2364 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
] - w
->left
);
2366 /* If the cursor's in the text we are about to rewrite,
2367 turn the cursor off. */
2369 && (curs_x
>= begrow
- 1 || curs_x
<= endrow
))
2371 x_display_cursor (f
, 0);
2376 CHAR_TO_PIXEL_COL (f
, column
),
2377 CHAR_TO_PIXEL_ROW (f
, i
),
2378 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2380 /* Highlight with mouse face if hl > 0. */
2384 /* If we turned the cursor off, turn it back on. */
2386 x_display_cursor (f
, 1);
2388 /* Change the mouse cursor according to the value of HL. */
2390 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->cross_cursor
);
2392 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->text_cursor
);
2395 /* Clear out the mouse-highlighted active region.
2396 Redraw it unhighlighted first. */
2401 if (! NILP (mouse_face_window
))
2402 show_mouse_face (0);
2404 mouse_face_beg
= -1;
2405 mouse_face_end
= -1;
2406 mouse_face_window
= Qnil
;
2409 static struct scroll_bar
*x_window_to_scroll_bar ();
2410 static void x_scroll_bar_report_motion ();
2412 /* Return the current position of the mouse.
2414 If the mouse movement started in a scroll bar, set *f, *bar_window,
2415 and *part to the frame, window, and scroll bar part that the mouse
2416 is over. Set *x and *y to the portion and whole of the mouse's
2417 position on the scroll bar.
2419 If the mouse movement started elsewhere, set *f to the frame the
2420 mouse is on, *bar_window to nil, and *x and *y to the character cell
2423 Set *time to the server timestamp for the time at which the mouse
2424 was at this position.
2426 Don't store anything if we don't have a valid set of values to report.
2428 This clears the mouse_moved flag, so we can wait for the next mouse
2429 movement. This also calls XQueryPointer, which will cause the
2430 server to give us another MotionNotify when the mouse moves
2434 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
2436 Lisp_Object
*bar_window
;
2437 enum scroll_bar_part
*part
;
2439 unsigned long *time
;
2445 if (! NILP (last_mouse_scroll_bar
))
2446 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
2452 Window dummy_window
;
2456 last_mouse_scroll_bar
= Qnil
;
2458 /* Figure out which root window we're on. */
2459 XQueryPointer (x_current_display
,
2460 DefaultRootWindow (x_current_display
),
2462 /* The root window which contains the pointer. */
2465 /* Trash which we can't trust if the pointer is on
2466 a different screen. */
2469 /* The position on that root window. */
2472 /* More trash we can't trust. */
2475 /* Modifier keys and pointer buttons, about which
2477 (unsigned int *) &dummy
);
2479 /* Now we have a position on the root; find the innermost window
2480 containing the pointer. */
2484 int parent_x
, parent_y
;
2488 if (x_mouse_grabbed
)
2490 /* If mouse was grabbed on a frame, give coords for that frame
2491 even if the mouse is now outside it. */
2492 XTranslateCoordinates (x_current_display
,
2494 /* From-window, to-window. */
2495 root
, FRAME_X_WINDOW (last_mouse_frame
),
2497 /* From-position, to-position. */
2498 root_x
, root_y
, &win_x
, &win_y
,
2502 f1
= last_mouse_frame
;
2508 XTranslateCoordinates (x_current_display
,
2510 /* From-window, to-window. */
2513 /* From-position, to-position. */
2514 root_x
, root_y
, &win_x
, &win_y
,
2527 /* Now we know that:
2528 win is the innermost window containing the pointer
2529 (XTC says it has no child containing the pointer),
2530 win_x and win_y are the pointer's position in it
2531 (XTC did this the last time through), and
2532 parent_x and parent_y are the pointer's position in win's parent.
2533 (They are what win_x and win_y were when win was child.
2534 If win is the root window, it has no parent, and
2535 parent_{x,y} are invalid, but that's okay, because we'll
2536 never use them in that case.) */
2538 /* Is win one of our frames? */
2539 f1
= x_any_window_to_frame (win
);
2542 /* If not, is it one of our scroll bars? */
2545 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2549 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2557 int ignore1
, ignore2
;
2559 /* Ok, we found a frame. Store all the values. */
2561 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2562 &last_mouse_glyph
, x_mouse_grabbed
);
2567 XSET (*x
, Lisp_Int
, win_x
);
2568 XSET (*y
, Lisp_Int
, win_y
);
2569 *time
= last_mouse_movement_time
;
2577 #else /* ! defined (HAVE_X11) */
2578 #define XEvent XKeyPressedEvent
2579 #endif /* ! defined (HAVE_X11) */
2581 /* Scroll bar support. */
2583 /* Given an X window ID, find the struct scroll_bar which manages it.
2584 This can be called in GC, so we have to make sure to strip off mark
2586 static struct scroll_bar
*
2587 x_window_to_scroll_bar (window_id
)
2590 Lisp_Object tail
, frame
;
2592 for (tail
= Vframe_list
;
2593 XGCTYPE (tail
) == Lisp_Cons
;
2594 tail
= XCONS (tail
)->cdr
)
2596 Lisp_Object frame
, bar
, condemned
;
2598 frame
= XCONS (tail
)->car
;
2599 /* All elements of Vframe_list should be frames. */
2600 if (XGCTYPE (frame
) != Lisp_Frame
)
2603 /* Scan this frame's scroll bar list for a scroll bar with the
2605 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2606 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2607 /* This trick allows us to search both the ordinary and
2608 condemned scroll bar lists with one loop. */
2609 ! GC_NILP (bar
) || (bar
= condemned
,
2612 bar
= XSCROLL_BAR (bar
)->next
)
2613 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2614 return XSCROLL_BAR (bar
);
2620 /* Open a new X window to serve as a scroll bar, and return the
2621 scroll bar vector for it. */
2622 static struct scroll_bar
*
2623 x_scroll_bar_create (window
, top
, left
, width
, height
)
2624 struct window
*window
;
2625 int top
, left
, width
, height
;
2627 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2628 struct scroll_bar
*bar
=
2629 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2634 XSetWindowAttributes a
;
2636 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2637 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2638 | ButtonMotionMask
| PointerMotionHintMask
2640 a
.cursor
= x_vertical_scroll_bar_cursor
;
2642 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2647 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2648 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2649 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2650 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2651 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2652 sb_widget
= XtCreateManagedWidget ("box",
2654 frame
->display
.x
->edit_widget
, al
, ac
);
2655 SET_SCROLL_BAR_X_WINDOW
2656 (bar
, sb_widget
->core
.window
);
2658 SET_SCROLL_BAR_X_WINDOW
2660 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2662 /* Position and size of scroll bar. */
2663 left
, top
, width
, height
,
2665 /* Border width, depth, class, and visual. */
2666 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2672 XSET (bar
->window
, Lisp_Window
, window
);
2673 XSET (bar
->top
, Lisp_Int
, top
);
2674 XSET (bar
->left
, Lisp_Int
, left
);
2675 XSET (bar
->width
, Lisp_Int
, width
);
2676 XSET (bar
->height
, Lisp_Int
, height
);
2677 XSET (bar
->start
, Lisp_Int
, 0);
2678 XSET (bar
->end
, Lisp_Int
, 0);
2679 bar
->dragging
= Qnil
;
2681 /* Add bar to its frame's list of scroll bars. */
2682 bar
->next
= FRAME_SCROLL_BARS (frame
);
2684 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2685 if (! NILP (bar
->next
))
2686 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2688 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2695 /* Draw BAR's handle in the proper position.
2696 If the handle is already drawn from START to END, don't bother
2697 redrawing it, unless REBUILD is non-zero; in that case, always
2698 redraw it. (REBUILD is handy for drawing the handle after expose
2701 Normally, we want to constrain the start and end of the handle to
2702 fit inside its rectangle, but if the user is dragging the scroll bar
2703 handle, we want to let them drag it down all the way, so that the
2704 bar's top is as far down as it goes; otherwise, there's no way to
2705 move to the very end of the buffer. */
2707 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2708 struct scroll_bar
*bar
;
2712 int dragging
= ! NILP (bar
->dragging
);
2713 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2714 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2716 /* If the display is already accurate, do nothing. */
2718 && start
== XINT (bar
->start
)
2719 && end
== XINT (bar
->end
))
2725 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2726 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2727 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2729 /* Make sure the values are reasonable, and try to preserve
2730 the distance between start and end. */
2732 int length
= end
- start
;
2736 else if (start
> top_range
)
2738 end
= start
+ length
;
2742 else if (end
> top_range
&& ! dragging
)
2746 /* Store the adjusted setting in the scroll bar. */
2747 XSET (bar
->start
, Lisp_Int
, start
);
2748 XSET (bar
->end
, Lisp_Int
, end
);
2750 /* Clip the end position, just for display. */
2751 if (end
> top_range
)
2754 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2755 below top positions, to make sure the handle is always at least
2756 that many pixels tall. */
2757 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2759 /* Draw the empty space above the handle. Note that we can't clear
2760 zero-height areas; that means "clear to end of window." */
2762 XClearArea (x_current_display
, w
,
2764 /* x, y, width, height, and exposures. */
2765 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2766 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2767 inside_width
, start
,
2770 /* Draw the handle itself. */
2771 XFillRectangle (x_current_display
, w
, gc
,
2773 /* x, y, width, height */
2774 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2775 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2776 inside_width
, end
- start
);
2779 /* Draw the empty space below the handle. Note that we can't
2780 clear zero-height areas; that means "clear to end of window." */
2781 if (end
< inside_height
)
2782 XClearArea (x_current_display
, w
,
2784 /* x, y, width, height, and exposures. */
2785 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2786 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2787 inside_width
, inside_height
- end
,
2795 /* Move a scroll bar around on the screen, to accommodate changing
2796 window configurations. */
2798 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2799 struct scroll_bar
*bar
;
2800 int top
, left
, width
, height
;
2806 unsigned int mask
= 0;
2813 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2814 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2815 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2816 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2819 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2823 XSET (bar
->left
, Lisp_Int
, left
);
2824 XSET (bar
->top
, Lisp_Int
, top
);
2825 XSET (bar
->width
, Lisp_Int
, width
);
2826 XSET (bar
->height
, Lisp_Int
, height
);
2831 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2834 x_scroll_bar_remove (bar
)
2835 struct scroll_bar
*bar
;
2837 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2841 /* Destroy the window. */
2842 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2844 /* Disassociate this scroll bar from its window. */
2845 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2850 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2851 that we are displaying PORTION characters out of a total of WHOLE
2852 characters, starting at POSITION. If WINDOW has no scroll bar,
2855 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2856 struct window
*window
;
2857 int portion
, whole
, position
;
2859 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2860 int top
= XINT (window
->top
);
2861 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2862 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2864 /* Where should this scroll bar be, pixelwise? */
2865 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2866 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2867 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2868 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2870 struct scroll_bar
*bar
;
2872 /* Does the scroll bar exist yet? */
2873 if (NILP (window
->vertical_scroll_bar
))
2874 bar
= x_scroll_bar_create (window
,
2875 pixel_top
, pixel_left
,
2876 pixel_width
, pixel_height
);
2879 /* It may just need to be moved and resized. */
2880 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2881 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2884 /* Set the scroll bar's current state, unless we're currently being
2886 if (NILP (bar
->dragging
))
2889 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2892 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2895 int start
= ((double) position
* top_range
) / whole
;
2896 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2898 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2902 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2906 /* The following three hooks are used when we're doing a thorough
2907 redisplay of the frame. We don't explicitly know which scroll bars
2908 are going to be deleted, because keeping track of when windows go
2909 away is a real pain - "Can you say set-window-configuration, boys
2910 and girls?" Instead, we just assert at the beginning of redisplay
2911 that *all* scroll bars are to be removed, and then save a scroll bar
2912 from the fiery pit when we actually redisplay its window. */
2914 /* Arrange for all scroll bars on FRAME to be removed at the next call
2915 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2916 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2918 XTcondemn_scroll_bars (frame
)
2921 /* The condemned list should be empty at this point; if it's not,
2922 then the rest of Emacs isn't using the condemn/redeem/judge
2923 protocol correctly. */
2924 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2927 /* Move them all to the "condemned" list. */
2928 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2929 FRAME_SCROLL_BARS (frame
) = Qnil
;
2932 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2933 Note that WINDOW isn't necessarily condemned at all. */
2935 XTredeem_scroll_bar (window
)
2936 struct window
*window
;
2938 struct scroll_bar
*bar
;
2940 /* We can't redeem this window's scroll bar if it doesn't have one. */
2941 if (NILP (window
->vertical_scroll_bar
))
2944 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2946 /* Unlink it from the condemned list. */
2948 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2950 if (NILP (bar
->prev
))
2952 /* If the prev pointer is nil, it must be the first in one of
2954 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2955 /* It's not condemned. Everything's fine. */
2957 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2958 window
->vertical_scroll_bar
))
2959 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2961 /* If its prev pointer is nil, it must be at the front of
2962 one or the other! */
2966 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2968 if (! NILP (bar
->next
))
2969 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2971 bar
->next
= FRAME_SCROLL_BARS (f
);
2973 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2974 if (! NILP (bar
->next
))
2975 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2979 /* Remove all scroll bars on FRAME that haven't been saved since the
2980 last call to `*condemn_scroll_bars_hook'. */
2982 XTjudge_scroll_bars (f
)
2985 Lisp_Object bar
, next
;
2987 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2989 /* Clear out the condemned list now so we won't try to process any
2990 more events on the hapless scroll bars. */
2991 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2993 for (; ! NILP (bar
); bar
= next
)
2995 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2997 x_scroll_bar_remove (b
);
3000 b
->next
= b
->prev
= Qnil
;
3003 /* Now there should be no references to the condemned scroll bars,
3004 and they should get garbage-collected. */
3008 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3010 This may be called from a signal handler, so we have to ignore GC
3013 x_scroll_bar_expose (bar
, event
)
3014 struct scroll_bar
*bar
;
3017 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3018 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
3022 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3024 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3025 XDrawRectangle (x_current_display
, w
, gc
,
3027 /* x, y, width, height */
3028 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
3033 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3034 is set to something other than no_event, it is enqueued.
3036 This may be called from a signal handler, so we have to ignore GC
3039 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3040 struct scroll_bar
*bar
;
3042 struct input_event
*emacs_event
;
3044 if (XGCTYPE (bar
->window
) != Lisp_Window
)
3047 emacs_event
->kind
= scroll_bar_click
;
3048 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3049 emacs_event
->modifiers
=
3050 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
3051 | (event
->type
== ButtonRelease
3054 emacs_event
->frame_or_window
= bar
->window
;
3055 emacs_event
->timestamp
= event
->xbutton
.time
;
3057 int internal_height
=
3058 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3060 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3061 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3064 if (y
> top_range
) y
= top_range
;
3066 if (y
< XINT (bar
->start
))
3067 emacs_event
->part
= scroll_bar_above_handle
;
3068 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3069 emacs_event
->part
= scroll_bar_handle
;
3071 emacs_event
->part
= scroll_bar_below_handle
;
3073 /* Just because the user has clicked on the handle doesn't mean
3074 they want to drag it. Lisp code needs to be able to decide
3075 whether or not we're dragging. */
3077 /* If the user has just clicked on the handle, record where they're
3079 if (event
->type
== ButtonPress
3080 && emacs_event
->part
== scroll_bar_handle
)
3081 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
3084 /* If the user has released the handle, set it to its final position. */
3085 if (event
->type
== ButtonRelease
3086 && ! NILP (bar
->dragging
))
3088 int new_start
= y
- XINT (bar
->dragging
);
3089 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3091 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3092 bar
->dragging
= Qnil
;
3095 /* Same deal here as the other #if 0. */
3097 /* Clicks on the handle are always reported as occurring at the top of
3099 if (emacs_event
->part
== scroll_bar_handle
)
3100 emacs_event
->x
= bar
->start
;
3102 XSET (emacs_event
->x
, Lisp_Int
, y
);
3104 XSET (emacs_event
->x
, Lisp_Int
, y
);
3107 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
3111 /* Handle some mouse motion while someone is dragging the scroll bar.
3113 This may be called from a signal handler, so we have to ignore GC
3116 x_scroll_bar_note_movement (bar
, event
)
3117 struct scroll_bar
*bar
;
3120 last_mouse_movement_time
= event
->xmotion
.time
;
3123 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
3125 /* If we're dragging the bar, display it. */
3126 if (! GC_NILP (bar
->dragging
))
3128 /* Where should the handle be now? */
3129 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3131 if (new_start
!= XINT (bar
->start
))
3133 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3135 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3139 /* Call XQueryPointer so we'll get an event the next time the mouse
3140 moves and we can see *still* on the same position. */
3144 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
3145 (Window
*) &dummy
, (Window
*) &dummy
,
3146 &dummy
, &dummy
, &dummy
, &dummy
,
3147 (unsigned int *) &dummy
);
3151 /* Return information to the user about the current position of the mouse
3152 on the scroll bar. */
3154 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
3156 Lisp_Object
*bar_window
;
3157 enum scroll_bar_part
*part
;
3159 unsigned long *time
;
3161 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3163 Window dummy_window
;
3165 unsigned int dummy_mask
;
3169 /* Get the mouse's position relative to the scroll bar window, and
3171 if (! XQueryPointer (x_current_display
,
3172 SCROLL_BAR_X_WINDOW (bar
),
3174 /* Root, child, root x and root y. */
3175 &dummy_window
, &dummy_window
,
3176 &dummy_coord
, &dummy_coord
,
3178 /* Position relative to scroll bar. */
3181 /* Mouse buttons and modifier keys. */
3187 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
3189 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3191 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3193 if (! NILP (bar
->dragging
))
3194 win_y
-= XINT (bar
->dragging
);
3198 if (win_y
> top_range
)
3201 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3202 *bar_window
= bar
->window
;
3204 if (! NILP (bar
->dragging
))
3205 *part
= scroll_bar_handle
;
3206 else if (win_y
< XINT (bar
->start
))
3207 *part
= scroll_bar_above_handle
;
3208 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3209 *part
= scroll_bar_handle
;
3211 *part
= scroll_bar_below_handle
;
3213 XSET (*x
, Lisp_Int
, win_y
);
3214 XSET (*y
, Lisp_Int
, top_range
);
3217 last_mouse_scroll_bar
= Qnil
;
3220 *time
= last_mouse_movement_time
;
3226 /* The screen has been cleared so we may have changed foreground or
3227 background colors, and the scroll bars may need to be redrawn.
3228 Clear out the scroll bars, and ask for expose events, so we can
3231 x_scroll_bar_clear (f
)
3236 for (bar
= FRAME_SCROLL_BARS (f
);
3237 XTYPE (bar
) == Lisp_Vector
;
3238 bar
= XSCROLL_BAR (bar
)->next
)
3239 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3243 /* This processes Expose events from the menubar specific X event
3244 loop in menubar.c. This allows to redisplay the frame if necessary
3245 when handling menubar or popup items. */
3248 process_expose_from_menu (event
)
3255 f
= x_window_to_frame (event
.xexpose
.window
);
3258 if (f
->async_visible
== 0)
3260 f
->async_visible
= 1;
3261 f
->async_iconified
= 0;
3262 SET_FRAME_GARBAGED (f
);
3266 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3267 event
.xexpose
.x
, event
.xexpose
.y
,
3268 event
.xexpose
.width
, event
.xexpose
.height
);
3273 struct scroll_bar
*bar
3274 = x_window_to_scroll_bar (event
.xexpose
.window
);
3277 x_scroll_bar_expose (bar
, &event
);
3284 /* The main X event-reading loop - XTread_socket. */
3286 /* Timestamp of enter window event. This is only used by XTread_socket,
3287 but we have to put it out here, since static variables within functions
3288 sometimes don't work. */
3289 static Time enter_timestamp
;
3291 /* This holds the state XLookupString needs to implement dead keys
3292 and other tricks known as "compose processing". _X Window System_
3293 says that a portable program can't use this, but Stephen Gildea assures
3294 me that letting the compiler initialize it to zeros will work okay.
3296 This must be defined outside of XTread_socket, for the same reasons
3297 given for enter_timestamp, above. */
3298 static XComposeStatus compose_status
;
3300 /* Communication with window managers. */
3301 Atom Xatom_wm_protocols
;
3303 /* Kinds of protocol things we may receive. */
3304 Atom Xatom_wm_take_focus
;
3305 Atom Xatom_wm_save_yourself
;
3306 Atom Xatom_wm_delete_window
;
3308 /* Other WM communication */
3309 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3310 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3312 /* Window manager communication. */
3313 Atom Xatom_wm_change_state
;
3315 /* EditRes protocol */
3316 Atom Xatom_editres_name
;
3318 /* Record the last 100 characters stored
3319 to help debug the loss-of-chars-during-GC problem. */
3321 short temp_buffer
[100];
3323 /* Read events coming from the X server.
3324 This routine is called by the SIGIO handler.
3325 We return as soon as there are no more events to be read.
3327 Events representing keys are stored in buffer BUFP,
3328 which can hold up to NUMCHARS characters.
3329 We return the number of characters stored into the buffer,
3330 thus pretending to be `read'.
3332 WAITP is nonzero if we should block until input arrives.
3333 EXPECTED is nonzero if the caller knows input is available. */
3336 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3338 register struct input_event
*bufp
;
3339 register int numchars
;
3346 int items_pending
; /* How many items are in the X queue. */
3349 int event_found
= 0;
3353 if (interrupt_input_blocked
)
3355 interrupt_input_pending
= 1;
3359 interrupt_input_pending
= 0;
3363 abort (); /* Don't think this happens. */
3366 /* If available, Xlib uses FIOSNBIO to make the socket
3367 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3368 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3369 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3370 fcntl (fileno (stdin
), F_SETFL
, 0);
3371 #endif /* ! defined (FIOSNBIO) */
3375 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3377 extern int read_alarm_should_throw
;
3378 read_alarm_should_throw
= 1;
3379 XPeekEvent (XDISPLAY
&event
);
3380 read_alarm_should_throw
= 0;
3382 #endif /* HAVE_SELECT */
3385 while (XStuffPending () != 0)
3387 XNextEvent (XDISPLAY
&event
);
3395 if (event
.xclient
.message_type
== Xatom_wm_protocols
3396 && event
.xclient
.format
== 32)
3398 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3400 f
= x_window_to_frame (event
.xclient
.window
);
3401 #if 0 /* x_focus_on_frame is a no-op anyway. */
3403 x_focus_on_frame (f
);
3406 /* Since we set WM_TAKE_FOCUS, we must call
3407 XSetInputFocus explicitly. */
3408 XSetInputFocus (event
.xclient
.display
,
3409 event
.xclient
.window
,
3410 RevertToPointerRoot
,
3411 event
.xclient
.data
.l
[1]);
3412 /* Not certain about handling scroll bars here */
3414 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3416 /* Save state modify the WM_COMMAND property to
3417 something which can reinstate us. This notifies
3418 the session manager, who's looking for such a
3419 PropertyNotify. Can restart processing when
3420 a keyboard or mouse event arrives. */
3425 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3427 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3434 bufp
->kind
= delete_window_event
;
3435 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3443 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3446 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3449 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3451 new_x
= event
.xclient
.data
.s
[0];
3452 new_y
= event
.xclient
.data
.s
[1];
3456 f
->display
.x
->left_pos
= new_x
;
3457 f
->display
.x
->top_pos
= new_y
;
3460 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3461 else if (event
.xclient
.message_type
== Xatom_editres_name
)
3463 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3464 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3466 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3470 case SelectionNotify
:
3471 #ifdef USE_X_TOOLKIT
3472 if (! x_window_to_frame (event
.xselection
.requestor
))
3474 #endif /* not USE_X_TOOLKIT */
3475 x_handle_selection_notify (&event
);
3478 case SelectionClear
: /* Someone has grabbed ownership. */
3479 #ifdef USE_X_TOOLKIT
3480 if (! x_window_to_frame (event
.xselectionclear
.window
))
3482 #endif /* USE_X_TOOLKIT */
3484 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3489 bufp
->kind
= selection_clear_event
;
3490 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3491 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3492 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3500 case SelectionRequest
: /* Someone wants our selection. */
3501 #ifdef USE_X_TOOLKIT
3502 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3504 #endif /* USE_X_TOOLKIT */
3506 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3511 bufp
->kind
= selection_request_event
;
3512 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3513 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3514 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3515 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3516 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3517 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3525 case PropertyNotify
:
3526 #ifdef USE_X_TOOLKIT
3527 if (!x_any_window_to_frame (event
.xproperty
.window
))
3529 #endif /* not USE_X_TOOLKIT */
3530 x_handle_property_notify (&event
);
3533 case ReparentNotify
:
3534 f
= x_window_to_frame (event
.xreparent
.window
);
3536 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3540 f
= x_window_to_frame (event
.xexpose
.window
);
3543 if (f
->async_visible
== 0)
3545 f
->async_visible
= 1;
3546 f
->async_iconified
= 0;
3547 SET_FRAME_GARBAGED (f
);
3550 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3551 event
.xexpose
.x
, event
.xexpose
.y
,
3552 event
.xexpose
.width
, event
.xexpose
.height
);
3556 struct scroll_bar
*bar
3557 = x_window_to_scroll_bar (event
.xexpose
.window
);
3560 x_scroll_bar_expose (bar
, &event
);
3561 #ifdef USE_X_TOOLKIT
3564 #endif /* USE_X_TOOLKIT */
3568 case GraphicsExpose
: /* This occurs when an XCopyArea's
3569 source area was obscured or not
3571 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3575 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3576 event
.xgraphicsexpose
.width
,
3577 event
.xgraphicsexpose
.height
);
3579 #ifdef USE_X_TOOLKIT
3582 #endif /* USE_X_TOOLKIT */
3585 case NoExpose
: /* This occurs when an XCopyArea's
3586 source area was completely
3589 #else /* ! defined (HAVE_X11) */
3591 if (event
.subwindow
!= 0)
3592 break; /* duplicate event */
3593 f
= x_window_to_frame (event
.window
);
3594 if (event
.window
== f
->display
.x
->icon_desc
)
3597 f
->async_iconified
= 1;
3599 if (event
.window
== FRAME_X_WINDOW (f
))
3601 /* Say must check all windows' needs_exposure flags. */
3602 expose_all_windows
= 1;
3603 f
->display
.x
->needs_exposure
= 1;
3604 f
->async_visible
= 1;
3609 if (event
.subwindow
!= 0)
3610 break; /* duplicate event */
3611 f
= x_window_to_frame (event
.window
);
3612 if (event
.window
== f
->display
.x
->icon_desc
)
3617 /* If window already needs full redraw, ignore this rectangle. */
3618 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3620 /* Put the event on the queue of rectangles to redraw. */
3621 if (enqueue_event (&event
, &x_expose_queue
))
3622 /* If it is full, we can't record the rectangle,
3623 so redraw this entire window. */
3625 /* Say must check all windows' needs_exposure flags. */
3626 expose_all_windows
= 1;
3627 f
->display
.x
->needs_exposure
= 1;
3632 /* This should happen only when we are expecting it,
3633 in x_read_exposes. */
3635 #endif /* ! defined (HAVE_X11) */
3639 f
= x_any_window_to_frame (event
.xunmap
.window
);
3640 if (f
) /* F may no longer exist if
3641 the frame was deleted. */
3643 /* While a frame is unmapped, display generation is
3644 disabled; you don't want to spend time updating a
3645 display that won't ever be seen. */
3646 f
->async_visible
= 0;
3647 /* We can't distinguish, from the event, whether the window
3648 has become iconified or invisible. So assume, if it
3649 was previously visible, than now it is iconified.
3650 We depend on x_make_frame_invisible to mark it iconified. */
3651 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3652 f
->async_iconified
= 1;
3654 #ifdef USE_X_TOOLKIT
3656 #endif /* USE_X_TOOLKIT */
3660 /* We use x_top_window_to_frame because map events can come
3661 for subwindows and they don't mean that the frame is visible. */
3662 f
= x_top_window_to_frame (event
.xmap
.window
);
3665 f
->async_visible
= 1;
3666 f
->async_iconified
= 0;
3668 /* wait_reading_process_input will notice this and update
3669 the frame's display structures. */
3670 SET_FRAME_GARBAGED (f
);
3672 #ifdef USE_X_TOOLKIT
3674 #endif /* USE_X_TOOLKIT */
3677 /* Turn off processing if we become fully obscured. */
3678 case VisibilityNotify
:
3681 #else /* ! defined (HAVE_X11) */
3683 f
= x_window_to_frame (event
.window
);
3684 if (event
.window
== f
->display
.x
->icon_desc
)
3685 f
->async_iconified
= 0;
3686 if (event
.window
== FRAME_X_WINDOW (f
))
3687 f
->async_visible
= 0;
3689 #endif /* ! defined (HAVE_X11) */
3693 f
= x_any_window_to_frame (event
.xkey
.window
);
3697 KeySym keysym
, orig_keysym
;
3698 /* al%imercury@uunet.uu.net says that making this 81 instead of
3699 80 fixed a bug whereby meta chars made his Emacs hang. */
3700 unsigned char copy_buffer
[81];
3704 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3705 modifiers
= event
.xkey
.state
;
3707 /* This will have to go some day... */
3709 /* make_lispy_event turns chars into control chars.
3710 Don't do it here because XLookupString is too eager. */
3711 event
.xkey
.state
&= ~ControlMask
;
3713 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3716 /* Strip off the vendor-specific keysym bit, and take a shot
3717 at recognizing the codes. HP servers have extra keysyms
3718 that fit into the MiscFunctionKey category. */
3719 orig_keysym
= keysym
;
3724 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3725 || keysym
== XK_Delete
3726 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3727 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3729 /* This recognizes the "extended function keys".
3730 It seems there's no cleaner way.
3731 Test IsModifierKey to avoid handling mode_switch
3733 || ((unsigned) (keysym
) >= XK_Select
3734 && (unsigned)(keysym
) < XK_KP_Space
)
3736 #ifdef XK_dead_circumflex
3737 || orig_keysym
== XK_dead_circumflex
3739 #ifdef XK_dead_grave
3740 || orig_keysym
== XK_dead_grave
3742 #ifdef XK_dead_tilde
3743 || orig_keysym
== XK_dead_tilde
3745 #ifdef XK_dead_diaeresis
3746 || orig_keysym
== XK_dead_diaeresis
3748 #ifdef XK_dead_macron
3749 || orig_keysym
== XK_dead_macron
3751 #ifdef XK_dead_degree
3752 || orig_keysym
== XK_dead_degree
3754 #ifdef XK_dead_acute
3755 || orig_keysym
== XK_dead_acute
3757 #ifdef XK_dead_cedilla
3758 || orig_keysym
== XK_dead_cedilla
3760 #ifdef XK_dead_breve
3761 || orig_keysym
== XK_dead_breve
3763 #ifdef XK_dead_ogonek
3764 || orig_keysym
== XK_dead_ogonek
3766 #ifdef XK_dead_caron
3767 || orig_keysym
== XK_dead_caron
3769 #ifdef XK_dead_doubleacute
3770 || orig_keysym
== XK_dead_doubleacute
3772 #ifdef XK_dead_abovedot
3773 || orig_keysym
== XK_dead_abovedot
3775 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3776 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3777 || x_is_vendor_fkey (orig_keysym
))
3778 && ! (IsModifierKey (orig_keysym
)
3780 #ifdef XK_Mode_switch
3781 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3784 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3786 #endif /* not HAVE_X11R5 */
3789 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3791 temp_buffer
[temp_index
++] = keysym
;
3792 bufp
->kind
= non_ascii_keystroke
;
3793 bufp
->code
= keysym
;
3794 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3795 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3796 bufp
->timestamp
= event
.xkey
.time
;
3801 else if (numchars
> nbytes
)
3805 for (i
= 0; i
< nbytes
; i
++)
3807 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3809 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3810 bufp
->kind
= ascii_keystroke
;
3811 bufp
->code
= copy_buffer
[i
];
3812 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3813 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3814 bufp
->timestamp
= event
.xkey
.time
;
3828 #else /* ! defined (HAVE_X11) */
3831 register char *where_mapping
;
3833 f
= x_window_to_frame (event
.window
);
3834 /* Ignore keys typed on icon windows. */
3835 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3837 where_mapping
= XLookupMapping (&event
, &nbytes
);
3838 /* Nasty fix for arrow keys */
3839 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3841 switch (event
.detail
& 0xff)
3843 case KC_CURSOR_LEFT
:
3844 where_mapping
= "\002";
3846 case KC_CURSOR_RIGHT
:
3847 where_mapping
= "\006";
3850 where_mapping
= "\020";
3852 case KC_CURSOR_DOWN
:
3853 where_mapping
= "\016";
3858 if (numchars
- nbytes
> 0)
3862 for (i
= 0; i
< nbytes
; i
++)
3864 bufp
->kind
= ascii_keystroke
;
3865 bufp
->code
= where_mapping
[i
];
3866 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3867 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3875 #endif /* ! defined (HAVE_X11) */
3879 /* Here's a possible interpretation of the whole
3880 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3881 FocusIn event, you have to get a FocusOut event before you
3882 relinquish the focus. If you haven't received a FocusIn event,
3883 then a mere LeaveNotify is enough to free you. */
3886 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3888 if (event
.xcrossing
.focus
) /* Entered Window */
3890 /* Avoid nasty pop/raise loops. */
3891 if (f
&& (!(f
->auto_raise
)
3893 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3895 x_new_focus_frame (f
);
3896 enter_timestamp
= event
.xcrossing
.time
;
3899 else if (f
== x_focus_frame
)
3900 x_new_focus_frame (0);
3901 #ifdef USE_X_TOOLKIT
3903 #endif /* USE_X_TOOLKIT */
3907 f
= x_any_window_to_frame (event
.xfocus
.window
);
3908 if (event
.xfocus
.detail
!= NotifyPointer
)
3909 x_focus_event_frame
= f
;
3911 x_new_focus_frame (f
);
3912 #ifdef USE_X_TOOLKIT
3914 #endif /* USE_X_TOOLKIT */
3919 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3921 if (f
== mouse_face_mouse_frame
)
3922 /* If we move outside the frame,
3923 then we're certainly no longer on any text in the frame. */
3924 clear_mouse_face ();
3926 if (event
.xcrossing
.focus
)
3928 if (! x_focus_event_frame
)
3929 x_new_focus_frame (0);
3931 x_new_focus_frame (f
);
3935 if (f
== x_focus_event_frame
)
3936 x_focus_event_frame
= 0;
3937 if (f
== x_focus_frame
)
3938 x_new_focus_frame (0);
3940 #ifdef USE_X_TOOLKIT
3942 #endif /* USE_X_TOOLKIT */
3946 f
= x_any_window_to_frame (event
.xfocus
.window
);
3947 if (event
.xfocus
.detail
!= NotifyPointer
3948 && f
== x_focus_event_frame
)
3949 x_focus_event_frame
= 0;
3950 if (f
&& f
== x_focus_frame
)
3951 x_new_focus_frame (0);
3952 #ifdef USE_X_TOOLKIT
3954 #endif /* USE_X_TOOLKIT */
3957 #else /* ! defined (HAVE_X11) */
3960 if ((event
.detail
& 0xFF) == 1)
3961 break; /* Coming from our own subwindow */
3962 if (event
.subwindow
!= 0)
3963 break; /* Entering our own subwindow. */
3966 f
= x_window_to_frame (event
.window
);
3969 x_new_focus_frame (f
);
3974 if ((event
.detail
& 0xFF) == 1)
3975 break; /* Entering our own subwindow */
3976 if (event
.subwindow
!= 0)
3977 break; /* Leaving our own subwindow. */
3980 if (x_focus_frame
== 0
3981 && x_input_frame
!= 0
3982 && x_input_frame
== x_window_to_frame (event
.window
)
3983 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3988 frame_unhighlight (f
);
3991 #endif /* ! defined (HAVE_X11) */
3996 if (x_mouse_grabbed
)
3997 f
= last_mouse_frame
;
3999 f
= x_window_to_frame (event
.xmotion
.window
);
4001 note_mouse_movement (f
, &event
.xmotion
);
4004 struct scroll_bar
*bar
4005 = x_window_to_scroll_bar (event
.xmotion
.window
);
4008 x_scroll_bar_note_movement (bar
, &event
);
4010 /* If we move outside the frame,
4011 then we're certainly no longer on any text in the frame. */
4012 clear_mouse_face ();
4015 #ifdef USE_X_TOOLKIT
4017 #endif /* USE_X_TOOLKIT */
4020 case ConfigureNotify
:
4021 f
= x_any_window_to_frame (event
.xconfigure
.window
);
4022 #ifdef USE_X_TOOLKIT
4024 && ! event
.xconfigure
.send_event
4025 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
4030 /* Find the position of the outside upper-left corner of
4031 the window, in the root coordinate system. Don't
4032 refer to the parent window here; we may be processing
4033 this event after the window manager has changed our
4034 parent, but before we have reached the ReparentNotify. */
4035 XTranslateCoordinates (x_current_display
,
4037 /* From-window, to-window. */
4038 XtWindow (f
->display
.x
->widget
),
4041 /* From-position, to-position. */
4042 -event
.xconfigure
.border_width
,
4043 -event
.xconfigure
.border_width
,
4048 event
.xconfigure
.x
= win_x
;
4049 event
.xconfigure
.y
= win_y
;
4051 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4052 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4053 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4054 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4057 #else /* not USE_X_TOOLKIT */
4060 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4061 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4063 /* Even if the number of character rows and columns has
4064 not changed, the font size may have changed, so we need
4065 to check the pixel dimensions as well. */
4066 if (columns
!= f
->width
4067 || rows
!= f
->height
4068 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
4069 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
4071 change_frame_size (f
, rows
, columns
, 0, 1);
4072 SET_FRAME_GARBAGED (f
);
4075 if (! event
.xconfigure
.send_event
)
4080 /* Find the position of the outside upper-left corner of
4081 the window, in the root coordinate system. Don't
4082 refer to the parent window here; we may be processing
4083 this event after the window manager has changed our
4084 parent, but before we have reached the ReparentNotify. */
4085 XTranslateCoordinates (x_current_display
,
4087 /* From-window, to-window. */
4088 f
->display
.x
->window_desc
,
4091 /* From-position, to-position. */
4092 -event
.xconfigure
.border_width
,
4093 -event
.xconfigure
.border_width
,
4098 event
.xconfigure
.x
= win_x
;
4099 event
.xconfigure
.y
= win_y
;
4102 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
4103 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
4104 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
4105 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
4107 #endif /* not USE_X_TOOLKIT */
4113 /* If we decide we want to generate an event to be seen
4114 by the rest of Emacs, we put it here. */
4115 struct input_event emacs_event
;
4116 emacs_event
.kind
= no_event
;
4118 f
= x_window_to_frame (event
.xbutton
.window
);
4121 if (!x_focus_frame
|| (f
== x_focus_frame
))
4122 construct_mouse_click (&emacs_event
, &event
, f
);
4126 struct scroll_bar
*bar
=
4127 x_window_to_scroll_bar (event
.xbutton
.window
);
4130 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4131 #ifdef USE_X_TOOLKIT
4134 f
= x_any_window_to_frame (event
.xbutton
.window
);
4135 if (f
&& event
.type
== ButtonPress
)
4136 construct_menu_click (&emacs_event
,
4139 #endif /* USE_X_TOOLKIT */
4142 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4144 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4150 #ifdef USE_X_TOOLKIT
4152 #endif /* USE_X_TOOLKIT */
4156 #else /* ! defined (HAVE_X11) */
4158 case ButtonReleased
:
4159 f
= x_window_to_frame (event
.window
);
4162 if (event
.window
== f
->display
.x
->icon_desc
)
4164 x_make_frame_visible (f
);
4166 if (warp_mouse_on_deiconify
)
4167 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
4170 if (event
.window
== FRAME_X_WINDOW (f
))
4176 enqueue_event (&event
, &x_mouse_queue
);
4179 bufp
->kind
= ascii_keystroke
;
4180 bufp
->code
= 'X' & 037; /* C-x */
4181 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4182 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4185 bufp
->kind
= ascii_keystroke
;
4186 bufp
->code
= 0; /* C-@ */
4187 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
4188 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
4195 #endif /* ! defined (HAVE_X11) */
4199 case CirculateNotify
:
4201 case CirculateRequest
:
4204 #endif /* ! defined (HAVE_X11) */
4207 /* Someone has changed the keyboard mapping - update the
4209 switch (event
.xmapping
.request
)
4211 case MappingModifier
:
4212 x_find_modifier_meanings ();
4213 /* This is meant to fall through. */
4214 case MappingKeyboard
:
4215 XRefreshKeyboardMapping (&event
.xmapping
);
4217 #ifdef USE_X_TOOLKIT
4219 #endif /* USE_X_TOOLKIT */
4223 #ifdef USE_X_TOOLKIT
4226 XtDispatchEvent (&event
);
4228 #endif /* USE_X_TOOLKIT */
4235 /* On some systems, an X bug causes Emacs to get no more events
4236 when the window is destroyed. Detect that. (1994.) */
4237 XNoOp (x_current_display
);
4238 #endif /* X_IO_BUG */
4240 #if 0 /* This fails for serial-line connections to the X server,
4241 because the characters arrive one by one, and a partial
4242 command makes select return but gives nothing to read.
4243 We'll have to hope that the bug that this tried to fix
4244 in 1988 has been fixed in Xlib or the X server. */
4246 if (expected
&& ! event_found
)
4248 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4249 there is an EOF condition; in other words, that X has died.
4250 Act as if there had been a hangup. */
4251 int fd
= ConnectionNumber (x_current_display
);
4252 SELECT_TYPE mask
, junk1
, junk2
;
4257 EMACS_SET_SECS_USECS (timeout
, 0, 0);
4260 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
4261 && !XStuffPending ())
4262 kill (getpid (), SIGHUP
);
4264 #endif /* HAVE_SELECT */
4268 if (updating_frame
== 0)
4269 x_do_pending_expose ();
4272 /* If the focus was just given to an autoraising frame,
4275 if (pending_autoraise_frame
)
4277 x_raise_frame (pending_autoraise_frame
);
4278 pending_autoraise_frame
= 0;
4287 /* Read and process only Expose events
4288 until we get an ExposeCopy event; then return.
4289 This is used in insert/delete line.
4290 We assume input is already blocked. */
4296 XKeyPressedEvent event
;
4300 /* while there are more events*/
4301 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
4305 if (event
.subwindow
!= 0)
4306 break; /* duplicate event */
4307 f
= x_window_to_frame (event
.window
);
4308 if (event
.window
== f
->display
.x
->icon_desc
)
4313 if (event
.window
== FRAME_X_WINDOW (f
))
4315 expose_all_windows
= 1;
4316 f
->display
.x
->needs_exposure
= 1;
4322 if (event
.subwindow
!= 0)
4323 break; /* duplicate event */
4324 f
= x_window_to_frame (event
.window
);
4325 if (event
.window
== f
->display
.x
->icon_desc
)
4330 /* If window already needs full redraw, ignore this rectangle. */
4331 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
4333 /* Put the event on the queue of rectangles to redraw. */
4334 if (enqueue_event (&event
, &x_expose_queue
))
4335 /* If it is full, we can't record the rectangle,
4336 so redraw this entire window. */
4338 /* Say must check all windows' needs_exposure flags. */
4339 expose_all_windows
= 1;
4340 f
->display
.x
->needs_exposure
= 1;
4349 #endif /* HAVE_X11 */
4352 /* Drawing the cursor. */
4355 /* Draw a hollow box cursor. Don't change the inside of the box. */
4361 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
4362 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
4363 int width
= FONT_WIDTH (f
->display
.x
->font
);
4364 int height
= f
->display
.x
->line_height
;
4367 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4368 f
->display
.x
->cursor_gc
,
4369 left
, top
, width
- 1, height
- 1);
4370 #else /* ! defined (HAVE_X11) */
4371 XPixSet (FRAME_X_WINDOW (f
),
4372 left
, top
, width
, 1,
4373 f
->display
.x
->cursor_pixel
);
4375 XPixSet (FRAME_X_WINDOW (f
),
4376 left
, top
, 1, height
,
4377 f
->display
.x
->cursor_pixel
);
4379 XPixSet (FRAME_X_WINDOW (f
),
4380 left
+width
-1, top
, 1, height
,
4381 f
->display
.x
->cursor_pixel
);
4383 XPixSet (FRAME_X_WINDOW (f
),
4384 left
, top
+height
-1, width
, 1,
4385 f
->display
.x
->cursor_pixel
);
4386 #endif /* ! defined (HAVE_X11) */
4389 /* Clear the cursor of frame F to background color,
4390 and mark the cursor as not shown.
4391 This is used when the text where the cursor is
4392 is about to be rewritten. */
4400 if (! FRAME_VISIBLE_P (f
)
4401 || f
->phys_cursor_x
< 0)
4405 x_display_cursor (f
, 0);
4406 #else /* ! defined (HAVE_X11) */
4407 XPixSet (FRAME_X_WINDOW (f
),
4408 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4409 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4410 FONT_WIDTH (f
->display
.x
->font
), f
->display
.x
->line_height
,
4411 f
->display
.x
->background_pixel
);
4412 #endif /* ! defined (HAVE_X11) */
4413 f
->phys_cursor_x
= -1;
4416 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4417 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4421 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4428 CHAR_TO_PIXEL_COL (f
, column
),
4429 CHAR_TO_PIXEL_ROW (f
, row
),
4430 &glyph
, 1, highlight
, 0);
4434 x_display_bar_cursor (f
, on
)
4438 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4440 /* This is pointless on invisible frames, and dangerous on garbaged
4441 frames; in the latter case, the frame may be in the midst of
4442 changing its size, and curs_x and curs_y may be off the frame. */
4443 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4446 if (! on
&& f
->phys_cursor_x
< 0)
4449 /* If we're not updating, then we want to use the current frame's
4450 cursor position, not our local idea of where the cursor ought to be. */
4451 if (f
!= updating_frame
)
4453 curs_x
= FRAME_CURSOR_X (f
);
4454 curs_y
= FRAME_CURSOR_Y (f
);
4457 /* If there is anything wrong with the current cursor state, remove it. */
4458 if (f
->phys_cursor_x
>= 0
4460 || f
->phys_cursor_x
!= curs_x
4461 || f
->phys_cursor_y
!= curs_y
4462 || f
->display
.x
->current_cursor
!= bar_cursor
))
4464 /* Erase the cursor by redrawing the character underneath it. */
4465 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4466 f
->phys_cursor_glyph
,
4467 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4468 f
->phys_cursor_x
= -1;
4471 /* If we now need a cursor in the new place or in the new form, do it so. */
4473 && (f
->phys_cursor_x
< 0
4474 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4476 f
->phys_cursor_glyph
4477 = ((current_glyphs
->enable
[curs_y
]
4478 && curs_x
< current_glyphs
->used
[curs_y
])
4479 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4481 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4482 f
->display
.x
->cursor_gc
,
4483 CHAR_TO_PIXEL_COL (f
, curs_x
),
4484 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4485 1, f
->display
.x
->line_height
);
4487 f
->phys_cursor_x
= curs_x
;
4488 f
->phys_cursor_y
= curs_y
;
4490 f
->display
.x
->current_cursor
= bar_cursor
;
4493 if (updating_frame
!= f
)
4498 /* Turn the displayed cursor of frame F on or off according to ON.
4499 If ON is nonzero, where to put the cursor is specified
4500 by F->cursor_x and F->cursor_y. */
4503 x_display_box_cursor (f
, on
)
4507 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4509 /* This is pointless on invisible frames, and dangerous on garbaged
4510 frames; in the latter case, the frame may be in the midst of
4511 changing its size, and curs_x and curs_y may be off the frame. */
4512 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4515 /* If cursor is off and we want it off, return quickly. */
4516 if (!on
&& f
->phys_cursor_x
< 0)
4519 /* If we're not updating, then we want to use the current frame's
4520 cursor position, not our local idea of where the cursor ought to be. */
4521 if (f
!= updating_frame
)
4523 curs_x
= FRAME_CURSOR_X (f
);
4524 curs_y
= FRAME_CURSOR_Y (f
);
4527 /* If cursor is currently being shown and we don't want it to be
4528 or it is in the wrong place,
4529 or we want a hollow box and it's not so, (pout!)
4531 if (f
->phys_cursor_x
>= 0
4533 || f
->phys_cursor_x
!= curs_x
4534 || f
->phys_cursor_y
!= curs_y
4535 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4536 && (f
!= x_highlight_frame
))))
4538 /* If the font is not as tall as a whole line,
4539 we must explicitly clear the line's whole height. */
4540 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4541 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
4542 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4543 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4544 FONT_WIDTH (f
->display
.x
->font
),
4545 f
->display
.x
->line_height
, False
);
4546 /* Erase the cursor by redrawing the character underneath it. */
4547 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4548 f
->phys_cursor_glyph
,
4549 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4550 f
->phys_cursor_x
= -1;
4553 /* If we want to show a cursor,
4554 or we want a box cursor and it's not so,
4555 write it in the right place. */
4557 && (f
->phys_cursor_x
< 0
4558 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4559 && f
== x_highlight_frame
)))
4561 f
->phys_cursor_glyph
4562 = ((current_glyphs
->enable
[curs_y
]
4563 && curs_x
< current_glyphs
->used
[curs_y
])
4564 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4566 if (f
!= x_highlight_frame
)
4569 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4573 x_draw_single_glyph (f
, curs_y
, curs_x
,
4574 f
->phys_cursor_glyph
, 2);
4575 f
->display
.x
->current_cursor
= filled_box_cursor
;
4578 f
->phys_cursor_x
= curs_x
;
4579 f
->phys_cursor_y
= curs_y
;
4582 if (updating_frame
!= f
)
4586 x_display_cursor (f
, on
)
4592 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4593 x_display_box_cursor (f
, on
);
4594 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4595 x_display_bar_cursor (f
, on
);
4597 /* Those are the only two we have implemented! */
4605 /* Refresh bitmap kitchen sink icon for frame F
4606 when we get an expose event for it. */
4612 /* Normally, the window manager handles this function. */
4613 #else /* ! defined (HAVE_X11) */
4616 if (f
->display
.x
->icon_bitmap_flag
)
4617 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
4618 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
4619 icon_bitmap
, GXcopy
, AllPlanes
);
4622 extern struct frame
*selected_frame
;
4623 struct Lisp_String
*str
;
4624 unsigned char *string
;
4627 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
4629 if (f
->display
.x
->icon_label
!= string
)
4631 f
->display
.x
->icon_label
= string
;
4632 XChangeWindow (f
->display
.x
->icon_desc
,
4633 XQueryWidth (string
, icon_font_info
->id
) + 10,
4634 icon_font_info
->height
+ 10);
4637 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4638 str
->size
, icon_font_info
->id
,
4639 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4642 #endif /* ! defined (HAVE_X11) */
4645 /* Make the x-window of frame F use the gnu icon bitmap. */
4654 if (FRAME_X_WINDOW (f
) == 0)
4660 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4661 gnu_bits
, gnu_width
, gnu_height
);
4662 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4663 f
->display
.x
->icon_bitmap_flag
= 1;
4664 #else /* ! defined (HAVE_X11) */
4665 if (f
->display
.x
->icon_desc
)
4667 XClearIconWindow (FRAME_X_WINDOW (f
));
4668 XDestroyWindow (f
->display
.x
->icon_desc
);
4671 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4672 0, 0, sink_width
, sink_height
,
4673 2, WhitePixmap
, (Pixmap
) NULL
);
4675 if (icon_window
== 0)
4678 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4679 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4681 f
->display
.x
->icon_desc
= icon_window
;
4682 f
->display
.x
->icon_bitmap_flag
= 1;
4684 if (icon_bitmap
== 0)
4686 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4687 #endif /* ! defined (HAVE_X11) */
4693 /* Make the x-window of frame F use a rectangle with text. */
4696 x_text_icon (f
, icon_name
)
4704 char *X_DefaultValue
;
4708 #define WhitePixel 1
4709 #endif /* WhitePixel */
4712 #define BlackPixel 0
4713 #endif /* BlackPixel */
4714 #endif /* HAVE_X11 */
4716 if (FRAME_X_WINDOW (f
) == 0)
4721 f
->display
.x
->icon_label
= icon_name
;
4723 if (! f
->display
.x
->icon_label
)
4724 f
->display
.x
->icon_label
= " *emacs* ";
4727 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4728 (char *) f
->display
.x
->icon_label
);
4731 f
->display
.x
->icon_bitmap_flag
= 0;
4732 x_wm_set_icon_pixmap (f
, 0);
4733 #else /* ! defined (HAVE_X11) */
4734 if (icon_font_info
== 0)
4736 = XGetFont (XGetDefault (XDISPLAY
4737 (char *) XSTRING (Vinvocation_name
)->data
,
4740 if (f
->display
.x
->icon_desc
)
4742 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4743 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4747 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4749 if (! f
->display
.x
->icon_label
)
4750 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4752 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4753 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4754 f
->display
.x
->left_pos
,
4755 f
->display
.x
->top_pos
,
4756 width
+ 10, icon_font_info
->height
+ 10,
4757 2, BlackPixmap
, WhitePixmap
);
4759 if (icon_window
== 0)
4762 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4763 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4765 f
->display
.x
->icon_desc
= icon_window
;
4766 f
->display
.x
->icon_bitmap_flag
= 0;
4767 f
->display
.x
->icon_label
= 0;
4768 #endif /* ! defined (HAVE_X11) */
4773 /* Handling X errors. */
4775 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4776 X server's connection, or an error reported via the X protocol. */
4779 x_connection_closed ()
4784 shut_down_emacs (0, 1, Qnil
);
4789 /* An X error handler which prints an error message and then kills
4790 Emacs. This is what's normally installed as Xlib's handler for
4793 x_error_quitter (display
, error
)
4799 /* Note that there is no real way portable across R3/R4 to get the
4800 original error handler. */
4802 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4803 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4804 buf
, error
->request_code
);
4807 /* While we're testing Emacs 19, we'll just dump core whenever we
4808 get an X error, so we can figure out why it happened. */
4812 x_connection_closed ();
4815 /* A handler for X IO errors which prints an error message and then
4816 kills Emacs. This is what is always installed as Xlib's handler
4819 x_io_error_quitter (display
)
4822 fprintf (stderr
, "Connection to X server %s lost.\n",
4823 XDisplayName (DisplayString (display
)));
4826 /* While we're testing Emacs 19, we'll just dump core whenever we
4827 get an X error, so we can figure out why it happened. */
4831 x_connection_closed ();
4834 /* A buffer for storing X error messages. */
4835 static char *x_caught_error_message
;
4836 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4838 /* An X error handler which stores the error message in
4839 x_caught_error_message. This is what's installed when
4840 x_catch_errors is in effect. */
4842 x_error_catcher (display
, error
)
4846 XGetErrorText (display
, error
->error_code
,
4847 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4851 /* Begin trapping X errors.
4853 After calling this function, X protocol errors no longer cause
4854 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4856 Calling x_check_errors signals an Emacs error if an X error has
4857 occurred since the last call to x_catch_errors or x_check_errors.
4859 Calling x_uncatch_errors resumes the normal error handling. */
4861 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4866 /* Make sure any errors from previous requests have been dealt with. */
4867 XSync (x_current_display
, False
);
4869 /* Set up the error buffer. */
4870 x_caught_error_message
4871 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4872 x_caught_error_message
[0] = '\0';
4874 /* Install our little error handler. */
4875 XHandleError (x_error_catcher
);
4878 /* If any X protocol errors have arrived since the last call to
4879 x_catch_errors or x_check_errors, signal an Emacs error using
4880 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4883 x_check_errors (format
)
4886 /* Make sure to catch any errors incurred so far. */
4887 XSync (x_current_display
, False
);
4889 if (x_caught_error_message
[0])
4891 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4893 sprintf (buf
, format
, x_caught_error_message
);
4894 x_uncatch_errors ();
4899 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4904 /* Make sure to catch any errors incurred so far. */
4905 XSync (x_current_display
, False
);
4907 return x_caught_error_message
[0] != 0;
4910 /* Stop catching X protocol errors and let them make Emacs die. */
4915 xfree (x_caught_error_message
);
4916 x_caught_error_message
= 0;
4917 XHandleError (x_error_quitter
);
4921 static unsigned int x_wire_count
;
4924 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4929 /* Changing the font of the frame. */
4931 /* Set the font of the x-window specified by frame F
4932 to the font named NEWNAME. This is safe to use
4933 even before F has an actual x-window. */
4943 /* A table of all the fonts we have already loaded. */
4944 static struct font_info
*x_font_table
;
4946 /* The current capacity of x_font_table. */
4947 static int x_font_table_size
;
4949 /* The number of fonts actually stored in x_font_table.
4950 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4951 0 <= n_fonts <= x_font_table_size. */
4955 x_new_font (f
, fontname
)
4957 register char *fontname
;
4960 int n_matching_fonts
;
4961 XFontStruct
*font_info
;
4964 /* Get a list of all the fonts that match this name. Once we
4965 have a list of matching fonts, we compare them against the fonts
4966 we already have by comparing font ids. */
4967 font_names
= (char **) XListFonts (x_current_display
, fontname
,
4968 1024, &n_matching_fonts
);
4969 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4970 find any matches; font_names == 0 is the only clue. */
4972 n_matching_fonts
= 0;
4974 /* Don't just give up if n_matching_fonts is 0.
4975 Apparently there's a bug on Suns: XListFontsWithInfo can
4976 fail to find a font, but XLoadQueryFont may still find it. */
4978 /* See if we've already loaded a matching font. */
4979 already_loaded
= -1;
4980 if (n_matching_fonts
!= 0)
4984 for (i
= 0; i
< n_fonts
; i
++)
4985 for (j
= 0; j
< n_matching_fonts
; j
++)
4986 if (!strcmp (x_font_table
[i
].name
, font_names
[j
]))
4989 fontname
= font_names
[j
];
4995 /* If we have, just return it from the table. */
4996 if (already_loaded
>= 0)
4997 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
4999 /* Otherwise, load the font and add it to the table. */
5005 /* Try to find a character-cell font in the list. */
5007 /* A laudable goal, but this isn't how to do it. */
5008 for (i
= 0; i
< n_matching_fonts
; i
++)
5009 if (! font_info
[i
].per_char
)
5015 /* See comment above. */
5016 if (n_matching_fonts
!= 0)
5017 fontname
= font_names
[i
];
5019 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
5022 /* Free the information from XListFonts. */
5023 if (n_matching_fonts
)
5024 XFreeFontNames (font_names
);
5028 /* Do we need to create the table? */
5029 if (x_font_table_size
== 0)
5031 x_font_table_size
= 16;
5033 = (struct font_info
*) xmalloc (x_font_table_size
5034 * sizeof (x_font_table
[0]));
5036 /* Do we need to grow the table? */
5037 else if (n_fonts
>= x_font_table_size
)
5039 x_font_table_size
*= 2;
5041 = (struct font_info
*) xrealloc (x_font_table
,
5043 * sizeof (x_font_table
[0])));
5046 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
5047 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
5048 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
5051 /* Now make the frame display the given font. */
5052 if (FRAME_X_WINDOW (f
) != 0)
5054 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
5055 f
->display
.x
->font
->fid
);
5056 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
5057 f
->display
.x
->font
->fid
);
5058 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
5059 f
->display
.x
->font
->fid
);
5061 frame_update_line_height (f
);
5062 x_set_window_size (f
, 0, f
->width
, f
->height
);
5065 /* If we are setting a new frame's font for the first time,
5066 there are no faces yet, so this font's height is the line height. */
5067 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
5070 Lisp_Object lispy_name
;
5072 lispy_name
= build_string (fontname
);
5074 /* Free the information from XListFonts. The data
5075 we actually retain comes from XLoadQueryFont. */
5076 XFreeFontNames (font_names
);
5081 #else /* ! defined (HAVE_X11) */
5082 x_new_font (f
, newname
)
5084 register char *newname
;
5089 temp
= XGetFont (newname
);
5090 if (temp
== (FONT_TYPE
*) 0)
5093 if (f
->display
.x
->font
)
5094 XLoseFont (f
->display
.x
->font
);
5096 f
->display
.x
->font
= temp
;
5098 if (FRAME_X_WINDOW (f
) != 0)
5099 x_set_window_size (f
, 0, f
->width
, f
->height
);
5103 #endif /* ! defined (HAVE_X11) */
5105 x_calc_absolute_position (f
)
5110 int win_x
= 0, win_y
= 0;
5112 /* Find the position of the outside upper-left corner of
5113 the inner window, with respect to the outer window. */
5114 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
5117 XTranslateCoordinates (x_current_display
,
5119 /* From-window, to-window. */
5120 f
->display
.x
->window_desc
,
5121 f
->display
.x
->parent_desc
,
5123 /* From-position, to-position. */
5124 0, 0, &win_x
, &win_y
,
5131 /* Treat negative positions as relative to the leftmost bottommost
5132 position that fits on the screen. */
5133 if (f
->display
.x
->left_pos
< 0)
5134 f
->display
.x
->left_pos
= (x_screen_width
5135 - 2 * f
->display
.x
->border_width
- win_x
5137 + f
->display
.x
->left_pos
);
5139 if (f
->display
.x
->top_pos
< 0)
5140 f
->display
.x
->top_pos
= (x_screen_height
5141 - 2 * f
->display
.x
->border_width
- win_y
5143 + f
->display
.x
->top_pos
);
5145 #else /* ! defined (HAVE_X11) */
5146 WINDOWINFO_TYPE parentinfo
;
5148 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
5150 if (f
->display
.x
->left_pos
< 0)
5151 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
5152 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
5154 if (f
->display
.x
->top_pos
< 0)
5155 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
5156 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
5157 #endif /* ! defined (HAVE_X11) */
5160 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5162 register int xoff
, yoff
;
5165 f
->display
.x
->top_pos
= yoff
;
5166 f
->display
.x
->left_pos
= xoff
;
5167 x_calc_absolute_position (f
);
5170 #ifdef USE_X_TOOLKIT
5171 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
5172 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5173 #else /* not USE_X_TOOLKIT */
5174 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
5175 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
5176 #endif /* not USE_X_TOOLKIT */
5179 f
->display
.x
->win_gravity
= NorthWestGravity
;
5181 x_wm_set_size_hint (f
, 0, 1);
5182 #endif /* ! defined (HAVE_X11) */
5186 /* Call this to change the size of frame F's x-window.
5187 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5188 for this size change and subsequent size changes.
5189 Otherwise we leave the window gravity unchanged. */
5191 x_set_window_size (f
, change_gravity
, cols
, rows
)
5196 int pixelwidth
, pixelheight
;
5199 #ifdef USE_X_TOOLKIT
5201 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
5204 #else /* not USE_X_TOOLKIT */
5208 check_frame_size (f
, &rows
, &cols
);
5209 f
->display
.x
->vertical_scroll_bar_extra
5210 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5211 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
5213 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5214 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5217 x_wm_set_size_hint (f
, 0, change_gravity
);
5218 #endif /* ! defined (HAVE_X11) */
5219 XSync (x_current_display
, False
);
5220 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
5222 /* Now, strictly speaking, we can't be sure that this is accurate,
5223 but the window manager will get around to dealing with the size
5224 change request eventually, and we'll hear how it went when the
5225 ConfigureNotify event gets here.
5227 We could just not bother storing any of this information here,
5228 and let the ConfigureNotify event set everything up, but that
5229 might be kind of confusing to the lisp code, since size changes
5230 wouldn't be reported in the frame parameters until some random
5231 point in the future when the ConfigureNotify event arrives. */
5232 change_frame_size (f
, rows
, cols
, 0, 0);
5233 PIXEL_WIDTH (f
) = pixelwidth
;
5234 PIXEL_HEIGHT (f
) = pixelheight
;
5236 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5237 receive in the ConfigureNotify event; if we get what we asked
5238 for, then the event won't cause the screen to become garbaged, so
5239 we have to make sure to do it here. */
5240 SET_FRAME_GARBAGED (f
);
5244 #endif /* not USE_X_TOOLKIT */
5248 x_set_resize_hint (f
)
5251 XSetResizeHint (FRAME_X_WINDOW (f
),
5252 2 * f
->display
.x
->internal_border_width
,
5253 2 * f
->display
.x
->internal_border_width
,
5254 FONT_WIDTH (f
->display
.x
->font
),
5255 f
->display
.x
->line_height
);
5257 #endif /* HAVE_X11 */
5259 /* Mouse warping, focus shifting, raising and lowering. */
5261 x_set_mouse_position (f
, x
, y
)
5267 #if 0 /* Let the user ask for this if he wants it. */
5271 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
5272 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
5274 if (pix_x
< 0) pix_x
= 0;
5275 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5277 if (pix_y
< 0) pix_y
= 0;
5278 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5282 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
5287 x_focus_on_frame (f
)
5290 #if 0 /* This proves to be unpleasant. */
5294 /* I don't think that the ICCCM allows programs to do things like this
5295 without the interaction of the window manager. Whatever you end up
5296 doing with this code, do it to x_unfocus_frame too. */
5297 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
5298 RevertToPointerRoot
, CurrentTime
);
5306 /* Look at the remarks in x_focus_on_frame. */
5307 if (x_focus_frame
== f
)
5308 XSetInputFocus (x_current_display
, PointerRoot
,
5309 RevertToPointerRoot
, CurrentTime
);
5313 #endif /* ! defined (HAVE_X11) */
5315 /* Raise frame F. */
5320 if (f
->async_visible
)
5323 #ifdef USE_X_TOOLKIT
5324 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5325 #else /* not USE_X_TOOLKIT */
5326 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5327 #endif /* not USE_X_TOOLKIT */
5333 /* Lower frame F. */
5338 if (f
->async_visible
)
5341 #ifdef USE_X_TOOLKIT
5342 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
5343 #else /* not USE_X_TOOLKIT */
5344 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5345 #endif /* not USE_X_TOOLKIT */
5352 XTframe_raise_lower (f
, raise
)
5363 /* Change from withdrawn state to mapped state. */
5365 x_make_frame_visible (f
)
5372 if (! FRAME_VISIBLE_P (f
))
5375 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5377 if (! EQ (Vx_no_window_manager
, Qt
))
5378 x_wm_set_window_state (f
, NormalState
);
5379 #ifdef USE_X_TOOLKIT
5380 XtPopup (f
->display
.x
->widget
, XtGrabNone
);
5381 #else /* not USE_X_TOOLKIT */
5382 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5383 #endif /* not USE_X_TOOLKIT */
5384 #if 0 /* This seems to bring back scroll bars in the wrong places
5385 if the window configuration has changed. They seem
5386 to come back ok without this. */
5387 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5388 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5390 #else /* ! defined (HAVE_X11) */
5391 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5392 if (f
->display
.x
->icon_desc
!= 0)
5393 XUnmapWindow (f
->display
.x
->icon_desc
);
5395 /* Handled by the MapNotify event for X11 */
5396 f
->async_visible
= 1;
5397 f
->async_iconified
= 0;
5399 /* NOTE: this may cause problems for the first frame. */
5401 #endif /* ! defined (HAVE_X11) */
5409 /* Change from mapped state to withdrawn state. */
5411 x_make_frame_invisible (f
)
5416 /* Don't keep the highlight on an invisible frame. */
5417 if (x_highlight_frame
== f
)
5418 x_highlight_frame
= 0;
5420 #if 0/* This might add unreliability; I don't trust it -- rms. */
5421 if (! f
->async_visible
&& ! f
->async_iconified
)
5429 #ifdef USE_X_TOOLKIT
5430 XtPopdown (f
->display
.x
->widget
);
5431 #else /* not USE_X_TOOLKIT */
5432 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
5433 DefaultScreen (x_current_display
)))
5435 UNBLOCK_INPUT_RESIGNAL
;
5436 error ("can't notify window manager of window withdrawal");
5438 #endif /* not USE_X_TOOLKIT */
5440 #else /* ! defined (HAVE_X11R4) */
5443 /* Tell the window manager what we're going to do. */
5444 if (! EQ (Vx_no_window_manager
, Qt
))
5448 unmap
.xunmap
.type
= UnmapNotify
;
5449 #ifdef USE_X_TOOLKIT
5450 unmap
.xunmap
.window
= XtWindow (f
->display
.x
->widget
);
5451 #else /* not USE_X_TOOLKIT */
5452 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
5453 #endif /* not USE_X_TOOLKIT */
5454 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5455 unmap
.xunmap
.from_configure
= False
;
5456 if (! XSendEvent (x_current_display
,
5457 DefaultRootWindow (x_current_display
),
5459 SubstructureRedirectMask
|SubstructureNotifyMask
,
5462 UNBLOCK_INPUT_RESIGNAL
;
5463 error ("can't notify window manager of withdrawal");
5467 /* Unmap the window ourselves. Cheeky! */
5468 #ifdef USE_X_TOOLKIT
5469 XUnmapWindow (x_current_display
, XtWindow (f
->display
.x
->widget
));
5470 #else /* not USE_X_TOOLKIT */
5471 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
5472 #endif /* not USE_X_TOOLKIT */
5473 #else /* ! defined (HAVE_X11) */
5475 XUnmapWindow (FRAME_X_WINDOW (f
));
5476 if (f
->display
.x
->icon_desc
!= 0)
5477 XUnmapWindow (f
->display
.x
->icon_desc
);
5479 #endif /* ! defined (HAVE_X11) */
5480 #endif /* ! defined (HAVE_X11R4) */
5482 /* We can't distinguish this from iconification
5483 just by the event that we get from the server.
5484 So we can't win using the usual strategy of letting
5485 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5486 and synchronize with the server to make sure we agree. */
5488 FRAME_ICONIFIED_P (f
) = 0;
5489 f
->async_visible
= 0;
5490 f
->async_iconified
= 0;
5497 /* Change window state from mapped to iconified. */
5505 /* Don't keep the highlight on an invisible frame. */
5506 if (x_highlight_frame
== f
)
5507 x_highlight_frame
= 0;
5509 if (f
->async_iconified
)
5512 #ifdef USE_X_TOOLKIT
5514 result
= XIconifyWindow (x_current_display
,
5515 XtWindow (f
->display
.x
->widget
),
5516 DefaultScreen (x_current_display
));
5520 error ("Can't notify window manager of iconification.");
5522 f
->async_iconified
= 1;
5527 #else /* not USE_X_TOOLKIT */
5532 /* Since we don't know which revision of X we're running, we'll use both
5533 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5535 /* X11R4: send a ClientMessage to the window manager using the
5536 WM_CHANGE_STATE type. */
5540 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5541 message
.xclient
.type
= ClientMessage
;
5542 message
.xclient
.message_type
= Xatom_wm_change_state
;
5543 message
.xclient
.format
= 32;
5544 message
.xclient
.data
.l
[0] = IconicState
;
5546 if (! XSendEvent (x_current_display
,
5547 DefaultRootWindow (x_current_display
),
5549 SubstructureRedirectMask
| SubstructureNotifyMask
,
5552 UNBLOCK_INPUT_RESIGNAL
;
5553 error ("Can't notify window manager of iconification.");
5557 /* X11R3: set the initial_state field of the window manager hints to
5559 x_wm_set_window_state (f
, IconicState
);
5561 if (!FRAME_VISIBLE_P (f
))
5563 /* If the frame was withdrawn, before, we must map it. */
5564 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5565 #if 0 /* We don't have subwindows in the icon. */
5566 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5567 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5571 f
->async_iconified
= 1;
5572 #else /* ! defined (HAVE_X11) */
5573 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5575 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
5576 if (f
->display
.x
->icon_desc
!= 0)
5578 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
5581 #endif /* ! defined (HAVE_X11) */
5585 #endif /* not USE_X_TOOLKIT */
5588 /* Destroy the X window of frame F. */
5590 x_destroy_window (f
)
5595 if (f
->display
.x
->icon_desc
!= 0)
5596 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5597 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5598 #ifdef USE_X_TOOLKIT
5599 XtDestroyWidget (f
->display
.x
->widget
);
5600 free_frame_menubar (f
);
5601 #endif /* USE_X_TOOLKIT */
5603 free_frame_faces (f
);
5606 xfree (f
->display
.x
);
5608 if (f
== x_focus_frame
)
5610 if (f
== x_highlight_frame
)
5611 x_highlight_frame
= 0;
5613 if (f
== mouse_face_mouse_frame
)
5615 mouse_face_beg
= -1;
5616 mouse_face_end
= -1;
5617 mouse_face_window
= Qnil
;
5623 /* Manage event queues for X10. */
5627 /* Manage event queues.
5629 This code is only used by the X10 support.
5631 We cannot leave events in the X queue and get them when we are ready
5632 because X does not provide a subroutine to get only a certain kind
5633 of event but not block if there are no queued events of that kind.
5635 Therefore, we must examine events as they come in and copy events
5636 of certain kinds into our private queues.
5638 All ExposeRegion events are put in x_expose_queue.
5639 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5642 /* Write the event *P_XREP into the event queue *QUEUE.
5643 If the queue is full, do nothing, but return nonzero. */
5646 enqueue_event (p_xrep
, queue
)
5647 register XEvent
*p_xrep
;
5648 register struct event_queue
*queue
;
5650 int newindex
= queue
->windex
+ 1;
5651 if (newindex
== EVENT_BUFFER_SIZE
)
5653 if (newindex
== queue
->rindex
)
5655 queue
->xrep
[queue
->windex
] = *p_xrep
;
5656 queue
->windex
= newindex
;
5660 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5661 If *QUEUE is empty, do nothing and return 0. */
5664 dequeue_event (p_xrep
, queue
)
5665 register XEvent
*p_xrep
;
5666 register struct event_queue
*queue
;
5668 if (queue
->windex
== queue
->rindex
)
5670 *p_xrep
= queue
->xrep
[queue
->rindex
++];
5671 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
5676 /* Return the number of events buffered in *QUEUE. */
5679 queue_event_count (queue
)
5680 register struct event_queue
*queue
;
5682 int tem
= queue
->windex
- queue
->rindex
;
5685 return EVENT_BUFFER_SIZE
+ tem
;
5688 /* Return nonzero if mouse input is pending. */
5691 mouse_event_pending_p ()
5693 return queue_event_count (&x_mouse_queue
);
5695 #endif /* HAVE_X11 */
5697 /* Setting window manager hints. */
5701 /* SPEC_X and SPEC_Y are the specified positions.
5702 We look only at their sign, to decide the gravity.
5703 If CHANGE_GRAVITY is 0, we may set PWinGravity. */
5705 x_wm_set_size_hint (f
, prompting
, change_gravity
)
5710 XSizeHints size_hints
;
5712 #ifdef USE_X_TOOLKIT
5715 Dimension widget_width
, widget_height
;
5716 Window window
= XtWindow (f
->display
.x
->widget
);
5717 #else /* not USE_X_TOOLKIT */
5718 Window window
= FRAME_X_WINDOW (f
);
5719 #endif /* not USE_X_TOOLKIT */
5721 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5723 flexlines
= f
->height
;
5725 size_hints
.x
= f
->display
.x
->left_pos
;
5726 size_hints
.y
= f
->display
.x
->top_pos
;
5727 #ifdef USE_X_TOOLKIT
5728 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5729 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5730 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5731 size_hints
.height
= widget_height
;
5732 size_hints
.width
= widget_width
;
5733 #else /* not USE_X_TOOLKIT */
5734 size_hints
.height
= PIXEL_HEIGHT (f
);
5735 size_hints
.width
= PIXEL_WIDTH (f
);
5736 #endif /* not USE_X_TOOLKIT */
5737 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5738 size_hints
.height_inc
= f
->display
.x
->line_height
;
5741 int base_width
, base_height
;
5742 int min_rows
= 0, min_cols
= 0;
5744 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5745 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5747 check_frame_size (f
, &min_rows
, &min_cols
);
5749 /* The window manager uses the base width hints to calculate the
5750 current number of rows and columns in the frame while
5751 resizing; min_width and min_height aren't useful for this
5752 purpose, since they might not give the dimensions for a
5753 zero-row, zero-column frame.
5755 We use the base_width and base_height members if we have
5756 them; otherwise, we set the min_width and min_height members
5757 to the size for a zero x zero frame. */
5760 size_hints
.flags
|= PBaseSize
;
5761 size_hints
.base_width
= base_width
;
5762 size_hints
.base_height
= base_height
;
5763 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5764 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5766 size_hints
.min_width
= base_width
;
5767 size_hints
.min_height
= base_height
;
5772 size_hints
.flags
|= prompting
;
5775 XSizeHints hints
; /* Sometimes I hate X Windows... */
5777 if (XGetNormalHints (x_current_display
, window
, &hints
) == 0)
5779 if (hints
.flags
& PSize
)
5780 size_hints
.flags
|= PSize
;
5781 if (hints
.flags
& PPosition
)
5782 size_hints
.flags
|= PPosition
;
5783 if (hints
.flags
& USPosition
)
5784 size_hints
.flags
|= USPosition
;
5785 if (hints
.flags
& USSize
)
5786 size_hints
.flags
|= USSize
;
5789 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5791 #if defined (PWinGravity)
5794 if (! (size_hints
.flags
& USPosition
))
5795 size_hints
.flags
|= PWinGravity
;
5797 #endif /* PWinGravity */
5800 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
5802 XSetNormalHints (x_current_display
, window
, &size_hints
);
5806 /* Used for IconicState or NormalState */
5807 x_wm_set_window_state (f
, state
)
5811 #ifdef USE_X_TOOLKIT
5812 Window window
= XtWindow (f
->display
.x
->widget
);
5813 #else /* not USE_X_TOOLKIT */
5814 Window window
= FRAME_X_WINDOW (f
);
5815 #endif /* not USE_X_TOOLKIT */
5817 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5818 f
->display
.x
->wm_hints
.initial_state
= state
;
5820 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5823 x_wm_set_icon_pixmap (f
, icon_pixmap
)
5827 Window window
= FRAME_X_WINDOW (f
);
5831 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5832 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5835 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5837 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5840 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5844 Window window
= FRAME_X_WINDOW (f
);
5846 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5847 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5848 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5850 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5854 /* Initialization. */
5856 #ifdef USE_X_TOOLKIT
5857 static XrmOptionDescRec emacs_options
[] = {
5858 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5859 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5861 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5862 XrmoptionSepArg
, NULL
},
5863 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5865 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5866 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5867 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5868 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5869 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5870 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5871 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5873 #endif /* USE_X_TOOLKIT */
5876 x_term_init (display_name
)
5883 #ifndef F_SETOWN_BUG
5885 extern int old_fcntl_owner
;
5886 #endif /* ! defined (F_SETOWN) */
5887 #endif /* F_SETOWN_BUG */
5889 x_focus_frame
= x_highlight_frame
= 0;
5891 #ifdef USE_X_TOOLKIT
5892 argv
= (char **) XtMalloc (5 * sizeof (char *));
5894 argv
[1] = "-display";
5895 argv
[2] = display_name
;
5899 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
5900 emacs_options
, XtNumber (emacs_options
),
5904 x_current_display
= XtDisplay (Xt_app_shell
);
5906 #else /* not USE_X_TOOLKIT */
5907 x_current_display
= XOpenDisplay (display_name
);
5908 #endif /* not USE_X_TOOLKIT */
5909 if (x_current_display
== 0)
5910 fatal ("X server %s not responding.\n\
5911 Check the DISPLAY environment variable or use \"-d\"\n",
5917 XSetAfterFunction (x_current_display
, x_trace_wire
);
5919 hostname
= get_system_name ();
5920 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5923 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
5926 /* Figure out which modifier bits mean what. */
5927 x_find_modifier_meanings ();
5929 /* Get the scroll bar cursor. */
5930 x_vertical_scroll_bar_cursor
5931 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
5934 /* Watch for PropertyNotify events on the root window; we use them
5935 to figure out when to invalidate our cache of the cut buffers. */
5936 x_watch_cut_buffer_cache ();
5939 if (ConnectionNumber (x_current_display
) != 0)
5940 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
5941 change_input_fd (ConnectionNumber (x_current_display
));
5943 #endif /* ! defined (HAVE_X11) */
5945 #ifndef F_SETOWN_BUG
5947 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
5948 #ifdef F_SETOWN_SOCK_NEG
5949 /* stdin is a socket here */
5950 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
5951 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5952 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
5953 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5954 #endif /* ! defined (F_SETOWN) */
5955 #endif /* F_SETOWN_BUG */
5959 #endif /* ! defined (SIGIO) */
5961 expose_all_windows
= 0;
5963 clear_frame_hook
= XTclear_frame
;
5964 clear_end_of_line_hook
= XTclear_end_of_line
;
5965 ins_del_lines_hook
= XTins_del_lines
;
5966 change_line_highlight_hook
= XTchange_line_highlight
;
5967 insert_glyphs_hook
= XTinsert_glyphs
;
5968 write_glyphs_hook
= XTwrite_glyphs
;
5969 delete_glyphs_hook
= XTdelete_glyphs
;
5970 ring_bell_hook
= XTring_bell
;
5971 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5972 set_terminal_modes_hook
= XTset_terminal_modes
;
5973 update_begin_hook
= XTupdate_begin
;
5974 update_end_hook
= XTupdate_end
;
5975 set_terminal_window_hook
= XTset_terminal_window
;
5976 read_socket_hook
= XTread_socket
;
5977 frame_up_to_date_hook
= XTframe_up_to_date
;
5978 cursor_to_hook
= XTcursor_to
;
5979 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5980 mouse_position_hook
= XTmouse_position
;
5981 frame_rehighlight_hook
= XTframe_rehighlight
;
5982 frame_raise_lower_hook
= XTframe_raise_lower
;
5983 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5984 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5985 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5986 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5988 scroll_region_ok
= 1; /* we'll scroll partial frames */
5989 char_ins_del_ok
= 0; /* just as fast to write the line */
5990 line_ins_del_ok
= 1; /* we'll just blt 'em */
5991 fast_clear_end_of_line
= 1; /* X does this well */
5992 memory_below_frame
= 0; /* we don't remember what scrolls
5996 /* Try to use interrupt input; if we can't, then start polling. */
5997 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5999 /* Note that there is no real way portable across R3/R4 to get the
6000 original error handler. */
6001 XHandleError (x_error_quitter
);
6002 XHandleIOError (x_io_error_quitter
);
6004 /* Disable Window Change signals; they are handled by X events. */
6006 signal (SIGWINCH
, SIG_DFL
);
6007 #endif /* ! defined (SIGWINCH) */
6009 signal (SIGPIPE
, x_connection_closed
);
6015 staticpro (&last_mouse_scroll_bar
);
6016 last_mouse_scroll_bar
= Qnil
;
6017 staticpro (&mouse_face_window
);
6018 mouse_face_window
= Qnil
;
6020 #endif /* ! defined (HAVE_X11) */
6021 #endif /* ! defined (HAVE_X_WINDOWS) */