1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
60 #ifndef INCLUDED_FCNTL
67 #include <sys/param.h>
70 #include "dispextern.h"
71 #include "termhooks.h"
83 #include "intervals.h"
86 extern void free_frame_menubar ();
87 extern void _XEditResCheckMessages ();
88 #endif /* USE_X_TOOLKIT */
91 #define x_any_window_to_frame x_window_to_frame
92 #define x_top_window_to_frame x_window_to_frame
96 #ifndef XtNinitialState
97 #define XtNinitialState "initialState"
101 #define min(a,b) ((a)<(b) ? (a) : (b))
102 #define max(a,b) ((a)>(b) ? (a) : (b))
104 /* This is a chain of structures for all the X displays currently in use. */
105 struct x_display_info
*x_display_list
;
107 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
108 one for each element of x_display_list and in the same order.
109 NAME is the name of the frame.
110 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
111 Lisp_Object x_display_name_list
;
113 /* Frame being updated by update_frame. This is declared in term.c.
114 This is set by update_begin and looked at by all the
115 XT functions. It is zero while not inside an update.
116 In that case, the XT functions assume that `selected_frame'
117 is the frame to apply to. */
118 extern struct frame
*updating_frame
;
120 /* The frame (if any) which has the X window that has keyboard focus.
121 Zero if none. This is examined by Ffocus_frame in frame.c. Note
122 that a mere EnterNotify event can set this; if you need to know the
123 last frame specified in a FocusIn or FocusOut event, use
124 x_focus_event_frame. */
125 struct frame
*x_focus_frame
;
127 /* This is a frame waiting to be autoraised, within XTread_socket. */
128 struct frame
*pending_autoraise_frame
;
130 /* The last frame mentioned in a FocusIn or FocusOut event. This is
131 separate from x_focus_frame, because whether or not LeaveNotify
132 events cause us to lose focus depends on whether or not we have
133 received a FocusIn event for it. */
134 struct frame
*x_focus_event_frame
;
136 /* The frame which currently has the visual highlight, and should get
137 keyboard input (other sorts of input have the frame encoded in the
138 event). It points to the X focus frame's selected window's
139 frame. It differs from x_focus_frame when we're using a global
141 static struct frame
*x_highlight_frame
;
144 /* The application context for Xt use. */
145 XtAppContext Xt_app_con
;
148 /* During an update, maximum vpos for ins/del line operations to affect. */
150 static int flexlines
;
152 /* During an update, nonzero if chars output now should be highlighted. */
154 static int highlight
;
156 /* Nominal cursor position -- where to draw output.
157 During an update, these are different from the cursor-box position. */
164 In order to avoid asking for motion events and then throwing most
165 of them away or busy-polling the server for mouse positions, we ask
166 the server for pointer motion hints. This means that we get only
167 one event per group of mouse movements. "Groups" are delimited by
168 other kinds of events (focus changes and button clicks, for
169 example), or by XQueryPointer calls; when one of these happens, we
170 get another MotionNotify event the next time the mouse moves. This
171 is at least as efficient as getting motion events when mouse
172 tracking is on, and I suspect only negligibly worse when tracking
175 The silly O'Reilly & Associates Nutshell guides barely document
176 pointer motion hints at all (I think you have to infer how they
177 work from an example), and the description of XQueryPointer doesn't
178 mention that calling it causes you to get another motion hint from
179 the server, which is very important. */
181 /* Where the mouse was last time we reported a mouse event. */
182 static FRAME_PTR last_mouse_frame
;
183 static XRectangle last_mouse_glyph
;
185 /* The scroll bar in which the last X motion event occurred.
187 If the last X motion event occurred in a scroll bar, we set this
188 so XTmouse_position can know whether to report a scroll bar motion or
191 If the last X motion event didn't occur in a scroll bar, we set this
192 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
193 static Lisp_Object last_mouse_scroll_bar
;
195 /* This is a hack. We would really prefer that XTmouse_position would
196 return the time associated with the position it returns, but there
197 doesn't seem to be any way to wrest the timestamp from the server
198 along with the position query. So, we just keep track of the time
199 of the last movement we received, and return that in hopes that
200 it's somewhat accurate. */
201 static Time last_mouse_movement_time
;
203 /* Incremented by XTread_socket whenever it really tries to read events. */
205 static int volatile input_signal_count
;
207 static int input_signal_count
;
210 /* Used locally within XTread_socket. */
211 static int x_noop_count
;
213 /* Initial values of argv and argc. */
214 extern char **initial_argv
;
215 extern int initial_argc
;
217 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
219 /* Tells if a window manager is present or not. */
221 extern Lisp_Object Vx_no_window_manager
;
223 /* Nonzero enables some debugging for the X interface code. */
226 extern Lisp_Object Qface
, Qmouse_face
;
230 /* A mask of extra modifier bits to put into every keyboard char. */
231 extern int extra_keyboard_modifiers
;
233 extern XrmDatabase
x_load_resources ();
235 void x_delete_display ();
237 static void flashback ();
238 static void redraw_previous_char ();
239 static void redraw_following_char ();
240 static unsigned int x_x_to_emacs_modifiers ();
242 static int fast_find_position ();
243 static void note_mouse_highlight ();
244 static void clear_mouse_face ();
245 static void show_mouse_face ();
246 static void do_line_dance ();
248 static int XTcursor_to ();
249 static int XTclear_end_of_line ();
250 static int x_io_error_quitter ();
252 /* Return the struct x_display_info corresponding to DPY. */
254 struct x_display_info
*
255 x_display_info_for_display (dpy
)
258 struct x_display_info
*dpyinfo
;
260 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
261 if (dpyinfo
->display
== dpy
)
267 /* Starting and ending updates.
269 These hooks are called by update_frame at the beginning and end
270 of a frame update. We record in `updating_frame' the identity
271 of the frame being updated, so that the XT... functions do not
272 need to take a frame as argument. Most of the XT... functions
273 should never be called except during an update, the only exceptions
274 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
285 flexlines
= f
->height
;
290 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
292 /* Don't do highlighting for mouse motion during the update. */
293 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
295 /* If the frame needs to be redrawn,
296 simply forget about any prior mouse highlighting. */
297 if (FRAME_GARBAGED_P (f
))
298 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
300 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
302 int firstline
, lastline
, i
;
303 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
305 /* Find the first, and the last+1, lines affected by redisplay. */
306 for (firstline
= 0; firstline
< f
->height
; firstline
++)
307 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
310 lastline
= f
->height
;
311 for (i
= f
->height
- 1; i
>= 0; i
--)
313 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
319 /* Can we tell that this update does not affect the window
320 where the mouse highlight is? If so, no need to turn off.
321 Likewise, don't do anything if the frame is garbaged;
322 in that case, the FRAME_CURRENT_GLYPHS that we would use
323 are all wrong, and we will redisplay that line anyway. */
324 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
325 || lastline
< XFASTINT (w
->top
)))
326 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
342 x_display_cursor (f
, 1);
344 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
345 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
347 /* This fails in the case of having updated only the echo area
348 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
349 has no relation to the current contents, and its charstarts
350 have no relation to the contents of the window-buffer.
351 I don't know a clean way to check
352 for that case. window_end_valid isn't set up yet. */
353 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
354 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
355 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
358 XFlush (FRAME_X_DISPLAY (f
));
362 /* This is called after a redisplay on frame F. */
365 XTframe_up_to_date (f
)
368 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
369 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
371 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
372 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
373 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
374 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
378 /* External interface to control of standout mode.
379 Call this when about to modify line at position VPOS
380 and not change whether it is highlighted. */
382 XTreassert_line_highlight (new, vpos
)
388 /* Call this when about to modify line at position VPOS
389 and change whether it is highlighted. */
392 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
393 int new_highlight
, vpos
, first_unused_hpos
;
395 highlight
= new_highlight
;
396 XTcursor_to (vpos
, 0);
397 XTclear_end_of_line (updating_frame
->width
);
400 /* This is used when starting Emacs and when restarting after suspend.
401 When starting Emacs, no X window is mapped. And nothing must be done
402 to Emacs's own window if it is suspended (though that rarely happens). */
405 XTset_terminal_modes ()
409 /* This is called when exiting or suspending Emacs.
410 Exiting will make the X-windows go away, and suspending
411 requires no action. */
414 XTreset_terminal_modes ()
416 /* XTclear_frame (); */
419 /* Set the nominal cursor position of the frame.
420 This is where display update commands will take effect.
421 This does not affect the place where the cursor-box is displayed. */
424 XTcursor_to (row
, col
)
425 register int row
, col
;
433 if (updating_frame
== 0)
436 x_display_cursor (selected_frame
, 1);
437 XFlush (FRAME_X_DISPLAY (selected_frame
));
442 /* Display a sequence of N glyphs found at GP.
443 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
444 HL is 1 if this text is highlighted, 2 if the cursor is on it,
445 3 if should appear in its mouse-face.
446 JUST_FOREGROUND if 1 means draw only the foreground;
447 don't alter the background.
449 FONT is the default font to use (for glyphs whose font-code is 0).
451 Since the display generation code is responsible for calling
452 compute_char_face and compute_glyph_face on everything it puts in
453 the display structure, we can assume that the face code on each
454 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
455 to which we can actually apply intern_face.
456 Call this function with input blocked. */
459 /* This is the multi-face code. */
462 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
465 register GLYPH
*gp
; /* Points to first GLYPH. */
466 register int n
; /* Number of glyphs to display. */
470 /* Holds characters to be displayed. */
471 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
472 register char *cp
; /* Steps through buf[]. */
473 register int tlen
= GLYPH_TABLE_LENGTH
;
474 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
475 Window window
= FRAME_X_WINDOW (f
);
476 int orig_left
= left
;
480 /* Get the face-code of the next GLYPH. */
484 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
485 cf
= FAST_GLYPH_FACE (g
);
487 /* Find the run of consecutive glyphs with the same face-code.
488 Extract their character codes into BUF. */
493 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
494 if (FAST_GLYPH_FACE (g
) != cf
)
497 *cp
++ = FAST_GLYPH_CHAR (g
);
502 /* LEN gets the length of the run. */
505 /* Now output this run of chars, with the font and pixel values
506 determined by the face code CF. */
508 struct face
*face
= FRAME_DEFAULT_FACE (f
);
509 XFontStruct
*font
= FACE_FONT (face
);
510 GC gc
= FACE_GC (face
);
513 /* HL = 3 means use a mouse face previously chosen. */
515 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
517 /* First look at the face of the text itself. */
520 /* It's possible for the display table to specify
521 a face code that is out of range. Use 0 in that case. */
522 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
523 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
527 face
= FRAME_MODE_LINE_FACE (f
);
529 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
530 font
= FACE_FONT (face
);
532 if (FACE_STIPPLE (face
))
536 /* Then comes the distinction between modeline and normal text. */
541 face
= FRAME_MODE_LINE_FACE (f
);
542 font
= FACE_FONT (face
);
544 if (FACE_STIPPLE (face
))
548 #define FACE_DEFAULT (~0)
550 /* Now override that if the cursor's on this character. */
553 /* The cursor overrides stippling. */
557 || (int) face
->font
== FACE_DEFAULT
558 || face
->font
== f
->display
.x
->font
)
559 && face
->background
== f
->display
.x
->background_pixel
560 && face
->foreground
== f
->display
.x
->foreground_pixel
)
562 gc
= f
->display
.x
->cursor_gc
;
564 /* Cursor on non-default face: must merge. */
570 xgcv
.background
= f
->display
.x
->cursor_pixel
;
571 xgcv
.foreground
= face
->background
;
572 /* If the glyph would be invisible,
573 try a different foreground. */
574 if (xgcv
.foreground
== xgcv
.background
)
575 xgcv
.foreground
= face
->foreground
;
576 if (xgcv
.foreground
== xgcv
.background
)
577 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
578 if (xgcv
.foreground
== xgcv
.background
)
579 xgcv
.foreground
= face
->foreground
;
580 /* Make sure the cursor is distinct from text in this face. */
581 if (xgcv
.background
== face
->background
582 && xgcv
.foreground
== face
->foreground
)
584 xgcv
.background
= face
->foreground
;
585 xgcv
.foreground
= face
->background
;
587 xgcv
.font
= face
->font
->fid
;
588 xgcv
.graphics_exposures
= 0;
589 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
590 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
591 XChangeGC (FRAME_X_DISPLAY (f
),
592 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
595 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
596 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
597 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
599 /* If this code is restored, it must also reset to the default stipple
601 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
602 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
607 if ((int) font
== FACE_DEFAULT
)
608 font
= f
->display
.x
->font
;
611 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
612 left
, top
+ FONT_BASE (font
), buf
, len
);
617 /* Turn stipple on. */
618 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
620 /* Draw stipple on background. */
621 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
623 FONT_WIDTH (font
) * len
,
626 /* Turn stipple off. */
627 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
629 /* Draw the text, solidly, onto the stipple pattern. */
630 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
631 left
, top
+ FONT_BASE (font
), buf
, len
);
634 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
635 left
, top
+ FONT_BASE (font
), buf
, len
);
637 /* Clear the rest of the line's height. */
638 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
639 XClearArea (FRAME_X_DISPLAY (f
), window
, left
,
640 top
+ FONT_HEIGHT (font
),
641 FONT_WIDTH (font
) * len
,
642 /* This is how many pixels of height
644 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
648 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
649 which often is not up to date yet. */
650 if (!just_foreground
)
652 if (left
== orig_left
)
653 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
654 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
656 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
657 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
661 /* We should probably check for XA_UNDERLINE_POSITION and
662 XA_UNDERLINE_THICKNESS properties on the font, but let's
663 just get the thing working, and come back to that. */
665 int underline_position
= 1;
667 if (font
->descent
<= underline_position
)
668 underline_position
= font
->descent
- 1;
671 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
675 + underline_position
),
676 len
* FONT_WIDTH (font
), 1);
679 left
+= len
* FONT_WIDTH (font
);
686 /* This is the old single-face code. */
689 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
692 register GLYPH
*gp
; /* Points to first GLYPH. */
693 register int n
; /* Number of glyphs to display. */
698 Window window
= FRAME_X_WINDOW (f
);
699 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
700 : (hl
? f
->display
.x
->reverse_gc
701 : f
->display
.x
->normal_gc
));
703 if (sizeof (GLYPH
) == sizeof (XChar2b
))
704 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
705 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
706 else if (sizeof (GLYPH
) == sizeof (unsigned char))
707 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
708 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
710 /* What size of glyph ARE you using? And does X have a function to
716 /* Output some text at the nominal frame cursor position.
717 Advance the cursor over the text.
718 Output LEN glyphs at START.
720 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
721 controls the pixel values used for foreground and background. */
724 XTwrite_glyphs (start
, len
)
725 register GLYPH
*start
;
728 register int temp_length
;
739 /* If not within an update,
740 output at the frame's visible cursor. */
741 curs_x
= f
->cursor_x
;
742 curs_y
= f
->cursor_y
;
746 CHAR_TO_PIXEL_COL (f
, curs_x
),
747 CHAR_TO_PIXEL_ROW (f
, curs_y
),
748 start
, len
, highlight
, 0);
750 /* If we drew on top of the cursor, note that it is turned off. */
751 if (curs_y
== f
->phys_cursor_y
752 && curs_x
<= f
->phys_cursor_x
753 && curs_x
+ len
> f
->phys_cursor_x
)
754 f
->phys_cursor_x
= -1;
756 if (updating_frame
== 0)
759 x_display_cursor (f
, 1);
768 /* Clear to the end of the line.
769 Erase the current text line from the nominal cursor position (inclusive)
770 to column FIRST_UNUSED (exclusive). The idea is that everything
771 from FIRST_UNUSED onward is already erased. */
774 XTclear_end_of_line (first_unused
)
775 register int first_unused
;
777 struct frame
*f
= updating_frame
;
783 if (curs_y
< 0 || curs_y
>= f
->height
)
785 if (first_unused
<= 0)
788 if (first_unused
>= f
->width
)
789 first_unused
= f
->width
;
795 /* Notice if the cursor will be cleared by this operation. */
796 if (curs_y
== f
->phys_cursor_y
797 && curs_x
<= f
->phys_cursor_x
798 && f
->phys_cursor_x
< first_unused
)
799 f
->phys_cursor_x
= -1;
801 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
802 CHAR_TO_PIXEL_COL (f
, curs_x
),
803 CHAR_TO_PIXEL_ROW (f
, curs_y
),
804 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
805 f
->display
.x
->line_height
, False
);
807 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
817 struct frame
*f
= updating_frame
;
822 f
->phys_cursor_x
= -1; /* Cursor not visible. */
823 curs_x
= 0; /* Nominal cursor position is top left. */
828 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
830 /* We have to clear the scroll bars, too. If we have changed
831 colors or something like that, then they should be notified. */
832 x_scroll_bar_clear (f
);
834 XFlush (FRAME_X_DISPLAY (f
));
839 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
840 always contain the right glyphs to use.
842 It also needs to be changed to look at the details of the font and
843 see whether there is really overlap, and do nothing when there is
844 not. This can use font_char_overlap_left and font_char_overlap_right,
845 but just how to use them is not clear. */
847 /* Erase the character (if any) at the position just before X, Y in frame F,
848 then redraw it and the character before it.
849 This is necessary when we erase starting at X,
850 in case the character after X overlaps into the one before X.
851 Call this function with input blocked. */
854 redraw_previous_char (f
, x
, y
, highlight_flag
)
859 /* Erase the character before the new ones, in case
860 what was here before overlaps it.
861 Reoutput that character, and the previous character
862 (in case the previous character overlaps it). */
868 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
869 CHAR_TO_PIXEL_COL (f
, x
- 1),
870 CHAR_TO_PIXEL_ROW (f
, y
),
871 FONT_WIDTH (f
->display
.x
->font
),
872 f
->display
.x
->line_height
, False
);
874 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
875 CHAR_TO_PIXEL_ROW (f
, y
),
876 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
877 x
- start_x
, highlight_flag
, 1);
881 /* Erase the character (if any) at the position X, Y in frame F,
882 then redraw it and the character after it.
883 This is necessary when we erase endng at X,
884 in case the character after X overlaps into the one before X.
885 Call this function with input blocked. */
888 redraw_following_char (f
, x
, y
, highlight_flag
)
893 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
894 /* Erase the character after the new ones, in case
895 what was here before overlaps it.
896 Reoutput that character, and the following character
897 (in case the following character overlaps it). */
899 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
904 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
905 CHAR_TO_PIXEL_COL (f
, x
),
906 CHAR_TO_PIXEL_ROW (f
, y
),
907 FONT_WIDTH (f
->display
.x
->font
),
908 f
->display
.x
->line_height
, False
);
910 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
911 CHAR_TO_PIXEL_ROW (f
, y
),
912 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
913 end_x
- x
, highlight_flag
, 1);
918 #if 0 /* Not in use yet */
920 /* Return 1 if character C in font F extends past its left edge. */
923 font_char_overlap_left (font
, c
)
929 /* Find the bounding-box info for C. */
930 if (font
->per_char
== 0)
931 s
= &font
->max_bounds
;
934 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
937 /* Decode char into row number (byte 1) and code within row (byte 2). */
940 if (!(within
>= font
->min_char_or_byte2
941 && within
<= font
->max_char_or_byte2
942 && row
>= font
->min_byte1
943 && row
<= font
->max_byte1
))
945 /* If char is out of range, try the font's default char instead. */
946 c
= font
->default_char
;
947 row
= c
>> (INTBITS
- 8);
950 if (!(within
>= font
->min_char_or_byte2
951 && within
<= font
->max_char_or_byte2
952 && row
>= font
->min_byte1
953 && row
<= font
->max_byte1
))
954 /* Still out of range means this char does not overlap. */
957 /* We found the info for this char. */
958 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
962 return (s
&& s
->lbearing
< 0);
965 /* Return 1 if character C in font F extends past its right edge. */
968 font_char_overlap_right (font
, c
)
974 /* Find the bounding-box info for C. */
975 if (font
->per_char
== 0)
976 s
= &font
->max_bounds
;
979 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
982 /* Decode char into row number (byte 1) and code within row (byte 2). */
985 if (!(within
>= font
->min_char_or_byte2
986 && within
<= font
->max_char_or_byte2
987 && row
>= font
->min_byte1
988 && row
<= font
->max_byte1
))
990 /* If char is out of range, try the font's default char instead. */
991 c
= font
->default_char
;
992 row
= c
>> (INTBITS
- 8);
995 if (!(within
>= font
->min_char_or_byte2
996 && within
<= font
->max_char_or_byte2
997 && row
>= font
->min_byte1
998 && row
<= font
->max_byte1
))
999 /* Still out of range means this char does not overlap. */
1002 /* We found the info for this char. */
1003 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1007 return (s
&& s
->rbearing
>= s
->width
);
1011 /* Invert the middle quarter of the frame for .15 sec. */
1013 /* We use the select system call to do the waiting, so we have to make sure
1014 it's available. If it isn't, we just won't do visual bells. */
1015 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1017 /* Subtract the `struct timeval' values X and Y,
1018 storing the result in RESULT.
1019 Return 1 if the difference is negative, otherwise 0. */
1022 timeval_subtract (result
, x
, y
)
1023 struct timeval
*result
, x
, y
;
1025 /* Perform the carry for the later subtraction by updating y.
1026 This is safer because on some systems
1027 the tv_sec member is unsigned. */
1028 if (x
.tv_usec
< y
.tv_usec
)
1030 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1031 y
.tv_usec
-= 1000000 * nsec
;
1034 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1036 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1037 y
.tv_usec
+= 1000000 * nsec
;
1041 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1042 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1043 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1045 /* Return indication of whether the result should be considered negative. */
1046 return x
.tv_sec
< y
.tv_sec
;
1057 /* Create a GC that will use the GXxor function to flip foreground pixels
1058 into background pixels. */
1062 values
.function
= GXxor
;
1063 values
.foreground
= (f
->display
.x
->foreground_pixel
1064 ^ f
->display
.x
->background_pixel
);
1066 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1067 GCFunction
| GCForeground
, &values
);
1071 int width
= PIXEL_WIDTH (f
);
1072 int height
= PIXEL_HEIGHT (f
);
1074 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1075 width
/4, height
/4, width
/2, height
/2);
1076 XFlush (FRAME_X_DISPLAY (f
));
1079 struct timeval wakeup
, now
;
1081 EMACS_GET_TIME (wakeup
);
1083 /* Compute time to wait until, propagating carry from usecs. */
1084 wakeup
.tv_usec
+= 150000;
1085 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1086 wakeup
.tv_usec
%= 1000000;
1088 /* Keep waiting until past the time wakeup. */
1091 struct timeval timeout
;
1093 EMACS_GET_TIME (timeout
);
1095 /* In effect, timeout = wakeup - timeout.
1096 Break if result would be negative. */
1097 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1100 /* Try to wait that long--but we might wake up sooner. */
1101 select (0, 0, 0, 0, &timeout
);
1105 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1106 width
/4, height
/4, width
/2, height
/2);
1107 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1108 XFlush (FRAME_X_DISPLAY (f
));
1118 /* Make audible bell. */
1120 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1124 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1127 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1129 XTflash (selected_frame
);
1135 XFlush (FRAME_X_DISPLAY (selected_frame
));
1140 /* Insert and delete character.
1141 These are not supposed to be used because we are supposed to turn
1142 off the feature of using them. */
1145 XTinsert_glyphs (start
, len
)
1146 register char *start
;
1159 /* Specify how many text lines, from the top of the window,
1160 should be affected by insert-lines and delete-lines operations.
1161 This, and those operations, are used only within an update
1162 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1165 XTset_terminal_window (n
)
1168 if (updating_frame
== 0)
1171 if ((n
<= 0) || (n
> updating_frame
->height
))
1172 flexlines
= updating_frame
->height
;
1177 /* These variables need not be per frame
1178 because redisplay is done on a frame-by-frame basis
1179 and the line dance for one frame is finished before
1180 anything is done for anoter frame. */
1182 /* Array of line numbers from cached insert/delete operations.
1183 line_dance[i] is the old position of the line that we want
1184 to move to line i, or -1 if we want a blank line there. */
1185 static int *line_dance
;
1187 /* Allocated length of that array. */
1188 static int line_dance_len
;
1190 /* Flag indicating whether we've done any work. */
1191 static int line_dance_in_progress
;
1193 /* Perform an insert-lines or delete-lines operation,
1194 inserting N lines or deleting -N lines at vertical position VPOS. */
1195 XTins_del_lines (vpos
, n
)
1198 register int fence
, i
;
1200 if (vpos
>= flexlines
)
1203 if (!line_dance_in_progress
)
1205 int ht
= updating_frame
->height
;
1206 if (ht
> line_dance_len
)
1208 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1209 line_dance_len
= ht
;
1211 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1212 line_dance_in_progress
= 1;
1216 if (n
> flexlines
- vpos
)
1217 n
= flexlines
- vpos
;
1219 for (i
= flexlines
; --i
>= fence
;)
1220 line_dance
[i
] = line_dance
[i
-n
];
1221 for (i
= fence
; --i
>= vpos
;)
1227 if (n
> flexlines
- vpos
)
1228 n
= flexlines
- vpos
;
1229 fence
= flexlines
- n
;
1230 for (i
= vpos
; i
< fence
; ++i
)
1231 line_dance
[i
] = line_dance
[i
+ n
];
1232 for (i
= fence
; i
< flexlines
; ++i
)
1237 /* Here's where we actually move the pixels around.
1238 Must be called with input blocked. */
1242 register int i
, j
, distance
;
1243 register struct frame
*f
;
1247 /* Must check this flag first. If it's not set, then not only is the
1248 array uninitialized, but we might not even have a frame. */
1249 if (!line_dance_in_progress
)
1257 intborder
= f
->display
.x
->internal_border_width
;
1259 x_display_cursor (updating_frame
, 0);
1261 for (i
= 0; i
< ht
; ++i
)
1262 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1264 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1265 && line_dance
[j
]-j
== distance
); ++j
);
1266 /* Copy [i,j) upward from [i+distance,j+distance) */
1267 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1268 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1269 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1270 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1271 (j
-i
) * f
->display
.x
->line_height
,
1272 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1276 for (i
= ht
; --i
>=0; )
1277 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1279 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1280 && line_dance
[j
]-j
== distance
););
1281 /* Copy (j,i] downward from (j+distance, i+distance] */
1282 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1283 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1284 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1285 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1286 (i
-j
) * f
->display
.x
->line_height
,
1287 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1291 for (i
= 0; i
< ht
; ++i
)
1292 if (line_dance
[i
] == -1)
1294 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1296 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1297 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1298 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1299 (j
-i
) * f
->display
.x
->line_height
, False
);
1302 line_dance_in_progress
= 0;
1305 /* Support routines for exposure events. */
1306 static void clear_cursor ();
1308 /* Output into a rectangle of an X-window (for frame F)
1309 the characters in f->phys_lines that overlap that rectangle.
1310 TOP and LEFT are the position of the upper left corner of the rectangle.
1311 ROWS and COLS are the size of the rectangle.
1312 Call this function with input blocked. */
1315 dumprectangle (f
, left
, top
, cols
, rows
)
1317 register int left
, top
, cols
, rows
;
1319 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1320 int cursor_cleared
= 0;
1324 if (FRAME_GARBAGED_P (f
))
1327 /* Express rectangle as four edges, instead of position-and-size. */
1328 bottom
= top
+ rows
;
1329 right
= left
+ cols
;
1331 /* Convert rectangle edges in pixels to edges in chars.
1332 Round down for left and top, up for right and bottom. */
1333 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1334 left
= PIXEL_TO_CHAR_COL (f
, left
);
1335 bottom
+= (f
->display
.x
->line_height
- 1);
1336 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1337 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1338 right
= PIXEL_TO_CHAR_COL (f
, right
);
1340 /* Clip the rectangle to what can be visible. */
1345 if (right
> f
->width
)
1347 if (bottom
> f
->height
)
1350 /* Get size in chars of the rectangle. */
1351 cols
= right
- left
;
1352 rows
= bottom
- top
;
1354 /* If rectangle has zero area, return. */
1355 if (rows
<= 0) return;
1356 if (cols
<= 0) return;
1358 /* Turn off the cursor if it is in the rectangle.
1359 We will turn it back on afterward. */
1360 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1361 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1367 /* Display the text in the rectangle, one text line at a time. */
1369 for (y
= top
; y
< bottom
; y
++)
1371 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1373 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1377 CHAR_TO_PIXEL_COL (f
, left
),
1378 CHAR_TO_PIXEL_ROW (f
, y
),
1379 line
, min (cols
, active_frame
->used
[y
] - left
),
1380 active_frame
->highlight
[y
], 0);
1383 /* Turn the cursor on if we turned it off. */
1386 x_display_cursor (f
, 1);
1393 /* We used to only do this if Vx_no_window_manager was non-nil, but
1394 the ICCCM (section 4.1.6) says that the window's border pixmap
1395 and border pixel are window attributes which are "private to the
1396 client", so we can always change it to whatever we want. */
1398 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1399 f
->display
.x
->border_pixel
);
1401 x_display_cursor (f
, 1);
1405 frame_unhighlight (f
)
1408 /* We used to only do this if Vx_no_window_manager was non-nil, but
1409 the ICCCM (section 4.1.6) says that the window's border pixmap
1410 and border pixel are window attributes which are "private to the
1411 client", so we can always change it to whatever we want. */
1413 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1414 f
->display
.x
->border_tile
);
1416 x_display_cursor (f
, 1);
1419 static void XTframe_rehighlight ();
1421 /* The focus has changed. Update the frames as necessary to reflect
1422 the new situation. Note that we can't change the selected frame
1423 here, because the lisp code we are interrupting might become confused.
1424 Each event gets marked with the frame in which it occurred, so the
1425 lisp code can tell when the switch took place by examining the events. */
1428 x_new_focus_frame (frame
)
1429 struct frame
*frame
;
1431 struct frame
*old_focus
= x_focus_frame
;
1432 int events_enqueued
= 0;
1434 if (frame
!= x_focus_frame
)
1436 /* Set this before calling other routines, so that they see
1437 the correct value of x_focus_frame. */
1438 x_focus_frame
= frame
;
1440 if (old_focus
&& old_focus
->auto_lower
)
1441 x_lower_frame (old_focus
);
1444 selected_frame
= frame
;
1445 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1447 Fselect_window (selected_frame
->selected_window
);
1448 choose_minibuf_frame ();
1451 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1452 pending_autoraise_frame
= x_focus_frame
;
1454 pending_autoraise_frame
= 0;
1457 XTframe_rehighlight ();
1460 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1465 if (! x_focus_event_frame
)
1466 x_new_focus_frame (NULL
);
1468 x_new_focus_frame (x_focus_event_frame
); /* Was f, but that seems wrong. */
1471 /* The focus has changed, or we have redirected a frame's focus to
1472 another frame (this happens when a frame uses a surrogate
1473 minibuffer frame). Shift the highlight as appropriate. */
1475 XTframe_rehighlight ()
1477 struct frame
*old_highlight
= x_highlight_frame
;
1482 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (x_focus_frame
)))
1483 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1485 if (! FRAME_LIVE_P (x_highlight_frame
))
1487 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1488 x_highlight_frame
= x_focus_frame
;
1492 x_highlight_frame
= 0;
1494 if (x_highlight_frame
!= old_highlight
)
1497 frame_unhighlight (old_highlight
);
1498 if (x_highlight_frame
)
1499 frame_highlight (x_highlight_frame
);
1503 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1505 /* Initialize mode_switch_bit and modifier_meaning. */
1507 x_find_modifier_meanings (dpyinfo
)
1508 struct x_display_info
*dpyinfo
;
1510 int min_code
, max_code
;
1513 XModifierKeymap
*mods
;
1515 dpyinfo
->meta_mod_mask
= 0;
1516 dpyinfo
->shift_lock_mask
= 0;
1517 dpyinfo
->alt_mod_mask
= 0;
1518 dpyinfo
->super_mod_mask
= 0;
1519 dpyinfo
->hyper_mod_mask
= 0;
1522 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1524 min_code
= display
->min_keycode
;
1525 max_code
= display
->max_keycode
;
1528 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1529 min_code
, max_code
- min_code
+ 1,
1531 mods
= XGetModifierMapping (dpyinfo
->display
);
1533 /* Scan the modifier table to see which modifier bits the Meta and
1534 Alt keysyms are on. */
1536 int row
, col
; /* The row and column in the modifier table. */
1538 for (row
= 3; row
< 8; row
++)
1539 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1542 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1544 /* Zeroes are used for filler. Skip them. */
1548 /* Are any of this keycode's keysyms a meta key? */
1552 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1554 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1560 dpyinfo
->meta_mod_mask
|= (1 << row
);
1565 dpyinfo
->alt_mod_mask
|= (1 << row
);
1570 dpyinfo
->hyper_mod_mask
|= (1 << row
);
1575 dpyinfo
->super_mod_mask
|= (1 << row
);
1579 /* Ignore this if it's not on the lock modifier. */
1580 if ((1 << row
) == LockMask
)
1581 dpyinfo
->shift_lock_mask
= LockMask
;
1589 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1590 if (! dpyinfo
->meta_mod_mask
)
1592 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
1593 dpyinfo
->alt_mod_mask
= 0;
1596 /* If some keys are both alt and meta,
1597 make them just meta, not alt. */
1598 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
1600 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
1603 XFree ((char *) syms
);
1604 XFreeModifiermap (mods
);
1607 /* Convert between the modifier bits X uses and the modifier bits
1610 x_x_to_emacs_modifiers (dpyinfo
, state
)
1611 struct x_display_info
*dpyinfo
;
1614 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
1615 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1616 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
1617 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
1618 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
1619 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
1623 x_emacs_to_x_modifiers (dpyinfo
, state
)
1624 struct x_display_info
*dpyinfo
;
1627 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
1628 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
1629 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
1630 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1631 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1632 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
1635 /* Mouse clicks and mouse movement. Rah. */
1637 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1638 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1639 that the glyph at X, Y occupies, if BOUNDS != 0.
1640 If NOCLIP is nonzero, do not force the value into range. */
1643 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1645 register int pix_x
, pix_y
;
1646 register int *x
, *y
;
1650 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1651 even for negative values. */
1653 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1655 pix_y
-= (f
)->display
.x
->line_height
- 1;
1657 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1658 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1662 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1663 bounds
->height
= f
->display
.x
->line_height
;
1664 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1665 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1672 else if (pix_x
> f
->width
)
1677 else if (pix_y
> f
->height
)
1686 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1689 register int *pix_x
, *pix_y
;
1691 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1692 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1695 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1697 If the event is a button press, then note that we have grabbed
1701 construct_mouse_click (result
, event
, f
)
1702 struct input_event
*result
;
1703 XButtonEvent
*event
;
1706 /* Make the event type no_event; we'll change that when we decide
1708 result
->kind
= mouse_click
;
1709 result
->code
= event
->button
- Button1
;
1710 result
->timestamp
= event
->time
;
1711 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1713 | (event
->type
== ButtonRelease
1721 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1722 XSETFASTINT (result
->x
, column
);
1723 XSETFASTINT (result
->y
, row
);
1725 XSETINT (result
->x
, event
->x
);
1726 XSETINT (result
->y
, event
->y
);
1727 XSETFRAME (result
->frame_or_window
, f
);
1731 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1734 construct_menu_click (result
, event
, f
)
1735 struct input_event
*result
;
1736 XButtonEvent
*event
;
1739 /* Make the event type no_event; we'll change that when we decide
1741 result
->kind
= mouse_click
;
1742 XSETINT (result
->code
, event
->button
- Button1
);
1743 result
->timestamp
= event
->time
;
1744 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
1746 | (event
->type
== ButtonRelease
1750 XSETINT (result
->x
, event
->x
);
1751 XSETINT (result
->y
, -1);
1752 XSETFRAME (result
->frame_or_window
, f
);
1755 /* Function to report a mouse movement to the mainstream Emacs code.
1756 The input handler calls this.
1758 We have received a mouse movement event, which is given in *event.
1759 If the mouse is over a different glyph than it was last time, tell
1760 the mainstream emacs code by setting mouse_moved. If not, ask for
1761 another motion event, so we can check again the next time it moves. */
1764 note_mouse_movement (frame
, event
)
1766 XMotionEvent
*event
;
1769 last_mouse_movement_time
= event
->time
;
1771 if (event
->window
!= FRAME_X_WINDOW (frame
))
1774 last_mouse_scroll_bar
= Qnil
;
1776 note_mouse_highlight (frame
, -1, -1);
1778 /* Ask for another mouse motion event. */
1781 Window dummy_window
;
1783 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1784 &dummy_window
, &dummy_window
,
1785 &dummy
, &dummy
, &dummy
, &dummy
,
1786 (unsigned int *) &dummy
);
1790 /* Has the mouse moved off the glyph it was on at the last sighting? */
1791 else if (event
->x
< last_mouse_glyph
.x
1792 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1793 || event
->y
< last_mouse_glyph
.y
1794 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1797 last_mouse_scroll_bar
= Qnil
;
1799 note_mouse_highlight (frame
, event
->x
, event
->y
);
1801 /* Ask for another mouse motion event. */
1804 Window dummy_window
;
1806 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1807 &dummy_window
, &dummy_window
,
1808 &dummy
, &dummy
, &dummy
, &dummy
,
1809 (unsigned int *) &dummy
);
1814 /* It's on the same glyph. Call XQueryPointer so we'll get an
1815 event the next time the mouse moves and we can see if it's
1816 *still* on the same glyph. */
1818 Window dummy_window
;
1820 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1821 &dummy_window
, &dummy_window
,
1822 &dummy
, &dummy
, &dummy
, &dummy
,
1823 (unsigned int *) &dummy
);
1827 /* This is used for debugging, to turn off note_mouse_highlight. */
1828 static int disable_mouse_highlight
;
1830 /* Take proper action when the mouse has moved to position X, Y on frame F
1831 as regards highlighting characters that have mouse-face properties.
1832 Also dehighlighting chars where the mouse was before.
1833 X and Y can be negative or out of range. */
1836 note_mouse_highlight (f
, x
, y
)
1839 int row
, column
, portion
;
1840 XRectangle new_glyph
;
1844 if (disable_mouse_highlight
)
1847 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1848 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1849 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1851 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
1856 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1860 /* Find out which glyph the mouse is on. */
1861 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1862 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
1864 /* Which window is that in? */
1865 window
= window_from_coordinates (f
, column
, row
, &portion
);
1866 w
= XWINDOW (window
);
1868 /* If we were displaying active text in another window, clear that. */
1869 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
1870 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1872 /* Are we in a window whose display is up to date?
1873 And verify the buffer's text has not changed. */
1874 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1875 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1876 && EQ (w
->window_end_valid
, w
->buffer
)
1877 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1879 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1882 /* Find which buffer position the mouse corresponds to. */
1883 for (i
= column
; i
>= 0; i
--)
1887 /* Is it outside the displayed active region (if any)? */
1889 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1890 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
1891 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1892 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1893 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
1894 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1895 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
1896 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
1897 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1899 Lisp_Object mouse_face
, overlay
, position
;
1900 Lisp_Object
*overlay_vec
;
1901 int len
, noverlays
, ignor1
;
1902 struct buffer
*obuf
;
1905 /* If we get an out-of-range value, return now; avoid an error. */
1906 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1909 /* Make the window's buffer temporarily current for
1910 overlays_at and compute_char_face. */
1911 obuf
= current_buffer
;
1912 current_buffer
= XBUFFER (w
->buffer
);
1918 /* Yes. Clear the display of the old active region, if any. */
1919 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
1921 /* Is this char mouse-active? */
1922 XSETINT (position
, pos
);
1925 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1927 /* Put all the overlays we want in a vector in overlay_vec.
1928 Store the length in len. */
1929 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1931 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1933 /* Find the highest priority overlay that has a mouse-face prop. */
1935 for (i
= 0; i
< noverlays
; i
++)
1937 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1938 if (!NILP (mouse_face
))
1940 overlay
= overlay_vec
[i
];
1945 /* If no overlay applies, get a text property. */
1947 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1949 /* Handle the overlay case. */
1950 if (! NILP (overlay
))
1952 /* Find the range of text around this char that
1953 should be active. */
1954 Lisp_Object before
, after
;
1957 before
= Foverlay_start (overlay
);
1958 after
= Foverlay_end (overlay
);
1959 /* Record this as the current active region. */
1960 fast_find_position (window
, before
,
1961 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1962 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1963 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
1964 = !fast_find_position (window
, after
,
1965 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
1966 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
1967 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1968 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
1969 = compute_char_face (f
, w
, pos
, 0, 0,
1970 &ignore
, pos
+ 1, 1);
1972 /* Display it as active. */
1973 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
1975 /* Handle the text property case. */
1976 else if (! NILP (mouse_face
))
1978 /* Find the range of text around this char that
1979 should be active. */
1980 Lisp_Object before
, after
, beginning
, end
;
1983 beginning
= Fmarker_position (w
->start
);
1984 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1985 - XFASTINT (w
->window_end_pos
)));
1987 = Fprevious_single_property_change (make_number (pos
+ 1),
1989 w
->buffer
, beginning
);
1991 = Fnext_single_property_change (position
, Qmouse_face
,
1993 /* Record this as the current active region. */
1994 fast_find_position (window
, before
,
1995 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1996 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1997 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
1998 = !fast_find_position (window
, after
,
1999 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2000 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2001 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2002 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2003 = compute_char_face (f
, w
, pos
, 0, 0,
2004 &ignore
, pos
+ 1, 1);
2006 /* Display it as active. */
2007 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2011 current_buffer
= obuf
;
2016 /* Find the row and column of position POS in window WINDOW.
2017 Store them in *COLUMNP and *ROWP.
2018 This assumes display in WINDOW is up to date.
2019 If POS is above start of WINDOW, return coords
2020 of start of first screen line.
2021 If POS is after end of WINDOW, return coords of end of last screen line.
2023 Value is 1 if POS is in range, 0 if it was off screen. */
2026 fast_find_position (window
, pos
, columnp
, rowp
)
2029 int *columnp
, *rowp
;
2031 struct window
*w
= XWINDOW (window
);
2032 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2037 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2038 int width
= window_internal_width (w
);
2041 int maybe_next_line
= 0;
2043 /* Find the right row. */
2048 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2049 if (linestart
> pos
)
2051 /* If the position sought is the end of the buffer,
2052 don't include the blank lines at the bottom of the window. */
2053 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2055 maybe_next_line
= 1;
2062 /* Find the right column with in it. */
2063 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2065 for (i
= 0; i
< width
; i
++)
2067 if (charstarts
[left
+ i
] == pos
)
2070 *columnp
= i
+ left
;
2073 else if (charstarts
[left
+ i
] > pos
)
2075 else if (charstarts
[left
+ i
] > 0)
2079 /* If we're looking for the end of the buffer,
2080 and we didn't find it in the line we scanned,
2081 use the start of the following line. */
2082 if (maybe_next_line
)
2093 /* Display the active region described by mouse_face_*
2094 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2097 show_mouse_face (dpyinfo
, hl
)
2098 struct x_display_info
*dpyinfo
;
2101 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2102 int width
= window_internal_width (w
);
2103 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2106 int old_curs_x
= curs_x
;
2107 int old_curs_y
= curs_y
;
2109 /* Set these variables temporarily
2110 so that if we have to turn the cursor off and on again
2111 we will put it back at the same place. */
2112 curs_x
= f
->phys_cursor_x
;
2113 curs_y
= f
->phys_cursor_y
;
2115 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2116 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2118 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2119 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2121 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2122 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2124 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2126 /* If the cursor's in the text we are about to rewrite,
2127 turn the cursor off. */
2129 && curs_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
2130 && curs_x
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
)
2132 x_display_cursor (f
, 0);
2137 CHAR_TO_PIXEL_COL (f
, column
),
2138 CHAR_TO_PIXEL_ROW (f
, i
),
2139 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2141 /* Highlight with mouse face if hl > 0. */
2145 /* If we turned the cursor off, turn it back on. */
2147 x_display_cursor (f
, 1);
2149 curs_x
= old_curs_x
;
2150 curs_y
= old_curs_y
;
2152 /* Change the mouse cursor according to the value of HL. */
2154 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2155 f
->display
.x
->cross_cursor
);
2157 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2158 f
->display
.x
->text_cursor
);
2161 /* Clear out the mouse-highlighted active region.
2162 Redraw it unhighlighted first. */
2165 clear_mouse_face (dpyinfo
)
2166 struct x_display_info
*dpyinfo
;
2168 if (! NILP (dpyinfo
->mouse_face_window
))
2169 show_mouse_face (dpyinfo
, 0);
2171 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2172 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2173 dpyinfo
->mouse_face_window
= Qnil
;
2176 static struct scroll_bar
*x_window_to_scroll_bar ();
2177 static void x_scroll_bar_report_motion ();
2179 /* Return the current position of the mouse.
2181 If the mouse movement started in a scroll bar, set *f, *bar_window,
2182 and *part to the frame, window, and scroll bar part that the mouse
2183 is over. Set *x and *y to the portion and whole of the mouse's
2184 position on the scroll bar.
2186 If the mouse movement started elsewhere, set *f to the frame the
2187 mouse is on, *bar_window to nil, and *x and *y to the character cell
2190 Set *time to the server timestamp for the time at which the mouse
2191 was at this position.
2193 Don't store anything if we don't have a valid set of values to report.
2195 This clears the mouse_moved flag, so we can wait for the next mouse
2196 movement. This also calls XQueryPointer, which will cause the
2197 server to give us another MotionNotify when the mouse moves
2201 XTmouse_position (fp
, bar_window
, part
, x
, y
, time
)
2203 Lisp_Object
*bar_window
;
2204 enum scroll_bar_part
*part
;
2206 unsigned long *time
;
2212 if (! NILP (last_mouse_scroll_bar
))
2213 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2219 Window dummy_window
;
2223 last_mouse_scroll_bar
= Qnil
;
2225 /* Figure out which root window we're on. */
2226 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2227 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2229 /* The root window which contains the pointer. */
2232 /* Trash which we can't trust if the pointer is on
2233 a different screen. */
2236 /* The position on that root window. */
2239 /* More trash we can't trust. */
2242 /* Modifier keys and pointer buttons, about which
2244 (unsigned int *) &dummy
);
2246 /* Now we have a position on the root; find the innermost window
2247 containing the pointer. */
2251 int parent_x
, parent_y
;
2255 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2256 && FRAME_LIVE_P (last_mouse_frame
))
2258 /* If mouse was grabbed on a frame, give coords for that frame
2259 even if the mouse is now outside it. */
2260 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2262 /* From-window, to-window. */
2263 root
, FRAME_X_WINDOW (last_mouse_frame
),
2265 /* From-position, to-position. */
2266 root_x
, root_y
, &win_x
, &win_y
,
2270 f1
= last_mouse_frame
;
2276 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2278 /* From-window, to-window. */
2281 /* From-position, to-position. */
2282 root_x
, root_y
, &win_x
, &win_y
,
2295 /* Now we know that:
2296 win is the innermost window containing the pointer
2297 (XTC says it has no child containing the pointer),
2298 win_x and win_y are the pointer's position in it
2299 (XTC did this the last time through), and
2300 parent_x and parent_y are the pointer's position in win's parent.
2301 (They are what win_x and win_y were when win was child.
2302 If win is the root window, it has no parent, and
2303 parent_{x,y} are invalid, but that's okay, because we'll
2304 never use them in that case.) */
2306 /* Is win one of our frames? */
2307 f1
= x_any_window_to_frame (win
);
2310 /* If not, is it one of our scroll bars? */
2313 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2317 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2325 int ignore1
, ignore2
;
2327 /* Ok, we found a frame. Store all the values. */
2329 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2331 FRAME_X_DISPLAY_INFO (f1
)->grabbed
);
2336 XSETINT (*x
, win_x
);
2337 XSETINT (*y
, win_y
);
2338 *time
= last_mouse_movement_time
;
2346 /* Scroll bar support. */
2348 /* Given an X window ID, find the struct scroll_bar which manages it.
2349 This can be called in GC, so we have to make sure to strip off mark
2351 static struct scroll_bar
*
2352 x_window_to_scroll_bar (window_id
)
2355 Lisp_Object tail
, frame
;
2357 for (tail
= Vframe_list
;
2358 XGCTYPE (tail
) == Lisp_Cons
;
2359 tail
= XCONS (tail
)->cdr
)
2361 Lisp_Object frame
, bar
, condemned
;
2363 frame
= XCONS (tail
)->car
;
2364 /* All elements of Vframe_list should be frames. */
2365 if (! GC_FRAMEP (frame
))
2368 /* Scan this frame's scroll bar list for a scroll bar with the
2370 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2371 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2372 /* This trick allows us to search both the ordinary and
2373 condemned scroll bar lists with one loop. */
2374 ! GC_NILP (bar
) || (bar
= condemned
,
2377 bar
= XSCROLL_BAR (bar
)->next
)
2378 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2379 return XSCROLL_BAR (bar
);
2385 /* Open a new X window to serve as a scroll bar, and return the
2386 scroll bar vector for it. */
2387 static struct scroll_bar
*
2388 x_scroll_bar_create (window
, top
, left
, width
, height
)
2389 struct window
*window
;
2390 int top
, left
, width
, height
;
2392 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2393 struct scroll_bar
*bar
2394 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2399 XSetWindowAttributes a
;
2401 a
.background_pixel
= f
->display
.x
->background_pixel
;
2402 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2403 | ButtonMotionMask
| PointerMotionHintMask
2405 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2407 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2412 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2413 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2414 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2415 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2416 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2417 sb_widget
= XtCreateManagedWidget ("box",
2419 f
->display
.x
->edit_widget
, al
, ac
);
2420 SET_SCROLL_BAR_X_WINDOW
2421 (bar
, sb_widget
->core
.window
);
2423 SET_SCROLL_BAR_X_WINDOW
2425 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2427 /* Position and size of scroll bar. */
2428 left
, top
, width
, height
,
2430 /* Border width, depth, class, and visual. */
2431 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2437 XSETWINDOW (bar
->window
, window
);
2438 XSETINT (bar
->top
, top
);
2439 XSETINT (bar
->left
, left
);
2440 XSETINT (bar
->width
, width
);
2441 XSETINT (bar
->height
, height
);
2442 XSETINT (bar
->start
, 0);
2443 XSETINT (bar
->end
, 0);
2444 bar
->dragging
= Qnil
;
2446 /* Add bar to its frame's list of scroll bars. */
2447 bar
->next
= FRAME_SCROLL_BARS (f
);
2449 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2450 if (! NILP (bar
->next
))
2451 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2453 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2460 /* Draw BAR's handle in the proper position.
2461 If the handle is already drawn from START to END, don't bother
2462 redrawing it, unless REBUILD is non-zero; in that case, always
2463 redraw it. (REBUILD is handy for drawing the handle after expose
2466 Normally, we want to constrain the start and end of the handle to
2467 fit inside its rectangle, but if the user is dragging the scroll bar
2468 handle, we want to let them drag it down all the way, so that the
2469 bar's top is as far down as it goes; otherwise, there's no way to
2470 move to the very end of the buffer. */
2472 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2473 struct scroll_bar
*bar
;
2477 int dragging
= ! NILP (bar
->dragging
);
2478 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2479 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2480 GC gc
= f
->display
.x
->normal_gc
;
2482 /* If the display is already accurate, do nothing. */
2484 && start
== XINT (bar
->start
)
2485 && end
== XINT (bar
->end
))
2491 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2492 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2493 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2495 /* Make sure the values are reasonable, and try to preserve
2496 the distance between start and end. */
2498 int length
= end
- start
;
2502 else if (start
> top_range
)
2504 end
= start
+ length
;
2508 else if (end
> top_range
&& ! dragging
)
2512 /* Store the adjusted setting in the scroll bar. */
2513 XSETINT (bar
->start
, start
);
2514 XSETINT (bar
->end
, end
);
2516 /* Clip the end position, just for display. */
2517 if (end
> top_range
)
2520 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2521 below top positions, to make sure the handle is always at least
2522 that many pixels tall. */
2523 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2525 /* Draw the empty space above the handle. Note that we can't clear
2526 zero-height areas; that means "clear to end of window." */
2528 XClearArea (FRAME_X_DISPLAY (f
), w
,
2530 /* x, y, width, height, and exposures. */
2531 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2532 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2533 inside_width
, start
,
2536 /* Draw the handle itself. */
2537 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2539 /* x, y, width, height */
2540 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2541 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2542 inside_width
, end
- start
);
2545 /* Draw the empty space below the handle. Note that we can't
2546 clear zero-height areas; that means "clear to end of window." */
2547 if (end
< inside_height
)
2548 XClearArea (FRAME_X_DISPLAY (f
), w
,
2550 /* x, y, width, height, and exposures. */
2551 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2552 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2553 inside_width
, inside_height
- end
,
2561 /* Move a scroll bar around on the screen, to accommodate changing
2562 window configurations. */
2564 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2565 struct scroll_bar
*bar
;
2566 int top
, left
, width
, height
;
2568 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2569 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2575 unsigned int mask
= 0;
2582 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2583 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2584 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2585 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2588 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
2592 XSETINT (bar
->left
, left
);
2593 XSETINT (bar
->top
, top
);
2594 XSETINT (bar
->width
, width
);
2595 XSETINT (bar
->height
, height
);
2600 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2603 x_scroll_bar_remove (bar
)
2604 struct scroll_bar
*bar
;
2606 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2610 /* Destroy the window. */
2611 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2613 /* Disassociate this scroll bar from its window. */
2614 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2619 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2620 that we are displaying PORTION characters out of a total of WHOLE
2621 characters, starting at POSITION. If WINDOW has no scroll bar,
2624 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2625 struct window
*window
;
2626 int portion
, whole
, position
;
2628 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2629 int top
= XINT (window
->top
);
2630 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2631 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2633 /* Where should this scroll bar be, pixelwise? */
2634 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2635 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2637 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2638 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2639 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
2640 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2642 struct scroll_bar
*bar
;
2644 /* Does the scroll bar exist yet? */
2645 if (NILP (window
->vertical_scroll_bar
))
2646 bar
= x_scroll_bar_create (window
,
2647 pixel_top
, pixel_left
,
2648 pixel_width
, pixel_height
);
2651 /* It may just need to be moved and resized. */
2652 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2653 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2656 /* Set the scroll bar's current state, unless we're currently being
2658 if (NILP (bar
->dragging
))
2660 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2663 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2666 int start
= ((double) position
* top_range
) / whole
;
2667 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2669 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2673 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2677 /* The following three hooks are used when we're doing a thorough
2678 redisplay of the frame. We don't explicitly know which scroll bars
2679 are going to be deleted, because keeping track of when windows go
2680 away is a real pain - "Can you say set-window-configuration, boys
2681 and girls?" Instead, we just assert at the beginning of redisplay
2682 that *all* scroll bars are to be removed, and then save a scroll bar
2683 from the fiery pit when we actually redisplay its window. */
2685 /* Arrange for all scroll bars on FRAME to be removed at the next call
2686 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2687 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2689 XTcondemn_scroll_bars (frame
)
2692 /* The condemned list should be empty at this point; if it's not,
2693 then the rest of Emacs isn't using the condemn/redeem/judge
2694 protocol correctly. */
2695 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2698 /* Move them all to the "condemned" list. */
2699 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2700 FRAME_SCROLL_BARS (frame
) = Qnil
;
2703 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2704 Note that WINDOW isn't necessarily condemned at all. */
2706 XTredeem_scroll_bar (window
)
2707 struct window
*window
;
2709 struct scroll_bar
*bar
;
2711 /* We can't redeem this window's scroll bar if it doesn't have one. */
2712 if (NILP (window
->vertical_scroll_bar
))
2715 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2717 /* Unlink it from the condemned list. */
2719 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2721 if (NILP (bar
->prev
))
2723 /* If the prev pointer is nil, it must be the first in one of
2725 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2726 /* It's not condemned. Everything's fine. */
2728 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2729 window
->vertical_scroll_bar
))
2730 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2732 /* If its prev pointer is nil, it must be at the front of
2733 one or the other! */
2737 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2739 if (! NILP (bar
->next
))
2740 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2742 bar
->next
= FRAME_SCROLL_BARS (f
);
2744 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2745 if (! NILP (bar
->next
))
2746 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2750 /* Remove all scroll bars on FRAME that haven't been saved since the
2751 last call to `*condemn_scroll_bars_hook'. */
2753 XTjudge_scroll_bars (f
)
2756 Lisp_Object bar
, next
;
2758 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2760 /* Clear out the condemned list now so we won't try to process any
2761 more events on the hapless scroll bars. */
2762 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2764 for (; ! NILP (bar
); bar
= next
)
2766 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2768 x_scroll_bar_remove (b
);
2771 b
->next
= b
->prev
= Qnil
;
2774 /* Now there should be no references to the condemned scroll bars,
2775 and they should get garbage-collected. */
2779 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2781 This may be called from a signal handler, so we have to ignore GC
2784 x_scroll_bar_expose (bar
, event
)
2785 struct scroll_bar
*bar
;
2788 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2789 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2790 GC gc
= f
->display
.x
->normal_gc
;
2794 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2796 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2797 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
2799 /* x, y, width, height */
2800 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2805 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2806 is set to something other than no_event, it is enqueued.
2808 This may be called from a signal handler, so we have to ignore GC
2811 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2812 struct scroll_bar
*bar
;
2814 struct input_event
*emacs_event
;
2816 if (! GC_WINDOWP (bar
->window
))
2819 emacs_event
->kind
= scroll_bar_click
;
2820 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2821 emacs_event
->modifiers
2822 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2823 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
2824 event
->xbutton
.state
)
2825 | (event
->type
== ButtonRelease
2828 emacs_event
->frame_or_window
= bar
->window
;
2829 emacs_event
->timestamp
= event
->xbutton
.time
;
2832 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2834 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2835 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2838 if (y
> top_range
) y
= top_range
;
2840 if (y
< XINT (bar
->start
))
2841 emacs_event
->part
= scroll_bar_above_handle
;
2842 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2843 emacs_event
->part
= scroll_bar_handle
;
2845 emacs_event
->part
= scroll_bar_below_handle
;
2847 /* Just because the user has clicked on the handle doesn't mean
2848 they want to drag it. Lisp code needs to be able to decide
2849 whether or not we're dragging. */
2851 /* If the user has just clicked on the handle, record where they're
2853 if (event
->type
== ButtonPress
2854 && emacs_event
->part
== scroll_bar_handle
)
2855 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
2858 /* If the user has released the handle, set it to its final position. */
2859 if (event
->type
== ButtonRelease
2860 && ! NILP (bar
->dragging
))
2862 int new_start
= y
- XINT (bar
->dragging
);
2863 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2865 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2866 bar
->dragging
= Qnil
;
2869 /* Same deal here as the other #if 0. */
2871 /* Clicks on the handle are always reported as occurring at the top of
2873 if (emacs_event
->part
== scroll_bar_handle
)
2874 emacs_event
->x
= bar
->start
;
2876 XSETINT (emacs_event
->x
, y
);
2878 XSETINT (emacs_event
->x
, y
);
2881 XSETINT (emacs_event
->y
, top_range
);
2885 /* Handle some mouse motion while someone is dragging the scroll bar.
2887 This may be called from a signal handler, so we have to ignore GC
2890 x_scroll_bar_note_movement (bar
, event
)
2891 struct scroll_bar
*bar
;
2894 last_mouse_movement_time
= event
->xmotion
.time
;
2897 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2899 /* If we're dragging the bar, display it. */
2900 if (! GC_NILP (bar
->dragging
))
2902 /* Where should the handle be now? */
2903 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2905 if (new_start
!= XINT (bar
->start
))
2907 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2909 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2913 /* Call XQueryPointer so we'll get an event the next time the mouse
2914 moves and we can see *still* on the same position. */
2917 Window dummy_window
;
2919 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2920 &dummy_window
, &dummy_window
,
2921 &dummy
, &dummy
, &dummy
, &dummy
,
2922 (unsigned int *) &dummy
);
2926 /* Return information to the user about the current position of the mouse
2927 on the scroll bar. */
2929 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2931 Lisp_Object
*bar_window
;
2932 enum scroll_bar_part
*part
;
2934 unsigned long *time
;
2936 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2937 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2938 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2940 Window dummy_window
;
2942 unsigned int dummy_mask
;
2946 /* Get the mouse's position relative to the scroll bar window, and
2948 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
2950 /* Root, child, root x and root y. */
2951 &dummy_window
, &dummy_window
,
2952 &dummy_coord
, &dummy_coord
,
2954 /* Position relative to scroll bar. */
2957 /* Mouse buttons and modifier keys. */
2963 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2965 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2967 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2969 if (! NILP (bar
->dragging
))
2970 win_y
-= XINT (bar
->dragging
);
2974 if (win_y
> top_range
)
2978 *bar_window
= bar
->window
;
2980 if (! NILP (bar
->dragging
))
2981 *part
= scroll_bar_handle
;
2982 else if (win_y
< XINT (bar
->start
))
2983 *part
= scroll_bar_above_handle
;
2984 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2985 *part
= scroll_bar_handle
;
2987 *part
= scroll_bar_below_handle
;
2989 XSETINT (*x
, win_y
);
2990 XSETINT (*y
, top_range
);
2993 last_mouse_scroll_bar
= Qnil
;
2996 *time
= last_mouse_movement_time
;
3002 /* The screen has been cleared so we may have changed foreground or
3003 background colors, and the scroll bars may need to be redrawn.
3004 Clear out the scroll bars, and ask for expose events, so we can
3007 x_scroll_bar_clear (f
)
3012 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3013 bar
= XSCROLL_BAR (bar
)->next
)
3014 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3018 /* This processes Expose events from the menubar specific X event
3019 loop in menubar.c. This allows to redisplay the frame if necessary
3020 when handling menubar or popup items. */
3023 process_expose_from_menu (event
)
3030 f
= x_window_to_frame (event
.xexpose
.window
);
3033 if (f
->async_visible
== 0)
3035 f
->async_visible
= 1;
3036 f
->async_iconified
= 0;
3037 SET_FRAME_GARBAGED (f
);
3041 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3042 event
.xexpose
.x
, event
.xexpose
.y
,
3043 event
.xexpose
.width
, event
.xexpose
.height
);
3048 struct scroll_bar
*bar
3049 = x_window_to_scroll_bar (event
.xexpose
.window
);
3052 x_scroll_bar_expose (bar
, &event
);
3058 /* Define a queue to save up SelectionRequest events for later handling. */
3060 struct selection_event_queue
3063 struct selection_event_queue
*next
;
3066 static struct selection_event_queue
*queue
;
3068 /* Nonzero means queue up certain events--don't process them yet. */
3069 static int x_queue_selection_requests
;
3071 /* Queue up an X event *EVENT, to be processed later. */
3074 x_queue_event (f
, event
)
3078 struct selection_event_queue
*queue_tmp
3079 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3081 if (queue_tmp
!= NULL
)
3083 queue_tmp
->event
= *event
;
3084 queue_tmp
->next
= queue
;
3089 /* Take all the queued events and put them back
3090 so that they get processed afresh. */
3093 x_unqueue_events (f
)
3096 while (queue
!= NULL
)
3098 struct selection_event_queue
*queue_tmp
= queue
;
3099 XPutBackEvent (FRAME_X_DISPLAY (f
), &queue_tmp
->event
);
3100 queue
= queue_tmp
->next
;
3101 free ((char *)queue_tmp
);
3105 /* Start queuing SelectionRequest events. */
3108 x_start_queuing_selection_requests (f
)
3111 x_queue_selection_requests
++;
3114 /* Stop queuing SelectionRequest events. */
3117 x_stop_queuing_selection_requests (f
)
3120 x_queue_selection_requests
--;
3121 x_unqueue_events (f
);
3124 /* The main X event-reading loop - XTread_socket. */
3126 /* Timestamp of enter window event. This is only used by XTread_socket,
3127 but we have to put it out here, since static variables within functions
3128 sometimes don't work. */
3129 static Time enter_timestamp
;
3131 /* This holds the state XLookupString needs to implement dead keys
3132 and other tricks known as "compose processing". _X Window System_
3133 says that a portable program can't use this, but Stephen Gildea assures
3134 me that letting the compiler initialize it to zeros will work okay.
3136 This must be defined outside of XTread_socket, for the same reasons
3137 given for enter_timestamp, above. */
3138 static XComposeStatus compose_status
;
3140 /* Record the last 100 characters stored
3141 to help debug the loss-of-chars-during-GC problem. */
3143 short temp_buffer
[100];
3145 /* Set this to nonzero to fake an "X I/O error"
3146 on a particular display. */
3147 struct x_display_info
*XTread_socket_fake_io_error
;
3149 /* Read events coming from the X server.
3150 This routine is called by the SIGIO handler.
3151 We return as soon as there are no more events to be read.
3153 Events representing keys are stored in buffer BUFP,
3154 which can hold up to NUMCHARS characters.
3155 We return the number of characters stored into the buffer,
3156 thus pretending to be `read'.
3158 WAITP is nonzero if we should block until input arrives.
3159 EXPECTED is nonzero if the caller knows input is available. */
3162 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3164 register struct input_event
*bufp
;
3165 register int numchars
;
3172 int items_pending
; /* How many items are in the X queue. */
3175 int event_found
= 0;
3178 struct x_display_info
*dpyinfo
;
3180 if (interrupt_input_blocked
)
3182 interrupt_input_pending
= 1;
3186 interrupt_input_pending
= 0;
3189 /* So people can tell when we have read the available input. */
3190 input_signal_count
++;
3193 abort (); /* Don't think this happens. */
3195 /* Find the display we are supposed to read input for.
3196 It's the one communicating on descriptor SD. */
3197 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3199 #if 0 /* This ought to be unnecessary; let's verify it. */
3201 /* If available, Xlib uses FIOSNBIO to make the socket
3202 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3203 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3204 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3205 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3206 #endif /* ! defined (FIOSNBIO) */
3209 #if 0 /* This code can't be made to work, with multiple displays,
3210 and appears not to be used on any system any more.
3211 Also keyboard.c doesn't turn O_NDELAY on and off
3212 for X connections. */
3215 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3217 extern int read_alarm_should_throw
;
3218 read_alarm_should_throw
= 1;
3219 XPeekEvent (dpyinfo
->display
, &event
);
3220 read_alarm_should_throw
= 0;
3222 #endif /* HAVE_SELECT */
3226 /* For debugging, this gives a way to fake an I/O error. */
3227 if (dpyinfo
== XTread_socket_fake_io_error
)
3229 XTread_socket_fake_io_error
= 0;
3230 x_io_error_quitter (dpyinfo
->display
);
3233 while (XPending (dpyinfo
->display
) != 0)
3235 XNextEvent (dpyinfo
->display
, &event
);
3242 if (event
.xclient
.message_type
3243 == dpyinfo
->Xatom_wm_protocols
3244 && event
.xclient
.format
== 32)
3246 if (event
.xclient
.data
.l
[0]
3247 == dpyinfo
->Xatom_wm_take_focus
)
3249 f
= x_window_to_frame (event
.xclient
.window
);
3250 /* Since we set WM_TAKE_FOCUS, we must call
3251 XSetInputFocus explicitly. But not if f is null,
3252 since that might be an event for a deleted frame. */
3254 XSetInputFocus (event
.xclient
.display
,
3255 event
.xclient
.window
,
3256 RevertToPointerRoot
,
3257 event
.xclient
.data
.l
[1]);
3258 /* Not certain about handling scroll bars here */
3260 else if (event
.xclient
.data
.l
[0]
3261 == dpyinfo
->Xatom_wm_save_yourself
)
3263 /* Save state modify the WM_COMMAND property to
3264 something which can reinstate us. This notifies
3265 the session manager, who's looking for such a
3266 PropertyNotify. Can restart processing when
3267 a keyboard or mouse event arrives. */
3270 f
= x_top_window_to_frame (event
.xclient
.window
);
3272 /* This is just so we only give real data once
3273 for a single Emacs process. */
3274 if (f
== selected_frame
)
3275 XSetCommand (FRAME_X_DISPLAY (f
),
3276 event
.xclient
.window
,
3277 initial_argv
, initial_argc
);
3279 XSetCommand (FRAME_X_DISPLAY (f
),
3280 event
.xclient
.window
,
3284 else if (event
.xclient
.data
.l
[0]
3285 == dpyinfo
->Xatom_wm_delete_window
)
3287 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3294 bufp
->kind
= delete_window_event
;
3295 XSETFRAME (bufp
->frame_or_window
, f
);
3303 else if (event
.xclient
.message_type
3304 == dpyinfo
->Xatom_wm_configure_denied
)
3307 else if (event
.xclient
.message_type
3308 == dpyinfo
->Xatom_wm_window_moved
)
3311 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3313 new_x
= event
.xclient
.data
.s
[0];
3314 new_y
= event
.xclient
.data
.s
[1];
3318 f
->display
.x
->left_pos
= new_x
;
3319 f
->display
.x
->top_pos
= new_y
;
3322 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3323 else if (event
.xclient
.message_type
3324 == dpyinfo
->Xatom_editres
)
3326 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3327 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3329 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3333 case SelectionNotify
:
3334 #ifdef USE_X_TOOLKIT
3335 if (! x_window_to_frame (event
.xselection
.requestor
))
3337 #endif /* not USE_X_TOOLKIT */
3338 x_handle_selection_notify (&event
);
3341 case SelectionClear
: /* Someone has grabbed ownership. */
3342 #ifdef USE_X_TOOLKIT
3343 if (! x_window_to_frame (event
.xselectionclear
.window
))
3345 #endif /* USE_X_TOOLKIT */
3347 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3352 bufp
->kind
= selection_clear_event
;
3353 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3354 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3355 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3363 case SelectionRequest
: /* Someone wants our selection. */
3364 #ifdef USE_X_TOOLKIT
3365 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3367 #endif /* USE_X_TOOLKIT */
3368 if (x_queue_selection_requests
)
3369 x_queue_event (x_window_to_frame (event
.xselectionrequest
.owner
),
3373 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3378 bufp
->kind
= selection_request_event
;
3379 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3380 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3381 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3382 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3383 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3384 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3392 case PropertyNotify
:
3393 #ifdef USE_X_TOOLKIT
3394 if (!x_any_window_to_frame (event
.xproperty
.window
))
3396 #endif /* not USE_X_TOOLKIT */
3397 x_handle_property_notify (&event
);
3400 case ReparentNotify
:
3401 f
= x_top_window_to_frame (event
.xreparent
.window
);
3405 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3406 x_real_positions (f
, &x
, &y
);
3407 f
->display
.x
->left_pos
= x
;
3408 f
->display
.x
->top_pos
= y
;
3413 f
= x_window_to_frame (event
.xexpose
.window
);
3416 if (f
->async_visible
== 0)
3418 f
->async_visible
= 1;
3419 f
->async_iconified
= 0;
3420 SET_FRAME_GARBAGED (f
);
3423 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3424 event
.xexpose
.x
, event
.xexpose
.y
,
3425 event
.xexpose
.width
, event
.xexpose
.height
);
3429 struct scroll_bar
*bar
3430 = x_window_to_scroll_bar (event
.xexpose
.window
);
3433 x_scroll_bar_expose (bar
, &event
);
3434 #ifdef USE_X_TOOLKIT
3437 #endif /* USE_X_TOOLKIT */
3441 case GraphicsExpose
: /* This occurs when an XCopyArea's
3442 source area was obscured or not
3444 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3448 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3449 event
.xgraphicsexpose
.width
,
3450 event
.xgraphicsexpose
.height
);
3452 #ifdef USE_X_TOOLKIT
3455 #endif /* USE_X_TOOLKIT */
3458 case NoExpose
: /* This occurs when an XCopyArea's
3459 source area was completely
3464 f
= x_any_window_to_frame (event
.xunmap
.window
);
3465 if (f
) /* F may no longer exist if
3466 the frame was deleted. */
3468 /* While a frame is unmapped, display generation is
3469 disabled; you don't want to spend time updating a
3470 display that won't ever be seen. */
3471 f
->async_visible
= 0;
3472 /* We can't distinguish, from the event, whether the window
3473 has become iconified or invisible. So assume, if it
3474 was previously visible, than now it is iconified.
3475 We depend on x_make_frame_invisible to mark it iconified. */
3476 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3477 f
->async_iconified
= 1;
3479 bufp
->kind
= iconify_event
;
3480 XSETFRAME (bufp
->frame_or_window
, f
);
3485 #ifdef USE_X_TOOLKIT
3487 #endif /* USE_X_TOOLKIT */
3491 /* We use x_top_window_to_frame because map events can come
3492 for subwindows and they don't mean that the frame is visible. */
3493 f
= x_top_window_to_frame (event
.xmap
.window
);
3496 f
->async_visible
= 1;
3497 f
->async_iconified
= 0;
3499 /* wait_reading_process_input will notice this and update
3500 the frame's display structures. */
3501 SET_FRAME_GARBAGED (f
);
3503 bufp
->kind
= deiconify_event
;
3504 XSETFRAME (bufp
->frame_or_window
, f
);
3509 #ifdef USE_X_TOOLKIT
3511 #endif /* USE_X_TOOLKIT */
3514 /* Turn off processing if we become fully obscured. */
3515 case VisibilityNotify
:
3519 f
= x_any_window_to_frame (event
.xkey
.window
);
3523 KeySym keysym
, orig_keysym
;
3524 /* al%imercury@uunet.uu.net says that making this 81 instead of
3525 80 fixed a bug whereby meta chars made his Emacs hang. */
3526 unsigned char copy_buffer
[81];
3530 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
3531 extra_keyboard_modifiers
);
3532 modifiers
= event
.xkey
.state
;
3534 /* This will have to go some day... */
3536 /* make_lispy_event turns chars into control chars.
3537 Don't do it here because XLookupString is too eager. */
3538 event
.xkey
.state
&= ~ControlMask
;
3539 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
3540 80, &keysym
, &compose_status
);
3542 orig_keysym
= keysym
;
3546 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3547 || keysym
== XK_Delete
3548 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3549 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3551 /* This recognizes the "extended function keys".
3552 It seems there's no cleaner way.
3553 Test IsModifierKey to avoid handling mode_switch
3555 || ((unsigned) (keysym
) >= XK_Select
3556 && (unsigned)(keysym
) < XK_KP_Space
)
3558 #ifdef XK_dead_circumflex
3559 || orig_keysym
== XK_dead_circumflex
3561 #ifdef XK_dead_grave
3562 || orig_keysym
== XK_dead_grave
3564 #ifdef XK_dead_tilde
3565 || orig_keysym
== XK_dead_tilde
3567 #ifdef XK_dead_diaeresis
3568 || orig_keysym
== XK_dead_diaeresis
3570 #ifdef XK_dead_macron
3571 || orig_keysym
== XK_dead_macron
3573 #ifdef XK_dead_degree
3574 || orig_keysym
== XK_dead_degree
3576 #ifdef XK_dead_acute
3577 || orig_keysym
== XK_dead_acute
3579 #ifdef XK_dead_cedilla
3580 || orig_keysym
== XK_dead_cedilla
3582 #ifdef XK_dead_breve
3583 || orig_keysym
== XK_dead_breve
3585 #ifdef XK_dead_ogonek
3586 || orig_keysym
== XK_dead_ogonek
3588 #ifdef XK_dead_caron
3589 || orig_keysym
== XK_dead_caron
3591 #ifdef XK_dead_doubleacute
3592 || orig_keysym
== XK_dead_doubleacute
3594 #ifdef XK_dead_abovedot
3595 || orig_keysym
== XK_dead_abovedot
3597 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3598 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3599 /* Any "vendor-specific" key is ok. */
3600 || (orig_keysym
& (1 << 28)))
3601 && ! (IsModifierKey (orig_keysym
)
3603 #ifdef XK_Mode_switch
3604 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3607 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3609 #endif /* not HAVE_X11R5 */
3612 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3614 temp_buffer
[temp_index
++] = keysym
;
3615 bufp
->kind
= non_ascii_keystroke
;
3616 bufp
->code
= keysym
;
3617 XSETFRAME (bufp
->frame_or_window
, f
);
3619 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3621 bufp
->timestamp
= event
.xkey
.time
;
3626 else if (numchars
> nbytes
)
3630 for (i
= 0; i
< nbytes
; i
++)
3632 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3634 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3635 bufp
->kind
= ascii_keystroke
;
3636 bufp
->code
= copy_buffer
[i
];
3637 XSETFRAME (bufp
->frame_or_window
, f
);
3639 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3641 bufp
->timestamp
= event
.xkey
.time
;
3656 /* Here's a possible interpretation of the whole
3657 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3658 FocusIn event, you have to get a FocusOut event before you
3659 relinquish the focus. If you haven't received a FocusIn event,
3660 then a mere LeaveNotify is enough to free you. */
3663 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3665 if (event
.xcrossing
.focus
) /* Entered Window */
3667 /* Avoid nasty pop/raise loops. */
3668 if (f
&& (!(f
->auto_raise
)
3670 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3672 x_new_focus_frame (f
);
3673 enter_timestamp
= event
.xcrossing
.time
;
3676 else if (f
== x_focus_frame
)
3677 x_new_focus_frame (0);
3678 /* EnterNotify counts as mouse movement,
3679 so update things that depend on mouse position. */
3681 note_mouse_movement (f
, &event
.xmotion
);
3682 #ifdef USE_X_TOOLKIT
3684 #endif /* USE_X_TOOLKIT */
3688 f
= x_any_window_to_frame (event
.xfocus
.window
);
3689 if (event
.xfocus
.detail
!= NotifyPointer
)
3690 x_focus_event_frame
= f
;
3692 x_new_focus_frame (f
);
3693 #ifdef USE_X_TOOLKIT
3695 #endif /* USE_X_TOOLKIT */
3700 f
= x_top_window_to_frame (event
.xcrossing
.window
);
3703 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3704 /* If we move outside the frame,
3705 then we're certainly no longer on any text in the frame. */
3706 clear_mouse_face (dpyinfo
);
3708 if (event
.xcrossing
.focus
)
3712 if (f
== x_focus_event_frame
)
3713 x_focus_event_frame
= 0;
3714 if (f
== x_focus_frame
)
3715 x_new_focus_frame (0);
3718 #ifdef USE_X_TOOLKIT
3720 #endif /* USE_X_TOOLKIT */
3724 f
= x_any_window_to_frame (event
.xfocus
.window
);
3725 if (event
.xfocus
.detail
!= NotifyPointer
3726 && f
== x_focus_event_frame
)
3727 x_focus_event_frame
= 0;
3728 if (f
&& f
== x_focus_frame
)
3729 x_new_focus_frame (0);
3730 #ifdef USE_X_TOOLKIT
3732 #endif /* USE_X_TOOLKIT */
3737 if (dpyinfo
->grabbed
&& last_mouse_frame
3738 && FRAME_LIVE_P (last_mouse_frame
))
3739 f
= last_mouse_frame
;
3741 f
= x_window_to_frame (event
.xmotion
.window
);
3743 note_mouse_movement (f
, &event
.xmotion
);
3746 struct scroll_bar
*bar
3747 = x_window_to_scroll_bar (event
.xmotion
.window
);
3750 x_scroll_bar_note_movement (bar
, &event
);
3752 /* If we move outside the frame,
3753 then we're certainly no longer on any text in the frame. */
3754 clear_mouse_face (dpyinfo
);
3757 #if 0 /* This should be unnecessary, since the toolkit has no use
3758 for motion events that happen outside of the menu event loop,
3759 and it seems to cause the bug that mouse events stop coming
3761 #ifdef USE_X_TOOLKIT
3763 #endif /* USE_X_TOOLKIT */
3767 case ConfigureNotify
:
3768 f
= x_any_window_to_frame (event
.xconfigure
.window
);
3769 #ifdef USE_X_TOOLKIT
3772 && ! event
.xconfigure
.send_event
3774 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
3779 /* Find the position of the outside upper-left corner of
3780 the window, in the root coordinate system. Don't
3781 refer to the parent window here; we may be processing
3782 this event after the window manager has changed our
3783 parent, but before we have reached the ReparentNotify. */
3784 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3786 /* From-window, to-window. */
3787 XtWindow (f
->display
.x
->widget
),
3788 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3790 /* From-position, to-position. */
3791 -event
.xconfigure
.border_width
,
3792 -event
.xconfigure
.border_width
,
3797 event
.xconfigure
.x
= win_x
;
3798 event
.xconfigure
.y
= win_y
;
3800 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3801 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3802 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3803 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3805 /* What we have now is the position of Emacs's own window.
3806 Convert that to the position of the window manager window. */
3809 x_real_positions (f
, &x
, &y
);
3810 f
->display
.x
->left_pos
= x
;
3811 f
->display
.x
->top_pos
= y
;
3815 #else /* not USE_X_TOOLKIT */
3818 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3819 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3821 /* Even if the number of character rows and columns has
3822 not changed, the font size may have changed, so we need
3823 to check the pixel dimensions as well. */
3824 if (columns
!= f
->width
3825 || rows
!= f
->height
3826 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3827 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3829 change_frame_size (f
, rows
, columns
, 0, 1);
3830 SET_FRAME_GARBAGED (f
);
3833 if (! event
.xconfigure
.send_event
)
3838 /* Find the position of the outside upper-left corner of
3839 the window, in the root coordinate system. Don't
3840 refer to the parent window here; we may be processing
3841 this event after the window manager has changed our
3842 parent, but before we have reached the ReparentNotify. */
3843 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
3845 /* From-window, to-window. */
3846 f
->display
.x
->window_desc
,
3847 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3849 /* From-position, to-position. */
3850 -event
.xconfigure
.border_width
,
3851 -event
.xconfigure
.border_width
,
3856 event
.xconfigure
.x
= win_x
;
3857 event
.xconfigure
.y
= win_y
;
3860 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3861 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3862 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3863 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3865 /* What we have now is the position of Emacs's own window.
3866 Convert that to the position of the window manager window. */
3869 x_real_positions (f
, &x
, &y
);
3870 f
->display
.x
->left_pos
= x
;
3871 f
->display
.x
->top_pos
= y
;
3872 if (y
!= event
.xconfigure
.y
)
3874 /* Since the WM decorations come below top_pos now,
3875 we must put them below top_pos in the future. */
3876 f
->display
.x
->win_gravity
= NorthWestGravity
;
3877 x_wm_set_size_hint (f
, 0, 0);
3881 #endif /* not USE_X_TOOLKIT */
3887 /* If we decide we want to generate an event to be seen
3888 by the rest of Emacs, we put it here. */
3889 struct input_event emacs_event
;
3890 emacs_event
.kind
= no_event
;
3892 bzero (&compose_status
, sizeof (compose_status
));
3894 if (dpyinfo
->grabbed
&& last_mouse_frame
3895 && FRAME_LIVE_P (last_mouse_frame
))
3896 f
= last_mouse_frame
;
3898 f
= x_window_to_frame (event
.xmotion
.window
);
3902 if (!x_focus_frame
|| (f
== x_focus_frame
))
3903 construct_mouse_click (&emacs_event
, &event
, f
);
3907 struct scroll_bar
*bar
3908 = x_window_to_scroll_bar (event
.xbutton
.window
);
3911 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3912 #ifdef USE_X_TOOLKIT
3915 /* Assume we have a menubar button press. A bad
3916 assumption should behave benignly. */
3917 popup_get_selection (&event
);
3920 #endif /* USE_X_TOOLKIT */
3923 if (event
.type
== ButtonPress
)
3925 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
3926 last_mouse_frame
= f
;
3930 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
3933 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3935 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3941 #ifdef USE_X_TOOLKIT
3943 #endif /* USE_X_TOOLKIT */
3947 case CirculateNotify
:
3949 case CirculateRequest
:
3953 /* Someone has changed the keyboard mapping - update the
3955 switch (event
.xmapping
.request
)
3957 case MappingModifier
:
3958 x_find_modifier_meanings (dpyinfo
);
3959 /* This is meant to fall through. */
3960 case MappingKeyboard
:
3961 XRefreshKeyboardMapping (&event
.xmapping
);
3963 #ifdef USE_X_TOOLKIT
3965 #endif /* USE_X_TOOLKIT */
3969 #ifdef USE_X_TOOLKIT
3972 XtDispatchEvent (&event
);
3974 #endif /* USE_X_TOOLKIT */
3980 /* On some systems, an X bug causes Emacs to get no more events
3981 when the window is destroyed. Detect that. (1994.) */
3984 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
3985 One XNOOP in 100 loops will make Emacs terminate.
3986 B. Bretthauer, 1994 */
3988 if (x_noop_count
>= 100)
3991 /* Use the first display in the list. Why not? */
3992 XNoOp (x_display_list
->display
);
3996 /* If the focus was just given to an autoraising frame,
3998 /* ??? This ought to be able to handle more than one such frame. */
3999 if (pending_autoraise_frame
)
4001 x_raise_frame (pending_autoraise_frame
);
4002 pending_autoraise_frame
= 0;
4009 /* Drawing the cursor. */
4012 /* Draw a hollow box cursor. Don't change the inside of the box. */
4018 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
4019 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
4020 int width
= FONT_WIDTH (f
->display
.x
->font
);
4021 int height
= f
->display
.x
->line_height
;
4023 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4024 f
->display
.x
->cursor_gc
,
4025 left
, top
, width
- 1, height
- 1);
4028 /* Clear the cursor of frame F to background color,
4029 and mark the cursor as not shown.
4030 This is used when the text where the cursor is
4031 is about to be rewritten. */
4039 if (! FRAME_VISIBLE_P (f
)
4040 || f
->phys_cursor_x
< 0)
4043 x_display_cursor (f
, 0);
4044 f
->phys_cursor_x
= -1;
4047 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4048 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4052 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4059 CHAR_TO_PIXEL_COL (f
, column
),
4060 CHAR_TO_PIXEL_ROW (f
, row
),
4061 &glyph
, 1, highlight
, 0);
4065 x_display_bar_cursor (f
, on
)
4069 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4071 /* This is pointless on invisible frames, and dangerous on garbaged
4072 frames; in the latter case, the frame may be in the midst of
4073 changing its size, and curs_x and curs_y may be off the frame. */
4074 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4077 if (! on
&& f
->phys_cursor_x
< 0)
4080 /* If we're not updating, then we want to use the current frame's
4081 cursor position, not our local idea of where the cursor ought to be. */
4082 if (f
!= updating_frame
)
4084 curs_x
= FRAME_CURSOR_X (f
);
4085 curs_y
= FRAME_CURSOR_Y (f
);
4088 /* If there is anything wrong with the current cursor state, remove it. */
4089 if (f
->phys_cursor_x
>= 0
4091 || f
->phys_cursor_x
!= curs_x
4092 || f
->phys_cursor_y
!= curs_y
4093 || f
->display
.x
->current_cursor
!= bar_cursor
))
4095 /* Erase the cursor by redrawing the character underneath it. */
4096 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4097 f
->phys_cursor_glyph
,
4098 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4099 f
->phys_cursor_x
= -1;
4102 /* If we now need a cursor in the new place or in the new form, do it so. */
4104 && (f
->phys_cursor_x
< 0
4105 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4107 f
->phys_cursor_glyph
4108 = ((current_glyphs
->enable
[curs_y
]
4109 && curs_x
< current_glyphs
->used
[curs_y
])
4110 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4112 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4113 f
->display
.x
->cursor_gc
,
4114 CHAR_TO_PIXEL_COL (f
, curs_x
),
4115 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4116 1, f
->display
.x
->line_height
);
4118 f
->phys_cursor_x
= curs_x
;
4119 f
->phys_cursor_y
= curs_y
;
4121 f
->display
.x
->current_cursor
= bar_cursor
;
4124 if (updating_frame
!= f
)
4125 XFlush (FRAME_X_DISPLAY (f
));
4129 /* Turn the displayed cursor of frame F on or off according to ON.
4130 If ON is nonzero, where to put the cursor is specified
4131 by F->cursor_x and F->cursor_y. */
4134 x_display_box_cursor (f
, on
)
4138 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4140 /* This is pointless on invisible frames, and dangerous on garbaged
4141 frames; in the latter case, the frame may be in the midst of
4142 changing its size, and curs_x and curs_y may be off the frame. */
4143 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4146 /* If cursor is off and we want it off, return quickly. */
4147 if (!on
&& f
->phys_cursor_x
< 0)
4150 /* If we're not updating, then we want to use the current frame's
4151 cursor position, not our local idea of where the cursor ought to be. */
4152 if (f
!= updating_frame
)
4154 curs_x
= FRAME_CURSOR_X (f
);
4155 curs_y
= FRAME_CURSOR_Y (f
);
4158 /* If cursor is currently being shown and we don't want it to be
4159 or it is in the wrong place,
4160 or we want a hollow box and it's not so, (pout!)
4162 if (f
->phys_cursor_x
>= 0
4164 || f
->phys_cursor_x
!= curs_x
4165 || f
->phys_cursor_y
!= curs_y
4166 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4167 && (f
!= x_highlight_frame
))))
4169 int mouse_face_here
= 0;
4170 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4172 /* If the cursor is in the mouse face area, redisplay that when
4173 we clear the cursor. */
4174 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4176 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4177 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4178 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4180 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4181 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4182 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4183 /* Don't redraw the cursor's spot in mouse face
4184 if it is at the end of a line (on a newline).
4185 The cursor appears there, but mouse highlighting does not. */
4186 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4187 mouse_face_here
= 1;
4189 /* If the font is not as tall as a whole line,
4190 we must explicitly clear the line's whole height. */
4191 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4192 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4193 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4194 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4195 FONT_WIDTH (f
->display
.x
->font
),
4196 f
->display
.x
->line_height
, False
);
4197 /* Erase the cursor by redrawing the character underneath it. */
4198 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4199 f
->phys_cursor_glyph
,
4202 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4203 f
->phys_cursor_x
= -1;
4206 /* If we want to show a cursor,
4207 or we want a box cursor and it's not so,
4208 write it in the right place. */
4210 && (f
->phys_cursor_x
< 0
4211 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4212 && f
== x_highlight_frame
)))
4214 f
->phys_cursor_glyph
4215 = ((current_glyphs
->enable
[curs_y
]
4216 && curs_x
< current_glyphs
->used
[curs_y
])
4217 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4219 if (f
!= x_highlight_frame
)
4222 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4226 x_draw_single_glyph (f
, curs_y
, curs_x
,
4227 f
->phys_cursor_glyph
, 2);
4228 f
->display
.x
->current_cursor
= filled_box_cursor
;
4231 f
->phys_cursor_x
= curs_x
;
4232 f
->phys_cursor_y
= curs_y
;
4235 if (updating_frame
!= f
)
4236 XFlush (FRAME_X_DISPLAY (f
));
4239 x_display_cursor (f
, on
)
4245 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4246 x_display_box_cursor (f
, on
);
4247 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4248 x_display_bar_cursor (f
, on
);
4250 /* Those are the only two we have implemented! */
4258 /* Refresh bitmap kitchen sink icon for frame F
4259 when we get an expose event for it. */
4264 /* Normally, the window manager handles this function. */
4267 /* Make the x-window of frame F use the gnu icon bitmap. */
4270 x_bitmap_icon (f
, file
)
4274 int mask
, bitmap_id
;
4277 if (FRAME_X_WINDOW (f
) == 0)
4280 /* Free up our existing icon bitmap if any. */
4281 if (f
->display
.x
->icon_bitmap
> 0)
4282 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4283 f
->display
.x
->icon_bitmap
= 0;
4286 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4289 /* Create the GNU bitmap if necessary. */
4290 if (!FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4291 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4292 = x_create_bitmap_from_data (f
, gnu_bits
,
4293 gnu_width
, gnu_height
);
4295 /* The first time we create the GNU bitmap,
4296 this increments the refcount one extra time.
4297 As a result, the GNU bitmap is never freed.
4298 That way, we don't have to worry about allocating it again. */
4299 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4301 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4304 x_wm_set_icon_pixmap (f
, bitmap_id
);
4305 f
->display
.x
->icon_bitmap
= bitmap_id
;
4311 /* Make the x-window of frame F use a rectangle with text. */
4314 x_text_icon (f
, icon_name
)
4318 if (FRAME_X_WINDOW (f
) == 0)
4322 f
->display
.x
->icon_label
= icon_name
;
4324 if (! f
->display
.x
->icon_label
)
4325 f
->display
.x
->icon_label
= " *emacs* ";
4328 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4329 (char *) f
->display
.x
->icon_label
);
4332 if (f
->display
.x
->icon_bitmap
> 0)
4333 x_destroy_bitmap (f
, f
->display
.x
->icon_bitmap
);
4334 f
->display
.x
->icon_bitmap
= 0;
4335 x_wm_set_icon_pixmap (f
, 0);
4340 /* Handling X errors. */
4342 /* Handle the loss of connection to display DISPLAY. */
4345 x_connection_closed (display
, error_message
)
4347 char *error_message
;
4349 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4350 Lisp_Object frame
, tail
;
4355 /* First delete frames whose minibuffers are on frames
4356 that are on the dead display. */
4357 FOR_EACH_FRAME (tail
, frame
)
4359 Lisp_Object minibuf_frame
;
4361 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4362 if (! EQ (frame
, minibuf_frame
)
4363 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4364 Fdelete_frame (frame
, Qt
);
4367 /* Now delete all remaining frames on the dead display.
4368 We are now sure none of these is used as the minibuffer
4369 for another frame that we need to delete. */
4370 FOR_EACH_FRAME (tail
, frame
)
4371 if (FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4372 Fdelete_frame (frame
, Qt
);
4374 x_delete_display (dpyinfo
);
4376 if (x_display_list
== 0)
4378 fprintf (stderr
, "%s", error_message
);
4379 shut_down_emacs (0, 0, Qnil
);
4383 /* Ordinary stack unwind doesn't deal with these. */
4385 sigunblock (sigmask (SIGIO
));
4387 sigunblock (sigmask (SIGALRM
));
4388 TOTALLY_UNBLOCK_INPUT
;
4390 error ("%s", error_message
);
4393 /* This is the usual handler for X protocol errors.
4394 It kills all frames on the display that we got the error for.
4395 If that was the only one, it prints an error message and kills Emacs. */
4398 x_error_quitter (display
, error
)
4402 char buf
[256], buf1
[356];
4404 /* Note that there is no real way portable across R3/R4 to get the
4405 original error handler. */
4407 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4408 sprintf (buf1
, "X protocol error: %s on protocol request %d",
4409 buf
, error
->request_code
);
4410 x_connection_closed (display
, buf1
);
4413 /* This is the handler for X IO errors, always.
4414 It kills all frames on the display that we lost touch with.
4415 If that was the only one, it prints an error message and kills Emacs. */
4418 x_io_error_quitter (display
)
4423 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
4424 x_connection_closed (display
, buf
);
4427 /* A buffer for storing X error messages. */
4428 static char *x_caught_error_message
;
4429 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4431 /* An X error handler which stores the error message in
4432 x_caught_error_message. This is what's installed when
4433 x_catch_errors is in effect. */
4436 x_error_catcher (display
, error
)
4440 XGetErrorText (display
, error
->error_code
,
4441 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4445 /* Begin trapping X errors for display DPY. Actually we trap X errors
4446 for all displays, but DPY should be the display you are actually
4449 After calling this function, X protocol errors no longer cause
4450 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4452 Calling x_check_errors signals an Emacs error if an X error has
4453 occurred since the last call to x_catch_errors or x_check_errors.
4455 Calling x_uncatch_errors resumes the normal error handling. */
4457 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4460 x_catch_errors (dpy
)
4463 /* Make sure any errors from previous requests have been dealt with. */
4466 /* Set up the error buffer. */
4467 x_caught_error_message
4468 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4469 x_caught_error_message
[0] = '\0';
4471 /* Install our little error handler. */
4472 XSetErrorHandler (x_error_catcher
);
4475 /* If any X protocol errors have arrived since the last call to
4476 x_catch_errors or x_check_errors, signal an Emacs error using
4477 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4480 x_check_errors (dpy
, format
)
4484 /* Make sure to catch any errors incurred so far. */
4487 if (x_caught_error_message
[0])
4489 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4491 sprintf (buf
, format
, x_caught_error_message
);
4492 x_uncatch_errors (dpy
);
4497 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4500 x_had_errors_p (dpy
)
4503 /* Make sure to catch any errors incurred so far. */
4506 return x_caught_error_message
[0] != 0;
4509 /* Stop catching X protocol errors and let them make Emacs die. */
4512 x_uncatch_errors (dpy
)
4515 xfree (x_caught_error_message
);
4516 x_caught_error_message
= 0;
4517 XSetErrorHandler (x_error_quitter
);
4521 static unsigned int x_wire_count
;
4524 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4529 /* Changing the font of the frame. */
4531 /* Give frame F the font named FONTNAME as its default font, and
4532 return the full name of that font. FONTNAME may be a wildcard
4533 pattern; in that case, we choose some font that fits the pattern.
4534 The return value shows which font we chose. */
4537 x_new_font (f
, fontname
)
4539 register char *fontname
;
4542 int n_matching_fonts
;
4543 XFontStruct
*font_info
;
4546 /* Get a list of all the fonts that match this name. Once we
4547 have a list of matching fonts, we compare them against the fonts
4548 we already have by comparing font ids. */
4549 font_names
= (char **) XListFonts (FRAME_X_DISPLAY (f
), fontname
,
4550 1024, &n_matching_fonts
);
4551 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4552 find any matches; font_names == 0 is the only clue. */
4554 n_matching_fonts
= 0;
4556 /* Don't just give up if n_matching_fonts is 0.
4557 Apparently there's a bug on Suns: XListFontsWithInfo can
4558 fail to find a font, but XLoadQueryFont may still find it. */
4560 /* See if we've already loaded a matching font. */
4561 already_loaded
= -1;
4562 if (n_matching_fonts
!= 0)
4566 for (i
= 0; i
< FRAME_X_DISPLAY_INFO (f
)->n_fonts
; i
++)
4567 for (j
= 0; j
< n_matching_fonts
; j
++)
4568 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].name
, font_names
[j
])
4569 || !strcmp (FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
, font_names
[j
]))
4572 fontname
= FRAME_X_DISPLAY_INFO (f
)->font_table
[i
].full_name
;
4578 /* If we have, just return it from the table. */
4579 if (already_loaded
>= 0)
4580 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
4581 /* Otherwise, load the font and add it to the table. */
4589 /* Try to find a character-cell font in the list. */
4591 /* A laudable goal, but this isn't how to do it. */
4592 for (i
= 0; i
< n_matching_fonts
; i
++)
4593 if (! font_info
[i
].per_char
)
4599 /* See comment above. */
4600 if (n_matching_fonts
!= 0)
4601 fontname
= font_names
[i
];
4603 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
4606 /* Free the information from XListFonts. */
4607 if (n_matching_fonts
)
4608 XFreeFontNames (font_names
);
4612 /* Do we need to create the table? */
4613 if (FRAME_X_DISPLAY_INFO (f
)->font_table_size
== 0)
4615 FRAME_X_DISPLAY_INFO (f
)->font_table_size
= 16;
4616 FRAME_X_DISPLAY_INFO (f
)->font_table
4617 = (struct font_info
*) xmalloc (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4618 * sizeof (struct font_info
));
4620 /* Do we need to grow the table? */
4621 else if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
4622 >= FRAME_X_DISPLAY_INFO (f
)->font_table_size
)
4624 FRAME_X_DISPLAY_INFO (f
)->font_table_size
*= 2;
4625 FRAME_X_DISPLAY_INFO (f
)->font_table
4626 = (struct font_info
*) xrealloc (FRAME_X_DISPLAY_INFO (f
)->font_table
,
4627 (FRAME_X_DISPLAY_INFO (f
)->font_table_size
4628 * sizeof (struct font_info
)));
4631 /* Try to get the full name of FONT. Put it in full_name. */
4633 for (i
= 0; i
< font
->n_properties
; i
++)
4636 = XGetAtomName (FRAME_X_DISPLAY (f
), font
->properties
[i
].name
);
4637 if (!strcmp (atom
, "FONT"))
4639 char *name
= XGetAtomName (FRAME_X_DISPLAY (f
),
4640 (Atom
) (font
->properties
[i
].card32
));
4644 /* Count the number of dashes in the "full name".
4645 If it is too few, this isn't really the font's full name,
4647 In X11R4, the fonts did not come with their canonical names
4665 n_fonts
= FRAME_X_DISPLAY_INFO (f
)->n_fonts
;
4666 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4667 bcopy (fontname
, FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4669 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= full_name
;
4671 FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].full_name
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
;
4672 f
->display
.x
->font
= FRAME_X_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
4673 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
4676 fontname
= full_name
;
4679 /* Compute the scroll bar width in character columns. */
4680 if (f
->scroll_bar_pixel_width
> 0)
4682 int wid
= FONT_WIDTH (f
->display
.x
->font
);
4683 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4686 f
->scroll_bar_cols
= 2;
4688 /* Now make the frame display the given font. */
4689 if (FRAME_X_WINDOW (f
) != 0)
4691 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->normal_gc
,
4692 f
->display
.x
->font
->fid
);
4693 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->reverse_gc
,
4694 f
->display
.x
->font
->fid
);
4695 XSetFont (FRAME_X_DISPLAY (f
), f
->display
.x
->cursor_gc
,
4696 f
->display
.x
->font
->fid
);
4698 frame_update_line_height (f
);
4699 x_set_window_size (f
, 0, f
->width
, f
->height
);
4702 /* If we are setting a new frame's font for the first time,
4703 there are no faces yet, so this font's height is the line height. */
4704 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
4707 Lisp_Object lispy_name
;
4709 lispy_name
= build_string (fontname
);
4711 /* Free the information from XListFonts. The data
4712 we actually retain comes from XLoadQueryFont. */
4713 XFreeFontNames (font_names
);
4719 x_calc_absolute_position (f
)
4723 int win_x
= 0, win_y
= 0;
4724 int flags
= f
->display
.x
->size_hint_flags
;
4726 /* Find the position of the outside upper-left corner of
4727 the inner window, with respect to the outer window. */
4728 if (f
->display
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4731 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4733 /* From-window, to-window. */
4734 f
->display
.x
->window_desc
,
4735 f
->display
.x
->parent_desc
,
4737 /* From-position, to-position. */
4738 0, 0, &win_x
, &win_y
,
4745 /* Treat negative positions as relative to the leftmost bottommost
4746 position that fits on the screen. */
4747 if (flags
& XNegative
)
4748 f
->display
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
4749 - 2 * f
->display
.x
->border_width
- win_x
4751 + f
->display
.x
->left_pos
);
4753 if (flags
& YNegative
)
4754 f
->display
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
4755 - 2 * f
->display
.x
->border_width
- win_y
4757 + f
->display
.x
->top_pos
);
4758 /* The left_pos and top_pos
4759 are now relative to the top and left screen edges,
4760 so the flags should correspond. */
4761 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4764 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4765 to really change the position, and 0 when calling from
4766 x_make_frame_visible (in that case, XOFF and YOFF are the current
4767 position values). */
4769 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4771 register int xoff
, yoff
;
4776 f
->display
.x
->top_pos
= yoff
;
4777 f
->display
.x
->left_pos
= xoff
;
4778 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4780 f
->display
.x
->size_hint_flags
|= XNegative
;
4782 f
->display
.x
->size_hint_flags
|= YNegative
;
4783 f
->display
.x
->win_gravity
= NorthWestGravity
;
4785 x_calc_absolute_position (f
);
4788 x_wm_set_size_hint (f
, 0, 0);
4790 #ifdef USE_X_TOOLKIT
4791 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
),
4792 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4793 #else /* not USE_X_TOOLKIT */
4794 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4795 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4796 #endif /* not USE_X_TOOLKIT */
4800 /* Call this to change the size of frame F's x-window.
4801 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4802 for this size change and subsequent size changes.
4803 Otherwise we leave the window gravity unchanged. */
4805 x_set_window_size (f
, change_gravity
, cols
, rows
)
4810 int pixelwidth
, pixelheight
;
4813 #ifdef USE_X_TOOLKIT
4816 /* The x and y position of the widget is clobbered by the
4817 call to XtSetValues within EmacsFrameSetCharSize.
4818 This is a real kludge, but I don't understand Xt so I can't
4819 figure out a correct fix. Can anyone else tell me? -- rms. */
4820 int xpos
= f
->display
.x
->widget
->core
.x
;
4821 int ypos
= f
->display
.x
->widget
->core
.y
;
4822 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4823 f
->display
.x
->widget
->core
.x
= xpos
;
4824 f
->display
.x
->widget
->core
.y
= ypos
;
4828 #else /* not USE_X_TOOLKIT */
4832 check_frame_size (f
, &rows
, &cols
);
4833 f
->display
.x
->vertical_scroll_bar_extra
4834 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4836 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4837 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4838 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
4839 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4840 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4842 f
->display
.x
->win_gravity
= NorthWestGravity
;
4843 x_wm_set_size_hint (f
, 0, 0);
4845 XSync (FRAME_X_DISPLAY (f
), False
);
4846 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4847 pixelwidth
, pixelheight
);
4849 /* Now, strictly speaking, we can't be sure that this is accurate,
4850 but the window manager will get around to dealing with the size
4851 change request eventually, and we'll hear how it went when the
4852 ConfigureNotify event gets here.
4854 We could just not bother storing any of this information here,
4855 and let the ConfigureNotify event set everything up, but that
4856 might be kind of confusing to the lisp code, since size changes
4857 wouldn't be reported in the frame parameters until some random
4858 point in the future when the ConfigureNotify event arrives. */
4859 change_frame_size (f
, rows
, cols
, 0, 0);
4860 PIXEL_WIDTH (f
) = pixelwidth
;
4861 PIXEL_HEIGHT (f
) = pixelheight
;
4863 /* If cursor was outside the new size, mark it as off. */
4864 if (f
->phys_cursor_y
>= rows
4865 || f
->phys_cursor_x
>= cols
)
4867 f
->phys_cursor_x
= -1;
4868 f
->phys_cursor_y
= -1;
4871 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4872 receive in the ConfigureNotify event; if we get what we asked
4873 for, then the event won't cause the screen to become garbaged, so
4874 we have to make sure to do it here. */
4875 SET_FRAME_GARBAGED (f
);
4877 XFlush (FRAME_X_DISPLAY (f
));
4879 #endif /* not USE_X_TOOLKIT */
4882 /* Mouse warping, focus shifting, raising and lowering. */
4885 x_set_mouse_position (f
, x
, y
)
4891 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4892 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
4894 if (pix_x
< 0) pix_x
= 0;
4895 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4897 if (pix_y
< 0) pix_y
= 0;
4898 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4902 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4903 0, 0, 0, 0, pix_x
, pix_y
);
4907 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
4910 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4916 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4917 0, 0, 0, 0, pix_x
, pix_y
);
4921 x_focus_on_frame (f
)
4924 #if 0 /* This proves to be unpleasant. */
4928 /* I don't think that the ICCCM allows programs to do things like this
4929 without the interaction of the window manager. Whatever you end up
4930 doing with this code, do it to x_unfocus_frame too. */
4931 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4932 RevertToPointerRoot
, CurrentTime
);
4940 /* Look at the remarks in x_focus_on_frame. */
4941 if (x_focus_frame
== f
)
4942 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
4943 RevertToPointerRoot
, CurrentTime
);
4947 /* Raise frame F. */
4952 if (f
->async_visible
)
4955 #ifdef USE_X_TOOLKIT
4956 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4957 #else /* not USE_X_TOOLKIT */
4958 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4959 #endif /* not USE_X_TOOLKIT */
4960 XFlush (FRAME_X_DISPLAY (f
));
4965 /* Lower frame F. */
4970 if (f
->async_visible
)
4973 #ifdef USE_X_TOOLKIT
4974 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->display
.x
->widget
));
4975 #else /* not USE_X_TOOLKIT */
4976 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4977 #endif /* not USE_X_TOOLKIT */
4978 XFlush (FRAME_X_DISPLAY (f
));
4984 XTframe_raise_lower (f
, raise
)
4994 /* Change from withdrawn state to mapped state,
4997 x_make_frame_visible (f
)
5005 type
= x_icon_type (f
);
5007 x_bitmap_icon (f
, type
);
5009 if (! FRAME_VISIBLE_P (f
))
5011 #ifndef USE_X_TOOLKIT
5012 if (! FRAME_ICONIFIED_P (f
))
5013 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5016 if (! EQ (Vx_no_window_manager
, Qt
))
5017 x_wm_set_window_state (f
, NormalState
);
5018 #ifdef USE_X_TOOLKIT
5019 /* This was XtPopup, but that did nothing for an iconified frame. */
5020 XtMapWidget (f
->display
.x
->widget
);
5021 #else /* not USE_X_TOOLKIT */
5022 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5023 #endif /* not USE_X_TOOLKIT */
5024 #if 0 /* This seems to bring back scroll bars in the wrong places
5025 if the window configuration has changed. They seem
5026 to come back ok without this. */
5027 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5028 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5032 XFlush (FRAME_X_DISPLAY (f
));
5034 /* Synchronize to ensure Emacs knows the frame is visible
5035 before we do anything else. We do this loop with input not blocked
5036 so that incoming events are handled. */
5039 int count
= input_signal_count
;
5041 /* This must come after we set COUNT. */
5044 XSETFRAME (frame
, f
);
5049 /* Once we have handled input events,
5050 we should have received the MapNotify if one is coming.
5051 So if we have not got it yet, stop looping.
5052 Some window managers make their own decisions
5053 about visibility. */
5054 if (input_signal_count
!= count
)
5056 /* Machines that do polling rather than SIGIO have been observed
5057 to go into a busy-wait here. So we'll fake an alarm signal
5058 to let the handler know that there's something to be read.
5059 We used to raise a real alarm, but it seems that the handler
5060 isn't always enabled here. This is probably a bug. */
5061 if (input_polling_used ())
5063 /* It could be confusing if a real alarm arrives while processing
5064 the fake one. Turn it off and let the handler reset it. */
5066 input_poll_signal ();
5068 /* Once we have handled input events,
5069 we should have received the MapNotify if one is coming.
5070 So if we have not got it yet, stop looping.
5071 Some window managers make their own decisions
5072 about visibility. */
5073 if (input_signal_count
!= count
)
5076 FRAME_SAMPLE_VISIBILITY (f
);
5080 /* Change from mapped state to withdrawn state. */
5082 x_make_frame_invisible (f
)
5088 #ifdef USE_X_TOOLKIT
5089 /* Use the frame's outermost window, not the one we normally draw on. */
5090 window
= XtWindow (f
->display
.x
->widget
);
5091 #else /* not USE_X_TOOLKIT */
5092 window
= FRAME_X_WINDOW (f
);
5093 #endif /* not USE_X_TOOLKIT */
5095 /* Don't keep the highlight on an invisible frame. */
5096 if (x_highlight_frame
== f
)
5097 x_highlight_frame
= 0;
5099 #if 0/* This might add unreliability; I don't trust it -- rms. */
5100 if (! f
->async_visible
&& ! f
->async_iconified
)
5106 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5107 that the current position of the window is user-specified, rather than
5108 program-specified, so that when the window is mapped again, it will be
5109 placed at the same location, without forcing the user to position it
5110 by hand again (they have already done that once for this window.) */
5111 x_wm_set_size_hint (f
, 0, 1);
5115 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5116 DefaultScreen (FRAME_X_DISPLAY (f
))))
5118 UNBLOCK_INPUT_RESIGNAL
;
5119 error ("Can't notify window manager of window withdrawal");
5121 #else /* ! defined (HAVE_X11R4) */
5123 /* Tell the window manager what we're going to do. */
5124 if (! EQ (Vx_no_window_manager
, Qt
))
5128 unmap
.xunmap
.type
= UnmapNotify
;
5129 unmap
.xunmap
.window
= window
;
5130 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5131 unmap
.xunmap
.from_configure
= False
;
5132 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5133 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5135 SubstructureRedirectMask
|SubstructureNotifyMask
,
5138 UNBLOCK_INPUT_RESIGNAL
;
5139 error ("Can't notify window manager of withdrawal");
5143 /* Unmap the window ourselves. Cheeky! */
5144 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5145 #endif /* ! defined (HAVE_X11R4) */
5147 /* We can't distinguish this from iconification
5148 just by the event that we get from the server.
5149 So we can't win using the usual strategy of letting
5150 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5151 and synchronize with the server to make sure we agree. */
5153 FRAME_ICONIFIED_P (f
) = 0;
5154 f
->async_visible
= 0;
5155 f
->async_iconified
= 0;
5162 /* Change window state from mapped to iconified. */
5171 /* Don't keep the highlight on an invisible frame. */
5172 if (x_highlight_frame
== f
)
5173 x_highlight_frame
= 0;
5175 if (f
->async_iconified
)
5180 type
= x_icon_type (f
);
5182 x_bitmap_icon (f
, type
);
5184 #ifdef USE_X_TOOLKIT
5186 if (! FRAME_VISIBLE_P (f
))
5188 if (! EQ (Vx_no_window_manager
, Qt
))
5189 x_wm_set_window_state (f
, IconicState
);
5190 /* This was XtPopup, but that did nothing for an iconified frame. */
5191 XtMapWidget (f
->display
.x
->widget
);
5196 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5197 XtWindow (f
->display
.x
->widget
),
5198 DefaultScreen (FRAME_X_DISPLAY (f
)));
5202 error ("Can't notify window manager of iconification");
5204 f
->async_iconified
= 1;
5207 XFlush (FRAME_X_DISPLAY (f
));
5209 #else /* not USE_X_TOOLKIT */
5211 /* Make sure the X server knows where the window should be positioned,
5212 in case the user deiconifies with the window manager. */
5213 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5214 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5216 /* Since we don't know which revision of X we're running, we'll use both
5217 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5219 /* X11R4: send a ClientMessage to the window manager using the
5220 WM_CHANGE_STATE type. */
5224 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5225 message
.xclient
.type
= ClientMessage
;
5226 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5227 message
.xclient
.format
= 32;
5228 message
.xclient
.data
.l
[0] = IconicState
;
5230 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5231 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5233 SubstructureRedirectMask
| SubstructureNotifyMask
,
5236 UNBLOCK_INPUT_RESIGNAL
;
5237 error ("Can't notify window manager of iconification");
5241 /* X11R3: set the initial_state field of the window manager hints to
5243 x_wm_set_window_state (f
, IconicState
);
5245 if (!FRAME_VISIBLE_P (f
))
5247 /* If the frame was withdrawn, before, we must map it. */
5248 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5251 f
->async_iconified
= 1;
5253 XFlush (FRAME_X_DISPLAY (f
));
5255 #endif /* not USE_X_TOOLKIT */
5258 /* Destroy the X window of frame F. */
5260 x_destroy_window (f
)
5263 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5267 if (f
->display
.x
->icon_desc
!= 0)
5268 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->icon_desc
);
5269 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->display
.x
->window_desc
);
5270 #ifdef USE_X_TOOLKIT
5271 XtDestroyWidget (f
->display
.x
->widget
);
5272 free_frame_menubar (f
);
5273 #endif /* USE_X_TOOLKIT */
5275 free_frame_faces (f
);
5276 XFlush (FRAME_X_DISPLAY (f
));
5278 xfree (f
->display
.x
);
5280 if (f
== x_focus_frame
)
5282 if (f
== x_highlight_frame
)
5283 x_highlight_frame
= 0;
5285 dpyinfo
->reference_count
--;
5287 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5289 dpyinfo
->mouse_face_beg_row
5290 = dpyinfo
->mouse_face_beg_col
= -1;
5291 dpyinfo
->mouse_face_end_row
5292 = dpyinfo
->mouse_face_end_col
= -1;
5293 dpyinfo
->mouse_face_window
= Qnil
;
5299 /* Setting window manager hints. */
5301 /* Set the normal size hints for the window manager, for frame F.
5302 FLAGS is the flags word to use--or 0 meaning preserve the flags
5303 that the window now has.
5304 If USER_POSITION is nonzero, we set the USPosition
5305 flag (this is useful when FLAGS is 0). */
5307 x_wm_set_size_hint (f
, flags
, user_position
)
5312 XSizeHints size_hints
;
5314 #ifdef USE_X_TOOLKIT
5317 Dimension widget_width
, widget_height
;
5318 Window window
= XtWindow (f
->display
.x
->widget
);
5319 #else /* not USE_X_TOOLKIT */
5320 Window window
= FRAME_X_WINDOW (f
);
5321 #endif /* not USE_X_TOOLKIT */
5323 /* Setting PMaxSize caused various problems. */
5324 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5326 flexlines
= f
->height
;
5328 size_hints
.x
= f
->display
.x
->left_pos
;
5329 size_hints
.y
= f
->display
.x
->top_pos
;
5331 #ifdef USE_X_TOOLKIT
5332 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5333 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5334 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5335 size_hints
.height
= widget_height
;
5336 size_hints
.width
= widget_width
;
5337 #else /* not USE_X_TOOLKIT */
5338 size_hints
.height
= PIXEL_HEIGHT (f
);
5339 size_hints
.width
= PIXEL_WIDTH (f
);
5340 #endif /* not USE_X_TOOLKIT */
5342 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5343 size_hints
.height_inc
= f
->display
.x
->line_height
;
5344 size_hints
.max_width
5345 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5346 size_hints
.max_height
5347 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5350 int base_width
, base_height
;
5351 int min_rows
= 0, min_cols
= 0;
5353 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5354 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5356 check_frame_size (f
, &min_rows
, &min_cols
);
5358 /* The window manager uses the base width hints to calculate the
5359 current number of rows and columns in the frame while
5360 resizing; min_width and min_height aren't useful for this
5361 purpose, since they might not give the dimensions for a
5362 zero-row, zero-column frame.
5364 We use the base_width and base_height members if we have
5365 them; otherwise, we set the min_width and min_height members
5366 to the size for a zero x zero frame. */
5369 size_hints
.flags
|= PBaseSize
;
5370 size_hints
.base_width
= base_width
;
5371 size_hints
.base_height
= base_height
;
5372 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5373 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5375 size_hints
.min_width
= base_width
;
5376 size_hints
.min_height
= base_height
;
5381 size_hints
.flags
|= flags
;
5384 XSizeHints hints
; /* Sometimes I hate X Windows... */
5385 long supplied_return
;
5389 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5392 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5397 if (hints
.flags
& PSize
)
5398 size_hints
.flags
|= PSize
;
5399 if (hints
.flags
& PPosition
)
5400 size_hints
.flags
|= PPosition
;
5401 if (hints
.flags
& USPosition
)
5402 size_hints
.flags
|= USPosition
;
5403 if (hints
.flags
& USSize
)
5404 size_hints
.flags
|= USSize
;
5408 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5409 size_hints
.flags
|= PWinGravity
;
5413 size_hints
.flags
&= ~ PPosition
;
5414 size_hints
.flags
|= USPosition
;
5416 #endif /* PWinGravity */
5419 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5421 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5425 /* Used for IconicState or NormalState */
5426 x_wm_set_window_state (f
, state
)
5430 #ifdef USE_X_TOOLKIT
5433 XtSetArg (al
[0], XtNinitialState
, state
);
5434 XtSetValues (f
->display
.x
->widget
, al
, 1);
5435 #else /* not USE_X_TOOLKIT */
5436 Window window
= FRAME_X_WINDOW (f
);
5438 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5439 f
->display
.x
->wm_hints
.initial_state
= state
;
5441 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5442 #endif /* not USE_X_TOOLKIT */
5445 x_wm_set_icon_pixmap (f
, pixmap_id
)
5449 #ifdef USE_X_TOOLKIT
5450 Window window
= XtWindow (f
->display
.x
->widget
);
5452 Window window
= FRAME_X_WINDOW (f
);
5457 Pixmap icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5458 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5459 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5463 f
->display
.x
->wm_hints
.icon_pixmap
= None
;
5464 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5467 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5470 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5474 #ifdef USE_X_TOOLKIT
5475 Window window
= XtWindow (f
->display
.x
->widget
);
5477 Window window
= FRAME_X_WINDOW (f
);
5480 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5481 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5482 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5484 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5488 /* Initialization. */
5490 #ifdef USE_X_TOOLKIT
5491 static XrmOptionDescRec emacs_options
[] = {
5492 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5493 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5495 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5496 XrmoptionSepArg
, NULL
},
5497 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5499 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5500 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5501 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5502 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5503 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5504 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5505 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5507 #endif /* USE_X_TOOLKIT */
5509 static int x_initialized
;
5511 struct x_display_info
*
5512 x_term_init (display_name
, xrm_option
, resource_name
)
5513 Lisp_Object display_name
;
5515 char *resource_name
;
5521 struct x_display_info
*dpyinfo
;
5530 #ifdef USE_X_TOOLKIT
5532 XtSetLanguageProc (NULL
, NULL
, NULL
);
5543 argv
[argc
++] = "-xrm";
5544 argv
[argc
++] = xrm_option
;
5546 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
5547 resource_name
, EMACS_CLASS
,
5548 emacs_options
, XtNumber (emacs_options
),
5552 #else /* not USE_X_TOOLKIT */
5554 XSetLocaleModifiers ("");
5556 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
5557 #endif /* not USE_X_TOOLKIT */
5559 /* Detect failure. */
5563 /* We have definitely succeeded. Record the new connection. */
5565 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
5567 /* Put this display on the chain. */
5568 dpyinfo
->next
= x_display_list
;
5569 x_display_list
= dpyinfo
;
5571 /* Put it on x_display_name_list as well, to keep them parallel. */
5572 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
5573 x_display_name_list
);
5574 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
5576 dpyinfo
->display
= dpy
;
5579 XSetAfterFunction (x_current_display
, x_trace_wire
);
5583 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5584 + XSTRING (Vsystem_name
)->size
5586 sprintf (dpyinfo
->x_id_name
, "%s@%s",
5587 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5589 /* Figure out which modifier bits mean what. */
5590 x_find_modifier_meanings (dpyinfo
);
5592 /* Get the scroll bar cursor. */
5593 dpyinfo
->vertical_scroll_bar_cursor
5594 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
5596 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
5597 resource_name
, EMACS_CLASS
);
5598 #ifdef HAVE_XRMSETDATABASE
5599 XrmSetDatabase (dpyinfo
->display
, xrdb
);
5601 dpyinfo
->display
->db
= xrdb
;
5603 /* Put thr rdb where we can find it in a way that works on
5605 dpyinfo
->xrdb
= xrdb
;
5607 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
5608 DefaultScreen (dpyinfo
->display
));
5609 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
5610 &dpyinfo
->n_planes
);
5611 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
5612 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
5613 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
5614 dpyinfo
->grabbed
= 0;
5615 dpyinfo
->reference_count
= 0;
5616 dpyinfo
->icon_bitmap_id
= -1;
5617 dpyinfo
->n_fonts
= 0;
5618 dpyinfo
->font_table_size
= 0;
5619 dpyinfo
->bitmaps
= 0;
5620 dpyinfo
->bitmaps_size
= 0;
5621 dpyinfo
->bitmaps_last
= 0;
5622 dpyinfo
->scratch_cursor_gc
= 0;
5623 dpyinfo
->mouse_face_mouse_frame
= 0;
5624 dpyinfo
->mouse_face_deferred_gc
= 0;
5625 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5626 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5627 dpyinfo
->mouse_face_face_id
= 0;
5628 dpyinfo
->mouse_face_window
= Qnil
;
5629 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
5630 dpyinfo
->mouse_face_defer
= 0;
5632 dpyinfo
->Xatom_wm_protocols
5633 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
5634 dpyinfo
->Xatom_wm_take_focus
5635 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
5636 dpyinfo
->Xatom_wm_save_yourself
5637 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
5638 dpyinfo
->Xatom_wm_delete_window
5639 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
5640 dpyinfo
->Xatom_wm_change_state
5641 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
5642 dpyinfo
->Xatom_wm_configure_denied
5643 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
5644 dpyinfo
->Xatom_wm_window_moved
5645 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
5646 dpyinfo
->Xatom_editres
5647 = XInternAtom (dpyinfo
->display
, "Editres", False
);
5648 dpyinfo
->Xatom_CLIPBOARD
5649 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
5650 dpyinfo
->Xatom_TIMESTAMP
5651 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
5653 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
5654 dpyinfo
->Xatom_DELETE
5655 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
5656 dpyinfo
->Xatom_MULTIPLE
5657 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
5659 = XInternAtom (dpyinfo
->display
, "INCR", False
);
5660 dpyinfo
->Xatom_EMACS_TMP
5661 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
5662 dpyinfo
->Xatom_TARGETS
5663 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
5665 = XInternAtom (dpyinfo
->display
, "NULL", False
);
5666 dpyinfo
->Xatom_ATOM_PAIR
5667 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
5669 connection
= ConnectionNumber (dpyinfo
->display
);
5670 dpyinfo
->connection
= connection
;
5673 /* This is only needed for distinguishing keyboard and process input. */
5674 if (connection
!= 0)
5675 add_keyboard_wait_descriptor (connection
);
5678 #ifndef F_SETOWN_BUG
5680 #ifdef F_SETOWN_SOCK_NEG
5681 /* stdin is a socket here */
5682 fcntl (connection
, F_SETOWN
, -getpid ());
5683 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5684 fcntl (connection
, F_SETOWN
, getpid ());
5685 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5686 #endif /* ! defined (F_SETOWN) */
5687 #endif /* F_SETOWN_BUG */
5690 init_sigio (connection
);
5691 #endif /* ! defined (SIGIO) */
5696 /* Get rid of display DPYINFO, assuming all frames are already gone,
5697 and without sending any more commands to the X server. */
5700 x_delete_display (dpyinfo
)
5701 struct x_display_info
*dpyinfo
;
5703 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
5705 /* Discard this display from x_display_name_list and x_display_list.
5706 We can't use Fdelq because that can quit. */
5707 if (! NILP (x_display_name_list
)
5708 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
5709 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
5714 tail
= x_display_name_list
;
5715 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
5717 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
5718 dpyinfo
->name_list_element
))
5720 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
5723 tail
= XCONS (tail
)->cdr
;
5727 if (x_display_list
== dpyinfo
)
5728 x_display_list
= dpyinfo
->next
;
5731 struct x_display_info
*tail
;
5733 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
5734 if (tail
->next
== dpyinfo
)
5735 tail
->next
= tail
->next
->next
;
5738 #ifndef USE_X_TOOLKIT
5739 /* I'm told Xt does this itself. */
5740 XrmDestroyDatabase (dpyinfo
->xrdb
);
5742 free (dpyinfo
->font_table
);
5743 free (dpyinfo
->x_id_name
);
5747 /* Set up use of X before we make the first connection. */
5751 clear_frame_hook
= XTclear_frame
;
5752 clear_end_of_line_hook
= XTclear_end_of_line
;
5753 ins_del_lines_hook
= XTins_del_lines
;
5754 change_line_highlight_hook
= XTchange_line_highlight
;
5755 insert_glyphs_hook
= XTinsert_glyphs
;
5756 write_glyphs_hook
= XTwrite_glyphs
;
5757 delete_glyphs_hook
= XTdelete_glyphs
;
5758 ring_bell_hook
= XTring_bell
;
5759 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5760 set_terminal_modes_hook
= XTset_terminal_modes
;
5761 update_begin_hook
= XTupdate_begin
;
5762 update_end_hook
= XTupdate_end
;
5763 set_terminal_window_hook
= XTset_terminal_window
;
5764 read_socket_hook
= XTread_socket
;
5765 frame_up_to_date_hook
= XTframe_up_to_date
;
5766 cursor_to_hook
= XTcursor_to
;
5767 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5768 mouse_position_hook
= XTmouse_position
;
5769 frame_rehighlight_hook
= XTframe_rehighlight
;
5770 frame_raise_lower_hook
= XTframe_raise_lower
;
5771 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5772 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5773 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5774 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5776 scroll_region_ok
= 1; /* we'll scroll partial frames */
5777 char_ins_del_ok
= 0; /* just as fast to write the line */
5778 line_ins_del_ok
= 1; /* we'll just blt 'em */
5779 fast_clear_end_of_line
= 1; /* X does this well */
5780 memory_below_frame
= 0; /* we don't remember what scrolls
5786 x_focus_frame
= x_highlight_frame
= 0;
5788 /* Try to use interrupt input; if we can't, then start polling. */
5789 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5791 #ifdef USE_X_TOOLKIT
5792 XtToolkitInitialize ();
5793 Xt_app_con
= XtCreateApplicationContext ();
5796 /* Note that there is no real way portable across R3/R4 to get the
5797 original error handler. */
5798 XSetErrorHandler (x_error_quitter
);
5799 XSetIOErrorHandler (x_io_error_quitter
);
5801 /* Disable Window Change signals; they are handled by X events. */
5803 signal (SIGWINCH
, SIG_DFL
);
5804 #endif /* ! defined (SIGWINCH) */
5806 signal (SIGPIPE
, x_connection_closed
);
5812 staticpro (&x_display_name_list
);
5813 x_display_name_list
= Qnil
;
5815 staticpro (&last_mouse_scroll_bar
);
5816 last_mouse_scroll_bar
= Qnil
;
5818 #endif /* ! defined (HAVE_X_WINDOWS) */