1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
60 #ifndef INCLUDED_FCNTL
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
71 #include "dispextern.h"
72 #include "termhooks.h"
84 #include "intervals.h"
87 extern void free_frame_menubar ();
88 extern void _XEditResCheckMessages ();
89 #endif /* USE_X_TOOLKIT */
92 #define x_any_window_to_frame x_window_to_frame
93 #define x_top_window_to_frame x_window_to_frame
97 #ifndef XtNinitialState
98 #define XtNinitialState "initialState"
102 #define min(a,b) ((a)<(b) ? (a) : (b))
103 #define max(a,b) ((a)>(b) ? (a) : (b))
105 /* This is a chain of structures for all the X displays currently in use. */
106 struct x_display_info
*x_display_list
;
108 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
109 one for each element of x_display_list and in the same order.
110 NAME is the name of the frame.
111 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
112 Lisp_Object x_display_name_list
;
114 /* Frame being updated by update_frame. This is declared in term.c.
115 This is set by update_begin and looked at by all the
116 XT functions. It is zero while not inside an update.
117 In that case, the XT functions assume that `selected_frame'
118 is the frame to apply to. */
119 extern struct frame
*updating_frame
;
121 /* The frame (if any) which has the X window that has keyboard focus.
122 Zero if none. This is examined by Ffocus_frame in frame.c. Note
123 that a mere EnterNotify event can set this; if you need to know the
124 last frame specified in a FocusIn or FocusOut event, use
125 x_focus_event_frame. */
126 struct frame
*x_focus_frame
;
128 /* This is a frame waiting to be autoraised, within XTread_socket. */
129 struct frame
*pending_autoraise_frame
;
131 /* The last frame mentioned in a FocusIn or FocusOut event. This is
132 separate from x_focus_frame, because whether or not LeaveNotify
133 events cause us to lose focus depends on whether or not we have
134 received a FocusIn event for it. */
135 struct frame
*x_focus_event_frame
;
137 /* The frame which currently has the visual highlight, and should get
138 keyboard input (other sorts of input have the frame encoded in the
139 event). It points to the X focus frame's selected window's
140 frame. It differs from x_focus_frame when we're using a global
142 static struct frame
*x_highlight_frame
;
145 /* The application context for Xt use. */
146 XtAppContext Xt_app_con
;
149 /* During an update, maximum vpos for ins/del line operations to affect. */
151 static int flexlines
;
153 /* During an update, nonzero if chars output now should be highlighted. */
155 static int highlight
;
157 /* Nominal cursor position -- where to draw output.
158 During an update, these are different from the cursor-box position. */
165 In order to avoid asking for motion events and then throwing most
166 of them away or busy-polling the server for mouse positions, we ask
167 the server for pointer motion hints. This means that we get only
168 one event per group of mouse movements. "Groups" are delimited by
169 other kinds of events (focus changes and button clicks, for
170 example), or by XQueryPointer calls; when one of these happens, we
171 get another MotionNotify event the next time the mouse moves. This
172 is at least as efficient as getting motion events when mouse
173 tracking is on, and I suspect only negligibly worse when tracking
176 The silly O'Reilly & Associates Nutshell guides barely document
177 pointer motion hints at all (I think you have to infer how they
178 work from an example), and the description of XQueryPointer doesn't
179 mention that calling it causes you to get another motion hint from
180 the server, which is very important. */
182 /* Where the mouse was last time we reported a mouse event. */
183 static FRAME_PTR last_mouse_frame
;
184 static XRectangle last_mouse_glyph
;
186 /* The scroll bar in which the last X motion event occurred.
188 If the last X motion event occurred in a scroll bar, we set this
189 so XTmouse_position can know whether to report a scroll bar motion or
192 If the last X motion event didn't occur in a scroll bar, we set this
193 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
194 static Lisp_Object last_mouse_scroll_bar
;
196 /* This is a hack. We would really prefer that XTmouse_position would
197 return the time associated with the position it returns, but there
198 doesn't seem to be any way to wrest the timestamp from the server
199 along with the position query. So, we just keep track of the time
200 of the last movement we received, and return that in hopes that
201 it's somewhat accurate. */
202 static Time last_mouse_movement_time
;
204 /* Incremented by XTread_socket whenever it really tries to read events. */
206 static int volatile input_signal_count
;
208 static int input_signal_count
;
211 /* Used locally within XTread_socket. */
212 static int x_noop_count
;
214 /* Initial values of argv and argc. */
215 extern char **initial_argv
;
216 extern int initial_argc
;
218 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
220 /* Tells if a window manager is present or not. */
222 extern Lisp_Object Vx_no_window_manager
;
224 /* Nonzero enables some debugging for the X interface code. */
227 extern Lisp_Object Qface
, Qmouse_face
;
231 /* A mask of extra modifier bits to put into every keyboard char. */
232 extern int extra_keyboard_modifiers
;
234 extern XrmDatabase
x_load_resources ();
236 void x_delete_display ();
238 static void flashback ();
239 static void redraw_previous_char ();
240 static void redraw_following_char ();
241 static unsigned int x_x_to_emacs_modifiers ();
243 static int fast_find_position ();
244 static void note_mouse_highlight ();
245 static void clear_mouse_face ();
246 static void show_mouse_face ();
247 static void do_line_dance ();
249 static int XTcursor_to ();
250 static int XTclear_end_of_line ();
251 static int x_io_error_quitter ();
253 /* Return the struct x_display_info corresponding to DPY. */
255 struct x_display_info
*
256 x_display_info_for_display (dpy
)
259 struct x_display_info
*dpyinfo
;
261 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
262 if (dpyinfo
->display
== dpy
)
268 /* Starting and ending updates.
270 These hooks are called by update_frame at the beginning and end
271 of a frame update. We record in `updating_frame' the identity
272 of the frame being updated, so that the XT... functions do not
273 need to take a frame as argument. Most of the XT... functions
274 should never be called except during an update, the only exceptions
275 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
286 flexlines
= f
->height
;
291 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
293 /* Don't do highlighting for mouse motion during the update. */
294 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
296 /* If the frame needs to be redrawn,
297 simply forget about any prior mouse highlighting. */
298 if (FRAME_GARBAGED_P (f
))
299 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
301 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
303 int firstline
, lastline
, i
;
304 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
306 /* Find the first, and the last+1, lines affected by redisplay. */
307 for (firstline
= 0; firstline
< f
->height
; firstline
++)
308 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
311 lastline
= f
->height
;
312 for (i
= f
->height
- 1; i
>= 0; i
--)
314 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
320 /* Can we tell that this update does not affect the window
321 where the mouse highlight is? If so, no need to turn off.
322 Likewise, don't do anything if the frame is garbaged;
323 in that case, the FRAME_CURRENT_GLYPHS that we would use
324 are all wrong, and we will redisplay that line anyway. */
325 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
326 || lastline
< XFASTINT (w
->top
)))
327 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
343 x_display_cursor (f
, 1);
345 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
346 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
348 /* This fails in the case of having updated only the echo area
349 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
350 has no relation to the current contents, and its charstarts
351 have no relation to the contents of the window-buffer.
352 I don't know a clean way to check
353 for that case. window_end_valid isn't set up yet. */
354 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
355 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
356 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
359 XFlush (FRAME_X_DISPLAY (f
));
363 /* This is called after a redisplay on frame F. */
366 XTframe_up_to_date (f
)
369 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
370 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
372 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
373 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
374 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
375 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
379 /* External interface to control of standout mode.
380 Call this when about to modify line at position VPOS
381 and not change whether it is highlighted. */
383 XTreassert_line_highlight (new, vpos
)
389 /* Call this when about to modify line at position VPOS
390 and change whether it is highlighted. */
393 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
394 int new_highlight
, vpos
, first_unused_hpos
;
396 highlight
= new_highlight
;
397 XTcursor_to (vpos
, 0);
398 XTclear_end_of_line (updating_frame
->width
);
401 /* This is used when starting Emacs and when restarting after suspend.
402 When starting Emacs, no X window is mapped. And nothing must be done
403 to Emacs's own window if it is suspended (though that rarely happens). */
406 XTset_terminal_modes ()
410 /* This is called when exiting or suspending Emacs.
411 Exiting will make the X-windows go away, and suspending
412 requires no action. */
415 XTreset_terminal_modes ()
417 /* XTclear_frame (); */
420 /* Set the nominal cursor position of the frame.
421 This is where display update commands will take effect.
422 This does not affect the place where the cursor-box is displayed. */
425 XTcursor_to (row
, col
)
426 register int row
, col
;
434 if (updating_frame
== 0)
437 x_display_cursor (selected_frame
, 1);
438 XFlush (FRAME_X_DISPLAY (selected_frame
));
443 /* Display a sequence of N glyphs found at GP.
444 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
445 HL is 1 if this text is highlighted, 2 if the cursor is on it,
446 3 if should appear in its mouse-face.
447 JUST_FOREGROUND if 1 means draw only the foreground;
448 don't alter the background.
450 FONT is the default font to use (for glyphs whose font-code is 0).
452 Since the display generation code is responsible for calling
453 compute_char_face and compute_glyph_face on everything it puts in
454 the display structure, we can assume that the face code on each
455 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
456 to which we can actually apply intern_face.
457 Call this function with input blocked. */
460 /* This is the multi-face code. */
463 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
466 register GLYPH
*gp
; /* Points to first GLYPH. */
467 register int n
; /* Number of glyphs to display. */
471 /* Holds characters to be displayed. */
472 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
473 register char *cp
; /* Steps through buf[]. */
474 register int tlen
= GLYPH_TABLE_LENGTH
;
475 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
476 Window window
= FRAME_X_WINDOW (f
);
477 int orig_left
= left
;
481 /* Get the face-code of the next GLYPH. */
485 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
486 cf
= FAST_GLYPH_FACE (g
);
488 /* Find the run of consecutive glyphs with the same face-code.
489 Extract their character codes into BUF. */
494 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
495 if (FAST_GLYPH_FACE (g
) != cf
)
498 *cp
++ = FAST_GLYPH_CHAR (g
);
503 /* LEN gets the length of the run. */
506 /* Now output this run of chars, with the font and pixel values
507 determined by the face code CF. */
509 struct face
*face
= FRAME_DEFAULT_FACE (f
);
510 XFontStruct
*font
= FACE_FONT (face
);
511 GC gc
= FACE_GC (face
);
514 /* HL = 3 means use a mouse face previously chosen. */
516 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
518 /* First look at the face of the text itself. */
521 /* It's possible for the display table to specify
522 a face code that is out of range. Use 0 in that case. */
523 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
524 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
528 face
= FRAME_MODE_LINE_FACE (f
);
530 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
531 font
= FACE_FONT (face
);
533 if (FACE_STIPPLE (face
))
537 /* Then comes the distinction between modeline and normal text. */
542 face
= FRAME_MODE_LINE_FACE (f
);
543 font
= FACE_FONT (face
);
545 if (FACE_STIPPLE (face
))
549 #define FACE_DEFAULT (~0)
551 /* Now override that if the cursor's on this character. */
554 /* The cursor overrides stippling. */
558 || (int) face
->font
== FACE_DEFAULT
559 || face
->font
== f
->display
.x
->font
)
560 && face
->background
== f
->display
.x
->background_pixel
561 && face
->foreground
== f
->display
.x
->foreground_pixel
)
563 gc
= f
->display
.x
->cursor_gc
;
565 /* Cursor on non-default face: must merge. */
571 xgcv
.background
= f
->display
.x
->cursor_pixel
;
572 xgcv
.foreground
= face
->background
;
573 /* If the glyph would be invisible,
574 try a different foreground. */
575 if (xgcv
.foreground
== xgcv
.background
)
576 xgcv
.foreground
= face
->foreground
;
577 if (xgcv
.foreground
== xgcv
.background
)
578 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
579 if (xgcv
.foreground
== xgcv
.background
)
580 xgcv
.foreground
= face
->foreground
;
581 /* Make sure the cursor is distinct from text in this face. */
582 if (xgcv
.background
== face
->background
583 && xgcv
.foreground
== face
->foreground
)
585 xgcv
.background
= face
->foreground
;
586 xgcv
.foreground
= face
->background
;
588 xgcv
.font
= face
->font
->fid
;
589 xgcv
.graphics_exposures
= 0;
590 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
591 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
592 XChangeGC (FRAME_X_DISPLAY (f
),
593 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
596 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
597 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
598 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
600 /* If this code is restored, it must also reset to the default stipple
602 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
603 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
608 if ((int) font
== FACE_DEFAULT
)
609 font
= f
->display
.x
->font
;
612 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
613 left
, top
+ FONT_BASE (font
), buf
, len
);
618 /* Turn stipple on. */
619 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
621 /* Draw stipple on background. */
622 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
624 FONT_WIDTH (font
) * len
,
627 /* Turn stipple off. */
628 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
630 /* Draw the text, solidly, onto the stipple pattern. */
631 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
632 left
, top
+ FONT_BASE (font
), buf
, len
);
635 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
636 left
, top
+ FONT_BASE (font
), buf
, len
);
638 /* Clear the rest of the line's height. */
639 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
640 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
641 top
+ FONT_HEIGHT (font
),
642 FONT_WIDTH (font
) * len
,
643 /* This is how many pixels of height
645 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
649 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
650 which often is not up to date yet. */
651 if (!just_foreground
)
653 if (left
== orig_left
)
654 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
655 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
657 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
658 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
662 /* We should probably check for XA_UNDERLINE_POSITION and
663 XA_UNDERLINE_THICKNESS properties on the font, but let's
664 just get the thing working, and come back to that. */
666 int underline_position
= 1;
668 if (font
->descent
<= underline_position
)
669 underline_position
= font
->descent
- 1;
672 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
676 + underline_position
),
677 len
* FONT_WIDTH (font
), 1);
680 left
+= len
* FONT_WIDTH (font
);
687 /* This is the old single-face code. */
690 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
693 register GLYPH
*gp
; /* Points to first GLYPH. */
694 register int n
; /* Number of glyphs to display. */
699 Window window
= FRAME_X_WINDOW (f
);
700 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
701 : (hl
? f
->display
.x
->reverse_gc
702 : f
->display
.x
->normal_gc
));
704 if (sizeof (GLYPH
) == sizeof (XChar2b
))
705 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
706 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
707 else if (sizeof (GLYPH
) == sizeof (unsigned char))
708 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
709 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
711 /* What size of glyph ARE you using? And does X have a function to
717 /* Output some text at the nominal frame cursor position.
718 Advance the cursor over the text.
719 Output LEN glyphs at START.
721 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
722 controls the pixel values used for foreground and background. */
725 XTwrite_glyphs (start
, len
)
726 register GLYPH
*start
;
729 register int temp_length
;
740 /* If not within an update,
741 output at the frame's visible cursor. */
742 curs_x
= f
->cursor_x
;
743 curs_y
= f
->cursor_y
;
747 CHAR_TO_PIXEL_COL (f
, curs_x
),
748 CHAR_TO_PIXEL_ROW (f
, curs_y
),
749 start
, len
, highlight
, 0);
751 /* If we drew on top of the cursor, note that it is turned off. */
752 if (curs_y
== f
->phys_cursor_y
753 && curs_x
<= f
->phys_cursor_x
754 && curs_x
+ len
> f
->phys_cursor_x
)
755 f
->phys_cursor_x
= -1;
757 if (updating_frame
== 0)
760 x_display_cursor (f
, 1);
769 /* Clear to the end of the line.
770 Erase the current text line from the nominal cursor position (inclusive)
771 to column FIRST_UNUSED (exclusive). The idea is that everything
772 from FIRST_UNUSED onward is already erased. */
775 XTclear_end_of_line (first_unused
)
776 register int first_unused
;
778 struct frame
*f
= updating_frame
;
784 if (curs_y
< 0 || curs_y
>= f
->height
)
786 if (first_unused
<= 0)
789 if (first_unused
>= f
->width
)
790 first_unused
= f
->width
;
796 /* Notice if the cursor will be cleared by this operation. */
797 if (curs_y
== f
->phys_cursor_y
798 && curs_x
<= f
->phys_cursor_x
799 && f
->phys_cursor_x
< first_unused
)
800 f
->phys_cursor_x
= -1;
802 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
803 CHAR_TO_PIXEL_COL (f
, curs_x
),
804 CHAR_TO_PIXEL_ROW (f
, curs_y
),
805 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
806 f
->display
.x
->line_height
, False
);
808 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
818 struct frame
*f
= updating_frame
;
823 f
->phys_cursor_x
= -1; /* Cursor not visible. */
824 curs_x
= 0; /* Nominal cursor position is top left. */
829 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
831 /* We have to clear the scroll bars, too. If we have changed
832 colors or something like that, then they should be notified. */
833 x_scroll_bar_clear (f
);
835 XFlush (FRAME_X_DISPLAY (f
));
840 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
841 always contain the right glyphs to use.
843 It also needs to be changed to look at the details of the font and
844 see whether there is really overlap, and do nothing when there is
845 not. This can use font_char_overlap_left and font_char_overlap_right,
846 but just how to use them is not clear. */
848 /* Erase the character (if any) at the position just before X, Y in frame F,
849 then redraw it and the character before it.
850 This is necessary when we erase starting at X,
851 in case the character after X overlaps into the one before X.
852 Call this function with input blocked. */
855 redraw_previous_char (f
, x
, y
, highlight_flag
)
860 /* Erase the character before the new ones, in case
861 what was here before overlaps it.
862 Reoutput that character, and the previous character
863 (in case the previous character overlaps it). */
869 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
870 CHAR_TO_PIXEL_COL (f
, x
- 1),
871 CHAR_TO_PIXEL_ROW (f
, y
),
872 FONT_WIDTH (f
->display
.x
->font
),
873 f
->display
.x
->line_height
, False
);
875 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
876 CHAR_TO_PIXEL_ROW (f
, y
),
877 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
878 x
- start_x
, highlight_flag
, 1);
882 /* Erase the character (if any) at the position X, Y in frame F,
883 then redraw it and the character after it.
884 This is necessary when we erase endng at X,
885 in case the character after X overlaps into the one before X.
886 Call this function with input blocked. */
889 redraw_following_char (f
, x
, y
, highlight_flag
)
894 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
895 /* Erase the character after the new ones, in case
896 what was here before overlaps it.
897 Reoutput that character, and the following character
898 (in case the following character overlaps it). */
900 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
905 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
906 CHAR_TO_PIXEL_COL (f
, x
),
907 CHAR_TO_PIXEL_ROW (f
, y
),
908 FONT_WIDTH (f
->display
.x
->font
),
909 f
->display
.x
->line_height
, False
);
911 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
912 CHAR_TO_PIXEL_ROW (f
, y
),
913 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
914 end_x
- x
, highlight_flag
, 1);
919 #if 0 /* Not in use yet */
921 /* Return 1 if character C in font F extends past its left edge. */
924 font_char_overlap_left (font
, c
)
930 /* Find the bounding-box info for C. */
931 if (font
->per_char
== 0)
932 s
= &font
->max_bounds
;
935 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
938 /* Decode char into row number (byte 1) and code within row (byte 2). */
941 if (!(within
>= font
->min_char_or_byte2
942 && within
<= font
->max_char_or_byte2
943 && row
>= font
->min_byte1
944 && row
<= font
->max_byte1
))
946 /* If char is out of range, try the font's default char instead. */
947 c
= font
->default_char
;
948 row
= c
>> (INTBITS
- 8);
951 if (!(within
>= font
->min_char_or_byte2
952 && within
<= font
->max_char_or_byte2
953 && row
>= font
->min_byte1
954 && row
<= font
->max_byte1
))
955 /* Still out of range means this char does not overlap. */
958 /* We found the info for this char. */
959 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
963 return (s
&& s
->lbearing
< 0);
966 /* Return 1 if character C in font F extends past its right edge. */
969 font_char_overlap_right (font
, c
)
975 /* Find the bounding-box info for C. */
976 if (font
->per_char
== 0)
977 s
= &font
->max_bounds
;
980 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
983 /* Decode char into row number (byte 1) and code within row (byte 2). */
986 if (!(within
>= font
->min_char_or_byte2
987 && within
<= font
->max_char_or_byte2
988 && row
>= font
->min_byte1
989 && row
<= font
->max_byte1
))
991 /* If char is out of range, try the font's default char instead. */
992 c
= font
->default_char
;
993 row
= c
>> (INTBITS
- 8);
996 if (!(within
>= font
->min_char_or_byte2
997 && within
<= font
->max_char_or_byte2
998 && row
>= font
->min_byte1
999 && row
<= font
->max_byte1
))
1000 /* Still out of range means this char does not overlap. */
1003 /* We found the info for this char. */
1004 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1008 return (s
&& s
->rbearing
>= s
->width
);
1012 /* Invert the middle quarter of the frame for .15 sec. */
1014 /* We use the select system call to do the waiting, so we have to make sure
1015 it's available. If it isn't, we just won't do visual bells. */
1016 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1018 /* Subtract the `struct timeval' values X and Y,
1019 storing the result in RESULT.
1020 Return 1 if the difference is negative, otherwise 0. */
1023 timeval_subtract (result
, x
, y
)
1024 struct timeval
*result
, x
, y
;
1026 /* Perform the carry for the later subtraction by updating y.
1027 This is safer because on some systems
1028 the tv_sec member is unsigned. */
1029 if (x
.tv_usec
< y
.tv_usec
)
1031 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1032 y
.tv_usec
-= 1000000 * nsec
;
1035 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1037 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1038 y
.tv_usec
+= 1000000 * nsec
;
1042 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1043 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1044 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1046 /* Return indication of whether the result should be considered negative. */
1047 return x
.tv_sec
< y
.tv_sec
;
1058 /* Create a GC that will use the GXxor function to flip foreground pixels
1059 into background pixels. */
1063 values
.function
= GXxor
;
1064 values
.foreground
= (f
->display
.x
->foreground_pixel
1065 ^ f
->display
.x
->background_pixel
);
1067 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1068 GCFunction
| GCForeground
, &values
);
1072 int width
= PIXEL_WIDTH (f
);
1073 int height
= PIXEL_HEIGHT (f
);
1075 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1076 width
/4, height
/4, width
/2, height
/2);
1077 XFlush (FRAME_X_DISPLAY (f
));
1080 struct timeval wakeup
, now
;
1082 EMACS_GET_TIME (wakeup
);
1084 /* Compute time to wait until, propagating carry from usecs. */
1085 wakeup
.tv_usec
+= 150000;
1086 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1087 wakeup
.tv_usec
%= 1000000;
1089 /* Keep waiting until past the time wakeup. */
1092 struct timeval timeout
;
1094 EMACS_GET_TIME (timeout
);
1096 /* In effect, timeout = wakeup - timeout.
1097 Break if result would be negative. */
1098 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1101 /* Try to wait that long--but we might wake up sooner. */
1102 select (0, 0, 0, 0, &timeout
);
1106 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1107 width
/4, height
/4, width
/2, height
/2);
1108 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1109 XFlush (FRAME_X_DISPLAY (f
));
1119 /* Make audible bell. */
1121 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1125 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1128 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1130 XTflash (selected_frame
);
1136 XFlush (FRAME_X_DISPLAY (selected_frame
));
1141 /* Insert and delete character.
1142 These are not supposed to be used because we are supposed to turn
1143 off the feature of using them. */
1146 XTinsert_glyphs (start
, len
)
1147 register char *start
;
1160 /* Specify how many text lines, from the top of the window,
1161 should be affected by insert-lines and delete-lines operations.
1162 This, and those operations, are used only within an update
1163 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1166 XTset_terminal_window (n
)
1169 if (updating_frame
== 0)
1172 if ((n
<= 0) || (n
> updating_frame
->height
))
1173 flexlines
= updating_frame
->height
;
1178 /* These variables need not be per frame
1179 because redisplay is done on a frame-by-frame basis
1180 and the line dance for one frame is finished before
1181 anything is done for anoter frame. */
1183 /* Array of line numbers from cached insert/delete operations.
1184 line_dance[i] is the old position of the line that we want
1185 to move to line i, or -1 if we want a blank line there. */
1186 static int *line_dance
;
1188 /* Allocated length of that array. */
1189 static int line_dance_len
;
1191 /* Flag indicating whether we've done any work. */
1192 static int line_dance_in_progress
;
1194 /* Perform an insert-lines or delete-lines operation,
1195 inserting N lines or deleting -N lines at vertical position VPOS. */
1196 XTins_del_lines (vpos
, n
)
1199 register int fence
, i
;
1201 if (vpos
>= flexlines
)
1204 if (!line_dance_in_progress
)
1206 int ht
= updating_frame
->height
;
1207 if (ht
> line_dance_len
)
1209 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1210 line_dance_len
= ht
;
1212 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1213 line_dance_in_progress
= 1;
1217 if (n
> flexlines
- vpos
)
1218 n
= flexlines
- vpos
;
1220 for (i
= flexlines
; --i
>= fence
;)
1221 line_dance
[i
] = line_dance
[i
-n
];
1222 for (i
= fence
; --i
>= vpos
;)
1228 if (n
> flexlines
- vpos
)
1229 n
= flexlines
- vpos
;
1230 fence
= flexlines
- n
;
1231 for (i
= vpos
; i
< fence
; ++i
)
1232 line_dance
[i
] = line_dance
[i
+ n
];
1233 for (i
= fence
; i
< flexlines
; ++i
)
1238 /* Here's where we actually move the pixels around.
1239 Must be called with input blocked. */
1243 register int i
, j
, distance
;
1244 register struct frame
*f
;
1248 /* Must check this flag first. If it's not set, then not only is the
1249 array uninitialized, but we might not even have a frame. */
1250 if (!line_dance_in_progress
)
1258 intborder
= f
->display
.x
->internal_border_width
;
1260 x_display_cursor (updating_frame
, 0);
1262 for (i
= 0; i
< ht
; ++i
)
1263 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1265 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1266 && line_dance
[j
]-j
== distance
); ++j
);
1267 /* Copy [i,j) upward from [i+distance,j+distance) */
1268 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1269 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1270 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1271 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1272 (j
-i
) * f
->display
.x
->line_height
,
1273 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1277 for (i
= ht
; --i
>=0; )
1278 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1280 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1281 && line_dance
[j
]-j
== distance
););
1282 /* Copy (j,i] downward from (j+distance, i+distance] */
1283 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1284 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1285 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1286 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1287 (i
-j
) * f
->display
.x
->line_height
,
1288 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1292 for (i
= 0; i
< ht
; ++i
)
1293 if (line_dance
[i
] == -1)
1295 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1297 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1298 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1299 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1300 (j
-i
) * f
->display
.x
->line_height
, False
);
1303 line_dance_in_progress
= 0;
1306 /* Support routines for exposure events. */
1307 static void clear_cursor ();
1309 /* Output into a rectangle of an X-window (for frame F)
1310 the characters in f->phys_lines that overlap that rectangle.
1311 TOP and LEFT are the position of the upper left corner of the rectangle.
1312 ROWS and COLS are the size of the rectangle.
1313 Call this function with input blocked. */
1316 dumprectangle (f
, left
, top
, cols
, rows
)
1318 register int left
, top
, cols
, rows
;
1320 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1321 int cursor_cleared
= 0;
1325 if (FRAME_GARBAGED_P (f
))
1328 /* Express rectangle as four edges, instead of position-and-size. */
1329 bottom
= top
+ rows
;
1330 right
= left
+ cols
;
1332 /* Convert rectangle edges in pixels to edges in chars.
1333 Round down for left and top, up for right and bottom. */
1334 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1335 left
= PIXEL_TO_CHAR_COL (f
, left
);
1336 bottom
+= (f
->display
.x
->line_height
- 1);
1337 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1338 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1339 right
= PIXEL_TO_CHAR_COL (f
, right
);
1341 /* Clip the rectangle to what can be visible. */
1346 if (right
> f
->width
)
1348 if (bottom
> f
->height
)
1351 /* Get size in chars of the rectangle. */
1352 cols
= right
- left
;
1353 rows
= bottom
- top
;
1355 /* If rectangle has zero area, return. */
1356 if (rows
<= 0) return;
1357 if (cols
<= 0) return;
1359 /* Turn off the cursor if it is in the rectangle.
1360 We will turn it back on afterward. */
1361 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1362 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1368 /* Display the text in the rectangle, one text line at a time. */
1370 for (y
= top
; y
< bottom
; y
++)
1372 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1374 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1378 CHAR_TO_PIXEL_COL (f
, left
),
1379 CHAR_TO_PIXEL_ROW (f
, y
),
1380 line
, min (cols
, active_frame
->used
[y
] - left
),
1381 active_frame
->highlight
[y
], 0);
1384 /* Turn the cursor on if we turned it off. */
1387 x_display_cursor (f
, 1);
1394 /* We used to only do this if Vx_no_window_manager was non-nil, but
1395 the ICCCM (section 4.1.6) says that the window's border pixmap
1396 and border pixel are window attributes which are "private to the
1397 client", so we can always change it to whatever we want. */
1399 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1400 f
->display
.x
->border_pixel
);
1402 x_display_cursor (f
, 1);
1406 frame_unhighlight (f
)
1409 /* We used to only do this if Vx_no_window_manager was non-nil, but
1410 the ICCCM (section 4.1.6) says that the window's border pixmap
1411 and border pixel are window attributes which are "private to the
1412 client", so we can always change it to whatever we want. */
1414 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1415 f
->display
.x
->border_tile
);
1417 x_display_cursor (f
, 1);
1420 static void XTframe_rehighlight ();
1422 /* The focus has changed. Update the frames as necessary to reflect
1423 the new situation. Note that we can't change the selected frame
1424 here, because the Lisp code we are interrupting might become confused.
1425 Each event gets marked with the frame in which it occurred, so the
1426 Lisp code can tell when the switch took place by examining the events. */
1429 x_new_focus_frame (frame
)
1430 struct frame
*frame
;
1432 struct frame
*old_focus
= x_focus_frame
;
1433 int events_enqueued
= 0;
1435 if (frame
!= x_focus_frame
)
1437 /* Set this before calling other routines, so that they see
1438 the correct value of x_focus_frame. */
1439 x_focus_frame
= frame
;
1441 if (old_focus
&& old_focus
->auto_lower
)
1442 x_lower_frame (old_focus
);
1445 selected_frame
= frame
;
1446 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1448 Fselect_window (selected_frame
->selected_window
);
1449 choose_minibuf_frame ();
1452 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1453 pending_autoraise_frame
= x_focus_frame
;
1455 pending_autoraise_frame
= 0;
1458 XTframe_rehighlight ();
1461 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1466 if (! x_focus_event_frame
)
1467 x_new_focus_frame (NULL
);
1469 x_new_focus_frame (x_focus_event_frame
); /* Was f, but that seems wrong. */
1472 /* The focus has changed, or we have redirected a frame's focus to
1473 another frame (this happens when a frame uses a surrogate
1474 minibuffer frame). Shift the highlight as appropriate. */
1476 XTframe_rehighlight ()
1478 struct frame
*old_highlight
= x_highlight_frame
;
1483 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (x_focus_frame
)))
1484 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1486 if (! FRAME_LIVE_P (x_highlight_frame
))
1488 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1489 x_highlight_frame
= x_focus_frame
;
1493 x_highlight_frame
= 0;
1495 if (x_highlight_frame
!= old_highlight
)
1498 frame_unhighlight (old_highlight
);
1499 if (x_highlight_frame
)
1500 frame_highlight (x_highlight_frame
);
1504 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1506 /* Initialize mode_switch_bit and modifier_meaning. */
1508 x_find_modifier_meanings (dpyinfo
)
1509 struct x_display_info
*dpyinfo
;
1511 int min_code
, max_code
;
1514 XModifierKeymap
*mods
;
1516 dpyinfo
->meta_mod_mask
= 0;
1517 dpyinfo
->shift_lock_mask
= 0;
1518 dpyinfo
->alt_mod_mask
= 0;
1519 dpyinfo
->super_mod_mask
= 0;
1520 dpyinfo
->hyper_mod_mask
= 0;
1523 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1525 min_code
= display
->min_keycode
;
1526 max_code
= display
->max_keycode
;
1529 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1530 min_code
, max_code
- min_code
+ 1,
1532 mods
= XGetModifierMapping (dpyinfo
->display
);
1534 /* Scan the modifier table to see which modifier bits the Meta and
1535 Alt keysyms are on. */
1537 int row
, col
; /* The row and column in the modifier table. */
1539 for (row
= 3; row
< 8; row
++)
1540 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1543 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1545 /* Zeroes are used for filler. Skip them. */
1549 /* Are any of this keycode's keysyms a meta key? */
1553 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1555 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1561 dpyinfo
->meta_mod_mask
|= (1 << row
);
1566 dpyinfo
->alt_mod_mask
|= (1 << row
);
1571 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1576 dpyinfo
->super_mod_mask
|= (1 << row
);
1580 /* Ignore this if it's not on the lock modifier. */
1581 if ((1 << row
) == LockMask
)
1582 dpyinfo
->shift_lock_mask
= LockMask
;
1590 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1591 if (! dpyinfo
->meta_mod_mask
)
1593 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1594 dpyinfo
->alt_mod_mask
= 0;
1597 /* If some keys are both alt and meta,
1598 make them just meta, not alt. */
1599 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1601 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1604 XFree ((char *) syms
);
1605 XFreeModifiermap (mods
);
1608 /* Convert between the modifier bits X uses and the modifier bits
1611 x_x_to_emacs_modifiers (dpyinfo
, state
)
1612 struct x_display_info
*dpyinfo
;
1615 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1616 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1617 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1618 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1619 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1620 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1624 x_emacs_to_x_modifiers (dpyinfo
, state
)
1625 struct x_display_info
*dpyinfo
;
1628 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1629 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1630 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1631 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1632 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1633 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1636 /* Mouse clicks and mouse movement. Rah. */
1638 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1639 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1640 that the glyph at X, Y occupies, if BOUNDS != 0.
1641 If NOCLIP is nonzero, do not force the value into range. */
1644 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1646 register int pix_x
, pix_y
;
1647 register int *x
, *y
;
1651 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1652 even for negative values. */
1654 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1656 pix_y
-= (f
)->display
.x
->line_height
- 1;
1658 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1659 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1663 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1664 bounds
->height
= f
->display
.x
->line_height
;
1665 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1666 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1673 else if (pix_x
> f
->width
)
1678 else if (pix_y
> f
->height
)
1687 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1690 register int *pix_x
, *pix_y
;
1692 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1693 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1696 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1698 If the event is a button press, then note that we have grabbed
1702 construct_mouse_click (result
, event
, f
)
1703 struct input_event
*result
;
1704 XButtonEvent
*event
;
1707 /* Make the event type no_event; we'll change that when we decide
1709 result
->kind
= mouse_click
;
1710 result
->code
= event
->button
- Button1
;
1711 result
->timestamp
= event
->time
;
1712 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1714 | (event
->type
== ButtonRelease
1722 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1723 XSETFASTINT (result
->x
, column
);
1724 XSETFASTINT (result
->y
, row
);
1726 XSETINT (result
->x
, event
->x
);
1727 XSETINT (result
->y
, event
->y
);
1728 XSETFRAME (result
->frame_or_window
, f
);
1732 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1735 construct_menu_click (result
, event
, f
)
1736 struct input_event
*result
;
1737 XButtonEvent
*event
;
1740 /* Make the event type no_event; we'll change that when we decide
1742 result
->kind
= mouse_click
;
1743 XSETINT (result
->code
, event
->button
- Button1
);
1744 result
->timestamp
= event
->time
;
1745 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1747 | (event
->type
== ButtonRelease
1751 XSETINT (result
->x
, event
->x
);
1752 XSETINT (result
->y
, -1);
1753 XSETFRAME (result
->frame_or_window
, f
);
1756 /* Function to report a mouse movement to the mainstream Emacs code.
1757 The input handler calls this.
1759 We have received a mouse movement event, which is given in *event.
1760 If the mouse is over a different glyph than it was last time, tell
1761 the mainstream emacs code by setting mouse_moved. If not, ask for
1762 another motion event, so we can check again the next time it moves. */
1765 note_mouse_movement (frame
, event
)
1767 XMotionEvent
*event
;
1770 last_mouse_movement_time
= event
->time
;
1772 if (event
->window
!= FRAME_X_WINDOW (frame
))
1775 last_mouse_scroll_bar
= Qnil
;
1777 note_mouse_highlight (frame
, -1, -1);
1779 /* Ask for another mouse motion event. */
1782 Window dummy_window
;
1784 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1785 &dummy_window
, &dummy_window
,
1786 &dummy
, &dummy
, &dummy
, &dummy
,
1787 (unsigned int *) &dummy
);
1791 /* Has the mouse moved off the glyph it was on at the last sighting? */
1792 else if (event
->x
< last_mouse_glyph
.x
1793 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1794 || event
->y
< last_mouse_glyph
.y
1795 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1798 last_mouse_scroll_bar
= Qnil
;
1800 note_mouse_highlight (frame
, event
->x
, event
->y
);
1802 /* Ask for another mouse motion event. */
1805 Window dummy_window
;
1807 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1808 &dummy_window
, &dummy_window
,
1809 &dummy
, &dummy
, &dummy
, &dummy
,
1810 (unsigned int *) &dummy
);
1815 /* It's on the same glyph. Call XQueryPointer so we'll get an
1816 event the next time the mouse moves and we can see if it's
1817 *still* on the same glyph. */
1819 Window dummy_window
;
1821 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1822 &dummy_window
, &dummy_window
,
1823 &dummy
, &dummy
, &dummy
, &dummy
,
1824 (unsigned int *) &dummy
);
1828 /* This is used for debugging, to turn off note_mouse_highlight. */
1829 static int disable_mouse_highlight
;
1831 /* Take proper action when the mouse has moved to position X, Y on frame F
1832 as regards highlighting characters that have mouse-face properties.
1833 Also dehighlighting chars where the mouse was before.
1834 X and Y can be negative or out of range. */
1837 note_mouse_highlight (f
, x
, y
)
1840 int row
, column
, portion
;
1841 XRectangle new_glyph
;
1845 if (disable_mouse_highlight
)
1848 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1849 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1850 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1852 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1857 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1861 /* Find out which glyph the mouse is on. */
1862 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1863 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1865 /* Which window is that in? */
1866 window
= window_from_coordinates (f
, column
, row
, &portion
);
1867 w
= XWINDOW (window
);
1869 /* If we were displaying active text in another window, clear that. */
1870 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1871 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1873 /* Are we in a window whose display is up to date?
1874 And verify the buffer's text has not changed. */
1875 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1876 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1877 && EQ (w
->window_end_valid
, w
->buffer
)
1878 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1880 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1883 /* Find which buffer position the mouse corresponds to. */
1884 for (i
= column
; i
>= 0; i
--)
1888 /* Is it outside the displayed active region (if any)? */
1890 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1891 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1892 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1893 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1894 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1895 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1896 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1897 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1898 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1900 Lisp_Object mouse_face
, overlay
, position
;
1901 Lisp_Object
*overlay_vec
;
1902 int len
, noverlays
, ignor1
;
1903 struct buffer
*obuf
;
1906 /* If we get an out-of-range value, return now; avoid an error. */
1907 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1910 /* Make the window's buffer temporarily current for
1911 overlays_at and compute_char_face. */
1912 obuf
= current_buffer
;
1913 current_buffer
= XBUFFER (w
->buffer
);
1919 /* Yes. Clear the display of the old active region, if any. */
1920 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1922 /* Is this char mouse-active? */
1923 XSETINT (position
, pos
);
1926 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1928 /* Put all the overlays we want in a vector in overlay_vec.
1929 Store the length in len. */
1930 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1932 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1934 /* Find the highest priority overlay that has a mouse-face prop. */
1936 for (i
= 0; i
< noverlays
; i
++)
1938 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1939 if (!NILP (mouse_face
))
1941 overlay
= overlay_vec
[i
];
1946 /* If no overlay applies, get a text property. */
1948 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1950 /* Handle the overlay case. */
1951 if (! NILP (overlay
))
1953 /* Find the range of text around this char that
1954 should be active. */
1955 Lisp_Object before
, after
;
1958 before
= Foverlay_start (overlay
);
1959 after
= Foverlay_end (overlay
);
1960 /* Record this as the current active region. */
1961 fast_find_position (window
, before
,
1962 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1963 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1964 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
1965 = !fast_find_position (window
, after
,
1966 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
1967 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
1968 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1969 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
1970 = compute_char_face (f
, w
, pos
, 0, 0,
1971 &ignore
, pos
+ 1, 1);
1973 /* Display it as active. */
1974 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
1976 /* Handle the text property case. */
1977 else if (! NILP (mouse_face
))
1979 /* Find the range of text around this char that
1980 should be active. */
1981 Lisp_Object before
, after
, beginning
, end
;
1984 beginning
= Fmarker_position (w
->start
);
1985 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1986 - XFASTINT (w
->window_end_pos
)));
1988 = Fprevious_single_property_change (make_number (pos
+ 1),
1990 w
->buffer
, beginning
);
1992 = Fnext_single_property_change (position
, Qmouse_face
,
1994 /* Record this as the current active region. */
1995 fast_find_position (window
, before
,
1996 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1997 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1998 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
1999 = !fast_find_position (window
, after
,
2000 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2001 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2002 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2003 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2004 = compute_char_face (f
, w
, pos
, 0, 0,
2005 &ignore
, pos
+ 1, 1);
2007 /* Display it as active. */
2008 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2012 current_buffer
= obuf
;
2017 /* Find the row and column of position POS in window WINDOW.
2018 Store them in *COLUMNP and *ROWP.
2019 This assumes display in WINDOW is up to date.
2020 If POS is above start of WINDOW, return coords
2021 of start of first screen line.
2022 If POS is after end of WINDOW, return coords of end of last screen line.
2024 Value is 1 if POS is in range, 0 if it was off screen. */
2027 fast_find_position (window
, pos
, columnp
, rowp
)
2030 int *columnp
, *rowp
;
2032 struct window
*w
= XWINDOW (window
);
2033 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2038 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2039 int width
= window_internal_width (w
);
2042 int maybe_next_line
= 0;
2044 /* Find the right row. */
2049 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2050 if (linestart
> pos
)
2052 /* If the position sought is the end of the buffer,
2053 don't include the blank lines at the bottom of the window. */
2054 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2056 maybe_next_line
= 1;
2063 /* Find the right column with in it. */
2064 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2066 for (i
= 0; i
< width
; i
++)
2068 if (charstarts
[left
+ i
] == pos
)
2071 *columnp
= i
+ left
;
2074 else if (charstarts
[left
+ i
] > pos
)
2076 else if (charstarts
[left
+ i
] > 0)
2080 /* If we're looking for the end of the buffer,
2081 and we didn't find it in the line we scanned,
2082 use the start of the following line. */
2083 if (maybe_next_line
)
2094 /* Display the active region described by mouse_face_*
2095 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2098 show_mouse_face (dpyinfo
, hl
)
2099 struct x_display_info
*dpyinfo
;
2102 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2103 int width
= window_internal_width (w
);
2104 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2107 int old_curs_x
= curs_x
;
2108 int old_curs_y
= curs_y
;
2110 /* Set these variables temporarily
2111 so that if we have to turn the cursor off and on again
2112 we will put it back at the same place. */
2113 curs_x
= f
->phys_cursor_x
;
2114 curs_y
= f
->phys_cursor_y
;
2116 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2117 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2119 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2120 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2122 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2123 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2125 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2127 /* If the cursor's in the text we are about to rewrite,
2128 turn the cursor off. */
2130 && curs_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
2131 && curs_x
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
)
2133 x_display_cursor (f
, 0);
2138 CHAR_TO_PIXEL_COL (f
, column
),
2139 CHAR_TO_PIXEL_ROW (f
, i
),
2140 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2142 /* Highlight with mouse face if hl > 0. */
2146 /* If we turned the cursor off, turn it back on. */
2148 x_display_cursor (f
, 1);
2150 curs_x
= old_curs_x
;
2151 curs_y
= old_curs_y
;
2153 /* Change the mouse cursor according to the value of HL. */
2155 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2156 f
->display
.x
->cross_cursor
);
2158 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2159 f
->display
.x
->text_cursor
);
2162 /* Clear out the mouse-highlighted active region.
2163 Redraw it unhighlighted first. */
2166 clear_mouse_face (dpyinfo
)
2167 struct x_display_info
*dpyinfo
;
2169 if (! NILP (dpyinfo
->mouse_face_window
))
2170 show_mouse_face (dpyinfo
, 0);
2172 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2173 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2174 dpyinfo
->mouse_face_window
= Qnil
;
2177 static struct scroll_bar
*x_window_to_scroll_bar ();
2178 static void x_scroll_bar_report_motion ();
2180 /* Return the current position of the mouse.
2182 If the mouse movement started in a scroll bar, set *f, *bar_window,
2183 and *part to the frame, window, and scroll bar part that the mouse
2184 is over. Set *x and *y to the portion and whole of the mouse's
2185 position on the scroll bar.
2187 If the mouse movement started elsewhere, set *f to the frame the
2188 mouse is on, *bar_window to nil, and *x and *y to the character cell
2191 Set *time to the server timestamp for the time at which the mouse
2192 was at this position.
2194 Don't store anything if we don't have a valid set of values to report.
2196 This clears the mouse_moved flag, so we can wait for the next mouse
2197 movement. This also calls XQueryPointer, which will cause the
2198 server to give us another MotionNotify when the mouse moves
2202 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2205 Lisp_Object
*bar_window
;
2206 enum scroll_bar_part
*part
;
2208 unsigned long *time
;
2214 if (! NILP (last_mouse_scroll_bar
))
2215 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2221 Window dummy_window
;
2225 last_mouse_scroll_bar
= Qnil
;
2227 /* Figure out which root window we're on. */
2228 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2229 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2231 /* The root window which contains the pointer. */
2234 /* Trash which we can't trust if the pointer is on
2235 a different screen. */
2238 /* The position on that root window. */
2241 /* More trash we can't trust. */
2244 /* Modifier keys and pointer buttons, about which
2246 (unsigned int *) &dummy
);
2248 /* Now we have a position on the root; find the innermost window
2249 containing the pointer. */
2253 int parent_x
, parent_y
;
2257 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2258 && FRAME_LIVE_P (last_mouse_frame
))
2260 /* If mouse was grabbed on a frame, give coords for that frame
2261 even if the mouse is now outside it. */
2262 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2264 /* From-window, to-window. */
2265 root
, FRAME_X_WINDOW (last_mouse_frame
),
2267 /* From-position, to-position. */
2268 root_x
, root_y
, &win_x
, &win_y
,
2272 f1
= last_mouse_frame
;
2278 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2280 /* From-window, to-window. */
2283 /* From-position, to-position. */
2284 root_x
, root_y
, &win_x
, &win_y
,
2297 /* Now we know that:
2298 win is the innermost window containing the pointer
2299 (XTC says it has no child containing the pointer),
2300 win_x and win_y are the pointer's position in it
2301 (XTC did this the last time through), and
2302 parent_x and parent_y are the pointer's position in win's parent.
2303 (They are what win_x and win_y were when win was child.
2304 If win is the root window, it has no parent, and
2305 parent_{x,y} are invalid, but that's okay, because we'll
2306 never use them in that case.) */
2308 /* Is win one of our frames? */
2309 f1
= x_any_window_to_frame (win
);
2312 /* If not, is it one of our scroll bars? */
2315 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2319 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2325 if (f1
== 0 && insist
)
2326 f1
= selected_frame
;
2330 int ignore1
, ignore2
;
2332 /* Ok, we found a frame. Store all the values. */
2334 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2336 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2342 XSETINT (*x
, win_x
);
2343 XSETINT (*y
, win_y
);
2344 *time
= last_mouse_movement_time
;
2352 /* Scroll bar support. */
2354 /* Given an X window ID, find the struct scroll_bar which manages it.
2355 This can be called in GC, so we have to make sure to strip off mark
2357 static struct scroll_bar
*
2358 x_window_to_scroll_bar (window_id
)
2361 Lisp_Object tail
, frame
;
2363 for (tail
= Vframe_list
;
2364 XGCTYPE (tail
) == Lisp_Cons
;
2365 tail
= XCONS (tail
)->cdr
)
2367 Lisp_Object frame
, bar
, condemned
;
2369 frame
= XCONS (tail
)->car
;
2370 /* All elements of Vframe_list should be frames. */
2371 if (! GC_FRAMEP (frame
))
2374 /* Scan this frame's scroll bar list for a scroll bar with the
2376 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2377 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2378 /* This trick allows us to search both the ordinary and
2379 condemned scroll bar lists with one loop. */
2380 ! GC_NILP (bar
) || (bar
= condemned
,
2383 bar
= XSCROLL_BAR (bar
)->next
)
2384 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2385 return XSCROLL_BAR (bar
);
2391 /* Open a new X window to serve as a scroll bar, and return the
2392 scroll bar vector for it. */
2393 static struct scroll_bar
*
2394 x_scroll_bar_create (window
, top
, left
, width
, height
)
2395 struct window
*window
;
2396 int top
, left
, width
, height
;
2398 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2399 struct scroll_bar
*bar
2400 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2405 XSetWindowAttributes a
;
2407 a
.background_pixel
= f
->display
.x
->background_pixel
;
2408 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2409 | ButtonMotionMask
| PointerMotionHintMask
2411 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2413 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2418 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2419 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2420 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2421 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2422 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2423 sb_widget
= XtCreateManagedWidget ("box",
2425 f
->display
.x
->edit_widget
, al
, ac
);
2426 SET_SCROLL_BAR_X_WINDOW
2427 (bar
, sb_widget
->core
.window
);
2429 SET_SCROLL_BAR_X_WINDOW
2431 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2433 /* Position and size of scroll bar. */
2434 left
, top
, width
, height
,
2436 /* Border width, depth, class, and visual. */
2437 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2443 XSETWINDOW (bar
->window
, window
);
2444 XSETINT (bar
->top
, top
);
2445 XSETINT (bar
->left
, left
);
2446 XSETINT (bar
->width
, width
);
2447 XSETINT (bar
->height
, height
);
2448 XSETINT (bar
->start
, 0);
2449 XSETINT (bar
->end
, 0);
2450 bar
->dragging
= Qnil
;
2452 /* Add bar to its frame's list of scroll bars. */
2453 bar
->next
= FRAME_SCROLL_BARS (f
);
2455 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2456 if (! NILP (bar
->next
))
2457 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2459 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2466 /* Draw BAR's handle in the proper position.
2467 If the handle is already drawn from START to END, don't bother
2468 redrawing it, unless REBUILD is non-zero; in that case, always
2469 redraw it. (REBUILD is handy for drawing the handle after expose
2472 Normally, we want to constrain the start and end of the handle to
2473 fit inside its rectangle, but if the user is dragging the scroll bar
2474 handle, we want to let them drag it down all the way, so that the
2475 bar's top is as far down as it goes; otherwise, there's no way to
2476 move to the very end of the buffer. */
2478 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2479 struct scroll_bar
*bar
;
2483 int dragging
= ! NILP (bar
->dragging
);
2484 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2485 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2486 GC gc
= f
->display
.x
->normal_gc
;
2488 /* If the display is already accurate, do nothing. */
2490 && start
== XINT (bar
->start
)
2491 && end
== XINT (bar
->end
))
2497 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2498 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2499 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2501 /* Make sure the values are reasonable, and try to preserve
2502 the distance between start and end. */
2504 int length
= end
- start
;
2508 else if (start
> top_range
)
2510 end
= start
+ length
;
2514 else if (end
> top_range
&& ! dragging
)
2518 /* Store the adjusted setting in the scroll bar. */
2519 XSETINT (bar
->start
, start
);
2520 XSETINT (bar
->end
, end
);
2522 /* Clip the end position, just for display. */
2523 if (end
> top_range
)
2526 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2527 below top positions, to make sure the handle is always at least
2528 that many pixels tall. */
2529 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2531 /* Draw the empty space above the handle. Note that we can't clear
2532 zero-height areas; that means "clear to end of window." */
2534 XClearArea (FRAME_X_DISPLAY (f
), w
,
2536 /* x, y, width, height, and exposures. */
2537 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2538 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2539 inside_width
, start
,
2542 /* Draw the handle itself. */
2543 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2545 /* x, y, width, height */
2546 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2547 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2548 inside_width
, end
- start
);
2551 /* Draw the empty space below the handle. Note that we can't
2552 clear zero-height areas; that means "clear to end of window." */
2553 if (end
< inside_height
)
2554 XClearArea (FRAME_X_DISPLAY (f
), w
,
2556 /* x, y, width, height, and exposures. */
2557 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2558 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2559 inside_width
, inside_height
- end
,
2567 /* Move a scroll bar around on the screen, to accommodate changing
2568 window configurations. */
2570 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2571 struct scroll_bar
*bar
;
2572 int top
, left
, width
, height
;
2574 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2575 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2581 unsigned int mask
= 0;
2588 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2589 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2590 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2591 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2594 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2598 XSETINT (bar
->left
, left
);
2599 XSETINT (bar
->top
, top
);
2600 XSETINT (bar
->width
, width
);
2601 XSETINT (bar
->height
, height
);
2606 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2609 x_scroll_bar_remove (bar
)
2610 struct scroll_bar
*bar
;
2612 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2616 /* Destroy the window. */
2617 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2619 /* Disassociate this scroll bar from its window. */
2620 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2625 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2626 that we are displaying PORTION characters out of a total of WHOLE
2627 characters, starting at POSITION. If WINDOW has no scroll bar,
2630 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2631 struct window
*window
;
2632 int portion
, whole
, position
;
2634 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2635 int top
= XINT (window
->top
);
2636 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2637 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2639 /* Where should this scroll bar be, pixelwise? */
2640 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2641 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2643 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2644 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2645 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
2646 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2648 struct scroll_bar
*bar
;
2650 /* Does the scroll bar exist yet? */
2651 if (NILP (window
->vertical_scroll_bar
))
2652 bar
= x_scroll_bar_create (window
,
2653 pixel_top
, pixel_left
,
2654 pixel_width
, pixel_height
);
2657 /* It may just need to be moved and resized. */
2658 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2659 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2662 /* Set the scroll bar's current state, unless we're currently being
2664 if (NILP (bar
->dragging
))
2666 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2669 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2672 int start
= ((double) position
* top_range
) / whole
;
2673 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2675 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2679 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2683 /* The following three hooks are used when we're doing a thorough
2684 redisplay of the frame. We don't explicitly know which scroll bars
2685 are going to be deleted, because keeping track of when windows go
2686 away is a real pain - "Can you say set-window-configuration, boys
2687 and girls?" Instead, we just assert at the beginning of redisplay
2688 that *all* scroll bars are to be removed, and then save a scroll bar
2689 from the fiery pit when we actually redisplay its window. */
2691 /* Arrange for all scroll bars on FRAME to be removed at the next call
2692 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2693 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2695 XTcondemn_scroll_bars (frame
)
2698 /* The condemned list should be empty at this point; if it's not,
2699 then the rest of Emacs isn't using the condemn/redeem/judge
2700 protocol correctly. */
2701 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2704 /* Move them all to the "condemned" list. */
2705 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2706 FRAME_SCROLL_BARS (frame
) = Qnil
;
2709 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2710 Note that WINDOW isn't necessarily condemned at all. */
2712 XTredeem_scroll_bar (window
)
2713 struct window
*window
;
2715 struct scroll_bar
*bar
;
2717 /* We can't redeem this window's scroll bar if it doesn't have one. */
2718 if (NILP (window
->vertical_scroll_bar
))
2721 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2723 /* Unlink it from the condemned list. */
2725 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2727 if (NILP (bar
->prev
))
2729 /* If the prev pointer is nil, it must be the first in one of
2731 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2732 /* It's not condemned. Everything's fine. */
2734 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2735 window
->vertical_scroll_bar
))
2736 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2738 /* If its prev pointer is nil, it must be at the front of
2739 one or the other! */
2743 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2745 if (! NILP (bar
->next
))
2746 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2748 bar
->next
= FRAME_SCROLL_BARS (f
);
2750 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2751 if (! NILP (bar
->next
))
2752 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2756 /* Remove all scroll bars on FRAME that haven't been saved since the
2757 last call to `*condemn_scroll_bars_hook'. */
2759 XTjudge_scroll_bars (f
)
2762 Lisp_Object bar
, next
;
2764 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2766 /* Clear out the condemned list now so we won't try to process any
2767 more events on the hapless scroll bars. */
2768 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2770 for (; ! NILP (bar
); bar
= next
)
2772 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2774 x_scroll_bar_remove (b
);
2777 b
->next
= b
->prev
= Qnil
;
2780 /* Now there should be no references to the condemned scroll bars,
2781 and they should get garbage-collected. */
2785 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2787 This may be called from a signal handler, so we have to ignore GC
2790 x_scroll_bar_expose (bar
, event
)
2791 struct scroll_bar
*bar
;
2794 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2795 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2796 GC gc
= f
->display
.x
->normal_gc
;
2800 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2802 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2803 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2805 /* x, y, width, height */
2806 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2811 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2812 is set to something other than no_event, it is enqueued.
2814 This may be called from a signal handler, so we have to ignore GC
2817 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2818 struct scroll_bar
*bar
;
2820 struct input_event
*emacs_event
;
2822 if (! GC_WINDOWP (bar
->window
))
2825 emacs_event
->kind
= scroll_bar_click
;
2826 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2827 emacs_event
->modifiers
2828 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2829 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2830 event
->xbutton
.state
)
2831 | (event
->type
== ButtonRelease
2834 emacs_event
->frame_or_window
= bar
->window
;
2835 emacs_event
->timestamp
= event
->xbutton
.time
;
2838 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2840 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2841 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2844 if (y
> top_range
) y
= top_range
;
2846 if (y
< XINT (bar
->start
))
2847 emacs_event
->part
= scroll_bar_above_handle
;
2848 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2849 emacs_event
->part
= scroll_bar_handle
;
2851 emacs_event
->part
= scroll_bar_below_handle
;
2853 /* Just because the user has clicked on the handle doesn't mean
2854 they want to drag it. Lisp code needs to be able to decide
2855 whether or not we're dragging. */
2857 /* If the user has just clicked on the handle, record where they're
2859 if (event
->type
== ButtonPress
2860 && emacs_event
->part
== scroll_bar_handle
)
2861 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2864 /* If the user has released the handle, set it to its final position. */
2865 if (event
->type
== ButtonRelease
2866 && ! NILP (bar
->dragging
))
2868 int new_start
= y
- XINT (bar
->dragging
);
2869 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2871 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2872 bar
->dragging
= Qnil
;
2875 /* Same deal here as the other #if 0. */
2877 /* Clicks on the handle are always reported as occurring at the top of
2879 if (emacs_event
->part
== scroll_bar_handle
)
2880 emacs_event
->x
= bar
->start
;
2882 XSETINT (emacs_event
->x
, y
);
2884 XSETINT (emacs_event
->x
, y
);
2887 XSETINT (emacs_event
->y
, top_range
);
2891 /* Handle some mouse motion while someone is dragging the scroll bar.
2893 This may be called from a signal handler, so we have to ignore GC
2896 x_scroll_bar_note_movement (bar
, event
)
2897 struct scroll_bar
*bar
;
2900 last_mouse_movement_time
= event
->xmotion
.time
;
2903 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2905 /* If we're dragging the bar, display it. */
2906 if (! GC_NILP (bar
->dragging
))
2908 /* Where should the handle be now? */
2909 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2911 if (new_start
!= XINT (bar
->start
))
2913 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2915 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2919 /* Call XQueryPointer so we'll get an event the next time the mouse
2920 moves and we can see *still* on the same position. */
2923 Window dummy_window
;
2925 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2926 &dummy_window
, &dummy_window
,
2927 &dummy
, &dummy
, &dummy
, &dummy
,
2928 (unsigned int *) &dummy
);
2932 /* Return information to the user about the current position of the mouse
2933 on the scroll bar. */
2935 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2937 Lisp_Object
*bar_window
;
2938 enum scroll_bar_part
*part
;
2940 unsigned long *time
;
2942 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2943 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2944 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2946 Window dummy_window
;
2948 unsigned int dummy_mask
;
2952 /* Get the mouse's position relative to the scroll bar window, and
2954 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
2956 /* Root, child, root x and root y. */
2957 &dummy_window
, &dummy_window
,
2958 &dummy_coord
, &dummy_coord
,
2960 /* Position relative to scroll bar. */
2963 /* Mouse buttons and modifier keys. */
2969 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2971 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2973 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2975 if (! NILP (bar
->dragging
))
2976 win_y
-= XINT (bar
->dragging
);
2980 if (win_y
> top_range
)
2984 *bar_window
= bar
->window
;
2986 if (! NILP (bar
->dragging
))
2987 *part
= scroll_bar_handle
;
2988 else if (win_y
< XINT (bar
->start
))
2989 *part
= scroll_bar_above_handle
;
2990 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2991 *part
= scroll_bar_handle
;
2993 *part
= scroll_bar_below_handle
;
2995 XSETINT (*x
, win_y
);
2996 XSETINT (*y
, top_range
);
2999 last_mouse_scroll_bar
= Qnil
;
3002 *time
= last_mouse_movement_time
;
3008 /* The screen has been cleared so we may have changed foreground or
3009 background colors, and the scroll bars may need to be redrawn.
3010 Clear out the scroll bars, and ask for expose events, so we can
3013 x_scroll_bar_clear (f
)
3018 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3019 bar
= XSCROLL_BAR (bar
)->next
)
3020 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3024 /* This processes Expose events from the menubar specific X event
3025 loop in menubar.c. This allows to redisplay the frame if necessary
3026 when handling menubar or popup items. */
3029 process_expose_from_menu (event
)
3036 f
= x_window_to_frame (event
.xexpose
.window
);
3039 if (f
->async_visible
== 0)
3041 f
->async_visible
= 1;
3042 f
->async_iconified
= 0;
3043 SET_FRAME_GARBAGED (f
);
3047 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3048 event
.xexpose
.x
, event
.xexpose
.y
,
3049 event
.xexpose
.width
, event
.xexpose
.height
);
3054 struct scroll_bar
*bar
3055 = x_window_to_scroll_bar (event
.xexpose
.window
);
3058 x_scroll_bar_expose (bar
, &event
);
3064 /* Define a queue to save up SelectionRequest events for later handling. */
3066 struct selection_event_queue
3069 struct selection_event_queue
*next
;
3072 static struct selection_event_queue
*queue
;
3074 /* Nonzero means queue up certain events--don't process them yet. */
3075 static int x_queue_selection_requests
;
3077 /* Queue up an X event *EVENT, to be processed later. */
3080 x_queue_event (f
, event
)
3084 struct selection_event_queue
*queue_tmp
3085 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3087 if (queue_tmp
!= NULL
)
3089 queue_tmp
->event
= *event
;
3090 queue_tmp
->next
= queue
;
3095 /* Take all the queued events and put them back
3096 so that they get processed afresh. */
3099 x_unqueue_events (display
)
3102 while (queue
!= NULL
)
3104 struct selection_event_queue
*queue_tmp
= queue
;
3105 XPutBackEvent (display
, &queue_tmp
->event
);
3106 queue
= queue_tmp
->next
;
3107 free ((char *)queue_tmp
);
3111 /* Start queuing SelectionRequest events. */
3114 x_start_queuing_selection_requests (display
)
3117 x_queue_selection_requests
++;
3120 /* Stop queuing SelectionRequest events. */
3123 x_stop_queuing_selection_requests (display
)
3126 x_queue_selection_requests
--;
3127 x_unqueue_events (display
);
3130 /* The main X event-reading loop - XTread_socket. */
3132 /* Timestamp of enter window event. This is only used by XTread_socket,
3133 but we have to put it out here, since static variables within functions
3134 sometimes don't work. */
3135 static Time enter_timestamp
;
3137 /* This holds the state XLookupString needs to implement dead keys
3138 and other tricks known as "compose processing". _X Window System_
3139 says that a portable program can't use this, but Stephen Gildea assures
3140 me that letting the compiler initialize it to zeros will work okay.
3142 This must be defined outside of XTread_socket, for the same reasons
3143 given for enter_timestamp, above. */
3144 static XComposeStatus compose_status
;
3146 /* Record the last 100 characters stored
3147 to help debug the loss-of-chars-during-GC problem. */
3149 short temp_buffer
[100];
3151 /* Set this to nonzero to fake an "X I/O error"
3152 on a particular display. */
3153 struct x_display_info
*XTread_socket_fake_io_error
;
3155 /* Read events coming from the X server.
3156 This routine is called by the SIGIO handler.
3157 We return as soon as there are no more events to be read.
3159 Events representing keys are stored in buffer BUFP,
3160 which can hold up to NUMCHARS characters.
3161 We return the number of characters stored into the buffer,
3162 thus pretending to be `read'.
3164 WAITP is nonzero if we should block until input arrives.
3165 EXPECTED is nonzero if the caller knows input is available. */
3168 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3170 register struct input_event
*bufp
;
3171 register int numchars
;
3178 int items_pending
; /* How many items are in the X queue. */
3181 int event_found
= 0;
3184 struct x_display_info
*dpyinfo
;
3186 if (interrupt_input_blocked
)
3188 interrupt_input_pending
= 1;
3192 interrupt_input_pending
= 0;
3195 /* So people can tell when we have read the available input. */
3196 input_signal_count
++;
3199 abort (); /* Don't think this happens. */
3201 /* Find the display we are supposed to read input for.
3202 It's the one communicating on descriptor SD. */
3203 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3205 #if 0 /* This ought to be unnecessary; let's verify it. */
3207 /* If available, Xlib uses FIOSNBIO to make the socket
3208 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3209 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3210 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3211 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3212 #endif /* ! defined (FIOSNBIO) */
3215 #if 0 /* This code can't be made to work, with multiple displays,
3216 and appears not to be used on any system any more.
3217 Also keyboard.c doesn't turn O_NDELAY on and off
3218 for X connections. */
3221 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3223 extern int read_alarm_should_throw
;
3224 read_alarm_should_throw
= 1;
3225 XPeekEvent (dpyinfo
->display
, &event
);
3226 read_alarm_should_throw
= 0;
3228 #endif /* HAVE_SELECT */
3232 /* For debugging, this gives a way to fake an I/O error. */
3233 if (dpyinfo
== XTread_socket_fake_io_error
)
3235 XTread_socket_fake_io_error
= 0;
3236 x_io_error_quitter (dpyinfo
->display
);
3239 while (XPending (dpyinfo
->display
) != 0)
3241 XNextEvent (dpyinfo
->display
, &event
);
3248 if (event
.xclient
.message_type
3249 == dpyinfo
->Xatom_wm_protocols
3250 && event
.xclient
.format
== 32)
3252 if (event
.xclient
.data
.l
[0]
3253 == dpyinfo
->Xatom_wm_take_focus
)
3255 f
= x_window_to_frame (event
.xclient
.window
);
3256 /* Since we set WM_TAKE_FOCUS, we must call
3257 XSetInputFocus explicitly. But not if f is null,
3258 since that might be an event for a deleted frame. */
3260 XSetInputFocus (event
.xclient
.display
,
3261 event
.xclient
.window
,
3262 RevertToPointerRoot
,
3263 event
.xclient
.data
.l
[1]);
3264 /* Not certain about handling scroll bars here */
3266 else if (event
.xclient
.data
.l
[0]
3267 == dpyinfo
->Xatom_wm_save_yourself
)
3269 /* Save state modify the WM_COMMAND property to
3270 something which can reinstate us. This notifies
3271 the session manager, who's looking for such a
3272 PropertyNotify. Can restart processing when
3273 a keyboard or mouse event arrives. */
3276 f
= x_top_window_to_frame (event
.xclient
.window
);
3278 /* This is just so we only give real data once
3279 for a single Emacs process. */
3280 if (f
== selected_frame
)
3281 XSetCommand (FRAME_X_DISPLAY (f
),
3282 event
.xclient
.window
,
3283 initial_argv
, initial_argc
);
3285 XSetCommand (FRAME_X_DISPLAY (f
),
3286 event
.xclient
.window
,
3290 else if (event
.xclient
.data
.l
[0]
3291 == dpyinfo
->Xatom_wm_delete_window
)
3293 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3300 bufp
->kind
= delete_window_event
;
3301 XSETFRAME (bufp
->frame_or_window
, f
);
3309 else if (event
.xclient
.message_type
3310 == dpyinfo
->Xatom_wm_configure_denied
)
3313 else if (event
.xclient
.message_type
3314 == dpyinfo
->Xatom_wm_window_moved
)
3317 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3319 new_x
= event
.xclient
.data
.s
[0];
3320 new_y
= event
.xclient
.data
.s
[1];
3324 f
->display
.x
->left_pos
= new_x
;
3325 f
->display
.x
->top_pos
= new_y
;
3328 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3329 else if (event
.xclient
.message_type
3330 == dpyinfo
->Xatom_editres
)
3332 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3333 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3335 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3339 case SelectionNotify
:
3340 #ifdef USE_X_TOOLKIT
3341 if (! x_window_to_frame (event
.xselection
.requestor
))
3343 #endif /* not USE_X_TOOLKIT */
3344 x_handle_selection_notify (&event
);
3347 case SelectionClear
: /* Someone has grabbed ownership. */
3348 #ifdef USE_X_TOOLKIT
3349 if (! x_window_to_frame (event
.xselectionclear
.window
))
3351 #endif /* USE_X_TOOLKIT */
3353 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3358 bufp
->kind
= selection_clear_event
;
3359 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3360 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3361 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3369 case SelectionRequest
: /* Someone wants our selection. */
3370 #ifdef USE_X_TOOLKIT
3371 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3373 #endif /* USE_X_TOOLKIT */
3374 if (x_queue_selection_requests
)
3375 x_queue_event (x_window_to_frame (event
.xselectionrequest
.owner
),
3379 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3384 bufp
->kind
= selection_request_event
;
3385 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3386 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3387 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3388 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3389 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3390 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3398 case PropertyNotify
:
3399 #ifdef USE_X_TOOLKIT
3400 if (!x_any_window_to_frame (event
.xproperty
.window
))
3402 #endif /* not USE_X_TOOLKIT */
3403 x_handle_property_notify (&event
);
3406 case ReparentNotify
:
3407 f
= x_top_window_to_frame (event
.xreparent
.window
);
3411 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3412 x_real_positions (f
, &x
, &y
);
3413 f
->display
.x
->left_pos
= x
;
3414 f
->display
.x
->top_pos
= y
;
3419 f
= x_window_to_frame (event
.xexpose
.window
);
3422 if (f
->async_visible
== 0)
3424 f
->async_visible
= 1;
3425 f
->async_iconified
= 0;
3426 SET_FRAME_GARBAGED (f
);
3429 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3430 event
.xexpose
.x
, event
.xexpose
.y
,
3431 event
.xexpose
.width
, event
.xexpose
.height
);
3435 struct scroll_bar
*bar
3436 = x_window_to_scroll_bar (event
.xexpose
.window
);
3439 x_scroll_bar_expose (bar
, &event
);
3440 #ifdef USE_X_TOOLKIT
3443 #endif /* USE_X_TOOLKIT */
3447 case GraphicsExpose
: /* This occurs when an XCopyArea's
3448 source area was obscured or not
3450 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3454 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3455 event
.xgraphicsexpose
.width
,
3456 event
.xgraphicsexpose
.height
);
3458 #ifdef USE_X_TOOLKIT
3461 #endif /* USE_X_TOOLKIT */
3464 case NoExpose
: /* This occurs when an XCopyArea's
3465 source area was completely
3470 f
= x_any_window_to_frame (event
.xunmap
.window
);
3471 if (f
) /* F may no longer exist if
3472 the frame was deleted. */
3474 /* While a frame is unmapped, display generation is
3475 disabled; you don't want to spend time updating a
3476 display that won't ever be seen. */
3477 f
->async_visible
= 0;
3478 /* We can't distinguish, from the event, whether the window
3479 has become iconified or invisible. So assume, if it
3480 was previously visible, than now it is iconified.
3481 We depend on x_make_frame_invisible to mark it iconified. */
3482 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3483 f
->async_iconified
= 1;
3485 bufp
->kind
= iconify_event
;
3486 XSETFRAME (bufp
->frame_or_window
, f
);
3491 #ifdef USE_X_TOOLKIT
3493 #endif /* USE_X_TOOLKIT */
3497 /* We use x_top_window_to_frame because map events can come
3498 for subwindows and they don't mean that the frame is visible. */
3499 f
= x_top_window_to_frame (event
.xmap
.window
);
3502 f
->async_visible
= 1;
3503 f
->async_iconified
= 0;
3505 /* wait_reading_process_input will notice this and update
3506 the frame's display structures. */
3507 SET_FRAME_GARBAGED (f
);
3509 bufp
->kind
= deiconify_event
;
3510 XSETFRAME (bufp
->frame_or_window
, f
);
3515 #ifdef USE_X_TOOLKIT
3517 #endif /* USE_X_TOOLKIT */
3520 /* Turn off processing if we become fully obscured. */
3521 case VisibilityNotify
:
3525 f
= x_any_window_to_frame (event
.xkey
.window
);
3529 KeySym keysym
, orig_keysym
;
3530 /* al%imercury@uunet.uu.net says that making this 81 instead of
3531 80 fixed a bug whereby meta chars made his Emacs hang. */
3532 unsigned char copy_buffer
[81];
3536 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3537 extra_keyboard_modifiers
);
3538 modifiers
= event
.xkey
.state
;
3540 /* This will have to go some day... */
3542 /* make_lispy_event turns chars into control chars.
3543 Don't do it here because XLookupString is too eager. */
3544 event
.xkey
.state
&= ~ControlMask
;
3545 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3546 80, &keysym
, &compose_status
);
3548 orig_keysym
= keysym
;
3552 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3553 || keysym
== XK_Delete
3554 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3555 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3557 /* This recognizes the "extended function keys".
3558 It seems there's no cleaner way.
3559 Test IsModifierKey to avoid handling mode_switch
3561 || ((unsigned) (keysym
) >= XK_Select
3562 && (unsigned)(keysym
) < XK_KP_Space
)
3564 #ifdef XK_dead_circumflex
3565 || orig_keysym
== XK_dead_circumflex
3567 #ifdef XK_dead_grave
3568 || orig_keysym
== XK_dead_grave
3570 #ifdef XK_dead_tilde
3571 || orig_keysym
== XK_dead_tilde
3573 #ifdef XK_dead_diaeresis
3574 || orig_keysym
== XK_dead_diaeresis
3576 #ifdef XK_dead_macron
3577 || orig_keysym
== XK_dead_macron
3579 #ifdef XK_dead_degree
3580 || orig_keysym
== XK_dead_degree
3582 #ifdef XK_dead_acute
3583 || orig_keysym
== XK_dead_acute
3585 #ifdef XK_dead_cedilla
3586 || orig_keysym
== XK_dead_cedilla
3588 #ifdef XK_dead_breve
3589 || orig_keysym
== XK_dead_breve
3591 #ifdef XK_dead_ogonek
3592 || orig_keysym
== XK_dead_ogonek
3594 #ifdef XK_dead_caron
3595 || orig_keysym
== XK_dead_caron
3597 #ifdef XK_dead_doubleacute
3598 || orig_keysym
== XK_dead_doubleacute
3600 #ifdef XK_dead_abovedot
3601 || orig_keysym
== XK_dead_abovedot
3603 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3604 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3605 /* Any "vendor-specific" key is ok. */
3606 || (orig_keysym
& (1 << 28)))
3607 && ! (IsModifierKey (orig_keysym
)
3609 #ifdef XK_Mode_switch
3610 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3613 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3615 #endif /* not HAVE_X11R5 */
3618 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3620 temp_buffer
[temp_index
++] = keysym
;
3621 bufp
->kind
= non_ascii_keystroke
;
3622 bufp
->code
= keysym
;
3623 XSETFRAME (bufp
->frame_or_window
, f
);
3625 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3627 bufp
->timestamp
= event
.xkey
.time
;
3632 else if (numchars
> nbytes
)
3636 for (i
= 0; i
< nbytes
; i
++)
3638 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3640 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3641 bufp
->kind
= ascii_keystroke
;
3642 bufp
->code
= copy_buffer
[i
];
3643 XSETFRAME (bufp
->frame_or_window
, f
);
3645 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3647 bufp
->timestamp
= event
.xkey
.time
;
3662 /* Here's a possible interpretation of the whole
3663 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3664 FocusIn event, you have to get a FocusOut event before you
3665 relinquish the focus. If you haven't received a FocusIn event,
3666 then a mere LeaveNotify is enough to free you. */
3669 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3671 if (event
.xcrossing
.focus
) /* Entered Window */
3673 /* Avoid nasty pop/raise loops. */
3674 if (f
&& (!(f
->auto_raise
)
3676 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3678 x_new_focus_frame (f
);
3679 enter_timestamp
= event
.xcrossing
.time
;
3682 else if (f
== x_focus_frame
)
3683 x_new_focus_frame (0);
3684 /* EnterNotify counts as mouse movement,
3685 so update things that depend on mouse position. */
3687 note_mouse_movement (f
, &event
.xmotion
);
3688 #ifdef USE_X_TOOLKIT
3690 #endif /* USE_X_TOOLKIT */
3694 f
= x_any_window_to_frame (event
.xfocus
.window
);
3695 if (event
.xfocus
.detail
!= NotifyPointer
)
3696 x_focus_event_frame
= f
;
3698 x_new_focus_frame (f
);
3699 #ifdef USE_X_TOOLKIT
3701 #endif /* USE_X_TOOLKIT */
3706 f
= x_top_window_to_frame (event
.xcrossing
.window
);
3709 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3710 /* If we move outside the frame,
3711 then we're certainly no longer on any text in the frame. */
3712 clear_mouse_face (dpyinfo
);
3714 if (event
.xcrossing
.focus
)
3718 if (f
== x_focus_event_frame
)
3719 x_focus_event_frame
= 0;
3720 if (f
== x_focus_frame
)
3721 x_new_focus_frame (0);
3724 #ifdef USE_X_TOOLKIT
3726 #endif /* USE_X_TOOLKIT */
3730 f
= x_any_window_to_frame (event
.xfocus
.window
);
3731 if (event
.xfocus
.detail
!= NotifyPointer
3732 && f
== x_focus_event_frame
)
3733 x_focus_event_frame
= 0;
3734 if (f
&& f
== x_focus_frame
)
3735 x_new_focus_frame (0);
3736 #ifdef USE_X_TOOLKIT
3738 #endif /* USE_X_TOOLKIT */
3743 if (dpyinfo
->grabbed
&& last_mouse_frame
3744 && FRAME_LIVE_P (last_mouse_frame
))
3745 f
= last_mouse_frame
;
3747 f
= x_window_to_frame (event
.xmotion
.window
);
3749 note_mouse_movement (f
, &event
.xmotion
);
3752 struct scroll_bar
*bar
3753 = x_window_to_scroll_bar (event
.xmotion
.window
);
3756 x_scroll_bar_note_movement (bar
, &event
);
3758 /* If we move outside the frame,
3759 then we're certainly no longer on any text in the frame. */
3760 clear_mouse_face (dpyinfo
);
3763 #if 0 /* This should be unnecessary, since the toolkit has no use
3764 for motion events that happen outside of the menu event loop,
3765 and it seems to cause the bug that mouse events stop coming
3767 #ifdef USE_X_TOOLKIT
3769 #endif /* USE_X_TOOLKIT */
3773 case ConfigureNotify
:
3774 f
= x_any_window_to_frame (event
.xconfigure
.window
);
3775 #ifdef USE_X_TOOLKIT
3778 && ! event
.xconfigure
.send_event
3780 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
3785 /* Find the position of the outside upper-left corner of
3786 the window, in the root coordinate system. Don't
3787 refer to the parent window here; we may be processing
3788 this event after the window manager has changed our
3789 parent, but before we have reached the ReparentNotify. */
3790 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3792 /* From-window, to-window. */
3793 XtWindow (f
->display
.x
->widget
),
3794 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3796 /* From-position, to-position. */
3797 -event
.xconfigure
.border_width
,
3798 -event
.xconfigure
.border_width
,
3803 event
.xconfigure
.x
= win_x
;
3804 event
.xconfigure
.y
= win_y
;
3806 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3807 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3808 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3809 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3811 /* What we have now is the position of Emacs's own window.
3812 Convert that to the position of the window manager window. */
3815 x_real_positions (f
, &x
, &y
);
3816 f
->display
.x
->left_pos
= x
;
3817 f
->display
.x
->top_pos
= y
;
3821 #else /* not USE_X_TOOLKIT */
3824 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3825 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3827 /* Even if the number of character rows and columns has
3828 not changed, the font size may have changed, so we need
3829 to check the pixel dimensions as well. */
3830 if (columns
!= f
->width
3831 || rows
!= f
->height
3832 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3833 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3835 change_frame_size (f
, rows
, columns
, 0, 1);
3836 SET_FRAME_GARBAGED (f
);
3839 if (! event
.xconfigure
.send_event
)
3844 /* Find the position of the outside upper-left corner of
3845 the window, in the root coordinate system. Don't
3846 refer to the parent window here; we may be processing
3847 this event after the window manager has changed our
3848 parent, but before we have reached the ReparentNotify. */
3849 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3851 /* From-window, to-window. */
3852 f
->display
.x
->window_desc
,
3853 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3855 /* From-position, to-position. */
3856 -event
.xconfigure
.border_width
,
3857 -event
.xconfigure
.border_width
,
3862 event
.xconfigure
.x
= win_x
;
3863 event
.xconfigure
.y
= win_y
;
3866 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3867 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3868 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3869 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3871 /* What we have now is the position of Emacs's own window.
3872 Convert that to the position of the window manager window. */
3875 x_real_positions (f
, &x
, &y
);
3876 f
->display
.x
->left_pos
= x
;
3877 f
->display
.x
->top_pos
= y
;
3878 if (y
!= event
.xconfigure
.y
)
3880 /* Since the WM decorations come below top_pos now,
3881 we must put them below top_pos in the future. */
3882 f
->display
.x
->win_gravity
= NorthWestGravity
;
3883 x_wm_set_size_hint (f
, 0, 0);
3887 #endif /* not USE_X_TOOLKIT */
3893 /* If we decide we want to generate an event to be seen
3894 by the rest of Emacs, we put it here. */
3895 struct input_event emacs_event
;
3896 emacs_event
.kind
= no_event
;
3898 bzero (&compose_status
, sizeof (compose_status
));
3900 if (dpyinfo
->grabbed
&& last_mouse_frame
3901 && FRAME_LIVE_P (last_mouse_frame
))
3902 f
= last_mouse_frame
;
3904 f
= x_window_to_frame (event
.xmotion
.window
);
3908 if (!x_focus_frame
|| (f
== x_focus_frame
))
3909 construct_mouse_click (&emacs_event
, &event
, f
);
3913 struct scroll_bar
*bar
3914 = x_window_to_scroll_bar (event
.xbutton
.window
);
3917 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3918 #ifdef USE_X_TOOLKIT
3921 /* Assume we have a menubar button press. A bad
3922 assumption should behave benignly. */
3923 popup_get_selection (&event
);
3926 #endif /* USE_X_TOOLKIT */
3929 if (event
.type
== ButtonPress
)
3931 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
3932 last_mouse_frame
= f
;
3936 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
3939 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3941 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3947 #ifdef USE_X_TOOLKIT
3949 #endif /* USE_X_TOOLKIT */
3953 case CirculateNotify
:
3955 case CirculateRequest
:
3959 /* Someone has changed the keyboard mapping - update the
3961 switch (event
.xmapping
.request
)
3963 case MappingModifier
:
3964 x_find_modifier_meanings (dpyinfo
);
3965 /* This is meant to fall through. */
3966 case MappingKeyboard
:
3967 XRefreshKeyboardMapping (&event
.xmapping
);
3969 #ifdef USE_X_TOOLKIT
3971 #endif /* USE_X_TOOLKIT */
3975 #ifdef USE_X_TOOLKIT
3978 XtDispatchEvent (&event
);
3980 #endif /* USE_X_TOOLKIT */
3986 /* On some systems, an X bug causes Emacs to get no more events
3987 when the window is destroyed. Detect that. (1994.) */
3990 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
3991 One XNOOP in 100 loops will make Emacs terminate.
3992 B. Bretthauer, 1994 */
3994 if (x_noop_count
>= 100)
3997 /* Use the first display in the list. Why not? */
3998 XNoOp (x_display_list
->display
);
4002 /* If the focus was just given to an autoraising frame,
4004 /* ??? This ought to be able to handle more than one such frame. */
4005 if (pending_autoraise_frame
)
4007 x_raise_frame (pending_autoraise_frame
);
4008 pending_autoraise_frame
= 0;
4015 /* Drawing the cursor. */
4018 /* Draw a hollow box cursor. Don't change the inside of the box. */
4024 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
4025 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
4026 int width
= FONT_WIDTH (f
->display
.x
->font
);
4027 int height
= f
->display
.x
->line_height
;
4029 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4030 f
->display
.x
->cursor_gc
,
4031 left
, top
, width
- 1, height
- 1);
4034 /* Clear the cursor of frame F to background color,
4035 and mark the cursor as not shown.
4036 This is used when the text where the cursor is
4037 is about to be rewritten. */
4045 if (! FRAME_VISIBLE_P (f
)
4046 || f
->phys_cursor_x
< 0)
4049 x_display_cursor (f
, 0);
4050 f
->phys_cursor_x
= -1;
4053 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4054 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4058 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4065 CHAR_TO_PIXEL_COL (f
, column
),
4066 CHAR_TO_PIXEL_ROW (f
, row
),
4067 &glyph
, 1, highlight
, 0);
4071 x_display_bar_cursor (f
, on
)
4075 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4077 /* This is pointless on invisible frames, and dangerous on garbaged
4078 frames; in the latter case, the frame may be in the midst of
4079 changing its size, and curs_x and curs_y may be off the frame. */
4080 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4083 if (! on
&& f
->phys_cursor_x
< 0)
4086 /* If we're not updating, then we want to use the current frame's
4087 cursor position, not our local idea of where the cursor ought to be. */
4088 if (f
!= updating_frame
)
4090 curs_x
= FRAME_CURSOR_X (f
);
4091 curs_y
= FRAME_CURSOR_Y (f
);
4094 /* If there is anything wrong with the current cursor state, remove it. */
4095 if (f
->phys_cursor_x
>= 0
4097 || f
->phys_cursor_x
!= curs_x
4098 || f
->phys_cursor_y
!= curs_y
4099 || f
->display
.x
->current_cursor
!= bar_cursor
))
4101 /* Erase the cursor by redrawing the character underneath it. */
4102 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4103 f
->phys_cursor_glyph
,
4104 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4105 f
->phys_cursor_x
= -1;
4108 /* If we now need a cursor in the new place or in the new form, do it so. */
4110 && (f
->phys_cursor_x
< 0
4111 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4113 f
->phys_cursor_glyph
4114 = ((current_glyphs
->enable
[curs_y
]
4115 && curs_x
< current_glyphs
->used
[curs_y
])
4116 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4118 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4119 f
->display
.x
->cursor_gc
,
4120 CHAR_TO_PIXEL_COL (f
, curs_x
),
4121 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4122 max (f
->display
.x
->cursor_width
, 1),
4123 f
->display
.x
->line_height
);
4125 f
->phys_cursor_x
= curs_x
;
4126 f
->phys_cursor_y
= curs_y
;
4128 f
->display
.x
->current_cursor
= bar_cursor
;
4131 if (updating_frame
!= f
)
4132 XFlush (FRAME_X_DISPLAY (f
));
4136 /* Turn the displayed cursor of frame F on or off according to ON.
4137 If ON is nonzero, where to put the cursor is specified
4138 by F->cursor_x and F->cursor_y. */
4141 x_display_box_cursor (f
, on
)
4145 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4147 /* This is pointless on invisible frames, and dangerous on garbaged
4148 frames; in the latter case, the frame may be in the midst of
4149 changing its size, and curs_x and curs_y may be off the frame. */
4150 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4153 /* If cursor is off and we want it off, return quickly. */
4154 if (!on
&& f
->phys_cursor_x
< 0)
4157 /* If we're not updating, then we want to use the current frame's
4158 cursor position, not our local idea of where the cursor ought to be. */
4159 if (f
!= updating_frame
)
4161 curs_x
= FRAME_CURSOR_X (f
);
4162 curs_y
= FRAME_CURSOR_Y (f
);
4165 /* If cursor is currently being shown and we don't want it to be
4166 or it is in the wrong place,
4167 or we want a hollow box and it's not so, (pout!)
4169 if (f
->phys_cursor_x
>= 0
4171 || f
->phys_cursor_x
!= curs_x
4172 || f
->phys_cursor_y
!= curs_y
4173 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4174 && (f
!= x_highlight_frame
))))
4176 int mouse_face_here
= 0;
4177 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4179 /* If the cursor is in the mouse face area, redisplay that when
4180 we clear the cursor. */
4181 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4183 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4184 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4185 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4187 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4188 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4189 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4190 /* Don't redraw the cursor's spot in mouse face
4191 if it is at the end of a line (on a newline).
4192 The cursor appears there, but mouse highlighting does not. */
4193 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4194 mouse_face_here
= 1;
4196 /* If the font is not as tall as a whole line,
4197 we must explicitly clear the line's whole height. */
4198 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4199 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4200 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4201 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4202 FONT_WIDTH (f
->display
.x
->font
),
4203 f
->display
.x
->line_height
, False
);
4204 /* Erase the cursor by redrawing the character underneath it. */
4205 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4206 f
->phys_cursor_glyph
,
4209 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4210 f
->phys_cursor_x
= -1;
4213 /* If we want to show a cursor,
4214 or we want a box cursor and it's not so,
4215 write it in the right place. */
4217 && (f
->phys_cursor_x
< 0
4218 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4219 && f
== x_highlight_frame
)))
4221 f
->phys_cursor_glyph
4222 = ((current_glyphs
->enable
[curs_y
]
4223 && curs_x
< current_glyphs
->used
[curs_y
])
4224 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4226 if (f
!= x_highlight_frame
)
4229 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4233 x_draw_single_glyph (f
, curs_y
, curs_x
,
4234 f
->phys_cursor_glyph
, 2);
4235 f
->display
.x
->current_cursor
= filled_box_cursor
;
4238 f
->phys_cursor_x
= curs_x
;
4239 f
->phys_cursor_y
= curs_y
;
4242 if (updating_frame
!= f
)
4243 XFlush (FRAME_X_DISPLAY (f
));
4246 x_display_cursor (f
, on
)
4252 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4253 x_display_box_cursor (f
, on
);
4254 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4255 x_display_bar_cursor (f
, on
);
4257 /* Those are the only two we have implemented! */
4265 /* Refresh bitmap kitchen sink icon for frame F
4266 when we get an expose event for it. */
4271 /* Normally, the window manager handles this function. */
4274 /* Make the x-window of frame F use the gnu icon bitmap. */
4277 x_bitmap_icon (f
, file
)
4281 int mask
, bitmap_id
;
4284 if (FRAME_X_WINDOW (f
) == 0)
4287 /* Free up our existing icon bitmap if any. */
4288 if (f
->display
.x
->icon_bitmap
> 0)
4289 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4290 f
->display
.x
->icon_bitmap
= 0;
4293 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4296 /* Create the GNU bitmap if necessary. */
4297 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4298 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4299 = x_create_bitmap_from_data (f
, gnu_bits
,
4300 gnu_width
, gnu_height
);
4302 /* The first time we create the GNU bitmap,
4303 this increments the refcount one extra time.
4304 As a result, the GNU bitmap is never freed.
4305 That way, we don't have to worry about allocating it again. */
4306 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4308 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4311 x_wm_set_icon_pixmap (f
, bitmap_id
);
4312 f
->display
.x
->icon_bitmap
= bitmap_id
;
4318 /* Make the x-window of frame F use a rectangle with text. */
4321 x_text_icon (f
, icon_name
)
4325 if (FRAME_X_WINDOW (f
) == 0)
4329 f
->display
.x
->icon_label
= icon_name
;
4331 if (! f
->display
.x
->icon_label
)
4332 f
->display
.x
->icon_label
= " *emacs* ";
4335 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4336 (char *) f
->display
.x
->icon_label
);
4339 if (f
->display
.x
->icon_bitmap
> 0)
4340 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4341 f
->display
.x
->icon_bitmap
= 0;
4342 x_wm_set_icon_pixmap (f
, 0);
4347 /* Handling X errors. */
4349 /* Handle the loss of connection to display DISPLAY. */
4352 x_connection_closed (display
, error_message
)
4354 char *error_message
;
4356 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4357 Lisp_Object frame
, tail
;
4362 /* First delete frames whose minibuffers are on frames
4363 that are on the dead display. */
4364 FOR_EACH_FRAME (tail
, frame
)
4366 Lisp_Object minibuf_frame
;
4368 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4369 if (FRAME_X_P (XFRAME (frame
))
4370 && FRAME_X_P (XFRAME (minibuf_frame
))
4371 && ! EQ (frame
, minibuf_frame
)
4372 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4373 Fdelete_frame (frame
, Qt
);
4376 /* Now delete all remaining frames on the dead display.
4377 We are now sure none of these is used as the minibuffer
4378 for another frame that we need to delete. */
4379 FOR_EACH_FRAME (tail
, frame
)
4380 if (FRAME_X_P (XFRAME (frame
))
4381 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4382 Fdelete_frame (frame
, Qt
);
4384 x_delete_display (dpyinfo
);
4386 if (x_display_list
== 0)
4388 fprintf (stderr
, "%s", error_message
);
4389 shut_down_emacs (0, 0, Qnil
);
4393 /* Ordinary stack unwind doesn't deal with these. */
4395 sigunblock (sigmask (SIGIO
));
4397 sigunblock (sigmask (SIGALRM
));
4398 TOTALLY_UNBLOCK_INPUT
;
4400 error ("%s", error_message
);
4404 x_connection_signal (signalnum
) /* If we don't have an argument, */
4405 int signalnum
; /* some compilers complain in signal calls. */
4407 /* We really ought to close the connection to the display
4408 that actually failed.
4409 But do we actually get this signal ever with X11? */
4410 fprintf (stderr
, "X connection closed");
4411 shut_down_emacs (0, 0, Qnil
);
4415 /* This is the usual handler for X protocol errors.
4416 It kills all frames on the display that we got the error for.
4417 If that was the only one, it prints an error message and kills Emacs. */
4420 x_error_quitter (display
, error
)
4424 char buf
[256], buf1
[356];
4426 /* Note that there is no real way portable across R3/R4 to get the
4427 original error handler. */
4429 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4430 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4431 buf
, error
->request_code
);
4432 x_connection_closed (display
, buf1
);
4435 /* This is the handler for X IO errors, always.
4436 It kills all frames on the display that we lost touch with.
4437 If that was the only one, it prints an error message and kills Emacs. */
4440 x_io_error_quitter (display
)
4445 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4446 x_connection_closed (display
, buf
);
4449 /* A buffer for storing X error messages. */
4450 static char *x_caught_error_message
;
4451 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4453 /* An X error handler which stores the error message in
4454 x_caught_error_message. This is what's installed when
4455 x_catch_errors is in effect. */
4458 x_error_catcher (display
, error
)
4462 XGetErrorText (display
, error
->error_code
,
4463 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4467 /* Begin trapping X errors for display DPY. Actually we trap X errors
4468 for all displays, but DPY should be the display you are actually
4471 After calling this function, X protocol errors no longer cause
4472 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4474 Calling x_check_errors signals an Emacs error if an X error has
4475 occurred since the last call to x_catch_errors or x_check_errors.
4477 Calling x_uncatch_errors resumes the normal error handling. */
4479 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4482 x_catch_errors (dpy
)
4485 /* Make sure any errors from previous requests have been dealt with. */
4488 /* Set up the error buffer. */
4489 x_caught_error_message
4490 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4491 x_caught_error_message
[0] = '\0';
4493 /* Install our little error handler. */
4494 XSetErrorHandler (x_error_catcher
);
4497 /* If any X protocol errors have arrived since the last call to
4498 x_catch_errors or x_check_errors, signal an Emacs error using
4499 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4502 x_check_errors (dpy
, format
)
4506 /* Make sure to catch any errors incurred so far. */
4509 if (x_caught_error_message
[0])
4511 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4513 sprintf (buf
, format
, x_caught_error_message
);
4514 x_uncatch_errors (dpy
);
4519 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4522 x_had_errors_p (dpy
)
4525 /* Make sure to catch any errors incurred so far. */
4528 return x_caught_error_message
[0] != 0;
4531 /* Stop catching X protocol errors and let them make Emacs die. */
4534 x_uncatch_errors (dpy
)
4537 xfree (x_caught_error_message
);
4538 x_caught_error_message
= 0;
4539 XSetErrorHandler (x_error_quitter
);
4543 static unsigned int x_wire_count
;
4546 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4551 /* Changing the font of the frame. */
4553 /* Give frame F the font named FONTNAME as its default font, and
4554 return the full name of that font. FONTNAME may be a wildcard
4555 pattern; in that case, we choose some font that fits the pattern.
4556 The return value shows which font we chose. */
4559 x_new_font (f
, fontname
)
4561 register char *fontname
;
4564 int n_matching_fonts
;
4565 XFontStruct
*font_info
;
4568 /* Get a list of all the fonts that match this name. Once we
4569 have a list of matching fonts, we compare them against the fonts
4570 we already have by comparing font ids. */
4571 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4572 1024, &n_matching_fonts
);
4573 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4574 find any matches; font_names == 0 is the only clue. */
4576 n_matching_fonts
= 0;
4578 /* Don't just give up if n_matching_fonts is 0.
4579 Apparently there's a bug on Suns: XListFontsWithInfo can
4580 fail to find a font, but XLoadQueryFont may still find it. */
4582 /* See if we've already loaded a matching font. */
4583 already_loaded
= -1;
4584 if (n_matching_fonts
!= 0)
4588 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4589 for (j
= 0; j
< n_matching_fonts
; j
++)
4590 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4591 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4594 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4600 /* If we have, just return it from the table. */
4601 if (already_loaded
>= 0)
4602 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4603 /* Otherwise, load the font and add it to the table. */
4611 /* Try to find a character-cell font in the list. */
4613 /* A laudable goal, but this isn't how to do it. */
4614 for (i
= 0; i
< n_matching_fonts
; i
++)
4615 if (! font_info
[i
].per_char
)
4621 /* See comment above. */
4622 if (n_matching_fonts
!= 0)
4623 fontname
= font_names
[i
];
4625 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4628 /* Free the information from XListFonts. */
4629 if (n_matching_fonts
)
4630 XFreeFontNames (font_names
);
4634 /* Do we need to create the table? */
4635 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4637 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4638 FRAME_X_DISPLAY_INFO (f
)->font_table
4639 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4640 * sizeof (struct font_info
));
4642 /* Do we need to grow the table? */
4643 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4644 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4646 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4647 FRAME_X_DISPLAY_INFO (f
)->font_table
4648 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4649 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4650 * sizeof (struct font_info
)));
4653 /* Try to get the full name of FONT. Put it in full_name. */
4655 for (i
= 0; i
< font
->n_properties
; i
++)
4658 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4659 if (!strcmp (atom
, "FONT"))
4661 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4662 (Atom
) (font
->properties
[i
].card32
));
4666 /* Count the number of dashes in the "full name".
4667 If it is too few, this isn't really the font's full name,
4669 In X11R4, the fonts did not come with their canonical names
4687 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4688 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4689 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4691 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4693 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4694 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4695 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4698 fontname
= full_name
;
4701 /* Compute the scroll bar width in character columns. */
4702 if (f
->scroll_bar_pixel_width
> 0)
4704 int wid
= FONT_WIDTH (f
->display
.x
->font
);
4705 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4708 f
->scroll_bar_cols
= 2;
4710 /* Now make the frame display the given font. */
4711 if (FRAME_X_WINDOW (f
) != 0)
4713 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->normal_gc
,
4714 f
->display
.x
->font
->fid
);
4715 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->reverse_gc
,
4716 f
->display
.x
->font
->fid
);
4717 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->cursor_gc
,
4718 f
->display
.x
->font
->fid
);
4720 frame_update_line_height (f
);
4721 x_set_window_size (f
, 0, f
->width
, f
->height
);
4724 /* If we are setting a new frame's font for the first time,
4725 there are no faces yet, so this font's height is the line height. */
4726 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
4729 Lisp_Object lispy_name
;
4731 lispy_name
= build_string (fontname
);
4733 /* Free the information from XListFonts. The data
4734 we actually retain comes from XLoadQueryFont. */
4735 XFreeFontNames (font_names
);
4741 x_calc_absolute_position (f
)
4745 int win_x
= 0, win_y
= 0;
4746 int flags
= f
->display
.x
->size_hint_flags
;
4748 /* Find the position of the outside upper-left corner of
4749 the inner window, with respect to the outer window. */
4750 if (f
->display
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4753 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4755 /* From-window, to-window. */
4756 f
->display
.x
->window_desc
,
4757 f
->display
.x
->parent_desc
,
4759 /* From-position, to-position. */
4760 0, 0, &win_x
, &win_y
,
4767 /* Treat negative positions as relative to the leftmost bottommost
4768 position that fits on the screen. */
4769 if (flags
& XNegative
)
4770 f
->display
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4771 - 2 * f
->display
.x
->border_width
- win_x
4773 + f
->display
.x
->left_pos
);
4775 if (flags
& YNegative
)
4776 f
->display
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
4777 - 2 * f
->display
.x
->border_width
- win_y
4779 + f
->display
.x
->top_pos
);
4780 /* The left_pos and top_pos
4781 are now relative to the top and left screen edges,
4782 so the flags should correspond. */
4783 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4786 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4787 to really change the position, and 0 when calling from
4788 x_make_frame_visible (in that case, XOFF and YOFF are the current
4789 position values). */
4791 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4793 register int xoff
, yoff
;
4798 f
->display
.x
->top_pos
= yoff
;
4799 f
->display
.x
->left_pos
= xoff
;
4800 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4802 f
->display
.x
->size_hint_flags
|= XNegative
;
4804 f
->display
.x
->size_hint_flags
|= YNegative
;
4805 f
->display
.x
->win_gravity
= NorthWestGravity
;
4807 x_calc_absolute_position (f
);
4810 x_wm_set_size_hint (f
, 0, 0);
4812 #ifdef USE_X_TOOLKIT
4813 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
),
4814 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4815 #else /* not USE_X_TOOLKIT */
4816 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4817 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4818 #endif /* not USE_X_TOOLKIT */
4822 /* Call this to change the size of frame F's x-window.
4823 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4824 for this size change and subsequent size changes.
4825 Otherwise we leave the window gravity unchanged. */
4827 x_set_window_size (f
, change_gravity
, cols
, rows
)
4832 int pixelwidth
, pixelheight
;
4835 #ifdef USE_X_TOOLKIT
4838 /* The x and y position of the widget is clobbered by the
4839 call to XtSetValues within EmacsFrameSetCharSize.
4840 This is a real kludge, but I don't understand Xt so I can't
4841 figure out a correct fix. Can anyone else tell me? -- rms. */
4842 int xpos
= f
->display
.x
->widget
->core
.x
;
4843 int ypos
= f
->display
.x
->widget
->core
.y
;
4844 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4845 f
->display
.x
->widget
->core
.x
= xpos
;
4846 f
->display
.x
->widget
->core
.y
= ypos
;
4850 #else /* not USE_X_TOOLKIT */
4854 check_frame_size (f
, &rows
, &cols
);
4855 f
->display
.x
->vertical_scroll_bar_extra
4856 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4858 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4859 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4860 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
4861 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4862 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4864 f
->display
.x
->win_gravity
= NorthWestGravity
;
4865 x_wm_set_size_hint (f
, 0, 0);
4867 XSync (FRAME_X_DISPLAY (f
), False
);
4868 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4869 pixelwidth
, pixelheight
);
4871 /* Now, strictly speaking, we can't be sure that this is accurate,
4872 but the window manager will get around to dealing with the size
4873 change request eventually, and we'll hear how it went when the
4874 ConfigureNotify event gets here.
4876 We could just not bother storing any of this information here,
4877 and let the ConfigureNotify event set everything up, but that
4878 might be kind of confusing to the lisp code, since size changes
4879 wouldn't be reported in the frame parameters until some random
4880 point in the future when the ConfigureNotify event arrives. */
4881 change_frame_size (f
, rows
, cols
, 0, 0);
4882 PIXEL_WIDTH (f
) = pixelwidth
;
4883 PIXEL_HEIGHT (f
) = pixelheight
;
4885 /* If cursor was outside the new size, mark it as off. */
4886 if (f
->phys_cursor_y
>= rows
4887 || f
->phys_cursor_x
>= cols
)
4889 f
->phys_cursor_x
= -1;
4890 f
->phys_cursor_y
= -1;
4893 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4894 receive in the ConfigureNotify event; if we get what we asked
4895 for, then the event won't cause the screen to become garbaged, so
4896 we have to make sure to do it here. */
4897 SET_FRAME_GARBAGED (f
);
4899 XFlush (FRAME_X_DISPLAY (f
));
4901 #endif /* not USE_X_TOOLKIT */
4904 /* Mouse warping, focus shifting, raising and lowering. */
4907 x_set_mouse_position (f
, x
, y
)
4913 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4914 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
4916 if (pix_x
< 0) pix_x
= 0;
4917 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4919 if (pix_y
< 0) pix_y
= 0;
4920 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4924 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4925 0, 0, 0, 0, pix_x
, pix_y
);
4929 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
4932 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4938 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4939 0, 0, 0, 0, pix_x
, pix_y
);
4943 x_focus_on_frame (f
)
4946 #if 0 /* This proves to be unpleasant. */
4950 /* I don't think that the ICCCM allows programs to do things like this
4951 without the interaction of the window manager. Whatever you end up
4952 doing with this code, do it to x_unfocus_frame too. */
4953 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4954 RevertToPointerRoot
, CurrentTime
);
4962 /* Look at the remarks in x_focus_on_frame. */
4963 if (x_focus_frame
== f
)
4964 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
4965 RevertToPointerRoot
, CurrentTime
);
4969 /* Raise frame F. */
4974 if (f
->async_visible
)
4977 #ifdef USE_X_TOOLKIT
4978 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4979 #else /* not USE_X_TOOLKIT */
4980 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4981 #endif /* not USE_X_TOOLKIT */
4982 XFlush (FRAME_X_DISPLAY (f
));
4987 /* Lower frame F. */
4992 if (f
->async_visible
)
4995 #ifdef USE_X_TOOLKIT
4996 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4997 #else /* not USE_X_TOOLKIT */
4998 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4999 #endif /* not USE_X_TOOLKIT */
5000 XFlush (FRAME_X_DISPLAY (f
));
5006 XTframe_raise_lower (f
, raise
)
5016 /* Change from withdrawn state to mapped state,
5019 x_make_frame_visible (f
)
5027 type
= x_icon_type (f
);
5029 x_bitmap_icon (f
, type
);
5031 if (! FRAME_VISIBLE_P (f
))
5033 #ifndef USE_X_TOOLKIT
5034 if (! FRAME_ICONIFIED_P (f
))
5035 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5038 if (! EQ (Vx_no_window_manager
, Qt
))
5039 x_wm_set_window_state (f
, NormalState
);
5040 #ifdef USE_X_TOOLKIT
5041 /* This was XtPopup, but that did nothing for an iconified frame. */
5042 XtMapWidget (f
->display
.x
->widget
);
5043 #else /* not USE_X_TOOLKIT */
5044 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5045 #endif /* not USE_X_TOOLKIT */
5046 #if 0 /* This seems to bring back scroll bars in the wrong places
5047 if the window configuration has changed. They seem
5048 to come back ok without this. */
5049 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5050 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5054 XFlush (FRAME_X_DISPLAY (f
));
5056 /* Synchronize to ensure Emacs knows the frame is visible
5057 before we do anything else. We do this loop with input not blocked
5058 so that incoming events are handled. */
5061 int count
= input_signal_count
;
5063 /* This must come after we set COUNT. */
5066 XSETFRAME (frame
, f
);
5071 /* Once we have handled input events,
5072 we should have received the MapNotify if one is coming.
5073 So if we have not got it yet, stop looping.
5074 Some window managers make their own decisions
5075 about visibility. */
5076 if (input_signal_count
!= count
)
5078 /* Machines that do polling rather than SIGIO have been observed
5079 to go into a busy-wait here. So we'll fake an alarm signal
5080 to let the handler know that there's something to be read.
5081 We used to raise a real alarm, but it seems that the handler
5082 isn't always enabled here. This is probably a bug. */
5083 if (input_polling_used ())
5085 /* It could be confusing if a real alarm arrives while processing
5086 the fake one. Turn it off and let the handler reset it. */
5088 input_poll_signal ();
5090 /* Once we have handled input events,
5091 we should have received the MapNotify if one is coming.
5092 So if we have not got it yet, stop looping.
5093 Some window managers make their own decisions
5094 about visibility. */
5095 if (input_signal_count
!= count
)
5098 FRAME_SAMPLE_VISIBILITY (f
);
5102 /* Change from mapped state to withdrawn state. */
5104 x_make_frame_invisible (f
)
5110 #ifdef USE_X_TOOLKIT
5111 /* Use the frame's outermost window, not the one we normally draw on. */
5112 window
= XtWindow (f
->display
.x
->widget
);
5113 #else /* not USE_X_TOOLKIT */
5114 window
= FRAME_X_WINDOW (f
);
5115 #endif /* not USE_X_TOOLKIT */
5117 /* Don't keep the highlight on an invisible frame. */
5118 if (x_highlight_frame
== f
)
5119 x_highlight_frame
= 0;
5121 #if 0/* This might add unreliability; I don't trust it -- rms. */
5122 if (! f
->async_visible
&& ! f
->async_iconified
)
5128 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5129 that the current position of the window is user-specified, rather than
5130 program-specified, so that when the window is mapped again, it will be
5131 placed at the same location, without forcing the user to position it
5132 by hand again (they have already done that once for this window.) */
5133 x_wm_set_size_hint (f
, 0, 1);
5137 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5138 DefaultScreen (FRAME_X_DISPLAY (f
))))
5140 UNBLOCK_INPUT_RESIGNAL
;
5141 error ("Can't notify window manager of window withdrawal");
5143 #else /* ! defined (HAVE_X11R4) */
5145 /* Tell the window manager what we're going to do. */
5146 if (! EQ (Vx_no_window_manager
, Qt
))
5150 unmap
.xunmap
.type
= UnmapNotify
;
5151 unmap
.xunmap
.window
= window
;
5152 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5153 unmap
.xunmap
.from_configure
= False
;
5154 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5155 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5157 SubstructureRedirectMask
|SubstructureNotifyMask
,
5160 UNBLOCK_INPUT_RESIGNAL
;
5161 error ("Can't notify window manager of withdrawal");
5165 /* Unmap the window ourselves. Cheeky! */
5166 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5167 #endif /* ! defined (HAVE_X11R4) */
5169 /* We can't distinguish this from iconification
5170 just by the event that we get from the server.
5171 So we can't win using the usual strategy of letting
5172 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5173 and synchronize with the server to make sure we agree. */
5175 FRAME_ICONIFIED_P (f
) = 0;
5176 f
->async_visible
= 0;
5177 f
->async_iconified
= 0;
5184 /* Change window state from mapped to iconified. */
5193 /* Don't keep the highlight on an invisible frame. */
5194 if (x_highlight_frame
== f
)
5195 x_highlight_frame
= 0;
5197 if (f
->async_iconified
)
5202 type
= x_icon_type (f
);
5204 x_bitmap_icon (f
, type
);
5206 #ifdef USE_X_TOOLKIT
5208 if (! FRAME_VISIBLE_P (f
))
5210 if (! EQ (Vx_no_window_manager
, Qt
))
5211 x_wm_set_window_state (f
, IconicState
);
5212 /* This was XtPopup, but that did nothing for an iconified frame. */
5213 XtMapWidget (f
->display
.x
->widget
);
5218 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5219 XtWindow (f
->display
.x
->widget
),
5220 DefaultScreen (FRAME_X_DISPLAY (f
)));
5224 error ("Can't notify window manager of iconification");
5226 f
->async_iconified
= 1;
5229 XFlush (FRAME_X_DISPLAY (f
));
5231 #else /* not USE_X_TOOLKIT */
5233 /* Make sure the X server knows where the window should be positioned,
5234 in case the user deiconifies with the window manager. */
5235 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5236 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5238 /* Since we don't know which revision of X we're running, we'll use both
5239 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5241 /* X11R4: send a ClientMessage to the window manager using the
5242 WM_CHANGE_STATE type. */
5246 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5247 message
.xclient
.type
= ClientMessage
;
5248 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5249 message
.xclient
.format
= 32;
5250 message
.xclient
.data
.l
[0] = IconicState
;
5252 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5253 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5255 SubstructureRedirectMask
| SubstructureNotifyMask
,
5258 UNBLOCK_INPUT_RESIGNAL
;
5259 error ("Can't notify window manager of iconification");
5263 /* X11R3: set the initial_state field of the window manager hints to
5265 x_wm_set_window_state (f
, IconicState
);
5267 if (!FRAME_VISIBLE_P (f
))
5269 /* If the frame was withdrawn, before, we must map it. */
5270 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5273 f
->async_iconified
= 1;
5275 XFlush (FRAME_X_DISPLAY (f
));
5277 #endif /* not USE_X_TOOLKIT */
5280 /* Destroy the X window of frame F. */
5282 x_destroy_window (f
)
5285 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5289 if (f
->display
.x
->icon_desc
!= 0)
5290 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->icon_desc
);
5291 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->window_desc
);
5292 #ifdef USE_X_TOOLKIT
5293 XtDestroyWidget (f
->display
.x
->widget
);
5294 free_frame_menubar (f
);
5295 #endif /* USE_X_TOOLKIT */
5297 free_frame_faces (f
);
5298 XFlush (FRAME_X_DISPLAY (f
));
5300 xfree (f
->display
.x
);
5302 if (f
== x_focus_frame
)
5304 if (f
== x_focus_event_frame
)
5305 x_focus_event_frame
= 0;
5306 if (f
== x_highlight_frame
)
5307 x_highlight_frame
= 0;
5309 dpyinfo
->reference_count
--;
5311 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5313 dpyinfo
->mouse_face_beg_row
5314 = dpyinfo
->mouse_face_beg_col
= -1;
5315 dpyinfo
->mouse_face_end_row
5316 = dpyinfo
->mouse_face_end_col
= -1;
5317 dpyinfo
->mouse_face_window
= Qnil
;
5323 /* Setting window manager hints. */
5325 /* Set the normal size hints for the window manager, for frame F.
5326 FLAGS is the flags word to use--or 0 meaning preserve the flags
5327 that the window now has.
5328 If USER_POSITION is nonzero, we set the USPosition
5329 flag (this is useful when FLAGS is 0). */
5331 x_wm_set_size_hint (f
, flags
, user_position
)
5336 XSizeHints size_hints
;
5338 #ifdef USE_X_TOOLKIT
5341 Dimension widget_width
, widget_height
;
5342 Window window
= XtWindow (f
->display
.x
->widget
);
5343 #else /* not USE_X_TOOLKIT */
5344 Window window
= FRAME_X_WINDOW (f
);
5345 #endif /* not USE_X_TOOLKIT */
5347 /* Setting PMaxSize caused various problems. */
5348 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5350 flexlines
= f
->height
;
5352 size_hints
.x
= f
->display
.x
->left_pos
;
5353 size_hints
.y
= f
->display
.x
->top_pos
;
5355 #ifdef USE_X_TOOLKIT
5356 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5357 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5358 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5359 size_hints
.height
= widget_height
;
5360 size_hints
.width
= widget_width
;
5361 #else /* not USE_X_TOOLKIT */
5362 size_hints
.height
= PIXEL_HEIGHT (f
);
5363 size_hints
.width
= PIXEL_WIDTH (f
);
5364 #endif /* not USE_X_TOOLKIT */
5366 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5367 size_hints
.height_inc
= f
->display
.x
->line_height
;
5368 size_hints
.max_width
5369 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5370 size_hints
.max_height
5371 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5374 int base_width
, base_height
;
5375 int min_rows
= 0, min_cols
= 0;
5377 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5378 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5380 check_frame_size (f
, &min_rows
, &min_cols
);
5382 /* The window manager uses the base width hints to calculate the
5383 current number of rows and columns in the frame while
5384 resizing; min_width and min_height aren't useful for this
5385 purpose, since they might not give the dimensions for a
5386 zero-row, zero-column frame.
5388 We use the base_width and base_height members if we have
5389 them; otherwise, we set the min_width and min_height members
5390 to the size for a zero x zero frame. */
5393 size_hints
.flags
|= PBaseSize
;
5394 size_hints
.base_width
= base_width
;
5395 size_hints
.base_height
= base_height
;
5396 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5397 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5399 size_hints
.min_width
= base_width
;
5400 size_hints
.min_height
= base_height
;
5405 size_hints
.flags
|= flags
;
5408 XSizeHints hints
; /* Sometimes I hate X Windows... */
5409 long supplied_return
;
5413 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5416 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5421 if (hints
.flags
& PSize
)
5422 size_hints
.flags
|= PSize
;
5423 if (hints
.flags
& PPosition
)
5424 size_hints
.flags
|= PPosition
;
5425 if (hints
.flags
& USPosition
)
5426 size_hints
.flags
|= USPosition
;
5427 if (hints
.flags
& USSize
)
5428 size_hints
.flags
|= USSize
;
5432 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5433 size_hints
.flags
|= PWinGravity
;
5437 size_hints
.flags
&= ~ PPosition
;
5438 size_hints
.flags
|= USPosition
;
5440 #endif /* PWinGravity */
5443 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5445 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5449 /* Used for IconicState or NormalState */
5450 x_wm_set_window_state (f
, state
)
5454 #ifdef USE_X_TOOLKIT
5457 XtSetArg (al
[0], XtNinitialState
, state
);
5458 XtSetValues (f
->display
.x
->widget
, al
, 1);
5459 #else /* not USE_X_TOOLKIT */
5460 Window window
= FRAME_X_WINDOW (f
);
5462 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5463 f
->display
.x
->wm_hints
.initial_state
= state
;
5465 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5466 #endif /* not USE_X_TOOLKIT */
5469 x_wm_set_icon_pixmap (f
, pixmap_id
)
5473 #ifdef USE_X_TOOLKIT
5474 Window window
= XtWindow (f
->display
.x
->widget
);
5476 Window window
= FRAME_X_WINDOW (f
);
5481 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5482 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5483 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5487 f
->display
.x
->wm_hints
.icon_pixmap
= None
;
5488 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5491 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5494 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5498 #ifdef USE_X_TOOLKIT
5499 Window window
= XtWindow (f
->display
.x
->widget
);
5501 Window window
= FRAME_X_WINDOW (f
);
5504 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5505 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5506 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5508 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5512 /* Initialization. */
5514 #ifdef USE_X_TOOLKIT
5515 static XrmOptionDescRec emacs_options
[] = {
5516 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5517 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5519 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5520 XrmoptionSepArg
, NULL
},
5521 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5523 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5524 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5525 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5526 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5527 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5528 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5529 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5531 #endif /* USE_X_TOOLKIT */
5533 static int x_initialized
;
5536 /* Test whether two display-name strings agree up to the dot that separates
5537 the screen number from the server number. */
5539 same_x_server (name1
, name2
)
5540 char *name1
, *name2
;
5543 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5547 if (seen_colon
&& *name1
== '.')
5551 && (*name1
== '.' || *name1
== '\0')
5552 && (*name2
== '.' || *name2
== '\0'));
5556 struct x_display_info
*
5557 x_term_init (display_name
, xrm_option
, resource_name
)
5558 Lisp_Object display_name
;
5560 char *resource_name
;
5566 struct x_display_info
*dpyinfo
;
5575 #ifdef USE_X_TOOLKIT
5577 XtSetLanguageProc (NULL
, NULL
, NULL
);
5588 argv
[argc
++] = "-xrm";
5589 argv
[argc
++] = xrm_option
;
5591 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5592 resource_name
, EMACS_CLASS
,
5593 emacs_options
, XtNumber (emacs_options
),
5597 #else /* not USE_X_TOOLKIT */
5599 XSetLocaleModifiers ("");
5601 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5602 #endif /* not USE_X_TOOLKIT */
5604 /* Detect failure. */
5608 /* We have definitely succeeded. Record the new connection. */
5610 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5614 struct x_display_info
*share
;
5617 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5618 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5619 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5620 XSTRING (display_name
)->data
))
5623 dpyinfo
->kboard
= share
->kboard
;
5626 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5627 init_kboard (dpyinfo
->kboard
);
5628 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5629 all_kboards
= dpyinfo
->kboard
;
5631 dpyinfo
->kboard
->reference_count
++;
5635 /* Put this display on the chain. */
5636 dpyinfo
->next
= x_display_list
;
5637 x_display_list
= dpyinfo
;
5639 /* Put it on x_display_name_list as well, to keep them parallel. */
5640 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5641 x_display_name_list
);
5642 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5644 dpyinfo
->display
= dpy
;
5647 XSetAfterFunction (x_current_display
, x_trace_wire
);
5651 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5652 + XSTRING (Vsystem_name
)->size
5654 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5655 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5657 /* Figure out which modifier bits mean what. */
5658 x_find_modifier_meanings (dpyinfo
);
5660 /* Get the scroll bar cursor. */
5661 dpyinfo
->vertical_scroll_bar_cursor
5662 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5664 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5665 resource_name
, EMACS_CLASS
);
5666 #ifdef HAVE_XRMSETDATABASE
5667 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5669 dpyinfo
->display
->db
= xrdb
;
5671 /* Put the rdb where we can find it in a way that works on
5673 dpyinfo
->xrdb
= xrdb
;
5675 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5676 DefaultScreen (dpyinfo
->display
));
5677 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5678 &dpyinfo
->n_planes
);
5679 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
5680 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
5681 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
5682 dpyinfo
->grabbed
= 0;
5683 dpyinfo
->reference_count
= 0;
5684 dpyinfo
->icon_bitmap_id
= -1;
5685 dpyinfo
->n_fonts
= 0;
5686 dpyinfo
->font_table_size
= 0;
5687 dpyinfo
->bitmaps
= 0;
5688 dpyinfo
->bitmaps_size
= 0;
5689 dpyinfo
->bitmaps_last
= 0;
5690 dpyinfo
->scratch_cursor_gc
= 0;
5691 dpyinfo
->mouse_face_mouse_frame
= 0;
5692 dpyinfo
->mouse_face_deferred_gc
= 0;
5693 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5694 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5695 dpyinfo
->mouse_face_face_id
= 0;
5696 dpyinfo
->mouse_face_window
= Qnil
;
5697 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
5698 dpyinfo
->mouse_face_defer
= 0;
5700 dpyinfo
->Xatom_wm_protocols
5701 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
5702 dpyinfo
->Xatom_wm_take_focus
5703 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
5704 dpyinfo
->Xatom_wm_save_yourself
5705 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
5706 dpyinfo
->Xatom_wm_delete_window
5707 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
5708 dpyinfo
->Xatom_wm_change_state
5709 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
5710 dpyinfo
->Xatom_wm_configure_denied
5711 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
5712 dpyinfo
->Xatom_wm_window_moved
5713 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
5714 dpyinfo
->Xatom_editres
5715 = XInternAtom (dpyinfo
->display
, "Editres", False
);
5716 dpyinfo
->Xatom_CLIPBOARD
5717 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
5718 dpyinfo
->Xatom_TIMESTAMP
5719 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
5721 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
5722 dpyinfo
->Xatom_DELETE
5723 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
5724 dpyinfo
->Xatom_MULTIPLE
5725 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
5727 = XInternAtom (dpyinfo
->display
, "INCR", False
);
5728 dpyinfo
->Xatom_EMACS_TMP
5729 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
5730 dpyinfo
->Xatom_TARGETS
5731 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
5733 = XInternAtom (dpyinfo
->display
, "NULL", False
);
5734 dpyinfo
->Xatom_ATOM_PAIR
5735 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
5737 dpyinfo
->cut_buffers_initialized
= 0;
5739 connection
= ConnectionNumber (dpyinfo
->display
);
5740 dpyinfo
->connection
= connection
;
5743 /* This is only needed for distinguishing keyboard and process input. */
5744 if (connection
!= 0)
5745 add_keyboard_wait_descriptor (connection
);
5748 #ifndef F_SETOWN_BUG
5750 #ifdef F_SETOWN_SOCK_NEG
5751 /* stdin is a socket here */
5752 fcntl (connection
, F_SETOWN
, -getpid ());
5753 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5754 fcntl (connection
, F_SETOWN
, getpid ());
5755 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5756 #endif /* ! defined (F_SETOWN) */
5757 #endif /* F_SETOWN_BUG */
5760 init_sigio (connection
);
5761 #endif /* ! defined (SIGIO) */
5766 /* Get rid of display DPYINFO, assuming all frames are already gone,
5767 and without sending any more commands to the X server. */
5770 x_delete_display (dpyinfo
)
5771 struct x_display_info
*dpyinfo
;
5773 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
5775 /* Discard this display from x_display_name_list and x_display_list.
5776 We can't use Fdelq because that can quit. */
5777 if (! NILP (x_display_name_list
)
5778 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
5779 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
5784 tail
= x_display_name_list
;
5785 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
5787 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
5788 dpyinfo
->name_list_element
))
5790 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
5793 tail
= XCONS (tail
)->cdr
;
5797 if (x_display_list
== dpyinfo
)
5798 x_display_list
= dpyinfo
->next
;
5801 struct x_display_info
*tail
;
5803 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
5804 if (tail
->next
== dpyinfo
)
5805 tail
->next
= tail
->next
->next
;
5808 #ifndef USE_X_TOOLKIT
5809 /* I'm told Xt does this itself. */
5810 XrmDestroyDatabase (dpyinfo
->xrdb
);
5813 if (--dpyinfo
->kboard
->reference_count
== 0)
5814 delete_kboard (dpyinfo
->kboard
);
5816 xfree (dpyinfo
->font_table
);
5817 xfree (dpyinfo
->x_id_name
);
5821 /* Set up use of X before we make the first connection. */
5825 clear_frame_hook
= XTclear_frame
;
5826 clear_end_of_line_hook
= XTclear_end_of_line
;
5827 ins_del_lines_hook
= XTins_del_lines
;
5828 change_line_highlight_hook
= XTchange_line_highlight
;
5829 insert_glyphs_hook
= XTinsert_glyphs
;
5830 write_glyphs_hook
= XTwrite_glyphs
;
5831 delete_glyphs_hook
= XTdelete_glyphs
;
5832 ring_bell_hook
= XTring_bell
;
5833 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5834 set_terminal_modes_hook
= XTset_terminal_modes
;
5835 update_begin_hook
= XTupdate_begin
;
5836 update_end_hook
= XTupdate_end
;
5837 set_terminal_window_hook
= XTset_terminal_window
;
5838 read_socket_hook
= XTread_socket
;
5839 frame_up_to_date_hook
= XTframe_up_to_date
;
5840 cursor_to_hook
= XTcursor_to
;
5841 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5842 mouse_position_hook
= XTmouse_position
;
5843 frame_rehighlight_hook
= XTframe_rehighlight
;
5844 frame_raise_lower_hook
= XTframe_raise_lower
;
5845 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5846 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5847 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5848 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5850 scroll_region_ok
= 1; /* we'll scroll partial frames */
5851 char_ins_del_ok
= 0; /* just as fast to write the line */
5852 line_ins_del_ok
= 1; /* we'll just blt 'em */
5853 fast_clear_end_of_line
= 1; /* X does this well */
5854 memory_below_frame
= 0; /* we don't remember what scrolls
5860 x_focus_frame
= x_highlight_frame
= 0;
5862 /* Try to use interrupt input; if we can't, then start polling. */
5863 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5865 #ifdef USE_X_TOOLKIT
5866 XtToolkitInitialize ();
5867 Xt_app_con
= XtCreateApplicationContext ();
5870 /* Note that there is no real way portable across R3/R4 to get the
5871 original error handler. */
5872 XSetErrorHandler (x_error_quitter
);
5873 XSetIOErrorHandler (x_io_error_quitter
);
5875 /* Disable Window Change signals; they are handled by X events. */
5877 signal (SIGWINCH
, SIG_DFL
);
5878 #endif /* ! defined (SIGWINCH) */
5880 signal (SIGPIPE
, x_connection_signal
);
5886 staticpro (&x_display_name_list
);
5887 x_display_name_list
= Qnil
;
5889 staticpro (&last_mouse_scroll_bar
);
5890 last_mouse_scroll_bar
= Qnil
;
5892 #endif /* ! defined (HAVE_X_WINDOWS) */