1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995 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 || face
->font
== (XFontStruct
*) 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 (font
== (XFontStruct
*) 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 (FRAME_X_DISPLAY_INFO (*fp
), 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 xmenu.c. This allows to redisplay the frame if necessary
3026 when handling menubar or popup items. */
3029 process_expose_from_menu (event
)
3033 struct x_display_info
*dpyinfo
;
3037 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3038 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3041 if (f
->async_visible
== 0)
3043 f
->async_visible
= 1;
3044 f
->async_iconified
= 0;
3045 SET_FRAME_GARBAGED (f
);
3049 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3050 event
.xexpose
.x
, event
.xexpose
.y
,
3051 event
.xexpose
.width
, event
.xexpose
.height
);
3056 struct scroll_bar
*bar
3057 = x_window_to_scroll_bar (event
.xexpose
.window
);
3060 x_scroll_bar_expose (bar
, &event
);
3066 /* Define a queue to save up SelectionRequest events for later handling. */
3068 struct selection_event_queue
3071 struct selection_event_queue
*next
;
3074 static struct selection_event_queue
*queue
;
3076 /* Nonzero means queue up certain events--don't process them yet. */
3077 static int x_queue_selection_requests
;
3079 /* Queue up an X event *EVENT, to be processed later. */
3082 x_queue_event (f
, event
)
3086 struct selection_event_queue
*queue_tmp
3087 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3089 if (queue_tmp
!= NULL
)
3091 queue_tmp
->event
= *event
;
3092 queue_tmp
->next
= queue
;
3097 /* Take all the queued events and put them back
3098 so that they get processed afresh. */
3101 x_unqueue_events (display
)
3104 while (queue
!= NULL
)
3106 struct selection_event_queue
*queue_tmp
= queue
;
3107 XPutBackEvent (display
, &queue_tmp
->event
);
3108 queue
= queue_tmp
->next
;
3109 free ((char *)queue_tmp
);
3113 /* Start queuing SelectionRequest events. */
3116 x_start_queuing_selection_requests (display
)
3119 x_queue_selection_requests
++;
3122 /* Stop queuing SelectionRequest events. */
3125 x_stop_queuing_selection_requests (display
)
3128 x_queue_selection_requests
--;
3129 x_unqueue_events (display
);
3132 /* The main X event-reading loop - XTread_socket. */
3134 /* Timestamp of enter window event. This is only used by XTread_socket,
3135 but we have to put it out here, since static variables within functions
3136 sometimes don't work. */
3137 static Time enter_timestamp
;
3139 /* This holds the state XLookupString needs to implement dead keys
3140 and other tricks known as "compose processing". _X Window System_
3141 says that a portable program can't use this, but Stephen Gildea assures
3142 me that letting the compiler initialize it to zeros will work okay.
3144 This must be defined outside of XTread_socket, for the same reasons
3145 given for enter_timestamp, above. */
3146 static XComposeStatus compose_status
;
3148 /* Record the last 100 characters stored
3149 to help debug the loss-of-chars-during-GC problem. */
3151 short temp_buffer
[100];
3153 /* Set this to nonzero to fake an "X I/O error"
3154 on a particular display. */
3155 struct x_display_info
*XTread_socket_fake_io_error
;
3157 /* Read events coming from the X server.
3158 This routine is called by the SIGIO handler.
3159 We return as soon as there are no more events to be read.
3161 Events representing keys are stored in buffer BUFP,
3162 which can hold up to NUMCHARS characters.
3163 We return the number of characters stored into the buffer,
3164 thus pretending to be `read'.
3166 WAITP is nonzero if we should block until input arrives.
3167 EXPECTED is nonzero if the caller knows input is available. */
3170 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3172 register struct input_event
*bufp
;
3173 register int numchars
;
3180 int items_pending
; /* How many items are in the X queue. */
3183 int event_found
= 0;
3186 struct x_display_info
*dpyinfo
;
3188 if (interrupt_input_blocked
)
3190 interrupt_input_pending
= 1;
3194 interrupt_input_pending
= 0;
3197 /* So people can tell when we have read the available input. */
3198 input_signal_count
++;
3201 abort (); /* Don't think this happens. */
3203 /* Find the display we are supposed to read input for.
3204 It's the one communicating on descriptor SD. */
3205 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3207 #if 0 /* This ought to be unnecessary; let's verify it. */
3209 /* If available, Xlib uses FIOSNBIO to make the socket
3210 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3211 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3212 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3213 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3214 #endif /* ! defined (FIOSNBIO) */
3217 #if 0 /* This code can't be made to work, with multiple displays,
3218 and appears not to be used on any system any more.
3219 Also keyboard.c doesn't turn O_NDELAY on and off
3220 for X connections. */
3223 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3225 extern int read_alarm_should_throw
;
3226 read_alarm_should_throw
= 1;
3227 XPeekEvent (dpyinfo
->display
, &event
);
3228 read_alarm_should_throw
= 0;
3230 #endif /* HAVE_SELECT */
3234 /* For debugging, this gives a way to fake an I/O error. */
3235 if (dpyinfo
== XTread_socket_fake_io_error
)
3237 XTread_socket_fake_io_error
= 0;
3238 x_io_error_quitter (dpyinfo
->display
);
3241 while (XPending (dpyinfo
->display
) != 0)
3243 XNextEvent (dpyinfo
->display
, &event
);
3250 if (event
.xclient
.message_type
3251 == dpyinfo
->Xatom_wm_protocols
3252 && event
.xclient
.format
== 32)
3254 if (event
.xclient
.data
.l
[0]
3255 == dpyinfo
->Xatom_wm_take_focus
)
3257 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3258 /* Since we set WM_TAKE_FOCUS, we must call
3259 XSetInputFocus explicitly. But not if f is null,
3260 since that might be an event for a deleted frame. */
3262 XSetInputFocus (event
.xclient
.display
,
3263 event
.xclient
.window
,
3264 RevertToPointerRoot
,
3265 event
.xclient
.data
.l
[1]);
3266 /* Not certain about handling scroll bars here */
3268 else if (event
.xclient
.data
.l
[0]
3269 == dpyinfo
->Xatom_wm_save_yourself
)
3271 /* Save state modify the WM_COMMAND property to
3272 something which can reinstate us. This notifies
3273 the session manager, who's looking for such a
3274 PropertyNotify. Can restart processing when
3275 a keyboard or mouse event arrives. */
3278 f
= x_top_window_to_frame (dpyinfo
,
3279 event
.xclient
.window
);
3281 /* This is just so we only give real data once
3282 for a single Emacs process. */
3283 if (f
== selected_frame
)
3284 XSetCommand (FRAME_X_DISPLAY (f
),
3285 event
.xclient
.window
,
3286 initial_argv
, initial_argc
);
3288 XSetCommand (FRAME_X_DISPLAY (f
),
3289 event
.xclient
.window
,
3293 else if (event
.xclient
.data
.l
[0]
3294 == dpyinfo
->Xatom_wm_delete_window
)
3297 = x_any_window_to_frame (dpyinfo
,
3298 event
.xclient
.window
);
3305 bufp
->kind
= delete_window_event
;
3306 XSETFRAME (bufp
->frame_or_window
, f
);
3314 else if (event
.xclient
.message_type
3315 == dpyinfo
->Xatom_wm_configure_denied
)
3318 else if (event
.xclient
.message_type
3319 == dpyinfo
->Xatom_wm_window_moved
)
3323 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3325 new_x
= event
.xclient
.data
.s
[0];
3326 new_y
= event
.xclient
.data
.s
[1];
3330 f
->display
.x
->left_pos
= new_x
;
3331 f
->display
.x
->top_pos
= new_y
;
3334 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3335 else if (event
.xclient
.message_type
3336 == dpyinfo
->Xatom_editres
)
3339 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3340 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
,
3343 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3347 case SelectionNotify
:
3348 #ifdef USE_X_TOOLKIT
3349 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3351 #endif /* not USE_X_TOOLKIT */
3352 x_handle_selection_notify (&event
);
3355 case SelectionClear
: /* Someone has grabbed ownership. */
3356 #ifdef USE_X_TOOLKIT
3357 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3359 #endif /* USE_X_TOOLKIT */
3361 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3366 bufp
->kind
= selection_clear_event
;
3367 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3368 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3369 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3377 case SelectionRequest
: /* Someone wants our selection. */
3378 #ifdef USE_X_TOOLKIT
3379 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3381 #endif /* USE_X_TOOLKIT */
3382 if (x_queue_selection_requests
)
3383 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3387 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3392 bufp
->kind
= selection_request_event
;
3393 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3394 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3395 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3396 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3397 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3398 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3406 case PropertyNotify
:
3407 #ifdef USE_X_TOOLKIT
3408 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3410 #endif /* not USE_X_TOOLKIT */
3411 x_handle_property_notify (&event
);
3414 case ReparentNotify
:
3415 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3419 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3420 x_real_positions (f
, &x
, &y
);
3421 f
->display
.x
->left_pos
= x
;
3422 f
->display
.x
->top_pos
= y
;
3427 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3430 if (f
->async_visible
== 0)
3432 f
->async_visible
= 1;
3433 f
->async_iconified
= 0;
3434 SET_FRAME_GARBAGED (f
);
3437 dumprectangle (x_window_to_frame (dpyinfo
,
3438 event
.xexpose
.window
),
3439 event
.xexpose
.x
, event
.xexpose
.y
,
3440 event
.xexpose
.width
, event
.xexpose
.height
);
3444 struct scroll_bar
*bar
3445 = x_window_to_scroll_bar (event
.xexpose
.window
);
3448 x_scroll_bar_expose (bar
, &event
);
3449 #ifdef USE_X_TOOLKIT
3452 #endif /* USE_X_TOOLKIT */
3456 case GraphicsExpose
: /* This occurs when an XCopyArea's
3457 source area was obscured or not
3459 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3463 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3464 event
.xgraphicsexpose
.width
,
3465 event
.xgraphicsexpose
.height
);
3467 #ifdef USE_X_TOOLKIT
3470 #endif /* USE_X_TOOLKIT */
3473 case NoExpose
: /* This occurs when an XCopyArea's
3474 source area was completely
3479 f
= x_any_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3480 if (f
) /* F may no longer exist if
3481 the frame was deleted. */
3483 /* While a frame is unmapped, display generation is
3484 disabled; you don't want to spend time updating a
3485 display that won't ever be seen. */
3486 f
->async_visible
= 0;
3487 /* We can't distinguish, from the event, whether the window
3488 has become iconified or invisible. So assume, if it
3489 was previously visible, than now it is iconified.
3490 We depend on x_make_frame_invisible to mark it iconified. */
3491 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3492 f
->async_iconified
= 1;
3494 bufp
->kind
= iconify_event
;
3495 XSETFRAME (bufp
->frame_or_window
, f
);
3500 #ifdef USE_X_TOOLKIT
3502 #endif /* USE_X_TOOLKIT */
3506 /* We use x_top_window_to_frame because map events can come
3507 for subwindows and they don't mean that the frame is visible. */
3508 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
3511 f
->async_visible
= 1;
3512 f
->async_iconified
= 0;
3514 /* wait_reading_process_input will notice this and update
3515 the frame's display structures. */
3516 SET_FRAME_GARBAGED (f
);
3518 bufp
->kind
= deiconify_event
;
3519 XSETFRAME (bufp
->frame_or_window
, f
);
3524 #ifdef USE_X_TOOLKIT
3526 #endif /* USE_X_TOOLKIT */
3529 /* Turn off processing if we become fully obscured. */
3530 case VisibilityNotify
:
3534 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
3538 KeySym keysym
, orig_keysym
;
3539 /* al%imercury@uunet.uu.net says that making this 81 instead of
3540 80 fixed a bug whereby meta chars made his Emacs hang. */
3541 unsigned char copy_buffer
[81];
3545 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3546 extra_keyboard_modifiers
);
3547 modifiers
= event
.xkey
.state
;
3549 /* This will have to go some day... */
3551 /* make_lispy_event turns chars into control chars.
3552 Don't do it here because XLookupString is too eager. */
3553 event
.xkey
.state
&= ~ControlMask
;
3554 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3555 80, &keysym
, &compose_status
);
3557 orig_keysym
= keysym
;
3561 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3562 || keysym
== XK_Delete
3563 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3564 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3566 /* This recognizes the "extended function keys".
3567 It seems there's no cleaner way.
3568 Test IsModifierKey to avoid handling mode_switch
3570 || ((unsigned) (keysym
) >= XK_Select
3571 && (unsigned)(keysym
) < XK_KP_Space
)
3573 #ifdef XK_dead_circumflex
3574 || orig_keysym
== XK_dead_circumflex
3576 #ifdef XK_dead_grave
3577 || orig_keysym
== XK_dead_grave
3579 #ifdef XK_dead_tilde
3580 || orig_keysym
== XK_dead_tilde
3582 #ifdef XK_dead_diaeresis
3583 || orig_keysym
== XK_dead_diaeresis
3585 #ifdef XK_dead_macron
3586 || orig_keysym
== XK_dead_macron
3588 #ifdef XK_dead_degree
3589 || orig_keysym
== XK_dead_degree
3591 #ifdef XK_dead_acute
3592 || orig_keysym
== XK_dead_acute
3594 #ifdef XK_dead_cedilla
3595 || orig_keysym
== XK_dead_cedilla
3597 #ifdef XK_dead_breve
3598 || orig_keysym
== XK_dead_breve
3600 #ifdef XK_dead_ogonek
3601 || orig_keysym
== XK_dead_ogonek
3603 #ifdef XK_dead_caron
3604 || orig_keysym
== XK_dead_caron
3606 #ifdef XK_dead_doubleacute
3607 || orig_keysym
== XK_dead_doubleacute
3609 #ifdef XK_dead_abovedot
3610 || orig_keysym
== XK_dead_abovedot
3612 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3613 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3614 /* Any "vendor-specific" key is ok. */
3615 || (orig_keysym
& (1 << 28)))
3616 && ! (IsModifierKey (orig_keysym
)
3618 #ifdef XK_Mode_switch
3619 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3622 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3624 #endif /* not HAVE_X11R5 */
3627 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3629 temp_buffer
[temp_index
++] = keysym
;
3630 bufp
->kind
= non_ascii_keystroke
;
3631 bufp
->code
= keysym
;
3632 XSETFRAME (bufp
->frame_or_window
, f
);
3634 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3636 bufp
->timestamp
= event
.xkey
.time
;
3641 else if (numchars
> nbytes
)
3645 for (i
= 0; i
< nbytes
; i
++)
3647 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3649 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3650 bufp
->kind
= ascii_keystroke
;
3651 bufp
->code
= copy_buffer
[i
];
3652 XSETFRAME (bufp
->frame_or_window
, f
);
3654 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3656 bufp
->timestamp
= event
.xkey
.time
;
3671 /* Here's a possible interpretation of the whole
3672 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3673 FocusIn event, you have to get a FocusOut event before you
3674 relinquish the focus. If you haven't received a FocusIn event,
3675 then a mere LeaveNotify is enough to free you. */
3678 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3680 if (event
.xcrossing
.focus
) /* Entered Window */
3682 /* Avoid nasty pop/raise loops. */
3683 if (f
&& (!(f
->auto_raise
)
3685 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3687 x_new_focus_frame (f
);
3688 enter_timestamp
= event
.xcrossing
.time
;
3691 else if (f
== x_focus_frame
)
3692 x_new_focus_frame (0);
3693 /* EnterNotify counts as mouse movement,
3694 so update things that depend on mouse position. */
3696 note_mouse_movement (f
, &event
.xmotion
);
3697 #ifdef USE_X_TOOLKIT
3699 #endif /* USE_X_TOOLKIT */
3703 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3704 if (event
.xfocus
.detail
!= NotifyPointer
)
3705 x_focus_event_frame
= f
;
3707 x_new_focus_frame (f
);
3708 #ifdef USE_X_TOOLKIT
3710 #endif /* USE_X_TOOLKIT */
3715 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
3718 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3719 /* If we move outside the frame,
3720 then we're certainly no longer on any text in the frame. */
3721 clear_mouse_face (dpyinfo
);
3723 if (event
.xcrossing
.focus
)
3727 if (f
== x_focus_event_frame
)
3728 x_focus_event_frame
= 0;
3729 if (f
== x_focus_frame
)
3730 x_new_focus_frame (0);
3733 #ifdef USE_X_TOOLKIT
3735 #endif /* USE_X_TOOLKIT */
3739 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
3740 if (event
.xfocus
.detail
!= NotifyPointer
3741 && f
== x_focus_event_frame
)
3742 x_focus_event_frame
= 0;
3743 if (f
&& f
== x_focus_frame
)
3744 x_new_focus_frame (0);
3745 #ifdef USE_X_TOOLKIT
3747 #endif /* USE_X_TOOLKIT */
3752 if (dpyinfo
->grabbed
&& last_mouse_frame
3753 && FRAME_LIVE_P (last_mouse_frame
))
3754 f
= last_mouse_frame
;
3756 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3758 note_mouse_movement (f
, &event
.xmotion
);
3761 struct scroll_bar
*bar
3762 = x_window_to_scroll_bar (event
.xmotion
.window
);
3765 x_scroll_bar_note_movement (bar
, &event
);
3767 /* If we move outside the frame,
3768 then we're certainly no longer on any text in the frame. */
3769 clear_mouse_face (dpyinfo
);
3772 #if 0 /* This should be unnecessary, since the toolkit has no use
3773 for motion events that happen outside of the menu event loop,
3774 and it seems to cause the bug that mouse events stop coming
3776 #ifdef USE_X_TOOLKIT
3778 #endif /* USE_X_TOOLKIT */
3782 case ConfigureNotify
:
3783 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
3784 #ifdef USE_X_TOOLKIT
3787 && ! event
.xconfigure
.send_event
3789 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
3794 /* Find the position of the outside upper-left corner of
3795 the window, in the root coordinate system. Don't
3796 refer to the parent window here; we may be processing
3797 this event after the window manager has changed our
3798 parent, but before we have reached the ReparentNotify. */
3799 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3801 /* From-window, to-window. */
3802 XtWindow (f
->display
.x
->widget
),
3803 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3805 /* From-position, to-position. */
3806 -event
.xconfigure
.border_width
,
3807 -event
.xconfigure
.border_width
,
3812 event
.xconfigure
.x
= win_x
;
3813 event
.xconfigure
.y
= win_y
;
3815 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3816 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3817 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3818 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3820 /* What we have now is the position of Emacs's own window.
3821 Convert that to the position of the window manager window. */
3824 x_real_positions (f
, &x
, &y
);
3825 f
->display
.x
->left_pos
= x
;
3826 f
->display
.x
->top_pos
= y
;
3830 #else /* not USE_X_TOOLKIT */
3833 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3834 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3836 /* Even if the number of character rows and columns has
3837 not changed, the font size may have changed, so we need
3838 to check the pixel dimensions as well. */
3839 if (columns
!= f
->width
3840 || rows
!= f
->height
3841 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3842 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3844 change_frame_size (f
, rows
, columns
, 0, 1);
3845 SET_FRAME_GARBAGED (f
);
3848 if (! event
.xconfigure
.send_event
)
3853 /* Find the position of the outside upper-left corner of
3854 the window, in the root coordinate system. Don't
3855 refer to the parent window here; we may be processing
3856 this event after the window manager has changed our
3857 parent, but before we have reached the ReparentNotify. */
3858 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3860 /* From-window, to-window. */
3861 f
->display
.x
->window_desc
,
3862 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3864 /* From-position, to-position. */
3865 -event
.xconfigure
.border_width
,
3866 -event
.xconfigure
.border_width
,
3871 event
.xconfigure
.x
= win_x
;
3872 event
.xconfigure
.y
= win_y
;
3875 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3876 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3877 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3878 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3880 /* What we have now is the position of Emacs's own window.
3881 Convert that to the position of the window manager window. */
3884 x_real_positions (f
, &x
, &y
);
3885 f
->display
.x
->left_pos
= x
;
3886 f
->display
.x
->top_pos
= y
;
3887 if (y
!= event
.xconfigure
.y
)
3889 /* Since the WM decorations come below top_pos now,
3890 we must put them below top_pos in the future. */
3891 f
->display
.x
->win_gravity
= NorthWestGravity
;
3892 x_wm_set_size_hint (f
, 0, 0);
3896 #endif /* not USE_X_TOOLKIT */
3902 /* If we decide we want to generate an event to be seen
3903 by the rest of Emacs, we put it here. */
3904 struct input_event emacs_event
;
3905 emacs_event
.kind
= no_event
;
3907 bzero (&compose_status
, sizeof (compose_status
));
3909 if (dpyinfo
->grabbed
&& last_mouse_frame
3910 && FRAME_LIVE_P (last_mouse_frame
))
3911 f
= last_mouse_frame
;
3913 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
3917 if (!x_focus_frame
|| (f
== x_focus_frame
))
3918 construct_mouse_click (&emacs_event
, &event
, f
);
3922 struct scroll_bar
*bar
3923 = x_window_to_scroll_bar (event
.xbutton
.window
);
3926 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3927 #ifdef USE_X_TOOLKIT
3930 /* Assume we have a menubar button press. A bad
3931 assumption should behave benignly. */
3932 popup_get_selection (&event
);
3935 #endif /* USE_X_TOOLKIT */
3938 if (event
.type
== ButtonPress
)
3940 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
3941 last_mouse_frame
= f
;
3945 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
3948 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3950 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3956 #ifdef USE_X_TOOLKIT
3958 #endif /* USE_X_TOOLKIT */
3962 case CirculateNotify
:
3964 case CirculateRequest
:
3968 /* Someone has changed the keyboard mapping - update the
3970 switch (event
.xmapping
.request
)
3972 case MappingModifier
:
3973 x_find_modifier_meanings (dpyinfo
);
3974 /* This is meant to fall through. */
3975 case MappingKeyboard
:
3976 XRefreshKeyboardMapping (&event
.xmapping
);
3978 #ifdef USE_X_TOOLKIT
3980 #endif /* USE_X_TOOLKIT */
3984 #ifdef USE_X_TOOLKIT
3987 XtDispatchEvent (&event
);
3989 #endif /* USE_X_TOOLKIT */
3995 /* On some systems, an X bug causes Emacs to get no more events
3996 when the window is destroyed. Detect that. (1994.) */
3999 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4000 One XNOOP in 100 loops will make Emacs terminate.
4001 B. Bretthauer, 1994 */
4003 if (x_noop_count
>= 100)
4006 /* Use the first display in the list. Why not? */
4007 XNoOp (x_display_list
->display
);
4011 /* If the focus was just given to an autoraising frame,
4013 /* ??? This ought to be able to handle more than one such frame. */
4014 if (pending_autoraise_frame
)
4016 x_raise_frame (pending_autoraise_frame
);
4017 pending_autoraise_frame
= 0;
4024 /* Drawing the cursor. */
4027 /* Draw a hollow box cursor. Don't change the inside of the box. */
4033 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
4034 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
4035 int width
= FONT_WIDTH (f
->display
.x
->font
);
4036 int height
= f
->display
.x
->line_height
;
4038 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4039 f
->display
.x
->cursor_gc
,
4040 left
, top
, width
- 1, height
- 1);
4043 /* Clear the cursor of frame F to background color,
4044 and mark the cursor as not shown.
4045 This is used when the text where the cursor is
4046 is about to be rewritten. */
4054 if (! FRAME_VISIBLE_P (f
)
4055 || f
->phys_cursor_x
< 0)
4058 x_display_cursor (f
, 0);
4059 f
->phys_cursor_x
= -1;
4062 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4063 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4067 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4074 CHAR_TO_PIXEL_COL (f
, column
),
4075 CHAR_TO_PIXEL_ROW (f
, row
),
4076 &glyph
, 1, highlight
, 0);
4080 x_display_bar_cursor (f
, on
)
4084 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4086 /* This is pointless on invisible frames, and dangerous on garbaged
4087 frames; in the latter case, the frame may be in the midst of
4088 changing its size, and curs_x and curs_y may be off the frame. */
4089 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4092 if (! on
&& f
->phys_cursor_x
< 0)
4095 /* If we're not updating, then we want to use the current frame's
4096 cursor position, not our local idea of where the cursor ought to be. */
4097 if (f
!= updating_frame
)
4099 curs_x
= FRAME_CURSOR_X (f
);
4100 curs_y
= FRAME_CURSOR_Y (f
);
4103 /* If there is anything wrong with the current cursor state, remove it. */
4104 if (f
->phys_cursor_x
>= 0
4106 || f
->phys_cursor_x
!= curs_x
4107 || f
->phys_cursor_y
!= curs_y
4108 || f
->display
.x
->current_cursor
!= bar_cursor
))
4110 /* Erase the cursor by redrawing the character underneath it. */
4111 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4112 f
->phys_cursor_glyph
,
4113 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4114 f
->phys_cursor_x
= -1;
4117 /* If we now need a cursor in the new place or in the new form, do it so. */
4119 && (f
->phys_cursor_x
< 0
4120 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4122 f
->phys_cursor_glyph
4123 = ((current_glyphs
->enable
[curs_y
]
4124 && curs_x
< current_glyphs
->used
[curs_y
])
4125 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4127 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4128 f
->display
.x
->cursor_gc
,
4129 CHAR_TO_PIXEL_COL (f
, curs_x
),
4130 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4131 max (f
->display
.x
->cursor_width
, 1),
4132 f
->display
.x
->line_height
);
4134 f
->phys_cursor_x
= curs_x
;
4135 f
->phys_cursor_y
= curs_y
;
4137 f
->display
.x
->current_cursor
= bar_cursor
;
4140 if (updating_frame
!= f
)
4141 XFlush (FRAME_X_DISPLAY (f
));
4145 /* Turn the displayed cursor of frame F on or off according to ON.
4146 If ON is nonzero, where to put the cursor is specified
4147 by F->cursor_x and F->cursor_y. */
4150 x_display_box_cursor (f
, on
)
4154 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4156 /* This is pointless on invisible frames, and dangerous on garbaged
4157 frames; in the latter case, the frame may be in the midst of
4158 changing its size, and curs_x and curs_y may be off the frame. */
4159 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4162 /* If cursor is off and we want it off, return quickly. */
4163 if (!on
&& f
->phys_cursor_x
< 0)
4166 /* If we're not updating, then we want to use the current frame's
4167 cursor position, not our local idea of where the cursor ought to be. */
4168 if (f
!= updating_frame
)
4170 curs_x
= FRAME_CURSOR_X (f
);
4171 curs_y
= FRAME_CURSOR_Y (f
);
4174 /* If cursor is currently being shown and we don't want it to be
4175 or it is in the wrong place,
4176 or we want a hollow box and it's not so, (pout!)
4178 if (f
->phys_cursor_x
>= 0
4180 || f
->phys_cursor_x
!= curs_x
4181 || f
->phys_cursor_y
!= curs_y
4182 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4183 && (f
!= x_highlight_frame
))))
4185 int mouse_face_here
= 0;
4186 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4188 /* If the cursor is in the mouse face area, redisplay that when
4189 we clear the cursor. */
4190 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4192 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4193 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4194 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4196 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4197 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4198 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4199 /* Don't redraw the cursor's spot in mouse face
4200 if it is at the end of a line (on a newline).
4201 The cursor appears there, but mouse highlighting does not. */
4202 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4203 mouse_face_here
= 1;
4205 /* If the font is not as tall as a whole line,
4206 we must explicitly clear the line's whole height. */
4207 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4208 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4209 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4210 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4211 FONT_WIDTH (f
->display
.x
->font
),
4212 f
->display
.x
->line_height
, False
);
4213 /* Erase the cursor by redrawing the character underneath it. */
4214 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4215 f
->phys_cursor_glyph
,
4218 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4219 f
->phys_cursor_x
= -1;
4222 /* If we want to show a cursor,
4223 or we want a box cursor and it's not so,
4224 write it in the right place. */
4226 && (f
->phys_cursor_x
< 0
4227 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4228 && f
== x_highlight_frame
)))
4230 f
->phys_cursor_glyph
4231 = ((current_glyphs
->enable
[curs_y
]
4232 && curs_x
< current_glyphs
->used
[curs_y
])
4233 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4235 if (f
!= x_highlight_frame
)
4238 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4242 x_draw_single_glyph (f
, curs_y
, curs_x
,
4243 f
->phys_cursor_glyph
, 2);
4244 f
->display
.x
->current_cursor
= filled_box_cursor
;
4247 f
->phys_cursor_x
= curs_x
;
4248 f
->phys_cursor_y
= curs_y
;
4251 if (updating_frame
!= f
)
4252 XFlush (FRAME_X_DISPLAY (f
));
4255 x_display_cursor (f
, on
)
4261 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4262 x_display_box_cursor (f
, on
);
4263 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4264 x_display_bar_cursor (f
, on
);
4266 /* Those are the only two we have implemented! */
4274 /* Refresh bitmap kitchen sink icon for frame F
4275 when we get an expose event for it. */
4280 /* Normally, the window manager handles this function. */
4283 /* Make the x-window of frame F use the gnu icon bitmap. */
4286 x_bitmap_icon (f
, file
)
4290 int mask
, bitmap_id
;
4293 if (FRAME_X_WINDOW (f
) == 0)
4296 /* Free up our existing icon bitmap if any. */
4297 if (f
->display
.x
->icon_bitmap
> 0)
4298 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4299 f
->display
.x
->icon_bitmap
= 0;
4302 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4305 /* Create the GNU bitmap if necessary. */
4306 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4307 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4308 = x_create_bitmap_from_data (f
, gnu_bits
,
4309 gnu_width
, gnu_height
);
4311 /* The first time we create the GNU bitmap,
4312 this increments the refcount one extra time.
4313 As a result, the GNU bitmap is never freed.
4314 That way, we don't have to worry about allocating it again. */
4315 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4317 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4320 x_wm_set_icon_pixmap (f
, bitmap_id
);
4321 f
->display
.x
->icon_bitmap
= bitmap_id
;
4327 /* Make the x-window of frame F use a rectangle with text. */
4330 x_text_icon (f
, icon_name
)
4334 if (FRAME_X_WINDOW (f
) == 0)
4338 f
->display
.x
->icon_label
= icon_name
;
4340 if (! f
->display
.x
->icon_label
)
4341 f
->display
.x
->icon_label
= " *emacs* ";
4344 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4345 (char *) f
->display
.x
->icon_label
);
4348 if (f
->display
.x
->icon_bitmap
> 0)
4349 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4350 f
->display
.x
->icon_bitmap
= 0;
4351 x_wm_set_icon_pixmap (f
, 0);
4356 /* Handling X errors. */
4358 /* Handle the loss of connection to display DISPLAY. */
4361 x_connection_closed (display
, error_message
)
4363 char *error_message
;
4365 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4366 Lisp_Object frame
, tail
;
4371 /* First delete frames whose minibuffers are on frames
4372 that are on the dead display. */
4373 FOR_EACH_FRAME (tail
, frame
)
4375 Lisp_Object minibuf_frame
;
4377 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4378 if (FRAME_X_P (XFRAME (frame
))
4379 && FRAME_X_P (XFRAME (minibuf_frame
))
4380 && ! EQ (frame
, minibuf_frame
)
4381 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4382 Fdelete_frame (frame
, Qt
);
4385 /* Now delete all remaining frames on the dead display.
4386 We are now sure none of these is used as the minibuffer
4387 for another frame that we need to delete. */
4388 FOR_EACH_FRAME (tail
, frame
)
4389 if (FRAME_X_P (XFRAME (frame
))
4390 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4391 Fdelete_frame (frame
, Qt
);
4393 x_delete_display (dpyinfo
);
4395 if (x_display_list
== 0)
4397 fprintf (stderr
, "%s", error_message
);
4398 shut_down_emacs (0, 0, Qnil
);
4402 /* Ordinary stack unwind doesn't deal with these. */
4404 sigunblock (sigmask (SIGIO
));
4406 sigunblock (sigmask (SIGALRM
));
4407 TOTALLY_UNBLOCK_INPUT
;
4409 error ("%s", error_message
);
4413 x_connection_signal (signalnum
) /* If we don't have an argument, */
4414 int signalnum
; /* some compilers complain in signal calls. */
4416 /* We really ought to close the connection to the display
4417 that actually failed.
4418 But do we actually get this signal ever with X11? */
4419 fprintf (stderr
, "X connection closed");
4420 shut_down_emacs (0, 0, Qnil
);
4424 /* This is the usual handler for X protocol errors.
4425 It kills all frames on the display that we got the error for.
4426 If that was the only one, it prints an error message and kills Emacs. */
4429 x_error_quitter (display
, error
)
4433 char buf
[256], buf1
[356];
4435 /* Note that there is no real way portable across R3/R4 to get the
4436 original error handler. */
4438 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4439 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4440 buf
, error
->request_code
);
4441 x_connection_closed (display
, buf1
);
4444 /* This is the handler for X IO errors, always.
4445 It kills all frames on the display that we lost touch with.
4446 If that was the only one, it prints an error message and kills Emacs. */
4449 x_io_error_quitter (display
)
4454 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4455 x_connection_closed (display
, buf
);
4458 /* A buffer for storing X error messages. */
4459 static char *x_caught_error_message
;
4460 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4462 /* An X error handler which stores the error message in
4463 x_caught_error_message. This is what's installed when
4464 x_catch_errors is in effect. */
4467 x_error_catcher (display
, error
)
4471 XGetErrorText (display
, error
->error_code
,
4472 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4476 /* Begin trapping X errors for display DPY. Actually we trap X errors
4477 for all displays, but DPY should be the display you are actually
4480 After calling this function, X protocol errors no longer cause
4481 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4483 Calling x_check_errors signals an Emacs error if an X error has
4484 occurred since the last call to x_catch_errors or x_check_errors.
4486 Calling x_uncatch_errors resumes the normal error handling. */
4488 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4491 x_catch_errors (dpy
)
4494 /* Make sure any errors from previous requests have been dealt with. */
4497 /* Set up the error buffer. */
4498 x_caught_error_message
4499 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4500 x_caught_error_message
[0] = '\0';
4502 /* Install our little error handler. */
4503 XSetErrorHandler (x_error_catcher
);
4506 /* If any X protocol errors have arrived since the last call to
4507 x_catch_errors or x_check_errors, signal an Emacs error using
4508 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4511 x_check_errors (dpy
, format
)
4515 /* Make sure to catch any errors incurred so far. */
4518 if (x_caught_error_message
[0])
4520 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4522 sprintf (buf
, format
, x_caught_error_message
);
4523 x_uncatch_errors (dpy
);
4528 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4531 x_had_errors_p (dpy
)
4534 /* Make sure to catch any errors incurred so far. */
4537 return x_caught_error_message
[0] != 0;
4540 /* Stop catching X protocol errors and let them make Emacs die. */
4543 x_uncatch_errors (dpy
)
4546 xfree (x_caught_error_message
);
4547 x_caught_error_message
= 0;
4548 XSetErrorHandler (x_error_quitter
);
4552 static unsigned int x_wire_count
;
4555 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4560 /* Changing the font of the frame. */
4562 /* Give frame F the font named FONTNAME as its default font, and
4563 return the full name of that font. FONTNAME may be a wildcard
4564 pattern; in that case, we choose some font that fits the pattern.
4565 The return value shows which font we chose. */
4568 x_new_font (f
, fontname
)
4570 register char *fontname
;
4573 int n_matching_fonts
;
4574 XFontStruct
*font_info
;
4577 /* Get a list of all the fonts that match this name. Once we
4578 have a list of matching fonts, we compare them against the fonts
4579 we already have by comparing font ids. */
4580 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4581 1024, &n_matching_fonts
);
4582 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4583 find any matches; font_names == 0 is the only clue. */
4585 n_matching_fonts
= 0;
4587 /* Don't just give up if n_matching_fonts is 0.
4588 Apparently there's a bug on Suns: XListFontsWithInfo can
4589 fail to find a font, but XLoadQueryFont may still find it. */
4591 /* See if we've already loaded a matching font. */
4592 already_loaded
= -1;
4593 if (n_matching_fonts
!= 0)
4597 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4598 for (j
= 0; j
< n_matching_fonts
; j
++)
4599 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4600 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4603 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4609 /* If we have, just return it from the table. */
4610 if (already_loaded
>= 0)
4611 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4612 /* Otherwise, load the font and add it to the table. */
4620 /* Try to find a character-cell font in the list. */
4622 /* A laudable goal, but this isn't how to do it. */
4623 for (i
= 0; i
< n_matching_fonts
; i
++)
4624 if (! font_info
[i
].per_char
)
4630 /* See comment above. */
4631 if (n_matching_fonts
!= 0)
4632 fontname
= font_names
[i
];
4634 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4637 /* Free the information from XListFonts. */
4638 if (n_matching_fonts
)
4639 XFreeFontNames (font_names
);
4643 /* Do we need to create the table? */
4644 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4646 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4647 FRAME_X_DISPLAY_INFO (f
)->font_table
4648 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4649 * sizeof (struct font_info
));
4651 /* Do we need to grow the table? */
4652 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4653 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4655 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4656 FRAME_X_DISPLAY_INFO (f
)->font_table
4657 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4658 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4659 * sizeof (struct font_info
)));
4662 /* Try to get the full name of FONT. Put it in full_name. */
4664 for (i
= 0; i
< font
->n_properties
; i
++)
4667 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4668 if (!strcmp (atom
, "FONT"))
4670 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4671 (Atom
) (font
->properties
[i
].card32
));
4675 /* Count the number of dashes in the "full name".
4676 If it is too few, this isn't really the font's full name,
4678 In X11R4, the fonts did not come with their canonical names
4696 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4697 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4698 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4700 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4702 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4703 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4704 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4707 fontname
= full_name
;
4710 /* Compute the scroll bar width in character columns. */
4711 if (f
->scroll_bar_pixel_width
> 0)
4713 int wid
= FONT_WIDTH (f
->display
.x
->font
);
4714 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4717 f
->scroll_bar_cols
= 2;
4719 /* Now make the frame display the given font. */
4720 if (FRAME_X_WINDOW (f
) != 0)
4722 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->normal_gc
,
4723 f
->display
.x
->font
->fid
);
4724 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->reverse_gc
,
4725 f
->display
.x
->font
->fid
);
4726 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->cursor_gc
,
4727 f
->display
.x
->font
->fid
);
4729 frame_update_line_height (f
);
4730 x_set_window_size (f
, 0, f
->width
, f
->height
);
4733 /* If we are setting a new frame's font for the first time,
4734 there are no faces yet, so this font's height is the line height. */
4735 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
4738 Lisp_Object lispy_name
;
4740 lispy_name
= build_string (fontname
);
4742 /* Free the information from XListFonts. The data
4743 we actually retain comes from XLoadQueryFont. */
4744 XFreeFontNames (font_names
);
4750 x_calc_absolute_position (f
)
4754 int win_x
= 0, win_y
= 0;
4755 int flags
= f
->display
.x
->size_hint_flags
;
4757 /* Find the position of the outside upper-left corner of
4758 the inner window, with respect to the outer window. */
4759 if (f
->display
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4762 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4764 /* From-window, to-window. */
4765 f
->display
.x
->window_desc
,
4766 f
->display
.x
->parent_desc
,
4768 /* From-position, to-position. */
4769 0, 0, &win_x
, &win_y
,
4776 /* Treat negative positions as relative to the leftmost bottommost
4777 position that fits on the screen. */
4778 if (flags
& XNegative
)
4779 f
->display
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4780 - 2 * f
->display
.x
->border_width
- win_x
4782 + f
->display
.x
->left_pos
);
4784 if (flags
& YNegative
)
4785 f
->display
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
4786 - 2 * f
->display
.x
->border_width
- win_y
4788 + f
->display
.x
->top_pos
);
4789 /* The left_pos and top_pos
4790 are now relative to the top and left screen edges,
4791 so the flags should correspond. */
4792 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4795 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4796 to really change the position, and 0 when calling from
4797 x_make_frame_visible (in that case, XOFF and YOFF are the current
4798 position values). */
4800 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4802 register int xoff
, yoff
;
4807 f
->display
.x
->top_pos
= yoff
;
4808 f
->display
.x
->left_pos
= xoff
;
4809 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4811 f
->display
.x
->size_hint_flags
|= XNegative
;
4813 f
->display
.x
->size_hint_flags
|= YNegative
;
4814 f
->display
.x
->win_gravity
= NorthWestGravity
;
4816 x_calc_absolute_position (f
);
4819 x_wm_set_size_hint (f
, 0, 0);
4821 #ifdef USE_X_TOOLKIT
4822 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
),
4823 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4824 #else /* not USE_X_TOOLKIT */
4825 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4826 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4827 #endif /* not USE_X_TOOLKIT */
4831 /* Call this to change the size of frame F's x-window.
4832 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4833 for this size change and subsequent size changes.
4834 Otherwise we leave the window gravity unchanged. */
4836 x_set_window_size (f
, change_gravity
, cols
, rows
)
4841 int pixelwidth
, pixelheight
;
4844 #ifdef USE_X_TOOLKIT
4847 /* The x and y position of the widget is clobbered by the
4848 call to XtSetValues within EmacsFrameSetCharSize.
4849 This is a real kludge, but I don't understand Xt so I can't
4850 figure out a correct fix. Can anyone else tell me? -- rms. */
4851 int xpos
= f
->display
.x
->widget
->core
.x
;
4852 int ypos
= f
->display
.x
->widget
->core
.y
;
4853 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4854 f
->display
.x
->widget
->core
.x
= xpos
;
4855 f
->display
.x
->widget
->core
.y
= ypos
;
4859 #else /* not USE_X_TOOLKIT */
4863 check_frame_size (f
, &rows
, &cols
);
4864 f
->display
.x
->vertical_scroll_bar_extra
4865 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4867 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4868 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4869 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
4870 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4871 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4873 f
->display
.x
->win_gravity
= NorthWestGravity
;
4874 x_wm_set_size_hint (f
, 0, 0);
4876 XSync (FRAME_X_DISPLAY (f
), False
);
4877 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4878 pixelwidth
, pixelheight
);
4880 /* Now, strictly speaking, we can't be sure that this is accurate,
4881 but the window manager will get around to dealing with the size
4882 change request eventually, and we'll hear how it went when the
4883 ConfigureNotify event gets here.
4885 We could just not bother storing any of this information here,
4886 and let the ConfigureNotify event set everything up, but that
4887 might be kind of confusing to the lisp code, since size changes
4888 wouldn't be reported in the frame parameters until some random
4889 point in the future when the ConfigureNotify event arrives. */
4890 change_frame_size (f
, rows
, cols
, 0, 0);
4891 PIXEL_WIDTH (f
) = pixelwidth
;
4892 PIXEL_HEIGHT (f
) = pixelheight
;
4894 /* If cursor was outside the new size, mark it as off. */
4895 if (f
->phys_cursor_y
>= rows
4896 || f
->phys_cursor_x
>= cols
)
4898 f
->phys_cursor_x
= -1;
4899 f
->phys_cursor_y
= -1;
4902 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4903 receive in the ConfigureNotify event; if we get what we asked
4904 for, then the event won't cause the screen to become garbaged, so
4905 we have to make sure to do it here. */
4906 SET_FRAME_GARBAGED (f
);
4908 XFlush (FRAME_X_DISPLAY (f
));
4910 #endif /* not USE_X_TOOLKIT */
4913 /* Mouse warping, focus shifting, raising and lowering. */
4916 x_set_mouse_position (f
, x
, y
)
4922 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4923 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
4925 if (pix_x
< 0) pix_x
= 0;
4926 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4928 if (pix_y
< 0) pix_y
= 0;
4929 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4933 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4934 0, 0, 0, 0, pix_x
, pix_y
);
4938 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
4941 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4947 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4948 0, 0, 0, 0, pix_x
, pix_y
);
4952 x_focus_on_frame (f
)
4955 #if 0 /* This proves to be unpleasant. */
4959 /* I don't think that the ICCCM allows programs to do things like this
4960 without the interaction of the window manager. Whatever you end up
4961 doing with this code, do it to x_unfocus_frame too. */
4962 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4963 RevertToPointerRoot
, CurrentTime
);
4971 /* Look at the remarks in x_focus_on_frame. */
4972 if (x_focus_frame
== f
)
4973 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
4974 RevertToPointerRoot
, CurrentTime
);
4978 /* Raise frame F. */
4983 if (f
->async_visible
)
4986 #ifdef USE_X_TOOLKIT
4987 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4988 #else /* not USE_X_TOOLKIT */
4989 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4990 #endif /* not USE_X_TOOLKIT */
4991 XFlush (FRAME_X_DISPLAY (f
));
4996 /* Lower frame F. */
5001 if (f
->async_visible
)
5004 #ifdef USE_X_TOOLKIT
5005 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
5006 #else /* not USE_X_TOOLKIT */
5007 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5008 #endif /* not USE_X_TOOLKIT */
5009 XFlush (FRAME_X_DISPLAY (f
));
5015 XTframe_raise_lower (f
, raise
)
5025 /* Change from withdrawn state to mapped state,
5028 x_make_frame_visible (f
)
5036 type
= x_icon_type (f
);
5038 x_bitmap_icon (f
, type
);
5040 if (! FRAME_VISIBLE_P (f
))
5042 #ifndef USE_X_TOOLKIT
5043 if (! FRAME_ICONIFIED_P (f
))
5044 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5047 if (! EQ (Vx_no_window_manager
, Qt
))
5048 x_wm_set_window_state (f
, NormalState
);
5049 #ifdef USE_X_TOOLKIT
5050 /* This was XtPopup, but that did nothing for an iconified frame. */
5051 XtMapWidget (f
->display
.x
->widget
);
5052 #else /* not USE_X_TOOLKIT */
5053 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5054 #endif /* not USE_X_TOOLKIT */
5055 #if 0 /* This seems to bring back scroll bars in the wrong places
5056 if the window configuration has changed. They seem
5057 to come back ok without this. */
5058 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5059 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5063 XFlush (FRAME_X_DISPLAY (f
));
5065 /* Synchronize to ensure Emacs knows the frame is visible
5066 before we do anything else. We do this loop with input not blocked
5067 so that incoming events are handled. */
5070 int count
= input_signal_count
;
5072 /* This must come after we set COUNT. */
5075 XSETFRAME (frame
, f
);
5080 /* Once we have handled input events,
5081 we should have received the MapNotify if one is coming.
5082 So if we have not got it yet, stop looping.
5083 Some window managers make their own decisions
5084 about visibility. */
5085 if (input_signal_count
!= count
)
5087 /* Machines that do polling rather than SIGIO have been observed
5088 to go into a busy-wait here. So we'll fake an alarm signal
5089 to let the handler know that there's something to be read.
5090 We used to raise a real alarm, but it seems that the handler
5091 isn't always enabled here. This is probably a bug. */
5092 if (input_polling_used ())
5094 /* It could be confusing if a real alarm arrives while processing
5095 the fake one. Turn it off and let the handler reset it. */
5097 input_poll_signal ();
5099 /* Once we have handled input events,
5100 we should have received the MapNotify if one is coming.
5101 So if we have not got it yet, stop looping.
5102 Some window managers make their own decisions
5103 about visibility. */
5104 if (input_signal_count
!= count
)
5107 FRAME_SAMPLE_VISIBILITY (f
);
5111 /* Change from mapped state to withdrawn state. */
5113 x_make_frame_invisible (f
)
5119 #ifdef USE_X_TOOLKIT
5120 /* Use the frame's outermost window, not the one we normally draw on. */
5121 window
= XtWindow (f
->display
.x
->widget
);
5122 #else /* not USE_X_TOOLKIT */
5123 window
= FRAME_X_WINDOW (f
);
5124 #endif /* not USE_X_TOOLKIT */
5126 /* Don't keep the highlight on an invisible frame. */
5127 if (x_highlight_frame
== f
)
5128 x_highlight_frame
= 0;
5130 #if 0/* This might add unreliability; I don't trust it -- rms. */
5131 if (! f
->async_visible
&& ! f
->async_iconified
)
5137 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5138 that the current position of the window is user-specified, rather than
5139 program-specified, so that when the window is mapped again, it will be
5140 placed at the same location, without forcing the user to position it
5141 by hand again (they have already done that once for this window.) */
5142 x_wm_set_size_hint (f
, 0, 1);
5146 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5147 DefaultScreen (FRAME_X_DISPLAY (f
))))
5149 UNBLOCK_INPUT_RESIGNAL
;
5150 error ("Can't notify window manager of window withdrawal");
5152 #else /* ! defined (HAVE_X11R4) */
5154 /* Tell the window manager what we're going to do. */
5155 if (! EQ (Vx_no_window_manager
, Qt
))
5159 unmap
.xunmap
.type
= UnmapNotify
;
5160 unmap
.xunmap
.window
= window
;
5161 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5162 unmap
.xunmap
.from_configure
= False
;
5163 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5164 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5166 SubstructureRedirectMask
|SubstructureNotifyMask
,
5169 UNBLOCK_INPUT_RESIGNAL
;
5170 error ("Can't notify window manager of withdrawal");
5174 /* Unmap the window ourselves. Cheeky! */
5175 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5176 #endif /* ! defined (HAVE_X11R4) */
5178 /* We can't distinguish this from iconification
5179 just by the event that we get from the server.
5180 So we can't win using the usual strategy of letting
5181 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5182 and synchronize with the server to make sure we agree. */
5184 FRAME_ICONIFIED_P (f
) = 0;
5185 f
->async_visible
= 0;
5186 f
->async_iconified
= 0;
5193 /* Change window state from mapped to iconified. */
5202 /* Don't keep the highlight on an invisible frame. */
5203 if (x_highlight_frame
== f
)
5204 x_highlight_frame
= 0;
5206 if (f
->async_iconified
)
5211 type
= x_icon_type (f
);
5213 x_bitmap_icon (f
, type
);
5215 #ifdef USE_X_TOOLKIT
5217 if (! FRAME_VISIBLE_P (f
))
5219 if (! EQ (Vx_no_window_manager
, Qt
))
5220 x_wm_set_window_state (f
, IconicState
);
5221 /* This was XtPopup, but that did nothing for an iconified frame. */
5222 XtMapWidget (f
->display
.x
->widget
);
5227 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5228 XtWindow (f
->display
.x
->widget
),
5229 DefaultScreen (FRAME_X_DISPLAY (f
)));
5233 error ("Can't notify window manager of iconification");
5235 f
->async_iconified
= 1;
5238 XFlush (FRAME_X_DISPLAY (f
));
5240 #else /* not USE_X_TOOLKIT */
5242 /* Make sure the X server knows where the window should be positioned,
5243 in case the user deiconifies with the window manager. */
5244 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5245 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5247 /* Since we don't know which revision of X we're running, we'll use both
5248 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5250 /* X11R4: send a ClientMessage to the window manager using the
5251 WM_CHANGE_STATE type. */
5255 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5256 message
.xclient
.type
= ClientMessage
;
5257 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5258 message
.xclient
.format
= 32;
5259 message
.xclient
.data
.l
[0] = IconicState
;
5261 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5262 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5264 SubstructureRedirectMask
| SubstructureNotifyMask
,
5267 UNBLOCK_INPUT_RESIGNAL
;
5268 error ("Can't notify window manager of iconification");
5272 /* X11R3: set the initial_state field of the window manager hints to
5274 x_wm_set_window_state (f
, IconicState
);
5276 if (!FRAME_VISIBLE_P (f
))
5278 /* If the frame was withdrawn, before, we must map it. */
5279 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5282 f
->async_iconified
= 1;
5284 XFlush (FRAME_X_DISPLAY (f
));
5286 #endif /* not USE_X_TOOLKIT */
5289 /* Destroy the X window of frame F. */
5291 x_destroy_window (f
)
5294 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5298 if (f
->display
.x
->icon_desc
!= 0)
5299 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->icon_desc
);
5300 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->window_desc
);
5301 #ifdef USE_X_TOOLKIT
5302 XtDestroyWidget (f
->display
.x
->widget
);
5303 free_frame_menubar (f
);
5304 #endif /* USE_X_TOOLKIT */
5306 free_frame_faces (f
);
5307 XFlush (FRAME_X_DISPLAY (f
));
5309 xfree (f
->display
.x
);
5311 if (f
== x_focus_frame
)
5313 if (f
== x_focus_event_frame
)
5314 x_focus_event_frame
= 0;
5315 if (f
== x_highlight_frame
)
5316 x_highlight_frame
= 0;
5318 dpyinfo
->reference_count
--;
5320 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5322 dpyinfo
->mouse_face_beg_row
5323 = dpyinfo
->mouse_face_beg_col
= -1;
5324 dpyinfo
->mouse_face_end_row
5325 = dpyinfo
->mouse_face_end_col
= -1;
5326 dpyinfo
->mouse_face_window
= Qnil
;
5332 /* Setting window manager hints. */
5334 /* Set the normal size hints for the window manager, for frame F.
5335 FLAGS is the flags word to use--or 0 meaning preserve the flags
5336 that the window now has.
5337 If USER_POSITION is nonzero, we set the USPosition
5338 flag (this is useful when FLAGS is 0). */
5340 x_wm_set_size_hint (f
, flags
, user_position
)
5345 XSizeHints size_hints
;
5347 #ifdef USE_X_TOOLKIT
5350 Dimension widget_width
, widget_height
;
5351 Window window
= XtWindow (f
->display
.x
->widget
);
5352 #else /* not USE_X_TOOLKIT */
5353 Window window
= FRAME_X_WINDOW (f
);
5354 #endif /* not USE_X_TOOLKIT */
5356 /* Setting PMaxSize caused various problems. */
5357 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5359 flexlines
= f
->height
;
5361 size_hints
.x
= f
->display
.x
->left_pos
;
5362 size_hints
.y
= f
->display
.x
->top_pos
;
5364 #ifdef USE_X_TOOLKIT
5365 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5366 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5367 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5368 size_hints
.height
= widget_height
;
5369 size_hints
.width
= widget_width
;
5370 #else /* not USE_X_TOOLKIT */
5371 size_hints
.height
= PIXEL_HEIGHT (f
);
5372 size_hints
.width
= PIXEL_WIDTH (f
);
5373 #endif /* not USE_X_TOOLKIT */
5375 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5376 size_hints
.height_inc
= f
->display
.x
->line_height
;
5377 size_hints
.max_width
5378 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5379 size_hints
.max_height
5380 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5383 int base_width
, base_height
;
5384 int min_rows
= 0, min_cols
= 0;
5386 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5387 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5389 check_frame_size (f
, &min_rows
, &min_cols
);
5391 /* The window manager uses the base width hints to calculate the
5392 current number of rows and columns in the frame while
5393 resizing; min_width and min_height aren't useful for this
5394 purpose, since they might not give the dimensions for a
5395 zero-row, zero-column frame.
5397 We use the base_width and base_height members if we have
5398 them; otherwise, we set the min_width and min_height members
5399 to the size for a zero x zero frame. */
5402 size_hints
.flags
|= PBaseSize
;
5403 size_hints
.base_width
= base_width
;
5404 size_hints
.base_height
= base_height
;
5405 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5406 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5408 size_hints
.min_width
= base_width
;
5409 size_hints
.min_height
= base_height
;
5414 size_hints
.flags
|= flags
;
5417 XSizeHints hints
; /* Sometimes I hate X Windows... */
5418 long supplied_return
;
5422 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5425 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5430 if (hints
.flags
& PSize
)
5431 size_hints
.flags
|= PSize
;
5432 if (hints
.flags
& PPosition
)
5433 size_hints
.flags
|= PPosition
;
5434 if (hints
.flags
& USPosition
)
5435 size_hints
.flags
|= USPosition
;
5436 if (hints
.flags
& USSize
)
5437 size_hints
.flags
|= USSize
;
5441 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5442 size_hints
.flags
|= PWinGravity
;
5446 size_hints
.flags
&= ~ PPosition
;
5447 size_hints
.flags
|= USPosition
;
5449 #endif /* PWinGravity */
5452 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5454 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5458 /* Used for IconicState or NormalState */
5459 x_wm_set_window_state (f
, state
)
5463 #ifdef USE_X_TOOLKIT
5466 XtSetArg (al
[0], XtNinitialState
, state
);
5467 XtSetValues (f
->display
.x
->widget
, al
, 1);
5468 #else /* not USE_X_TOOLKIT */
5469 Window window
= FRAME_X_WINDOW (f
);
5471 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5472 f
->display
.x
->wm_hints
.initial_state
= state
;
5474 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5475 #endif /* not USE_X_TOOLKIT */
5478 x_wm_set_icon_pixmap (f
, pixmap_id
)
5482 #ifdef USE_X_TOOLKIT
5483 Window window
= XtWindow (f
->display
.x
->widget
);
5485 Window window
= FRAME_X_WINDOW (f
);
5490 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5491 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5492 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5496 f
->display
.x
->wm_hints
.icon_pixmap
= None
;
5497 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5500 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5503 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5507 #ifdef USE_X_TOOLKIT
5508 Window window
= XtWindow (f
->display
.x
->widget
);
5510 Window window
= FRAME_X_WINDOW (f
);
5513 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5514 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5515 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5517 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5521 /* Initialization. */
5523 #ifdef USE_X_TOOLKIT
5524 static XrmOptionDescRec emacs_options
[] = {
5525 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5526 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5528 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5529 XrmoptionSepArg
, NULL
},
5530 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5532 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5533 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5534 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5535 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5536 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5537 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5538 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5540 #endif /* USE_X_TOOLKIT */
5542 static int x_initialized
;
5545 /* Test whether two display-name strings agree up to the dot that separates
5546 the screen number from the server number. */
5548 same_x_server (name1
, name2
)
5549 char *name1
, *name2
;
5552 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
5556 if (seen_colon
&& *name1
== '.')
5560 && (*name1
== '.' || *name1
== '\0')
5561 && (*name2
== '.' || *name2
== '\0'));
5565 struct x_display_info
*
5566 x_term_init (display_name
, xrm_option
, resource_name
)
5567 Lisp_Object display_name
;
5569 char *resource_name
;
5575 struct x_display_info
*dpyinfo
;
5584 #ifdef USE_X_TOOLKIT
5586 XtSetLanguageProc (NULL
, NULL
, NULL
);
5597 argv
[argc
++] = "-xrm";
5598 argv
[argc
++] = xrm_option
;
5600 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5601 resource_name
, EMACS_CLASS
,
5602 emacs_options
, XtNumber (emacs_options
),
5606 #else /* not USE_X_TOOLKIT */
5608 XSetLocaleModifiers ("");
5610 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5611 #endif /* not USE_X_TOOLKIT */
5613 /* Detect failure. */
5617 /* We have definitely succeeded. Record the new connection. */
5619 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5623 struct x_display_info
*share
;
5626 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
5627 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
5628 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
5629 XSTRING (display_name
)->data
))
5632 dpyinfo
->kboard
= share
->kboard
;
5635 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
5636 init_kboard (dpyinfo
->kboard
);
5637 dpyinfo
->kboard
->next_kboard
= all_kboards
;
5638 all_kboards
= dpyinfo
->kboard
;
5640 dpyinfo
->kboard
->reference_count
++;
5644 /* Put this display on the chain. */
5645 dpyinfo
->next
= x_display_list
;
5646 x_display_list
= dpyinfo
;
5648 /* Put it on x_display_name_list as well, to keep them parallel. */
5649 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5650 x_display_name_list
);
5651 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5653 dpyinfo
->display
= dpy
;
5656 XSetAfterFunction (x_current_display
, x_trace_wire
);
5660 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5661 + XSTRING (Vsystem_name
)->size
5663 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5664 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5666 /* Figure out which modifier bits mean what. */
5667 x_find_modifier_meanings (dpyinfo
);
5669 /* Get the scroll bar cursor. */
5670 dpyinfo
->vertical_scroll_bar_cursor
5671 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5673 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5674 resource_name
, EMACS_CLASS
);
5675 #ifdef HAVE_XRMSETDATABASE
5676 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5678 dpyinfo
->display
->db
= xrdb
;
5680 /* Put the rdb where we can find it in a way that works on
5682 dpyinfo
->xrdb
= xrdb
;
5684 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5685 DefaultScreen (dpyinfo
->display
));
5686 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5687 &dpyinfo
->n_planes
);
5688 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
5689 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
5690 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
5691 dpyinfo
->grabbed
= 0;
5692 dpyinfo
->reference_count
= 0;
5693 dpyinfo
->icon_bitmap_id
= -1;
5694 dpyinfo
->n_fonts
= 0;
5695 dpyinfo
->font_table_size
= 0;
5696 dpyinfo
->bitmaps
= 0;
5697 dpyinfo
->bitmaps_size
= 0;
5698 dpyinfo
->bitmaps_last
= 0;
5699 dpyinfo
->scratch_cursor_gc
= 0;
5700 dpyinfo
->mouse_face_mouse_frame
= 0;
5701 dpyinfo
->mouse_face_deferred_gc
= 0;
5702 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5703 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5704 dpyinfo
->mouse_face_face_id
= 0;
5705 dpyinfo
->mouse_face_window
= Qnil
;
5706 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
5707 dpyinfo
->mouse_face_defer
= 0;
5709 dpyinfo
->Xatom_wm_protocols
5710 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
5711 dpyinfo
->Xatom_wm_take_focus
5712 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
5713 dpyinfo
->Xatom_wm_save_yourself
5714 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
5715 dpyinfo
->Xatom_wm_delete_window
5716 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
5717 dpyinfo
->Xatom_wm_change_state
5718 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
5719 dpyinfo
->Xatom_wm_configure_denied
5720 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
5721 dpyinfo
->Xatom_wm_window_moved
5722 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
5723 dpyinfo
->Xatom_editres
5724 = XInternAtom (dpyinfo
->display
, "Editres", False
);
5725 dpyinfo
->Xatom_CLIPBOARD
5726 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
5727 dpyinfo
->Xatom_TIMESTAMP
5728 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
5730 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
5731 dpyinfo
->Xatom_DELETE
5732 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
5733 dpyinfo
->Xatom_MULTIPLE
5734 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
5736 = XInternAtom (dpyinfo
->display
, "INCR", False
);
5737 dpyinfo
->Xatom_EMACS_TMP
5738 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
5739 dpyinfo
->Xatom_TARGETS
5740 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
5742 = XInternAtom (dpyinfo
->display
, "NULL", False
);
5743 dpyinfo
->Xatom_ATOM_PAIR
5744 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
5746 dpyinfo
->cut_buffers_initialized
= 0;
5748 connection
= ConnectionNumber (dpyinfo
->display
);
5749 dpyinfo
->connection
= connection
;
5752 /* This is only needed for distinguishing keyboard and process input. */
5753 if (connection
!= 0)
5754 add_keyboard_wait_descriptor (connection
);
5757 #ifndef F_SETOWN_BUG
5759 #ifdef F_SETOWN_SOCK_NEG
5760 /* stdin is a socket here */
5761 fcntl (connection
, F_SETOWN
, -getpid ());
5762 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5763 fcntl (connection
, F_SETOWN
, getpid ());
5764 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5765 #endif /* ! defined (F_SETOWN) */
5766 #endif /* F_SETOWN_BUG */
5769 init_sigio (connection
);
5770 #endif /* ! defined (SIGIO) */
5775 /* Get rid of display DPYINFO, assuming all frames are already gone,
5776 and without sending any more commands to the X server. */
5779 x_delete_display (dpyinfo
)
5780 struct x_display_info
*dpyinfo
;
5782 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
5784 /* Discard this display from x_display_name_list and x_display_list.
5785 We can't use Fdelq because that can quit. */
5786 if (! NILP (x_display_name_list
)
5787 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
5788 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
5793 tail
= x_display_name_list
;
5794 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
5796 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
5797 dpyinfo
->name_list_element
))
5799 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
5802 tail
= XCONS (tail
)->cdr
;
5806 if (x_display_list
== dpyinfo
)
5807 x_display_list
= dpyinfo
->next
;
5810 struct x_display_info
*tail
;
5812 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
5813 if (tail
->next
== dpyinfo
)
5814 tail
->next
= tail
->next
->next
;
5817 #ifndef USE_X_TOOLKIT
5818 /* I'm told Xt does this itself. */
5819 XrmDestroyDatabase (dpyinfo
->xrdb
);
5822 if (--dpyinfo
->kboard
->reference_count
== 0)
5823 delete_kboard (dpyinfo
->kboard
);
5825 xfree (dpyinfo
->font_table
);
5826 xfree (dpyinfo
->x_id_name
);
5830 /* Set up use of X before we make the first connection. */
5834 clear_frame_hook
= XTclear_frame
;
5835 clear_end_of_line_hook
= XTclear_end_of_line
;
5836 ins_del_lines_hook
= XTins_del_lines
;
5837 change_line_highlight_hook
= XTchange_line_highlight
;
5838 insert_glyphs_hook
= XTinsert_glyphs
;
5839 write_glyphs_hook
= XTwrite_glyphs
;
5840 delete_glyphs_hook
= XTdelete_glyphs
;
5841 ring_bell_hook
= XTring_bell
;
5842 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5843 set_terminal_modes_hook
= XTset_terminal_modes
;
5844 update_begin_hook
= XTupdate_begin
;
5845 update_end_hook
= XTupdate_end
;
5846 set_terminal_window_hook
= XTset_terminal_window
;
5847 read_socket_hook
= XTread_socket
;
5848 frame_up_to_date_hook
= XTframe_up_to_date
;
5849 cursor_to_hook
= XTcursor_to
;
5850 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5851 mouse_position_hook
= XTmouse_position
;
5852 frame_rehighlight_hook
= XTframe_rehighlight
;
5853 frame_raise_lower_hook
= XTframe_raise_lower
;
5854 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5855 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5856 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5857 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5859 scroll_region_ok
= 1; /* we'll scroll partial frames */
5860 char_ins_del_ok
= 0; /* just as fast to write the line */
5861 line_ins_del_ok
= 1; /* we'll just blt 'em */
5862 fast_clear_end_of_line
= 1; /* X does this well */
5863 memory_below_frame
= 0; /* we don't remember what scrolls
5869 x_focus_frame
= x_highlight_frame
= 0;
5871 /* Try to use interrupt input; if we can't, then start polling. */
5872 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5874 #ifdef USE_X_TOOLKIT
5875 XtToolkitInitialize ();
5876 Xt_app_con
= XtCreateApplicationContext ();
5879 /* Note that there is no real way portable across R3/R4 to get the
5880 original error handler. */
5881 XSetErrorHandler (x_error_quitter
);
5882 XSetIOErrorHandler (x_io_error_quitter
);
5884 /* Disable Window Change signals; they are handled by X events. */
5886 signal (SIGWINCH
, SIG_DFL
);
5887 #endif /* ! defined (SIGWINCH) */
5889 signal (SIGPIPE
, x_connection_signal
);
5895 staticpro (&x_display_name_list
);
5896 x_display_name_list
= Qnil
;
5898 staticpro (&last_mouse_scroll_bar
);
5899 last_mouse_scroll_bar
= Qnil
;
5901 #endif /* ! defined (HAVE_X_WINDOWS) */